summaryrefslogtreecommitdiff
path: root/tools/source
diff options
context:
space:
mode:
Diffstat (limited to 'tools/source')
-rw-r--r--tools/source/communi/geninfo.cxx469
-rw-r--r--tools/source/communi/makefile.mk102
-rw-r--r--tools/source/communi/parser.cxx438
-rw-r--r--tools/source/datetime/datetime.cxx349
-rw-r--r--tools/source/datetime/makefile.mk88
-rw-r--r--tools/source/datetime/tdate.cxx540
-rw-r--r--tools/source/datetime/ttime.cxx531
-rw-r--r--tools/source/debug/debug.cxx1581
-rw-r--r--tools/source/debug/makefile.mk89
-rw-r--r--tools/source/debug/stcktree.cxx351
-rw-r--r--tools/source/fsys/comdep.cxx116
-rw-r--r--tools/source/fsys/comdep.hxx224
-rw-r--r--tools/source/fsys/dirent.cxx3521
-rw-r--r--tools/source/fsys/filecopy.cxx578
-rw-r--r--tools/source/fsys/fstat.cxx516
-rw-r--r--tools/source/fsys/makefile.mk98
-rw-r--r--tools/source/fsys/os2.cxx1153
-rw-r--r--tools/source/fsys/os2.hxx151
-rw-r--r--tools/source/fsys/tdir.cxx808
-rw-r--r--tools/source/fsys/tempfile.cxx337
-rw-r--r--tools/source/fsys/unx.cxx694
-rw-r--r--tools/source/fsys/unx.hxx139
-rw-r--r--tools/source/fsys/urlobj.cxx5021
-rw-r--r--tools/source/fsys/wldcrd.cxx177
-rw-r--r--tools/source/fsys/wntmsc.cxx1103
-rw-r--r--tools/source/fsys/wntmsc.hxx130
-rw-r--r--tools/source/generic/bigint.cxx1187
-rw-r--r--tools/source/generic/color.cxx403
-rw-r--r--tools/source/generic/fract.cxx720
-rw-r--r--tools/source/generic/gen.cxx699
-rw-r--r--tools/source/generic/link.cxx92
-rw-r--r--tools/source/generic/makefile.mk98
-rw-r--r--tools/source/generic/toolsin.cxx159
-rw-r--r--tools/source/inet/inetmime.cxx4630
-rw-r--r--tools/source/inet/inetmsg.cxx2945
-rw-r--r--tools/source/inet/inetstrm.cxx2059
-rw-r--r--tools/source/inet/makefile.mk83
-rw-r--r--tools/source/makefile.mk96
-rw-r--r--tools/source/memtools/contnr.cxx1754
-rw-r--r--tools/source/memtools/makefile.mk92
-rw-r--r--tools/source/memtools/mempool.cxx323
-rw-r--r--tools/source/memtools/multisel.cxx897
-rw-r--r--tools/source/memtools/table.cxx442
-rw-r--r--tools/source/memtools/unqidx.cxx643
-rw-r--r--tools/source/rc/makefile.mk89
-rw-r--r--tools/source/rc/rc.cxx311
-rw-r--r--tools/source/rc/resmgr.cxx1364
-rw-r--r--tools/source/ref/errinf.cxx443
-rw-r--r--tools/source/ref/globname.cxx441
-rw-r--r--tools/source/ref/makefile.mk90
-rw-r--r--tools/source/ref/pstm.cxx945
-rw-r--r--tools/source/ref/ref.cxx90
-rw-r--r--tools/source/solar/makefile.mk100
-rw-r--r--tools/source/solar/solar.c590
-rw-r--r--tools/source/stream/cachestr.cxx329
-rw-r--r--tools/source/stream/makefile.mk103
-rw-r--r--tools/source/stream/stream.cxx2905
-rw-r--r--tools/source/stream/strmos2.cxx870
-rw-r--r--tools/source/stream/strmsys.cxx74
-rw-r--r--tools/source/stream/strmunx.cxx897
-rw-r--r--tools/source/stream/strmwnt.cxx892
-rw-r--r--tools/source/stream/vcompat.cxx116
-rw-r--r--tools/source/string/makefile.mk88
-rw-r--r--tools/source/string/strascii.cxx773
-rw-r--r--tools/source/string/strcvt.cxx757
-rw-r--r--tools/source/string/strimp.cxx2306
-rw-r--r--tools/source/string/strucvt.cxx251
-rw-r--r--tools/source/string/tstring.cxx304
-rw-r--r--tools/source/string/tustring.cxx173
-rw-r--r--tools/source/zcodec/makefile.mk80
-rw-r--r--tools/source/zcodec/zcodec.cxx524
71 files changed, 52531 insertions, 0 deletions
diff --git a/tools/source/communi/geninfo.cxx b/tools/source/communi/geninfo.cxx
new file mode 100644
index 000000000000..f817b58b1dc3
--- /dev/null
+++ b/tools/source/communi/geninfo.cxx
@@ -0,0 +1,469 @@
+/*************************************************************************
+ *
+ * $RCSfile: geninfo.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include "geninfo.hxx"
+#include <stdio.h>
+
+//
+// class GenericInformation
+//
+
+/*****************************************************************************/
+GenericInformation::GenericInformation( const ByteString &rKey,
+ const ByteString &rValue,
+ GenericInformationList *pParentList,
+ GenericInformationList *pSubInfos )
+/*****************************************************************************/
+ : ByteString( rKey ),
+ sValue( rValue ),
+ pParent( pParentList ),
+ pInfoList( pSubInfos )
+{
+ // if a ParentList exists, insert this object into it
+ if ( pParent )
+ pParent->InsertInfo( this );
+ // make myself owner of pInfoList
+ if ( pInfoList )
+ pInfoList->SetOwner( this );
+}
+
+/*****************************************************************************/
+GenericInformation::GenericInformation( const GenericInformation& rInf,
+ BOOL bCopySubs)
+/*****************************************************************************/
+ : ByteString( rInf ),
+ sValue( rInf.sValue ),
+ pParent(NULL),
+ pInfoList( 0L )
+{
+ if(bCopySubs && rInf.pInfoList)
+ pInfoList = new GenericInformationList(*rInf.pInfoList, this);
+}
+
+/*****************************************************************************/
+GenericInformation::~GenericInformation()
+/*****************************************************************************/
+{
+ // remove pInfoList and all childs out of memory
+ delete pInfoList;
+ pInfoList = 0;
+
+ // remove this Info out of ParentList
+ if ( pParent )
+ pParent->RemoveInfo( this );
+}
+
+/*****************************************************************************/
+BOOL GenericInformation::InsertSubInfo( GenericInformation *pInfo )
+/*****************************************************************************/
+{
+ return ( pInfoList && pInfoList->InsertInfo( pInfo ));
+}
+
+/*****************************************************************************/
+BOOL GenericInformation::InsertSubInfo( const ByteString &rPathKey, const ByteString &rValue,
+ BOOL bSearchByPath, BOOL bNewPath )
+/*****************************************************************************/
+{
+ return (pInfoList && pInfoList->InsertInfo( rPathKey, rValue, bSearchByPath, bNewPath ));
+}
+
+/*****************************************************************************/
+void GenericInformation::RemoveSubInfo( GenericInformation *pInfo,
+ BOOL bDelete )
+/*****************************************************************************/
+{
+ pInfoList->RemoveInfo( pInfo, bDelete );
+}
+
+/*****************************************************************************/
+//void GenericInformation::RemoveSelf( BOOL bDelete )
+/*****************************************************************************/
+/*{
+ if ( pParent )
+ pParent->RemoveInfo( this, bDelete ); // loescht sich aus der Liste vom Parent und
+ // bei Bedarf auch mit obiger Methode alle Sublisten
+
+ // loescht sich bei Bedarf auch selbst
+ if ( bDelete )
+ delete this;
+}
+*/
+
+/*****************************************************************************/
+GenericInformation *GenericInformation::GetSubInfo( ByteString &rKey,
+ BOOL bSearchByPath,
+ BOOL bCreatePath )
+/*****************************************************************************/
+{
+ if ( !pInfoList && bCreatePath )
+ pInfoList = new GenericInformationList( this );
+ if ( pInfoList )
+ return pInfoList->GetInfo( rKey, bSearchByPath, bCreatePath );
+ return NULL;
+}
+
+
+//
+// class GenericInformationList
+//
+
+/*****************************************************************************/
+GenericInformationList::GenericInformationList( GenericInformation *pParent )
+/*****************************************************************************/
+ : pOwner( pParent )
+{
+}
+
+/*****************************************************************************/
+GenericInformationList::GenericInformationList(const GenericInformationList& rList,
+ GenericInformation *pParent)
+/*****************************************************************************/
+{
+ USHORT i;
+ GenericInformation* pTemp,*pWork;
+
+ pOwner = pParent;
+
+ for(i=0;i<rList.Count();i++)
+ {
+ pTemp = rList.GetObject(i);
+ pWork = new GenericInformation(*pTemp,TRUE);
+
+ Insert(pWork,LIST_APPEND);
+ }
+}
+
+/*****************************************************************************/
+GenericInformationList::~GenericInformationList()
+/*****************************************************************************/
+{
+ // delete all Informations stored in this List
+ // ### GH: Hier werden dann wohl etwa die Hälfte der Einträge gelöscht
+/* for ( ULONG i = 0; i < Count(); i++ ) {
+ GetObject( i )->ListDeleted();
+ delete GetObject( i );
+ Remove( i );*/
+ // Neue Variante:
+ while ( Count() ) {
+ GetObject( 0 )->ListDeleted();
+ delete GetObject( 0 );
+ Remove( (ULONG)0 );
+ }
+}
+
+/*****************************************************************************/
+GenericInformation *GenericInformationList::Search( ULONG &rPos, ByteString sKey,
+ ULONG nStart, ULONG nEnd )
+/*****************************************************************************/
+{
+ if ( Count() == 0 ) {
+ rPos = 0;
+ return NULL;
+ }
+
+ if ( nStart == nEnd ) {
+ rPos = nStart;
+ ByteString sCandidate = ByteString( *GetObject( nStart ));
+ if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) {
+ return GetObject( nStart ); // found !!!
+ }
+ else {
+ // requested key not found
+ return NULL;
+ }
+ }
+
+ // search binary in existing list
+ ULONG nActPos = nStart + (( nEnd - nStart ) / 2 );
+ rPos = nActPos;
+ ByteString sCandidate = ByteString( *GetObject( nActPos ));
+
+ if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii())
+ return GetObject( nActPos ); // found !!!
+
+ // split the list at ActPos
+ if ( sCandidate < sKey )
+ return Search( rPos, sKey, nActPos + 1, nEnd );
+ else
+ return Search( rPos, sKey, nStart, nActPos );
+}
+
+/*****************************************************************************/
+GenericInformation *GenericInformationList::GetInfo( ByteString &rKey,
+ BOOL bSearchByPath,
+ BOOL bCreatePath )
+/*****************************************************************************/
+{
+
+ rKey.EraseLeadingChars( '/' );
+ rKey.EraseTrailingChars( '/' );
+
+ ByteString sKey;
+ if ( bSearchByPath )
+ sKey = rKey.GetToken( 0, '/' );
+ else
+ sKey = rKey;
+
+ ULONG nPos = 0;
+ GenericInformation *pReturnInfo = Search( nPos, sKey, 0, Count() - 1 );
+ /* wenn kein Searchpath gesetzt und kein Returninfo vorhanden,
+ * gib NULL zurueck
+ * wenn Searchpath gesetzt und returninfo vorhanden,
+ * suche weiter nach unten
+ * wenn searchpath gesetzt kein returninfo vorhanden und newpath gesetzt,
+ * mache neues Verzeichniss
+ */
+ USHORT nTokenCount = rKey.GetTokenCount('/');
+ // search for next key of path in next level of tree
+ if ( bSearchByPath && (nTokenCount > 1)) {
+ ByteString sPath = ByteString(rKey.Copy( sKey.Len() + 1 ));
+ if ( !pReturnInfo ) { // wenn kein Return, dann muss man es anlegen
+ if ( !bCreatePath ) // wenn aber kein Create, dann nicht anlegen
+ return NULL;
+ USHORT nTmp = 0;
+ pReturnInfo = new GenericInformation( sKey, "", this, NULL);
+ pReturnInfo->SetSubList( new GenericInformationList( pReturnInfo ));
+ }
+ return pReturnInfo->GetSubInfo( sPath, TRUE, bCreatePath );
+ }
+ if ( !pReturnInfo && bCreatePath ) {
+ pReturnInfo = new GenericInformation ( sKey, "", this, NULL);
+ }
+
+ return pReturnInfo; // kann durchaus NULL sein.
+}
+
+/*****************************************************************************/
+ULONG GenericInformationList::InsertSorted( GenericInformation *pInfo,
+ BOOL bOverwrite,
+ ULONG nStart, ULONG nEnd )
+/*****************************************************************************/
+{
+ if ( Count() == 0 ) {
+ // empty list, so insert at first pos
+ Insert( pInfo, LIST_APPEND );
+ return 0;
+ }
+
+// ### GH: dieser Block schein überflüssig zu sein
+ ByteString sKey( pInfo->GetBuffer());
+ if ( Count() == 1 ) {
+ ByteString sCandidate( *GetObject( 0 ));
+ if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) {
+ // key allready exists in list
+ if ( bOverwrite )
+ Replace( pInfo, ULONG(0)); // ### Laut NF scheint hier ein Memory Leak zu sein
+ return 0;
+ }
+ else if ( sCandidate > sKey ) {
+ Insert( pInfo, ULONG(0));
+ return 0;
+ }
+ else {
+ Insert( pInfo, LIST_APPEND );
+ return 1;
+ }
+ }
+// ### GH: /ENDE/ dieser Block schein überflüssig zu sein
+
+ ULONG nActPos = nStart + (( nEnd - nStart ) / 2 );
+ ByteString sCandidate = ByteString( *GetObject( nActPos ));
+
+ if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) {
+ // key allready exists in list
+ if ( bOverwrite )
+ Replace( pInfo, nActPos ); // ### Laut NF scheint hier ein Memory Leak zu sein
+ return nActPos;
+ }
+
+ if ( nStart == nEnd ) {
+ // now more ways to search for key -> insert here
+ if ( sCandidate > sKey ) {
+ Insert( pInfo, nStart );
+ return nStart;
+ }
+ else {
+ Insert( pInfo, nStart + 1 );
+ return ( nStart + 1 );
+ }
+ }
+
+ if ( nActPos == Count() - 1 ) {
+ // reached end of list -> insert here
+ Insert( pInfo, LIST_APPEND );
+ return ( nActPos + 1 );
+ }
+
+ ByteString sSecondCand = ByteString( *GetObject( nActPos + 1 ));
+ if (( sCandidate < sKey ) && ( sSecondCand.ToUpperAscii() > sKey )) {
+ // optimal position to insert object
+ Insert( pInfo, nActPos + 1 );
+ return ( nActPos + 1 );
+ }
+
+ if ( sCandidate < sKey )
+ return InsertSorted( pInfo, bOverwrite, nActPos + 1, nEnd );
+ else
+ return InsertSorted( pInfo, bOverwrite, nStart, nActPos );
+}
+
+/*****************************************************************************/
+BOOL GenericInformationList::InsertInfo( GenericInformation *pInfo,
+ BOOL bOverwrite )
+/*****************************************************************************/
+{
+ if ( !pInfo->Len())
+ return FALSE;
+
+ InsertSorted( pInfo, bOverwrite, 0, Count() - 1 );
+ return TRUE;
+}
+
+
+/*****************************************************************************/
+BOOL GenericInformationList::InsertInfo( const ByteString &rPathKey, const ByteString &rValue,
+ BOOL bSearchByPath, BOOL bNewPath )
+/*****************************************************************************/
+{
+ GenericInformation *pInfo;
+ ByteString sPathKey ( rPathKey );
+ sPathKey.EraseLeadingChars( '/' );
+ sPathKey.EraseTrailingChars( '/' );
+
+ pInfo = GetInfo( sPathKey, bSearchByPath, bNewPath );
+
+ if ( pInfo ) {
+ pInfo->SetValue( rValue );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*****************************************************************************
+BOOL GenericInformationList::InsertInfo( const String &rPathKey,
+ const String &rValue,
+ BOOL bNewPath = FALSE)
+/*****************************************************************************
+{
+ GenericInformation *pInfo;
+
+ if ( !pPathKey || '\0'==pPathKey[0] )
+ return FALSE;
+
+ char *pNextItem = strchr( pPathKey, '/' );
+ if ( !pNextItem ) { // kein Token mehr gefunden
+ /* aus dem PathKey kann nun eine GenericInformation gebildet
+ * und eingefuegt werden *
+ pInfo = GetInfo( pPathKey, FALSE );
+ // Object besteht nicht und soll auch nicht nachgebildet werden
+ if ( !pInfo && !bNewPath )
+ return FALSE;
+ // erzeuge neue GI und stopfe sie in die Liste. Fertig !
+ pInfo = new GenericInformation( String( pPathKey ), String( pValue ), 0, 0 );
+ return InsertInfo( pInfo, TRUE );
+ }
+ else { // noch nicht fertig, muss noch tiefer in den Baum gehen
+ // SuchString anfertigen
+ String sSearch ( pPathKey );
+ sSearch.Erase ( USHORT(pNextItem - pPathKey));
+ // suchen..
+ pInfo = GetInfo( sSearch, FALSE );
+ if ( !pInfo && ! bNewPath) // subinfo nicht vorhanden und
+ return FALSE; // ich darf keinen neuen Pfad anlegen
+
+ if ( !pInfo )
+ // neue Subinfo machen und einfuegen
+ pInfo = new GenericInformation ( sSearch , "", this, 0 );
+
+ pNextItem++;
+ return pInfo->InsertSubInfo( pNextItem, pValue, bNewPath );
+ }
+ }
+}
+*/
+
+/*****************************************************************************/
+void GenericInformationList::RemoveInfo( GenericInformation *pInfo,
+ BOOL bDelete )
+/*****************************************************************************/
+{
+ Remove( pInfo );
+ if ( bDelete )
+ delete pInfo;
+ if ( Count() == 0 && pOwner ) // Leere Listen entfernen;
+ {
+ SetOwner( NULL );
+ delete this;
+ }
+}
+
+GenericInformation* GenericInformationList::SetOwner( GenericInformation *pNewOwner )
+{
+ GenericInformation *pOldOwner = pOwner;
+ if ( pOwner ) // bei parent austragen;
+ pOwner->SetSubList( NULL );
+ if ( pNewOwner )
+ pNewOwner->SetSubList( this );
+ pOwner = pNewOwner;
+ return pOldOwner;
+}
+
+
diff --git a/tools/source/communi/makefile.mk b/tools/source/communi/makefile.mk
new file mode 100644
index 000000000000..970f41a6121a
--- /dev/null
+++ b/tools/source/communi/makefile.mk
@@ -0,0 +1,102 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=TOOLS
+TARGET=communi
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES= simplecm.cxx bcst.cxx
+
+OBJFILES= $(OBJ)$/simplecm.obj \
+ $(OBJ)$/bcst.obj \
+ $(OBJ)$/persbcst.obj \
+ $(OBJ)$/iiclient.obj \
+ $(OBJ)$/siclient.obj \
+ $(OBJ)$/infocom.obj \
+ $(OBJ)$/bsockcon.obj \
+ $(OBJ)$/ssockcon.obj \
+ $(OBJ)$/parser.obj \
+ $(OBJ)$/geninfo.obj \
+
+SLOFILES= $(SLO)$/simplecm.obj \
+ $(SLO)$/bcst.obj \
+ $(SLO)$/persbcst.obj \
+ $(SLO)$/iiclient.obj \
+ $(SLO)$/siclient.obj \
+ $(SLO)$/infocom.obj \
+ $(SLO)$/bsockcon.obj \
+ $(SLO)$/ssockcon.obj \
+ $(SLO)$/parser.obj \
+ $(SLO)$/geninfo.obj \
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/communi/parser.cxx b/tools/source/communi/parser.cxx
new file mode 100644
index 000000000000..99160560504a
--- /dev/null
+++ b/tools/source/communi/parser.cxx
@@ -0,0 +1,438 @@
+/*************************************************************************
+ *
+ * $RCSfile: parser.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <stream.hxx>
+#include <fsys.hxx>
+
+#include "iparser.hxx"
+#include "geninfo.hxx"
+
+
+
+//
+// class InformationParser
+//
+
+const char InformationParser::cKeyLevelChars = '\t';
+
+/*****************************************************************************/
+InformationParser::InformationParser( BOOL bReplace )
+/*****************************************************************************/
+ : pActStream( NULL ),
+ nErrorCode( 0 ),
+ nErrorLine( 0 ),
+ nActLine( 0 ),
+ bRecover( FALSE ),
+ sOldLine( "" ),
+ sErrorText( "" ),
+ bReplaceVariables( bReplace ),
+ nLevel( 0 ),
+ sUPD( "" ),
+ sVersion( "" )
+{
+}
+
+/*****************************************************************************/
+InformationParser::~InformationParser()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+ByteString &InformationParser::ReadLine()
+/*****************************************************************************/
+{
+ ByteString sLine;
+ if ( bRecover ) {
+ bRecover = FALSE;
+ }
+ else {
+ pActStream->ReadLine( sLine );
+ sLine.EraseLeadingChars( 0x09 );
+ sLine.EraseLeadingChars( ' ' );
+
+ if ( bReplaceVariables ) {
+ while( sLine.SearchAndReplace( "%UPD", sUPD ) != (USHORT)-1 );
+ while( sLine.SearchAndReplace( "%VERSION", sVersion ) != (USHORT)-1 );
+ }
+
+ sOldLine = sLine;
+ nActLine++;
+ }
+
+ return sOldLine;
+}
+
+/*****************************************************************************/
+GenericInformation *InformationParser::ReadKey(
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ // this method has no error handling yet, but it works very fast.
+ // it is used to create whole informations and sub informations in
+ // a simple data format in memory, readed in a configuration file with
+ // following format:
+
+ /*
+
+ key [value]
+ {
+ key [value]
+ key [value]
+ {
+ key [value]
+ ...
+ ...
+ }
+ }
+ key [value]
+ ...
+ ...
+
+ */
+
+ GenericInformation *pInfo = NULL;
+
+ ByteString sLine( ReadLine());
+ ByteString sKey( "" );
+ ByteString sValue( "" );
+
+ // key separated from value by tab?
+ USHORT nWSPos = sLine.Search( ' ' );
+ if ( sLine.Search( '\t' ) < nWSPos ) {
+ nWSPos = sLine.Search( '\t' );
+ sLine.SearchAndReplace( "\t", " " );
+ }
+
+ if ( sLine.GetTokenCount( ' ' ) > 1 ) {
+ sKey = sLine.GetToken( 0, ' ' );
+ sValue = sLine.Copy( sKey.Len() + 1 );
+ while (( sValue.Search( ' ' ) == 0 ) || ( sValue.Search( '\t' ) == 0 )) {
+ sValue.Erase( 0, 1 );
+ }
+ }
+ else
+ sKey=sLine;
+
+ if ( bReplaceVariables && !nLevel ) {
+ sUPD = sKey.Copy( sKey.Len() - 3 );
+ sVersion = sKey;
+ }
+
+ if ( ReadLine() == "{" ) {
+ nLevel++;
+ GenericInformationList *pSubList = new GenericInformationList();
+ while ( ReadLine() != "}" ) {
+ Recover();
+ ReadKey( pSubList );
+ }
+ nLevel--;
+ pInfo = new GenericInformation( sKey, sValue,
+ pExistingList, pSubList );
+ }
+ else {
+ Recover();
+ pInfo = new GenericInformation( sKey, sValue, pExistingList );
+ }
+
+ return pInfo;
+}
+
+/*****************************************************************************/
+void InformationParser::Recover()
+/*****************************************************************************/
+{
+ bRecover = TRUE;
+}
+
+/*****************************************************************************/
+BOOL InformationParser::Save( SvStream &rOutStream,
+ const GenericInformationList *pSaveList,
+ USHORT nLevel )
+/*****************************************************************************/
+{
+ USHORT i;
+ ULONG nInfoListCount;
+ ByteString sTmpStr;
+ GenericInformation *pGenericInfo;
+ GenericInformationList *pGenericInfoList;
+
+ for ( nInfoListCount = 0; nInfoListCount < pSaveList->Count(); nInfoListCount++) {
+ // Key-Value Paare schreiben
+ pGenericInfo = pSaveList->GetObject( nInfoListCount );
+ sTmpStr = "";
+ for( i=0; i<nLevel; i++)
+ sTmpStr += cKeyLevelChars;
+ sTmpStr += pGenericInfo->GetBuffer();
+ sTmpStr += ' ';
+ sTmpStr += pGenericInfo->GetValue();
+ if ( !rOutStream.WriteLine( sTmpStr ) )
+ return FALSE;
+
+ // wenn vorhanden, bearbeite recursive die Sublisten
+ if (( pGenericInfoList = pGenericInfo->GetSubList() ) != 0) {
+ // oeffnende Klammer
+ sTmpStr = "";
+ for( i=0; i<nLevel; i++)
+ sTmpStr += cKeyLevelChars;
+ sTmpStr += '{';
+ if ( !rOutStream.WriteLine( sTmpStr ) )
+ return FALSE;
+ // recursiv die sublist abarbeiten
+ if ( !Save( rOutStream, pGenericInfoList, nLevel+1 ) )
+ return FALSE;
+ // schliessende Klammer
+ sTmpStr = "";
+ for( i=0; i<nLevel; i++)
+ sTmpStr += cKeyLevelChars;
+ sTmpStr += '}';
+ if ( !rOutStream.WriteLine( sTmpStr ) )
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*****************************************************************************/
+GenericInformationList *InformationParser::Execute(
+ SvStream &rSourceStream,
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ GenericInformationList *pList;
+ if ( pExistingList )
+ pList = pExistingList;
+ else
+ pList = new GenericInformationList();
+
+ pActStream = &rSourceStream;
+
+ // read all infos out of current file
+ while( !rSourceStream.IsEof()) {
+ nLevel = 0;
+ ReadKey( pList );
+ }
+
+ return pList;
+}
+
+/*****************************************************************************/
+GenericInformationList *InformationParser::Execute( SvMemoryStream &rSourceStream,
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ sStreamName = UniString( "Memory", gsl_getSystemTextEncoding());
+ return Execute( (SvStream &)rSourceStream, pExistingList );
+}
+
+/*****************************************************************************/
+GenericInformationList *InformationParser::Execute(
+ SvFileStream &rSourceStream,
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ if ( !rSourceStream.IsOpen())
+ return NULL;
+ sStreamName = rSourceStream.GetFileName();
+ return Execute( (SvStream &)rSourceStream, pExistingList );
+}
+
+/*****************************************************************************/
+GenericInformationList *InformationParser::Execute( UniString &rSourceFile,
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ DirEntry aDirEntry( rSourceFile );
+ if ( !aDirEntry.Exists())
+ return NULL;
+
+ GenericInformationList *pList;
+ if ( pExistingList )
+ pList = pExistingList;
+ else
+ pList = new GenericInformationList();
+
+ // reset status
+ nErrorCode = 0;
+ nErrorLine = 0;
+ nActLine = 0;
+
+ SvFileStream aActStream;
+ aActStream.Open( rSourceFile, STREAM_READ );
+ if( aActStream.GetError())
+ return NULL;
+
+ pActStream = &aActStream;
+ if ( !Execute( aActStream, pList )) {
+ delete pList;
+ pList = NULL;
+ }
+
+ // close the stream
+ aActStream.Close();
+ pActStream = NULL;
+
+ if ( !nErrorCode )
+ return pList;
+
+ return NULL;
+}
+
+/*****************************************************************************/
+GenericInformationList *InformationParser::Execute( Dir &rDir,
+ GenericInformationList *pExistingList )
+/*****************************************************************************/
+{
+ GenericInformationList *pList;
+
+ if ( pExistingList )
+ pList = pExistingList;
+ else
+ pList = new GenericInformationList();
+
+ for ( USHORT i = 0; i < rDir.Count(); i++ ) {
+
+ // execute this dir
+ UniString sNextFile( rDir[i].GetFull());
+ GenericInformationList *pSubList = Execute( sNextFile );
+
+ if ( !pSubList ) {
+ // any errors ?
+ delete pList;
+ return NULL;
+ }
+
+ // create new info and insert it into list
+ ByteString sFileKey( rDir[i].GetName(), RTL_TEXTENCODING_UTF8 );
+ GenericInformation *pInfo = new GenericInformation(
+ sFileKey,
+ ByteString( "" ),
+ pList, pSubList );
+ }
+
+ return pList;
+}
+
+/*****************************************************************************/
+BOOL InformationParser::Save( SvFileStream &rSourceStream,
+ const GenericInformationList *pSaveList )
+/*****************************************************************************/
+{
+ if ( !rSourceStream.IsOpen() || !Save( (SvStream &)rSourceStream, pSaveList, 0 ))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+BOOL InformationParser::Save( SvMemoryStream &rSourceStream,
+ const GenericInformationList *pSaveList )
+/*****************************************************************************/
+{
+ return Save( (SvStream &)rSourceStream, pSaveList, 0 );
+}
+
+/*****************************************************************************/
+BOOL InformationParser::Save( const UniString &rSourceFile,
+ const GenericInformationList *pSaveList )
+/*****************************************************************************/
+{
+ SvFileStream *pOutFile = new SvFileStream( rSourceFile, STREAM_STD_WRITE | STREAM_TRUNC );
+
+ if ( !Save( *pOutFile, pSaveList )) {
+ delete pOutFile;
+ return FALSE;
+ }
+ delete pOutFile;
+ return TRUE;
+}
+
+/*****************************************************************************/
+USHORT InformationParser::GetErrorCode()
+/*****************************************************************************/
+{
+ return nErrorCode;
+}
+
+/*****************************************************************************/
+ByteString &InformationParser::GetErrorText()
+/*****************************************************************************/
+{
+ // sErrorText = pActStream->GetFileName();
+ sErrorText = ByteString( sStreamName, gsl_getSystemTextEncoding());
+ sErrorText += ByteString( " (" );
+ sErrorText += ByteString( nErrorLine );
+ sErrorText += ByteString( "): " );
+
+ switch ( nErrorCode ) {
+ case IP_NO_ERROR:
+ sErrorText += ByteString( "Keine Fehler aufgetereten" );
+ break;
+ case IP_UNEXPECTED_EOF:
+ sErrorText += ByteString( "Ungültiges Dateiende!" );
+ break;
+ }
+
+ return sErrorText;
+}
+
+
diff --git a/tools/source/datetime/datetime.cxx b/tools/source/datetime/datetime.cxx
new file mode 100644
index 000000000000..e3cf4a8895fe
--- /dev/null
+++ b/tools/source/datetime/datetime.cxx
@@ -0,0 +1,349 @@
+/*************************************************************************
+ *
+ * $RCSfile: datetime.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <datetime.hxx>
+
+/*************************************************************************
+|*
+|* DateTime::IsBetween()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 18.05.92
+|* Letzte Aenderung TH 18.05.92
+|*
+*************************************************************************/
+
+BOOL DateTime::IsBetween( const DateTime& rFrom,
+ const DateTime& rTo ) const
+{
+ if ( (*this >= rFrom) && (*this <= rTo) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator >()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 18.05.92
+|* Letzte Aenderung TH 18.05.92
+|*
+*************************************************************************/
+
+BOOL DateTime::operator >( const DateTime& rDateTime ) const
+{
+ if ( (Date::operator>( rDateTime )) ||
+ (Date::operator==( rDateTime ) && Time::operator>( rDateTime )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator <()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 18.05.92
+|* Letzte Aenderung TH 18.05.92
+|*
+*************************************************************************/
+
+BOOL DateTime::operator <( const DateTime& rDateTime ) const
+{
+ if ( (Date::operator<( rDateTime )) ||
+ (Date::operator==( rDateTime ) && Time::operator<( rDateTime )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator >=()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 18.05.92
+|* Letzte Aenderung TH 18.05.92
+|*
+*************************************************************************/
+
+BOOL DateTime::operator >=( const DateTime& rDateTime ) const
+{
+ if ( (Date::operator>( rDateTime )) ||
+ (Date::operator==( rDateTime ) && Time::operator>=( rDateTime )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator <=()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 18.05.92
+|* Letzte Aenderung TH 18.05.92
+|*
+*************************************************************************/
+
+BOOL DateTime::operator <=( const DateTime& rDateTime ) const
+{
+ if ( (Date::operator<( rDateTime )) ||
+ (Date::operator==( rDateTime ) && Time::operator<=( rDateTime )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DateTime::GetSecFromDateTime()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+ULONG DateTime::GetSecFromDateTime( const Date& rDate ) const
+{
+ if ( Date::operator<( rDate ) )
+ return 0;
+ else
+ {
+ ULONG nSec = *this-rDate;
+ nSec *= 24UL*60*60;
+ long nHour = GetHour();
+ long nMin = GetMin();
+ nSec += (nHour*3600)+(nMin*60)+GetSec();
+ return nSec;
+ }
+}
+
+/*************************************************************************
+|*
+|* DateTime::GetSecFromDateTime()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+void DateTime::MakeDateTimeFromSec( const Date& rDate, ULONG nSec )
+{
+ long nDays = nSec / (24UL*60*60);
+ ((Date*)this)->operator=( rDate );
+ nSec -= nDays * (24UL*60*60);
+ USHORT nMin = nSec / 60;
+ nSec -= nMin * 60;
+ ((Time*)this)->operator=( Time( 0, nMin, (USHORT)nSec ) );
+ operator+=( nDays );
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator +=()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime& DateTime::operator +=( const Time& rTime )
+{
+ Time aTime = *this;
+ aTime += rTime;
+ USHORT nHours = aTime.GetHour();
+ if ( aTime.GetTime() > 0 )
+ {
+ while ( nHours >= 24 )
+ {
+ Date::operator++();
+ nHours -= 24;
+ }
+ aTime.SetHour( nHours );
+ }
+ else if ( aTime.GetTime() != 0 )
+ {
+ while ( nHours >= 24 )
+ {
+ Date::operator--();
+ nHours -= 24;
+ }
+ Date::operator--();
+ aTime = Time( 24, 0, 0 )+aTime;
+ }
+ Time::operator=( aTime );
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator -=()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime& DateTime::operator -=( const Time& rTime )
+{
+ Time aTime = *this;
+ aTime -= rTime;
+ USHORT nHours = aTime.GetHour();
+ if ( aTime.GetTime() > 0 )
+ {
+ while ( nHours >= 24 )
+ {
+ Date::operator++();
+ nHours -= 24;
+ }
+ aTime.SetHour( nHours );
+ }
+ else if ( aTime.GetTime() != 0 )
+ {
+ while ( nHours >= 24 )
+ {
+ Date::operator--();
+ nHours -= 24;
+ }
+ Date::operator--();
+ aTime = Time( 24, 0, 0 )+aTime;
+ }
+ Time::operator=( aTime );
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator+()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime operator +( const DateTime& rDateTime, long nDays )
+{
+ DateTime aDateTime( rDateTime );
+ aDateTime += nDays;
+ return aDateTime;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator-()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime operator -( const DateTime& rDateTime, long nDays )
+{
+ DateTime aDateTime( rDateTime );
+ aDateTime -= nDays;
+ return aDateTime;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator+()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime operator +( const DateTime& rDateTime, const Time& rTime )
+{
+ DateTime aDateTime( rDateTime );
+ aDateTime += rTime;
+ return aDateTime;
+}
+
+/*************************************************************************
+|*
+|* DateTime::operator-()
+|*
+|* Beschreibung DATETIME.SDW
+|* Ersterstellung TH 02.10.96
+|* Letzte Aenderung TH 02.10.96
+|*
+*************************************************************************/
+
+DateTime operator -( const DateTime& rDateTime, const Time& rTime )
+{
+ DateTime aDateTime( rDateTime );
+ aDateTime -= rTime;
+ return aDateTime;
+}
diff --git a/tools/source/datetime/makefile.mk b/tools/source/datetime/makefile.mk
new file mode 100644
index 000000000000..5a53e0a0039f
--- /dev/null
+++ b/tools/source/datetime/makefile.mk
@@ -0,0 +1,88 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=datetime
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/tdate.obj \
+ $(SLO)$/ttime.obj \
+ $(SLO)$/datetime.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/tdate.obj \
+ $(OBJ)$/ttime.obj \
+ $(OBJ)$/datetime.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/datetime/tdate.cxx b/tools/source/datetime/tdate.cxx
new file mode 100644
index 000000000000..72c188944096
--- /dev/null
+++ b/tools/source/datetime/tdate.cxx
@@ -0,0 +1,540 @@
+/*************************************************************************
+ *
+ * $RCSfile: tdate.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#if defined( OS2 )
+#include <svpm.h>
+#elif defined( WNT )
+#include <svwin.h>
+#elif defined( WIN ) || defined( DOS )
+#include <dos.h>
+#elif defined( MAC )
+#include "mac_start.h"
+#ifndef __OSUTILS__
+#include "OSUtils.h"
+#endif
+#include "mac_end.h"
+#else
+#include <time.h>
+#endif
+
+#include <debug.hxx>
+#include <date.hxx>
+#ifdef MACOSX
+extern "C" {
+struct tm *localtime_r(const time_t *timep, struct tm *buffer);
+}
+#endif
+
+// =======================================================================
+
+static USHORT aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31 };
+
+#define MAX_DAYS 3636532
+
+// =======================================================================
+
+inline BOOL ImpIsLeapYear( USHORT nYear )
+{
+ return (((nYear % 4) == 0) && ((nYear % 100) != 0) || ((nYear % 400) == 0));
+}
+
+// -----------------------------------------------------------------------
+
+inline USHORT DaysInMonth( USHORT nMonth, USHORT nYear )
+{
+ if ( nMonth != 2 )
+ return aDaysInMonth[nMonth-1];
+ else
+ {
+ if ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ||
+ ((nYear % 400) == 0) )
+ return aDaysInMonth[nMonth-1] + 1;
+ else
+ return aDaysInMonth[nMonth-1];
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long DateToDays( USHORT nDay, USHORT nMonth, USHORT nYear )
+{
+ long nDays;
+
+ nDays = ((ULONG)nYear-1) * 365;
+ nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
+ for( USHORT i = 1; i < nMonth; i++ )
+ nDays += DaysInMonth(i,nYear);
+ nDays += nDay;
+ return nDays;
+}
+
+// -----------------------------------------------------------------------
+
+static void DaysToDate( long nDays,
+ USHORT& rDay, USHORT& rMonth, USHORT& rYear )
+{
+ long nTempDays;
+ long i = 0;
+ BOOL bCalc;
+
+ do
+ {
+ nTempDays = (long)nDays;
+ rYear = (USHORT)((nTempDays / 365) - i);
+ nTempDays -= ((ULONG)rYear-1) * 365;
+ nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400);
+ bCalc = FALSE;
+ if ( nTempDays < 1 )
+ {
+ i++;
+ bCalc = TRUE;
+ }
+ else
+ {
+ if ( nTempDays > 365 )
+ {
+ if ( (nTempDays != 366) || !ImpIsLeapYear( rYear ) )
+ {
+ i--;
+ bCalc = TRUE;
+ }
+ }
+ }
+ }
+ while ( bCalc );
+
+ rMonth = 1;
+ while ( (ULONG)nTempDays > DaysInMonth( rMonth, rYear ) )
+ {
+ nTempDays -= DaysInMonth( rMonth, rYear );
+ rMonth++;
+ }
+ rDay = (USHORT)nTempDays;
+}
+
+// =======================================================================
+
+Date::Date()
+{
+#if defined( OS2 )
+ DATETIME aDateTime;
+ DosGetDateTime( &aDateTime );
+
+ // Datum zusammenbauen
+ nDate = ((ULONG)aDateTime.day) +
+ (((ULONG)aDateTime.month)*100) +
+ (((ULONG)aDateTime.year)*10000);
+#elif defined( WNT )
+ SYSTEMTIME aDateTime;
+ GetLocalTime( &aDateTime );
+
+ // Datum zusammenbauen
+ nDate = ((ULONG)aDateTime.wDay) +
+ (((ULONG)aDateTime.wMonth)*100) +
+ (((ULONG)aDateTime.wYear)*10000);
+#elif ( defined( WIN ) || defined( DOS )) && !defined( BLC )
+ _dosdate_t aDate;
+ _dos_getdate( &aDate );
+
+ // Datum zusammenbauen
+ nDate = ((ULONG)aDate.day) +
+ (((ULONG)aDate.month)*100) +
+ (((ULONG)aDate.year)*10000);
+#elif ( defined( WIN ) || defined( DOS )) && defined( BLC )
+ dosdate_t aDate;
+ _dos_getdate( &aDate );
+
+ // Datum zusammenbauen
+ nDate = ((ULONG)aDate.day) +
+ (((ULONG)aDate.month)*100) +
+ (((ULONG)aDate.year)*10000);
+#elif defined( MAC )
+ DateTimeRec dt;
+ ::GetTime(&dt);
+ nDate = ((ULONG)dt.day) +
+ (((ULONG)dt.month)*100) +
+ (((ULONG)dt.year )*10000);
+#else
+ time_t nTmpTime;
+ struct tm aTime;
+
+ // Zeit ermitteln
+ nTmpTime = time( 0 );
+
+ // Datum zusammenbauen
+ if ( localtime_r( &nTmpTime, &aTime ) )
+ {
+ nDate = ((ULONG)aTime.tm_mday) +
+ (((ULONG)(aTime.tm_mon+1))*100) +
+ (((ULONG)(aTime.tm_year+1900))*10000);
+ }
+ else
+ nDate = 1 + 100 + (((ULONG)1900)*10000);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Date::SetDay( USHORT nNewDay )
+{
+ ULONG nMonth = GetMonth();
+ ULONG nYear = GetYear();
+
+ nDate = ((ULONG)(nNewDay%100)) + (nMonth*100) + (nYear*10000);
+}
+
+// -----------------------------------------------------------------------
+
+void Date::SetMonth( USHORT nNewMonth )
+{
+ ULONG nDay = GetDay();
+ ULONG nYear = GetYear();
+
+ nDate = nDay + (((ULONG)(nNewMonth%100))*100) + (nYear*10000);
+}
+
+// -----------------------------------------------------------------------
+
+void Date::SetYear( USHORT nNewYear )
+{
+ ULONG nDay = GetDay();
+ ULONG nMonth = GetMonth();
+
+ nDate = nDay + (nMonth*100) + (((ULONG)(nNewYear%10000))*10000);
+}
+
+// -----------------------------------------------------------------------
+
+DayOfWeek Date::GetDayOfWeek() const
+{
+ return (DayOfWeek)((ULONG)(DateToDays( GetDay(), GetMonth(), GetYear() )-1) % 7);
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Date::GetDayOfYear() const
+{
+ USHORT nDay = GetDay();
+ for( USHORT i = 1; i < GetMonth(); i++ )
+ nDay += ::DaysInMonth( i, GetYear() );
+ return nDay;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Date::GetWeekOfYear( DayOfWeek eStartDay,
+ WeekCountStart eWeekStart ) const
+{
+ short nWeek;
+ short n1WDay = (short)Date( 1, 1, GetYear() ).GetDayOfWeek();
+ short nDayOfYear = (short)GetDayOfYear();
+
+ // Wochentage beginnen bei 0, deshalb einen abziehen
+ nDayOfYear--;
+ // StartDay beruecksichtigen
+ n1WDay = (n1WDay+(7-(short)eStartDay)) % 7;
+
+ if ( eWeekStart == WEEKCOUNT_FIRSTDAY )
+ {
+ nWeek = ((n1WDay+nDayOfYear)/7) + 1;
+ // 53te-Woche nur dann, wenn wir nicht schon in der ersten
+ // Woche des neuen Jahres liegen
+ if ( nWeek == 54 )
+ nWeek = 1;
+ else if ( nWeek == 53 )
+ {
+ short nDaysInYear = (short)GetDaysInYear();
+ short nDaysNextYear = (short)Date( 1, 1, GetYear()+1 ).GetDayOfWeek();
+ nDaysNextYear = (nDaysNextYear+(7-(short)eStartDay)) % 7;
+ if ( nDayOfYear > (nDaysInYear-nDaysNextYear-1) )
+ nWeek = 1;
+ }
+ }
+ else if ( eWeekStart == WEEKCOUNT_FIRSTFULLWEEK )
+ {
+ nWeek = ((n1WDay+nDayOfYear)/7);
+ // Erste Woche eines Jahres entspricht der letzen Woche des
+ // vorherigen Jahres
+ if ( nWeek == 0 )
+ {
+ Date aLastDatePrevYear( 31, 12, GetYear()-1 );
+ nWeek = aLastDatePrevYear.GetWeekOfYear( eStartDay, eWeekStart );
+ }
+ }
+ else // ( eWeekStart == WEEKCOUNT_FIRST4DAYWEEK )
+ {
+ // x_monday - thursday
+ if ( n1WDay < 4 )
+ nWeek = 1;
+ // friday
+ else if ( n1WDay == 4 )
+ nWeek = 53;
+ // saturday
+ else if ( n1WDay == 5 )
+ {
+ // Jahr nach Schaltjahr
+ if ( Date( 1, 1, GetYear()-1 ).IsLeapYear() )
+ nWeek = 53;
+ else
+ nWeek = 52;
+ }
+ // sunday
+ else
+ nWeek = 52;
+
+ if ( (nWeek == 1) || (nDayOfYear + n1WDay > 6) )
+ {
+ if ( nWeek == 1 )
+ nWeek += (nDayOfYear + n1WDay) / 7;
+ else
+ nWeek = (nDayOfYear + n1WDay) / 7;
+ if ( nWeek == 53 )
+ {
+ // naechster x_Sonntag == erster x_Sonntag im neuen Jahr
+ // == noch gleiche Woche
+ long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
+ nTempDays += 6 - (GetDayOfWeek()+(7-(short)eStartDay)) % 7;
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT nYear;
+ DaysToDate( nTempDays, nDay, nMonth, nYear );
+ nWeek = Date( nDay, nMonth, nYear ).GetWeekOfYear( eStartDay, eWeekStart );
+ }
+ }
+ }
+
+ return (USHORT)nWeek;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Date::GetDaysInMonth() const
+{
+ return DaysInMonth( GetMonth(), GetYear() );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Date::IsLeapYear() const
+{
+ USHORT nYear = GetYear();
+ return ImpIsLeapYear( nYear );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Date::IsValid() const
+{
+ USHORT nDay = GetDay();
+ USHORT nMonth = GetMonth();
+ USHORT nYear = GetYear();
+
+ if ( !nMonth || (nMonth > 12) )
+ return FALSE;
+ if ( !nDay || (nDay > DaysInMonth( nMonth, nYear )) )
+ return FALSE;
+ else if ( nYear <= 1582 )
+ {
+ if ( nYear < 1582 )
+ return FALSE;
+ else if ( nMonth < 10 )
+ return FALSE;
+ else if ( (nMonth == 10) && (nDay < 15) )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Date& Date::operator +=( long nDays )
+{
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT nYear;
+ long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
+
+ nTempDays += nDays;
+ if ( nTempDays > MAX_DAYS )
+ nDate = 31 + (12*100) + (((ULONG)9999)*10000);
+ else if ( nTempDays <= 0 )
+ nDate = 1 + 100;
+ else
+ {
+ DaysToDate( nTempDays, nDay, nMonth, nYear );
+ nDate = ((ULONG)nDay) + (((ULONG)nMonth)*100) + (((ULONG)nYear)*10000);
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Date& Date::operator -=( long nDays )
+{
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT nYear;
+ long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
+
+ nTempDays -= nDays;
+ if ( nTempDays > MAX_DAYS )
+ nDate = 31 + (12*100) + (((ULONG)9999)*10000);
+ else if ( nTempDays <= 0 )
+ nDate = 1 + 100;
+ else
+ {
+ DaysToDate( nTempDays, nDay, nMonth, nYear );
+ nDate = ((ULONG)nDay) + (((ULONG)nMonth)*100) + (((ULONG)nYear)*10000);
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Date& Date::operator ++()
+{
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT nYear;
+ long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
+
+ if ( nTempDays < MAX_DAYS )
+ {
+ nTempDays++;
+ DaysToDate( nTempDays, nDay, nMonth, nYear );
+ nDate = ((ULONG)nDay) + (((ULONG)nMonth)*100) + (((ULONG)nYear)*10000);
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Date& Date::operator --()
+{
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT nYear;
+ long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
+
+ if ( nTempDays > 1 )
+ {
+ nTempDays--;
+ DaysToDate( nTempDays, nDay, nMonth, nYear );
+ nDate = ((ULONG)nDay) + (((ULONG)nMonth)*100) + (((ULONG)nYear)*10000);
+ }
+ return *this;
+}
+
+#ifndef MPW33
+
+// -----------------------------------------------------------------------
+
+Date Date::operator ++( int )
+{
+ Date aOldDate = *this;
+ Date::operator++();
+ return aOldDate;
+}
+
+// -----------------------------------------------------------------------
+
+Date Date::operator --( int )
+{
+ Date aOldDate = *this;
+ Date::operator--();
+ return aOldDate;
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+Date operator +( const Date& rDate, long nDays )
+{
+ Date aDate( rDate );
+ aDate += nDays;
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+Date operator -( const Date& rDate, long nDays )
+{
+ Date aDate( rDate );
+ aDate -= nDays;
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+long operator -( const Date& rDate1, const Date& rDate2 )
+{
+ ULONG nTempDays1 = DateToDays( rDate1.GetDay(), rDate1.GetMonth(),
+ rDate1.GetYear() );
+ ULONG nTempDays2 = DateToDays( rDate2.GetDay(), rDate2.GetMonth(),
+ rDate2.GetYear() );
+ return nTempDays1 - nTempDays2;
+}
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
new file mode 100644
index 000000000000..af1f2ef267e1
--- /dev/null
+++ b/tools/source/datetime/ttime.cxx
@@ -0,0 +1,531 @@
+/*************************************************************************
+ *
+ * $RCSfile: ttime.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_TIME_CXX
+
+#if defined( OS2 )
+#define INCL_DOSMISC
+#include <svpm.h>
+#elif defined( WNT )
+#include <svwin.h>
+#elif defined( WIN )
+#include <svwin.h>
+#include <dos.h>
+#elif defined( DOS )
+#include <dos.h>
+#elif defined UNX
+#include <limits.h>
+#ifdef IRIX
+#include <unistd.h>
+#endif
+#include <sys/times.h>
+#elif defined( MAC )
+#include "mac_start.h"
+#ifndef __OSUTILS__
+#include "OSUtils.h"
+#include <MAC_Timer.h>
+#include "mac_end.h"
+#endif
+#endif
+
+#include <time.h>
+#include <time.hxx>
+
+#ifdef UNX
+#include <math.h>
+#endif
+
+#ifndef WNT
+#ifndef localtime_r
+extern "C" {
+struct tm *localtime_r(const time_t *timep, struct tm *buffer);
+}
+#endif
+
+#ifndef gmtime_r
+extern "C" {
+struct tm *gmtime_r(const time_t *timep, struct tm *buffer);
+}
+#endif
+#endif
+
+// =======================================================================
+
+static long TimeToSec100( const Time& rTime )
+{
+ short nSign = (rTime.GetTime() >= 0) ? +1 : -1;
+ long nHour = rTime.GetHour();
+ long nMin = rTime.GetMin();
+ long nSec = rTime.GetSec();
+ long n100Sec = rTime.Get100Sec();
+
+// Wegen Interal Compiler Error bei MSC, etwas komplizierter
+// return (n100Sec + (nSec*100) + (nMin*60*100) + (nHour*60*60*100) * nSign);
+
+ long nRet = n100Sec;
+ nRet += nSec*100;
+ nRet += nMin*60*100;
+ nRet += nHour*60*60*100;
+
+ return (nRet * nSign);
+}
+
+// -----------------------------------------------------------------------
+
+static Time Sec100ToTime( long nSec100 )
+{
+ short nSign;
+ if ( nSec100 < 0 )
+ {
+ nSec100 *= -1;
+ nSign = -1;
+ }
+ else
+ nSign = 1;
+
+ Time aTime( 0, 0, 0, nSec100 );
+ aTime.SetTime( aTime.GetTime() * nSign );
+ return aTime;
+}
+
+// =======================================================================
+
+Time::Time()
+{
+#if defined( OS2 )
+ DATETIME aDateTime;
+ DosGetDateTime( &aDateTime );
+
+ // Zeit zusammenbauen
+ nTime = (((long)aDateTime.hours)*1000000) +
+ (((long)aDateTime.minutes)*10000) +
+ (((long)aDateTime.seconds)*100) +
+ ((long)aDateTime.hundredths);
+#elif defined( WNT )
+ SYSTEMTIME aDateTime;
+ GetLocalTime( &aDateTime );
+
+ // Zeit zusammenbauen
+ nTime = (((long)aDateTime.wHour)*1000000) +
+ (((long)aDateTime.wMinute)*10000) +
+ (((long)aDateTime.wSecond)*100) +
+ ((long)aDateTime.wMilliseconds/10);
+#elif ( defined( WIN ) || defined( DOS ) ) && !defined ( BLC )
+ _dostime_t aTime;
+ _dos_gettime( &aTime );
+
+ // Zeit zusammenbauen
+ nTime = (((long)aTime.hour)*1000000) +
+ (((long)aTime.minute)*10000) +
+ (((long)aTime.second)*100) +
+ ((long)aTime.hsecond);
+#elif ( defined( WIN ) || defined( DOS ) ) && defined ( BLC )
+ dostime_t aTime;
+ _dos_gettime( &aTime );
+
+ // Zeit zusammenbauen
+ nTime = (((long)aTime.hour)*1000000) +
+ (((long)aTime.minute)*10000) +
+ (((long)aTime.second)*100) +
+ ((long)aTime.hsecond);
+#elif defined( MAC )
+ DateTimeRec dt;
+ ::GetTime(&dt);
+ nTime = (((long)dt.hour)*1000000) +
+ (((long)dt.minute)*10000) +
+ (((long)dt.second)*100);
+#else
+ time_t nTmpTime;
+ struct tm aTime;
+
+ // Zeit ermitteln
+ nTmpTime = time( 0 );
+
+ // Zeit zusammenbauen
+ if ( localtime_r( &nTmpTime, &aTime ) )
+ {
+ nTime = (((long)aTime.tm_hour)*1000000) +
+ (((long)aTime.tm_min)*10000) +
+ (((long)aTime.tm_sec)*100);
+ }
+ else
+ nTime = 0;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Time::Time( ULONG nHour, ULONG nMin, ULONG nSec, ULONG n100Sec )
+{
+ // Zeit normalisieren
+ nSec += n100Sec / 100;
+ n100Sec = n100Sec % 100;
+ nMin += nSec / 60;
+ nSec = nSec % 60;
+ nHour += nMin / 60;
+ nMin = nMin % 60;
+
+ // Zeit zusammenbauen
+ nTime = (long)(n100Sec + (nSec*100) + (nMin*10000) + (nHour*1000000));
+}
+
+// -----------------------------------------------------------------------
+
+void Time::SetHour( USHORT nNewHour )
+{
+ short nSign = (nTime >= 0) ? +1 : -1;
+ long nMin = GetMin();
+ long nSec = GetSec();
+ long n100Sec = Get100Sec();
+
+ nTime = (n100Sec + (nSec*100) + (nMin*10000) +
+ (((long)nNewHour)*1000000)) * nSign;
+}
+
+// -----------------------------------------------------------------------
+
+void Time::SetMin( USHORT nNewMin )
+{
+ short nSign = (nTime >= 0) ? +1 : -1;
+ long nHour = GetHour();
+ long nSec = GetSec();
+ long n100Sec = Get100Sec();
+
+ // kein Ueberlauf
+ nNewMin = nNewMin % 60;
+
+ nTime = (n100Sec + (nSec*100) + (((long)nNewMin)*10000) +
+ (nHour*1000000)) * nSign;
+}
+
+// -----------------------------------------------------------------------
+
+void Time::SetSec( USHORT nNewSec )
+{
+ short nSign = (nTime >= 0) ? +1 : -1;
+ long nHour = GetHour();
+ long nMin = GetMin();
+ long n100Sec = Get100Sec();
+
+ // kein Ueberlauf
+ nNewSec = nNewSec % 60;
+
+ nTime = (n100Sec + (((long)nNewSec)*100) + (nMin*10000) +
+ (nHour*1000000)) * nSign;
+}
+
+// -----------------------------------------------------------------------
+
+void Time::Set100Sec( USHORT nNew100Sec )
+{
+ short nSign = (nTime >= 0) ? +1 : -1;
+ long nHour = GetHour();
+ long nMin = GetMin();
+ long nSec = GetSec();
+
+ // kein Ueberlauf
+ nNew100Sec = nNew100Sec % 100;
+
+ nTime = (((long)nNew100Sec) + (nSec*100) + (nMin*10000) +
+ (nHour*1000000)) * nSign;
+}
+
+// -----------------------------------------------------------------------
+
+long Time::GetMSFromTime() const
+{
+ short nSign = (nTime >= 0) ? +1 : -1;
+ long nHour = GetHour();
+ long nMin = GetMin();
+ long nSec = GetSec();
+ long n100Sec = Get100Sec();
+
+ return (((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10))*nSign);
+}
+
+// -----------------------------------------------------------------------
+
+void Time::MakeTimeFromMS( long nMS )
+{
+ short nSign;
+ if ( nMS < 0 )
+ {
+ nMS *= -1;
+ nSign = -1;
+ }
+ else
+ nSign = 1;
+
+ Time aTime( 0, 0, 0, nMS/10 );
+ SetTime( aTime.GetTime() * nSign );
+}
+
+// -----------------------------------------------------------------------
+
+Time& Time::operator +=( const Time& rTime )
+{
+ nTime = Sec100ToTime( TimeToSec100( *this ) +
+ TimeToSec100( rTime ) ).GetTime();
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Time& Time::operator -=( const Time& rTime )
+{
+ nTime = Sec100ToTime( TimeToSec100( *this ) -
+ TimeToSec100( rTime ) ).GetTime();
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Time operator +( const Time& rTime1, const Time& rTime2 )
+{
+ return Sec100ToTime( TimeToSec100( rTime1 ) +
+ TimeToSec100( rTime2 ) );
+}
+
+// -----------------------------------------------------------------------
+
+Time operator -( const Time& rTime1, const Time& rTime2 )
+{
+ return Sec100ToTime( TimeToSec100( rTime1 ) -
+ TimeToSec100( rTime2 ) );
+}
+
+// -----------------------------------------------------------------------
+
+Time Time::GetUTCOffset()
+{
+#if defined( OS2 )
+#undef timezone
+ DATETIME aDateTime;
+ DosGetDateTime( &aDateTime );
+
+ // Zeit zusammenbauen
+ if ( aDateTime.timezone != -1 )
+ {
+ short nTempTime = (short)Abs( aDateTime.timezone );
+ Time aTime( 0, (USHORT)nTempTime );
+ if ( aDateTime.timezone > 0 )
+ aTime = -aTime;
+ return aTime;
+ }
+ else
+ return Time( 0 );
+#elif defined( WNT )
+ TIME_ZONE_INFORMATION aTimeZone;
+ aTimeZone.Bias = 0;
+ DWORD nTimeZoneRet = GetTimeZoneInformation( &aTimeZone );
+ long nTempTime = aTimeZone.Bias;
+ if ( nTimeZoneRet == TIME_ZONE_ID_STANDARD )
+ nTempTime += aTimeZone.StandardBias;
+ else if ( nTimeZoneRet == TIME_ZONE_ID_DAYLIGHT )
+ nTempTime += aTimeZone.DaylightBias;
+ Time aTime( 0, (USHORT)Abs( nTempTime ) );
+ if ( nTempTime > 0 )
+ aTime = -aTime;
+ return aTime;
+#elif ( defined( WIN ) || defined( DOS ) ) && defined ( BLC )
+ static ULONG nCacheTicks = 0;
+ static long nCacheSecOffset = -1;
+ ULONG nTicks = Time::GetSystemTicks();
+ time_t nTime;
+ tm aTM;
+ long nLocalTime;
+ long nUTC;
+ short nTempTime;
+
+ // Evt. Wert neu ermitteln
+ if ( (nCacheSecOffset == -1) || ((nTicks - nCacheTicks) > 360000) )
+ {
+ nTime = time( 0 );
+ tm aTMTmp;
+ aTM = *localtime_r( &nTime, &aTMTmp);
+ nLocalTime = mktime( &aTM );
+ aTM = *gmtime_r( &nTime, &aTMTmp);
+ nUTC = mktime( &aTM );
+ nCacheTicks = nTicks;
+ nCacheSecOffset = (nLocalTime-nUTC) / 60;
+ }
+
+ nTempTime = (short)Abs( nCacheSecOffset );
+ Time aTime( 0, (USHORT)nTempTime );
+ if ( nCacheSecOffset < 0 )
+ aTime = -aTime;
+ return aTime;
+#else
+ static ULONG nCacheTicks = 0;
+ static long nCacheSecOffset = -1;
+ ULONG nTicks = Time::GetSystemTicks();
+ time_t nTime;
+ tm aTM;
+ long nLocalTime;
+ long nUTC;
+ short nTempTime;
+
+ // Evt. Wert neu ermitteln
+ if ( (nCacheSecOffset == -1) ||
+ ((nTicks - nCacheTicks) > 360000) ||
+ ( nTicks < nCacheTicks ) // handle overflow
+ )
+ {
+ nTime = time( 0 );
+ localtime_r( &nTime, &aTM );
+ nLocalTime = mktime( &aTM );
+#if defined( SOLARIS )
+ // Solaris gmtime_r() seems not to handle daylight saving time
+ // flags correctly
+ nUTC = nLocalTime + ( aTM.tm_isdst == 0 ? timezone : altzone );
+#elif defined( LINUX )
+ // Linux mktime() seems not to handle tm_isdst correctly
+ nUTC = nLocalTime - aTM.tm_gmtoff;
+#else
+ gmtime_r( &nTime, &aTM );
+ nUTC = mktime( &aTM );
+#endif
+ nCacheTicks = nTicks;
+ nCacheSecOffset = (nLocalTime-nUTC) / 60;
+ }
+
+ nTempTime = (short)Abs( nCacheSecOffset );
+ Time aTime( 0, (USHORT)nTempTime );
+ if ( nCacheSecOffset < 0 )
+ aTime = -aTime;
+ return aTime;
+#endif
+}
+
+
+// -----------------------------------------------------------------------
+
+ULONG Time::GetSystemTicks()
+{
+#if defined( WIN ) || defined( WNT )
+ return (ULONG)GetTickCount();
+#elif defined( OS2 )
+ PM_ULONG nClock;
+ DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
+ return (ULONG)nClock;
+#elif defined( MAC )
+ long long millisec;
+ Microseconds((UnsignedWide *)&millisec);
+ millisec = ( millisec + 500L ) / 1000L;
+ return (ULONG)millisec;
+#else
+ static ULONG nImplTicksPerSecond = 0;
+ static double dImplTicksPerSecond;
+ static double dImplTicksULONGMAX;
+ struct tms aTms;
+ ULONG nTicks = (ULONG)times( &aTms );
+
+ if ( !nImplTicksPerSecond )
+ {
+ nImplTicksPerSecond = CLK_TCK;
+ dImplTicksPerSecond = nImplTicksPerSecond;
+ dImplTicksULONGMAX = (double)(ULONG)ULONG_MAX;
+ }
+
+ double fTicks = nTicks;
+ fTicks *= 1000;
+ fTicks /= dImplTicksPerSecond;
+ fTicks = fmod (fTicks, dImplTicksULONGMAX);
+
+ return (ULONG)fTicks;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Time::GetProcessTicks()
+{
+#if defined( WIN ) || defined( WNT )
+ return (ULONG)GetTickCount();
+#elif defined( OS2 )
+ PM_ULONG nClock;
+ DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
+ return (ULONG)nClock;
+#elif defined( MAC )
+ long long millisec;
+ Microseconds((UnsignedWide *)&millisec);
+ millisec = ( millisec + 500L ) / 1000L;
+ return (ULONG)millisec;
+#else
+ static ULONG nImplTicksPerSecond = 0;
+ static double dImplTicksPerSecond;
+ static double dImplTicksULONGMAX;
+ ULONG nTicks = (ULONG)clock();
+
+ if ( !nImplTicksPerSecond )
+ {
+ nImplTicksPerSecond = CLOCKS_PER_SEC;
+ dImplTicksPerSecond = nImplTicksPerSecond;
+ dImplTicksULONGMAX = (double)(ULONG)ULONG_MAX;
+ }
+
+ double fTicks = nTicks;
+ fTicks *= 1000;
+ fTicks /= dImplTicksPerSecond;
+ fTicks = fmod (fTicks, dImplTicksULONGMAX);
+ return (ULONG)fTicks;
+#endif
+}
diff --git a/tools/source/debug/debug.cxx b/tools/source/debug/debug.cxx
new file mode 100644
index 000000000000..cfa1ce5dfa1b
--- /dev/null
+++ b/tools/source/debug/debug.cxx
@@ -0,0 +1,1581 @@
+/*************************************************************************
+ *
+ * $RCSfile: debug.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_DEBUG_CXX
+
+#ifndef MAC
+#if defined (UNX) || defined (GCC)
+#include <unistd.h>
+#else
+#include <direct.h>
+#endif
+#endif
+
+#include <time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef OS2
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSMISC
+#define INCL_WINDIALOGS
+#include <svpm.h>
+#endif
+
+#if defined ( WNT )
+#include <svwin.h>
+#endif
+
+#include <debug.hxx>
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+// --- DbgErrors ---
+
+static sal_Char const DbgError_ProfEnd1[] = "DBG_PROF...() without DBG_PROFSTART(): ";
+static sal_Char const DbgError_Xtor1[] = "DBG_DTOR() or DBG_CHKTHIS() without DBG_CTOR(): ";
+
+static sal_Char const DbgError_CtorDtor1[] = "this == NULL in class ";
+static sal_Char const DbgError_CtorDtor2[] = "invalid this-Pointer %p in class ";
+static sal_Char const DbgError_CtorDtor3[] = "Error-Msg from Object %p in class ";
+
+static sal_Char const DbgTrace_EnterCtor[] = "Enter Ctor from class ";
+static sal_Char const DbgTrace_LeaveCtor[] = "Leave Ctor from class ";
+static sal_Char const DbgTrace_EnterDtor[] = "Enter Dtor from class ";
+static sal_Char const DbgTrace_LeaveDtor[] = "Leave Dtor from class ";
+static sal_Char const DbgTrace_EnterMeth[] = "Enter method from class ";
+static sal_Char const DbgTrace_LeaveMeth[] = "Leave method from class ";
+
+// --- PointerList ---
+
+#define PBLOCKCOUNT 1024
+
+struct PBlock
+{
+ void* aData[PBLOCKCOUNT];
+ USHORT nCount;
+ PBlock* pPrev;
+ PBlock* pNext;
+};
+
+class PointerList
+{
+private:
+ PBlock* pFirst;
+ PBlock* pLast;
+ ULONG nCount;
+
+public:
+ PointerList() { pFirst = NULL; pLast = NULL; nCount = 0; }
+ ~PointerList();
+
+ void Add( const void* p );
+ BOOL Remove( const void* p );
+
+ const void* Get( ULONG nPos ) const;
+ BOOL IsIn( const void* p ) const;
+ ULONG Count() const { return nCount; }
+};
+
+// --- Datentypen ---
+
+#define DBG_MAXNAME 28
+
+struct ProfType
+{
+ ULONG nCount;
+ ULONG nTime;
+ ULONG nMinTime;
+ ULONG nMaxTime;
+ ULONG nStart;
+ ULONG nContinueTime;
+ ULONG nContinueStart;
+ sal_Char aName[DBG_MAXNAME+1];
+};
+
+struct XtorType
+{
+ ULONG nCtorCalls;
+ ULONG nDtorCalls;
+ ULONG nMaxCount;
+ ULONG nStatics;
+ sal_Char aName[DBG_MAXNAME+1];
+ BOOL bTest;
+ PointerList aThisList;
+};
+
+struct DebugData
+{
+ DbgData aDbgData;
+ USHORT bInit;
+ DbgPrintLine pDbgPrintMsgBox;
+ DbgPrintLine pDbgPrintWindow;
+ DbgPrintLine pDbgPrintShell;
+ DbgPrintLine pDbgPrintTestTool;
+ PointerList* pProfList;
+ PointerList* pXtorList;
+ DbgTestSolarMutexProc pDbgTestSolarMutex;
+};
+
+#define DBG_TEST_XTOR_EXTRA (DBG_TEST_XTOR_THIS | DBG_TEST_XTOR_FUNC | \
+ DBG_TEST_XTOR_EXIT | DBG_TEST_XTOR_REPORT )
+
+// ------------------------------
+// - statische Verwaltungsdaten -
+// ------------------------------
+
+static DebugData aDebugData =
+{
+ {
+ DBG_TEST_RESOURCE | DBG_TEST_MEM_INIT,
+ TRUE,
+ DBG_OUT_NULL,
+ DBG_OUT_NULL,
+ DBG_OUT_MSGBOX,
+ 0x77,
+ 0x55,
+ 0x33,
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ },
+ FALSE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+#ifndef MAC
+static sal_Char aCurPath[260];
+#endif
+
+static int bDbgImplInMain = FALSE;
+static sal_Char aBuf[DBG_BUF_MAXLEN];
+static sal_Char aBufOut[DBG_BUF_MAXLEN];
+
+// =======================================================================
+
+#if defined( WNT )
+static CRITICAL_SECTION aImplCritDbgSection;
+#elif defined( OS2 )
+static HMTX hImplCritDbgSection = 0;
+#endif
+static BOOL bImplCritDbgSectionInit = FALSE;
+
+// -----------------------------------------------------------------------
+
+void ImplDbgInitLock()
+{
+#if defined( WNT )
+ InitializeCriticalSection( &aImplCritDbgSection );
+#elif defined( OS2 )
+ DosCreateMutexSem( NULL, &hImplCritDbgSection, 0, FALSE );
+#endif
+ bImplCritDbgSectionInit = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDbgDeInitLock()
+{
+#if defined( WNT )
+ DeleteCriticalSection( &aImplCritDbgSection );
+#elif defined( OS2 )
+ DosCloseMutexSem( hImplCritDbgSection );
+#endif
+ bImplCritDbgSectionInit = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDbgLock()
+{
+ if ( !bImplCritDbgSectionInit )
+ return;
+
+#if defined( WNT )
+ EnterCriticalSection( &aImplCritDbgSection );
+#elif defined( OS2 )
+ DosRequestMutexSem( hImplCritDbgSection, SEM_INDEFINITE_WAIT );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDbgUnlock()
+{
+ if ( !bImplCritDbgSectionInit )
+ return;
+
+#if defined( WNT )
+ LeaveCriticalSection( &aImplCritDbgSection );
+#elif defined( OS2 )
+ DosReleaseMutexSem( hImplCritDbgSection );
+#endif
+}
+
+// =======================================================================
+
+// Aus DBMEM.CXX
+#if (defined( WNT ) || defined( OS2 ) || defined( MAC )) && !defined ( SVX_LIGHT )
+#define SV_MEMMGR
+#endif
+#ifdef SV_MEMMGR
+void DbgImpCheckMemory( void* p = NULL );
+void DbgImpCheckMemoryDeInit();
+void DbgImpMemoryInfo( sal_Char* pBuf );
+#endif
+
+#if defined( OS2 )
+#define FILE_LINEEND "\r\n"
+#else
+#define FILE_LINEEND "\n"
+#endif
+
+// =======================================================================
+
+static BOOL ImplActivateDebugger( const sal_Char* pMsg )
+{
+#if defined( WNT )
+ static sal_Char aImplDbgOutBuf[DBG_BUF_MAXLEN];
+ strcpy( aImplDbgOutBuf, pMsg );
+ strcat( aImplDbgOutBuf, "\r\n" );
+ OutputDebugString( aImplDbgOutBuf );
+ DebugBreak();
+ return TRUE;
+#elif defined( MAC )
+ debugstr( (sal_Char*)pLine );
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplCoreDump( const sal_Char* pMsg )
+{
+#if defined( WNT )
+ DebugBreak();
+#else
+ long* pTemp = 0;
+ *pTemp = 0xCCCC;
+#endif
+ return TRUE;
+}
+
+// =======================================================================
+
+static ULONG ImplGetPerfTime()
+{
+#if defined( WNT )
+ return (ULONG)GetTickCount();
+#elif defined( OS2 )
+ PM_ULONG nClock;
+ DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
+ return (ULONG)nClock;
+#elif defined( MAC )
+ long long millisec;
+ Microseconds((UnsignedWide *)&millisec);
+ millisec = ( millisec + 500L ) / 1000L;
+ return (ULONG)millisec;
+#else
+ static ULONG nImplTicksPerSecond = 0;
+ static double dImplTicksPerSecond;
+ ULONG nTicks = (ULONG)clock();
+
+ if ( !nImplTicksPerSecond )
+ {
+ nImplTicksPerSecond = CLOCKS_PER_SEC;
+ dImplTicksPerSecond = nImplTicksPerSecond;
+ }
+
+ double fTicks = nTicks;
+ fTicks *= 1000;
+ fTicks /= dImplTicksPerSecond;
+ return (ULONG)fTicks;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#if defined( OS2 )
+
+typedef HFILE FILETYPE;
+
+static FILETYPE FileOpen( const sal_Char* pFileName, const sal_Char* pOpenMode )
+{
+ HFILE hFile = 0;
+ ULONG lAction = 0;
+ ULONG nOpen1 = FILE_OPEN;
+ ULONG nOpen2 = OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY;
+
+ if ( *pOpenMode == 'w' )
+ {
+ nOpen1 = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+ nOpen2 = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE;
+ }
+ else if ( *pOpenMode == 'a' )
+ {
+ nOpen1 = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ nOpen2 = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE;
+ }
+
+ APIRET nRet = DosOpen( pFileName, &hFile, &lAction, 0,
+ FILE_NORMAL, nOpen1, nOpen2, 0L );
+
+ if ( nRet )
+ return NULL;
+ else
+ {
+ if ( *pOpenMode == 'a' )
+ {
+ ULONG nTemp;
+ DosSetFilePtr( hFile, 0, FILE_END, &nTemp );
+ }
+
+ return hFile;
+ }
+}
+
+static ULONG FileRead( void* pData, int n1, int n2, FILETYPE pFile )
+{
+ ULONG nRead;
+ DosRead( pFile, pData, n1*n2, &nRead );
+ return nRead;
+}
+
+static ULONG FileWrite( void* pData, int n1, int n2, FILETYPE pFile )
+{
+ ULONG nWritten;
+ DosWrite( pFile, pData, n1*n2, &nWritten );
+ return nWritten;
+}
+
+static void FilePrintF( FILETYPE pFile, const sal_Char* pFStr, ... )
+{
+ static sal_Char aTempBuf[DBG_BUF_MAXLEN];
+
+ va_list pList;
+
+ va_start( pList, pFStr );
+ vsprintf( aTempBuf, pFStr, pList );
+ va_end( pList );
+
+ FileWrite( aTempBuf, strlen( aTempBuf ), 1, pFile );
+}
+
+static void FileClose( FILETYPE pFile )
+{
+ DosClose( pFile );
+}
+
+#else
+
+typedef FILE* FILETYPE;
+#define FileOpen fopen
+#define FileRead fread
+#define FileWrite fwrite
+#define FilePrintF fprintf
+#define FileClose fclose
+
+#endif
+
+// =======================================================================
+
+PointerList::~PointerList()
+{
+ PBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ PBlock* pNextBlock = pBlock->pNext;
+ delete pBlock;
+ pBlock = pNextBlock;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PointerList::Add( const void* p )
+{
+ if ( !pFirst )
+ {
+ pFirst = new PBlock;
+ memset( pFirst->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
+ pFirst->nCount = 0;
+ pFirst->pPrev = NULL;
+ pFirst->pNext = NULL;
+ pLast = pFirst;
+ }
+
+ PBlock* pBlock = pFirst;
+ while ( pBlock && (pBlock->nCount == PBLOCKCOUNT) )
+ pBlock = pBlock->pNext;
+
+ if ( !pBlock )
+ {
+ pBlock = new PBlock;
+ memset( pBlock->aData, 0, PBLOCKCOUNT * sizeof( void* ) );
+ pBlock->nCount = 0;
+ pBlock->pPrev = pLast;
+ pBlock->pNext = NULL;
+ pLast->pNext = pBlock;
+ pLast = pBlock;
+ }
+
+ USHORT i = 0;
+ while ( pBlock->aData[i] )
+ i++;
+
+ pBlock->aData[i] = (void*)p;
+ pBlock->nCount++;
+ nCount++;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL PointerList::Remove( const void* p )
+{
+ if ( !p )
+ return FALSE;
+
+ PBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ USHORT i = 0;
+ while ( i < PBLOCKCOUNT )
+ {
+ if ( ((ULONG)p) == ((ULONG)pBlock->aData[i]) )
+ {
+ pBlock->aData[i] = NULL;
+ pBlock->nCount--;
+ nCount--;
+
+ if ( !pBlock->nCount )
+ {
+ if ( pBlock->pPrev )
+ pBlock->pPrev->pNext = pBlock->pNext;
+ if ( pBlock->pNext )
+ pBlock->pNext->pPrev = pBlock->pPrev;
+ if ( pBlock == pFirst )
+ pFirst = pBlock->pNext;
+ if ( pBlock == pLast )
+ pLast = pBlock->pPrev;
+ delete pBlock;
+ }
+
+ return TRUE;
+ }
+ i++;
+ }
+
+ pBlock = pBlock->pNext;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+const void* PointerList::Get( ULONG nPos ) const
+{
+ if ( nCount <= nPos )
+ return NULL;
+
+ PBlock* pBlock = pFirst;
+ ULONG nStart = 0;
+ while ( pBlock )
+ {
+ USHORT i = 0;
+ while ( i < PBLOCKCOUNT )
+ {
+ if ( pBlock->aData[i] )
+ {
+ nStart++;
+ if ( (nStart-1) == nPos )
+ return pBlock->aData[i];
+ }
+
+ i++;
+ }
+
+ pBlock = pBlock->pNext;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL PointerList::IsIn( const void* p ) const
+{
+ if ( !p )
+ return FALSE;
+
+ PBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ USHORT i = 0;
+ while ( i < PBLOCKCOUNT )
+ {
+ if ( ((ULONG)p) == ((ULONG)pBlock->aData[i]) )
+ return TRUE;
+ i++;
+ }
+
+ pBlock = pBlock->pNext;
+ }
+
+ return FALSE;
+}
+
+
+// =======================================================================
+
+static void DbgGetDbgFileName( sal_Char* pStr )
+{
+#if defined( UNX )
+ const sal_Char* pName = getenv("DBGSV_INIT");
+ if ( !pName )
+ pName = ".dbgsv.init";
+ strcpy( pStr, pName );
+#elif defined( WNT )
+ const sal_Char* pName = getenv("DBGSV_INIT");
+ if ( pName )
+ strcpy( pStr, pName );
+ else
+ GetProfileStringA( "sv", "dbgsv", "dbgsv.ini", pStr, 200 );
+#elif defined( OS2 )
+ PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSV",
+ "dbgsv.ini", (PSZ)pStr, 200 );
+#else
+ strcpy( pStr, "dbgsv.ini" );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static void DbgGetLogFileName( sal_Char* pStr )
+{
+#if defined( UNX )
+ const sal_Char* pName = getenv("DBGSV_LOG");
+ if ( !pName )
+ pName = "dbgsv.log";
+ strcpy( pStr, pName );
+#elif defined( WNT )
+ const sal_Char* pName = getenv("DBGSV_LOG");
+ if ( pName )
+ strcpy( pStr, pName );
+ else
+ GetProfileStringA( "sv", "dbgsvlog", "dbgsv.log", pStr, 200 );
+#elif defined( OS2 )
+ PrfQueryProfileString( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGSVLOG",
+ "dbgsv.log", (PSZ)pStr, 200 );
+#else
+ strcpy( pStr, "dbgsv.log" );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static int DbgImplIsAllErrorOut()
+{
+#if defined( WNT )
+ const sal_Char* pName = getenv("UPDATER");
+ if ( pName && (strcmp( pName, "YES" ) == 0) )
+ return TRUE;
+ if ( GetProfileInt( "sv", "dbgallerrorout", 0 ) )
+ return TRUE;
+ else
+ return FALSE;
+#elif defined( OS2 )
+ const sal_Char* pName = getenv("UPDATER");
+ if ( pName && (strcmp( pName, "YES" ) == 0) )
+ return TRUE;
+ if ( PrfQueryProfileInt( HINI_PROFILE, (PSZ)"SV", (PSZ)"DBGALLERROROUT", 0 ) )
+ return TRUE;
+ else
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static void DbgDebugBeep()
+{
+#if defined( WNT )
+ MessageBeep( MB_ICONHAND );
+#elif defined( OS2 )
+ WinAlarm( HWND_DESKTOP, WA_ERROR );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static DebugData* GetDebugData()
+{
+ if ( !aDebugData.bInit )
+ {
+ aDebugData.bInit = TRUE;
+
+ // Default Debug-Namen setzen
+ DbgGetLogFileName( aDebugData.aDbgData.aDebugName );
+
+ // DEBUG.INI-File
+ FILETYPE pDbgFile;
+ DbgGetDbgFileName( aBuf );
+ if ( (pDbgFile = FileOpen( aBuf, "r" )) != NULL )
+ {
+ FileRead( &(aDebugData.aDbgData), sizeof( DbgData ), 1, pDbgFile );
+ FileClose( pDbgFile );
+ }
+
+#ifndef MAC
+ getcwd( aCurPath, sizeof( aCurPath ) );
+#endif
+
+ // Daten initialisieren
+ if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_XTOR )
+ aDebugData.pXtorList = new PointerList;
+ if ( aDebugData.aDbgData.nTestFlags & DBG_TEST_PROFILING )
+ aDebugData.pProfList = new PointerList;
+ if ( aDebugData.aDbgData.nErrorOut < DBG_OUT_MSGBOX )
+ {
+ if ( !DbgImplIsAllErrorOut() )
+ aDebugData.aDbgData.nErrorOut = DBG_OUT_MSGBOX;
+ }
+ }
+
+ return &aDebugData;
+}
+
+// -----------------------------------------------------------------------
+
+inline DebugData* ImplGetDebugData()
+{
+ if ( !aDebugData.bInit )
+ return GetDebugData();
+ else
+ return &aDebugData;
+}
+
+// -----------------------------------------------------------------------
+
+static FILETYPE ImplDbgInitFile()
+{
+ static BOOL bFileInit = FALSE;
+
+#ifndef MAC
+ getcwd( aBuf, sizeof( aBuf ) );
+ chdir( aCurPath );
+#endif
+
+ DebugData* pData = GetDebugData();
+ FILETYPE pDebugFile;
+
+ if ( !bFileInit )
+ {
+ bFileInit = TRUE;
+
+ if ( pData->aDbgData.bOverwrite )
+ pDebugFile = FileOpen( pData->aDbgData.aDebugName, "w" );
+ else
+ pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
+
+ if ( pDebugFile )
+ {
+ time_t nTime = time( 0 );
+ tm* pTime;
+#ifdef UNX
+ tm aTime;
+ pTime = localtime_r( &nTime, &aTime );
+#else
+ pTime = localtime( &nTime );
+#endif
+
+ // Header ausgeben
+ FilePrintF( pDebugFile, "******************************************************************************%s", FILE_LINEEND );
+ FilePrintF( pDebugFile, "%s%s", pData->aDbgData.aDebugName, FILE_LINEEND );
+ if ( pTime )
+ FilePrintF( pDebugFile, "%s%s", asctime( pTime ), FILE_LINEEND );
+ }
+ }
+ else
+ pDebugFile = FileOpen( pData->aDbgData.aDebugName, "a" );
+
+#ifndef MAC
+ chdir( aBuf );
+#endif
+
+ return pDebugFile;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDbgPrintFile( const sal_Char* pLine )
+{
+ FILETYPE pDebugFile = ImplDbgInitFile();
+
+ if ( pDebugFile )
+ {
+ FilePrintF( pDebugFile, "%s%s", pLine, FILE_LINEEND );
+ FileClose( pDebugFile );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static int ImplStrSearch( const sal_Char* pSearchStr, int nSearchLen,
+ const sal_Char* pStr, int nLen )
+{
+ int nPos = 0;
+ while ( nPos+nSearchLen <= nLen )
+ {
+ if ( strncmp( pStr+nPos, pSearchStr, nSearchLen ) == 0 )
+ return 1;
+ nPos++;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static int ImplDbgFilter( const sal_Char* pFilter, const sal_Char* pMsg,
+ int bEmpty )
+{
+ int nStrLen = strlen( pFilter );
+ if ( !nStrLen )
+ return bEmpty;
+
+ int nMsgLen = strlen( pMsg );
+ const sal_Char* pTok = pFilter;
+ int nTok = 0;
+ while ( pTok[nTok] )
+ {
+ if ( pTok[nTok] == ';' )
+ {
+ if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
+ return TRUE;
+
+ pTok += nTok+1;
+ nTok = 0;
+ }
+
+ nTok++;
+ }
+
+ if ( nTok && ImplStrSearch( pTok, nTok, pMsg, nMsgLen ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static void DebugInit()
+{
+ bDbgImplInMain = TRUE;
+ ImplDbgInitLock();
+}
+
+// -----------------------------------------------------------------------
+
+static void DebugDeInit()
+{
+ DebugData* pData = GetDebugData();
+ ULONG i;
+ ULONG nCount;
+ ULONG nOldOut;
+
+ // Statistik-Ausgaben immer in File
+ nOldOut = pData->aDbgData.nTraceOut;
+ pData->aDbgData.nTraceOut = DBG_OUT_FILE;
+
+ // Xtor-Liste ausgeben
+ if ( pData->pXtorList && pData->pXtorList->Count() &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) )
+ {
+ DbgOutf( "------------------------------------------------------------------------------" );
+ DbgOutf( "Object Report" );
+ DbgOutf( "------------------------------------------------------------------------------" );
+ DbgOutf( "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
+ "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
+ DbgOutf( "----------------------------:-----------:-----------:---------:----:---------:" );
+ for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
+ {
+ XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
+ if ( pXtorData->bTest )
+ {
+ // Static-Objekte dazurechnen
+ pXtorData->nDtorCalls += pXtorData->nStatics;
+ if ( pXtorData->nStatics && (pXtorData->nDtorCalls > pXtorData->nCtorCalls) )
+ pXtorData->nDtorCalls = pXtorData->nCtorCalls;
+ DbgOutf( "%-27s : %9lu : %9lu : %7lu : %3lu : %4lu %-1s :",
+ pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls,
+ pXtorData->nMaxCount, pXtorData->nStatics,
+ pXtorData->nCtorCalls - pXtorData->nDtorCalls,
+ (pXtorData->nCtorCalls - pXtorData->nDtorCalls) ? "!" : " " );
+ }
+ }
+ DbgOutf( "==============================================================================" );
+ }
+
+ // Aufraeumen
+ if ( pData->pXtorList )
+ {
+ for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
+ {
+ XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
+ delete pXtorData;
+ }
+ delete pData->pXtorList;
+ pData->pXtorList = NULL;
+ }
+
+ // Alles auf FALSE setzen, damit globale Variablen nicht das
+ // System zum Abstuerzen bringt. Dabei muessen aber die
+ // Memory-Flags erhalten bleiben, da sonst new/delete in globalen
+ // Variablen abstuerzen, da die Pointeranpassung dann nicht mehr richtig
+ // funktioniert
+ pData->aDbgData.nTraceOut = nOldOut;
+ pData->aDbgData.nTestFlags &= (DBG_TEST_MEM | DBG_TEST_PROFILING);
+ pData->pDbgPrintTestTool = NULL;
+ pData->pDbgPrintShell = NULL;
+ pData->pDbgPrintWindow = NULL;
+ pData->pDbgPrintShell = NULL;
+ ImplDbgDeInitLock();
+}
+
+// -----------------------------------------------------------------------
+
+static void DebugGlobalDeInit()
+{
+ DebugData* pData = GetDebugData();
+ ULONG i;
+ ULONG nCount;
+ ULONG nOldOut;
+
+ // Statistik-Ausgaben immer in File
+ nOldOut = pData->aDbgData.nTraceOut;
+ pData->aDbgData.nTraceOut = DBG_OUT_FILE;
+
+ // Profileliste ausgeben
+ if ( pData->pProfList && pData->pProfList->Count() )
+ {
+ DbgOutf( "------------------------------------------------------------------------------" );
+ DbgOutf( "Profiling Report" );
+ DbgOutf( "------------------------------------------------------------------------------" );
+ DbgOutf( "%-25s : %-9s : %-6s : %-6s : %-6s : %-9s :",
+ "Prof-List (ms)", "Time", "Min", "Max", "Ave", "Count" );
+ DbgOutf( "--------------------------:-----------:--------:--------:--------:-----------:" );
+ for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ )
+ {
+ ProfType* pProfData = (ProfType*)pData->pProfList->Get( i );
+ ULONG nAve = pProfData->nTime / pProfData->nCount;
+ DbgOutf( "%-25s : %9lu : %6lu : %6lu : %6lu : %9lu :",
+ pProfData->aName, pProfData->nTime,
+ pProfData->nMinTime, pProfData->nMaxTime, nAve,
+ pProfData->nCount );
+ }
+ DbgOutf( "==============================================================================" );
+ }
+
+ // Aufraeumen
+ if ( pData->pProfList )
+ {
+ for( i = 0, nCount = pData->pProfList->Count(); i < nCount; i++ )
+ {
+ ProfType* pProfData = (ProfType*)pData->pProfList->Get( i );
+ delete pProfData;
+ }
+ delete pData->pProfList;
+ pData->pProfList = NULL;
+ }
+
+#ifdef SV_MEMMGR
+ DbgImpCheckMemoryDeInit();
+#endif
+
+ // Profiling-Flags ausschalten
+ pData->aDbgData.nTraceOut = nOldOut;
+ pData->aDbgData.nTestFlags &= ~DBG_TEST_PROFILING;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpDbgOutfBuf( sal_Char* pBuf, const sal_Char* pFStr, ... )
+{
+ va_list pList;
+
+ va_start( pList, pFStr );
+ vsprintf( aBuf, pFStr, pList );
+ va_end( pList );
+
+ strcat( pBuf, aBuf );
+ strcat( pBuf, "\n" );
+}
+
+// -----------------------------------------------------------------------
+
+static void DebugXTorInfo( sal_Char* pBuf )
+{
+ DebugData* pData = GetDebugData();
+ ULONG i;
+ ULONG nCount;
+
+ // Xtor-Liste ausgeben
+ if ( pData->pXtorList && pData->pXtorList->Count() &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_REPORT) )
+ {
+ ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" );
+ ImpDbgOutfBuf( pBuf, "Object Report" );
+ ImpDbgOutfBuf( pBuf, "------------------------------------------------------------------------------" );
+ ImpDbgOutfBuf( pBuf, "%-27s : %-9s : %-9s : %-7s : %-3s : %-6s :",
+ "XTor-List", "Ctor", "Dtor", "MaxInst", "St.", "Diff." );
+ ImpDbgOutfBuf( pBuf, "----------------------------:-----------:-----------:---------:----:---------:" );
+ for( i = 0, nCount = pData->pXtorList->Count(); i < nCount; i++ )
+ {
+ XtorType* pXtorData = (XtorType*)pData->pXtorList->Get( i );
+ if ( pXtorData->bTest )
+ {
+ ImpDbgOutfBuf( pBuf, "%-27s : %9lu : %9lu : %7lu : %3lu : %6lu :",
+ pXtorData->aName, pXtorData->nCtorCalls, pXtorData->nDtorCalls,
+ pXtorData->nMaxCount, pXtorData->nStatics,
+ pXtorData->nCtorCalls - pXtorData->nDtorCalls );
+ }
+ }
+ ImpDbgOutfBuf( pBuf, "==============================================================================" );
+ ImpDbgOutfBuf( pBuf, "" );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* DbgFunc( USHORT nAction, void* pParam )
+{
+ DebugData* pData = ImplGetDebugData();
+
+ if ( nAction == DBG_FUNC_GETDATA )
+ return (void*)&(pData->aDbgData);
+ else
+ {
+ switch ( nAction )
+ {
+ case DBG_FUNC_DEBUGSTART:
+ DebugInit();
+ break;
+
+ case DBG_FUNC_DEBUGEND:
+ DebugDeInit();
+ break;
+
+ case DBG_FUNC_GLOBALDEBUGEND:
+ DebugGlobalDeInit();
+ break;
+
+ case DBG_FUNC_SETPRINTMSGBOX:
+ pData->pDbgPrintMsgBox = (DbgPrintLine)pParam;
+ break;
+
+ case DBG_FUNC_SETPRINTWINDOW:
+ pData->pDbgPrintWindow = (DbgPrintLine)pParam;
+ break;
+
+ case DBG_FUNC_SETPRINTSHELL:
+ pData->pDbgPrintShell = (DbgPrintLine)pParam;
+ break;
+
+ case DBG_FUNC_SETPRINTTESTTOOL:
+ pData->pDbgPrintTestTool = (DbgPrintLine)pParam;
+ break;
+
+ case DBG_FUNC_SAVEDATA:
+ {
+ FILETYPE pDbgFile;
+ DbgGetDbgFileName( aBuf );
+ if ( (pDbgFile = FileOpen( aBuf, "w" )) != NULL )
+ {
+ FileWrite( pParam, sizeof( DbgData ), 1, pDbgFile );
+ FileClose( pDbgFile );
+ }
+ }
+ break;
+
+ case DBG_FUNC_MEMTEST:
+#ifdef SV_MEMMGR
+ DbgImpCheckMemory( pParam );
+#endif
+ break;
+
+ case DBG_FUNC_XTORINFO:
+ DebugXTorInfo( (sal_Char*)pParam );
+ break;
+
+ case DBG_FUNC_MEMINFO:
+#ifdef SV_MEMMGR
+ DbgImpMemoryInfo( (sal_Char*)pParam );
+#endif
+ break;
+
+ case DBG_FUNC_COREDUMP:
+ ImplCoreDump( NULL );
+ break;
+
+ case DBG_FUNC_ALLERROROUT:
+ return (void*)(ULONG)DbgImplIsAllErrorOut();
+
+ case DBG_FUNC_SETTESTSOLARMUTEX:
+ pData->pDbgTestSolarMutex = (DbgTestSolarMutexProc)pParam;
+ break;
+
+ case DBG_FUNC_TESTSOLARMUTEX:
+ if ( pData->pDbgTestSolarMutex )
+ pData->pDbgTestSolarMutex();
+ break;
+
+ case DBG_FUNC_PRINTFILE:
+ ImplDbgPrintFile( (const sal_Char*)pParam );
+ break;
+ }
+
+ return NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DbgProf( USHORT nAction, DbgDataType* pDbgData )
+{
+ // Ueberhaupt Profiling-Test an
+ DebugData* pData = ImplGetDebugData();
+ ProfType* pProfData = (ProfType*)pDbgData->pData;
+ ULONG nTime;
+
+ if ( !(pData->aDbgData.nTestFlags & DBG_TEST_PROFILING) )
+ return;
+
+ if ( (nAction != DBG_PROF_START) && !pProfData )
+ {
+ strcpy( aBuf, DbgError_ProfEnd1 );
+ strcat( aBuf, pDbgData->pName );
+ DbgError( aBuf );
+ return;
+ }
+
+ switch ( nAction )
+ {
+ case DBG_PROF_START:
+ if ( !pDbgData->pData )
+ {
+ pDbgData->pData = (void*)new ProfType;
+ pProfData = (ProfType*)pDbgData->pData;
+ strncpy( pProfData->aName, pDbgData->pName, DBG_MAXNAME );
+ pProfData->aName[DBG_MAXNAME] = '\0';
+ pProfData->nCount = 0;
+ pProfData->nTime = 0;
+ pProfData->nMinTime = 0xFFFFFFFF;
+ pProfData->nMaxTime = 0;
+ pProfData->nStart = 0xFFFFFFFF;
+ pProfData->nContinueTime = 0;
+ pProfData->nContinueStart = 0xFFFFFFFF;
+ pData->pProfList->Add( (void*)pProfData );
+ }
+
+ if ( pProfData->nStart == 0xFFFFFFFF )
+ {
+ pProfData->nStart = ImplGetPerfTime();
+ pProfData->nCount++;
+ }
+ break;
+
+ case DBG_PROF_STOP:
+ nTime = ImplGetPerfTime();
+
+ if ( pProfData->nStart == 0xFFFFFFFF )
+ {
+ DbgError( DbgError_ProfEnd1 );
+ return;
+ }
+
+ if ( pProfData->nContinueStart != 0xFFFFFFFF )
+ {
+ pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart;
+ pProfData->nContinueStart = 0xFFFFFFFF;
+ }
+
+ nTime -= pProfData->nStart;
+ nTime -= pProfData->nContinueTime;
+
+ if ( nTime < pProfData->nMinTime )
+ pProfData->nMinTime = nTime;
+
+ if ( nTime > pProfData->nMaxTime )
+ pProfData->nMaxTime = nTime;
+
+ pProfData->nTime += nTime;
+
+ pProfData->nStart = 0xFFFFFFFF;
+ pProfData->nContinueTime = 0;
+ pProfData->nContinueStart = 0xFFFFFFFF;
+ break;
+
+ case DBG_PROF_CONTINUE:
+ if ( pProfData->nContinueStart != 0xFFFFFFFF )
+ {
+ pProfData->nContinueTime += ImplGetPerfTime() - pProfData->nContinueStart;
+ pProfData->nContinueStart = 0xFFFFFFFF;
+ }
+ break;
+
+ case DBG_PROF_PAUSE:
+ if ( pProfData->nContinueStart == 0xFFFFFFFF )
+ pProfData->nContinueStart = ImplGetPerfTime();
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DbgXtor( DbgDataType* pDbgData, USHORT nAction, const void* pThis,
+ DbgUsr fDbgUsr )
+{
+ DebugData* pData = ImplGetDebugData();
+
+ // Verbindung zu Debug-Memory-Manager testen
+#ifdef SV_MEMMGR
+ if ( pData->aDbgData.nTestFlags & DBG_TEST_MEM_XTOR )
+ DbgImpCheckMemory();
+#endif
+
+ // Schnell-Test
+ if ( !(pData->aDbgData.nTestFlags & DBG_TEST_XTOR) )
+ return;
+
+ XtorType* pXtorData = (XtorType*)pDbgData->pData;
+ if ( !pXtorData )
+ {
+ pDbgData->pData = (void*)new XtorType;
+ pXtorData = (XtorType*)pDbgData->pData;
+ strncpy( pXtorData->aName, pDbgData->pName, DBG_MAXNAME );
+ pXtorData->aName[DBG_MAXNAME] = '\0';
+ pXtorData->nCtorCalls = 0;
+ pXtorData->nDtorCalls = 0;
+ pXtorData->nMaxCount = 0;
+ pXtorData->nStatics = 0;
+ pXtorData->bTest = TRUE;
+ pData->pXtorList->Add( (void*)pXtorData );
+
+ if ( !ImplDbgFilter( pData->aDbgData.aInclClassFilter, pXtorData->aName, TRUE ) )
+ pXtorData->bTest = FALSE;
+ if ( ImplDbgFilter( pData->aDbgData.aExclClassFilter, pXtorData->aName, FALSE ) )
+ pXtorData->bTest = FALSE;
+ }
+ if ( !pXtorData->bTest )
+ return;
+
+ USHORT nAct = nAction & ~DBG_XTOR_DTOROBJ;
+
+ // Trace (Enter)
+ if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE) &&
+ !(nAction & DBG_XTOR_DTOROBJ) )
+ {
+ if ( nAct != DBG_XTOR_CHKOBJ )
+ {
+ if ( nAct == DBG_XTOR_CTOR )
+ strcpy( aBuf, DbgTrace_EnterCtor );
+ else if ( nAct == DBG_XTOR_DTOR )
+ strcpy( aBuf, DbgTrace_EnterDtor );
+ else
+ strcpy( aBuf, DbgTrace_EnterMeth );
+ strcat( aBuf, pDbgData->pName );
+ DbgTrace( aBuf );
+ }
+ }
+
+ // Sind noch Xtor-Tests als Trace an
+ if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXTRA )
+ {
+ // DBG_CTOR-Aufruf vor allen anderen DBG_XTOR-Aufrufen
+ if ( ((nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR) && !pDbgData->pData )
+ {
+ strcpy( aBuf, DbgError_Xtor1 );
+ strcat( aBuf, pDbgData->pName );
+ DbgError( aBuf );
+ return;
+ }
+
+ // Testen, ob This-Pointer gueltig
+ if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
+ {
+ if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) ||
+ !(nAction & DBG_XTOR_DTOROBJ) )
+ {
+ // This-Pointer == NULL
+ if ( !pThis )
+ {
+ strcpy( aBuf, DbgError_CtorDtor1 );
+ strcat( aBuf, pDbgData->pName );
+ DbgError( aBuf );
+ return;
+ }
+
+ if ( (nAction & ~DBG_XTOR_DTOROBJ) != DBG_XTOR_CTOR )
+ {
+ if ( !pXtorData->aThisList.IsIn( pThis ) )
+ {
+ sprintf( aBuf, DbgError_CtorDtor2, pThis );
+ strcat( aBuf, pDbgData->pName );
+ DbgError( aBuf );
+ }
+ }
+ }
+ }
+
+ // Function-Test durchfuehren und Verwaltungsdaten updaten
+ const sal_Char* pMsg = NULL;
+ switch ( nAction & ~DBG_XTOR_DTOROBJ )
+ {
+ case DBG_XTOR_CTOR:
+ if ( nAction & DBG_XTOR_DTOROBJ )
+ {
+ if ( fDbgUsr &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
+ pMsg = fDbgUsr( pThis );
+ }
+ else
+ {
+ pXtorData->nCtorCalls++;
+ if ( !bDbgImplInMain )
+ pXtorData->nStatics++;
+ if ( (pXtorData->nCtorCalls-pXtorData->nDtorCalls) > pXtorData->nMaxCount )
+ pXtorData->nMaxCount = pXtorData->nCtorCalls - pXtorData->nDtorCalls;
+
+ if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
+ pXtorData->aThisList.Add( pThis );
+ }
+ break;
+
+ case DBG_XTOR_DTOR:
+ if ( nAction & DBG_XTOR_DTOROBJ )
+ {
+ pXtorData->nDtorCalls++;
+ if ( pData->aDbgData.nTestFlags & DBG_TEST_XTOR_THIS )
+ pXtorData->aThisList.Remove( pThis );
+ }
+ else
+ {
+ if ( fDbgUsr &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
+ pMsg = fDbgUsr( pThis );
+ }
+ break;
+
+ case DBG_XTOR_CHKTHIS:
+ case DBG_XTOR_CHKOBJ:
+ if ( nAction & DBG_XTOR_DTOROBJ )
+ {
+ if ( fDbgUsr &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_EXIT) &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
+ pMsg = fDbgUsr( pThis );
+ }
+ else
+ {
+ if ( fDbgUsr &&
+ (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_FUNC) )
+ pMsg = fDbgUsr( pThis );
+ }
+ break;
+ }
+
+ // Gegebenenfalls Fehlermeldung ausgeben
+ if ( pMsg )
+ {
+ sprintf( aBuf, DbgError_CtorDtor3, pThis );
+ strcat( aBuf, pDbgData->pName );
+ strcat( aBuf, ": \n" );
+ strcat( aBuf, pMsg );
+ DbgError( aBuf );
+ }
+ }
+
+ // Trace (Leave)
+ if ( (pData->aDbgData.nTestFlags & DBG_TEST_XTOR_TRACE) &&
+ (nAction & DBG_XTOR_DTOROBJ) )
+ {
+ if ( nAct != DBG_XTOR_CHKOBJ )
+ {
+ if ( nAct == DBG_XTOR_CTOR )
+ strcpy( aBuf, DbgTrace_LeaveCtor );
+ else if ( nAct == DBG_XTOR_DTOR )
+ strcpy( aBuf, DbgTrace_LeaveDtor );
+ else
+ strcpy( aBuf, DbgTrace_LeaveMeth );
+ strcat( aBuf, pDbgData->pName );
+ DbgTrace( aBuf );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DbgOut( const sal_Char* pMsg, USHORT nDbgOut, const sal_Char* pFile, USHORT nLine )
+{
+ static BOOL bIn = FALSE;
+ DebugData* pData = GetDebugData();
+ sal_Char* pStr;
+ ULONG nOut;
+ int nBufLen = 0;
+
+ if ( bIn )
+ return;
+ bIn = TRUE;
+
+ if ( nDbgOut == DBG_OUT_ERROR )
+ {
+ nOut = pData->aDbgData.nErrorOut;
+ pStr = "Error: ";
+ if ( pData->aDbgData.nErrorOut == DBG_OUT_FILE )
+ DbgDebugBeep();
+ }
+ else if ( nDbgOut == DBG_OUT_WARNING )
+ {
+ nOut = pData->aDbgData.nWarningOut;
+ pStr = "Warning: ";
+ }
+ else
+ {
+ nOut = pData->aDbgData.nTraceOut;
+ pStr = NULL;
+ }
+
+ if ( nOut == DBG_OUT_NULL )
+ {
+ bIn = FALSE;
+ return;
+ }
+
+ if ( (nDbgOut != DBG_OUT_ERROR) || DbgImplIsAllErrorOut() )
+ {
+ if ( !ImplDbgFilter( pData->aDbgData.aInclFilter, pMsg, TRUE ) )
+ {
+ bIn = FALSE;
+ return;
+ }
+ if ( ImplDbgFilter( pData->aDbgData.aExclFilter, pMsg, FALSE ) )
+ {
+ bIn = FALSE;
+ return;
+ }
+ }
+
+ ImplDbgLock();
+
+ if ( pStr )
+ {
+ strcpy( aBufOut, pStr );
+ nBufLen = strlen( pStr );
+ }
+ else
+ aBufOut[0] = '\0';
+
+ int nMsgLen = strlen( pMsg );
+ if ( nBufLen+nMsgLen > DBG_BUF_MAXLEN )
+ {
+ int nCopyLen = DBG_BUF_MAXLEN-nBufLen-3;
+ strncpy( &(aBufOut[nBufLen]), pMsg, nCopyLen );
+ strcpy( &(aBufOut[nBufLen+nCopyLen]), "..." );
+ }
+ else
+ strcpy( &(aBufOut[nBufLen]), pMsg );
+
+ if ( pFile && nLine && (nBufLen+nMsgLen < DBG_BUF_MAXLEN) )
+ {
+ if ( nOut == DBG_OUT_MSGBOX )
+ strcat( aBufOut, "\n" );
+ else
+ strcat( aBufOut, " " );
+ strcat( aBufOut, "From File " );
+ strcat( aBufOut, pFile );
+ strcat( aBufOut, " at Line " );
+
+ // Line in String umwandeln und dranhaengen
+ sal_Char aLine[9];
+ sal_Char* pLine = &aLine[7];
+ USHORT i;
+ memset( aLine, 0, sizeof( aLine ) );
+ do
+ {
+ i = nLine % 10;
+ pLine--;
+ *(pLine) = (sal_Char)i + 48;
+ nLine /= 10;
+ }
+ while ( nLine );
+ strcat( aBufOut, pLine );
+ }
+
+ if ( nOut == DBG_OUT_COREDUMP )
+ {
+ if ( !ImplCoreDump( aBufOut ) )
+ nOut = DBG_OUT_DEBUGGER;
+ }
+
+ if ( nOut == DBG_OUT_DEBUGGER )
+ {
+ if ( !ImplActivateDebugger( aBufOut ) )
+ nOut = DBG_OUT_TESTTOOL;
+ }
+
+ if ( nOut == DBG_OUT_TESTTOOL )
+ {
+ if ( pData->pDbgPrintTestTool )
+ pData->pDbgPrintTestTool( aBufOut );
+ else
+ nOut = DBG_OUT_MSGBOX;
+ }
+
+ if ( nOut == DBG_OUT_MSGBOX )
+ {
+ if ( pData->pDbgPrintMsgBox )
+ pData->pDbgPrintMsgBox( aBufOut );
+ else
+ nOut = DBG_OUT_SHELL;
+ }
+
+ if ( nOut == DBG_OUT_SHELL )
+ {
+ if ( pData->pDbgPrintShell )
+ pData->pDbgPrintShell( aBufOut );
+ else
+ nOut = DBG_OUT_WINDOW;
+ }
+
+ if ( nOut == DBG_OUT_WINDOW )
+ {
+ if ( pData->pDbgPrintWindow )
+ pData->pDbgPrintWindow( aBufOut );
+ else
+ nOut = DBG_OUT_FILE;
+ }
+
+ if ( nOut == DBG_OUT_FILE )
+ ImplDbgPrintFile( aBufOut );
+
+ ImplDbgUnlock();
+
+ bIn = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgOutTypef( USHORT nDbgOut, const sal_Char* pFStr, ... )
+{
+ va_list pList;
+
+ va_start( pList, pFStr );
+ vsprintf( aBuf, pFStr, pList );
+ va_end( pList );
+
+ DbgOut( aBuf, nDbgOut );
+}
+
+// -----------------------------------------------------------------------
+
+void DbgOutf( const sal_Char* pFStr, ... )
+{
+ va_list pList;
+
+ va_start( pList, pFStr );
+ vsprintf( aBuf, pFStr, pList );
+ va_end( pList );
+
+ DbgOut( aBuf );
+}
+
+// =======================================================================
+
+#else
+
+void* DbgFunc( USHORT, void* ) { return NULL; }
+
+void DbgProf( USHORT, DbgDataType* ) {}
+void DbgXtor( DbgDataType*, USHORT, const void*, DbgUsr ) {}
+
+void DbgOut( const sal_Char*, USHORT, const sal_Char*, USHORT ) {}
+void DbgOutTypef( USHORT, const sal_Char*, ... ) {}
+void DbgOutf( const sal_Char*, ... ) {}
+
+#endif
diff --git a/tools/source/debug/makefile.mk b/tools/source/debug/makefile.mk
new file mode 100644
index 000000000000..c21005fd0331
--- /dev/null
+++ b/tools/source/debug/makefile.mk
@@ -0,0 +1,89 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=debug
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES= debug.cxx \
+ stcktree.cxx
+
+SLOFILES= $(SLO)$/debug.obj \
+ $(SLO)$/stcktree.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/debug.obj \
+ $(OBJ)$/stcktree.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/debug/stcktree.cxx b/tools/source/debug/stcktree.cxx
new file mode 100644
index 000000000000..3e58510312df
--- /dev/null
+++ b/tools/source/debug/stcktree.cxx
@@ -0,0 +1,351 @@
+/*************************************************************************
+ *
+ * $RCSfile: stcktree.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#include <debug.hxx>
+
+// -----------------------------------------------------------------------
+
+#if defined( DBG_UTIL ) && defined( WNT ) && defined( INTEL )
+
+struct ImpDbgStackTree
+{
+ ImpDbgStackTree* pLeft_;
+ ImpDbgStackTree* pRight_;
+ ImpDbgStackTree* pCaller_;
+ ImpDbgStackTree* pSub_;
+ ULONG nIP_;
+ ULONG nBytesLeak_;
+ ULONG nBytesPeak_;
+ ULONG nBytes_;
+ ULONG nCountLeak_;
+ ULONG nCountPeak_;
+ ULONG nCount_;
+ ULONG nMax_;
+ ULONG nMin_;
+
+ ImpDbgStackTree( ImpDbgStackTree* pSub, ULONG nIP );
+ ~ImpDbgStackTree();
+
+ ImpDbgStackTree* Add( ULONG nAlloc, ULONG* pBP, ULONG nIP );
+ void Print( int nLevel, ULONG nCount, ULONG nCountLeak );
+ void Print( int nLevel );
+};
+
+static ImpDbgStackTree* pImpDbgStackTreeRoot = NULL;
+static ULONG* pImpDbgStackTreeBP = NULL;
+static ULONG nImpDbgStackTreeMain = 0;
+static int nImpDbgStackTreeSem = 0;
+
+// -----------------------------------------------------------------------
+
+ImpDbgStackTree::ImpDbgStackTree( ImpDbgStackTree* pSub, ULONG nIP )
+{
+ pSub_ = pSub;
+ nIP_ = nIP;
+ pLeft_ = pRight_ = pCaller_ = NULL;
+ nBytesLeak_ = nBytesPeak_ = nBytes_ = 0;
+ nCountLeak_ = nCountPeak_ = nCount_ = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImpDbgStackTree::~ImpDbgStackTree()
+{
+ if ( pLeft_ )
+ delete pLeft_;
+ if ( pRight_ )
+ delete pRight_;
+ if ( pCaller_ )
+ delete pCaller_;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpDbgStackTree::Print( int nLevel, ULONG nCount, ULONG nCountLeak )
+{
+ if ( pLeft_ )
+ pLeft_->Print( nLevel, nCount, nCountLeak );
+
+ if ( nCount_ >= nCount && nCountLeak_ >= nCountLeak )
+ {
+ if ( nMax_ == nMin_ )
+ {
+ ULONG nTemp = nCountLeak_ * nMin_;
+ DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu",
+ nLevel, ' ', nIP_,
+ nCount_, nCountPeak_, nCountLeak_,
+ nBytes_, nBytesPeak_, nTemp,
+ nMin_ );
+ }
+ else
+ {
+ DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu-%lu",
+ nLevel, ' ', nIP_,
+ nCount_, nCountPeak_, nCountLeak_,
+ nBytes_, nBytesPeak_, nBytesLeak_,
+ nMin_, nMax_ );
+ }
+
+ if ( pCaller_ )
+ if( nLevel > 3 && nCountLeak )
+ pCaller_->Print( nLevel + 1, nCount, 1 );
+ else
+ pCaller_->Print( nLevel + 1, nCount, nCountLeak );
+ }
+
+ if ( pRight_ )
+ pRight_->Print( nLevel, nCount, nCountLeak );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpDbgStackTree::Print( int nLevel )
+{
+ if ( pSub_ )
+ pSub_->Print( nLevel + 1 );
+ DbgOutf( "%*c%08lx", nLevel, ' ',nIP_ );
+}
+
+// -----------------------------------------------------------------------
+
+ImpDbgStackTree* ImpDbgStackTree::Add( ULONG nAlloc, ULONG *pBP, ULONG nIP )
+{
+ if ( nIP < nIP_ )
+ {
+ if ( !pLeft_ )
+ pLeft_ = new ImpDbgStackTree( pSub_, nIP );
+ return pLeft_->Add( nAlloc, pBP, nIP );
+ }
+ if ( nIP > nIP_ )
+ {
+ if ( !pRight_ )
+ pRight_ = new ImpDbgStackTree( pSub_, nIP );
+ return pRight_->Add( nAlloc, pBP, nIP );
+ }
+
+ nCount_++;
+ nCountLeak_++;
+ if ( nCountLeak_ > nCountPeak_ )
+ nCountPeak_ = nCountLeak_;
+ nBytes_ += nAlloc;
+ nBytesLeak_ += nAlloc;
+ if ( nBytesLeak_ > nBytesPeak_ )
+ nBytesPeak_ = nBytesLeak_;
+ if ( nCount_ == 1 )
+ nMax_ = nMin_ = nAlloc;
+ else if ( nMax_ < nAlloc )
+ nMax_ = nAlloc;
+ else if ( nMin_ > nAlloc )
+ nMin_ = nAlloc;
+
+ if ( !(pBP[0] & 3) && (ULONG)pBP < pBP[0] && pBP[0] < (ULONG)pImpDbgStackTreeBP )
+ {
+ pBP = (ULONG*)pBP[0];
+ nIP = pBP[1];
+ if ( 0x01100000 <= nIP && nIP < 0x20000000 && nIP != nImpDbgStackTreeMain )
+ {
+ if ( !pCaller_ )
+ pCaller_ = new ImpDbgStackTree( this, nIP );
+ return pCaller_->Add( nAlloc, pBP, nIP );
+ }
+ else
+ return this;
+ }
+
+ return this;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgStartStackTree()
+{
+ if ( !nImpDbgStackTreeMain )
+ {
+ ULONG* pBP;
+ __asm mov pBP, ebp;
+
+ pImpDbgStackTreeBP = (ULONG*)pBP[0];
+ nImpDbgStackTreeMain = pImpDbgStackTreeBP[1];
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DbgEndStackTree()
+{
+ if ( nImpDbgStackTreeMain )
+ {
+ nImpDbgStackTreeMain = 0;
+ if ( pImpDbgStackTreeRoot )
+ {
+ // Ausgaben ins File umleiten
+ DbgData* pData = DbgGetData();
+ ULONG nOldOut = pData->nTraceOut;
+ pData->nTraceOut = DBG_OUT_FILE;
+
+ DbgOutf( "Leak-Report" );
+ DbgOutf( "===========" );
+ DbgOutf( "Mem-StackTree:" );
+ DbgOutf( "{" );
+ pImpDbgStackTreeRoot->Print( 1, 1, 2 );
+ DbgOutf( "}" );
+
+ DbgOutf( "Alloc-Report" );
+ DbgOutf( "===========" );
+ DbgOutf( "Mem-StackTree:" );
+ DbgOutf( "{" );
+ pImpDbgStackTreeRoot->Print( 1, 1000, 0 ); // ???
+ DbgOutf( "}" );
+
+ pData->nTraceOut = nOldOut;
+
+ nImpDbgStackTreeSem++;
+ delete pImpDbgStackTreeRoot;
+ pImpDbgStackTreeRoot = NULL;
+ nImpDbgStackTreeSem--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* DbgGetStackTree( ULONG nAlloc )
+{
+ ImpDbgStackTree* pReturn = NULL;
+
+ if ( nImpDbgStackTreeMain && !nImpDbgStackTreeSem )
+ {
+ nImpDbgStackTreeSem++;
+
+ ULONG* pBP;
+ __asm mov pBP, ebp;
+
+ ULONG nIP = pBP[1];
+ if ( !pImpDbgStackTreeRoot )
+ pImpDbgStackTreeRoot = new ImpDbgStackTree( NULL, nIP );
+ pReturn = pImpDbgStackTreeRoot->Add( nAlloc, pBP, nIP );
+ nImpDbgStackTreeSem--;
+ }
+
+ return pReturn;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgFreeStackTree( void* pVoid, ULONG nAlloc )
+{
+ ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid;
+
+ if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem )
+ {
+ if ( nAlloc < p->nMin_ )
+ nAlloc = p->nMin_;
+
+ p->nCountLeak_--;
+ p->nBytesLeak_ -= nAlloc;
+
+ if ( p->nMax_ && 0xFFFFFFFF / p->nMax_ > p->nCountLeak_ )
+ {
+ if ( p->nBytesLeak_ > p->nMax_ * p->nCountLeak_ )
+ {
+ nAlloc += p->nBytesLeak_ - p->nMax_ * p->nCountLeak_;
+ p->nBytesLeak_ = p->nMax_ * p->nCountLeak_;
+ }
+ }
+
+ if ( p->pSub_ )
+ DbgFreeStackTree( (void*)(p->pSub_), nAlloc );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DbgPrintStackTree( void* pVoid )
+{
+ ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid;
+
+ if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem )
+ {
+ // Ausgaben ins File umleiten
+ DbgData* pData = DbgGetData();
+ ULONG nOldOut = pData->nTraceOut;
+ pData->nTraceOut = DBG_OUT_FILE;
+
+ DbgOutf( "Mem-StackTree:" );
+ DbgOutf( "{" );
+ p->Print( 1 );
+ DbgOutf( "}" );
+
+ pData->nTraceOut = nOldOut;
+ }
+}
+
+#else
+
+void DbgStartStackTree() {}
+void DbgEndStackTree() {}
+void* DbgGetStackTree( ULONG ) { return NULL; }
+void DbgFreeStackTree( void*, ULONG nAlloc ) {}
+void DbgPrintStackTree( void* ) {}
+
+#endif
diff --git a/tools/source/fsys/comdep.cxx b/tools/source/fsys/comdep.cxx
new file mode 100644
index 000000000000..4bd8d1cc359a
--- /dev/null
+++ b/tools/source/fsys/comdep.cxx
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * $RCSfile: comdep.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef MAC
+#define private public
+#define protected public
+#endif
+
+#include "comdep.hxx"
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _LIST_HXX
+#include <list.hxx>
+#endif
+#ifndef _FSYS_HXX
+#include <fsys.hxx>
+#endif
+
+DBG_NAMEEX( DirEntry );
+
+//--------------------------------------------------------------------
+
+#if defined( DOS ) || defined( WIN )
+
+#ifdef MSC
+#include "dosmsc.cxx"
+#endif
+
+#if defined( BLC ) || defined( TCPP )
+#include "dosblc.cxx"
+#endif
+
+#ifdef ZTC
+#include "dosztc.cxx"
+#endif
+
+#else
+
+#if defined( WNT ) && !defined( WTC )
+#include "wntmsc.cxx"
+#endif
+
+#ifdef UNX
+#include "unx.cxx"
+#endif
+
+#ifdef PM2
+#include "os2.cxx"
+#endif
+
+#ifdef MAC
+#include "mac.cxx"
+#endif
+
+#endif
+
diff --git a/tools/source/fsys/comdep.hxx b/tools/source/fsys/comdep.hxx
new file mode 100644
index 000000000000..702548429714
--- /dev/null
+++ b/tools/source/fsys/comdep.hxx
@@ -0,0 +1,224 @@
+/*************************************************************************
+ *
+ * $RCSfile: comdep.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _COMDEP_HXX
+#define _COMDEP_HXX
+
+#include "fsys.hxx"
+
+#define ACCESSDELIM(e) ( (e == FSYS_STYLE_MAC) ? ":" : \
+ ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
+ e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
+ ? "\\" : "/" )
+#define ACCESSDELIM_C(e)(char)\
+ ( (e == FSYS_STYLE_MAC) ? ':' : \
+ ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
+ e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
+ ? '\\' : '/' )
+#define SEARCHDELIM(e) ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ":" \
+ : ";" )
+#define SEARCHDELIM_C(e)(char)\
+ ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ':' \
+ : ';' )
+#define ACTPARENT(e) ( (e == FSYS_STYLE_MAC) ? ":" : ".." )
+#define ACTCURRENT(e) ( (e == FSYS_STYLE_MAC) ? "" : "." )
+
+#if defined(DOS) || defined(WIN)
+
+#ifdef MSC
+#include "dosmsc.hxx"
+#endif
+
+#if defined(TCPP) || defined(BLC)
+#include "dosblc.hxx"
+#endif
+
+#ifdef ZTC
+#include "dosztc.hxx"
+#endif
+
+#else
+
+#if defined( WNT ) && !defined( WTC )
+#include "wntmsc.hxx"
+#endif
+
+#ifdef UNX
+#include "unx.hxx"
+#endif
+
+#if defined(PM2) || defined(PM2)
+#include "os2.hxx"
+#endif
+
+#ifdef MAC
+#include "mac.hxx"
+#endif
+
+#endif
+
+//--------------------------------------------------------------------
+
+#ifndef LINUX
+DIR *opendir( const char* pPfad );
+dirent *readdir( DIR *pDir );
+int closedir( DIR *pDir );
+char *volumeid( const char* pPfad );
+#endif
+
+//--------------------------------------------------------------------
+
+struct DirReader_Impl
+{
+ Dir* pDir;
+#ifdef MAC
+ union
+ {
+ DIR* pDosDir;
+ dirent* pDosEntry;
+ };
+#else
+ DIR* pDosDir;
+ dirent* pDosEntry;
+#endif
+ DirEntry* pParent;
+ String aPath;
+ ByteString aBypass;
+ BOOL bReady;
+ BOOL bInUse;
+
+ DirReader_Impl( Dir &rDir )
+ : pDir( &rDir ),
+ aPath( GUI2FSYS(rDir.GetFull()) ),
+ pDosEntry( 0 ),
+ pParent( 0 ),
+ bReady ( FALSE ),
+ bInUse( FALSE )
+ {
+#ifndef BOOTSTRAP
+ // Redirection
+ FSysRedirector::DoRedirect( aPath );
+#endif
+
+ // nur den String der Memer-Var nehmen!
+
+#ifdef UNX //for further exlpanation see DirReader_Impl::Read() in unx.cxx
+ pDosDir = NULL;
+#else
+ aBypass = ByteString(aPath, osl_getThreadTextEncoding());
+ pDosDir = opendir( (char*) aBypass.GetBuffer() );
+#endif
+
+ // Parent f"ur die neuen DirEntries ermitteln
+ pParent = pDir->GetFlag() == FSYS_FLAG_NORMAL ||
+ pDir->GetFlag() == FSYS_FLAG_ABSROOT
+ ? pDir
+ : pDir->GetParent();
+
+ }
+
+ ~DirReader_Impl()
+ { if( pDosDir ) closedir( pDosDir ); }
+
+ // die folgenden sind systemabh"angig implementiert
+ USHORT Init(); // initialisiert, liest ggf. devices
+ USHORT Read(); // liest 1 Eintrag, F2ugt ein falls ok
+};
+
+//--------------------------------------------------------------------
+
+struct FileCopier_Impl
+{
+ FSysAction nActions; // was zu tun ist (Copy/Move/recur)
+ Link aErrorLink; // bei Fehlern zu rufen
+ ErrCode eErr; // aktueller Fehlercode im Error-Handler
+ const DirEntry* pErrSource; // fuer Error-Handler falls Source-Fehler
+ const DirEntry* pErrTarget; // fuer Error-Handler falls Target-Fehler
+
+ FileCopier_Impl()
+ : nActions( 0 ), eErr( 0 ),
+ pErrSource( 0 ), pErrTarget( 0 )
+ {}
+ FileCopier_Impl( const FileCopier_Impl &rOrig )
+ : nActions( rOrig.nActions ), eErr( 0 ),
+ pErrSource( 0 ), pErrTarget( 0 )
+ {}
+
+ FileCopier_Impl& operator=( const FileCopier_Impl &rOrig )
+ {
+ nActions = rOrig.nActions;
+ eErr = 0; pErrSource = 0; pErrTarget = 0;
+ return *this;
+ }
+};
+
+//--------------------------------------------------------------------
+
+#if defined(WNT) || defined(OS2)
+BOOL IsRedirectable_Impl( const ByteString &rPath );
+#else
+#define IsRedirectable_Impl( rPath ) TRUE
+#endif
+
+//--------------------------------------------------------------------
+
+
+#endif
diff --git a/tools/source/fsys/dirent.cxx b/tools/source/fsys/dirent.cxx
new file mode 100644
index 000000000000..996be942639e
--- /dev/null
+++ b/tools/source/fsys/dirent.cxx
@@ -0,0 +1,3521 @@
+/*************************************************************************
+ *
+ * $RCSfile: dirent.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#if !defined( MAC ) && !defined( UNX )
+#include <io.h>
+#endif
+
+#if defined UNX
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined (WIN) || defined (MAC)
+#include <time.h>
+#endif
+
+#ifdef PM2
+#include <os2.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _LIST_HXX
+#include <list.hxx>
+#endif
+
+#ifndef _COMDEP_HXX
+#include "comdep.hxx"
+#endif
+#ifndef _FSYS_HXX
+#include "fsys.hxx"
+#endif
+#define _TOOLS_HXX
+#ifndef _URLOBJ_HXX
+#include <urlobj.hxx>
+#endif
+
+#ifdef UNX
+#define _MAX_PATH 260
+#endif
+
+#ifdef MAC_UNIVERSAL
+#ifndef _UNISTD
+#include <unistd.h>
+#endif
+#endif
+#ifdef MAC
+#ifndef __ERRORS__
+#include "Errors.h"
+#endif
+#endif
+
+#ifndef _STREAM_HXX
+#include <stream.hxx>
+#endif
+
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+
+#include <osl/file.hxx>
+using namespace osl;
+using namespace rtl;
+
+int ApiRet2ToSolarError_Impl( int nApiRet );
+
+//--------------------------------------------------------------------
+int Sys2SolarError_Impl( int nSysErr )
+{
+ switch ( nSysErr )
+ {
+#ifdef WNT
+ case NO_ERROR: return ERRCODE_NONE;
+ case ERROR_INVALID_FUNCTION: return ERRCODE_IO_GENERAL;
+ case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_INVALID_HANDLE: return ERRCODE_IO_GENERAL;
+ case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
+ case ERROR_INVALID_BLOCK: return ERRCODE_IO_GENERAL;
+// case ERROR_BAD_ENVIRONMENT: return ERRCODE_IO_;
+ case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_INVALID_ACCESS: return ERRCODE_IO_ACCESSDENIED;
+// case ERROR_INVALID_DATA: return ERRCODE_IO_;
+ case ERROR_INVALID_DRIVE: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_CURRENTDIR;
+ case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_NOTSAMEDEVICE;
+// case ERROR_NO_MORE_FILES: return ERRCODE_IO_;
+ case ERROR_WRITE_PROTECT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_READY: return ERRCODE_IO_DEVICENOTREADY;
+ case ERROR_BAD_COMMAND: return ERRCODE_IO_GENERAL;
+ case ERROR_CRC: return ERRCODE_IO_BADCRC;
+ case ERROR_BAD_LENGTH: return ERRCODE_IO_INVALIDLENGTH;
+ case ERROR_SEEK: return ERRCODE_IO_CANTSEEK;
+ case ERROR_NOT_DOS_DISK: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_SECTOR_NOT_FOUND: return ERRCODE_IO_GENERAL;
+ case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
+ case ERROR_GEN_FAILURE: return ERRCODE_IO_GENERAL;
+ case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_WRONG_DISK: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
+#else
+ case 0: return ERRCODE_NONE;
+ case ENOENT: return ERRCODE_IO_NOTEXISTS;
+ case EACCES: return ERRCODE_IO_ACCESSDENIED;
+ case EEXIST: return ERRCODE_IO_ALREADYEXISTS;
+ case EINVAL: return ERRCODE_IO_INVALIDPARAMETER;
+ case EMFILE: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ENOMEM: return ERRCODE_IO_OUTOFMEMORY;
+ case ENOSPC: return ERRCODE_IO_OUTOFSPACE;
+#endif
+ }
+
+ DBG_TRACE1( "FSys: unknown system error %d occured", nSysErr );
+ return FSYS_ERR_UNKNOWN;
+}
+
+//--------------------------------------------------------------------
+
+#ifndef BOOTSTRAP
+
+#if SUPD>=380
+FSysRedirector* FSysRedirector::_pRedirector = 0;
+BOOL FSysRedirector::_bEnabled = TRUE;
+#ifdef UNX
+BOOL bInRedirection = TRUE;
+#else
+BOOL bInRedirection = FALSE;
+#endif
+static NAMESPACE_VOS( OMutex )* pRedirectMutex = 0;
+
+//========================================================================
+
+FSysRedirector::~FSysRedirector()
+{
+}
+
+//------------------------------------------------------------------------
+void FSysRedirector::Register( FSysRedirector *pRedirector )
+{
+ if ( pRedirector )
+ pRedirectMutex = new NAMESPACE_VOS( OMutex );
+ else
+ DELETEZ( pRedirectMutex );
+ _pRedirector = pRedirector;
+}
+
+//------------------------------------------------------------------------
+
+BOOL FSysRedirector::DoRedirect( String &rPath )
+{
+ ByteString aURL(rPath, osl_getThreadTextEncoding());
+
+ // if redirection is disabled or not even registered do nothing
+ if ( !_bEnabled || !pRedirectMutex )
+ return FALSE;
+
+ // redirect only removable or remote volumes
+ if ( !IsRedirectable_Impl( aURL ) )
+ return FALSE;
+
+ // Redirection is acessible only by one thread per time
+ // dont move the guard behind the !bInRedirection return FALSE!!!
+ // think of nested calls (when called from callback)
+ NAMESPACE_VOS( OGuard ) aGuard( pRedirectMutex );
+
+ // if already in redirection, dont redirect
+ if ( bInRedirection )
+ return FALSE;
+
+ // dont redirect on nested calls
+ bInRedirection = TRUE;
+
+ // convert to URL
+#ifndef UNX
+ for ( char *p = (char *) aURL.GetBuffer(); *p; ++p )
+#ifndef MAC
+ if ( '\\' == *p ) *p = '/';
+ else if ( ':' == *p ) *p = '|';
+#else
+ if ( ':' == *p ) *p = '/';
+#endif
+#endif
+
+ aURL.Insert( "file:///", 0 );
+
+ // do redirection
+ Redirector();
+ BOOL bRedirected = Redirector()->Redirect( String(aURL, osl_getThreadTextEncoding()) );
+
+ // if redirected transform URL to file name
+ if ( bRedirected )
+ {
+ rPath = String(aURL.Copy( 8 ), osl_getThreadTextEncoding());
+ aURL = ByteString(rPath, osl_getThreadTextEncoding());
+#ifndef UNX
+ for ( char *p = (char *) aURL.GetBuffer(); *p; ++p )
+#ifndef MAC
+ if ( '/' == *p ) *p = '\\';
+ else if ( '|' == *p ) *p = ':';
+#else
+ if ( '/' == *p ) *p = ':';
+#endif
+#endif
+ }
+
+ bInRedirection = FALSE;
+ return bRedirected;
+}
+
+//------------------------------------------------------------------------
+
+void FSysRedirector::EnableRedirection( BOOL bEnable )
+{
+ if ( !bEnable && pRedirectMutex)
+ pRedirectMutex->acquire();
+ _bEnabled = bEnable;
+ if ( bEnable && pRedirectMutex)
+ pRedirectMutex->release();
+}
+
+//------------------------------------------------------------------------
+
+BOOL FSysRedirector::Redirect( String &rPath )
+{
+#ifdef DBG_MI
+ if ( rPath.Len() && rPath(1) == ':' &&
+ ( rPath(0) == 'b' || rPath(0) == 'B' ) )
+ {
+ rPath(0) = 'd';
+ rPath.Insert( "\\mi", 2 );
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+
+FSysRedirector* FSysRedirector::Redirector()
+{
+ if ( !_pRedirector )
+ Register( new FSysRedirector );
+ return _pRedirector;
+}
+#endif
+
+#endif // BOOTSTRAP
+
+//--------------------------------------------------------------------
+
+class DirEntryStack: public List
+{
+public:
+ DirEntryStack() {};
+ ~DirEntryStack();
+
+ inline void Push( DirEntry *pEntry );
+ inline DirEntry* Pop();
+ inline DirEntry* Top();
+ inline DirEntry* Bottom();
+};
+
+inline void DirEntryStack::Push( DirEntry *pEntry )
+{
+ List::Insert( pEntry, LIST_APPEND );
+}
+
+inline DirEntry* DirEntryStack::Pop()
+{
+ return (DirEntry*) List::Remove( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Top()
+{
+ return (DirEntry*) List::GetObject( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Bottom()
+{
+ return (DirEntry*) List::GetObject( 0 );
+}
+
+//--------------------------------------------------------------------
+
+DBG_NAME( DirEntry );
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntryStack()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 04.07.91
+|*
+*************************************************************************/
+
+DirEntryStack::~DirEntryStack()
+{
+ while ( Count() )
+ delete Pop();
+}
+
+/*************************************************************************
+|*
+|* ImpCheckDirEntry()
+|*
+|* Beschreibung Pruefung eines DirEntry fuer DBG_UTIL
+|* Parameter void* p Zeiger auf den DirEntry
+|* Return-Wert char* Fehlermeldungs-TExtension oder NULL
+|* Ersterstellung MI 16.07.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* ImpCheckDirEntry( const void* p )
+{
+ DirEntry* p0 = (DirEntry*)p;
+
+ if ( p0->pParent )
+ DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry );
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* ImplCutPath()
+|*
+|* Beschreibung Fuegt ... ein, damit maximal nMaxChars lang
+|* Ersterstellung MI 06.04.94
+|* Letzte Aenderung DV 24.06.96
+|*
+*************************************************************************/
+
+ByteString ImplCutPath( const ByteString& rStr, USHORT nMax, char cAccDel )
+{
+ USHORT nMaxPathLen = nMax;
+ ByteString aCutPath( rStr );
+ BOOL bInsertPrefix = FALSE;
+ USHORT nBegin = aCutPath.Search( cAccDel );
+
+ if( nBegin == STRING_NOTFOUND )
+ nBegin = 0;
+ else
+ nMaxPathLen += 2; // fuer Prefix <Laufwerk>:
+
+ while( aCutPath.Len() > nMaxPathLen )
+ {
+ USHORT nEnd = aCutPath.Search( cAccDel, nBegin + 1 );
+ USHORT nCount;
+
+ if ( nEnd != STRING_NOTFOUND )
+ {
+ nCount = nEnd - nBegin;
+ aCutPath.Erase( nBegin, nCount );
+ bInsertPrefix = TRUE;
+ }
+ else
+ break;
+ }
+
+ if ( aCutPath.Len() > nMaxPathLen )
+ {
+ for ( USHORT n = nMaxPathLen; n > nMaxPathLen/2; --n )
+ if ( !ByteString(aCutPath.GetChar(n)).IsAlphaNumericAscii() )
+ {
+ aCutPath.Erase( n );
+ aCutPath += "...";
+ break;
+ }
+ }
+
+ if ( bInsertPrefix )
+ {
+ ByteString aIns( cAccDel );
+ aIns += "...";
+ aCutPath.Insert( aIns, nBegin );
+ }
+
+ return aCutPath;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseOs2Name()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 23.06.95
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseOs2Name( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ ByteString aPfad( rPfad );
+ DirEntryStack aStack;
+
+ do
+ {
+ // den Namen vor dem ersten "\\" abspalten,
+ // falls '\\' am Anfang, ist der Name '\\',
+ // der Rest immer ohne die fuehrenden '\\'.
+ // ein ":" trennt ebenfalls, gehoert aber zum Namen
+ // den ersten '\\', '/' oder ':' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && //?O
+ aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' && //?O
+ aPfad.GetChar(nPos) != ':'; //?O
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name ein UNC Pathname?
+ if ( nPos == 0 && aPfad.Len() > 1 &&
+ ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) ||
+ ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) )
+ {
+ for ( nPos = 2; aPfad.Len() > nPos; ++nPos )
+ if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' )
+ break;
+ aName = aPfad.Copy( 2, nPos-2 );
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ // ist der Name die Root des aktuellen Drives?
+ else if ( nPos == 0 && aPfad.Len() > 0 &&
+ ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // ist der Name ein Drive?
+ if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' )
+ {
+ aName = aPfad.Copy( 0, nPos + 1 );
+
+ // ist der Name die Root des Drives
+ if ( (nPos + 1) < aPfad.Len() &&
+ ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) )
+ {
+ // schon was auf dem Stack?
+ // oder Novell-Format? (not supported wegen URLs)
+ if ( aStack.Count() || aName.Len() > 2 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ // Root-Directory des Drive
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ else
+ {
+ // liegt ein anderes Drive auf dem Stack?
+ if ( aStack.Count() &&
+ COMPARE_EQUAL != aStack.Bottom()->aName.CompareIgnoreCaseToAscii(aName) )
+ aStack.Clear();
+
+ // liegt jetzt nichts mehr auf dem Stack?
+ if ( !aStack.Count() )
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT, eStyle ) );
+ }
+ }
+
+ // es ist kein Drive
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = aPfad.Copy( 0, nPos );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ // die hat keine Parent-Directory
+ aName = rPfad;
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+
+ else
+ {
+ if ( eStyle == FSYS_STYLE_FAT )
+ {
+ // ist der Name grundsaetzlich ungueltig?
+ int nPunkte = 0;
+ const char *pChar;
+ for ( pChar = aName.GetBuffer();
+ nPunkte < 2 && *pChar != 0;
+ pChar++ )
+ {
+ if ( *pChar == ';' )
+ nPunkte = 0;
+ else
+ nPunkte += ( *pChar == '.' ) ? 1 : 0;
+ }
+ if ( nPunkte > 1 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ }
+
+ // normalen Entries kommen auf den Stack
+ DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ ULONG nErr = ERRCODE_NONE;
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ nErr = aStack.Top()->nError;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent; // Zeiger auf den Member pParent setzen
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+
+ // Zeiger auf den Member pParent des eigenen Parent setzen
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ // wird damit ein Volume beschrieben?
+ if ( !pParent && eFlag == FSYS_FLAG_RELROOT && aName.Len() )
+ eFlag = FSYS_FLAG_VOLUME;
+
+ // bei gesetztem ErrorCode den Namen komplett "ubernehmen
+ if ( nErr )
+ aName = rPfad;
+ return nErr;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.08.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseName( const ByteString& rInitName,
+ FSysPathStyle eStyle )
+{
+ if ( eStyle == FSYS_STYLE_HOST )
+ eStyle = DEFSTYLE;
+
+ // KI-Division of FSys
+ if ( eStyle == FSYS_STYLE_DETECT )
+ {
+ char cFirst = rInitName.Copy(0,1).ToLowerAscii().GetChar(0);
+ if ( rInitName.Len() == 2 && rInitName.GetChar(1) == ':' &&
+ cFirst >= 'a' &&
+ cFirst <= 'z' )
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Len() > 2 && rInitName.GetChar(1) == ':' )
+ {
+ if ( rInitName.Search( ':', 2 ) == STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else
+ eStyle = FSYS_STYLE_MAC;
+ }
+ else if ( rInitName.Search( '/' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_BSD;
+ else if ( rInitName.Search( '\\' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Search( ':' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_MAC;
+ else
+ eStyle = FSYS_STYLE_HPFS;
+ }
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ return ImpParseOs2Name( rInitName, eStyle );
+
+ case FSYS_STYLE_BSD:
+ case FSYS_STYLE_SYSV:
+ return ImpParseUnixName( rInitName, eStyle );
+
+ case FSYS_STYLE_MAC:
+ return ImpParseMacName( rInitName );
+
+ default:
+ return FSYS_ERR_UNKNOWN;
+ }
+}
+
+/*************************************************************************
+|*
+|* GetStyle()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 15.11.91
+|* Letzte Aenderung MI 15.11.91
+|*
+*************************************************************************/
+
+static FSysPathStyle GetStyle( FSysPathStyle eStyle )
+{
+ if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT )
+ return DEFSTYLE;
+ else
+ return eStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpTrim()
+|*
+|* Beschreibung bringt den Namen auf Betriebssystem-Norm
+|* z.B. 8.3 lower beim MS-DOS Formatter
+|* wirkt nicht rekursiv
+|* Ersterstellung MI 12.08.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+void DirEntry::ImpTrim( FSysPathStyle eStyle )
+{
+ // Wildcards werden nicht geclipt
+ if ( ( aName.Search( '*' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( '?' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( ';' ) != STRING_NOTFOUND ) )
+ return;
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ {
+ USHORT nPunktPos = aName.Search( '.' );
+ if ( nPunktPos == STRING_NOTFOUND )
+ {
+ if ( aName.Len() > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8 );
+ }
+ }
+ else
+ {
+ if ( nPunktPos > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8, nPunktPos - 8 );
+ nPunktPos = 8;
+ }
+ if ( aName.Len() > nPunktPos + 3 )
+ {
+ if ( aName.Len() - nPunktPos > 4 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( nPunktPos + 4 );
+ }
+ }
+ }
+ aName.ToLowerAscii();
+ break;
+ }
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ if ( aName.Len() > 254 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 254 );
+ }
+
+ if ( eStyle == FSYS_STYLE_HPFS &&
+ ( eFlag == FSYS_FLAG_ABSROOT || eFlag == FSYS_FLAG_RELROOT ) )
+ aName.ToUpperAscii();
+ break;
+
+ case FSYS_STYLE_SYSV:
+ if ( aName.Len() > 14 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 14 );
+ }
+ break;
+
+ case FSYS_STYLE_BSD:
+ if ( aName.Len() > 250 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 250 );
+ }
+ break;
+
+ case FSYS_STYLE_MAC:
+ if ( eFlag & ( FSYS_FLAG_ABSROOT | FSYS_FLAG_VOLUME ) )
+ {
+ if ( aName.Len() > 27 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 27 );
+ }
+ }
+ else
+ {
+ if ( aName.Len() > 31 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 31 );
+ }
+ }
+ break;
+
+ default:
+ /* kann nicht sein */;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rName, DirEntryFlag eDirFlag,
+ FSysPathStyle eStyle ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( 0 ),
+#endif
+ aName( rName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+ eFlag = eDirFlag;
+ nError = FSYS_ERR_OK;
+
+ ImpTrim( eStyle );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const DirEntry& rOrig ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ),
+#endif
+ aName( rOrig.aName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = rOrig.eFlag;
+ nError = rOrig.nError;
+
+ if ( rOrig.pParent )
+ {
+ pParent = new DirEntry( *rOrig.pParent );
+ }
+ else
+ {
+ pParent = NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len())
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName(rInitName, osl_getThreadTextEncoding());
+ if( eStyle == FSYS_STYLE_URL || aTmpName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(INetURLObject( rInitName ).PathToFileName(), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif // BOOTSTRAP
+ }
+ else
+ {
+ ::rtl::OUString aTmp;
+ ::rtl::OUString aOInitName;
+ if ( FileBase::normalizePath( OUString( rInitName ), aTmp ) == osl_File_E_None )
+ {
+ FileBase::getSystemPathFromNormalizedPath( aTmp, aOInitName );
+ aTmpName = ByteString( String(aOInitName), osl_getThreadTextEncoding() );
+ }
+
+#ifdef DBG_UTIL
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ aTmpName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += aTmpName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+ }
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len() )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName( rInitName );
+ if( eStyle == FSYS_STYLE_URL || rInitName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(INetURLObject( rInitName ).PathToFileName(), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif
+ }
+#ifdef DBG_UTIL
+ else
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ rInitName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += rInitName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( DirEntryFlag eDirFlag )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = eDirFlag;
+ nError = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK;
+ pParent = NULL;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::~DirEntry()
+{
+ DBG_DTOR( DirEntry, ImpCheckDirEntry );
+
+ delete pParent;
+#ifdef FEAT_FSYS_DOUBLESPEED
+ delete pStat;
+#endif
+
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr() const
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+const DirEntry* DirEntry::ImpGetTopPtr() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetPreTopPtr()
+|*
+|* Beschreibung liefert einen Pointer auf den vorletzten Entry
+|* Ersterstellung MI 01.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetPreTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ if ( pTemp->pParent )
+ {
+ while ( pTemp->pParent->pParent )
+ pTemp = pTemp->pParent;
+ }
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpChangeParent()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, BOOL bNormalize )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = pParent;
+ if ( bNormalize && pNewParent &&
+ pNewParent->eFlag == FSYS_FLAG_RELROOT && !pNewParent->aName.Len() )
+ {
+ pParent = 0;
+ delete pNewParent;
+ }
+ else
+ pParent = pNewParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Exists()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 24.09.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::Exists( FSysAccess nAccess ) const
+{
+#ifndef BOOTSTRAP
+ static NAMESPACE_VOS(OMutex) aLocalMutex;
+ NAMESPACE_VOS(OGuard) aGuard( aLocalMutex );
+#endif
+ if ( !IsValid() )
+ return FALSE;
+
+#if defined(DOS) || defined(WIN) || defined(WNT) || defined(OS2)
+ // spezielle Filenamen sind vom System da
+ if ( ( aName.CompareIgnoreCaseToAscii("CLOCK$") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("CON") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("AUX") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM4") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("NUL") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("PRN") == COMPARE_EQUAL ) )
+ return TRUE;
+#endif
+
+ FSysFailOnErrorImpl();
+ DirEntryKind eKind = FileStat( *this, nAccess ).GetKind();
+ if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) )
+ {
+ return TRUE;
+ }
+
+#if defined(WIN) || defined(DOS) || defined(OS2) || defined(WNT)
+ if ( 0 != ( eKind & FSYS_KIND_DEV ) )
+ {
+ return DRIVE_EXISTS( ImpGetTopPtr()->aName.GetChar(0) );
+ }
+#endif
+
+ return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::First()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 15.01.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::First()
+{
+ FSysFailOnErrorImpl();
+
+ String aUniPathName( GetPath().GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aUniPathName );
+ ByteString aPathName(aUniPathName, osl_getThreadTextEncoding());
+#else
+ ByteString aPathName(aUniPathName, gsl_getSystemTextEncoding());
+#endif
+ aPathName = GUI2FSYS( aPathName );
+
+ DIR *pDir = opendir( (char*) aPathName.GetBuffer() );
+ if ( pDir )
+ {
+#ifndef BOOTSTRAP
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), osl_getThreadTextEncoding()) );
+#else
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), gsl_getSystemTextEncoding()) );
+#endif
+ for ( dirent* pEntry = readdir( pDir );
+ pEntry;
+ pEntry = readdir( pDir ) )
+ {
+ ByteString aFound( FSYS2GUI( ByteString( pEntry->d_name ) ) );
+ if ( aWildeKarte.Matches( String(CMP_LOWER( aFound ), osl_getThreadTextEncoding())))
+ {
+ aName = aFound;
+ closedir( pDir );
+ return TRUE;
+ }
+ }
+ closedir( pDir );
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetFull()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetFull( FSysPathStyle eStyle, BOOL bWithDelimiter,
+ USHORT nMaxChars ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+ if ( pParent )
+ {
+ if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT ||
+ pParent->eFlag == FSYS_FLAG_RELROOT ||
+ pParent->eFlag == FSYS_FLAG_VOLUME ) )
+ {
+ aRet = ByteString(pParent->GetName( eStyle ), osl_getThreadTextEncoding());
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ else
+ {
+ aRet = ByteString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding());
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ }
+ else
+ {
+ aRet = ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+
+ if ( ( eStyle == FSYS_STYLE_MAC ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_VOLUME ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_ABSROOT ) &&
+ ( aRet.GetChar(0) != ':' ) )
+ aRet.Insert( ACCESSDELIM_C(eStyle), 0 );
+
+ //! Hack
+ if ( bWithDelimiter )
+ if ( aRet.GetChar( aRet.Len()-1 ) != ACCESSDELIM_C(eStyle) )
+ aRet += ACCESSDELIM_C(eStyle);
+
+ //! noch ein Hack
+ if ( nMaxChars < STRING_MAXLEN )
+ aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) );
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::GetPath() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( pParent )
+ return DirEntry( *pParent );
+
+ return DirEntry();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetExtension( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(aName.Copy( p1 - p0 + 1 ), osl_getThreadTextEncoding());
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetBase( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(aName.Copy( 0, p1 - p0 ), osl_getThreadTextEncoding());
+
+ else
+ // es wurde kein cSep gefunden
+ return String(aName, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:47
+|*
+*************************************************************************/
+
+String DirEntry::GetName( FSysPathStyle eStyle ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+
+ switch( eFlag )
+ {
+ case FSYS_FLAG_PARENT:
+ aRet = ACTPARENT(eStyle);
+ break;
+
+ case FSYS_FLAG_ABSROOT:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+
+#ifndef UNX
+ if ( aName.Len())
+ {
+ if ( aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+ else
+ {
+#ifndef MAC
+ aRet.Insert( '/', 5 );
+#endif
+ }
+ aRet += "/";
+ }
+#endif
+ }
+ else if ( eStyle != FSYS_STYLE_MAC &&
+ aName.Len() > 1 && aName.GetChar( 1 ) != ':' )
+ {
+ // UNC-Pathname
+ aRet = ACCESSDELIM_C(eStyle);
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += aName ;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ else
+ {
+ aRet = aName;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ break;
+ }
+
+ case FSYS_FLAG_INVALID:
+ case FSYS_FLAG_VOLUME:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+#ifndef UNX
+ if ( aName.Len() && aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+#endif
+ }
+ else
+ {
+ aRet = aName;
+ }
+
+ break;
+ }
+
+ case FSYS_FLAG_RELROOT:
+ if ( !aName.Len() )
+ {
+ aRet = ACTCURRENT(eStyle);
+ break;
+ }
+
+ default:
+ aRet = aName;
+ }
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsAbs() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+#ifdef UNX
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT );
+#else
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && aName.Len() > 0 );
+#endif
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::CutName( FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ eStyle = GetStyle( eStyle );
+
+ String aOldName( GetName( eStyle ) );
+
+ if ( pParent )
+ {
+ DirEntry *pOldParent = pParent;
+ if ( pOldParent )
+ {
+ pParent = pOldParent->pParent;
+ eFlag = pOldParent->eFlag;
+ aName = pOldParent->aName;
+ pOldParent->pParent = NULL;
+ delete pOldParent;
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ delete pParent;
+ pParent = NULL;
+ }
+
+ return aOldName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::NameCompare
+|*
+|* Beschreibung Vergleich nur die Namen (ohne Pfad, aber mit Gross/Klein)
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+StringCompare DirEntry::NameCompare( const DirEntry &rWith ) const
+{
+ ByteString aThisName;
+ ByteString aParameterName;
+
+#ifdef UNX
+ aThisName = aName;
+ aParameterName = rWith.aName;
+#else
+ aThisName = ByteString(aName).ToLowerAscii();
+ aParameterName = ByteString(rWith.aName).ToLowerAscii();
+#endif
+
+ return aThisName.CompareTo( aParameterName );
+}
+
+
+/*************************************************************************
+|*
+|* DirEntry::operator==()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::operator==( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // test wheather the contents are textual the same
+
+ if ( nError && ( nError == rEntry.nError ) )
+ return TRUE;
+ if ( nError || rEntry.nError ||
+ ( eFlag == FSYS_FLAG_INVALID ) ||
+ ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
+ return FALSE;
+
+ const DirEntry *pThis = this;
+ const DirEntry *pWith = &rEntry;
+ while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
+ {
+ if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
+ break;
+ pThis = pThis->pParent;
+ pWith = pWith->pParent;
+ }
+
+ return ( !pThis && !pWith );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry& DirEntry::operator=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( this == &rEntry )
+ return *this;
+ if ( rEntry.nError != FSYS_ERR_OK ) {
+ DBG_ERROR("Zuweisung mit invalidem DirEntry");
+ nError = rEntry.nError;
+ return *this;
+ }
+
+ // Name und Typ uebernehmen, Refs beibehalten
+ aName = rEntry.aName;
+ eFlag = rEntry.eFlag;
+ nError = FSYS_ERR_OK;
+
+ DirEntry *pOldParent = pParent;
+ if ( rEntry.pParent )
+ pParent = new DirEntry( *rEntry.pParent );
+ else
+ pParent = NULL;
+
+ if ( pOldParent )
+ delete pOldParent;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::operator+( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+#ifdef DBG_UTIL
+ static BOOL bTested = FALSE;
+ if ( !bTested )
+ {
+ bTested = TRUE;
+ FSysTest();
+ }
+#endif
+
+ const DirEntry *pEntryTop = rEntry.ImpGetTopPtr();
+ const DirEntry *pThisTop = ImpGetTopPtr();
+
+ // "." + irgendwas oder irgendwas + "d:irgendwas"
+/* TPF:org
+ if ( ( eFlag == FSYS_FLAG_RELROOT && !aName ) ||
+ ( pEntryTop->aName.Len() &&
+ ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME ) ) )
+ return rEntry;
+*/
+
+ if (
+ (eFlag == FSYS_FLAG_RELROOT && !aName.Len()) ||
+ (
+ (pEntryTop->aName.Len() ||
+ ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.CompareIgnoreCaseToAscii(RFS_IDENTIFIER)==COMPARE_EQUAL):FALSE))
+ &&
+ (pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME)
+ )
+ )
+ {
+ return rEntry;
+ }
+
+ // irgendwas + "." (=> pEntryTop == &rEntry)
+ if ( pEntryTop->eFlag == FSYS_FLAG_RELROOT && !pEntryTop->aName.Len() )
+ {
+ DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" );
+ return *this;
+ }
+
+ // root += ".." (=> unmoeglich)
+ if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this &&
+ ( eFlag == FSYS_FLAG_ABSROOT ) )
+ return DirEntry( FSYS_FLAG_INVALID );
+
+ // irgendwas += abs (=> nur Device uebernehmen falls vorhanden)
+ if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ ByteString aDevice;
+ if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT )
+ aDevice = pThisTop->aName;
+ DirEntry aRet = rEntry;
+ if ( aDevice.Len() )
+ aRet.ImpGetTopPtr()->aName = aDevice;
+ return aRet;
+ }
+
+ // irgendwas += ".." (=> aufloesen)
+ if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT )
+ {
+ String aConcated( GetFull() );
+ aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST);
+ aConcated += rEntry.GetFull();
+ return DirEntry( aConcated );
+ }
+
+ // sonst einfach hintereinander haengen
+ DirEntry aRet( rEntry );
+ DirEntry *pTop = aRet.ImpGetTopPtr();
+ pTop->pParent = new DirEntry( *this );
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry &DirEntry::operator+=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ return *this = *this + rEntry;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetAccessDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.05.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ACCESSDELIM_C( GetStyle( eFormatter ) ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 02.08.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetExtension( const String& rExtension, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // do not set extensions for drives
+ if(eFlag == FSYS_FLAG_ABSROOT)
+ {
+ nError = FSYS_ERR_NOTSUPPORTED;
+ return;
+ }
+
+ // cSep im Namen suchen
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 ) );
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+ else if ( rExtension.Len() )
+ {
+ // es wurde kein cSep gefunden
+ aName += cSep;
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.07.93
+|* Letzte Aenderung MI 23.07.93
+|*
+*************************************************************************/
+
+String DirEntry::CutExtension( char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( p1-p0 );
+ return String(p1 + 1, osl_getThreadTextEncoding());
+ }
+
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.09.93
+|* Letzte Aenderung MI 04.09.93
+|*
+*************************************************************************/
+
+void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT )
+ eFormatter = DEFSTYLE;
+ ByteString aAccDelim( ACCESSDELIM_C( eFormatter ) );
+
+ if ( (eFlag != FSYS_FLAG_NORMAL) ||
+ (aName.Search( ':' ) != STRING_NOTFOUND) ||
+ (aName.Search( aAccDelim ) != STRING_NOTFOUND) ||
+ (eFormatter == FSYS_STYLE_FAT && (aName.GetTokenCount( '.' ) > 2) ) )
+ {
+ eFlag = FSYS_FLAG_INVALID;
+ }
+ else
+ {
+ aName = ByteString(rName, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Find()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+#if SUPD<=381
+BOOL DirEntry::Find( const String& rPfad )
+{
+ return Find( rPfad, SEARCHDELIM(DEFSTYLE)[0] );
+}
+#endif
+
+BOOL DirEntry::Find( const String& rPfad, char cDelim )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT )
+ return TRUE;
+
+ BOOL bWild = aName.Search( '*' ) != STRING_NOTFOUND ||
+ aName.Search( '?' ) != STRING_NOTFOUND;
+ if ( !cDelim )
+ cDelim = SEARCHDELIM(DEFSTYLE)[0];
+
+ USHORT nTokenCount = rPfad.GetTokenCount( cDelim );
+ USHORT nIndex = 0;
+#ifndef MAC
+ ByteString aThis = ACCESSDELIM(DEFSTYLE);
+ aThis += ByteString(GetFull(), osl_getThreadTextEncoding());
+#else
+ String aThis(GetFull(), osl_getThreadTextEncoding());
+#endif
+ for ( USHORT nToken = 0; nToken < nTokenCount; ++nToken )
+ {
+ ByteString aPath = ByteString(rPfad, osl_getThreadTextEncoding()).GetToken( 0, cDelim, nIndex );
+#ifdef MAC
+ if (aPath[aPath.Len()-1] == ':')
+ aPath.Cut(aPath.Len()-1);
+#endif
+ aPath += aThis;
+ DirEntry aEntry( String(aPath, osl_getThreadTextEncoding()));
+ if ( aEntry.ToAbs() &&
+ ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) )
+ {
+ (*this) = aEntry;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpToRel()
+|*
+|* Beschreibung
+|* Ersterstellung MI 17.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ImpToRel( String aCurStr )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aThis(*this);
+ aThis.ToAbs();
+ ByteString aThisStr( aThis.GetFull( FSYS_STYLE_HPFS ), osl_getThreadTextEncoding());
+ ByteString bCurStr( aCurStr, osl_getThreadTextEncoding());
+ aThisStr = CMP_LOWER( aThisStr );
+ bCurStr = CMP_LOWER( bCurStr );
+
+ // "Ubereinstimmung pr"ufen
+ USHORT nPos = aThisStr.Match( bCurStr );
+ if ( nPos == STRING_MATCH && aThisStr.Len() != bCurStr.Len() )
+ nPos = Min( aThisStr.Len(), bCurStr.Len() );
+
+ // Sonderfall, die DirEntries sind identisch
+ if ( nPos == STRING_MATCH )
+ {
+ // dann ist der relative Pfad das aktuelle Verzeichnis
+ *this = DirEntry();
+ return TRUE;
+ }
+
+ // Sonderfall, die DirEntries sind total verschieden
+ if ( nPos == 0 )
+ {
+ // dann ist der relativste Pfad absolut
+ *this = aThis;
+ return FALSE;
+ }
+
+ // sonst nehmen wir die identischen Einzelteile vorne weg
+ while ( nPos > 0 && aThisStr.GetChar(nPos) != '\\' )
+ --nPos;
+ aThisStr.Erase( 0, nPos + ( ( aThisStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+ bCurStr.Erase( 0, nPos + ( ( bCurStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+
+ // und fuellen mit dem Level der Directories auf
+ for ( nPos = 0; nPos < bCurStr.Len(); ++nPos )
+ if ( bCurStr.GetChar(nPos) == '\\' )
+ aThisStr.Insert( "..\\", 0 );
+
+ // das ist dann unser relativer Pfad
+ *this = DirEntry( String(aThisStr, osl_getThreadTextEncoding()), FSYS_STYLE_HPFS );
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutRelParents()
+|*
+|* Beschreibung
+|* Ersterstellung MI 01.08.95
+|* Letzte Aenderung MI 01.08.95
+|*
+*************************************************************************/
+
+USHORT DirEntry::CutRelParents()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // erstes '..' finden
+ DirEntry *pDir = 0;
+ DirEntry *pPar;
+
+ for ( pPar = this;
+ pPar && pPar->eFlag != FSYS_FLAG_PARENT;
+ pPar = pPar->pParent )
+ pDir = pPar;
+
+ // '..' zaehlen
+ USHORT nParCount = 0;
+ while ( pPar && pPar->eFlag == FSYS_FLAG_PARENT )
+ {
+ ++nParCount;
+ pPar = pPar->pParent;
+ }
+
+ // cutten
+ if ( pDir )
+ DELETEZ(pDir->pParent);
+ else
+ eFlag = FSYS_FLAG_CURRENT;
+
+ return nParCount;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aCur;
+ aCur.ToAbs();
+ return ImpToRel( aCur.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel( const DirEntry& rStart )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aStart( rStart );
+ aStart.ToAbs();
+ return ImpToRel( aStart.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetDevice()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+#ifndef UNX
+
+DirEntry DirEntry::GetDevice() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTop = ImpGetTopPtr();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
+ pTop->aName.Len() )
+ return DirEntry( pTop->aName, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ else
+ return DirEntry( ByteString(), FSYS_FLAG_INVALID, FSYS_STYLE_HOST );
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::SetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.10.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetBase( const String& rBase, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( 0, p1 - p0 );
+ aName.Insert( ByteString(rBase, osl_getThreadTextEncoding()), 0 );
+ }
+ else
+ aName = ByteString(rBase, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetSearchDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 10.06.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ByteString(SEARCHDELIM( GetStyle( eFormatter ) ) ), osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetMaxNameLen()
+|*
+|* Beschreibung Liefert die maximale Anzahl von Zeichen in
+|* einzelnen Namensteile. Bei FileSystmen mit
+|* fester Extension (FAT) zaehlt diese nicht mit.
+|* Bei unbekannten FileSytemen und FSYS_STYLE_URL
+|* wird USHRT_MAX zurueckgegeben.
+|* Ersterstellung MI 17.06.97
+|* Letzte Aenderung MI 17.06.97
+|*
+*************************************************************************/
+
+USHORT DirEntry::GetMaxNameLen( FSysPathStyle eFormatter )
+{
+ eFormatter = GetStyle( eFormatter );
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC: return 31;
+
+ case FSYS_STYLE_FAT: return 8;
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS: return 255;
+
+
+ case FSYS_STYLE_SYSV: return 14;
+
+ case FSYS_STYLE_BSD: return 250;
+ }
+
+ return USHRT_MAX;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::TempName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung VB 06.09.93 (im SWG)
+|* Letzte Aenderung MI 06.02.98
+|*
+*************************************************************************/
+
+DirEntry aTempNameBase_Impl;
+
+const DirEntry& DirEntry::SetTempNameBase( const String &rBase )
+{
+ DirEntry aTempDir = DirEntry().TempName().GetPath();
+ aTempDir += DirEntry( rBase );
+#ifdef UNX
+ ByteString aName( aTempDir.GetFull(), osl_getThreadTextEncoding());
+ if ( access( aName.GetBuffer(), W_OK | X_OK | R_OK ) )
+ {
+ aTempDir.MakeDir();
+ chmod( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO );
+ }
+#else
+ aTempDir.MakeDir();
+#endif
+ aTempNameBase_Impl = aTempDir.TempName( FSYS_KIND_DIR );
+ return aTempNameBase_Impl;
+}
+
+DirEntry DirEntry::TempName( DirEntryKind eKind ) const
+{
+ // ggf. Base-Temp-Dir verwenden (macht Remote keinen Sinn => vorher)
+ if ( !pParent && FSYS_FLAG_CURRENT != aTempNameBase_Impl.eFlag && FSYS_FLAG_ABSROOT != eFlag )
+
+ {
+ DirEntry aFactory( aTempNameBase_Impl );
+ aFactory += GetName();
+ return aFactory.TempName();
+ }
+
+#ifdef OS2
+ //
+ // resolves long FAT names used by OS2
+ //
+ if (Folder::IsAvailable() && IsLongNameOnFAT())
+ {
+ // in DirEntry mit kurzem Pfad wandeln
+ ItemIDPath aItemIDPath(GetFull());
+ String aString(aItemIDPath.GetHostNotationPath());
+ DirEntry aDirEntry(aString);
+
+ // Aufruf der Methode
+ return aDirEntry.TempName(eKind);
+ }
+#endif
+
+ ByteString aDirName; // hiermit hatte MPW C++ Probleme - immmer noch??
+ char *ret_val;
+ size_t i;
+
+ // dertermine Directory, Prefix and Extension
+ char pfx[6];
+ char ext[5];
+ const char *dir;
+ const char *pWild = strchr( aName.GetBuffer(), '*' );
+ if ( !pWild )
+ pWild = strchr( aName.GetBuffer(), '?' );
+
+ if ( pWild )
+ {
+ if ( pParent )
+ aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding());
+ strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) );
+ pfx[ pWild-aName.GetBuffer() ] = 0;
+ const char *pExt = strchr( pWild, '.' );
+ if ( pExt )
+ {
+ strncpy( ext, pExt, 4 );
+ ext[4] = 0;
+ }
+ else
+ strcpy( ext, ".tmp" );
+ }
+ else
+ {
+ aDirName = ByteString(GetFull(), osl_getThreadTextEncoding());
+ strcpy( pfx, "sv" );
+ strcpy( ext, ".tmp" );
+ }
+ dir = aDirName.GetBuffer();
+
+ // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz.
+ char sBuf[_MAX_PATH];
+ if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
+ dir = TempDirImpl(sBuf);
+
+ // ab hier leicht modifizierter Code von VB
+ DirEntry aRet(FSYS_FLAG_INVALID);
+ i = strlen(dir);
+ // need to add ?\\? + prefix + number + .ext + '\0'
+ // please note that number is of length 5 not 3
+# define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
+ ret_val = new char[i + TMPNAME_SIZE ];
+ if (ret_val)
+ {
+ strcpy(ret_val,dir);
+
+ /* Make sure directory ends with a separator */
+#if defined(DOS) || defined(PM2) || defined(WIN) || defined(WNT)
+ if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
+ ret_val[i-1] != ':')
+ ret_val[i++] = '\\';
+#elif (UNX)
+ if (i>0 && ret_val[i-1] != '/')
+ ret_val[i++] = '/';
+#elif (MAC)
+ if (i>0 && ret_val[i-1] != ':')
+ ret_val[i++] = ':';
+#else
+#error unknown operating system
+#endif
+
+ strncpy(ret_val + i, pfx, 5);
+ ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */
+ i = strlen(ret_val); /* than 'n' chars. */
+
+ /* Prefix can have 5 chars, leaving 3 for numbers.
+ 26 ** 3 == 17576
+ */
+#if (defined (MSC) || defined (BLC) || defined(ICC) ) && ( defined (WIN) || defined (WNT))
+ static unsigned long u = GetTickCount();
+#else
+ static unsigned long u = clock();
+#endif
+ for ( unsigned long nOld = u; ++u != nOld; )
+ {
+ u %= (26*26*26);
+ unsigned nTemp = (unsigned)u;
+#if defined(OS2) || defined(WIN) || defined(WNT) || defined(DOS)
+ itoa(nTemp,ret_val + i,26);
+#else
+ // the number needs length 5 not 3 !!!!
+ sprintf(ret_val+i, "%03u", nTemp);
+#endif
+ strcat(ret_val,ext);
+
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
+ STREAM_WRITE|STREAM_SHARE_DENYALL );
+ if ( aStream.IsOpen() )
+ {
+ aStream.Seek( STREAM_SEEK_TO_END );
+ if ( 0 == aStream.Tell() )
+ {
+ aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
+ break;
+ }
+ aStream.Close();
+ }
+ }
+ else
+ {
+ // Redirect
+ String aRetVal(ret_val, osl_getThreadTextEncoding());
+ String aRedirected (aRetVal);
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aRedirected );
+#endif
+ if ( FSYS_KIND_DIR == eKind )
+ {
+ if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+ }
+ else
+ {
+#if defined(MAC)
+ OSErr nErr;
+ FSSpec aFSSpec;
+ FInfo dummyFInfo;
+
+ nErr = FSMakeFSSpec( 0, 0, aRedirected.GetPascalStr(), &aFSSpec );
+ if (nErr == noErr)
+ nErr = FSpGetFInfo(&aFSSpec,&dummyFInfo);
+
+ if (nErr == fnfErr) // File Not Found, das ist was wir wollen ...
+ {
+ aRet = DirEntry( ret_val );
+ break;
+ }
+ else if( nErr != noErr )
+ {
+ DBG_ASSERT( nErr == noErr, "cannot generate TempName" )
+ // keine Chance mehr, etwas zu finden
+ break;
+ }
+#elif defined(PM2)
+#ifdef POWERPC
+ // !!!!! DosQueryPathInfo liefert dezeit (Beta2) immer OK !!!!!
+ APIRET nRet;
+ HFILE hFile = 0;
+ PM_ULONG lAction = 0;
+ nRet = DosOpen( (PSZ)ret_val, &hFile, &lAction, 0,
+ FILE_NORMAL, FILE_OPEN,
+ OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0L );
+ if ( !nRet )
+ DosClose( hFile );
+ else
+ {
+ aRet = DirEntry( ret_val );
+ break;
+ }
+#else
+ APIRET nRet;
+ ULONG nCount = 1;
+ HDIR hDirHandle = HDIR_SYSTEM;
+ FILEFINDBUF3 aDirEnt;
+ nRet = DosFindFirst( (PSZ) aRedirected.GetBuffer(),
+ &hDirHandle, 23, (PVOID) &aDirEnt,
+ sizeof( FILEFINDBUF3 ),
+ &nCount, FIL_STANDARD );
+ if( nRet == ERROR_FILE_NOT_FOUND
+ || nRet == ERROR_NO_MORE_FILES )
+ {
+ aRet = DirEntry( String( ret_val ) );
+ break;
+ }
+ else if( nRet != NO_ERROR )
+ {
+ DBG_ASSERT( nRet == NO_ERROR, "cannot generate TempName" )
+ // keine Chance mehr, etwas zu finden
+ break;
+ }
+#endif
+#elif defined UNX
+ if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#else
+ struct stat aStat;
+ if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#endif
+ }
+ }
+ }
+
+ delete ret_val;
+ ret_val = 0;
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator[]()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+const DirEntry &DirEntry::operator[]( USHORT nParentLevel ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ //TPF: maybe to be implemented (FastFSys)
+
+ const DirEntry *pRes = this;
+ while ( pRes && nParentLevel-- )
+ pRes = pRes->pParent;
+
+ return *pRes;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseUnixName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ DirEntryStack aStack;
+ ByteString aPfad( rPfad );
+ do
+ {
+ // den Namen vor dem ersten "/" abspalten,
+ // falls '/' am Anfang, ist der Name '/',
+ // der Rest immer ohne die fuehrenden '/'.
+ // den ersten '/' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/';
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name die Root des aktuellen Drives?
+ if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = aPfad.Copy( 0, nPos );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+#ifdef UNX
+ // stellt der Name das User-Dir dar?
+ else if ( aName == "~" )
+ {
+ DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
+ for ( USHORT n = aHome.Level(); n; --n )
+ aStack.Push( new DirEntry( aHome[ (USHORT) n-1 ] ) );
+ }
+#endif
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) {
+ // die hat keine Parent-Directory
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+ else
+ {
+ DirEntry *pNew = NULL;
+ // normalen Entries kommen auf den Stack
+ pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent;
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseMacName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 14.10.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseMacName( const ByteString& rPfad )
+{
+#if 0
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntryStack aStack;
+ ByteString aPfad( rPfad );
+
+ //If the Path starts with an ABSROOT ( Volume ) it has to be
+ //pushed. So the Tail can be easier evaluated
+ if ( ( aPfad.Search( ':' ) != STRING_NOTFOUND ) && ( aPfad.GetChar(0) != ':' ) ) {
+ aStack.Push( new DirEntry( aPfad.Cut( 0, aPfad.Search( ':' ) ),
+ FSYS_FLAG_ABSROOT, FSYS_STYLE_MAC ) );
+ aPfad.Erase( 0, 1 );
+ }
+
+ //Purge Current-Directory
+ if ( aPfad(0) == ':' )
+ aPfad.Erase( 0, 1 );
+
+ //Evaluate the Tail
+ while ( aPfad.Len() ) {
+
+ if ( aPfad.GetChar(0) == ':' ) {
+ //PARENT detected
+ if ( aStack.Count() && (aStack.Top()->eFlag == FSYS_FLAG_ABSROOT) ) {
+ //an ABSROOT couldn't have a PARENT
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else {
+ //Nothing or a Parent at the top?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ) {
+ //put leading Parents on the Top
+ aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
+ aPfad.Erase( 0, 1 );
+ }
+ else {
+ delete aStack.Pop();
+ aPfad.Erase( 0, 1 );
+ }
+ }
+ }
+ else
+ {
+ // Normal entry detected
+ USHORT nSepPos = aPfad.Search( ':' );
+ if ( STRING_NOTFOUND == nSepPos )
+ nSepPos = USHRT_MAX;
+ DirEntry *pNew = new DirEntry( aPfad.Cut( 0, nSepPos ),
+ FSYS_FLAG_NORMAL, FSYS_STYLE_MAC );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ if ( STRING_NOTFOUND == nSepPos )
+ aPfad.Erase();
+ else
+ aPfad.Erase( 0, 1 );
+ }
+ }
+
+ //assign *this
+ if ( aStack.Count() == 0 ) {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ delete aStack.Pop();
+ }
+ //assign the Parent-Entries
+ DirEntry** pTemp = &pParent;
+ while ( aStack.Count() ) {
+ *pTemp = aStack.Pop();
+ pTemp = &( (*pTemp)->pParent );
+ }
+#endif
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MakeShortName()
+|*
+|* Beschreibung
+|* Ersterstellung TLX
+|* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl())
+|*
+*************************************************************************/
+
+ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind )
+{
+ // versuchen, anzulegen (ausser bei FSYS_KIND_ALL)
+ ErrCode eErr = ERRCODE_NONE;
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE );
+ aStream.WriteLine( "" );
+ eErr = aStream.GetError();
+ }
+ else if ( FSYS_KIND_ALL != eKind )
+ eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN;
+
+ // erfolgreich?
+ if ( !rPath.Exists() )
+ eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ?
+
+ // ggf. wieder l"oschen
+ if ( FSYS_KIND_NONE == eKind )
+ rPath.Kill();
+
+ // Fehlercode zur?ckliefern
+ return eErr;
+}
+
+BOOL IsValidEntry_Impl( const DirEntry &rPath,
+ const String &rLongName,
+ DirEntryKind eKind,
+ BOOL bIsShortened,
+ BOOL bUseDelim )
+{
+ // Parameter-Pr"uefung
+ DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL ||
+ eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR,
+ "invalid entry-kind" );
+
+ // Alle von MSDOS erreichbaren FSYS_STYLES muessen den
+ // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert,
+ // ob sich eine Datei des gewuenschten Names anlegen laesst.
+ FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() );
+ DirEntry aPath(rPath);
+ DirEntry aName(rLongName, eStyle);
+ if ( !aName.IsValid() || aName.Level() != 1 )
+ return FALSE;
+ aPath += aName;
+ if ( 1 == aPath.Level() )
+ return FALSE;
+ if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS ||
+ eStyle == FSYS_STYLE_UNKNOWN )
+ {
+ DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT );
+ if ( !aDosEntry.IsValid() )
+ return FALSE;
+ }
+
+ // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER)
+ char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0);
+ if ( rLongName.Search( DirEntry::GetAccessDelimiter() ) != STRING_NOTFOUND ||
+ !bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND )
+ return FALSE;
+
+ // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht
+ if ( aPath.Exists() )
+ return FALSE;
+
+ return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind ));
+}
+
+//-------------------------------------------------------------------------
+
+#define MAX_EXT_FAT 3
+#define MAX_LEN_FAT 8
+#define INVALID_CHARS_FAT "\\/\"':|^<>[]?* "
+
+#define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung
+#define MAX_LEN_MAC 31
+#define INVALID_CHARS_MAC "\":"
+
+#define MAX_EXT_MAX 250
+#define MAX_LEN_MAX 255
+#define INVALID_CHARS_DEF "\\/\"':|^<>?*"
+
+BOOL DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind,
+ BOOL bUseDelim, FSysPathStyle eStyle )
+{
+ String aLongName(rLongName);
+
+ // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject
+ // damit Probleme hat. Siehe auch #51246#
+ aLongName.EraseAllChars( '#' );
+ ByteString bLongName(aLongName, osl_getThreadTextEncoding());
+
+ // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII
+
+ // HRO: #69627# Weg mit dem Scheiss. Wenn es Client gibt, die so einen
+ // BUG haben, dann muss halt der Client ersetzt werden, aber doch nicht das
+ // Office kastrieren !!!
+
+#if 0
+ if ( FSYS_STYLE_NWFS == GetPathStyle( ImpGetTopPtr()->GetName() ) )
+ {
+ for ( USHORT n = aLongName.Len(); n; --n )
+ {
+ short nChar = aLongName(n-1);
+ if ( nChar < 32 || nChar >= 127 )
+ aLongName.Erase( n-1, 1 );
+ }
+ }
+#endif
+
+ // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename)
+ ByteString aOldName;
+ if ( FSYS_KIND_ALL == eKind )
+ {
+ aOldName = ByteString(CutName(), osl_getThreadTextEncoding());
+ aOldName = CMP_LOWER(aOldName);
+ }
+
+ // ist der Langname direkt verwendbar?
+ if ( IsValidEntry_Impl( *this, aLongName, eKind, FALSE, bUseDelim ) )
+ {
+ operator+=( DirEntry(aLongName) );
+ return TRUE;
+ }
+
+ // max L"angen feststellen
+ USHORT nMaxExt, nMaxLen;
+ if ( FSYS_STYLE_DETECT == eStyle )
+ eStyle = DirEntry::GetPathStyle( GetDevice().GetName() );
+ ByteString aInvalidChars;
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ nMaxExt = MAX_EXT_FAT;
+ nMaxLen = MAX_LEN_FAT;
+ aInvalidChars = INVALID_CHARS_FAT;
+ break;
+
+ case FSYS_STYLE_MAC:
+ nMaxExt = MAX_EXT_MAC;
+ nMaxLen = MAX_LEN_MAC;
+ aInvalidChars = INVALID_CHARS_MAC;
+ break;
+
+ default:
+ nMaxExt = MAX_EXT_MAX;
+ nMaxLen = MAX_LEN_MAX;
+ aInvalidChars = INVALID_CHARS_DEF;
+ }
+
+ // Extension abschneiden und kuerzen
+ ByteString aExt;
+ ByteString aFName = bLongName;
+#if defined(MAC)
+ if ( TRUE )
+#else
+ if ( FSYS_STYLE_MAC != eStyle )
+#endif
+ {
+ DirEntry aUnparsed;
+ aUnparsed.aName = bLongName;
+ aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding());
+ aFName = aUnparsed.aName;
+ if ( aExt.Len() > nMaxExt )
+ {
+ char c = aExt.GetChar( aExt.Len() - 1 );
+ aExt.Erase(nMaxExt-1);
+ aExt += c;
+ }
+ }
+
+ if ( FSYS_STYLE_FAT != eStyle )
+ {
+ // ausser auf einem FAT-System geh"ort die Extension zur
+ // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden.
+ nMaxLen -= ( aExt.Len() + 1 );
+ }
+
+ // Name k"urzen
+ ByteString aSName;
+ for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc )
+ {
+ if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) &&
+ (unsigned char) *pc >= (unsigned char) 32 &&
+ ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) )
+ aSName += *pc;
+ }
+ aSName.EraseTrailingChars();
+
+ // HRO: #74246# Also cut leading spaces
+ aSName.EraseLeadingChars();
+
+ if ( !aSName.Len() )
+ aSName = "noname";
+
+ // kommt dabei der alte Name raus?
+ ByteString aNewName = aSName;
+ if ( aExt.Len() )
+ ( aNewName += '.' ) += aExt;
+ operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) );
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName )
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName )
+ return TRUE;
+
+ // kann der gek"urzte Name direkt verwendet werden?
+ if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) )
+ return TRUE;
+
+ // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen?
+ if ( bUseDelim )
+ {
+ // eindeutigen Namen per '?##' erzeugen
+ aSName.Erase( nMaxLen-3 );
+ if ( bUseDelim != 2 )
+ aSName += FSYS_SHORTNAME_DELIMITER;
+ for ( int n = 1; n < 99; ++n )
+ {
+ // Name zusammensetzen
+ ByteString aTmpStr( aSName );
+ aTmpStr += n;
+ if ( aExt.Len() )
+ ( aTmpStr += '.' ) += aExt;
+
+ // noch nicht vorhanden?
+ SetName( String(aTmpStr, osl_getThreadTextEncoding()) );
+
+ if ( !Exists() )
+ {
+ // Fehler setzen !!!
+ nError = CreateEntry_Impl( *this, eKind );
+ return (ERRCODE_NONE == nError);
+ }
+ }
+ }
+
+ // keine ## mehr frei / ?## soll nicht verwendet werden
+ nError = ERRCODE_IO_ALREADYEXISTS;
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CreatePath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::MakeDir( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // Schnellpruefung, ob vorhanden
+ if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ if ( bSloppy && pParent )
+ if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+
+ const DirEntry *pNewDir = bSloppy ? pParent : this;
+ if ( pNewDir )
+ {
+ // den Path zum Dir erzeugen
+ if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(FALSE) )
+ return FALSE;
+
+ // das Dir selbst erzeugen
+ if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_VOLUME )
+ return TRUE;
+ else
+ {
+ //? nError = ???
+ if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ else
+ {
+ FSysFailOnErrorImpl();
+ String aDirName(pNewDir->GetFull());
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aDirName );
+#endif
+ ByteString bDirName( aDirName, osl_getThreadTextEncoding() );
+ bDirName = GUI2FSYS( bDirName );
+
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ BOOL bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() ));
+ if ( !bResult )
+ {
+ // Wer hat diese Methode const gemacht ?
+#ifdef WIN32
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) );
+#else
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) );
+#endif
+ }
+
+ return bResult;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CopyTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
+#ifdef UNX
+ {
+ // Hardlink anlegen
+ HACK(redirection missing)
+ ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding());
+ ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding());
+ link( aThis.GetBuffer(), aDest.GetBuffer() );
+ return Sys2SolarError_Impl( errno );
+ }
+#else
+ return FSYS_ERR_NOTSUPPORTED;
+#endif
+
+ return FileCopier( *this, rDest ).Execute(nActions);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MoveTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung HRO 24.03.99
+|*
+*************************************************************************/
+
+#if defined(WNT) || defined(DOS) || defined(WIN) || defined(UNX)
+
+FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+/*
+ FileStat aSourceStat(*this);
+ if ( !aSourceStat.IsKind(FSYS_KIND_FILE) )
+ return FSYS_ERR_NOTAFILE;
+*/
+
+ DirEntry aDest(rNewName);
+ FileStat aDestStat(rNewName);
+ if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aDest += String(aName, osl_getThreadTextEncoding());
+ }
+ if ( aDest.Exists() )
+ {
+ return FSYS_ERR_ALREADYEXISTS;
+ }
+
+#ifdef WIN
+ if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() )
+ {
+ return FSYS_ERR_NOTSUPPORTED;
+ }
+#endif
+
+ FSysFailOnErrorImpl();
+ String aFrom( GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aFrom);
+#endif
+
+ String aTo( aDest.GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aTo);
+#endif
+
+ ByteString bFrom(aFrom, osl_getThreadTextEncoding());
+ ByteString bTo(aTo, osl_getThreadTextEncoding());
+ bFrom = GUI2FSYS(bFrom);
+ bTo = GUI2FSYS(bTo);
+
+#ifdef WNT
+ // MoveTo nun atomar
+ SetLastError(0);
+
+ DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding()));
+ DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding()));
+ aFromDevice.ToAbs();
+ aToDevice.ToAbs();
+ aFromDevice=aFromDevice.GetDevice();
+ aToDevice=aToDevice.GetDevice();
+
+ //Quelle und Ziel auf gleichem device?
+ if (aFromDevice==aToDevice)
+ {
+ // ja, also intra-device-move mit MoveFile
+ MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() );
+ // MoveFile ist buggy bei cross-device operationen.
+ // Der R?ckgabewert ist auch dann TRUE, wenn nur ein Teil der Operation geklappt hat.
+ // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen.
+ return Sys2SolarError_Impl( GetLastError() );
+ }
+ else
+ {
+ //nein, also inter-device-move mit copy/delete
+ FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
+
+ DirEntry aKill(String(bTo, osl_getThreadTextEncoding()));
+ FileStat aKillStat(String(bTo, osl_getThreadTextEncoding()));
+ if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aKill += String(aName, osl_getThreadTextEncoding());
+ }
+
+ if (nCopyError==FSYS_ERR_OK)
+ {
+ if (Kill()==FSYS_ERR_OK)
+ {
+ return FSYS_ERR_OK;
+ }
+ else
+ {
+ aKill.Kill();
+ return FSYS_ERR_ACCESSDENIED;
+ }
+ }
+ else
+ {
+ aKill.Kill();
+ return nCopyError;
+ }
+ }
+#else
+ // #68639#
+ // on some nfs connections rename with from == to
+ // leads to destruction of file
+ if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) )
+#ifndef UNX
+#ifdef WIN
+ { // einfaches umbenennen ist fehlgeschlagen, kopieren versuchen
+ FILE *fpIN = fopen(aFrom.GetBuffer(), "rb");
+ if (!fpIN) return Sys2SolarError_Impl(ENOENT); // Quelle kann nicht zum Lesen geoeffnet werden
+ FILE *fpOUT = fopen(aTo, "wb");
+ if (!fpOUT)
+ {
+ fclose(fpIN);
+ return Sys2SolarError_Impl(EACCES); // Ziel kann nicht zum Schreiben geoeffnet werden
+ }
+
+ char pBuf[16384];
+ int nRead, nWrite, nError = 0;
+ while((nRead = fread(pBuf, 1, 16384, fpIN)) && (!nError))
+ {
+ nWrite = fwrite(pBuf, 1, nRead, fpOUT);
+ if (nWrite != nRead) nError = ENOSPC;
+ }
+ fclose( fpIN );
+ fclose( fpOUT );
+ return Sys2SolarError_Impl(nError);
+ }
+#else
+ return Sys2SolarError_Impl( GetLastError() );
+#endif
+#else
+ {
+ if( errno == EXDEV )
+// cross device geht latuernich nicht mit rename
+ {
+ FILE *fpIN = fopen( bFrom.GetBuffer(), "r" );
+ FILE *fpOUT = fopen( bTo.GetBuffer(), "w" );
+ if( fpIN && fpOUT )
+ {
+ char pBuf[ 16384 ];
+ int nBytes, nWritten, nError = 0;
+ errno = 0;
+ while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nError )
+ {
+ nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
+ // Fehler im fwrite ?
+ if( nWritten < nBytes )
+ {
+ nError = errno;
+ break;
+ }
+ }
+ fclose( fpIN );
+ fclose( fpOUT );
+ if ( nError )
+ {
+ unlink( bTo.GetBuffer() );
+ return Sys2SolarError_Impl( nError );
+ }
+ else
+ {
+ unlink( bFrom.GetBuffer() );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( EXDEV );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( errno );
+ }
+ }
+#endif
+#endif
+ return ERRCODE_NONE;
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::Kill()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::Kill( FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ FSysError eError = FSYS_ERR_OK;
+ FSysFailOnErrorImpl();
+
+ // Name als doppelt 0-terminierter String
+ String aTmpName( GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aTmpName );
+#endif
+ ByteString bTmpName( aTmpName, osl_getThreadTextEncoding());
+ bTmpName = GUI2FSYS(bTmpName);
+
+ char *pName = new char[bTmpName.Len()+2];
+ strcpy( pName, bTmpName.GetBuffer() );
+ pName[bTmpName.Len()+1] = (char) 0;
+
+ //read-only files sollen auch geloescht werden koennen
+ BOOL isReadOnly = FileStat::GetReadOnlyFlag(*this);
+ if (isReadOnly)
+ {
+ FileStat::SetReadOnlyFlag(*this, FALSE);
+ }
+
+ // directory?
+ if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
+ {
+ // Inhalte recursiv loeschen?
+ if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
+ {
+ Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
+ for ( USHORT n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
+ {
+ const DirEntry &rSubDir = aDir[n];
+ DirEntryFlag eFlag = rSubDir.GetFlag();
+ if ( eFlag != FSYS_FLAG_CURRENT && eFlag != FSYS_FLAG_PARENT )
+ eError = rSubDir.Kill(nActions);
+ }
+ }
+
+ // das Dir selbst loeschen
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
+ //
+ {
+ // falls L"oschen nicht ging, CWD umsetzen
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ if ( eError )
+ {
+ GetPath().SetCWD();
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if (_rmdir( (char*) pName) != 0)
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = FSYS_ERR_OK;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
+ {
+#ifdef OS2
+ eError = ApiRet2ToSolarError_Impl( DosDelete( (char*) pName ) );
+#else
+#ifdef WNT
+ SHFILEOPSTRUCT aOp;
+ aOp.hwnd = 0;
+ aOp.wFunc = FO_DELETE;
+ aOp.pFrom = pName;
+ aOp.pTo = 0;
+ aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
+ aOp.hNameMappings = 0;
+ aOp.lpszProgressTitle = 0;
+ eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
+#else
+ eError = ERRCODE_IO_NOTSUPPORTED;
+#endif
+#endif
+ }
+ else
+ {
+#ifdef OS2
+ eError = ApiRet2ToSolarError_Impl( DosForceDelete( (PSZ) pName ) );
+#else
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( 0 != _unlink( (char*) pName ) )
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = ERRCODE_NONE;
+ }
+#endif
+ }
+ }
+
+ //falls Fehler, originales read-only flag wieder herstellen
+ if ( isReadOnly && (eError!=ERRCODE_NONE) )
+ {
+ FileStat::SetReadOnlyFlag(*this, isReadOnly);
+ }
+
+ delete pName;
+ return eError;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Contains()
+|*
+|* Beschreibung ob rSubEntry direkt oder indirect in *this liegt
+|* Ersterstellung MI 20.03.97
+|* Letzte Aenderung MI 20.03.97
+|*
+*************************************************************************/
+
+BOOL DirEntry::Contains( const DirEntry &rSubEntry ) const
+{
+ DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
+
+ USHORT nThisLevel = Level();
+ USHORT nSubLevel = rSubEntry.Level();
+ if ( nThisLevel < nSubLevel )
+ {
+ for ( ; nThisLevel; --nThisLevel, --nSubLevel )
+ if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Level()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+USHORT DirEntry::Level() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ USHORT nLevel = 0;
+ const DirEntry *pRes = this;
+ while ( pRes )
+ {
+ pRes = pRes->pParent;
+ nLevel++;
+ }
+
+ return nLevel;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertNameToSystem()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertNameToSystem( const String &rName )
+{
+#ifdef MAC
+ return ImpConvertNameToSystem( rName );
+#else
+ return rName;
+#endif
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertSystemToName()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertSystemToName( const String &rName )
+{
+#ifdef MAC
+ return ImpConvertSystemToName( rName );
+#else
+ return rName;
+#endif
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsValid()
+|*
+|* Beschreibung
+|* Ersterstellung MI 18.09.93
+|* Letzte Aenderung TPF 18.09.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsValid() const
+{
+ return (nError == FSYS_ERR_OK);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsRFSAvailable()
+|*
+|* Beschreibung
+|* Ersterstellung TPF 21.10.98
+|* Letzte Aenderung TPF 21.10.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsRFSAvailable()
+{
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* IsLongNameOnFAT()
+|*
+|* Beschreibung ?berpr?ft , ob das DirEntry einen langen
+|* Filenamen auf einer FAT-Partition enth?lt (EAs).
+|* (eigentlich nur f?r OS2 interessant)
+|* Ersterstellung TPF 02.10.98
+|* Letzte Aenderung TPF 01.03.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsLongNameOnFAT() const
+{
+ // FAT-System?
+ DirEntry aTempDirEntry(*this);
+ aTempDirEntry.ToAbs();
+ if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT)
+ {
+ return FALSE; // nein, also false
+ }
+
+ // DirEntry-Kette auf lange Dateinamen pr?fen
+ for( int iLevel = this->Level(); iLevel > 0; iLevel-- )
+ {
+ const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1];
+ String aBase( rEntry.GetBase() );
+ String aExtension( rEntry.GetExtension() );
+
+ if (aBase.Len()>8) // Name > 8?
+ {
+ return TRUE;
+ }
+
+ if (aExtension.Len()>3) // Extension > 3?
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//========================================================================
+
+#if defined(DBG_UTIL)
+
+void FSysTest()
+{
+}
+
+#endif
+
diff --git a/tools/source/fsys/filecopy.cxx b/tools/source/fsys/filecopy.cxx
new file mode 100644
index 000000000000..6be1822f8991
--- /dev/null
+++ b/tools/source/fsys/filecopy.cxx
@@ -0,0 +1,578 @@
+/*************************************************************************
+ *
+ * $RCSfile: filecopy.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#if defined(WIN) || defined(WNT)
+#ifndef _SVWIN_H
+#include <io.h>
+#include <svwin.h>
+#endif
+
+#elif defined(PM2) || defined(DOS)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <share.h>
+#include <io.h>
+
+#elif defined UNX
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#elif defined MAC
+#include <mac_start.h>
+#include <fcntl.h>
+#include <mac_end.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef PM2
+#include <stdio.h>
+#endif
+
+#ifndef _COMDEP_HXX
+#include "comdep.hxx"
+#endif
+
+#ifndef _FSYS_HXX
+#include "fsys.hxx"
+#endif
+
+#ifndef _STREAM_HXX
+#ifdef UNX
+#define private public
+#endif
+#include "stream.hxx"
+#endif
+
+EA_Copier* EA_Copier::_pCopier = NULL;
+
+//========================================================================
+
+EA_Copier::~EA_Copier()
+{
+}
+
+//------------------------------------------------------------------------
+void EA_Copier::Register( EA_Copier* pCopier )
+{
+ _pCopier = pCopier;
+}
+
+//------------------------------------------------------------------------
+
+EA_Copier* EA_Copier::Get()
+{
+ return _pCopier;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::FileCopier()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier::FileCopier() :
+
+ nBlockSize ( 4096 ),
+ nBytesTotal ( 0 ),
+ nBytesCopied( 0 ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+// -----------------------------------------------------------------------
+
+FileCopier::FileCopier( const DirEntry& rSource, const DirEntry& rTarget ) :
+
+ aSource ( rSource ),
+ aTarget ( rTarget ),
+ nBlockSize ( 4096 ),
+ nBytesTotal ( 0 ),
+ nBytesCopied( 0 ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+// -----------------------------------------------------------------------
+
+FileCopier::FileCopier( const FileCopier& rCopier ) :
+
+ aSource ( rCopier.aSource ),
+ aTarget ( rCopier.aTarget ),
+ nBlockSize ( 4096 ),
+ nBytesTotal ( 0 ),
+ nBytesCopied ( 0 ),
+ aProgressLink ( rCopier.aProgressLink ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+/*************************************************************************
+|*
+|* FileCopier::~FileCopier()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier::~FileCopier()
+{
+ delete pImp;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::operator =()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier& FileCopier::operator = ( const FileCopier &rCopier )
+{
+ aSource = rCopier.aSource;
+ aTarget = rCopier.aTarget;
+ nBytesTotal = rCopier.nBytesTotal;
+ nBytesCopied = rCopier.nBytesCopied;
+ nBytesCopied = rCopier.nBytesCopied;
+ nBlockSize = rCopier.nBlockSize;
+ aProgressLink = rCopier.aProgressLink;
+ *pImp = *(rCopier.pImp);
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::Progress()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+BOOL FileCopier::Progress()
+{
+ if ( !aProgressLink )
+ return TRUE;
+ else
+ {
+ if ( aProgressLink.Call( this ) )
+ return TRUE;
+ return ( 0 == Error( ERRCODE_ABORT, 0, 0 ) );
+ }
+}
+
+//---------------------------------------------------------------------------
+
+ErrCode FileCopier::Error( ErrCode eErr, const DirEntry* pSource, const DirEntry* pTarget )
+{
+ // kein Fehler oder kein ErrorHandler?
+ if ( !eErr || !pImp->aErrorLink )
+ // => Error beibehalten
+ return eErr;
+
+ // sonst gesetzten ErrorHandler fragen
+ pImp->pErrSource = pSource;
+ pImp->pErrTarget = pTarget;
+ pImp->eErr = eErr;
+ ErrCode eRet = (ErrCode) pImp->aErrorLink.Call( this );
+ pImp->pErrSource = 0;
+ pImp->pErrTarget = 0;
+ return eRet;
+}
+
+//---------------------------------------------------------------------------
+
+const DirEntry* FileCopier::GetErrorSource() const
+{
+ return pImp->pErrSource;
+}
+
+//---------------------------------------------------------------------------
+
+const DirEntry* FileCopier::GetErrorTarget() const
+{
+ return pImp->pErrTarget;
+}
+
+//---------------------------------------------------------------------------
+
+ErrCode FileCopier::GetError() const
+{
+ return pImp->eErr;
+}
+
+//---------------------------------------------------------------------------
+
+void FileCopier::SetErrorHdl( const Link &rLink )
+{
+ pImp->aErrorLink = rLink;
+}
+
+//---------------------------------------------------------------------------
+
+const Link& FileCopier::GetErrorHdl() const
+{
+ return pImp->aErrorLink ;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::Execute()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung PB 16.06.00
+|*
+*************************************************************************/
+
+#ifndef MAC
+
+#ifdef OS2
+BOOL createLongNameEA ( const PCSZ pszPath, ULONG ulAttributes, const String& aLongName );
+#endif
+
+FSysError FileCopier::DoCopy_Impl( const DirEntry &rSource, const DirEntry &rTarget,
+ BOOL bTop )
+{
+ FSysError eRet = FSYS_ERR_OK;
+ ErrCode eWarn = FSYS_ERR_OK;
+
+ // HPFS->FAT?
+ FSysPathStyle eSourceStyle = DirEntry::GetPathStyle( rSource.ImpGetTopPtr()->GetName() );
+ FSysPathStyle eTargetStyle = DirEntry::GetPathStyle( rTarget.ImpGetTopPtr()->GetName() );
+ BOOL bMakeShortNames = ( eSourceStyle == FSYS_STYLE_HPFS && eTargetStyle == FSYS_STYLE_FAT );
+
+ // Zieldateiname ggf. kuerzen
+ DirEntry aTarget;
+ if ( bMakeShortNames )
+ {
+ aTarget = rTarget.GetPath();
+ aTarget.MakeShortName( rTarget.GetName() );
+ }
+ else
+ aTarget = rTarget;
+
+ // kein Move wenn Namen gekuerzt werden muessten
+ if ( bMakeShortNames && FSYS_ACTION_MOVE == ( pImp->nActions & FSYS_ACTION_MOVE ) && aTarget != rTarget )
+ return ERRCODE_IO_NAMETOOLONG;
+
+ // source is directory?
+ FileStat aSourceFileStat( rSource );
+ if ( aSourceFileStat.IsKind( FSYS_KIND_DIR ) )
+ {
+#ifdef OS2
+ CHAR szSource[CCHMAXPATHCOMP];
+ HOBJECT hSourceObject;
+
+ strcpy(szSource, rSource.GetFull().GetStr());
+ hSourceObject = WinQueryObject(szSource);
+
+ if ( hSourceObject )
+ {
+ PSZ pszSourceName;
+ PSZ pszTargetName;
+ CHAR szTarget[CCHMAXPATHCOMP];
+ HOBJECT hTargetObject;
+ HOBJECT hReturn = NULLHANDLE;
+
+ strcpy(szTarget, rTarget.GetFull().GetStr());
+ pszTargetName = strrchr(szTarget, '\\');
+ pszSourceName = strrchr(szSource, '\\');
+
+ hTargetObject = WinQueryObject(szTarget);
+
+ if ( hTargetObject )
+ WinDestroyObject(hTargetObject);
+
+ if ( pszTargetName && pszSourceName )
+ {
+ *pszTargetName = '\0';
+ pszSourceName++;
+ pszTargetName++;
+
+ if(strcmp(pszSourceName, pszTargetName) == 0)
+ {
+ hTargetObject = WinQueryObject(szTarget);
+
+ if(pImp->nActions & FSYS_ACTION_MOVE)
+ {
+ hReturn = WinMoveObject(hSourceObject, hTargetObject, 0);
+ }
+ else
+ {
+ hReturn = WinCopyObject(hSourceObject, hTargetObject, 0);
+ }
+ if ( bMakeShortNames && aTarget.Exists() )
+ aTarget.Kill();
+ return hReturn ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN;
+ }
+ }
+ }
+#endif
+ // recursive copy
+ eRet = Error( aTarget.MakeDir() ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN, 0, &aTarget );
+ Dir aSourceDir( rSource, FSYS_KIND_DIR|FSYS_KIND_FILE );
+ for ( USHORT n = 0; ERRCODE_TOERROR(eRet) == FSYS_ERR_OK && n < aSourceDir.Count(); ++n )
+ {
+ const DirEntry &rSubSource = aSourceDir[n];
+ DirEntryFlag eFlag = rSubSource.GetFlag();
+ if ( eFlag != FSYS_FLAG_CURRENT && eFlag != FSYS_FLAG_PARENT )
+ {
+ DirEntry aSubTarget( aTarget );
+ aSubTarget += rSubSource.GetName();
+ eRet = DoCopy_Impl( rSubSource, aSubTarget, FALSE );
+ if ( eRet && !eWarn )
+ eWarn = eRet;
+ }
+ }
+ }
+ else if ( aSourceFileStat.IsKind(FSYS_KIND_FILE) )
+ {
+ if ( ( FSYS_ACTION_KEEP_EXISTING == ( pImp->nActions & FSYS_ACTION_KEEP_EXISTING ) ) &&
+ aTarget.Exists() )
+ {
+ // Do not overwrite existing file in target folder.
+ return ERRCODE_NONE;
+ }
+
+ // copy file
+ nBytesCopied = 0;
+ nBytesTotal = FileStat( rSource ).GetSize();
+
+ String aFileName( GUI2FSYS( rSource.GetFull() ).GetBuffer() );
+ SvFileStream aSource( aFileName, STREAM_READ|STREAM_NOCREATE|STREAM_SHARE_DENYNONE );
+
+ if ( !aSource.GetError() )
+ {
+#ifdef UNX
+ struct stat buf;
+ if ( fstat( aSource.GetFileHandle(), &buf ) == -1 )
+ eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTarget );
+#endif
+ SvFileStream aTargetStream( GUI2FSYS( aTarget.GetFull() ),
+ STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYWRITE );
+ if ( !aTargetStream.GetError() )
+ {
+#ifdef UNX
+ if ( fchmod( aTargetStream.GetFileHandle(), buf.st_mode ) == -1 )
+ eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTarget );
+#endif
+ size_t nAllocSize = 0, nSize = 0;
+ char *pBuf = 0;
+ while ( Progress() && nSize == nAllocSize && eRet == FSYS_ERR_OK )
+ {
+ // adjust the block-size
+ if ( nBlockSize > nAllocSize )
+ {
+ delete pBuf;
+ nAllocSize = nBlockSize;
+ pBuf = new char[nAllocSize];
+ }
+
+ // copy one block
+ nSize = aSource.Read( pBuf, nBlockSize );
+ aTargetStream.Write( pBuf, nSize );
+ if ( aTargetStream.GetError() )
+ eRet = Error( aTargetStream.GetError(), 0, &aTarget );
+
+ // adjust counters
+ nBytesCopied += nSize;
+ if ( nBytesCopied > nBytesTotal )
+ nBytesTotal = nBytesCopied;
+ }
+ delete pBuf;
+ }
+ else
+ eRet = Error( aTargetStream.GetError(), 0, &aTarget );
+
+ // ggf. EAs kopieren
+ if ( !eRet && EA_Copier::Get() && !EA_Copier::Get()->Copy( aSource, aTargetStream ) )
+ eRet = FSYS_ERR_UNKNOWN | ERRCODE_WARNING_MASK;
+
+ // unvollstaendiges File wieder loeschen
+ aTargetStream.Close();
+
+ if ( nBytesCopied != nBytesTotal )
+ {
+ aTarget.Kill();
+ }
+#ifdef OS2
+ else
+ {
+ // falls die Source-Target-Filenamen nicht gleich sind und der Target-Filename nicht
+ // 8.3 aber auf FAT ist, dann mu? das EA .longname korrekt gesetzt werden (TPF)
+ // (rSource.GetName()!=rTarget.GetName())
+
+ if ( rTarget.IsLongNameOnFAT() && Folder::IsAvailable() )
+ {
+ createLongNameEA( (const char*)aTargetStream.GetFileName(),
+ FILE_NORMAL, rTarget.GetName() );
+ }
+ }
+#endif
+ }
+ else
+ eRet = Error( aSource.GetError(), &rSource, 0 );
+ }
+ else if ( aSourceFileStat.IsKind(FSYS_KIND_NONE) )
+ eRet = Error( ERRCODE_IO_NOTEXISTS, &rSource, 0 );
+ else
+ eRet = Error( ERRCODE_IO_NOTSUPPORTED, &rSource, 0 );
+
+#ifdef WNT
+ // Set LastWriteTime and Attributes of the target identical with the source
+
+ if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) )
+ {
+ WIN32_FIND_DATA fdSource;
+ ByteString aFullSource(aSource.GetFull(), osl_getThreadTextEncoding());
+ ByteString aFullTarget(aTarget.GetFull(), osl_getThreadTextEncoding());
+ HANDLE hFind = FindFirstFile( aFullSource.GetBuffer() , &fdSource );
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ FindClose( hFind );
+
+ HANDLE hFile = CreateFile( aFullTarget.GetBuffer(), GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ SetFileTime( hFile, NULL, NULL, &fdSource.ftLastWriteTime );
+ CloseHandle( hFile );
+ }
+
+ SetFileAttributes( aFullTarget.GetBuffer(), fdSource.dwFileAttributes );
+ }
+ }
+#endif
+ // bei Move ggf. das File/Dir loeschen
+ if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) && ( pImp->nActions & FSYS_ACTION_MOVE ) )
+ {
+ ErrCode eKillErr = Error( rSource.Kill() | ERRCODE_WARNING_MASK, &rSource, 0 );
+ if ( eKillErr != ERRCODE_WARNING_MASK )
+ {
+ if ( rSource.Exists() )
+ // loeschen ging nicht => dann die Kopie wieder loeschen
+ aTarget.Kill( pImp->nActions );
+ if ( !eWarn )
+ eWarn = eKillErr;
+ }
+ }
+
+ return !eRet ? eWarn : eRet;
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+FSysError FileCopier::Execute( FSysAction nActions )
+{
+ return ExecuteExact( nActions );
+}
+
+// -----------------------------------------------------------------------
+
+FSysError FileCopier::ExecuteExact( FSysAction nActions, FSysExact eExact )
+{
+ DirEntry aAbsSource = DirEntry( aSource);
+ DirEntry aAbsTarget = DirEntry( aTarget );
+ pImp->nActions = nActions;
+
+ // check if both pathes are accessible and source and target are different
+ if ( !aAbsTarget.ToAbs() || !aAbsSource.ToAbs() || aAbsTarget == aAbsSource )
+ return FSYS_ERR_ACCESSDENIED;
+
+ // check if copy would be endless recursive into itself
+ if ( FSYS_ACTION_RECURSIVE == ( nActions & FSYS_ACTION_RECURSIVE ) &&
+ aAbsSource.Contains( aAbsTarget ) )
+ return ERRCODE_IO_RECURSIVE;
+
+ // target is directory?
+ if ( eExact == FSYS_NOTEXACT &&
+ FileStat( aAbsTarget ).IsKind(FSYS_KIND_DIR) && FileStat( aAbsSource ).IsKind(FSYS_KIND_FILE) )
+ // append name of source
+ aAbsTarget += aSource.GetName();
+
+ // recursive copy
+ return DoCopy_Impl( aAbsSource, aAbsTarget, TRUE );
+}
+
+
diff --git a/tools/source/fsys/fstat.cxx b/tools/source/fsys/fstat.cxx
new file mode 100644
index 000000000000..bbde14c83208
--- /dev/null
+++ b/tools/source/fsys/fstat.cxx
@@ -0,0 +1,516 @@
+/*************************************************************************
+ *
+ * $RCSfile: fstat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#if defined( WIN)
+#include <stdio.h>
+#include <dos.h>
+#endif
+
+#ifdef UNX
+#include <errno.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+
+#include "comdep.hxx"
+#include <fsys.hxx>
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MI 11.06.91
+|*
+*************************************************************************/
+
+FileStat::FileStat()
+: // don't use Default-Ctors!
+ aDateCreated( ULONG(0) ),
+ aTimeCreated( ULONG(0) ),
+ aDateModified( ULONG(0) ),
+ aTimeModified( ULONG(0) ),
+ aDateAccessed( ULONG(0) ),
+ aTimeAccessed( ULONG(0) )
+{
+ nSize = 0;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MI 11.06.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const DirEntry& rDirEntry, FSysAccess nAccess )
+: // don't use Default-Ctors!
+ aDateCreated( ULONG(0) ),
+ aTimeCreated( ULONG(0) ),
+ aDateModified( ULONG(0) ),
+ aTimeModified( ULONG(0) ),
+ aDateAccessed( ULONG(0) ),
+ aTimeAccessed( ULONG(0) )
+{
+ BOOL bCached = FSYS_ACCESS_CACHED == (nAccess & FSYS_ACCESS_CACHED);
+ BOOL bFloppy = FSYS_ACCESS_FLOPPY == (nAccess & FSYS_ACCESS_FLOPPY);
+
+#ifdef FEAT_FSYS_DOUBLESPEED
+ const FileStat *pStatFromDir = bCached ? rDirEntry.ImpGetStat() : 0;
+ if ( pStatFromDir )
+ {
+ nError = pStatFromDir->nError;
+ nKindFlags = pStatFromDir->nKindFlags;
+ nSize = pStatFromDir->nSize;
+ aCreator = pStatFromDir->aCreator;
+ aType = pStatFromDir->aType;
+ aDateCreated = pStatFromDir->aDateCreated;
+ aTimeCreated = pStatFromDir->aTimeCreated;
+ aDateModified = pStatFromDir->aDateModified;
+ aTimeModified = pStatFromDir->aTimeModified;
+ aDateAccessed = pStatFromDir->aDateAccessed;
+ aTimeAccessed = pStatFromDir->aTimeAccessed;
+ }
+ else
+#endif
+ Update( rDirEntry, bFloppy );
+}
+
+/*************************************************************************
+|*
+|* FileStat::IsYounger()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 11.11.91
+|* Letzte Aenderung MA 11.11.91
+|*
+*************************************************************************/
+
+// TRUE wenn die Instanz j"unger als rIsOlder ist.
+// FALSE wenn die Instanz "alter oder gleich alt wie rIsOlder ist.
+
+BOOL FileStat::IsYounger( const FileStat& rIsOlder ) const
+{
+ if ( aDateModified > rIsOlder.aDateModified )
+ return TRUE;
+ if ( ( aDateModified == rIsOlder.aDateModified ) &&
+ ( aTimeModified > rIsOlder.aTimeModified ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* FileStat::IsKind()
+|*
+|* Ersterstellung MA 11.11.91 (?)
+|* Letzte Aenderung KH 16.01.95
+|*
+*************************************************************************/
+
+BOOL FileStat::IsKind( DirEntryKind nKind ) const
+{
+ BOOL bRet = ( ( nKind == FSYS_KIND_UNKNOWN ) &&
+ ( nKindFlags == FSYS_KIND_UNKNOWN ) ) ||
+ ( ( nKindFlags & nKind ) == nKind );
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* FileStat::HasReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 01.07.98
+|*
+*************************************************************************/
+
+BOOL FileStat::HasReadOnlyFlag()
+{
+#if defined(WNT) || defined(OS2) || defined(UNX)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/*************************************************************************
+|*
+|* FileStat::GetReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 02.07.98
+|*
+*************************************************************************/
+
+BOOL FileStat::GetReadOnlyFlag( const DirEntry &rEntry )
+{
+
+ ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
+#ifdef WNT
+ DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
+ return ULONG_MAX != nRes &&
+ ( FILE_ATTRIBUTE_READONLY & nRes ) == FILE_ATTRIBUTE_READONLY;
+#endif
+
+#ifdef OS2
+ FILESTATUS3 aFileStat;
+ APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
+ switch ( nRet )
+ {
+ case NO_ERROR:
+ return FILE_READONLY == ( aFileStat.attrFile & FILE_READONLY );
+
+ case ERROR_SHARING_VIOLATION:
+ return ERRCODE_IO_LOCKVIOLATION;
+
+ default:
+ return ERRCODE_IO_NOTEXISTS;
+ }
+#endif
+
+#ifdef UNX
+ /* could we stat the object? */
+ struct stat aBuf;
+ if (stat(aFPath.GetBuffer(), &aBuf))
+ return FALSE;
+ /* jupp, is writable for user? */
+ return((aBuf.st_mode & S_IWUSR) != S_IWUSR);
+#endif
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 01.07.98
+|*
+*************************************************************************/
+
+ULONG FileStat::SetReadOnlyFlag( const DirEntry &rEntry, BOOL bRO )
+{
+
+ ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
+
+#ifdef WNT
+ DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
+ if ( ULONG_MAX != nRes )
+ nRes = SetFileAttributes( (LPCTSTR) aFPath.GetBuffer(),
+ ( nRes & ~FILE_ATTRIBUTE_READONLY ) |
+ ( bRO ? FILE_ATTRIBUTE_READONLY : 0 ) );
+ return ( ULONG_MAX == nRes ) ? ERRCODE_IO_UNKNOWN : 0;
+#endif
+
+#ifdef OS2
+ FILESTATUS3 aFileStat;
+ APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
+ if ( !nRet )
+ {
+ aFileStat.attrFile = ( aFileStat.attrFile & ~FILE_READONLY ) |
+ ( bRO ? FILE_READONLY : 0 );
+ nRet = DosSetPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat), 0 );
+ }
+ switch ( nRet )
+ {
+ case NO_ERROR:
+ return ERRCODE_NONE;
+
+ case ERROR_SHARING_VIOLATION:
+ return ERRCODE_IO_LOCKVIOLATION;
+
+ default:
+ return ERRCODE_IO_NOTEXISTS;
+ }
+#endif
+
+#ifdef UNX
+ /* first, stat the object to get permissions */
+ struct stat aBuf;
+ if (stat(aFPath.GetBuffer(), &aBuf))
+ return ERRCODE_IO_NOTEXISTS;
+ /* set or clear write bit for user */
+ mode_t nMode;
+ if (bRO)
+ {
+ nMode = aBuf.st_mode & ~S_IWUSR;
+ nMode = aBuf.st_mode & ~S_IWGRP;
+ nMode = aBuf.st_mode & ~S_IWOTH;
+ }
+ else
+ nMode = aBuf.st_mode | S_IWUSR;
+ /* change it on fs */
+ if (chmod(aFPath.GetBuffer(), nMode))
+ {
+ switch (errno)
+ {
+ case EPERM :
+ case EROFS :
+ return ERRCODE_IO_ACCESSDENIED;
+ default :
+ return ERRCODE_IO_NOTEXISTS;
+ }
+ }
+ else
+ return ERRCODE_NONE;
+#endif
+ return ERRCODE_IO_NOTSUPPORTED;
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetDateTime
+|*
+|* Ersterstellung PB 27.06.97
+|* Letzte Aenderung
+|*
+*************************************************************************/
+#if defined(WIN) | defined(WNT) | defined(OS2)
+
+void FileStat::SetDateTime( const String& rFileName,
+ const DateTime& rNewDateTime )
+{
+ ByteString aFileName(rFileName, osl_getThreadTextEncoding());
+
+ Date aNewDate = rNewDateTime;
+ Time aNewTime = rNewDateTime;
+#if defined(WIN)
+ unsigned date = 0;
+ unsigned time = 0;
+
+ date = (unsigned) aNewDate.GetDay();
+ date |= (unsigned)(aNewDate.GetMonth() << 5);
+ date |= (unsigned)((aNewDate.GetYear() - 1980) << 9);
+ time = (unsigned)(aNewTime.GetSec() / 2);
+ time |= (unsigned)(aNewTime.GetMin() << 5);
+ time |= (unsigned)(aNewTime.GetHour() << 11);
+
+
+ FILE* pFile = fopen( aFileName.GetBuffer(), "a" );
+
+ if ( pFile != NULL )
+ {
+ _dos_setftime( fileno(pFile), date, time );
+ fclose( pFile );
+ }
+
+#elif defined( WNT )
+
+ TIME_ZONE_INFORMATION aTZI;
+ DWORD dwTZI = GetTimeZoneInformation( &aTZI );
+
+ if ( dwTZI != (DWORD)-1 && dwTZI != TIME_ZONE_ID_UNKNOWN )
+ {
+ // 1. Korrektur der Zeitzone
+ short nDiff = (short)aTZI.Bias;
+ Time aOldTime = aNewTime; // alte Zeit merken
+
+ // 2. evt. Korrektur Sommer-/Winterzeit
+ if ( dwTZI == TIME_ZONE_ID_DAYLIGHT )
+ nDiff += (short)aTZI.DaylightBias;
+
+ Time aDiff( abs( nDiff / 60 /*Min -> Std*/ ), 0 );
+
+ if ( nDiff > 0 )
+ {
+ aNewTime += aDiff; // Stundenkorrektur
+
+ // bei "Uberlauf korrigieren
+ if ( aNewTime >= Time( 24, 0 ) )
+ aNewTime -= Time( 24, 0 );
+
+ // Tages"uberlauf?
+ if ( aOldTime == Time( 0, 0 ) || // 00:00 -> 01:00
+ aNewTime < aOldTime ) // 23:00 -> 00:00 | 01:00 ...
+ aNewDate++;
+ }
+ else if ( nDiff < 0 )
+ {
+ aNewTime -= aDiff; // Stundenkorrektur
+
+ // negative Zeit (-1:00) korrigieren: 23:00
+ if (aNewTime < Time( 0, 0 ) )
+ aNewTime += Time( 24, 0 );
+
+ // Tagesunterlauf ?
+ if ( aOldTime == Time( 0, 0 ) || // 00:00 -> 23:00
+ aNewTime > aOldTime ) // 01:00 -> 23:00 | 22:00 ...
+ aNewDate--;
+ }
+ }
+
+
+ SYSTEMTIME aTime;
+ aTime.wYear = aNewDate.GetYear();
+ aTime.wMonth = aNewDate.GetMonth();
+ aTime.wDayOfWeek = 0;
+ aTime.wDay = aNewDate.GetDay();
+ aTime.wHour = aNewTime.GetHour();
+ aTime.wMinute = aNewTime.GetMin();
+ aTime.wSecond = aNewTime.GetSec();
+ aTime.wMilliseconds = 0;
+ FILETIME aFileTime;
+ SystemTimeToFileTime( &aTime, &aFileTime );
+
+ HANDLE hFile = CreateFile( aFileName.GetBuffer(), GENERIC_WRITE, 0, 0,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
+
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ SetFileTime( hFile, &aFileTime, &aFileTime, &aFileTime );
+ CloseHandle( hFile );
+ }
+
+#endif
+#ifdef OS2
+ // open file
+ ULONG nAction = FILE_EXISTED;
+ HFILE hFile = 0;
+ ULONG nFlags = OPEN_FLAGS_WRITE_THROUGH |
+ OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE |
+ OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT |
+ OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE;
+
+ APIRET nRet = DosOpen((PSZ)aFileName.GetBuffer(), &hFile, (PULONG)&nAction,
+ 0/*size*/, FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ nFlags, 0/*ea*/);
+
+ if ( nRet == 0 )
+ {
+ FILESTATUS3 FileInfoBuffer;
+
+ nRet = DosQueryFileInfo(
+ hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
+
+ if ( nRet == 0 )
+ {
+ FDATE aNewDate;
+ FTIME aNewTime;
+
+ // create date and time words
+ aNewDate.day = rNewDateTime.GetDay();
+ aNewDate.month = rNewDateTime.GetMonth();
+ aNewDate.year = rNewDateTime.GetYear() - 1980;
+ aNewTime.twosecs = rNewDateTime.GetSec() / 2;
+ aNewTime.minutes = rNewDateTime.GetMin();
+ aNewTime.hours = rNewDateTime.GetHour();
+
+ // set file date and time
+ FileInfoBuffer.fdateCreation = aNewDate;
+ FileInfoBuffer.ftimeCreation = aNewTime;
+ FileInfoBuffer.fdateLastAccess = aNewDate;
+ FileInfoBuffer.ftimeLastAccess = aNewTime;
+ FileInfoBuffer.fdateLastWrite = aNewDate;
+ FileInfoBuffer.ftimeLastWrite = aNewTime;
+
+ DosSetFileInfo(hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
+ }
+ DosClose(hFile);
+ }
+#endif
+}
+
+#endif
+/*
+FileStatMembers *FileStat::GetAllMembers()
+{
+ FileStatMembers *members = new FileStatMembers;
+ members->nError = nError;
+ members->nKindFlags = nKindFlags;
+ members->nSize = nSize;
+ members->aCreator = aCreator;
+ members->aType = aType;
+ members->aDateCreated = aDateCreated.GetDate();
+ members->aTimeCreated = aTimeCreated.GetTime();
+ members->aDateAccessed = aDateAccessed.GetDate();
+ members->aTimeAccessed = aTimeAccessed.GetTime();
+ members->aDateModified = aDateModified.GetDate();
+ members->aTimeModified = aTimeModified.GetTime();
+ return members;
+}
+
+void FileStat::InitMembers(FileStatMembers *members)
+{
+ nError = members->nError;
+ members->nKindFlags = nKindFlags;
+ members->nSize = nSize;
+ members->aCreator = aCreator;
+ members->aType = aType;
+ aDateCreated.SetDate(members->aDateCreated);
+ aTimeCreated.SetTime(members->aTimeCreated);
+ aDateAccessed.SetDate(members->aDateAccessed);
+ aTimeAccessed.SetTime(members->aTimeAccessed);
+ aDateModified.SetDate(members->aDateModified);
+ aTimeModified.SetTime(members->aTimeModified);
+}
+*/
+
+
diff --git a/tools/source/fsys/makefile.mk b/tools/source/fsys/makefile.mk
new file mode 100644
index 000000000000..432ad2a1d8c4
--- /dev/null
+++ b/tools/source/fsys/makefile.mk
@@ -0,0 +1,98 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=fsys
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/tempfile.obj \
+ $(SLO)$/wldcrd.obj \
+ $(SLO)$/fstat.obj \
+ $(SLO)$/comdep.obj \
+ $(SLO)$/filecopy.obj \
+ $(SLO)$/dirent.obj \
+ $(SLO)$/tdir.obj \
+ $(SLO)$/urlobj.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/wldcrd.obj \
+ $(OBJ)$/fstat.obj \
+ $(OBJ)$/comdep.obj \
+ $(OBJ)$/filecopy.obj \
+ $(OBJ)$/dirent.obj \
+ $(OBJ)$/tdir.obj \
+ $(OBJ)$/urlobj.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/fsys/os2.cxx b/tools/source/fsys/os2.cxx
new file mode 100644
index 000000000000..f65956b7926e
--- /dev/null
+++ b/tools/source/fsys/os2.cxx
@@ -0,0 +1,1153 @@
+/*************************************************************************
+ *
+ * $RCSfile: os2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define INCL_DOSEXCEPTIONS
+
+#ifdef __BORLANDC__
+#include <alloc.h>
+#else
+#include <malloc.h>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _LIST_HXX
+#include <list.hxx>
+#endif
+#ifndef _BIGINT_HXX
+#include <bigint.hxx>
+#endif
+#ifndef _FSYS_HXX
+#include <fsys.hxx>
+#endif
+#include "comdep.hxx"
+
+#ifdef OS2
+#ifndef _VOS_MUTEX_HXX //autogen
+#include <vos/mutex.hxx>
+#endif
+#endif
+
+int Sys2SolarError_Impl( int nSysErr );
+
+DECLARE_LIST( DirEntryList, DirEntry* );
+DECLARE_LIST( FSysSortList, FSysSort* );
+DECLARE_LIST( FileStatList, FileStat* );
+
+static char sCaseMap[256];
+static BOOL bCaseMap = FALSE;
+static BOOL bDriveMap = FALSE;
+
+struct DriveMapItem
+{
+ DirEntryKind nKind;
+ char cName;
+ FSysPathStyle nStyle;
+};
+
+void CreateCaseMapImpl();
+void CreateDriveMapImpl();
+
+static DriveMapItem aDriveMap[26];
+
+static String sLastCaseSensitiveDir = "";
+static BOOL bLastCaseSensitive = FALSE;
+
+//====================================================================
+
+int ApiRet2ToSolarError_Impl( int nApiRet )
+{
+ switch ( nApiRet )
+ {
+ case NO_ERROR: return ERRCODE_NONE;
+ case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
+ case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_WRITE_PROTECT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_CRC: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_DOS_DISK: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
+ case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_WRONG_DISK: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_HANDLE_DISK_FULL: return ERRCODE_IO_OUTOFSPACE;
+ case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
+ case ERROR_DUP_NAME: return ERRCODE_IO_ALREADYEXISTS;
+ case ERROR_BAD_NETPATH: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_DEV_NOT_EXIST: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_NETWORK_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_INVALID_PARAMETER: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_NET_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_DEVICE_IN_USE: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_DISK_FULL: return ERRCODE_IO_OUTOFSPACE;
+ case ERROR_BAD_ARGUMENTS: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_BAD_PATHNAME: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_LOCK_FAILED: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCKED: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_DUPLICATE_NAME: return ERRCODE_IO_ALREADYEXISTS;
+ case ERROR_DIRECTORY_IN_CDS: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_FILENAME_EXCED_RANGE: return ERRCODE_IO_NAMETOOLONG;
+ }
+
+ DBG_TRACE1( "FSys: unknown apiret error %d occured", nApiRet );
+ return FSYS_ERR_UNKNOWN;
+}
+
+//--------------------------------------------------------------------
+
+DIR *opendir( const char* pPfad )
+{
+ DIR *pDir = new DIR;
+ if ( pDir )
+ pDir->p = (char*) pPfad;
+ return pDir;
+}
+
+struct dirent *readdir( DIR *pDir )
+{
+ APIRET nRet;
+ ULONG nCount = 1;
+ if ( pDir->p )
+ {
+ char *pBuf = new char[ strlen( pDir->p ) + 5 ];
+ if ( pBuf )
+ {
+ // *.* dahinter, ggf mit "\\" abtrennen (falls nicht schon da)
+ strcpy( pBuf, pDir->p );
+ strcat( pBuf, "\\*.*" + ( *(pBuf + strlen( pBuf ) - 1 ) == '\\' ) );
+ pDir->aDirHdl = HDIR_SYSTEM;
+ nRet = DosFindFirst( (PSZ) pBuf, &pDir->aDirHdl, 23,
+ (PVOID) &pDir->aDirEnt, sizeof( FILEFINDBUF3 ),
+ &nCount, FIL_STANDARD );
+ pDir->p = NULL;
+ delete pBuf;
+ }
+ else
+ nRet = 1;
+ }
+ else
+ {
+ nRet = DosFindNext( pDir->aDirHdl,
+ (PVOID) &pDir->aDirEnt, sizeof( pDir->aDirEnt ),
+ &nCount );
+ }
+
+ return !nRet ? &pDir->aDirEnt : NULL;
+}
+
+int closedir( DIR *pDir )
+{
+ if ( pDir )
+ {
+ if ( !pDir->p )
+ DosFindClose( pDir->aDirHdl );
+ delete pDir;
+ }
+ return (pDir != NULL);
+}
+
+typedef struct _FSInfo
+{
+ ULONG nSerial;
+ BYTE nNameLen;
+ UCHAR sName[40];
+} FSInfo;
+
+char* volumeid( const char* pPfad )
+{
+ static FSInfo aFSInfoBuf;
+
+ ULONG ulFSInfoLevel = FSIL_VOLSER;
+ ULONG nDriveNumber;
+
+ nDriveNumber = toupper(*pPfad) - 'A' + 1;
+
+ if ( nDriveNumber >= 3 )
+ {
+ APIRET rc = DosQueryFSInfo(
+ nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSInfo) );
+ if ( rc )
+ return 0;
+ return (char*) aFSInfoBuf.sName;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:30
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if (paVirtualURL)
+ {
+ return TRUE;
+ }
+
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ return TRUE;
+
+ char sBuf[512];
+
+ // Device bestimmen
+ DirEntry* pTop = ImpGetTopPtr();
+ ULONG nDev, nMap;
+ if ( ( pTop->eFlag == FSYS_FLAG_VOLUME || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
+ pTop->aName.Len() )
+ nDev = tolower(aName(0)) - 'a' + 1;
+ else
+ DosQueryCurrentDisk( &nDev, &nMap );
+
+ // das dortige CWD ermitteln;
+ ULONG nLen = sizeof( sBuf ) - 1;
+ DirEntry *pCWD = 0;
+ DosQueryCurrentDir( nDev, (PSZ) sBuf, &nLen );
+ if ( sBuf[0] == 0 )
+ strcpy( sBuf, "\\" );
+ else
+ pCWD = new DirEntry( String( sBuf ) );
+
+ // das Device voranstellen
+ String aTempStr( (char)(nDev + 'a' - 1) );
+ aTempStr += ':';
+ if ( pCWD )
+ pCWD->ImpGetTopPtr()->pParent =
+ new DirEntry( aTempStr, FSYS_FLAG_ABSROOT, DEFSTYLE );
+ else
+ pCWD = new DirEntry( aTempStr, FSYS_FLAG_ABSROOT, DEFSTYLE );
+
+ // die relative Root durch ihr aktuelles Verzeichnis ersetzen
+ if ( pTop == this &&
+ ( pTop->eFlag == FSYS_FLAG_RELROOT || pTop->eFlag == FSYS_FLAG_VOLUME ) )
+ {
+ *pTop = *pCWD;
+ delete pCWD;
+ }
+ else if ( pTop->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ pTop->aName = aTempStr;
+ delete pCWD;
+ }
+ else
+ {
+ // dir\\..-Sequenzen aufloesen
+ while ( (pTop = ImpGetTopPtr())->eFlag == FSYS_FLAG_PARENT &&
+ pTop != this )
+ {
+ pCWD->CutName();
+ ImpGetPreTopPtr()->pParent = 0;
+ delete pTop;
+ }
+
+ // Pfad davorhaengen
+ if ( pTop == this && eFlag == FSYS_FLAG_PARENT )
+ {
+ *this = pCWD->GetPath();
+ delete pCWD;
+ }
+ else
+ ImpGetTopPtr()->pParent = pCWD;
+ }
+
+ return IsAbs();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.03.92
+|* Letzte Aenderung MI 04.03.92
+|*
+*************************************************************************/
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTop = ImpGetTopPtr();
+
+ if ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME )
+ {
+ const char *pVol;
+ pVol = volumeid( (char*) pTop->aName.GetStr() );
+ return FSYS2GUI( String( pVol ? pVol : "" ) );
+ }
+
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy )
+{
+ if (paVirtualURL)
+ {
+ String aTempString(GetRealPathFromVirtualURL());
+ if (aTempString.Len()==0)
+ {
+ return FALSE;
+ }
+ DirEntry aTempDirEntry(aTempString);
+ return aTempDirEntry.SetCWD(bSloppy);
+ }
+
+ // is the device to be changed?
+ DirEntry *pTop = ImpGetTopPtr();
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT || pTop->eFlag == FSYS_FLAG_VOLUME )
+ && pTop->aName.Len() )
+ if ( DosSetDefaultDisk( pTop->aName.Lower()(0)-'a'+1 ) )
+ return FALSE;
+
+ APIRET nRet = DosSetCurrentDir( (PSZ) (const char *) GetFull() );
+ if ( nRet && bSloppy )
+ nRet = DosSetCurrentDir( (PSZ) (const char *) GetPath().GetFull() );
+ return !nRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MoveTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 14:07
+|*
+*************************************************************************/
+
+BOOL createLongNameEA( const PCSZ pszPath, ULONG ulAttributes, const String& aLongName );
+
+FSysError DirEntry::MoveTo( const DirEntry& rDest ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aTmpDest(rDest);
+ FileStat aTmpStat(aTmpDest);
+ if ( aTmpStat.IsKind(FSYS_KIND_DIR) )
+ aTmpDest += DirEntry( GetName() );
+
+ String aSource( GetFull() );
+ String aDest( aTmpDest.GetFull() );
+ String aShortSource("");
+ String aShortDest("");
+
+ if (Folder::IsAvailable())
+ {
+ if (IsLongNameOnFAT())
+ {
+ // in kurzen Pfad wandeln
+ ItemIDPath aItemIDPath(aSource);
+ aShortSource = aItemIDPath.GetHostNotationPath();
+ }
+ if (rDest.IsLongNameOnFAT())
+ {
+ // in kurzen Pfad wandeln
+ ItemIDPath aItemIDPath(aDest);
+ aShortDest = aItemIDPath.GetHostNotationPath();
+ }
+ }
+
+ APIRET nRet = DosMove( aShortSource.Len()>0?(PSZ)aShortSource.GetStr():(PSZ)aSource.GetStr(),
+ aShortDest.Len()>0?(PSZ)aShortDest.GetStr():(PSZ)aDest.GetStr());
+
+ if ( nRet == ERROR_DIRECTORY_IN_CDS ||
+ nRet == ERROR_CURRENT_DIRECTORY )
+ {
+ // 2nd chance with modified CWD
+ DosSetCurrentDir( (PSZ) "\\" );
+ nRet = DosMove( aShortSource.Len()>0?(PSZ)aShortSource.GetStr():(PSZ)aSource.GetStr(),
+ aShortDest.Len()>0?(PSZ)aShortDest.GetStr():(PSZ)aDest.GetStr());
+ }
+ else if ( nRet == ERROR_NOT_SAME_DEVICE )
+ {
+ // other volume => copy+delete
+ FileCopier aMover( *this, rDest );
+ nRet = aMover.Execute( FSYS_ACTION_MOVE|FSYS_ACTION_RECURSIVE );
+ return nRet;
+ }
+
+ if ( (nRet==NO_ERROR) && aShortDest.Len()>0)
+ {
+ createLongNameEA((const char*)aShortDest, FILE_NORMAL, rDest.GetName());
+ }
+
+ return ApiRet2ToSolarError_Impl( nRet );
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ USHORT nRead = 0;
+ if ( pDir->eAttrMask & FSYS_KIND_BLOCK )
+ {
+ CreateDriveMapImpl();
+ DirEntry aCurrentDir;
+ aCurrentDir.ToAbs();
+ char sDrive[3] = "?:";
+
+ for ( char c = START_DRV; c <= 'z'; c++ )
+ {
+ sDrive[0] = c;
+ DirEntry* pDrive = new DirEntry( sDrive,
+ FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ if ( aDriveMap[c-'a'].nKind != FSYS_KIND_UNKNOWN &&
+ pDir->aNameMask.Matches( sDrive ) )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( *pDrive );
+ pDir->ImpSortedInsert( pDrive, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pDrive, NULL );
+ ++nRead;
+ }
+ else
+ delete pDrive;
+ }
+
+ aCurrentDir.SetCWD();
+
+ }
+
+// OS2 ist beim Directory auslesen nicht threadfest
+#ifdef OS2
+ static NAMESPACE_VOS( OMutex )* pMutex = 0;
+ if( !pMutex ) pMutex = new NAMESPACE_VOS( OMutex );
+ NAMESPACE_VOS( OGuard ) aGuard( pMutex );
+#endif
+ // Workaround: kein async-read, da OS/2 dann nix mehr liefert
+ for ( USHORT nLastRead; nLastRead = Read(); )
+ nRead += nLastRead;
+
+ return nRead;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+ ( pDosEntry->d_type & DOS_DIRECT ) ) ||
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ !( pDosEntry->d_type & DOS_DIRECT ) ) ) &&
+ pDir->aNameMask.Matches(
+ ToLowerImpl( String( pDosEntry->d_name ) ) ) )
+ {
+ String aName( FSYS2GUI( pDosEntry->d_name ) );
+ DirEntryFlag eFlag =
+ aName == "." ? FSYS_FLAG_CURRENT
+ : aName == ".." ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( String( aName ),
+ eFlag, FSYS_STYLE_NTFS );
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE );
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( (void*) pDosDir, (void*) 0 );
+ pDir->ImpSortedInsert( pTemp, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );
+ return 1;
+ }
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *pInfo, // struct dirent
+ const void * ): // dummy
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+ paVirtualURL = NULL;
+
+ struct dirent *pDirent = (struct dirent*) pInfo;
+
+ nSize = pDirent->d_size;
+
+ aDateCreated = MsDos2Date( pDirent->d_date );
+ aTimeCreated = MsDos2Time( pDirent->d_time );
+ aDateModified = aDateModified;
+ aTimeModified = aTimeModified;
+ aDateAccessed = aDateModified;
+ aTimeAccessed = aTimeModified;
+
+ nKindFlags = FSYS_KIND_FILE;
+ if ( pDirent->d_type & DOS_DIRECT )
+ nKindFlags = FSYS_KIND_DIR;
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+struct _FSYS_FSQBUFFER
+{
+ FSQBUFFER2 aBuf;
+ UCHAR sBuf[256];
+};
+
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL bAccessRemovableDevice )
+{
+ paVirtualURL = rDirEntry.paVirtualURL;
+
+ nSize = 0;
+ FSysPathStyle eStyle = FSYS_STYLE_UNKNOWN;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if (paVirtualURL)
+ {
+ if (rDirEntry.GetRealPathFromVirtualURL().Len()==0)
+ {
+ // keine reale repräsentation für VirtualURL, also alles setzen,
+ // lediglich dir/file unterscheidbar
+ nKindFlags = FSYS_KIND_ALL;
+
+ if (Folder(ItemIDPath(rDirEntry.GetFull())).IsValid()) //ist dir?
+ {
+ nKindFlags &= ~FSYS_KIND_FILE; //ja, also kein file
+ }
+ else
+ {
+ nKindFlags &= ~FSYS_KIND_DIR; //nein, also kein dir
+ }
+
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+ }
+
+ nError = rDirEntry.IsValid() ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN;
+ if ( nError > FSYS_ERR_OK )
+ return FALSE;
+
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ String aTempName( rDirEntry.GetName() );
+ if ( strchr( (char*) (const char*) aTempName, '?' ) ||
+ strchr( (char*) (const char*) aTempName, '*' ) ||
+ strchr( (char*) (const char*) aTempName, ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root handelt
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME ||
+ rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = FSYS_KIND_DEV;
+ else
+ nKindFlags = FSYS_KIND_DIR;
+
+ if ( rDirEntry.aName.Len() == 2 )
+ {
+ if ( !bDriveMap )
+ CreateDriveMapImpl();
+
+ DriveMapItem &rItem = aDriveMap[toupper(rDirEntry.aName[0]) - 'A'];
+ if ( !rItem.nKind )
+ {
+ nError = ERRCODE_IO_INVALIDDEVICE;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ return FALSE;
+ }
+ else
+ {
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags |= FSYS_KIND_BLOCK | rItem.nKind;
+ eStyle = rItem.nStyle;
+ }
+ }
+
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // disable error-boxes for hard-errors
+ DosError(FERR_DISABLEHARDERR);
+
+ // Statusinformation vom Betriebssystem holen
+ DirEntry aTempDirEntry( rDirEntry );
+ char* p;
+ String aFullName;
+
+ aTempDirEntry.ToAbs();
+ aFullName = aTempDirEntry.GetFull();
+
+ if (aTempDirEntry.paVirtualURL)
+ {
+ aFullName = rDirEntry.GetRealPathFromVirtualURL();
+ }
+
+ if (Folder::IsAvailable() && aTempDirEntry.IsLongNameOnFAT())
+ {
+ // in String mit kurzem Pfad wandeln
+ ItemIDPath aItemIDPath(aTempDirEntry.GetFull());
+ aFullName = aItemIDPath.GetHostNotationPath();
+ }
+
+ p = (char *) aFullName.GetStr();
+
+ FILESTATUS3 filestat;
+ memset( &filestat, 0, sizeof( filestat ) );
+ if( DosQueryPathInfo( (PSZ)p, 1, &filestat, sizeof( filestat ) ) )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ return FALSE;
+ }
+
+ nError = FSYS_ERR_OK;
+ nSize = filestat.cbFile;
+
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ if( filestat.attrFile & FILE_DIRECTORY )
+ nKindFlags |= FSYS_KIND_DIR;
+ if ( nKindFlags == FSYS_KIND_UNKNOWN )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+
+ aDateModified = Date( filestat.fdateLastWrite.day,
+ filestat.fdateLastWrite.month,
+ filestat.fdateLastWrite.year + 1980 );
+
+ aTimeModified = Time( filestat.ftimeLastWrite.hours,
+ filestat.ftimeLastWrite.minutes,
+ filestat.ftimeLastWrite.twosecs*2 );
+
+ if ( filestat.fdateCreation.day )
+ {
+ aDateCreated = Date( filestat.fdateCreation.day,
+ filestat.fdateCreation.month,
+ filestat.fdateCreation.year + 1980 );
+
+ aTimeCreated = Time( filestat.ftimeCreation.hours,
+ filestat.ftimeCreation.minutes,
+ filestat.ftimeCreation.twosecs*2 );
+ }
+ else
+ {
+ aDateCreated = aDateModified;
+ aTimeCreated = aTimeModified;
+ }
+
+ if ( filestat.fdateLastAccess.day > 0 )
+ {
+ aDateAccessed = Date( filestat.fdateLastAccess.day,
+ filestat.fdateLastAccess.month,
+ filestat.fdateLastAccess.year + 1980 );
+
+ aTimeAccessed = Time( filestat.ftimeLastAccess.hours,
+ filestat.ftimeLastAccess.minutes,
+ filestat.ftimeLastAccess.twosecs*2 );
+ }
+ else
+ {
+ aDateAccessed = aDateModified;
+ aTimeAccessed = aTimeModified;
+ }
+
+ return TRUE;
+}
+
+#if SUPD>364
+BOOL IsRedirectable_Impl( const String &rPath )
+{
+ if ( rPath.Len() >= 3 && ':' == rPath.GetStr()[1] )
+ {
+ DriveMapItem &rItem = aDriveMap[toupper(rPath[0]) - 'A'];
+ return FSYS_KIND_FIXED != rItem.nKind;
+ }
+ return FALSE;
+}
+#endif
+
+const char* TempDirImpl( char *pBuf )
+{
+#if defined( __BORLANDC__ ) && (__BORLANDC__ < 0x0460)
+ PSZ pVar;
+#else
+ PCSZ pVar;
+#endif
+ USHORT nRet;
+ BOOL bAppendTemp = FALSE; // mu\s noch \\temp angeh"angt werden
+
+ // Erstmal sehen, ob TEMP oder TMP gesetzt sind
+ nRet = DosScanEnv( (PSZ)"TEMP", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"temp", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"TMP", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"tmp", &pVar );
+
+ // falls das geklappt hat, und ein Backslash dranhaengt,
+ // oder falls es bisher nicht geklappt hat,
+ // muessen wir nachher einen Backslash entfernen
+ BOOL bRemoveBS = nRet || *(pVar+strlen(pVar)-1) == '\\';
+
+ // Keine temp-Variable gefunden, dann gehen wir mal auf die Suche
+ // nach dem System-Laufwerk
+ if( nRet )
+ {
+ nRet = DosScanEnv( (PSZ)"USER_INI",&pVar );
+ bAppendTemp = (0 == nRet);
+ }
+ if( nRet )
+ {
+ nRet = DosScanEnv( (PSZ)"SYSTEM_INI", &pVar );
+ bAppendTemp = (0 == nRet);
+ }
+ if( nRet )
+ // Wenn das immer noch nicht reicht nehmen wir eben die Root von C:
+#ifdef __BORLANDC__
+ pVar = (PSZ)"c:\\temp\\";
+#else
+ pVar = (PCSZ)"c:\\temp\\";
+#endif
+ strcpy( pBuf, (const char*)pVar );
+
+ // jetzt haengt ggf. ein Backlash dran, den wir abschneiden,
+ // ggf. inklusive dahinter haengendem Dateinamen
+ if ( bRemoveBS )
+ {
+ char *pTail = pBuf + strlen(pBuf) - 1;
+ for ( char cLast = *pTail; cLast != '\\'; cLast = *(--pTail) )
+ *pTail = 0;
+ }
+
+ if ( bAppendTemp )
+ strcat( pBuf, "\\temp" );
+ DirEntry( pBuf ).MakeDir();
+
+ return pBuf;
+}
+
+#define CURRENT_COUNTRY 0
+#define NLS_CODEPAGE 850
+
+/*====================================================================
+ * CreateCaseMapImpl()
+ * creates a map of each character to convert to lower
+ *--------------------------------------------------------------------*/
+
+void CreateCaseMapImpl()
+{
+ // build a string starting with code 0 as first character upto 255
+ char sTemp[256];
+ for ( USHORT n = 0; n < 256; ++n )
+ sTemp[n] = (char) n;
+
+ // convert string to upper case
+ COUNTRYCODE aCountry;
+ aCountry.country = CURRENT_COUNTRY; /* Country code */
+ aCountry.codepage = NLS_CODEPAGE; /* Code page */
+ DosMapCase( 255, &aCountry, sTemp+1 );
+
+ // fill a global buffer starting with code 0 as first character upto 255
+ for ( n = 0; n < 256; ++n )
+ sCaseMap[n] = (char) n;
+
+ // reorder by upper-code and store in a global buffer
+ for ( n = 255; n > 0; --n )
+ // was this character converted?
+ if ( sTemp[n] != (char) n )
+ // we found a convertion from upper to lower
+ sCaseMap[ (unsigned char) sTemp[n] ] = (char) n;
+
+ bCaseMap = TRUE;
+}
+
+String ToLowerImpl( const String& rSource )
+{
+ if ( !bCaseMap )
+ CreateCaseMapImpl();
+
+ // TH sagt: International ist zu langsam, also mit einer eigenen Map
+ String aLower( rSource );
+ for ( USHORT n = 0; n < aLower.Len(); ++n )
+ aLower[n] = sCaseMap[ (unsigned char) aLower[n] ];
+ return aLower;
+}
+
+/*====================================================================
+ * CreateDriveMapImpl()
+ * creates a map of drive-infos like FileSystem (style) and Kind (remote)
+ *--------------------------------------------------------------------*/
+
+typedef struct _FSQBUFFER_
+{
+ FSQBUFFER2 aBuf;
+ UCHAR sBuf[64];
+} FSQBUFFER_;
+
+void CreateDriveMapImpl()
+{
+#ifdef POWERPC
+ // !!!!! Hack, da der untere Teil mit Beta 2 noch abstuertzt !!!!!
+ BYTE nFloppies = 1;
+ for ( USHORT nDrive = 0; nDrive < 26; ++nDrive )
+ {
+ if ( nDrive < nFloppies )
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
+ }
+ else
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
+ }
+ }
+
+ aDriveMap[2].nKind = FSYS_KIND_FIXED;
+ aDriveMap[2].nStyle = FSYS_STYLE_FAT;
+#else
+ FSQBUFFER_ aBuf;
+ ULONG nBufLen;
+ APIRET nRet;
+
+ // disable error-boxes for hard-errors
+ DosError(FERR_DISABLEHARDERR);
+
+ // determine number of floppy-drives
+ BYTE nFloppies;
+ nRet = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
+
+ // reset the map
+ for ( USHORT nDrive = 0; nDrive < 26; ++nDrive )
+ {
+ if ( nDrive < nFloppies )
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
+ }
+ else
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
+ }
+ }
+
+ // determine file-system via DosOpen/DocDevIOCtrl
+ for ( nDrive = 2; nDrive < 26; ++nDrive )
+ {
+ // open drive
+ BOOL bFixed;
+ HFILE nDevHandle;
+ char pDriveName[3] = "#:";
+ pDriveName[0] = nDrive+'a';
+ ULONG nAction;
+ nRet = DosOpen( (PSZ) pDriveName, &nDevHandle,
+ &nAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_FLAGS_DASD|OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY,
+ 0 );
+
+ // exists?
+ if ( !nRet )
+ {
+ // removeable?
+ BYTE nDriveId = nDrive;
+ ULONG nParaOutLen, nDataOutLen;
+ nRet = DosDevIOCtl(nDevHandle, 8, 0x20,
+ &nDriveId, sizeof(nDriveId), &nParaOutLen,
+ &bFixed, sizeof(bFixed), &nDataOutLen );
+
+ // prepare the drive-map
+ if ( !nRet && !bFixed )
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+
+ // close drive
+ DosClose(nDevHandle);
+ }
+ else if ( nRet == ERROR_NOT_READY )
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE | FSYS_KIND_CDROM;
+ }
+
+ // determine file-system via FSAttach
+ nRet = 0;
+ for ( USHORT n = 3; nRet != ERROR_NO_MORE_ITEMS; ++n )
+ {
+ nBufLen = sizeof( aBuf );
+ nRet = DosQueryFSAttach( 0, n, FSAIL_DRVNUMBER,
+ (_FSQBUFFER2*) &aBuf, &nBufLen );
+ if ( !nRet )
+ {
+ nDrive = toupper(aBuf.aBuf.szName[0]) - 'A';
+
+ if ( aDriveMap[nDrive].nKind == FSYS_KIND_UNKNOWN )
+ aDriveMap[nDrive].nKind =
+ aBuf.aBuf.iType == 3 ? FSYS_KIND_FIXED :
+ aBuf.aBuf.iType == 4 ? FSYS_KIND_REMOTE :
+ FSYS_KIND_UNKNOWN;
+
+ char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1);
+ aDriveMap[nDrive].nStyle =
+ strcmp( pType, "FAT" ) == 0 ? FSYS_STYLE_FAT :
+ strcmp( pType, "HPFS" ) == 0 ? FSYS_STYLE_HPFS :
+ strcmp( pType, "NWFS" ) == 0 ? FSYS_STYLE_NWFS :
+ strcmp( pType, "EXT2" ) == 0 ? FSYS_STYLE_UNX :
+ strcmp( pType, "NFS" ) == 0 ? FSYS_STYLE_UNX :
+ FSYS_STYLE_UNKNOWN;
+ if ( strcmp( pType, "CDFS" ) == 0 )
+ aDriveMap[nDrive].nKind = FSYS_KIND_CDROM|FSYS_KIND_REMOVEABLE;
+ }
+ }
+#endif
+
+ bDriveMap = TRUE;
+}
+
+Time MsDos2Time( const time_t *pTimeT )
+{
+ tm *pTm = localtime( pTimeT );
+ if ( pTm )
+ return Time( pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
+ else
+ return Time(0);
+}
+
+Date MsDos2Date( const time_t *pTimeT )
+{
+ tm *pTm = localtime( pTimeT );
+ if ( pTm )
+ return Date( pTm->tm_mday, pTm->tm_mon + 1, pTm->tm_year );
+ else
+ return Date(0);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
+{
+ // UNC-Pathname?
+ if ( !rDevice || ( rDevice.Len() > 1 && rDevice[ (USHORT) 1] != ':' ) )
+ return FSYS_STYLE_UNKNOWN;
+
+ if ( !bDriveMap )
+ CreateDriveMapImpl();
+ return aDriveMap[toupper(rDevice[0]) - 'A'].nStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsCaseSensitive() const
+|*
+|* Beschreibung
+|* Ersterstellung TPF 26.02.1999
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+ if (GetPathStyle(GetDevice().GetName()) == FSYS_STYLE_UNX)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ BOOL isCaseSensitive = FALSE; // ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = FALSE; // ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+
+
+
+//=========================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &rPath,
+ BigInt &rFreeBytes, BigInt &rTotalBytes )
+{
+ FSALLOCATE aFSInfoBuf;
+ String aVolume( DirEntry(rPath).ImpGetTopPtr()->GetName() );
+ ULONG nDriveNumber = toupper( aVolume(0) ) - 'A' + 1;
+
+ APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC,
+ &aFSInfoBuf, sizeof(aFSInfoBuf) );
+ if ( rc )
+ return Sys2SolarError_Impl( rc );
+
+ BigInt aBytesPerCluster( BigInt(aFSInfoBuf.cbSector) *
+ BigInt(aFSInfoBuf.cSectorUnit) );
+ rFreeBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnitAvail);
+ rTotalBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnit);
+ return 0;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL bEnable )
+{
+ DosError( bEnable ? 0 : FERR_DISABLEHARDERR );
+}
+
diff --git a/tools/source/fsys/os2.hxx b/tools/source/fsys/os2.hxx
new file mode 100644
index 000000000000..bc03d0e21582
--- /dev/null
+++ b/tools/source/fsys/os2.hxx
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * $RCSfile: os2.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _os2_hxx
+#define _os2_hxx
+
+#include <string.h>
+
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSFILEMGR
+#define INCL_DOSPROCESS
+#define INCL_DOSDEVICES
+#define INCL_DOSERRORS
+#define INCL_DOSMISC
+#define INCL_DOSNLS /* National Language Support values */
+#include <svpm.h>
+
+#include <string.hxx>
+
+#define FSYS_UNIX FALSE
+
+#define DOS_DIRECT 16
+#define setdrive(n,a) dos_setdrive(n,a)
+#define GETDRIVE(n) dos_getdrive(&n)
+
+#define _mkdir(p) DosCreateDir( (PSZ)p, 0 )
+#define _rmdir(p) DosDeleteDir( (PSZ)p )
+#define _unlink(p) DosForceDelete( (PSZ)p )
+#define _chdir chdir
+#define _getcwd getcwd
+#define _access access
+
+const char* TempDirImpl( char *pBuf );
+String ToLowerImpl( const String& );
+
+inline char *getcwd(char *p, ULONG nLen )
+{
+ return DosQueryCurrentDir( 0, (PBYTE)p, &nLen ) ? p : 0;
+}
+
+#define dirent _FILEFINDBUF3
+#define d_name achName
+#define d_type attrFile
+#define d_size cbFile
+#define d_attr attrFile
+#define d_date fdateLastWrite
+#define d_time ftimeLastWrite
+
+typedef struct
+{
+ HDIR aDirHdl;
+ FILEFINDBUF3 aDirEnt;
+ char *p;
+} DIR;
+
+#define DEFSTYLE FSYS_STYLE_OS2
+#define MKDIR( p ) mkdir( (unsigned char*) p )
+#define CMP_LOWER(aString) ToLowerImpl(aString)
+
+#define START_DRV 'a'
+
+inline BOOL DRIVE_EXISTS( char c )
+{
+ ULONG nCur, nMap;
+ APIRET nRet = DosQueryCurrentDisk( &nCur, &nMap );
+ return ( nMap & 1 << (c - 'a') ) != 0;
+}
+
+#include <time.h>
+#include <datetime.hxx>
+
+inline Time MsDos2Time( FTIME aTime )
+{
+ return Time( aTime.hours, aTime.minutes, 2*aTime.twosecs );
+}
+
+inline Date MsDos2Date( FDATE aDate )
+{
+ return Date( aDate.day, aDate.month, aDate.year );
+}
+
+Time MsDos2Time( const time_t *pTimeT );
+
+Date MsDos2Date( const time_t *pTimeT );
+
+#define FSysFailOnErrorImpl()
+
+#endif
diff --git a/tools/source/fsys/tdir.cxx b/tools/source/fsys/tdir.cxx
new file mode 100644
index 000000000000..021bed1f196e
--- /dev/null
+++ b/tools/source/fsys/tdir.cxx
@@ -0,0 +1,808 @@
+/*************************************************************************
+ *
+ * $RCSfile: tdir.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _DIR_CXX
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _LIST_HXX
+#include <list.hxx>
+#endif
+
+#ifndef _COMPED_HXX
+#include "comdep.hxx"
+#endif
+#ifndef _FSYS_HXX
+#include <fsys.hxx>
+#endif
+
+
+DBG_NAME( Dir );
+
+DECLARE_LIST( DirEntryList, DirEntry* );
+DECLARE_LIST( FSysSortList, FSysSort* );
+DECLARE_LIST( FileStatList, FileStat* );
+
+#define APPEND (USHORT) 65535
+
+/*************************************************************************
+|*
+|* Dir::InsertPointReached()
+|*
+|* Beschreibung stellt fest, ob eingefuegt werden musz
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+BOOL Dir::ImpInsertPointReached( const DirEntry& rNewEntry,
+ const FileStat& rNewStat,
+ ULONG nCurPos, ULONG nSortIndex ) const
+{
+#define VALUE( nKindFlags ) \
+ ( ( FSYS_KIND_FILE | FSYS_KIND_DIR | FSYS_KIND_DEV | \
+ FSYS_KIND_CHAR | FSYS_KIND_BLOCK ) & nKindFlags )
+
+ // einfache Dinge erfordern einfache Loesungen
+ if ( !pLst->Count() )
+ return TRUE;
+
+ FSysSort nSort = *( pSortLst->GetObject( nSortIndex ) );
+ FileStat *pOldStat = NULL;
+ DirEntry *pCurLstObj = pLst->GetObject( nCurPos );
+ if ( pStatLst )
+ pOldStat = pStatLst->GetObject( nCurPos );
+
+ switch( nSort )
+ {
+ case FSYS_SORT_NAME:
+ case (FSYS_SORT_NAME | FSYS_SORT_ASCENDING):
+ if ( pCurLstObj->aName > rNewEntry.aName )
+ return TRUE;
+ if ( !(pCurLstObj->aName == rNewEntry.aName) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_NAME | FSYS_SORT_DESCENDING):
+ if ( pCurLstObj->aName < rNewEntry.aName )
+ return TRUE;
+ if ( !(pCurLstObj->aName == rNewEntry.aName) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_EXT:
+ case (FSYS_SORT_EXT | FSYS_SORT_ASCENDING):
+ {
+ if ( pCurLstObj->GetExtension() > rNewEntry.GetExtension() )
+ return TRUE;
+ if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
+ return FALSE;
+ break;
+ }
+ case (FSYS_SORT_EXT | FSYS_SORT_DESCENDING):
+ {
+ if ( pCurLstObj->GetExtension() < rNewEntry.GetExtension() )
+ return TRUE;
+ if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
+ return FALSE;
+ break;
+ }
+
+ case FSYS_SORT_KIND:
+ case (FSYS_SORT_KIND | FSYS_SORT_ASCENDING ):
+ if ( VALUE(pOldStat->nKindFlags) > VALUE(rNewStat.nKindFlags) )
+ return TRUE;
+ if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_KIND | FSYS_SORT_DESCENDING):
+ if ( VALUE(pOldStat->nKindFlags) < VALUE(rNewStat.nKindFlags) )
+ return TRUE;
+ if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_SIZE:
+ case (FSYS_SORT_SIZE | FSYS_SORT_ASCENDING):
+ if ( pOldStat->nSize > rNewStat.nSize )
+ return TRUE;
+ if ( !(pOldStat->nSize == rNewStat.nSize) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_SIZE | FSYS_SORT_DESCENDING):
+ if ( pOldStat->nSize < rNewStat.nSize )
+ return TRUE;
+ if ( !(pOldStat->nSize == rNewStat.nSize) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_MODIFYED:
+ case (FSYS_SORT_MODIFYED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateModified >= rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified > rNewStat.aTimeModified) )
+ return TRUE;
+ if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_MODIFYED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateModified <= rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified < rNewStat.aTimeModified) )
+ return TRUE;
+ if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_CREATED:
+ case (FSYS_SORT_CREATED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateCreated >= rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated > rNewStat.aTimeCreated) )
+ return TRUE;
+ if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_CREATED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateCreated <= rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated < rNewStat.aTimeCreated) )
+ return TRUE;
+ if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_ACCESSED:
+ case (FSYS_SORT_ACCESSED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateAccessed >= rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed > rNewStat.aTimeAccessed) )
+ return TRUE;
+ if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_ACCESSED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateAccessed <= rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed < rNewStat.aTimeAccessed) )
+ return TRUE;
+ if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
+ return FALSE;
+ break;
+ default: /* Kann nicht sein */;
+ }
+
+ if ( nSortIndex == ( pSortLst->Count() - 1 ) )
+ return TRUE;
+ else
+ //Rekursion
+ return ImpInsertPointReached( rNewEntry, rNewStat,
+ nCurPos, nSortIndex + 1 );
+#undef VALUE
+}
+
+/*************************************************************************
+|*
+|* Dir::ImpSortedInsert()
+|*
+|* Beschreibung fuegt sortiert ein
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 03.12.91
+|*
+*************************************************************************/
+
+void Dir::ImpSortedInsert( const DirEntry *pNewEntry, const FileStat *pNewStat )
+{
+ //Sonderfall, keine Sortierung gewuenscht.
+ if ( !pSortLst ) {
+ pLst->Insert( (DirEntry*)pNewEntry, APPEND );
+ return;
+ }
+
+ pLst->First();
+ do {
+ if ( ImpInsertPointReached( *pNewEntry, *pNewStat, pLst->GetCurPos(),
+ (ULONG)0 ) )
+ {
+ if ( pStatLst )
+ pStatLst->Insert( (FileStat*)pNewStat, pLst->GetCurPos() );
+ pLst->Insert( (DirEntry*)pNewEntry );
+ return;
+ }
+ } while( pLst->Next() );
+
+ if ( pStatLst )
+ pStatLst->Insert( (FileStat*)pNewStat, APPEND );
+ pLst->Insert( (DirEntry*)pNewEntry, APPEND );
+}
+
+/*************************************************************************
+|*
+|* Dir::Construct()
+|*
+|* Beschreibung gemeinsame Implementation der Ctoren
+|* Ersterstellung MI 02.06.93
+|* Letzte Aenderung MI 02.06.93
+|*
+*************************************************************************/
+
+void Dir::Construct( DirEntryKind nKindFlags )
+{
+ pLst = NULL;
+ pSortLst = NULL;
+ pStatLst = NULL;
+ eAttrMask = nKindFlags;
+ ByteString aTempName( GetName(), osl_getThreadTextEncoding() );
+ if ( aTempName.Search( "*" ) != STRING_NOTFOUND ||
+ aTempName.Search( "?" ) != STRING_NOTFOUND )
+#if defined( WNT ) && !defined( WTC )
+ {
+ ByteString aTStr(CutName(), osl_getThreadTextEncoding());
+ char* pBuffer = new char[aTStr.Len()+1];
+ strcpy( pBuffer, aTStr.GetBuffer() );
+ CharLowerBuff( pBuffer, aTStr.Len() );
+ aNameMask = WildCard( String(pBuffer, osl_getThreadTextEncoding()), ';' );
+ delete pBuffer;
+ }
+#else
+ aNameMask = WildCard( CutName(), ';' );
+#endif
+ else
+ aNameMask = String("*", osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* Dir::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 19.09.96
+|*
+*************************************************************************/
+
+BOOL Dir::Update()
+{
+ Reset();
+ return Scan( USHRT_MAX ) > 0;
+}
+
+/*************************************************************************
+|*
+|* Dir::Reset()
+|*
+|* Beschreibung
+|* Ersterstellung MI 22.10.96
+|* Letzte Aenderung MI 22.10.96
+|*
+*************************************************************************/
+
+void Dir::Reset()
+{
+ // ggf. alten Reader l"oschen
+ if ( pReader && pReader->bInUse )
+ DELETEZ(pReader);
+
+ // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
+ if ( pLst )
+ {
+ DirEntry* pEntry = pLst->First();
+ while (pEntry)
+ {
+ DirEntry* pNext = pLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pLst->Clear();
+ }
+ else
+ pLst = new DirEntryList();
+
+ // Alte File-Stat's Loeschen
+ if ( pStatLst )
+ {
+ //Erstmal die alten Loeschen
+ FileStat* pEntry = pStatLst->First();
+ while (pEntry)
+ {
+ FileStat* pNext = pStatLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pStatLst->Clear();
+ delete pStatLst;
+ }
+
+ // Verlangen die Sortierkriterien FileStat's?
+ if ( pSortLst )
+ {
+ pSortLst->First();
+ do
+ {
+ if ( *( pSortLst->GetCurObject() ) &
+ ( FSYS_SORT_KIND | FSYS_SORT_SIZE |
+ FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_ACCESSED ) )
+ pStatLst = new FileStatList();
+ } while ( !pStatLst && pSortLst->Next() );
+ }
+
+#ifndef BOOTSTRAP
+ // ggf. einen neuen Reader aufsetzen
+ if ( !pReader )
+ pReader = new DirReader_Impl( *this );
+#endif
+
+ // gibt es das zu oeffnende Verzeichnis ueberhaupt?
+#ifndef UNX //explanation: see DirReader_Impl::Read() in unx.cxx
+ if( !pReader->pDosDir )
+ {
+ nError = FSYS_ERR_NOTADIRECTORY;
+ DELETEZ( pReader );
+ return;
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* Dir::Scan()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 18.09.96
+|* Letzte Aenderung MI 19.09.96
+|*
+*************************************************************************/
+
+USHORT Dir::Scan( USHORT nCount )
+{
+
+ USHORT nRead = 0; // Anzahl in dieser Runde gelesener Eintr"age
+ FSysFailOnErrorImpl();
+
+ // noch nicht fertig gewesen
+ if ( pReader )
+ {
+ // frischer Reader?
+ if ( !pLst->Count() )
+ {
+ // dann ggf. Laufwerke scannen
+ pReader->bInUse = TRUE;
+ nRead = pReader->Init();
+ }
+
+ // weiterlesen...
+ while ( nRead <= nCount && !pReader->bReady )
+ nRead += pReader->Read();
+
+ // fertig?
+ if ( pReader && pReader->bReady )
+ DELETEZ( pReader );
+ }
+
+ // Anzahl der gelesenen zur"uckgeben
+ return nRead;
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 04.03.92
+|*
+*************************************************************************/
+
+Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags, FSysSort nSort, ... ):
+ DirEntry( rDirEntry ),
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ Construct( nKindFlags );
+
+ va_list pArgs;
+ va_start( pArgs, nSort );
+ ImpSetSort( pArgs, nSort );
+
+ Reset();
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 02.06.93
+|* Letzte Aenderung MI 02.06.93
+|*
+*************************************************************************/
+
+Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags ):
+ DirEntry( rDirEntry ),
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ Construct( nKindFlags );
+ Reset();
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MA 04.11.91
+|*
+*************************************************************************/
+
+Dir::Dir():
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ pLst = NULL;
+ pSortLst = NULL;
+ pStatLst = NULL;
+ eAttrMask = FSYS_KIND_ALL;
+ aNameMask = String("*", osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* Dir::~Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MA 04.11.91
+|*
+*************************************************************************/
+
+Dir::~Dir()
+{
+ DBG_DTOR( Dir, NULL );
+
+ // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
+ if ( pLst )
+ {
+ DirEntry* pEntry = pLst->First();
+ while (pEntry)
+ {
+ DirEntry* pNext = pLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pLst->Clear();
+
+ delete pLst;
+ }
+
+ // alle Sorts aus der Liste entfernen und deren Speicher freigeben
+ if ( pSortLst )
+ {
+ FSysSort* pEntry = pSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pSortLst->Clear();
+
+ delete pSortLst;
+ }
+
+ // alle FileStat's aus der Liste entfernen und deren Speicher freigeben
+ if ( pStatLst )
+ {
+ FileStat* pEntry = pStatLst->First();
+ while (pEntry)
+ {
+ FileStat* pNext = pStatLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pStatLst->Clear();
+ delete pStatLst;
+ }
+
+ // ggf. laufenden Reader freigeben
+ delete pReader;
+}
+
+/*************************************************************************
+|*
+|* Dir::ImpSetSort()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 04.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+FSysError Dir::ImpSetSort( va_list pArgs, int nFirstSort )
+{
+ BOOL bLast;
+ FSysSort *pSort;
+ FSysSortList *pNewSortLst = new FSysSortList;
+
+ *( pSort = new FSysSort ) = nFirstSort;
+ do
+ {
+ // letztes Kriterium?
+ bLast = FSYS_SORT_END == (*pSort & FSYS_SORT_END);
+ *pSort &= ~FSYS_SORT_END;
+
+ // Ascending oder Descending?
+ BOOL bAscending = FSYS_SORT_ASCENDING ==
+ ( *pSort & ( FSYS_SORT_ASCENDING | FSYS_SORT_DESCENDING ) );
+ USHORT nSort = *pSort & ~(USHORT)FSYS_SORT_ASCENDING
+ & ~(USHORT)FSYS_SORT_DESCENDING;
+
+ // g"utliges Sortierkriterium?
+ if ( ( nSort == FSYS_SORT_NAME ) ||
+ ( nSort == FSYS_SORT_SIZE ) ||
+ ( nSort == FSYS_SORT_EXT ) ||
+ ( nSort == FSYS_SORT_CREATED ) ||
+ ( nSort == FSYS_SORT_MODIFYED ) ||
+ ( nSort == FSYS_SORT_ACCESSED ) ||
+ ( nSort == FSYS_SORT_KIND ) )
+ {
+ pNewSortLst->Insert( pSort, APPEND );
+ *(pSort = new FSysSort) = va_arg( pArgs, FSysSort );
+ }
+ else
+ { // ungueltiger Sort oder FSYS_SORT_NONE
+ FSysSort* pEntry = pNewSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pNewSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pNewSortLst->Clear();
+ delete pNewSortLst;
+ if ( *pSort == FSYS_SORT_NONE )
+ {
+ delete pSort;
+ if ( pSortLst )
+ delete pSortLst;
+ return FSYS_ERR_OK;
+ }
+ else
+ {
+ delete pSort;
+ return FSYS_ERR_NOTSUPPORTED;
+ }
+ }
+ } while ( !bLast );
+
+ va_end( pArgs );
+ delete pSort; // JP:6.3.00 - delete the initial pointer
+
+ //Enfernen der alten Sort-Elemente
+ if ( pSortLst )
+ {
+ FSysSort* pEntry = pSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pSortLst->Clear();
+ delete pSortLst;
+ }
+ pSortLst = pNewSortLst;
+
+ //Jetzt noch neu Sortieren...
+
+ //Wenn keine FileStats da sind, aber nun welche gebraucht werden,
+ //ist der Aufruf von Update() die einfachste Moeglichkeit
+ if ( !pStatLst && pSortLst )
+ {
+ pSortLst->First();
+ do
+ {
+ if ( *(pSortLst->GetCurObject()) &
+ ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE |
+ FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) )
+ {
+ Update();
+ return FSYS_ERR_OK;
+ }
+ } while ( !pStatLst && pSortLst->Next() );
+ }
+
+ if ( pLst ) { //Keine DirEntry's, kein Sort.
+ DirEntryList *pOldLst = pLst; //alte Liste merken
+ pLst = new DirEntryList(); //neue Liste (zu Sortieren)
+
+ FileStatList *pOldStatLst = NULL; //alte StatListe merken
+ if ( pStatLst ) {
+ pOldStatLst = pStatLst;
+ pStatLst = new FileStatList(); //neue StatListe (zu Sortieren)
+ }
+ pOldLst->First();
+ do
+ {
+ //Sortiertes Einfuegen der Elemente aus den gemerkten Listen
+ //in die 'richtigen' Listen
+ if ( pOldStatLst )
+ ImpSortedInsert( pOldLst->GetCurObject(),
+ pOldStatLst->GetObject( pOldLst->GetCurPos() ) );
+ else
+ ImpSortedInsert( pOldLst->GetCurObject(), NULL );
+ } while( pOldLst->Next() );
+
+ delete pOldLst;
+ if ( pOldStatLst )
+ delete pOldStatLst;
+ }
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* Dir::SetSort()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 04.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+FSysError Dir::SetSort( FSysSort nSort, ... )
+{
+ va_list pArgs;
+ va_start( pArgs, nSort );
+ return ImpSetSort( pArgs, nSort );
+}
+
+/*************************************************************************
+|*
+|* Dir::operator[]()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 16.05.91
+|*
+*************************************************************************/
+
+DirEntry& Dir::operator[] ( USHORT nIndex ) const
+{
+ DBG_ASSERT( nIndex < Count(), "Dir::operator[] : nIndex > Count()" );
+
+ DirEntry *pEntry = pLst->GetObject( nIndex );
+ return *pEntry;
+}
+
+/*************************************************************************
+|*
+|* Dir::operator+= ()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 16.05.91
+|*
+*************************************************************************/
+
+Dir& Dir::operator+=( const Dir& rDir )
+{
+ // ggf. erst den Rest lesen
+ if ( pReader )
+ Scan( USHRT_MAX );
+ DBG_ASSERT( !rDir.pReader, "Dir::+= with incomplete Dir" );
+
+ // ggf. initiale Liste erzeugen
+ if ( !pLst )
+ pLst = new DirEntryList();
+
+ //Verlangen die Sortierkriterien FileStat's?
+ BOOL bStat = FALSE;
+ if ( pSortLst ) {
+ pSortLst->First();
+ do {
+ if ( *(pSortLst->GetCurObject()) &
+ ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE |
+ FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) )
+ bStat = TRUE;
+ } while ( !bStat && pSortLst->Next() );
+ }
+ FileStat *pStat = NULL;
+ for ( USHORT nNr = 0; nNr < rDir.Count(); nNr++ ) {
+ if ( bStat )
+ if ( rDir.pStatLst )
+ {
+ pStat = new FileStat( *rDir.pStatLst->GetObject(nNr) );
+ }
+ else
+ pStat = new FileStat( rDir[nNr] );
+ ImpSortedInsert( new DirEntry( rDir[nNr] ), pStat );
+ }
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Dir::Count()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 18.09.96
+|*
+*************************************************************************/
+
+
+USHORT Dir::Count( BOOL bUpdated ) const
+{
+ // ggf. erst den Rest lesen
+ if ( bUpdated && pReader )
+ ((Dir*)this)->Scan( USHRT_MAX );
+
+ return pLst == NULL ? 0 : (USHORT) pLst->Count();
+}
diff --git a/tools/source/fsys/tempfile.cxx b/tools/source/fsys/tempfile.cxx
new file mode 100644
index 000000000000..f920d18dde0f
--- /dev/null
+++ b/tools/source/fsys/tempfile.cxx
@@ -0,0 +1,337 @@
+/*************************************************************************
+ *
+ * $RCSfile: tempfile.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include "tempfile.hxx"
+#include "comdep.hxx"
+
+#include <rtl/ustring.hxx>
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _TOOLS_TIME_HXX
+#include <time.hxx>
+#endif
+#include <debug.hxx>
+#include <stdio.h>
+
+#ifdef UNX
+#define _MAX_PATH 260
+#endif
+
+using namespace osl;
+
+static ::rtl::OUString aTempNameBase_Impl;
+
+struct TempFile_Impl
+{
+ String aName;
+ sal_Bool bIsDirectory;
+};
+
+String GetSystemTempDir_Impl()
+{
+ char sBuf[_MAX_PATH];
+ const char *pDir = TempDirImpl(sBuf);
+ ::rtl::OUString aTmp = ::rtl::OUString::createFromAscii( pDir );
+ rtl::OUString aRet;
+ FileBase::normalizePath( aTmp, aRet );
+ String aName = aRet;
+ sal_Int32 i = aName.Len();
+ if( aName.GetChar(i-1) != '/' )
+ aName += '/';
+ return aName;
+}
+
+#define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
+String ConstructTempDir_Impl( const String* pParent )
+{
+ String aName;
+ if ( pParent && pParent->Len() )
+ {
+ // if parent given try to use it
+ rtl::OUString aTmp( *pParent );
+ rtl::OUString aRet;
+
+ // test for valid filename
+ if ( FileBase::getNormalizedPathFromFileURL( aTmp, aRet ) == FileBase::E_None )
+ {
+ ::osl::DirectoryItem aItem;
+ sal_Int32 i = aRet.getLength();
+ if ( aRet[i-1] == '/' )
+ i--;
+
+ if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None )
+ aName = aRet;
+ }
+ }
+
+ if ( !aName.Len() )
+ {
+ // if no parent or invalid parent : use system directory
+ if ( !aTempNameBase_Impl.getLength() )
+ aTempNameBase_Impl = GetSystemTempDir_Impl();
+ aName = aTempNameBase_Impl;
+ }
+
+ // Make sure that directory ends with a separator
+ sal_Int32 i = aName.Len();
+ if( i>0 && aName.GetChar(i-1) != '/' )
+ aName += '/';
+
+ return aName;
+}
+
+void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
+{
+ // add a suitable tempname
+ // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
+ // ER 13.07.00 why not radix 36 [0-9A-Z] ?!?
+ const unsigned nRadix = 26;
+ String aName( rName );
+ aName += String::CreateFromAscii( "sv" );
+ sal_Int32 i = aName.Len();
+
+ rName.Erase();
+ static unsigned long u = Time::GetSystemTicks();
+ for ( unsigned long nOld = u; ++u != nOld; )
+ {
+ u %= (nRadix*nRadix*nRadix);
+ String aTmp( aName );
+ aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
+ aTmp += String::CreateFromAscii( ".tmp" );
+
+ if ( bDir )
+ {
+ FileBase::RC err = Directory::create( aTmp );
+ if ( err == FileBase::E_None )
+ {
+ // !bKeep: only for creating a name, not a file or directory
+ if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
+ rName = aTmp;
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ {
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ }
+ else
+ {
+ DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
+ File aFile( aTmp );
+ FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
+ if ( err == FileBase::E_None )
+ {
+ rName = aTmp;
+ aFile.close();
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ {
+ // if f.e. name contains invalid chars stop trying to create files
+ break;
+ }
+ }
+ }
+}
+
+String TempFile::CreateTempName( const String* pParent )
+{
+ // get correct directory
+ String aName = ConstructTempDir_Impl( pParent );
+
+ // get TempFile name with default naming scheme
+ CreateTempName_Impl( aName, sal_False );
+
+ // convert to file URL
+ rtl::OUString aTmp;
+ if ( aName.Len() )
+ FileBase::getFileURLFromNormalizedPath( aName, aTmp );
+ return aTmp;
+}
+
+TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
+ : pImp( new TempFile_Impl )
+ , bKillingFileEnabled( sal_False )
+{
+ pImp->bIsDirectory = bDirectory;
+
+ // get correct directory
+ pImp->aName = ConstructTempDir_Impl( pParent );
+
+ // get TempFile with default naming scheme
+ CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
+}
+
+TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
+ : pImp( new TempFile_Impl )
+ , bKillingFileEnabled( sal_False )
+{
+ pImp->bIsDirectory = bDirectory;
+
+ // get correct directory
+ String aName = ConstructTempDir_Impl( pParent );
+
+ // now use special naming scheme ( name takes leading chars and an index counting up from zero
+ aName += rLeadingChars;
+ for ( sal_Int32 i=0;; i++ )
+ {
+ String aTmp( aName );
+ aTmp += String::CreateFromInt32( i );
+ if ( pExtension )
+ aTmp += *pExtension;
+ else
+ aTmp += String::CreateFromAscii( ".tmp" );
+ if ( bDirectory )
+ {
+ FileBase::RC err = Directory::create( aTmp );
+ if ( err == FileBase::E_None )
+ {
+ pImp->aName = aTmp;
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ else
+ {
+ File aFile( aTmp );
+ FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
+ if ( err == FileBase::E_None )
+ {
+ pImp->aName = aTmp;
+ aFile.close();
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ }
+}
+
+TempFile::~TempFile()
+{
+ if ( bKillingFileEnabled )
+ {
+ if ( pImp->bIsDirectory )
+ {
+ // at the moment no recursiv algorithm present
+ Directory::remove( pImp->aName );
+ }
+ else
+ {
+ File::remove( pImp->aName );
+ }
+ }
+
+ delete pImp;
+}
+
+sal_Bool TempFile::IsValid() const
+{
+ return pImp->aName.Len() != 0;
+}
+
+String TempFile::GetName() const
+{
+ rtl::OUString aTmp;
+ FileBase::getFileURLFromNormalizedPath( pImp->aName, aTmp );
+ return aTmp;
+}
+
+String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
+{
+// if ( !aTempNameBase_Impl.getLength() )
+// aTempNameBase_Impl = GetSystemTempDir_Impl();
+// String aName( aTempNameBase_Impl );
+// aName += rBaseName;
+
+ String aName( rBaseName );
+
+ FileBase::RC err= Directory::create( aName );
+ if ( err == FileBase::E_None || err == FileBase::E_EXIST )
+ {
+ aTempNameBase_Impl = aName;
+ aTempNameBase_Impl += ::rtl::OUString( '/' );
+
+ TempFile aBase( NULL, sal_True );
+ if ( aBase.IsValid() )
+ aTempNameBase_Impl = aBase.pImp->aName;
+ }
+
+ rtl::OUString aTmp;
+ FileBase::getFileURLFromNormalizedPath( aTempNameBase_Impl, aTmp );
+ return aTmp;
+}
+
+String TempFile::GetTempNameBaseDirectory()
+{
+ if ( !aTempNameBase_Impl.getLength() )
+ aTempNameBase_Impl = GetSystemTempDir_Impl();
+
+ rtl::OUString aTmp;
+ FileBase::getFileURLFromNormalizedPath( aTempNameBase_Impl, aTmp );
+ return aTmp;
+}
+
diff --git a/tools/source/fsys/unx.cxx b/tools/source/fsys/unx.cxx
new file mode 100644
index 000000000000..245ba9ebad4d
--- /dev/null
+++ b/tools/source/fsys/unx.cxx
@@ -0,0 +1,694 @@
+/*************************************************************************
+ *
+ * $RCSfile: unx.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#if defined HPUX || defined LINUX || defined IRIX
+#include <mntent.h>
+#define mnttab mntent
+#elif defined SCO
+#include <mnttab.h>
+#elif defined AIX
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+extern "C" int mntctl( int cmd, size_t size, char* buf );
+#elif defined S390
+#include <sys/mntent.h>
+#define mnttab w_mntent
+#elif defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
+#elif defined DECUNIX
+struct mnttab
+{
+ char *mnt_dir;
+ char *mnt_fsname;
+};
+#else
+#include <sys/mnttab.h>
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#include <debug.hxx>
+#include <list.hxx>
+#include <fsys.hxx>
+#include "comdep.hxx"
+
+DECLARE_LIST( DirEntryList, DirEntry* )
+DECLARE_LIST( FSysSortList, FSysSort* )
+DECLARE_LIST( FileStatList, FileStat* )
+
+#if defined SOLARIS || defined SINIX
+#define MOUNTSPECIAL mnt_special
+#define MOUNTPOINT mnt_mountp
+#define MOUNTOPTS mnt_mntopts
+#define MOUNTFS mnt_fstype
+#elif defined SCO
+#define MNTTAB "/etc/mnttab"
+#define MOUNTSPECIAL mt_dev
+#define MOUNTPOINT mt_filsys
+#elif defined S390
+#define MOUNTSPECIAL mnt_fsname
+#define MOUNTPOINT mnt_mountpoint
+#else
+#define MOUNTSPECIAL mnt_fsname
+#define MOUNTPOINT mnt_dir
+#define MOUNTFS mnt_type
+#endif
+
+static ByteString sLastCaseSensitiveDir = "";
+static BOOL bLastCaseSensitive = FALSE;
+
+struct mymnttab
+{
+ dev_t mountdevice;
+ ByteString mountspecial;
+ ByteString mountpoint;
+ ByteString mymnttab_filesystem;
+ mymnttab() { mountdevice = (dev_t) -1; }
+};
+
+
+#if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
+BOOL GetMountEntry(dev_t dev, struct mymnttab *mytab)
+{
+ DBG_WARNING( "Sorry, not implemented: GetMountEntry" );
+ return FALSE;
+}
+
+#elif defined AIX
+BOOL GetMountEntry(dev_t dev, struct mymnttab *mytab)
+{
+ int bufsize;
+ if (mntctl (MCTL_QUERY, sizeof bufsize, (char*) &bufsize))
+ return FALSE;
+
+ char* buffer = (char *)malloc( bufsize * sizeof(char) );
+ if (mntctl (MCTL_QUERY, bufsize, buffer) != -1)
+ for ( char* vmt = buffer;
+ vmt < buffer + bufsize;
+ vmt += ((struct vmount*)vmt)->vmt_length)
+ {
+ struct stat buf;
+ char *mountp = vmt2dataptr((struct vmount*)vmt, VMT_STUB);
+ if ((stat (mountp, &buf) != -1) && (buf.st_dev == dev))
+ {
+ mytab->mountpoint = mountp;
+ mytab->mountspecial
+ = vmt2dataptr((struct vmount*)vmt, VMT_HOSTNAME);
+ if (mytab->mountspecial.Len())
+ mytab->mountspecial += ':';
+ mytab->mountspecial
+ += vmt2dataptr((struct vmount*)vmt, VMT_OBJECT);
+ mytab->mountdevice = dev;
+ free( buffer );
+ return TRUE;
+ }
+ }
+ free( buffer );
+ return FALSE;
+}
+
+#else
+
+
+static BOOL GetMountEntry(dev_t dev, struct mymnttab *mytab)
+{
+#if defined SOLARIS || defined SINIX
+ FILE *fp = fopen (MNTTAB, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while (getmntent (fp, mnt) != -1)
+#elif defined SCO
+ FILE *fp = fopen (MNTTAB, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while (fread (&mnt, sizeof mnt, 1, fp) > 0)
+#elif defined DECUNIX || defined AIX || defined S390
+ FILE *fp = NULL;
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while ( 0 )
+#else
+ FILE *fp = setmntent (MOUNTED, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab *mnt;
+ while ((mnt = getmntent (fp)) != NULL)
+#endif
+ {
+#ifdef SOLARIS
+ char *devopt = NULL;
+ if ( mnt->MOUNTOPTS != NULL )
+ devopt = strstr (mnt->MOUNTOPTS, "dev=");
+ if (devopt)
+ {
+ if (dev != (dev_t) strtoul (devopt+4, NULL, 16))
+ continue;
+ }
+ else
+#endif
+ {
+ struct stat buf;
+ if ((stat (mnt->MOUNTPOINT, &buf) == -1) || (buf.st_dev != dev))
+ continue;
+ }
+# ifdef LINUX
+ /* #61624# File mit setmntent oeffnen und mit fclose schliessen stoesst
+ bei der glibc-2.1 auf wenig Gegenliebe */
+ endmntent( fp );
+# else
+ fclose (fp);
+# endif
+ mytab->mountspecial = mnt->MOUNTSPECIAL;
+ mytab->mountpoint = mnt->MOUNTPOINT;
+ mytab->mountdevice = dev;
+#ifndef SCO
+ mytab->mymnttab_filesystem = mnt->MOUNTFS;
+#else
+ mytab->mymnttab_filesystem = "ext2"; //default ist case sensitiv unter unix
+#endif
+ return TRUE;
+ }
+# ifdef LINUX
+ /* #61624# dito */
+ endmntent( fp );
+# else
+ fclose (fp);
+# endif
+ return FALSE;
+}
+
+#endif
+
+/************************************************************************
+|*
+|* DirEntry::IsCaseSensitive()
+|*
+|* Beschreibung
+|* Ersterstellung TPF 25.02.1999
+|* Letzte Aenderung TPF 25.02.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+#ifdef NETBSD
+ return TRUE;
+#else
+ struct stat buf;
+ DirEntry aPath(*this);
+ aPath.ToAbs();
+
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() == 1)
+ {
+ return TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ }
+ aPath = aPath [1];
+ }
+
+ struct mymnttab fsmnt;
+ GetMountEntry(buf.st_dev, &fsmnt);
+ if ((fsmnt.mymnttab_filesystem.CompareTo("msdos")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("umsdos")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("vfat")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("hpfs")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("smb") ==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("ncpfs")==COMPARE_EQUAL))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+#endif
+ }
+ else
+ {
+ BOOL isCaseSensitive = TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+/************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:30
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ return TRUE;
+
+ char sBuf[MAXPATHLEN + 1];
+ *this = DirEntry( String( getcwd( sBuf, MAXPATHLEN ), osl_getThreadTextEncoding() ) ) + *this;
+ return IsAbs();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.03.92
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+static mymnttab mymnt;
+static String aEmptyString;
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aPath( *this );
+ aPath.ToAbs();
+
+ struct stat buf;
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() <= 1)
+ return aEmptyString;
+ aPath = aPath [1];
+ }
+
+ return ((buf.st_dev == mymnt.mountdevice ||
+ GetMountEntry(buf.st_dev, &mymnt)) ? String(mymnt.mountspecial, osl_getThreadTextEncoding()) : aEmptyString);
+}
+
+DirEntry DirEntry::GetDevice() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aPath( *this );
+ aPath.ToAbs();
+
+ struct stat buf;
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() <= 1)
+ return aEmptyString;
+ aPath = aPath [1];
+ }
+ return ((buf.st_dev == mymnt.mountdevice ||
+ GetMountEntry(buf.st_dev, &mymnt)) ? String( mymnt.mountpoint, osl_getThreadTextEncoding()) : aEmptyString);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung DV 04.11.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+
+ ByteString aPath( GetFull(), osl_getThreadTextEncoding());
+ if ( !chdir( aPath.GetBuffer() ) )
+ {
+ return TRUE;
+ }
+ else
+ {
+ if ( bSloppy && !chdir(aPath.GetBuffer()) )
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ if (!pDosDir)
+ {
+ pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
+ }
+
+ if (!pDosDir)
+ {
+ bReady = TRUE;
+ return 0;
+ }
+
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
+ if ( pDir->aNameMask.Matches( aD_Name ) )
+ {
+ DirEntryFlag eFlag =
+ 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
+ : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE);
+ FileStat aStat( *pTemp );
+ if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+ ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
+ !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
+ pDosEntry->d_name[0] == '.' ) )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );;
+ return 1;
+ }
+ else
+ delete pTemp;
+ }
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *, const void * ):
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+#if SUPD < 345
+BOOL FileStat::Update( const DirEntry& rDirEntry )
+{
+ return Update( rDirEntry, FALSE );
+}
+#endif
+
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL bAccessRemovableDevice )
+{
+
+ nSize = 0;
+ nKindFlags = 0;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if ( !rDirEntry.IsValid() )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root handelt
+ if ( rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ nKindFlags = FSYS_KIND_DIR;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ struct stat aStat;
+ ByteString aPath( rDirEntry.GetFull(), osl_getThreadTextEncoding() );
+ if ( stat( (char*) aPath.GetBuffer(), &aStat ) )
+ {
+ // pl: #67851#
+ // do this here, because an existing filename containing "wildcards"
+ // should be handled as a file, not a wildcard
+ // note that this is not a solution, since filenames containing special characters
+ // are handled badly across the whole Office
+
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
+ if ( strchr( (char*) aTempName.GetBuffer(), '?' ) ||
+ strchr( (char*) aTempName.GetBuffer(), '*' ) ||
+ strchr( (char*) aTempName.GetBuffer(), ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ nError = FSYS_ERR_OK;
+ nSize = aStat.st_size;
+
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ if ( ( aStat.st_mode & S_IFDIR ) == S_IFDIR )
+ nKindFlags = nKindFlags | FSYS_KIND_DIR;
+ if ( ( aStat.st_mode & S_IFREG ) == S_IFREG )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+ if ( ( aStat.st_mode & S_IFCHR ) == S_IFCHR )
+ nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_CHAR;
+ if ( ( aStat.st_mode & S_IFBLK ) == S_IFBLK )
+ nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_BLOCK;
+ if ( nKindFlags == FSYS_KIND_UNKNOWN )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+
+ Unx2DateAndTime( aStat.st_ctime, aTimeCreated, aDateCreated );
+ Unx2DateAndTime( aStat.st_mtime, aTimeModified, aDateModified );
+ Unx2DateAndTime( aStat.st_atime, aTimeAccessed, aDateAccessed );
+
+ return TRUE;
+}
+
+//====================================================================
+
+const char *TempDirImpl( char *pBuf )
+{
+ const char *pValue = getenv( "TEMP" );
+ if ( !pValue )
+ pValue = getenv( "TMP" );
+ if ( pValue )
+ strcpy( pBuf, pValue );
+ else
+ // auf Solaris und Linux ist P_tmpdir vorgesehen
+ strcpy( pBuf, P_tmpdir );
+ // hart auf "/tmp" sollte wohl nur im Notfall verwendet werden
+ //strcpy( pBuf, "/tmp" );
+ return pBuf;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
+{
+ return FSYS_STYLE_UNX;
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetDateTime
+|*
+|* Ersterstellung PB 27.06.97
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+void FileStat::SetDateTime( const String& rFileName,
+ const DateTime& rNewDateTime )
+{
+ tm times;
+
+ times.tm_year = rNewDateTime.GetYear() - 1900; // 1997 -> 97
+ times.tm_mon = rNewDateTime.GetMonth() - 1; // 0 == Januar!
+ times.tm_mday = rNewDateTime.GetDay();
+
+ times.tm_hour = rNewDateTime.GetHour();
+ times.tm_min = rNewDateTime.GetMin();
+ times.tm_sec = rNewDateTime.GetSec();
+
+ times.tm_wday = 0;
+ times.tm_yday = 0;
+#ifdef SOLARIS
+ times.tm_isdst = -1;
+#else
+ times.tm_isdst = 0;
+#endif
+
+ time_t time = mktime (&times);
+
+ if (time != (time_t) -1)
+ {
+ struct utimbuf u_time;
+ u_time.actime = time;
+ u_time.modtime = time;
+ utime (ByteString(rFileName, osl_getThreadTextEncoding()).GetBuffer(), &u_time);
+ }
+}
+
+//=========================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &rPath,
+ BigInt &rFreeBytes, BigInt &rTotalBytes )
+{
+ return ERRCODE_IO_NOTSUPPORTED;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL bEnable )
+{
+}
+
diff --git a/tools/source/fsys/unx.hxx b/tools/source/fsys/unx.hxx
new file mode 100644
index 000000000000..2751289b7c2e
--- /dev/null
+++ b/tools/source/fsys/unx.hxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * $RCSfile: unx.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _unx_hxx
+#define _unx_hxx
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef S390
+#include <sys/param.h>
+#endif
+
+#include <dirent.h>
+#include <unistd.h>
+/* #include <sysent.h> */
+
+#define FSYS_UNIX TRUE
+#define DRIVE_EXISTS(c) ( TRUE )
+
+#define _mkdir(p) mkdir(p, 0777)
+#define _rmdir rmdir
+#define _chdir chdir
+#define _unlink unlink
+#define _getcwd getcwd
+#define _access access
+
+#ifdef SYSV3
+#define DEFSTYLE FSYS_STYLE_SYSV
+#else
+#define DEFSTYLE FSYS_STYLE_BSD
+#endif
+
+#define CMP_LOWER(s) (s)
+#define TEMPNAME() tmpnam(0)
+#define LOWER(aString) (aString.Lower())
+
+#include <time.h>
+#include <datetime.hxx>
+
+#ifndef localtime_r
+extern "C" {
+struct tm *localtime_r(const time_t *timep, struct tm *buffer);
+}
+#endif
+
+inline Time Unx2Time( time_t nTime )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nTime, &atm );
+ return Time( pTime->tm_hour,
+ pTime->tm_min,
+ pTime->tm_sec );
+}
+
+inline Date Unx2Date( time_t nDate )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nDate, &atm );
+ return Date( pTime->tm_mday,
+ pTime->tm_mon + 1,
+ pTime->tm_year + 1900 );
+}
+
+inline void Unx2DateAndTime( time_t nDate, Time& rTime, Date& rDate )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nDate, &atm );
+ rTime = Time( pTime->tm_hour, pTime->tm_min, pTime->tm_sec );
+ rDate = Date( pTime->tm_mday, pTime->tm_mon + 1, pTime->tm_year + 1900 );
+}
+
+const char* TempDirImpl( char *pBuf );
+
+#define FSysFailOnErrorImpl()
+
+#endif
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
new file mode 100644
index 000000000000..e3c937c5a7d4
--- /dev/null
+++ b/tools/source/fsys/urlobj.cxx
@@ -0,0 +1,5021 @@
+/*************************************************************************
+ *
+ * $RCSfile: urlobj.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define min min // fool <tools/solar.h>...
+#define max max // fool <tools/solar.h>...
+
+#ifndef _URLOBJ_HXX
+#include <urlobj.hxx>
+#endif
+
+#include <limits>
+
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+
+#ifndef _TOOLS_DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef TOOLS_INETMIME_HXX
+#include <inetmime.hxx>
+#endif
+#ifndef _TOOLS_INTN_HXX
+#include <intn.hxx>
+#endif
+
+namespace unnamed_tools_urlobj {} using namespace unnamed_tools_urlobj;
+ // unnamed namespaces don't work well yet...
+
+//============================================================================
+//
+// INetURLObject
+//
+//============================================================================
+
+/* The URI grammar (using RFC 2234 conventions).
+
+ Constructs of the form
+ {reference <rule1> using rule2}
+ stand for a rule matching the given rule1 specified in the given reference,
+ encoded to URI syntax using rule2 (as specified in this URI grammar).
+
+
+ ; RFC 1738, RFC 2396, RFC 2732, private
+ login = [user [":" password] "@"] hostport
+ user = *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~")
+ password = *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~")
+ hostport = host [":" port]
+ host = incomplete-hostname / hostname / IPv4address / IPv6reference
+ incomplete-hostname = *(domainlabel ".") domainlabel
+ hostname = *(domainlabel ".") toplabel ["."]
+ domainlabel = alphadigit [*(alphadigit / "-") alphadigit]
+ toplabel = ALPHA [*(alphadigit / "-") alphadigit]
+ alphadigit = ALPHA / DIGIT
+ IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
+ IPv6reference = "[" hexpart [":" IPv4address] "]"
+ hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ hexseq = hex4 *(":" hex4)
+ hex4 = 1*4HEXDIG
+ port = *DIGIT
+ escaped = "%" HEXDIG HEXDIG
+ reserved = "$" / "&" / "+" / "," / "/" / ":" / ";" / "=" / "?" / "@" / "[" / "]"
+ mark = "!" / "'" / "(" / ")" / "*" / "-" / "." / "_" / "~"
+ alphanum = ALPHA / DIGIT
+ unreserved = alphanum / mark
+ uric = escaped / reserved / unreserved
+ pchar = escaped / unreserved / "$" / "&" / "+" / "," / ":" / "=" / "@"
+
+
+ ; RFC 1738, RFC 2396
+ ftp-url = "FTP://" login ["/" segment *("/" segment) [";TYPE=" ("A" / "D" / "I")]]
+ segment = *pchar
+
+
+ ; RFC 1738, RFC 2396
+ http-url = "HTTP://" hostport ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(pchar / ";")
+
+
+ ; RFC 1738, RFC 2396
+ file-url = "FILE://" [host / "LOCALHOST"] ["/" segment *("/" segment)]
+ segment = *pchar
+
+
+ ; RFC 2368, RFC 2396
+ mailto-url = "MAILTO:" [to] [headers]
+ to = {RFC 822 <#mailbox> using *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+ headers = "?" header *("&" header)
+ header = hname "=" hvalue
+ hname = {RFC 822 <field-name> using *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} / "BODY"
+ hvalue = {RFC 822 <field-body> using *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+
+
+ ; private (see RFC 1738)
+ news-url = "NEWS://" login ["/" (group / message)]
+ group = *uric
+ message = "<" *uric ">"
+
+
+ ; private
+ private-url = "PRIVATE:" path ["?" *uric]
+ path = *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~"
+
+
+ ; private
+ https-url = "HTTPS://" hostport ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ slot-url = "SLOT:" path ["?" *uric]
+ path = *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~"
+
+
+ ; private
+ macro-url = "MACRO:" path ["?" *uric]
+ path = *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~"
+
+
+ ; private
+ javascript-url = "JAVASCRIPT:" *uric
+
+
+ ; private (see RFC 2192)
+ imap-url = "IMAP://" user [";AUTH=" auth] "@" hostport "/" segment *("/" segment) ["/;UID=" nz_number]
+ user = 1*{RFC 2060 <CHAR8> using (escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "=" / "_" / "~")}
+ auth = {RFC 2060 <atom> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "+" / "," / "-" / "." / "=" / "_" / "~")}
+ segment = *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / "=" / "@" / "_" / "~")
+ nz_number = {RFC 2060 <nz_number> using *DIGIT}
+
+
+ ; private
+ pop3-url = "POP3://" login ["/" ["<" *uric ">"]]
+
+
+ ; RFC 2397
+ data-url = "DATA:" [mediatype] [";BASE64"] "," *uric
+ mediatype = [type "/" subtype] *(";" attribute "=" value)
+ type = {RFC 2045 <type> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ subtype = {RFC 2045 <subtype> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ attribute = {RFC 2045 <subtype> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ value = {RFC 2045 <subtype> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+
+
+ ; RFC 2392, RFC 2396
+ cid-url = "CID:" {RFC 822 <addr-spec> using *uric}
+
+
+ ; private
+ out-url = "OUT:///~" name ["/" *uric]
+ name = *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "?" / "@" / "_" / "~"
+
+
+ ; private
+ vim-url = "VIM://" +vimc [":" *vimc] ["/" [("INBOX" message) / ("NEWSGROUPS" ["/" [+vimc message]])]]
+ message = ["/" [+vimc [":" +DIGIT "." +DIGIT "." +DIGIT]]]
+ vimc = ("=" HEXDIG HEXDIG) / ALPHA / DIGIT
+
+
+ ; private
+ uno-url = ".UNO:" *uric
+
+
+ ; private
+ component-url = ".COMPONENT:" path ["?" *uric]
+ path = *(escaped / ALPHA / DIGIT / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~"
+
+
+ ; RFC 2255
+ ldap-url = "LDAP://" [hostport] ["/" [dn ["?" [attrdesct *("," attrdesc)] ["?" ["base" / "one" / "sub"] ["?" [filter] ["?" extension *("," extension)]]]]]]
+ dn = {RFC 2253 <distinguishedName> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ attrdesc = {RFC 2251 <AttributeDescription> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ filter = {RFC 2254 <filter> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ extension = ["!"] ["X-"] extoken ["=" exvalue]
+ extoken = {RFC 2252 <oid> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+ exvalue = {RFC 2251 <LDAPString> using *(escaped / ALPHA / DIGIT / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+
+
+ ; private
+ db-url = "DB:" *uric
+ */
+
+//============================================================================
+inline sal_Int32 INetURLObject::SubString::clear()
+{
+ sal_Int32 nDelta = -m_nLength;
+ m_nBegin = STRING_NOTFOUND;
+ m_nLength = 0;
+ return nDelta;
+}
+
+//============================================================================
+inline sal_Int32 INetURLObject::SubString::set(UniString & rString,
+ UniString const & rSubString)
+{
+ DBG_ASSERT(isPresent(), "INetURLObject::SubString::set(): Not present");
+ sal_Int32 nDelta = rSubString.Len() - m_nLength;
+ rString.Replace(m_nBegin, m_nLength, rSubString);
+ m_nLength = rSubString.Len();
+ return nDelta;
+}
+
+//============================================================================
+inline sal_Int32 INetURLObject::SubString::set(UniString & rString,
+ UniString const & rSubString,
+ xub_StrLen nTheBegin)
+{
+ m_nBegin = nTheBegin;
+ return set(rString, rSubString);
+}
+
+//============================================================================
+inline void INetURLObject::SubString::operator +=(sal_Int32 nDelta)
+{
+ if (isPresent())
+ m_nBegin += nDelta;
+}
+
+//============================================================================
+bool INetURLObject::SubString::equals(SubString const & rOther,
+ UniString const & rThisString,
+ UniString const & rOtherString) const
+{
+ if (m_nLength != rOther.m_nLength)
+ return true;
+ sal_Unicode const * p1 = rThisString.GetBuffer() + m_nBegin;
+ sal_Unicode const * p1End = p1 + m_nLength;
+ sal_Unicode const * p2 = rOtherString.GetBuffer() + rOther.m_nBegin;
+ while (p1 != p1End)
+ if (*p1++ != *p2++)
+ return false;
+ return true;
+}
+
+//============================================================================
+struct INetURLObject::SchemeInfo
+{
+ sal_Char const * m_pScheme;
+ sal_Char const * m_pPrefix;
+ sal_uInt16 m_nDefaultPort;
+ bool m_bAuthority;
+ bool m_bUser;
+ bool m_bAuth;
+ bool m_bPassword;
+ bool m_bHost;
+ bool m_bPort;
+ bool m_bHierarchical;
+ bool m_bQuery;
+};
+
+//============================================================================
+struct INetURLObject::PrefixInfo
+{
+ enum Kind { OFFICIAL, EXTERNAL, INTERNAL };
+
+ sal_Char const * m_pPrefix;
+ sal_Char const * m_pTranslatedPrefix;
+ INetProtocol m_eScheme;
+ Kind m_eKind;
+};
+
+//============================================================================
+// static
+
+static INetURLObject::SchemeInfo const aSchemeInfoMap[INET_PROT_END]
+ = { { "", "", 0, false, false, false, false, false, false, false,
+ false },
+ { "ftp", "ftp://", 21, true, true, false, true, true, true, true,
+ false },
+ { "http", "http://", 80, true, false, false, false, true, true,
+ true, true },
+ { "file", "file://", 0, true, false, false, false, true, false,
+ true, false },
+ { "mailto", "mailto:", 0, false, false, false, false, false,
+ false, false, true },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false },
+ { "news", "news:", 119, true, true, false, true, true, true,
+ false, false },
+ { "private", "private:", 0, false, false, false, false, false,
+ false, false, true },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false },
+ { "https", "https://", 443, true, false, false, false, true, true,
+ true, true },
+ { "slot", "slot:", 0, false, false, false, false, false, false,
+ false, true },
+ { "macro", "macro:", 0, false, false, false, false, false, false,
+ false, true },
+ { "javascript", "javascript:", 0, false, false, false, false,
+ false, false, false, false },
+ { "imap", "imap://", 143, true, true, true, false, true, true,
+ true, false },
+ { "pop3", "pop3://", 110, true, true, false, true, true, true,
+ false, false },
+ { "data", "data:", 0, false, false, false, false, false, false,
+ false, false },
+ { "cid", "cid:", 0, false, false, false, false, false, false,
+ false, false },
+ { "out", "out://", 0, true, false, false, false, false, false,
+ false, false },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false },
+ { "vim", "vim://", 0, true, true, false, true, false, false, true,
+ false },
+ { ".uno", ".uno:", 0, false, false, false, false, false, false,
+ false, false },
+ { ".component", ".component:", 0, false, false, false, false,
+ false, false, false, true },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false },
+ { "ldap", "ldap://", 389, true, false, false, false, true, true,
+ false, true },
+ { "db", "db:", 0, false, false, false, false, false, false, false,
+ false },
+ { 0, 0, 0, false, false, false, false, false, false, false,
+ false } };
+
+inline INetURLObject::SchemeInfo const &
+INetURLObject::getSchemeInfo(INetProtocol eTheScheme)
+{
+ return aSchemeInfoMap[eTheScheme];
+};
+
+//============================================================================
+inline INetURLObject::SchemeInfo const & INetURLObject::getSchemeInfo() const
+{
+ return getSchemeInfo(m_eScheme);
+}
+
+//============================================================================
+// static
+inline void INetURLObject::appendEscape(UniString & rTheText,
+ sal_Char cEscapePrefix,
+ sal_uInt32 nOctet)
+{
+ rTheText += cEscapePrefix;
+ rTheText += sal_Unicode(INetMIME::getHexDigit(int(nOctet >> 4)));
+ rTheText += sal_Unicode(INetMIME::getHexDigit(int(nOctet & 15)));
+}
+
+//============================================================================
+// static
+inline void INetURLObject::appendUTF32(UniString & rTheText,
+ sal_uInt32 nUTF32)
+{
+ DBG_ASSERT(nUTF32 <= 0x10FFFF, "INetURLObject::appendUTF32(): Bad char");
+ if (nUTF32 < 0x10000)
+ rTheText += sal_Unicode(nUTF32);
+ else
+ {
+ nUTF32 -= 0x10000;
+ rTheText += sal_Unicode(0xD800 | nUTF32 >> 10);
+ rTheText += sal_Unicode(0xDC00 | nUTF32 & 0x3FF);
+ }
+}
+
+//============================================================================
+namespace unnamed_tools_urlobj {
+
+enum
+{
+ pA = INetURLObject::PART_OBSOLETE_NORMAL,
+ pB = INetURLObject::PART_OBSOLETE_FILE,
+ pC = INetURLObject::PART_OBSOLETE_PARAM,
+ pD = INetURLObject::PART_USER_PASSWORD,
+ pE = INetURLObject::PART_IMAP_ACHAR,
+ pF = INetURLObject::PART_VIM,
+ pG = INetURLObject::PART_HOST_EXTRA,
+ pH = INetURLObject::PART_FPATH,
+ pI = INetURLObject::PART_AUTHORITY,
+ pJ = INetURLObject::PART_PATH_SEGMENTS_EXTRA,
+ pK = INetURLObject::PART_REL_SEGMENT_EXTRA,
+ pL = INetURLObject::PART_URIC,
+ pM = INetURLObject::PART_HTTP_PATH,
+ pN = INetURLObject::PART_FILE_SEGMENT_EXTRA,
+ pO = INetURLObject::PART_MESSAGE_ID,
+ pP = INetURLObject::PART_MESSAGE_ID_PATH,
+ pQ = INetURLObject::PART_MAILTO,
+ pR = INetURLObject::PART_PATH_BEFORE_QUERY,
+ pS = INetURLObject::PART_PCHAR,
+ pT = INetURLObject::PART_FRAGMENT,
+ pU = INetURLObject::PART_VISIBLE,
+ pV = INetURLObject::PART_VISIBLE_NONSPECIAL,
+ pW = INetURLObject::PART_CREATEFRAGMENT,
+ pX = INetURLObject::PART_UNO_PARAM_VALUE,
+ pY = INetURLObject::PART_UNAMBIGUOUS
+};
+static sal_uInt32 const aMustEncodeMap[128]
+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ pY,
+/* ! */ pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* " */ pU+pV+pY,
+/* # */ pU,
+/* $ */ pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* % */ pU,
+/* & */ pA+pB+pC+pD+pE+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pR+pS+pT+pU+pV+pW+pX,
+/* ' */ pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* ( */ pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* ) */ pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* * */ pA+pB+pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* + */ pA+pB+pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX,
+/* , */ pA+pB+pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW,
+/* - */ pA+pB+pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* . */ pA+pB+pC+pD+pE+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* / */ pA+pB+pC+pH+pJ+pL+pM+pP+pQ+pR+pT+pU+pV+pX,
+/* 0 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 1 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 2 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 3 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 4 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 5 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 6 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 7 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 8 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* 9 */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* : */ pB+pC+pH+pI+pJ+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX,
+/* ; */ pC+pD+pI+pJ+pK+pL+pM+pO+pP+pQ+pR+pT+pU+pW,
+/* < */ pC+pO+pP+pU+pV+pY,
+/* = */ pA+pB+pC+pD+pE+pH+pI+pJ+pK+pL+pM+pN+pR+pS+pT+pU+pV+pW,
+/* > */ pC+pO+pP+pU+pV+pY,
+/* ? */ pC+pL+pT+pU+pW+pX,
+/* @ */ pC+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* A */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* B */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* C */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* D */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* E */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* F */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* G */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* H */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* I */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* J */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* K */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* L */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* M */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* N */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* O */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* P */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* Q */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* R */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* S */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* T */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* U */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* V */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* W */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* X */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* Y */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* Z */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* [ */ pL+pU+pV+pX,
+/* \ */ pB+pU+pV+pY,
+/* ] */ pL+pU+pV+pX,
+/* ^ */ pU+pV+pY,
+/* _ */ pA+pB+pC+pD+pE +pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* ` */ +pU+pV+pY,
+/* a */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* b */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* c */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* d */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* e */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* f */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* g */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* h */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* i */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* j */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* k */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* l */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* m */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* n */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* o */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* p */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* q */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* r */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* s */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* t */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* u */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* v */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* w */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* x */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* y */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* z */ pA+pB+pC+pD+pE+pF+pG+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* { */ +pU+pV+pY,
+/* | */ pB+pC+pN+pT+pU+pV+pY,
+/* } */ +pU+pV+pY,
+/* ~ */ pA+pB+pC+pD+pE+pH+pI+pJ+pK+pL+pM+pN+pO+pP+pQ+pR+pS+pT+pU+pV+pW+pX+pY,
+/* */ 0 };
+
+inline bool mustEncode(sal_uInt32 nUTF32, INetURLObject::Part ePart)
+{
+ return !INetMIME::isUSASCII(nUTF32) || !(aMustEncodeMap[nUTF32] & ePart);
+}
+
+}
+
+//============================================================================
+void INetURLObject::setInvalid()
+{
+ m_aAbsURIRef.Erase();
+ m_eScheme = INET_PROT_NOT_VALID;
+ m_aUser.clear();
+ m_aAuth.clear();
+ m_aHost.clear();
+ m_aPort.clear();
+ m_aPath.clear();
+ m_aQuery.clear();
+ m_aFragment.clear();
+}
+
+//============================================================================
+
+namespace unnamed_tools_urlobj {
+
+INetURLObject::FSysStyle
+guessFSysStyleByCounting(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ INetURLObject::FSysStyle eStyle)
+{
+ DBG_ASSERT(eStyle
+ & (INetURLObject::FSYS_UNX
+ | INetURLObject::FSYS_DOS
+ | INetURLObject::FSYS_MAC),
+ "guessFSysStyleByCounting(): Bad style");
+ DBG_ASSERT(std::numeric_limits< sal_Int32 >::min() < pBegin - pEnd
+ && pEnd - pBegin <= std::numeric_limits< sal_Int32 >::max(),
+ "guessFSysStyleByCounting(): Too big");
+ sal_Int32 nSlashCount
+ = eStyle & INetURLObject::FSYS_UNX ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ sal_Int32 nBackslashCount
+ = eStyle & INetURLObject::FSYS_DOS ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ sal_Int32 nColonCount
+ = eStyle & INetURLObject::FSYS_MAC ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ while (pBegin != pEnd)
+ switch (*pBegin++)
+ {
+ case '/':
+ ++nSlashCount;
+ break;
+
+ case '\\':
+ ++nBackslashCount;
+ break;
+
+ case ':':
+ ++nColonCount;
+ break;
+ }
+ return nSlashCount >= nBackslashCount ?
+ nSlashCount >= nColonCount ?
+ INetURLObject::FSYS_UNX : INetURLObject::FSYS_MAC :
+ nBackslashCount >= nColonCount ?
+ INetURLObject::FSYS_DOS : INetURLObject::FSYS_MAC;
+}
+
+}
+
+bool INetURLObject::setAbsURIRef(UniString const & rTheAbsURIRef,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bSmart,
+ FSysStyle eStyle)
+{
+ sal_Unicode const * pPos = rTheAbsURIRef.GetBuffer();
+ sal_Unicode const * pEnd = pPos + rTheAbsURIRef.Len();
+
+ setInvalid();
+
+ sal_uInt32 nFragmentDelimiter = '#';
+
+ UniString aSynAbsURIRef;
+
+ // Parse <scheme>:
+ sal_Unicode const * p = pPos;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ if (pPrefix)
+ {
+ pPos = p;
+ m_eScheme = pPrefix->m_eScheme;
+ aSynAbsURIRef
+ = UniString::CreateFromAscii(pPrefix->m_eKind
+ == PrefixInfo::EXTERNAL ?
+ pPrefix->m_pTranslatedPrefix :
+ pPrefix->m_pPrefix);
+ }
+ else
+ {
+ if (bSmart)
+ {
+ // For scheme detection, the first (if any) of the following
+ // productions that matches the input string (and for which the
+ // appropriate style bit is set in eStyle, if applicable)
+ // determines the scheme. The productions use the auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // IPv6reference = "[" IPv6address "]"
+ // IPv6address = hexpart [":" IPv4address]
+ // IPv4address = 1*3DIGIT 3("." 1*3DIGIT)
+ // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ // hexseq = hex4 *(":" hex4)
+ // hex4 = 1*4HEXDIG
+ // UCS4 = <any UCS4 character>
+ //
+ // 1st Production (known scheme):
+ // <one of the known schemes, ignoring case> ":" *UCS4
+ //
+ // 2nd Production (mailto):
+ // domain "@" domain
+ //
+ // 3rd Production (ftp):
+ // "ftp" 2*("." label) ["/" *UCS4]
+ //
+ // 4th Production (http):
+ // label 2*("." label) ["/" *UCS4]
+ //
+ // 5th Production (file):
+ // "//" (domain / IPv6reference) ["/" *UCS4]
+ //
+ // 6th Production (Unix file):
+ // "/" *UCS4
+ //
+ // 7th Production (UNC file; FSYS_DOS only):
+ // "\\" domain ["\" *UCS4]
+ //
+ // 8th Production (Unix-like DOS file; FSYS_DOS only):
+ // ALPHA ":/" *UCS4
+ //
+ // 9th Production (DOS file; FSYS_DOS only):
+ // ALPHA ":\" *UCS4
+ //
+ // For the 'non URL' file productions 6--9, the interpretation of
+ // the input as a (degenerate) URI is turned off, i.e., escape
+ // sequences and fragments are never detected as such, but are
+ // taken as literal characters.
+
+ sal_Unicode const * p = pPos;
+ if (eStyle & FSYS_DOS
+ && pEnd - p >= 3
+ && INetMIME::isAlpha(p[0])
+ && p[1] == ':'
+ && (p[2] == '/' || p[2] == '\\'))
+ {
+ m_eScheme = INET_PROT_FILE; // 8th, 9th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ else if (pEnd - p >= 2 && p[0] == '/' && p[1] == '/')
+ {
+ p += 2;
+ if ((scanDomain(p, pEnd) > 0 || scanIPv6reference(p, pEnd))
+ && (p == pEnd || *p == '/'))
+ m_eScheme = INET_PROT_FILE; // 5th
+ }
+ else if (p != pEnd && *p == '/')
+ {
+ m_eScheme = INET_PROT_FILE; // 6th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ else if (eStyle & FSYS_DOS
+ && pEnd - p >= 2
+ && p[0] == '\\'
+ && p[1] == '\\')
+ {
+ p += 2;
+ if (scanDomain(p, pEnd) > 0 && (p == pEnd || *p == '\\'))
+ {
+ m_eScheme = INET_PROT_FILE; // 7th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ }
+ else
+ {
+ sal_Unicode const * pDomainEnd = p;
+ sal_uInt32 nLabels = scanDomain(pDomainEnd, pEnd);
+ if (nLabels > 0 && pDomainEnd != pEnd && *pDomainEnd == '@')
+ {
+ ++pDomainEnd;
+ if (scanDomain(pDomainEnd, pEnd) > 0
+ && pDomainEnd == pEnd)
+ m_eScheme = INET_PROT_MAILTO; // 2nd
+ }
+ else if (nLabels >= 3
+ && (pDomainEnd == pEnd || *pDomainEnd == '/'))
+ m_eScheme
+ = pDomainEnd - p >= 4
+ && p[0] == 'f'
+ && p[1] == 't'
+ && p[2] == 'p'
+ && p[3] == '.' ?
+ INET_PROT_FTP : INET_PROT_HTTP; // 3rd, 4th
+ }
+
+ if (m_eScheme == INET_PROT_NOT_VALID && pPos != pEnd
+ && *pPos != nFragmentDelimiter)
+ m_eScheme = m_eSmartScheme;
+ }
+
+ if (m_eScheme == INET_PROT_NOT_VALID)
+ {
+ setInvalid();
+ return false;
+ }
+
+ aSynAbsURIRef = UniString::CreateFromAscii(getSchemeInfo().m_pScheme);
+ aSynAbsURIRef += ':';
+ }
+
+ sal_Char cEscapePrefix = getEscapePrefix();
+ sal_uInt32 nSegmentDelimiter = '/';
+ sal_uInt32 nAltSegmentDelimiter = 0x80000000;
+ bool bSkippedInitialSlash = false;
+
+ // Parse //<user>;AUTH=<auth>@<host>:<port> or
+ // //<user>:<password>@<host>:<port>
+ if (getSchemeInfo().m_bAuthority)
+ {
+ aSynAbsURIRef.AppendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+
+ sal_Unicode const * pUserInfoBegin = 0;
+ sal_Unicode const * pUserInfoEnd = 0;
+ sal_Unicode const * pHostPortBegin = 0;
+ sal_Unicode const * pHostPortEnd = 0;
+
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ if (bSmart)
+ {
+ // The first of the following seven productions that
+ // matches the rest of the input string (and for which the
+ // appropriate style bit is set in eStyle, if applicable)
+ // determines the used notation. The productions use the
+ // auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // IPv6reference = "[" IPv6address "]"
+ // IPv6address = hexpart [":" IPv4address]
+ // IPv4address = 1*3DIGIT 3("." 1*3DIGIT)
+ // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ // hexseq = hex4 *(":" hex4)
+ // hex4 = 1*4HEXDIG
+ // path = <any UCS4 character except "#">
+ // UCS4 = <any UCS4 character>
+
+ // 1st Production (URL):
+ // "//" [domain / IPv6reference] ["/" *path]
+ // ["#" *UCS4]
+ // becomes
+ // "file://" domain "/" *path ["#" *UCS4]
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ sal_Unicode const * p = pPos + 2;
+ if (p == pEnd || *p == nFragmentDelimiter || *p == '/'
+ || (scanDomain(p, pEnd) > 0
+ || scanIPv6reference(p, pEnd))
+ && (p == pEnd || *p == nFragmentDelimiter
+ || *p == '/'))
+ {
+ pHostPortBegin = pPos + 2;
+ pHostPortEnd = p;
+ pPos = p;
+ break;
+ }
+ }
+
+ // 2nd Production (misscounted slashes):
+ // "//" *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ pPos += 2;
+ bSkippedInitialSlash = true;
+ break;
+ }
+
+ // 3rd Production (Unix):
+ // "/" *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ if (pPos < pEnd && *pPos == '/')
+ break;
+
+ // 4th Production (UNC; FSYS_DOS only):
+ // "\\" domain ["\" *path] ["#" *UCS4]
+ // becomes
+ // "file://" domain "/" *path ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ if (eStyle & FSYS_DOS
+ && pEnd - pPos >= 2
+ && pPos[0] == '\\'
+ && pPos[1] == '\\')
+ {
+ sal_Unicode const * p = pPos + 2;
+ if (scanDomain(p, pEnd) > 0
+ && (p == pEnd || *p == nFragmentDelimiter
+ || *p == '\\'))
+ {
+ pHostPortBegin = pPos + 2;
+ pHostPortEnd = p;
+ pPos = p;
+ nSegmentDelimiter = '\\';
+ break;
+ }
+ }
+
+ // 5th Production (Unix-like DOS; FSYS_DOS only):
+ // ALPHA ":/" *path ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":/" *path ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ //
+ // 6th Production (DOS; FSYS_DOS only):
+ // ALPHA ":\" *path ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":/" *path ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ if (eStyle & FSYS_DOS
+ && pEnd - pPos >= 3
+ && INetMIME::isAlpha(pPos[0])
+ && pPos[1] == ':'
+ && (pPos[2] == '/' || pPos[2] == '\\'))
+ {
+ nAltSegmentDelimiter = '\\';
+ bSkippedInitialSlash = true;
+ break;
+ }
+
+ // 7th Production (any):
+ // *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ // replacing the delimiter by "/" within <*path>. The
+ // delimiter is that character from the set { "/", "\",
+ // ":" } which appears most often in <*path> (if FSYS_UNX
+ // is not among the style bits, "/" is removed from the
+ // set; if FSYS_DOS is not among the style bits, "\" is
+ // removed from the set; if FSYS_MAC is not among the
+ // style bits, ":" is removed from the set). If two or
+ // more characters appear the same number of times, the
+ // character mentioned first in that set is chosen. If
+ // the first character of <*path> is the delimiter, that
+ // character is not copied.
+ if (eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC))
+ {
+ switch (guessFSysStyleByCounting(pPos, pEnd, eStyle))
+ {
+ case FSYS_UNX:
+ nSegmentDelimiter = '/';
+ break;
+
+ case FSYS_DOS:
+ nSegmentDelimiter = '\\';
+ break;
+
+ case FSYS_MAC:
+ nSegmentDelimiter = ':';
+ break;
+
+ default:
+ DBG_ERROR(
+ "INetURLObject::setAbsURIRef():"
+ " Bad guessFSysStyleByCounting");
+ break;
+ }
+ bSkippedInitialSlash
+ = pPos != pEnd && *pPos != nSegmentDelimiter;
+ break;
+ }
+ }
+ default:
+ {
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ pPos += 2;
+ else if (!bSmart)
+ {
+ setInvalid();
+ return false;
+ }
+
+ sal_Unicode const * pAuthority = pPos;
+ sal_uInt32 c = getSchemeInfo().m_bQuery ? '?' : 0x80000000;
+ while (pPos < pEnd && *pPos != '/' && *pPos != c
+ && *pPos != nFragmentDelimiter)
+ ++pPos;
+ if (getSchemeInfo().m_bUser)
+ if (getSchemeInfo().m_bHost)
+ {
+ sal_Unicode const * p = pAuthority;
+ while (p < pPos && *p != '@')
+ ++p;
+ if (p == pPos)
+ {
+ pHostPortBegin = pAuthority;
+ pHostPortEnd = pPos;
+ }
+ else
+ {
+ pUserInfoBegin = pAuthority;
+ pUserInfoEnd = p;
+ pHostPortBegin = p + 1;
+ pHostPortEnd = pPos;
+ }
+ }
+ else
+ {
+ pUserInfoBegin = pAuthority;
+ pUserInfoEnd = pPos;
+ }
+ else if (getSchemeInfo().m_bHost)
+ {
+ pHostPortBegin = pAuthority;
+ pHostPortEnd = pPos;
+ }
+ else if (pPos != pAuthority)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (pUserInfoBegin)
+ {
+ Part ePart = m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD;
+ bool bSupportsPassword = getSchemeInfo().m_bPassword;
+ bool bSupportsAuth
+ = !bSupportsPassword && getSchemeInfo().m_bAuth;
+ bool bHasAuth = false;
+ UniString aSynUser;
+ sal_Unicode const * p = pUserInfoBegin;
+ while (p < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pUserInfoEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ if (nUTF32 == ':' && bSupportsPassword)
+ {
+ bHasAuth = true;
+ break;
+ }
+ else if (nUTF32 == ';' && bSupportsAuth
+ && pUserInfoEnd - p
+ > RTL_CONSTASCII_LENGTH("auth=")
+ && INetMIME::equalIgnoreCase(
+ p,
+ p + RTL_CONSTASCII_LENGTH("auth="),
+ "auth="))
+ {
+ p += RTL_CONSTASCII_LENGTH("auth=");
+ bHasAuth = true;
+ break;
+ }
+ appendUCS4(aSynUser, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, false);
+ }
+ m_aUser.set(aSynAbsURIRef, aSynUser, aSynAbsURIRef.Len());
+ if (bHasAuth)
+ if (bSupportsPassword)
+ {
+ aSynAbsURIRef += ':';
+ UniString aSynAuth;
+ while (p < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pUserInfoEnd, bOctets,
+ cEscapePrefix,
+ eMechanism, eCharset,
+ eEscapeType);
+ appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets,
+ ePart, cEscapePrefix, eCharset, false);
+ }
+ m_aAuth.set(aSynAbsURIRef, aSynAuth, aSynAbsURIRef.Len());
+ }
+ else
+ {
+ aSynAbsURIRef.
+ AppendAscii(RTL_CONSTASCII_STRINGPARAM(";AUTH="));
+ UniString aSynAuth;
+ while (p < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pUserInfoEnd, bOctets,
+ cEscapePrefix,
+ eMechanism, eCharset,
+ eEscapeType);
+ if (!INetMIME::isIMAPAtomChar(nUTF32))
+ {
+ setInvalid();
+ return false;
+ }
+ appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets,
+ ePart, cEscapePrefix, eCharset, false);
+ }
+ m_aAuth.set(aSynAbsURIRef, aSynAuth, aSynAbsURIRef.Len());
+ }
+ if (pHostPortBegin)
+ aSynAbsURIRef += '@';
+ }
+
+ if (pHostPortBegin)
+ {
+ sal_Unicode const * pPort = pHostPortEnd;
+ if (getSchemeInfo().m_bPort && pHostPortBegin < pHostPortEnd)
+ {
+ sal_Unicode const * p = pHostPortEnd - 1;
+ while (p > pHostPortBegin && INetMIME::isDigit(*p))
+ --p;
+ if (*p == ':')
+ pPort = p;
+ }
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ // If the host equals "LOCALHOST" (unencoded and ignoring
+ // case), turn it into an empty host:
+ if (INetMIME::equalIgnoreCase(pHostPortBegin, pPort,
+ "localhost"))
+ pHostPortBegin = pPort;
+ break;
+
+ case INET_PROT_LDAP:
+ if (pHostPortBegin == pPort && pPort != pHostPortEnd)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+
+ default:
+ if (pHostPortBegin == pPort)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ UniString aSynHost;
+ if (pHostPortBegin != pPort
+ && (!parseHost(pHostPortBegin, pPort, bOctets, eMechanism,
+ eCharset, aSynHost)
+ || pHostPortBegin != pPort))
+ {
+ setInvalid();
+ return false;
+ }
+ m_aHost.set(aSynAbsURIRef, aSynHost, aSynAbsURIRef.Len());
+ if (pPort != pHostPortEnd)
+ {
+ aSynAbsURIRef += ':';
+ m_aPort.set(aSynAbsURIRef,
+ UniString(pPort + 1, pHostPortEnd - (pPort + 1)),
+ aSynAbsURIRef.Len());
+ }
+ }
+ }
+
+ // Parse <path>
+ UniString aSynPath;
+ if (!parsePath(&pPos, pEnd, bOctets, eMechanism, eCharset,
+ bSkippedInitialSlash, nSegmentDelimiter,
+ nAltSegmentDelimiter,
+ getSchemeInfo().m_bQuery ? '?' : 0x80000000,
+ nFragmentDelimiter, &aSynPath))
+ {
+ setInvalid();
+ return false;
+ }
+ m_aPath.set(aSynAbsURIRef, aSynPath, aSynAbsURIRef.Len());
+
+ // Parse ?<query>
+ if (getSchemeInfo().m_bQuery && pPos < pEnd && *pPos == '?')
+ {
+ aSynAbsURIRef += '?';
+ UniString aSynQuery;
+ for (++pPos; pPos < pEnd && *pPos != nFragmentDelimiter;)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aSynQuery, nUTF32, eEscapeType, bOctets,
+ PART_URIC, cEscapePrefix, eCharset, true);
+ }
+ m_aQuery.set(aSynAbsURIRef, aSynQuery, aSynAbsURIRef.Len());
+ }
+
+ // Parse #<fragment>
+ if (pPos < pEnd && *pPos == nFragmentDelimiter)
+ {
+ aSynAbsURIRef += nFragmentDelimiter;
+ UniString aSynFragment;
+ for (++pPos; pPos < pEnd;)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aSynFragment, nUTF32, eEscapeType, bOctets, PART_URIC,
+ cEscapePrefix, eCharset, true);
+ }
+ m_aFragment.set(aSynAbsURIRef, aSynFragment, aSynAbsURIRef.Len());
+ }
+
+ if (pPos != pEnd)
+ {
+ setInvalid();
+ return false;
+ }
+
+ m_aAbsURIRef = aSynAbsURIRef;
+
+ return true;
+}
+
+//============================================================================
+// static
+INetURLObject INetURLObject::m_aBaseURIRef;
+
+//============================================================================
+bool INetURLObject::convertRelToAbs(UniString const & rTheRelURIRef,
+ bool bOctets,
+ INetURLObject & rTheAbsURIRef,
+ bool & rWasAbsolute,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bIgnoreFragment, bool bSmart,
+ bool bRelativeNonURIs, FSysStyle eStyle)
+ const
+{
+ sal_Unicode const * p = rTheRelURIRef.GetBuffer();
+ sal_Unicode const * pEnd = p + rTheRelURIRef.Len();
+
+ sal_Unicode const * pPrefixBegin = p;
+ PrefixInfo const * pPrefix = getPrefix(pPrefixBegin, pEnd);
+
+ sal_uInt32 nSegmentDelimiter = '/';
+ sal_uInt32 nQueryDelimiter
+ = !bSmart || getSchemeInfo().m_bQuery ? '?' : 0x80000000;
+ sal_uInt32 nFragmentDelimiter = '#';
+ Part ePart = PART_VISIBLE;
+
+ if (!pPrefix && bSmart)
+ {
+ // If the input matches any of the following productions (for which
+ // the appropriate style bit is set in eStyle), it is assumed to be an
+ // absolute file system path, rather than a relative URI reference.
+ // (This is only a subset of the productions used for scheme detection
+ // in INetURLObject::setAbsURIRef(), because most of those productions
+ // interfere with the syntax of relative URI references.) The
+ // productions use the auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // UCS4 = <any UCS4 character>
+ //
+ // 1st Production (UNC file; FSYS_DOS only):
+ // "\\" domain ["\" *UCS4]
+ //
+ // 2nd Production (Unix-like DOS file; FSYS_DOS only):
+ // ALPHA ":/" *UCS4
+ //
+ // 3rd Production (DOS file; FSYS_DOS only):
+ // ALPHA ":\" *UCS4
+ if (eStyle & FSYS_DOS)
+ {
+ bool bFSys = false;
+ sal_Unicode const * q = p;
+ if (pEnd - q >= 3
+ && INetMIME::isAlpha(q[0])
+ && q[1] == ':'
+ && (q[2] == '/' || q[2] == '\\'))
+ bFSys = true; // 2nd, 3rd
+ else if (pEnd - q >= 2 && q[0] == '\\' && q[1] == '\\')
+ {
+ q += 2;
+ if (scanDomain(q, pEnd) > 0 && (q == pEnd || *q == '\\'))
+ bFSys = true; // 1st
+ }
+ if (bFSys)
+ {
+ INetURLObject aNewURI;
+ aNewURI.setAbsURIRef(rTheRelURIRef, bOctets, eMechanism,
+ eCharset, true, eStyle);
+ if (!aNewURI.HasError())
+ {
+ rTheAbsURIRef = aNewURI;
+ rWasAbsolute = true;
+ return true;
+ }
+ }
+ }
+
+ // When the base URL is a file URL, accept relative file system paths
+ // using "\" or ":" as delimiter (and ignoring URI conventions for "%"
+ // and "#"), as well as relative URIs using "/" as delimiter:
+ if (m_eScheme == INET_PROT_FILE)
+ switch (guessFSysStyleByCounting(p, pEnd, eStyle))
+ {
+ case FSYS_UNX:
+ nSegmentDelimiter = '/';
+ break;
+
+ case FSYS_DOS:
+ nSegmentDelimiter = '\\';
+ bRelativeNonURIs = true;
+ break;
+
+ case FSYS_MAC:
+ nSegmentDelimiter = ':';
+ bRelativeNonURIs = true;
+ break;
+
+ default:
+ DBG_ERROR("INetURLObject::convertRelToAbs():"
+ " Bad guessFSysStyleByCounting");
+ break;
+ }
+
+ if (bRelativeNonURIs)
+ {
+ eMechanism = ENCODE_ALL;
+ nQueryDelimiter = 0x80000000;
+ nFragmentDelimiter = 0x80000000;
+ ePart = PART_VISIBLE_NONSPECIAL;
+ }
+ }
+
+ // If the relative URI has the same scheme as the base URI, and that
+ // scheme is hierarchical, then ignore its presence in the relative
+ // URI in order to be backward compatible (cf. RFC 2396 section 5.2
+ // step 3):
+ if (pPrefix && pPrefix->m_eScheme == m_eScheme
+ && getSchemeInfo().m_bHierarchical)
+ {
+ pPrefix = 0;
+ while (p != pEnd && *p++ != ':');
+ }
+ rWasAbsolute = pPrefix != 0;
+
+ // Fast solution for non-relative URIs:
+ if (pPrefix)
+ {
+ INetURLObject aNewURI(rTheRelURIRef, eMechanism, eCharset);
+ if (aNewURI.HasError())
+ {
+ rWasAbsolute = false;
+ return false;
+ }
+
+ if (bIgnoreFragment)
+ aNewURI.clearFragment();
+ rTheAbsURIRef = aNewURI;
+ return true;
+ }
+
+ UniString aSynAbsURIRef(UniString::CreateFromAscii(getSchemeInfo().
+ m_pScheme));
+ aSynAbsURIRef += ':';
+
+ sal_Char cEscapePrefix = getEscapePrefix();
+
+ enum State { STATE_AUTH, STATE_ABS_PATH, STATE_REL_PATH, STATE_FRAGMENT,
+ STATE_DONE };
+ State eState = STATE_AUTH;
+ bool bSameDoc = true;
+
+ if (getSchemeInfo().m_bAuthority)
+ if (pEnd - p >= 2 && p[0] == '/' && p[1] == '/')
+ {
+ aSynAbsURIRef.AppendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ p += 2;
+ eState = STATE_ABS_PATH;
+ bSameDoc = false;
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ if (nUTF32 == nSegmentDelimiter)
+ break;
+ else if (nUTF32 == nFragmentDelimiter)
+ {
+ eState = STATE_FRAGMENT;
+ break;
+ }
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets,
+ PART_VISIBLE, cEscapePrefix, eCharset, true);
+ }
+ }
+ else
+ {
+ SubString aAuthority(getAuthority());
+ aSynAbsURIRef.Append(m_aAbsURIRef.GetBuffer()
+ + aAuthority.getBegin(),
+ aAuthority.getLength());
+ }
+
+ if (eState == STATE_AUTH)
+ if (p == pEnd)
+ eState = STATE_DONE;
+ else if (*p == nFragmentDelimiter)
+ {
+ ++p;
+ eState = STATE_FRAGMENT;
+ }
+ else if (*p == nSegmentDelimiter)
+ {
+ ++p;
+ eState = STATE_ABS_PATH;
+ bSameDoc = false;
+ }
+ else
+ {
+ eState = STATE_REL_PATH;
+ bSameDoc = false;
+ }
+
+ if (eState == STATE_ABS_PATH)
+ {
+ aSynAbsURIRef += '/';
+ eState = STATE_DONE;
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ if (nUTF32 == nFragmentDelimiter)
+ {
+ eState = STATE_FRAGMENT;
+ break;
+ }
+ else if (nUTF32 == nSegmentDelimiter)
+ nUTF32 = '/';
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+ }
+ else if (eState == STATE_REL_PATH)
+ {
+ if (!getSchemeInfo().m_bHierarchical)
+ {
+ rWasAbsolute = false;
+ return false;
+ }
+
+ sal_Unicode const * pBasePathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pBasePathEnd
+ = pBasePathBegin + m_aPath.getLength();
+ while (pBasePathEnd != pBasePathBegin)
+ if (*(--pBasePathEnd) == '/')
+ {
+ ++pBasePathEnd;
+ break;
+ }
+
+ xub_StrLen nPathBegin = aSynAbsURIRef.Len();
+ aSynAbsURIRef.Append(pBasePathBegin, pBasePathEnd - pBasePathBegin);
+ DBG_ASSERT(aSynAbsURIRef.Len() > nPathBegin
+ && aSynAbsURIRef.GetChar(aSynAbsURIRef.Len() - 1) == '/',
+ "INetURLObject::convertRelToAbs(): Bad base path");
+
+ while (p != pEnd && *p != nQueryDelimiter && *p != nFragmentDelimiter)
+ {
+ if (*p == '.')
+ if (pEnd - p == 1
+ || p[1] == nSegmentDelimiter
+ || p[1] == nQueryDelimiter
+ || p[1] == nFragmentDelimiter)
+ {
+ ++p;
+ if (p != pEnd && *p == nSegmentDelimiter)
+ ++p;
+ continue;
+ }
+ else if (pEnd - p >= 2
+ && p[1] == '.'
+ && (pEnd - p == 2
+ || p[2] == nSegmentDelimiter
+ || p[2] == nQueryDelimiter
+ || p[2] == nFragmentDelimiter)
+ && aSynAbsURIRef.Len() - nPathBegin > 1)
+ {
+ p += 2;
+ if (p != pEnd && *p == nSegmentDelimiter)
+ ++p;
+
+ xub_StrLen i = aSynAbsURIRef.Len() - 2;
+ while (i > nPathBegin && aSynAbsURIRef.GetChar(i) != '/')
+ --i;
+ aSynAbsURIRef.Erase(i + 1);
+ DBG_ASSERT(
+ aSynAbsURIRef.Len() > nPathBegin
+ && aSynAbsURIRef.GetChar(aSynAbsURIRef.Len() - 1)
+ == '/',
+ "INetURLObject::convertRelToAbs(): Bad base path");
+ continue;
+ }
+
+ while (p != pEnd
+ && *p != nSegmentDelimiter
+ && *p != nQueryDelimiter
+ && *p != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+ if (p != pEnd && *p == nSegmentDelimiter)
+ {
+ aSynAbsURIRef += '/';
+ ++p;
+ }
+ }
+
+ while (p != pEnd && *p != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+
+ if (p == pEnd)
+ eState = STATE_DONE;
+ else
+ {
+ ++p;
+ eState = STATE_FRAGMENT;
+ }
+ }
+ else if (bSameDoc)
+ {
+ aSynAbsURIRef.Append(m_aAbsURIRef.GetBuffer() + m_aPath.getBegin(),
+ m_aPath.getLength());
+ if (m_aQuery.isPresent())
+ aSynAbsURIRef.Append(m_aAbsURIRef.GetBuffer()
+ + m_aQuery.getBegin() - 1,
+ m_aQuery.getLength() + 1);
+ }
+
+ if (eState == STATE_FRAGMENT && !bIgnoreFragment)
+ {
+ aSynAbsURIRef += '#';
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets,
+ PART_VISIBLE, cEscapePrefix, eCharset, true);
+ }
+ }
+
+ INetURLObject aNewURI(aSynAbsURIRef);
+ if (aNewURI.HasError())
+ {
+ rWasAbsolute = false;
+ return false;
+ }
+
+ rTheAbsURIRef = aNewURI;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::convertAbsToRel(UniString const & rTheAbsURIRef,
+ bool bOctets, UniString & rTheRelURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle) const
+{
+ // Check for hierarchical base URL:
+ if (!getSchemeInfo().m_bHierarchical)
+ {
+ rTheRelURIRef
+ = decode(rTheAbsURIRef,
+ getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)),
+ eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // Convert the input (absolute URI ref, relative URI ref, file path) to an
+ // absolute URI ref:
+ INetURLObject aSubject;
+ bool bWasAbsolute;
+ if (!convertRelToAbs(rTheAbsURIRef, bOctets, aSubject, bWasAbsolute,
+ eEncodeMechanism, eCharset, false, true, false,
+ eStyle))
+ {
+ rTheRelURIRef
+ = decode(rTheAbsURIRef,
+ getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)),
+ eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // Check for differing scheme or authority parts:
+ if (m_eScheme != aSubject.m_eScheme
+ || !m_aUser.equals(aSubject.m_aUser, m_aAbsURIRef,
+ aSubject.m_aAbsURIRef)
+ || !m_aAuth.equals(aSubject.m_aAuth, m_aAbsURIRef,
+ aSubject.m_aAbsURIRef)
+ || !m_aHost.equals(aSubject.m_aHost, m_aAbsURIRef,
+ aSubject.m_aAbsURIRef)
+ || !m_aPort.equals(aSubject.m_aPort, m_aAbsURIRef,
+ aSubject.m_aAbsURIRef))
+ {
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ sal_Unicode const * pBasePathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pBasePathEnd = pBasePathBegin + m_aPath.getLength();
+ sal_Unicode const * pSubjectPathBegin
+ = aSubject.m_aAbsURIRef.GetBuffer() + aSubject.m_aPath.getBegin();
+ sal_Unicode const * pSubjectPathEnd
+ = pSubjectPathBegin + aSubject.m_aPath.getLength();
+
+ // Make nMatch point past the last matching slash, or past the end of the
+ // paths, in case they are equal:
+ sal_Unicode const * pSlash = 0;
+ sal_Unicode const * p1 = pBasePathBegin;
+ sal_Unicode const * p2 = pSubjectPathBegin;
+ for (;;)
+ {
+ if (p1 == pBasePathEnd || p2 == pSubjectPathEnd)
+ {
+ if (p1 == pBasePathEnd && p2 == pSubjectPathEnd)
+ pSlash = p1;
+ break;
+ }
+
+ sal_Unicode c = *p1++;
+ if (c != *p2++)
+ break;
+ if (c == '/')
+ pSlash = p1;
+ }
+ if (!pSlash)
+ {
+ // One of the paths does not start with '/':
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+ sal_uInt32 nMatch = pSlash - pBasePathBegin;
+
+ // For file URLs, if the common prefix of the two paths is only "/" (which
+ // covers different DOS volumes like "/a:" and "/b:"), the subject is not
+ // made relative (it could be, but some people don't like that):
+ if (m_eScheme == INET_PROT_FILE && nMatch <= 1)
+ {
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // For every slash in the base path after nMatch, a prefix of "../" is
+ // added to the new relative URL (if the common prefix of the two paths is
+ // only "/"---but see handling of file URLs above---, the complete subject
+ // path could go into the new relative URL instead, but some people don't
+ // like that):
+ UniString aSynRelURIRef;
+// if (nMatch <= 1) nMatch = 0; else // see comment above
+ for (sal_Unicode const * p = pBasePathBegin + nMatch; p != pBasePathEnd;
+ ++p)
+ {
+ if (*p == '/')
+ aSynRelURIRef.AppendAscii(RTL_CONSTASCII_STRINGPARAM("../"));
+ }
+
+ // If the new relative URL would start with "//" (i.e., it would be
+ // mistaken for a relative URL starting with an authority part), or if the
+ // new relative URL would neither be empty nor start with <"/"> nor start
+ // with <1*rseg> (i.e., it could be mistaken for an absolute URL starting
+ // with a scheme part), then the new relative URL is prefixed with "./":
+ if (aSynRelURIRef.Len() == 0)
+ if (pSubjectPathEnd - pSubjectPathBegin >= nMatch + 2
+ && pSubjectPathBegin[nMatch] == '/'
+ && pSubjectPathBegin[nMatch + 1] == '/')
+ aSynRelURIRef.AppendAscii(RTL_CONSTASCII_STRINGPARAM("./"));
+ else
+ for (sal_Unicode const * p = pSubjectPathBegin + nMatch;
+ p != pSubjectPathEnd && *p != '/'; ++p)
+ if (mustEncode(*p, PART_REL_SEGMENT_EXTRA))
+ {
+ aSynRelURIRef.
+ AppendAscii(RTL_CONSTASCII_STRINGPARAM("./"));
+ break;
+ }
+
+ // The remainder of the subject path, starting at nMatch, is appended to
+ // the new relative URL:
+ sal_Char cEscapePrefix = getEscapePrefix();
+ aSynRelURIRef += decode(pSubjectPathBegin + nMatch, pSubjectPathEnd,
+ cEscapePrefix, eDecodeMechanism, eCharset);
+
+ // If the subject has defined query or fragment parts, they are appended
+ // to the new relative URL:
+ if (aSubject.m_aQuery.isPresent())
+ {
+ aSynRelURIRef += '?';
+ aSynRelURIRef += aSubject.decode(aSubject.m_aQuery, cEscapePrefix,
+ eDecodeMechanism, eCharset);
+ }
+ if (aSubject.m_aFragment.isPresent())
+ {
+ aSynRelURIRef += '#';
+ aSynRelURIRef += aSubject.decode(aSubject.m_aFragment, cEscapePrefix,
+ eDecodeMechanism, eCharset);
+ }
+
+ rTheRelURIRef = aSynRelURIRef;
+ return true;
+}
+
+//============================================================================
+// static
+bool INetURLObject::convertIntToExt(UniString const & rTheIntURIRef,
+ bool bOctets, UniString & rTheExtURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset)
+{
+ sal_Char cEscapePrefix
+ = getEscapePrefix(CompareProtocolScheme(rTheIntURIRef));
+ UniString aSynExtURIRef(encodeText(rTheIntURIRef, bOctets, PART_VISIBLE,
+ cEscapePrefix, NOT_CANONIC, eCharset,
+ true));
+ sal_Unicode const * pBegin = aSynExtURIRef.GetBuffer();
+ sal_Unicode const * pEnd = pBegin + aSynExtURIRef.Len();
+ sal_Unicode const * p = pBegin;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::INTERNAL;
+ if (bConvert)
+ aSynExtURIRef.
+ Replace(0, p - pBegin,
+ UniString::CreateFromAscii(pPrefix->m_pTranslatedPrefix));
+ rTheExtURIRef = decode(aSynExtURIRef, cEscapePrefix, eDecodeMechanism,
+ eCharset);
+ return bConvert;
+}
+
+//============================================================================
+// static
+bool INetURLObject::convertExtToInt(UniString const & rTheExtURIRef,
+ bool bOctets, UniString & rTheIntURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset)
+{
+ sal_Char cEscapePrefix
+ = getEscapePrefix(CompareProtocolScheme(rTheExtURIRef));
+ UniString aSynIntURIRef(encodeText(rTheExtURIRef, bOctets, PART_VISIBLE,
+ cEscapePrefix, NOT_CANONIC, eCharset,
+ true));
+ sal_Unicode const * pBegin = aSynIntURIRef.GetBuffer();
+ sal_Unicode const * pEnd = pBegin + aSynIntURIRef.Len();
+ sal_Unicode const * p = pBegin;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::EXTERNAL;
+ if (bConvert)
+ aSynIntURIRef.
+ Replace(0, p - pBegin,
+ UniString::CreateFromAscii(pPrefix->m_pTranslatedPrefix));
+ rTheIntURIRef = decode(aSynIntURIRef, cEscapePrefix, eDecodeMechanism,
+ eCharset);
+ return bConvert;
+}
+
+//============================================================================
+// static
+INetURLObject::PrefixInfo const *
+INetURLObject::getPrefix(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd)
+{
+ static PrefixInfo const aMap[]
+ = { // dummy entry at front needed, because pLast may point here:
+ { 0, 0, INET_PROT_NOT_VALID, PrefixInfo::INTERNAL },
+ { ".component:", "staroffice.component:", INET_PROT_COMPONENT,
+ PrefixInfo::INTERNAL },
+ { ".uno:", "staroffice.uno:", INET_PROT_UNO,
+ PrefixInfo::INTERNAL },
+ { "cid:", 0, INET_PROT_CID, PrefixInfo::OFFICIAL },
+ { "data:", 0, INET_PROT_DATA, PrefixInfo::OFFICIAL },
+ { "db:", "staroffice.db:", INET_PROT_DB, PrefixInfo::INTERNAL },
+ { "file:", 0, INET_PROT_FILE, PrefixInfo::OFFICIAL },
+ { "ftp:", 0, INET_PROT_FTP, PrefixInfo::OFFICIAL },
+ { "http:", 0, INET_PROT_HTTP, PrefixInfo::OFFICIAL },
+ { "https:", 0, INET_PROT_HTTPS, PrefixInfo::OFFICIAL },
+ { "imap:", 0, INET_PROT_IMAP, PrefixInfo::OFFICIAL },
+ { "javascript:", 0, INET_PROT_JAVASCRIPT, PrefixInfo::OFFICIAL },
+ { "ldap:", 0, INET_PROT_LDAP, PrefixInfo::OFFICIAL },
+ { "macro:", "staroffice.macro:", INET_PROT_MACRO,
+ PrefixInfo::INTERNAL },
+ { "mailto:", 0, INET_PROT_MAILTO, PrefixInfo::OFFICIAL },
+ { "news:", 0, INET_PROT_NEWS, PrefixInfo::OFFICIAL },
+ { "out:", "staroffice.out:", INET_PROT_OUT,
+ PrefixInfo::INTERNAL },
+ { "pop3:", "staroffice.pop3:", INET_PROT_POP3,
+ PrefixInfo::INTERNAL },
+ { "private:", "staroffice.private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:factory/", "staroffice.factory:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "private:helpid/", "staroffice.helpid:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:java/", "staroffice.java:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:searchfolder:", "staroffice.searchfolder:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "private:trashcan:", "staroffice.trashcan:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "slot:", "staroffice.slot:", INET_PROT_SLOT,
+ PrefixInfo::INTERNAL },
+ { "staroffice.component:", ".component:", INET_PROT_COMPONENT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.db:", "db:", INET_PROT_DB, PrefixInfo::EXTERNAL },
+ { "staroffice.factory:", "private:factory/",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.helpid:", "private:helpid/", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.java:", "private:java/", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.macro:", "macro:", INET_PROT_MACRO,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.out:", "out:", INET_PROT_OUT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.pop3:", "pop3:", INET_PROT_POP3,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.private:", "private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.searchfolder:", "private:searchfolder:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.slot:", "slot:", INET_PROT_SLOT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.trashcan:", "private:trashcan:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.uno:", ".uno:", INET_PROT_UNO,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.vim:", "vim:", INET_PROT_VIM,
+ PrefixInfo::EXTERNAL },
+ { "staroffice:", "private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "vim:", "staroffice.vim:", INET_PROT_VIM,
+ PrefixInfo::INTERNAL } };
+ PrefixInfo const * pFirst = aMap + 1;
+ PrefixInfo const * pLast = aMap + sizeof aMap / sizeof (PrefixInfo) - 1;
+ PrefixInfo const * pMatch = 0;
+ sal_Unicode const * pMatched = rBegin;
+ sal_Unicode const * p = rBegin;
+ xub_StrLen i = 0;
+ for (; pFirst < pLast; ++i)
+ {
+ if (pFirst->m_pPrefix[i] == '\0')
+ {
+ pMatch = pFirst++;
+ pMatched = p;
+ }
+ if (p >= pEnd)
+ break;
+ sal_uInt32 nChar = INetMIME::toLowerCase(*p++);
+ while (pFirst <= pLast && pFirst->m_pPrefix[i] < nChar)
+ ++pFirst;
+ while (pFirst <= pLast && pLast->m_pPrefix[i] > nChar)
+ --pLast;
+ }
+ if (pFirst == pLast)
+ {
+ sal_Char const * q = pFirst->m_pPrefix + i;
+ while (p < pEnd && *q != '\0' && INetMIME::toLowerCase(*p) == *q)
+ {
+ ++p;
+ ++q;
+ }
+ if (*q == '\0')
+ {
+ rBegin = p;
+ return pFirst;
+ }
+ }
+ rBegin = pMatched;
+ return pMatch;
+}
+
+//============================================================================
+INetURLObject::SubString INetURLObject::getAuthority() const
+{
+ DBG_ASSERT(getSchemeInfo().m_bAuthority,
+ "INetURLObject::getAuthority(): Bad scheme");
+
+ xub_StrLen nBegin;
+ if (m_aUser.isPresent())
+ nBegin = m_aUser.getBegin();
+ else if (m_aHost.isPresent())
+ nBegin = m_aHost.getBegin();
+ else
+ nBegin = m_aPath.getBegin();
+ nBegin -= RTL_CONSTASCII_LENGTH("//");
+ DBG_ASSERT(m_aAbsURIRef.GetChar(nBegin) == '/'
+ && m_aAbsURIRef.GetChar(nBegin + 1) == '/',
+ "INetURLObject::getAuthority(): Bad authority");
+
+ xub_StrLen nEnd = m_aPort.isPresent() ? m_aPort.getEnd() :
+ m_aHost.isPresent() ? m_aHost.getEnd() :
+ m_aAuth.isPresent() ? m_aAuth.getEnd() :
+ m_aUser.isPresent() ? m_aUser.getEnd() :
+ nBegin + RTL_CONSTASCII_LENGTH("//");
+ return SubString(nBegin, nEnd - nBegin);
+}
+
+//============================================================================
+bool INetURLObject::setUser(UniString const & rTheUser,
+ bool bOctets, EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bUser
+ || m_eScheme == INET_PROT_IMAP && rTheUser.Len() == 0)
+ return false;
+ UniString aNewUser(encodeText(rTheUser, bOctets,
+ m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism, eCharset,
+ false));
+ sal_Int32 nDelta;
+ if (m_aUser.isPresent())
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser);
+ else if (m_aHost.isPresent())
+ {
+ m_aAbsURIRef.Insert('@', m_aHost.getBegin());
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aHost.getBegin()) + 1;
+ }
+ else if (getSchemeInfo().m_bHost)
+ return false;
+ else
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aPath.getBegin());
+ m_aAuth += nDelta;
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::clearPassword()
+{
+ if (!getSchemeInfo().m_bPassword)
+ return false;
+ if (m_aAuth.isPresent())
+ {
+ m_aAbsURIRef.Erase(m_aAuth.getBegin() - 1, m_aAuth.getLength() + 1);
+ sal_Int32 nDelta = m_aAuth.clear() - 1;
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setPassword(UniString const & rThePassword, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bPassword)
+ return false;
+ UniString aNewAuth(encodeText(rThePassword, bOctets,
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM : PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism, eCharset,
+ false));
+ sal_Int32 nDelta;
+ if (m_aAuth.isPresent())
+ nDelta = m_aAuth.set(m_aAbsURIRef, aNewAuth);
+ else if (m_aUser.isPresent())
+ {
+ m_aAbsURIRef.Insert(':', m_aUser.getEnd());
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aUser.getEnd() + 1) + 1;
+ }
+ else if (m_aHost.isPresent())
+ {
+ m_aAbsURIRef.InsertAscii(":@", m_aHost.getBegin());
+ m_aUser.set(m_aAbsURIRef, UniString(), m_aHost.getBegin());
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aHost.getBegin() + 1) + 2;
+ }
+ else if (getSchemeInfo().m_bHost)
+ return false;
+ else
+ {
+ m_aAbsURIRef.Insert(':', m_aPath.getBegin());
+ m_aUser.set(m_aAbsURIRef, UniString(), m_aPath.getBegin());
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aPath.getBegin() + 1) + 1;
+ }
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::encodeHostPort(UniString const & rTheHostPort,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ xub_StrLen nPort = rTheHostPort.Len();
+ if (rTheHostPort.Len() != 0)
+ {
+ xub_StrLen i = rTheHostPort.Len() - 1;
+ while (i != 0 && INetMIME::isDigit(rTheHostPort.GetChar(i)))
+ --i;
+ if (rTheHostPort.GetChar(i) == ':')
+ nPort = i;
+ }
+ UniString aResult(encodeText(rTheHostPort.Copy(0, nPort), bOctets,
+ PART_HOST_EXTRA, '%', eMechanism, eCharset,
+ true));
+ aResult += rTheHostPort.Copy(nPort);
+ return aResult;
+}
+
+//============================================================================
+bool INetURLObject::setHost(UniString const & rTheHost, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bHost)
+ return false;
+ UniString aSynHost(rTheHost);
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ if (aSynHost.EqualsIgnoreCaseAscii("localhost"))
+ aSynHost.Erase();
+ break;
+
+ case INET_PROT_LDAP:
+ if (aSynHost.Len() == 0 && m_aPort.isPresent())
+ return false;
+ break;
+
+ default:
+ if (aSynHost.Len() == 0)
+ return false;
+ break;
+ }
+ if (aSynHost.Len() != 0)
+ {
+ sal_Unicode const * p = aSynHost.GetBuffer();
+ sal_Unicode const * pEnd = p + aSynHost.Len();
+ if (!parseHost(p, pEnd, bOctets, eMechanism, eCharset, aSynHost)
+ || p != pEnd)
+ return false;
+ }
+ sal_Int32 nDelta = m_aHost.set(m_aAbsURIRef, aSynHost);
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::parsePath(sal_Unicode const ** pBegin,
+ sal_Unicode const * pEnd,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bSkippedInitialSlash,
+ sal_uInt32 nSegmentDelimiter,
+ sal_uInt32 nAltSegmentDelimiter,
+ sal_uInt32 nQueryDelimiter,
+ sal_uInt32 nFragmentDelimiter,
+ UniString * pSynPath)
+{
+ DBG_ASSERT(pBegin && pSynPath,
+ "INetURLObject::parsePath(): Null output param");
+
+ sal_Char cEscapePrefix = getEscapePrefix();
+
+ sal_Unicode const * pPos = *pBegin;
+ UniString aTheSynPath;
+
+ switch (m_eScheme)
+ {
+ case INET_PROT_NOT_VALID:
+ return false;
+
+ case INET_PROT_FTP:
+ case INET_PROT_IMAP:
+ if (pPos < pEnd && *pPos != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_HTTP_PATH, cEscapePrefix, eCharset, true);
+ }
+ if (aTheSynPath.Len() == 0)
+ aTheSynPath = '/';
+ break;
+
+ case INET_PROT_HTTP:
+ case INET_PROT_HTTPS:
+ if (pPos < pEnd && *pPos != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_HTTP_PATH, cEscapePrefix, eCharset, true);
+ }
+ if (aTheSynPath.Len() == 0)
+ aTheSynPath = '/';
+ break;
+
+ case INET_PROT_FILE:
+ {
+ if (bSkippedInitialSlash)
+ aTheSynPath = '/';
+ else if (pPos < pEnd
+ && *pPos != nSegmentDelimiter
+ && *pPos != nAltSegmentDelimiter)
+ {
+ setInvalid();
+ return false;
+ }
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ if (nUTF32 == nSegmentDelimiter
+ || nUTF32 == nAltSegmentDelimiter)
+ {
+ aTheSynPath += '/';
+ continue;
+ }
+ else if (nUTF32 == '|'
+ && (pPos == pEnd
+ || *pPos == nFragmentDelimiter
+ || *pPos == nSegmentDelimiter
+ || *pPos == nAltSegmentDelimiter)
+ && aTheSynPath.Len() == 2
+ && INetMIME::isAlpha(aTheSynPath.GetChar(1)))
+ {
+ // A first segment of <ALPHA "|"> is translated to
+ // <ALPHA ":">:
+ aTheSynPath += ':';
+ continue;
+ }
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PCHAR, cEscapePrefix, eCharset, true);
+ }
+ if (aTheSynPath.Len() == 0)
+ aTheSynPath = '/';
+ break;
+ }
+
+ case INET_PROT_MAILTO:
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_MAILTO, cEscapePrefix, eCharset, true);
+ }
+ break;
+
+ case INET_PROT_NEWS:
+ case INET_PROT_POP3:
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_MESSAGE_ID_PATH, cEscapePrefix, eCharset,
+ true);
+ }
+ break;
+
+ case INET_PROT_PRIV_SOFFICE:
+ case INET_PROT_SLOT:
+ case INET_PROT_MACRO:
+ case INET_PROT_COMPONENT:
+ case INET_PROT_LDAP:
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PATH_BEFORE_QUERY, cEscapePrefix, eCharset,
+ true);
+ }
+ break;
+
+ case INET_PROT_JAVASCRIPT:
+ case INET_PROT_DATA:
+ case INET_PROT_CID:
+ case INET_PROT_UNO:
+ case INET_PROT_DB:
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC, cEscapePrefix, eCharset, true);
+ }
+ break;
+
+ case INET_PROT_OUT:
+ if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '~')
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath.AssignAscii(RTL_CONSTASCII_STRINGPARAM("/~"));
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC, cEscapePrefix, eCharset, true);
+ }
+ break;
+
+ case INET_PROT_VIM:
+ {
+ if (m_aUser.isEmpty())
+ {
+ setInvalid();
+ return false;
+ }
+ sal_Unicode const * pPathEnd = pPos;
+ while (pPathEnd < pEnd && *pPathEnd != nFragmentDelimiter)
+ ++pPathEnd;
+ aTheSynPath = '/';
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ if (pPos == pPathEnd)
+ break;
+ while (pPos < pPathEnd && *pPos != '/')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath,
+ eEscapeType == ESCAPE_NO ?
+ INetMIME::toLowerCase(nUTF32) : nUTF32,
+ eEscapeType, bOctets, PART_VIM, cEscapePrefix,
+ eCharset, false);
+ }
+ bool bInbox;
+ if (aTheSynPath.EqualsAscii("/inbox"))
+ bInbox = true;
+ else if (aTheSynPath.EqualsAscii("/newsgroups"))
+ bInbox = false;
+ else
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath += '/';
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ if (!bInbox)
+ {
+ bool bEmpty = true;
+ while (pPos < pPathEnd && *pPos != '/')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_VIM, cEscapePrefix, eCharset, false);
+ bEmpty = false;
+ }
+ if (bEmpty)
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath += '/';
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ bool bEmpty = true;
+ while (pPos < pPathEnd && *pPos != ':')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_VIM, cEscapePrefix, eCharset, false);
+ bEmpty = false;
+ }
+ if (bEmpty)
+ {
+ setInvalid();
+ return false;
+ }
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != ':')
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath += ':';
+ for (int i = 0; i < 3; ++i)
+ {
+ if (i != 0)
+ {
+ if (pPos == pPathEnd || *pPos++ != '.')
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath += '.';
+ }
+ bool bEmpty = true;
+ while (pPos < pPathEnd && *pPos != '.')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (!INetMIME::isDigit(nUTF32))
+ {
+ setInvalid();
+ return false;
+ }
+ aTheSynPath += sal_Unicode(nUTF32);
+ bEmpty = false;
+ }
+ if (bEmpty)
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ if (pPos != pPathEnd)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ }
+
+ *pBegin = pPos;
+ *pSynPath = aTheSynPath;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setPath(UniString const & rThePath, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ UniString aSynPath;
+ sal_Unicode const * p = rThePath.GetBuffer();
+ if (!parsePath(&p, p + rThePath.Len(), bOctets, eMechanism, eCharset,
+ false, '/', 0x80000000, 0x80000000, 0x80000000, &aSynPath))
+ return false;
+ sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath);
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::appendSegment(UniString const & rTheSegment, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ return insertName(rTheSegment, bOctets, false, LAST_SEGMENT, true,
+ eMechanism, eCharset);
+}
+
+//============================================================================
+INetURLObject::SubString INetURLObject::getSegment(sal_Int32 nIndex,
+ bool bIgnoreFinalSlash)
+ const
+{
+ DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT,
+ "INetURLObject::getSegment(): Bad index");
+
+ if (!getSchemeInfo().m_bHierarchical)
+ return SubString();
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathBegin == pPathEnd || *pPathBegin != '/')
+ return SubString();
+
+ sal_Unicode const * pSegBegin;
+ sal_Unicode const * pSegEnd;
+ if (nIndex == LAST_SEGMENT)
+ {
+ pSegEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pSegEnd[-1] == '/'
+ && pSegEnd != pPathBegin + 1)
+ --pSegEnd;
+ pSegBegin = pSegEnd - 1;
+ while (*pSegBegin != '/')
+ --pSegBegin;
+ }
+ else
+ {
+ pSegBegin = pPathBegin;
+ pSegEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pSegEnd[-1] == '/')
+ --pSegEnd;
+ while (nIndex-- > 0)
+ do
+ {
+ ++pSegBegin;
+ if (pSegBegin >= pSegEnd)
+ return SubString();
+ }
+ while (*pSegBegin != '/');
+ pSegEnd = pSegBegin + 1;
+ while (pSegEnd != pPathEnd && *pSegEnd != '/')
+ ++pSegEnd;
+ }
+
+ return SubString(pSegBegin - m_aAbsURIRef.GetBuffer(),
+ pSegEnd - pSegBegin);
+}
+
+//============================================================================
+bool INetURLObject::insertName(UniString const & rTheName, bool bOctets,
+ bool bAppendFinalSlash, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT,
+ "INetURLObject::insertName(): Bad index");
+
+ if (!getSchemeInfo().m_bHierarchical)
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathBegin == pPathEnd || *pPathBegin != '/')
+ return false;
+
+ sal_Unicode const * pPrefixEnd;
+ sal_Unicode const * pSuffixBegin;
+ bool bPrefixSlash = true;
+ if (nIndex == LAST_SEGMENT)
+ {
+ pPrefixEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pPrefixEnd[-1] == '/')
+ bPrefixSlash = false;
+ pSuffixBegin = bAppendFinalSlash ? 0 : pPathEnd;
+ }
+ else
+ {
+ pPrefixEnd = pPathBegin;
+ sal_Unicode const * pEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pEnd[-1] == '/')
+ --pEnd;
+ while (nIndex-- > 0)
+ for (;;)
+ {
+ ++pPrefixEnd;
+ if (pPrefixEnd >= pEnd)
+ if (nIndex == 0)
+ {
+ pSuffixBegin = bAppendFinalSlash ? 0 : pPathEnd;
+ break;
+ }
+ else
+ return false;
+ if (*pPrefixEnd == '/')
+ {
+ pSuffixBegin = pPrefixEnd;
+ break;
+ }
+ }
+ }
+
+ UniString aNewPath(pPathBegin, pPrefixEnd - pPathBegin);
+ if (bPrefixSlash)
+ aNewPath += '/';
+ aNewPath += encodeText(rTheName, bOctets, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true);
+ if (pSuffixBegin)
+ aNewPath.Append(pSuffixBegin, pPathEnd - pSuffixBegin);
+ else
+ aNewPath += '/';
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::clearQuery()
+{
+ if (HasError())
+ return false;
+ if (m_aQuery.isPresent())
+ {
+ m_aAbsURIRef.Erase(m_aQuery.getBegin() - 1, m_aQuery.getLength() + 1);
+ m_aFragment += m_aQuery.clear() - 1;
+ }
+ return false;
+}
+
+//============================================================================
+bool INetURLObject::setQuery(UniString const & rTheQuery, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bQuery)
+ return false;
+ UniString aNewQuery(encodeText(rTheQuery, bOctets, PART_URIC,
+ getEscapePrefix(), eMechanism, eCharset,
+ true));
+ sal_Int32 nDelta;
+ if (m_aQuery.isPresent())
+ nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery);
+ else
+ {
+ m_aAbsURIRef.Insert('?', m_aPath.getEnd());
+ nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery, m_aPath.getEnd() + 1)
+ + 1;
+ }
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::clearFragment()
+{
+ if (HasError())
+ return false;
+ if (m_aFragment.isPresent())
+ {
+ m_aAbsURIRef.Erase(m_aFragment.getBegin() - 1);
+ m_aFragment.clear();
+ }
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setFragment(UniString const & rTheFragment, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (HasError())
+ return false;
+ UniString aNewFragment(encodeText(rTheFragment, bOctets, PART_URIC,
+ getEscapePrefix(), eMechanism,
+ eCharset, true));
+ if (m_aFragment.isPresent())
+ m_aFragment.set(m_aAbsURIRef, aNewFragment);
+ else
+ {
+ m_aAbsURIRef.Append('#');
+ m_aFragment.set(m_aAbsURIRef, aNewFragment, m_aAbsURIRef.Len());
+ }
+ return true;
+}
+
+//============================================================================
+INetURLObject::FTPType INetURLObject::getFTPType() const
+{
+ if (m_eScheme == INET_PROT_FTP
+ && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH(";type=") + 1
+ && m_aAbsURIRef.
+ EqualsIgnoreCaseAscii(";type=",
+ m_aPath.getEnd()
+ - (RTL_CONSTASCII_LENGTH(";type=")
+ + 1),
+ RTL_CONSTASCII_LENGTH(";type=")))
+ switch (m_aAbsURIRef.GetChar(m_aPath.getEnd()))
+ {
+ case 'A':
+ case 'a':
+ return FTP_TYPE_A;
+
+ case 'D':
+ case 'd':
+ return FTP_TYPE_D;
+
+ case 'I':
+ case 'i':
+ return FTP_TYPE_I;
+ }
+ return FTP_TYPE_NONE;
+}
+
+//============================================================================
+sal_uInt32 INetURLObject::getIMAPUID() const
+{
+ if (m_eScheme == INET_PROT_IMAP
+ && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH("/;uid=") + 1)
+ {
+ sal_Unicode const * pBegin = m_aAbsURIRef.GetBuffer()
+ + m_aPath.getBegin()
+ + RTL_CONSTASCII_LENGTH("/;uid=");
+ sal_Unicode const * pEnd = pBegin + m_aPath.getLength();
+ sal_Unicode const * p = pEnd;
+ while (p > pBegin && INetMIME::isDigit(p[-1]))
+ --p;
+ if (p < pEnd && *--p != '0'
+ && m_aAbsURIRef.
+ EqualsIgnoreCaseAscii("/;uid=",
+ p - RTL_CONSTASCII_LENGTH("/;uid=")
+ - m_aAbsURIRef.GetBuffer(),
+ RTL_CONSTASCII_LENGTH("/;uid=")))
+ {
+ sal_uInt32 nUID;
+ if (INetMIME::scanUnsigned(p, pEnd, false, nUID))
+ return nUID;
+ }
+ }
+ return 0;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::encodeText(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd, bool bOctets,
+ Part ePart, sal_Char cEscapePrefix,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bKeepVisibleEscapes)
+{
+ UniString aResult;
+ while (pBegin < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aResult, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, bKeepVisibleEscapes);
+ }
+ return aResult;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::decode(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ sal_Char cEscapePrefix,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ switch (eMechanism)
+ {
+ case NO_DECODE:
+ return UniString(pBegin, pEnd - pBegin);
+
+ case DECODE_TO_IURI:
+ eCharset = RTL_TEXTENCODING_UTF8;
+ break;
+ }
+ UniString aResult;
+ while (pBegin < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, false, cEscapePrefix,
+ WAS_ENCODED, eCharset, eEscapeType);
+ switch (eEscapeType)
+ {
+ case ESCAPE_NO:
+ aResult += sal_Unicode(nUTF32);
+ break;
+
+ case ESCAPE_OCTET:
+ appendEscape(aResult, cEscapePrefix, nUTF32);
+ break;
+
+ case ESCAPE_UTF32:
+ if (INetMIME::isUSASCII(nUTF32)
+ && (eMechanism == DECODE_TO_IURI
+ || eMechanism == DECODE_UNAMBIGUOUS
+ && mustEncode(nUTF32, PART_UNAMBIGUOUS)))
+ appendEscape(aResult, cEscapePrefix, nUTF32);
+ else
+ aResult += sal_Unicode(nUTF32);
+ break;
+ }
+ }
+ return aResult;
+}
+
+//============================================================================
+UniString INetURLObject::GetURLNoPass(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearPassword();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+UniString INetURLObject::GetURLNoMark(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::operator ==(INetURLObject const & rObject) const
+{
+ if (m_eScheme != rObject.m_eScheme)
+ return false;
+ if (m_eScheme == INET_PROT_NOT_VALID)
+ return (m_aAbsURIRef == rObject.m_aAbsURIRef) != false;
+ if (GetUser(NO_DECODE) != rObject.GetUser(NO_DECODE)
+ || GetPass(NO_DECODE) != rObject.GetPass(NO_DECODE)
+ || !GetHost(NO_DECODE).EqualsIgnoreCaseAscii(rObject.
+ GetHost(NO_DECODE))
+ || GetPort() != rObject.GetPort()
+ || HasParam() != rObject.HasParam()
+ || GetParam(NO_DECODE) != rObject.GetParam(NO_DECODE)
+ || GetMsgId(NO_DECODE) != rObject.GetMsgId(NO_DECODE))
+ return false;
+ UniString aPath1(GetURLPath(NO_DECODE));
+ UniString aPath2(rObject.GetURLPath(NO_DECODE));
+ if (m_eScheme == INET_PROT_FILE)
+ {
+ // If the URL paths of two file URLs only differ in that one has a
+ // final '/' and the other has not, take the two paths as equivalent
+ // (this could be usefull for other schemes, too):
+ xub_StrLen nLength = aPath1.Len();
+ switch (sal_Int32(nLength) - sal_Int32(aPath2.Len()))
+ {
+ case -1:
+ if (aPath2.GetChar(nLength) != '/')
+ return false;
+ break;
+
+ case 0:
+ break;
+
+ case 1:
+ if (aPath1.GetChar(--nLength) != '/')
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ return aPath1.CompareTo(aPath2, nLength) == COMPARE_EQUAL;
+ }
+ else
+ return (aPath1 == aPath2) != false;
+}
+
+//============================================================================
+bool INetURLObject::operator <(INetURLObject const & rObject) const
+{
+ switch (GetScheme(m_eScheme).CompareTo(GetScheme(rObject.m_eScheme)))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ sal_uInt32 nPort1 = GetPort();
+ sal_uInt32 nPort2 = rObject.GetPort();
+ if (nPort1 < nPort2)
+ return true;
+ else if (nPort1 > nPort2)
+ return false;
+ switch (GetUser(NO_DECODE).CompareTo(rObject.GetUser(NO_DECODE)))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ switch (GetPass(NO_DECODE).CompareTo(rObject.GetPass(NO_DECODE)))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ switch (GetHost(NO_DECODE).CompareTo(rObject.GetHost(NO_DECODE)))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ UniString aPath1(GetURLPath(NO_DECODE));
+ UniString aPath2(rObject.GetURLPath(NO_DECODE));
+ switch (aPath1.CompareTo(aPath2))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ switch (GetParam(NO_DECODE).CompareTo(rObject.GetParam(NO_DECODE)))
+ {
+ case COMPARE_LESS:
+ return true;
+
+ case COMPARE_GREATER:
+ return false;
+ }
+ return GetMsgId(NO_DECODE).CompareTo(rObject.GetMsgId(NO_DECODE))
+ == COMPARE_LESS;
+}
+
+//============================================================================
+bool INetURLObject::ConcatData(INetProtocol eTheScheme,
+ UniString const & rTheUser,
+ UniString const & rThePassword,
+ UniString const & rTheHost,
+ sal_uInt32 nThePort,
+ UniString const & rThePath,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ setInvalid();
+ m_eScheme = eTheScheme;
+ if (HasError())
+ return false;
+ m_aAbsURIRef.AssignAscii(getSchemeInfo().m_pScheme);
+ m_aAbsURIRef += ':';
+ if (getSchemeInfo().m_bAuthority)
+ {
+ m_aAbsURIRef.AppendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ bool bUserInfo = false;
+ if (getSchemeInfo().m_bUser)
+ {
+ if (m_eScheme == INET_PROT_IMAP && rTheUser.Len() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ if (rTheUser.Len() != 0)
+ {
+ m_aUser.set(m_aAbsURIRef,
+ encodeText(rTheUser, false,
+ m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism,
+ eCharset, false),
+ m_aAbsURIRef.Len());
+ bUserInfo = true;
+ }
+ }
+ else if (rTheUser.Len() != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ if (rThePassword.Len() != 0)
+ if (getSchemeInfo().m_bPassword)
+ {
+ m_aAbsURIRef += ':';
+ m_aAuth.set(m_aAbsURIRef,
+ encodeText(rThePassword, false,
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM : PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism,
+ eCharset, false),
+ m_aAbsURIRef.Len());
+ bUserInfo = true;
+ }
+ else
+ {
+ setInvalid();
+ return false;
+ }
+ if (bUserInfo && getSchemeInfo().m_bHost)
+ m_aAbsURIRef += '@';
+ if (getSchemeInfo().m_bHost)
+ {
+ UniString aSynHost(rTheHost);
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ if (aSynHost.EqualsIgnoreCaseAscii("localhost"))
+ aSynHost.Erase();
+ break;
+
+ case INET_PROT_LDAP:
+ if (aSynHost.Len() == 0 && nThePort != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+
+ default:
+ if (aSynHost.Len() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ if (aSynHost.Len() != 0)
+ {
+ sal_Unicode const * p = aSynHost.GetBuffer();
+ sal_Unicode const * pEnd = p + aSynHost.Len();
+ if (!parseHost(p, pEnd, false, eMechanism, eCharset, aSynHost)
+ || p != pEnd)
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ m_aHost.set(m_aAbsURIRef, aSynHost, m_aAbsURIRef.Len());
+ if (nThePort != 0)
+ if (getSchemeInfo().m_bPort)
+ {
+ m_aAbsURIRef += ':';
+ m_aPort.set(m_aAbsURIRef,
+ UniString::CreateFromInt64(nThePort),
+ m_aAbsURIRef.Len());
+ }
+ else
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ else if (rTheHost.Len() != 0 || nThePort != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ UniString aSynPath;
+ if (getSchemeInfo().m_bHierarchical
+ && rThePath.Len() == 0 || rThePath.GetChar(0) != '/')
+ aSynPath = '/';
+ aSynPath += rThePath;
+ m_aPath.set(m_aAbsURIRef,
+ encodeText(aSynPath, false,
+ m_eScheme == INET_PROT_FILE ?
+ PART_PATH_SEGMENTS_EXTRA :
+ m_eScheme == INET_PROT_NEWS
+ || m_eScheme == INET_PROT_POP3 ?
+ PART_MESSAGE_ID_PATH :
+ PART_HTTP_PATH,
+ getEscapePrefix(), eMechanism, eCharset, true),
+ m_aAbsURIRef.Len());
+ return true;
+}
+
+//============================================================================
+namespace unnamed_tools_urlobj {
+
+inline bool isWLetter(International const & rInternational, sal_Unicode c)
+{
+ return rInternational.IsAlphaNumeric(c) || c == '$' || c == '%'
+ || c == '&' || c == '-' || c == '/' || c == '@' || c == '\\';
+}
+
+inline bool checkWChar(International const & rInternational,
+ sal_Unicode const * p, sal_Unicode const *& rEnd,
+ bool bBackslash = false, bool bPipe = false)
+{
+ sal_Unicode c = *p;
+ if (rInternational.IsAlphaNumeric(c) || c == '/'
+ || c == '\\' && bBackslash || c == '|' && bPipe)
+ {
+ rEnd = p + 1;
+ return true;
+ }
+ else
+ return !mustEncode(c, INetURLObject::PART_URIC) || c == '%';
+}
+
+}
+
+// static
+UniString INetURLObject::FindFirstURLInText(UniString const & rText,
+ xub_StrLen & rBegin,
+ xub_StrLen & rEnd,
+ International const &
+ rInternational,
+ UniString const *,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!(rBegin <= rEnd && rEnd <= rText.Len()))
+ return UniString();
+
+ sal_Unicode const * pBegin = rText.GetBuffer() + rBegin;
+ sal_Unicode const * pEnd = rText.GetBuffer() + rEnd;
+
+ // Search for the first (longest possible) substring of [pBegin..pEnd[
+ // that matches any of the following productions. "\W" stands for a word
+ // break, i.e., the begin or end of the block of text, or a character that
+ // is neither a letter nor a digit (according to rInternational). The
+ // productions use the auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // IPv6reference = "[" IPv6address "]"
+ // IPv6address = hexpart [":" IPv4address]
+ // IPv4address = 1*3DIGIT 3("." 1*3DIGIT)
+ // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ // hexseq = hex4 *(":" hex4)
+ // hex4 = 1*4HEXDIG
+ // wchar = <any uric character (ignoring the escaped rule), or "%", or
+ // a letter or digit (according to rInternational)>
+ //
+ // 1st Production (file):
+ // \W "file:" 1*(wchar / "\" / "|") ["#" 1*wchar] \W
+ //
+ // 2nd Production (known scheme):
+ // \W <one of the known schemes, ignoring case> ":" 1*wchar
+ // ["#" 1*wchar] \W
+ //
+ // 3rd Production (mailto):
+ // \W domain "@" domain \W
+ //
+ // 4th Production (ftp):
+ // \W "ftp" 2*("." label) ["/" *wchar] ["#" 1*wchar] \W
+ //
+ // 5th Production (http):
+ // \W label 2*("." label) ["/" *wchar] ["#" 1*wchar] \W
+ //
+ // 6th Production (file):
+ // \W "//" (domain / IPv6reference) ["/" *wchar] ["#" 1*wchar] \W
+ //
+ // 7th Production (Unix file):
+ // \W "/" 1*wchar \W
+ //
+ // 8th Production (UNC file):
+ // \W "\\" domain ["\" *(wchar / "\")] \W
+ //
+ // 9th Production (Unix-like DOS file):
+ // \W ALPHA ":/" *wchar \W
+ //
+ // 10th Production (DOS file):
+ // \W ALPHA ":\" *(wchar / "\") \W
+
+ for (sal_Unicode const * pPos = pBegin; pPos != pEnd;)
+ if ((INetMIME::isAlpha(*pPos) || *pPos == '/' || *pPos == '\\')
+ && (pPos == pBegin || !isWLetter(rInternational, pPos[-1])))
+ {
+ sal_Unicode const * pURIEnd = 0;
+
+ if (INetMIME::isAlpha(*pPos))
+ {
+ sal_Unicode const * p = pPos;
+ sal_Unicode const * pPrefixEnd = p;
+ PrefixInfo const * pPrefix = getPrefix(pPrefixEnd, pEnd);
+ if (pPrefix) // 1st, 2nd
+ {
+ while (*p++ != ':');
+ pPrefixEnd = p;
+ if (pPrefix->m_eScheme == INET_PROT_FILE)
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd, true,
+ true))
+ ++p;
+ else
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ if (p != pPrefixEnd && *p == '#')
+ {
+ ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ }
+ }
+ else if (pEnd - p >= 3 && p[1] == ':' && p[2] == '/') // 9th
+ {
+ p += 3;
+ pURIEnd = p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ }
+ else if (pEnd - p >= 3 && p[1] == ':' && p[2] == '\\') // 10th
+ {
+ p += 3;
+ pURIEnd = p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd, true))
+ ++p;
+ }
+ else
+ {
+ sal_uInt32 nLabels = scanDomain(p, pEnd, false);
+ if (nLabels > 0 && p != pEnd && *p == '@') // 3rd
+ {
+ ++p;
+ if (scanDomain(p, pEnd, false) > 0)
+ pURIEnd = p;
+ }
+ else if (nLabels >= 3) // 4th, 5th
+ {
+ pURIEnd = p;
+ if (p != pEnd && *p == '/')
+ {
+ pURIEnd = ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ }
+ if (p != pEnd && *p == '#')
+ {
+ ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ }
+ }
+ }
+ }
+ else if (*pPos == '/')
+ {
+ sal_Unicode const * p = pPos;
+ if (pEnd - p >= 2)
+ if (p[1] == '/') // 6th
+ {
+ p += 2;
+ if (scanDomain(p, pEnd, false) > 0
+ || scanIPv6reference(p, pEnd, false))
+ {
+ pURIEnd = p;
+ if (p != pEnd && *p == '/')
+ {
+ pURIEnd = ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p,
+ pURIEnd))
+ ++p;
+ }
+ if (p != pEnd && *p == '#')
+ {
+ ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p,
+ pURIEnd))
+ ++p;
+ }
+ }
+ }
+ else // 7th
+ {
+ ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd))
+ ++p;
+ }
+ }
+ else if (*pPos == '\\') // 8th
+ {
+ sal_Unicode const * p = pPos;
+ if (pEnd - p >= 2 && p[1] == '\\')
+ {
+ p += 2;
+ if (scanDomain(p, pEnd, false) > 0)
+ {
+ pURIEnd = p;
+ if (p != pEnd && *p == '\\')
+ {
+ pURIEnd = ++p;
+ while (p != pEnd
+ && checkWChar(rInternational, p, pURIEnd,
+ true))
+ ++p;
+ }
+ }
+ }
+ }
+
+ if (pURIEnd
+ && (pURIEnd == pEnd || !isWLetter(rInternational, *pURIEnd)))
+ {
+ INetURLObject aURI(UniString(pPos, pURIEnd - pPos),
+ INET_PROT_HTTP, eMechanism, eCharset);
+ if (!aURI.HasError())
+ {
+ rBegin += pPos - pBegin;
+ rEnd -= pEnd - pURIEnd;
+ return aURI.GetMainURL();
+ }
+ }
+
+ ++pPos;
+ while (pPos != pEnd && isWLetter(rInternational, *pPos))
+ ++pPos;
+ }
+ else
+ ++pPos;
+
+ rBegin = rEnd;
+ return UniString();
+}
+
+//============================================================================
+UniString INetURLObject::getExternalURL(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ UniString aTheExtURIRef;
+ translateToExternal(m_aAbsURIRef, aTheExtURIRef, NOT_CANONIC, eMechanism,
+ eCharset);
+ return aTheExtURIRef;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::GetScheme(INetProtocol eTheScheme)
+{
+ return UniString::CreateFromAscii(getSchemeInfo(eTheScheme).m_pPrefix);
+}
+
+//============================================================================
+// static
+INetProtocol INetURLObject::CompareProtocolScheme(UniString const &
+ rTheAbsURIRef)
+{
+ sal_Unicode const * p = rTheAbsURIRef.GetBuffer();
+ PrefixInfo const * pPrefix = getPrefix(p, p + rTheAbsURIRef.Len());
+ return pPrefix ? pPrefix->m_eScheme : INET_PROT_NOT_VALID;
+}
+
+//============================================================================
+bool INetURLObject::hasPassword() const
+{
+ return m_aAuth.isPresent() && getSchemeInfo().m_bPassword;
+}
+
+//============================================================================
+void INetURLObject::makeAuthCanonic()
+{
+ if (m_eScheme == INET_PROT_IMAP && m_aAuth.getLength() == 1
+ && m_aAbsURIRef.GetChar(m_aAuth.getBegin()) == '*')
+ {
+ m_aAbsURIRef.Erase(m_aAuth.getBegin()
+ - RTL_CONSTASCII_LENGTH(";AUTH="),
+ RTL_CONSTASCII_LENGTH(";AUTH=*"));
+ sal_Int32 nDelta = m_aAuth.clear() - RTL_CONSTASCII_LENGTH(";AUTH=");
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+}
+
+//============================================================================
+UniString INetURLObject::GetHostPort(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ UniString aHostPort(decode(m_aHost, getEscapePrefix(), eMechanism,
+ eCharset));
+ if (m_aPort.isPresent())
+ {
+ aHostPort += ':';
+ aHostPort += decode(m_aPort, getEscapePrefix(), eMechanism, eCharset);
+ }
+ return aHostPort;
+}
+
+//============================================================================
+sal_uInt32 INetURLObject::GetPort() const
+{
+ if (m_aPort.isPresent())
+ {
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPort.getBegin();
+ sal_Unicode const * pEnd = p + m_aPort.getLength();
+ sal_uInt32 nThePort;
+ if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd)
+ return nThePort;
+ }
+ return 0;
+}
+
+//============================================================================
+bool INetURLObject::SetPort(sal_uInt32 nThePort)
+{
+ if (getSchemeInfo().m_bPort && m_aHost.isPresent())
+ {
+ UniString aNewPort(UniString::CreateFromInt64(nThePort));
+ sal_Int32 nDelta;
+ if (m_aPort.isPresent())
+ nDelta = m_aPort.set(m_aAbsURIRef, aNewPort);
+ else
+ {
+ m_aAbsURIRef.Insert(':', m_aHost.getEnd());
+ nDelta = m_aPort.set(m_aAbsURIRef, aNewPort, m_aHost.getEnd() + 1)
+ + 1;
+ }
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+ }
+ return false;
+}
+
+//============================================================================
+void INetURLObject::makePortCanonic()
+{
+ if (m_aPort.isPresent())
+ {
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPort.getBegin();
+ sal_Unicode const * pEnd = p + m_aPort.getLength();
+ sal_uInt32 nThePort;
+ if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd)
+ {
+ sal_Int32 nDelta;
+ if (nThePort != 0 && nThePort == getSchemeInfo().m_nDefaultPort)
+ {
+ m_aAbsURIRef.Erase(m_aPort.getBegin() - 1,
+ m_aPort.getLength() + 1);
+ nDelta = m_aPort.clear() - 1;
+ }
+ else
+ nDelta = m_aPort.set(m_aAbsURIRef,
+ UniString::CreateFromInt64(nThePort));
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+ }
+}
+
+//============================================================================
+// static
+bool INetURLObject::parseHost(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset, UniString & rCanonic)
+{
+ enum State { STATE_INITIAL, STATE_LABEL, STATE_LABEL_HYPHEN,
+ STATE_LABEL_DOT, STATE_TOPLABEL, STATE_TOPLABEL_HYPHEN,
+ STATE_TOPLABEL_DOT, STATE_IP4, STATE_IP4_DOT, STATE_IP6,
+ STATE_IP6_COLON, STATE_IP6_2COLON, STATE_IP6_3COLON,
+ STATE_IP6_HEXSEQ1, STATE_IP6_HEXSEQ1_COLON,
+ STATE_IP6_HEXSEQ1_MAYBE_IP4, STATE_IP6_HEXSEQ2,
+ STATE_IP6_HEXSEQ2_COLON, STATE_IP6_HEXSEQ2_MAYBE_IP4,
+ STATE_IP6_IP4, STATE_IP6_IP4_DOT, STATE_IP6_DONE };
+ UniString aTheCanonic;
+ sal_uInt32 nNumber;
+ int nDigits;
+ int nOctets;
+ State eState = STATE_INITIAL;
+ sal_Unicode const * p = rBegin;
+ for (; p != pEnd; ++p)
+ switch (eState)
+ {
+ case STATE_INITIAL:
+ if (*p == '[')
+ {
+ aTheCanonic = '[';
+ eState = STATE_IP6;
+ }
+ else if (INetMIME::isAlpha(*p))
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ nOctets = 1;
+ eState = STATE_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_LABEL:
+ if (*p == '.')
+ eState = STATE_LABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_LABEL_HYPHEN;
+ else if (!INetMIME::isAlphanumeric(*p))
+ goto done;
+ break;
+
+ case STATE_LABEL_HYPHEN:
+ if (INetMIME::isAlphanumeric(*p))
+ eState = STATE_LABEL;
+ else if (*p != '-')
+ goto done;
+ break;
+
+ case STATE_LABEL_DOT:
+ if (INetMIME::isAlpha(*p))
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_TOPLABEL:
+ if (*p == '.')
+ eState = STATE_TOPLABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_TOPLABEL_HYPHEN;
+ else if (!INetMIME::isAlphanumeric(*p))
+ goto done;
+ break;
+
+ case STATE_TOPLABEL_HYPHEN:
+ if (INetMIME::isAlphanumeric(*p))
+ eState = STATE_TOPLABEL;
+ else if (*p != '-')
+ goto done;
+ break;
+
+ case STATE_TOPLABEL_DOT:
+ if (INetMIME::isAlpha(*p))
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_IP4:
+ if (*p == '.')
+ if (nOctets < 4)
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ aTheCanonic += '.';
+ ++nOctets;
+ eState = STATE_IP4_DOT;
+ }
+ else
+ eState = STATE_LABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_LABEL_HYPHEN;
+ else if (INetMIME::isAlpha(*p))
+ eState = STATE_LABEL;
+ else if (INetMIME::isDigit(*p))
+ if (nDigits < 3)
+ {
+ nNumber = 10 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_IP4_DOT:
+ if (INetMIME::isAlpha(*p))
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6:
+ if (*p == ':')
+ eState = STATE_IP6_COLON;
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_COLON:
+ if (*p == ':')
+ {
+ aTheCanonic.AppendAscii(RTL_CONSTASCII_STRINGPARAM("::"));
+ eState = STATE_IP6_2COLON;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_2COLON:
+ if (*p == ']')
+ eState = STATE_IP6_DONE;
+ else if (*p == ':')
+ {
+ aTheCanonic += ':';
+ eState = STATE_IP6_3COLON;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_3COLON:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ nOctets = 1;
+ eState = STATE_IP6_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1:
+ if (*p == ']')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ aTheCanonic += ':';
+ eState = STATE_IP6_HEXSEQ1_COLON;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1_COLON:
+ if (*p == ':')
+ {
+ aTheCanonic.AppendAscii(RTL_CONSTASCII_STRINGPARAM("::"));
+ eState = STATE_IP6_2COLON;
+ }
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1_MAYBE_IP4;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1_MAYBE_IP4:
+ if (*p == ']')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ aTheCanonic += ':';
+ eState = STATE_IP6_HEXSEQ1_COLON;
+ }
+ else if (*p == '.')
+ {
+ nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15)
+ + (nNumber & 15);
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ aTheCanonic += '.';
+ nOctets = 2;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 16 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2:
+ if (*p == ']')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ aTheCanonic += ':';
+ eState = STATE_IP6_HEXSEQ2_COLON;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2_COLON:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2_MAYBE_IP4;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2_MAYBE_IP4:
+ if (*p == ']')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber, 16);
+ aTheCanonic += ':';
+ eState = STATE_IP6_HEXSEQ2_COLON;
+ }
+ else if (*p == '.')
+ {
+ nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15)
+ + (nNumber & 15);
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ aTheCanonic += '.';
+ nOctets = 2;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 16 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_IP4:
+ if (*p == ']')
+ if (nOctets == 4)
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ eState = STATE_IP6_DONE;
+ }
+ else
+ goto done;
+ else if (*p == '.')
+ if (nOctets < 4)
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ aTheCanonic += '.';
+ ++nOctets;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else
+ goto done;
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 10 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_IP4_DOT:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_IP4;
+ }
+ else
+ goto done;
+ break;
+ }
+ done:
+ switch (eState)
+ {
+ case STATE_LABEL:
+ case STATE_TOPLABEL:
+ case STATE_TOPLABEL_DOT:
+ aTheCanonic.Assign(rBegin, p - rBegin);
+ rBegin = p;
+ rCanonic = aTheCanonic;
+ return true;
+
+ case STATE_IP4:
+ if (nOctets == 4)
+ {
+ aTheCanonic += UniString::CreateFromInt32(nNumber);
+ rBegin = p;
+ rCanonic = aTheCanonic;
+ return true;
+ }
+ break;
+
+ case STATE_IP6_DONE:
+ aTheCanonic += ']';
+ rBegin = p;
+ rCanonic = aTheCanonic;
+ return true;
+ }
+ return false;
+}
+
+//============================================================================
+sal_Int32 INetURLObject::getSegmentCount(bool bIgnoreFinalSlash) const
+{
+ if (!getSchemeInfo().m_bHierarchical)
+ return 0;
+
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ if (p == pEnd || *p != '/')
+ return 0;
+
+ if (bIgnoreFinalSlash && pEnd[-1] == '/')
+ --pEnd;
+
+ sal_Int32 n = 0;
+ while (p != pEnd)
+ if (*p++ == '/')
+ ++n;
+ return n;
+}
+
+//============================================================================
+bool INetURLObject::removeSegment(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ UniString aNewPath(m_aAbsURIRef, m_aPath.getBegin(),
+ aSegment.getBegin() - m_aPath.getBegin());
+ if (bIgnoreFinalSlash && aSegment.getEnd() == m_aPath.getEnd())
+ aNewPath += '/';
+ else
+ aNewPath.Append(m_aAbsURIRef.GetBuffer() + aSegment.getEnd(),
+ m_aPath.getEnd() - aSegment.getEnd());
+ if (aNewPath.Len() == 0)
+ aNewPath = '/';
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+UniString INetURLObject::getName(sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return UniString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * p = pSegBegin;
+ while (p != pSegEnd && *p != ';')
+ ++p;
+
+ return decode(pSegBegin, p, getEscapePrefix(), eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setName(UniString const & rTheName, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * p = pSegBegin;
+ while (p != pSegEnd && *p != ';')
+ ++p;
+
+ UniString aNewPath(pPathBegin, pSegBegin - pPathBegin);
+ aNewPath += encodeText(rTheName, false, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true);
+ aNewPath.Append(p, pPathEnd - p);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::hasExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+ const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ for (sal_Unicode const * p = pSegBegin; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ return true;
+ return false;
+}
+
+//============================================================================
+UniString INetURLObject::getBase(sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return UniString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ return decode(pSegBegin, pExtension, getEscapePrefix(), eMechanism,
+ eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setBase(UniString const & rTheBase, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ UniString aNewPath(pPathBegin, pSegBegin - pPathBegin);
+ aNewPath += encodeText(rTheBase, false, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true);
+ aNewPath.Append(pExtension, pPathEnd - pExtension);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+UniString INetURLObject::getExtension(sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return UniString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+
+ if (!pExtension)
+ return UniString();
+
+ return decode(pExtension + 1, p, getEscapePrefix(), eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setExtension(UniString const & rTheExtension,
+ sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ UniString aNewPath(pPathBegin, pExtension - pPathBegin);
+ aNewPath += '.';
+ aNewPath += encodeText(rTheExtension, false, PART_PCHAR,
+ getEscapePrefix(), eMechanism, eCharset, true);
+ aNewPath.Append(p, pPathEnd - p);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::removeExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.GetBuffer() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ return true;
+
+ UniString aNewPath(pPathBegin, pExtension - pPathBegin);
+ aNewPath.Append(p, pPathEnd - p);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::hasFinalSlash() const
+{
+ if (!getSchemeInfo().m_bHierarchical)
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathBegin == pPathEnd || *pPathBegin != '/')
+ return false;
+
+ return pPathEnd[-1] == '/';
+}
+
+//============================================================================
+bool INetURLObject::setFinalSlash()
+{
+ if (!getSchemeInfo().m_bHierarchical)
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathBegin == pPathEnd || *pPathBegin != '/')
+ return false;
+
+ if (pPathEnd[-1] == '/')
+ return true;
+
+ UniString aNewPath(pPathBegin, pPathEnd - pPathBegin);
+ aNewPath += '/';
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::removeFinalSlash()
+{
+ if (!getSchemeInfo().m_bHierarchical)
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathBegin == pPathEnd || *pPathBegin != '/')
+ return false;
+
+ if (pPathEnd[-1] != '/')
+ return true;
+
+ --pPathEnd;
+ if (pPathEnd == pPathBegin)
+ return false;
+ UniString aNewPath(pPathBegin, pPathEnd - pPathBegin);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+// static
+UniString INetURLObject::createFragment(UniString const & rText)
+{
+ UniString aFragment(rText);
+ for (xub_StrLen i = 0; i < aFragment.Len();)
+ {
+ sal_Unicode c = aFragment.GetChar(i);
+ if (mustEncode(aFragment.GetChar(i), PART_CREATEFRAGMENT))
+ aFragment.Erase(i, 1);
+ else
+ ++i;
+ }
+ return aFragment;
+}
+
+//============================================================================
+bool INetURLObject::setFSysPath(UniString const & rFSysPath, FSysStyle eStyle)
+{
+ sal_Unicode const * pFSysBegin = rFSysPath.GetBuffer();
+ sal_Unicode const * pFSysEnd = pFSysBegin + rFSysPath.Len();
+
+ switch ((eStyle & FSYS_VOS ? 1 : 0)
+ + (eStyle & FSYS_UNX ? 1 : 0)
+ + (eStyle & FSYS_DOS ? 1 : 0)
+ + (eStyle & FSYS_MAC ? 1 : 0))
+ {
+ case 0:
+ return false;
+
+ case 1:
+ break;
+
+ default:
+ if (eStyle & FSYS_VOS
+ && pFSysEnd - pFSysBegin >= 2
+ && pFSysBegin[0] == '/'
+ && pFSysBegin[1] == '/')
+ {
+ if (pFSysEnd - pFSysBegin >= 3
+ && pFSysBegin[2] == '.'
+ && (pFSysEnd - pFSysBegin == 3 || pFSysBegin[3] == '/'))
+ {
+ eStyle = FSYS_VOS; // Production T1
+ break;
+ }
+
+ sal_Unicode const * p = pFSysBegin + 2;
+ UniString aHost;
+ if (parseHost(p, pFSysEnd, false, ENCODE_ALL,
+ RTL_TEXTENCODING_UTF8, aHost)
+ && (p == pFSysEnd || *p == '/'))
+ {
+ eStyle = FSYS_VOS; // Production T2
+ break;
+ }
+ }
+
+ if (eStyle & FSYS_DOS
+ && pFSysEnd - pFSysBegin >= 2
+ && pFSysBegin[0] == '\\'
+ && pFSysBegin[1] == '\\')
+ {
+ sal_Unicode const * p = pFSysBegin + 2;
+ UniString aHost;
+ if (parseHost(p, pFSysEnd, false, ENCODE_ALL,
+ RTL_TEXTENCODING_UTF8, aHost)
+ && (p == pFSysEnd || *p == '\\'))
+ {
+ eStyle = FSYS_DOS; // Production T3
+ break;
+ }
+ }
+
+ if (eStyle & FSYS_DOS
+ && pFSysEnd - pFSysBegin >= 3
+ && INetMIME::isAlpha(pFSysBegin[0])
+ && pFSysBegin[1] == ':'
+ && (pFSysBegin[2] == '/' || pFSysBegin[2] == '\\'))
+ {
+ eStyle = FSYS_DOS; // Productions T4, T5
+ break;
+ }
+
+ if (!(eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC)))
+ return false;
+
+ eStyle = guessFSysStyleByCounting(pFSysBegin, pFSysEnd, eStyle);
+ // Production T6
+ break;
+ }
+
+ UniString aSynAbsURIRef(RTL_CONSTASCII_USTRINGPARAM("file://"));
+ switch (eStyle)
+ {
+ case FSYS_VOS:
+ {
+ sal_Unicode const * p = pFSysBegin;
+ if (pFSysEnd - p < 2 || *p++ != '/' || *p++ != '/')
+ return false;
+ if (p != pFSysEnd && *p == '.'
+ && (pFSysEnd - p == 1 || p[1] == '/'))
+ ++p;
+ for (; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef += *p;
+ break;
+ }
+ break;
+ }
+
+ case FSYS_UNX:
+ {
+ sal_Unicode const * p = pFSysBegin;
+ if (p != pFSysEnd && *p != '/')
+ return false;
+ for (; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case '|':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef += *p;
+ break;
+ }
+ break;
+ }
+
+ case FSYS_DOS:
+ {
+ sal_uInt32 nAltDelimiter = 0x80000000;
+ sal_Unicode const * p = pFSysBegin;
+ if (pFSysEnd - p >= 3 && p[0] == '\\' && p[1] == '\\')
+ p += 2;
+ else
+ {
+ aSynAbsURIRef += '/';
+ if (pFSysEnd - p >= 3 && INetMIME::isAlpha(p[0])
+ && p[1] == ':' && (p[2] == '\\' || p[2] == '/'))
+ nAltDelimiter = '/';
+ }
+ for (; p != pFSysEnd; ++p)
+ if (*p == '\\' || *p == nAltDelimiter)
+ aSynAbsURIRef += '/';
+ else
+ switch (*p)
+ {
+ case '/':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef += *p;
+ break;
+ }
+ break;
+ }
+
+ case FSYS_MAC:
+ aSynAbsURIRef += '/';
+ {for (sal_Unicode const * p = pFSysBegin; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case ':':
+ aSynAbsURIRef += '/';
+ break;
+
+ case '/':
+ case '|':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef += *p;
+ break;
+ }
+ }
+ break;
+ }
+
+ INetURLObject aTemp(aSynAbsURIRef, WAS_ENCODED, RTL_TEXTENCODING_UTF8);
+ if (aTemp.HasError())
+ return false;
+
+ *this = aTemp;
+ return true;
+}
+
+//============================================================================
+UniString INetURLObject::getFSysPath(FSysStyle eStyle,
+ sal_Unicode * pDelimiter) const
+{
+ if (m_eScheme != INET_PROT_FILE)
+ return UniString();
+
+ if ((eStyle & FSYS_VOS ? 1 : 0)
+ + (eStyle & FSYS_UNX ? 1 : 0)
+ + (eStyle & FSYS_DOS ? 1 : 0)
+ + (eStyle & FSYS_MAC ? 1 : 0)
+ > 1)
+ {
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ eStyle = eStyle & FSYS_VOS
+ && m_aHost.isPresent()
+ && m_aHost.getLength() > 0 ?
+ FSYS_VOS :
+ eStyle & FSYS_DOS
+ && (!m_aHost.isPresent() || m_aHost.getLength() == 0)
+ && m_aPath.getLength() >= 3
+ && p[0] == '/'
+ && INetMIME::isAlpha(p[1])
+ && p[2] == ':'
+ && (m_aPath.getLength() == 3 || p[3] == '/') ?
+ FSYS_DOS :
+ eStyle & FSYS_UNX
+ && (!m_aHost.isPresent() || m_aHost.getLength() == 0) ?
+ FSYS_UNX :
+ FSysStyle(0);
+ }
+
+ switch (eStyle)
+ {
+ case FSYS_VOS:
+ {
+ if (pDelimiter)
+ *pDelimiter = '/';
+
+ UniString aSynFSysPath(RTL_CONSTASCII_USTRINGPARAM("//"));
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ aSynFSysPath += decode(m_aHost, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8);
+ else
+ aSynFSysPath += '.';
+ aSynFSysPath += decode(m_aPath, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8);
+ return aSynFSysPath;
+ }
+
+ case FSYS_UNX:
+ {
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ return UniString();
+
+ if (pDelimiter)
+ *pDelimiter = '/';
+
+ return decode(m_aPath, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8);
+ }
+
+ case FSYS_DOS:
+ {
+ if (pDelimiter)
+ *pDelimiter = '\\';
+
+ UniString aSynFSysPath;
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ {
+ aSynFSysPath.AssignAscii(RTL_CONSTASCII_STRINGPARAM("\\\\"));
+ aSynFSysPath += decode(m_aHost, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8);
+ aSynFSysPath += '\\';
+ }
+ sal_Unicode const * p
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ DBG_ASSERT(p < pEnd && *p == '/',
+ "INetURLObject::getFSysPath(): Bad path");
+ ++p;
+ while (p < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED,
+ RTL_TEXTENCODING_UTF8,
+ eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aSynFSysPath += '\\';
+ else
+ appendUTF32(aSynFSysPath, nUTF32);
+ }
+ return aSynFSysPath;
+ }
+
+ case FSYS_MAC:
+ {
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ return UniString();
+
+ if (pDelimiter)
+ *pDelimiter = ':';
+
+ UniString aSynFSysPath;
+ sal_Unicode const * p
+ = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ DBG_ASSERT(p < pEnd && *p == '/',
+ "INetURLObject::getFSysPath(): Bad path");
+ ++p;
+ while (p < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED,
+ RTL_TEXTENCODING_UTF8,
+ eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aSynFSysPath += ':';
+ else
+ appendUTF32(aSynFSysPath, nUTF32);
+ }
+ return aSynFSysPath;
+ }
+ }
+
+ return UniString();
+}
+
+//============================================================================
+bool INetURLObject::HasMsgId() const
+{
+ if (m_eScheme != INET_PROT_NEWS && m_eScheme != INET_PROT_POP3)
+ return false;
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ for (; p < pEnd; ++p)
+ if (*p == '<')
+ return true;
+ return false;
+}
+
+//============================================================================
+UniString INetURLObject::GetMsgId(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ if (m_eScheme != INET_PROT_NEWS && m_eScheme != INET_PROT_POP3)
+ return UniString();
+ sal_Unicode const * p = m_aAbsURIRef.GetBuffer() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ for (; p < pEnd; ++p)
+ if (*p == '<')
+ return decode(p, pEnd, getEscapePrefix(), eMechanism, eCharset);
+ return UniString();
+}
+
+//============================================================================
+// static
+void INetURLObject::appendUCS4Escape(UniString & rTheText,
+ sal_Char cEscapePrefix, sal_uInt32 nUCS4)
+{
+ DBG_ASSERT(nUCS4 < 0x80000000,
+ "INetURLObject::appendUCS4Escape(): Bad char");
+ if (nUCS4 < 0x80)
+ appendEscape(rTheText, cEscapePrefix, nUCS4);
+ else if (nUCS4 < 0x800)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 | 0xC0);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 & 0x3F | 0x80);
+ }
+ else if (nUCS4 < 0x10000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 | 0xE0);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 & 0x3F | 0x80);
+ }
+ else if (nUCS4 < 0x200000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 18 | 0xF0);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 & 0x3F | 0x80);
+ }
+ else if (nUCS4 < 0x4000000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 24 | 0xF8);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 18 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 & 0x3F | 0x80);
+ }
+ else
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 30 | 0xFC);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 24 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 18 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 & 0x3F | 0x80);
+ appendEscape(rTheText, cEscapePrefix, nUCS4 & 0x3F | 0x80);
+ }
+}
+
+//============================================================================
+// static
+void INetURLObject::appendUCS4(UniString & rTheText, sal_uInt32 nUCS4,
+ EscapeType eEscapeType, bool bOctets,
+ Part ePart, sal_Char cEscapePrefix,
+ rtl_TextEncoding eCharset,
+ bool bKeepVisibleEscapes)
+{
+ bool bEscape;
+ rtl_TextEncoding eTargetCharset;
+ switch (eEscapeType)
+ {
+ case ESCAPE_NO:
+ if (mustEncode(nUCS4, ePart))
+ {
+ bEscape = true;
+ eTargetCharset = bOctets ? RTL_TEXTENCODING_ISO_8859_1 :
+ RTL_TEXTENCODING_UTF8;
+ }
+ else
+ bEscape = false;
+ break;
+
+ case ESCAPE_OCTET:
+ bEscape = true;
+ eTargetCharset = RTL_TEXTENCODING_ISO_8859_1;
+ break;
+
+ case ESCAPE_UTF32:
+ if (mustEncode(nUCS4, ePart))
+ {
+ bEscape = true;
+ eTargetCharset = eCharset;
+ }
+ else if (bKeepVisibleEscapes && INetMIME::isVisible(nUCS4))
+ {
+ bEscape = true;
+ eTargetCharset = RTL_TEXTENCODING_ASCII_US;
+ }
+ else
+ bEscape = false;
+ break;
+ }
+ if (bEscape)
+ switch (eTargetCharset)
+ {
+ default:
+ DBG_ERROR("INetURLObject::appendUCS4(): Unsupported charset");
+ case RTL_TEXTENCODING_ASCII_US:
+ case RTL_TEXTENCODING_ISO_8859_1:
+ appendEscape(rTheText, cEscapePrefix, nUCS4);
+ break;
+
+ case RTL_TEXTENCODING_UTF8:
+ appendUCS4Escape(rTheText, cEscapePrefix, nUCS4);
+ break;
+ }
+ else
+ rTheText += sal_Unicode(nUCS4);
+}
+
+//============================================================================
+// static
+sal_uInt32 INetURLObject::getUTF32(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd, bool bOctets,
+ sal_Char cEscapePrefix,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ EscapeType & rEscapeType)
+{
+ DBG_ASSERT(rBegin < pEnd, "INetURLObject::getUTF32(): Bad sequence");
+ sal_uInt32 nUTF32 = bOctets ? *rBegin++ :
+ INetMIME::getUTF32Character(rBegin, pEnd);
+ switch (eMechanism)
+ {
+ case ENCODE_ALL:
+ rEscapeType = ESCAPE_NO;
+ break;
+
+ case WAS_ENCODED:
+ {
+ int nWeight1;
+ int nWeight2;
+ if (nUTF32 == cEscapePrefix && rBegin + 1 < pEnd
+ && (nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0
+ && (nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0)
+ {
+ rBegin += 2;
+ nUTF32 = nWeight1 << 4 | nWeight2;
+ switch (eCharset)
+ {
+ default:
+ DBG_ERROR(
+ "INetURLObject::getUTF32(): Unsupported charset");
+ case RTL_TEXTENCODING_ASCII_US:
+ rEscapeType = INetMIME::isUSASCII(nUTF32) ?
+ ESCAPE_UTF32 : ESCAPE_OCTET;
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_1:
+ rEscapeType = ESCAPE_UTF32;
+ break;
+
+ case RTL_TEXTENCODING_UTF8:
+ if (INetMIME::isUSASCII(nUTF32))
+ rEscapeType = ESCAPE_UTF32;
+ else
+ {
+ if (nUTF32 >= 0xC0 && nUTF32 <= 0xF4)
+ {
+ sal_uInt32 nEncoded;
+ int nShift;
+ sal_uInt32 nMin;
+ if (nUTF32 <= 0xDF)
+ {
+ nEncoded = (nUTF32 & 0x1F) << 6;
+ nShift = 0;
+ nMin = 0x80;
+ }
+ else if (nUTF32 <= 0xEF)
+ {
+ nEncoded = (nUTF32 & 0x0F) << 12;
+ nShift = 6;
+ nMin = 0x800;
+ }
+ else
+ {
+ nEncoded = (nUTF32 & 0x07) << 18;
+ nShift = 12;
+ nMin = 0x10000;
+ }
+ sal_Unicode const * p = rBegin;
+ bool bUTF8 = true;
+ for (;;)
+ {
+ if (pEnd - p < 3
+ || p[0] != cEscapePrefix
+ || (nWeight1
+ = INetMIME::getHexWeight(p[1]))
+ < 8
+ || nWeight1 > 11
+ || (nWeight2
+ = INetMIME::getHexWeight(p[2]))
+ < 0)
+ {
+ bUTF8 = false;
+ break;
+ }
+ p += 3;
+ nEncoded
+ |= ((nWeight1 & 3) << 4 | nWeight2)
+ << nShift;
+ if (nShift == 0)
+ break;
+ nShift -= 6;
+ }
+ if (bUTF8 && nEncoded >= nMin
+ && !INetMIME::isHighSurrogate(nEncoded)
+ && !INetMIME::isLowSurrogate(nEncoded)
+ && nEncoded <= 0x10FFFF)
+ {
+ rBegin = p;
+ nUTF32 = nEncoded;
+ rEscapeType = ESCAPE_UTF32;
+ break;
+ }
+ }
+ rEscapeType = ESCAPE_OCTET;
+ }
+ break;
+ }
+ }
+ else
+ rEscapeType = ESCAPE_NO;
+ break;
+ }
+
+ case NOT_CANONIC:
+ {
+ int nWeight1;
+ int nWeight2;
+ if (nUTF32 == cEscapePrefix && rBegin + 1 < pEnd
+ && ((nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0)
+ && ((nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0))
+ {
+ rBegin += 2;
+ nUTF32 = nWeight1 << 4 | nWeight2;
+ rEscapeType = ESCAPE_OCTET;
+ }
+ else
+ rEscapeType = ESCAPE_NO;
+ break;
+ }
+ }
+ return nUTF32;
+}
+
+//============================================================================
+// static
+sal_uInt32 INetURLObject::scanDomain(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd,
+ bool bEager)
+{
+ enum State { STATE_DOT, STATE_LABEL, STATE_HYPHEN };
+ State eState = STATE_DOT;
+ xub_StrLen nLabels = 0;
+ sal_Unicode const * pLastAlphanumeric = 0;
+ for (sal_Unicode const * p = rBegin;; ++p)
+ switch (eState)
+ {
+ case STATE_DOT:
+ if (p != pEnd && INetMIME::isAlphanumeric(*p))
+ {
+ ++nLabels;
+ eState = STATE_LABEL;
+ break;
+ }
+ if (bEager || nLabels == 0)
+ return 0;
+ rBegin = p - 1;
+ return nLabels;
+
+ case STATE_LABEL:
+ if (p != pEnd)
+ if (INetMIME::isAlphanumeric(*p))
+ break;
+ else if (*p == '.')
+ {
+ eState = STATE_DOT;
+ break;
+ }
+ else if (*p == '-')
+ {
+ pLastAlphanumeric = p;
+ eState = STATE_HYPHEN;
+ break;
+ }
+ rBegin = p;
+ return nLabels;
+
+ case STATE_HYPHEN:
+ if (p != pEnd)
+ if (INetMIME::isAlphanumeric(*p))
+ {
+ eState = STATE_LABEL;
+ break;
+ }
+ else if (*p == '-')
+ break;
+ if (bEager)
+ return 0;
+ rBegin = pLastAlphanumeric;
+ return nLabels;
+ }
+}
+
+//============================================================================
+// static
+bool INetURLObject::scanIPv6reference(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd,
+ bool bEager)
+{
+ return false; //@@@
+}
+
+//============================================================================
+// static
+UniString INetURLObject::RelToAbs(ByteString const & rTheRelURIRef,
+ bool bIgnoreFragment,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle)
+{
+ // Backwards compatibility:
+ if (rTheRelURIRef.Len() == 0 || rTheRelURIRef.GetChar(0) == '#')
+ return extend(rTheRelURIRef);
+
+ INetURLObject aTheAbsURIRef;
+ bool bWasAbsolute;
+ m_aBaseURIRef.convertRelToAbs(extend(rTheRelURIRef), true, aTheAbsURIRef,
+ bWasAbsolute, eEncodeMechanism, eCharset,
+ bIgnoreFragment, false, false, eStyle);
+ return aTheAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
+}
+
+//============================================================================
+// static
+UniString INetURLObject::RelToAbs(UniString const & rTheRelURIRef,
+ bool bIgnoreFragment,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle)
+{
+ // Backwards compatibility:
+ if (rTheRelURIRef.Len() == 0 || rTheRelURIRef.GetChar(0) == '#')
+ return rTheRelURIRef;
+
+ INetURLObject aTheAbsURIRef;
+ bool bWasAbsolute;
+ return m_aBaseURIRef.convertRelToAbs(rTheRelURIRef, false, aTheAbsURIRef,
+ bWasAbsolute, eEncodeMechanism,
+ eCharset, bIgnoreFragment, false,
+ false, eStyle)
+ || eEncodeMechanism != WAS_ENCODED
+ || eDecodeMechanism != DECODE_TO_IURI
+ || eCharset != RTL_TEXTENCODING_UTF8 ?
+ aTheAbsURIRef.GetMainURL(eDecodeMechanism, eCharset) :
+ rTheRelURIRef;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::AbsToRel(ByteString const & rTheAbsURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle)
+{
+ UniString aTheRelURIRef;
+ m_aBaseURIRef.convertAbsToRel(extend(rTheAbsURIRef), true, aTheRelURIRef,
+ eEncodeMechanism, eDecodeMechanism,
+ eCharset, eStyle);
+ return aTheRelURIRef;
+}
+
+//============================================================================
+// static
+UniString INetURLObject::AbsToRel(UniString const & rTheAbsURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle)
+{
+ UniString aTheRelURIRef;
+ m_aBaseURIRef.convertAbsToRel(rTheAbsURIRef, false, aTheRelURIRef,
+ eEncodeMechanism, eDecodeMechanism,
+ eCharset, eStyle);
+ return aTheRelURIRef;
+}
+
+//============================================================================
+// static
+bool INetURLObject::SetBaseURL(ByteString const & rTheBaseURIRef,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ return m_aBaseURIRef.SetURL(rTheBaseURIRef, eMechanism, eCharset);
+}
+
+//============================================================================
+// static
+bool INetURLObject::SetBaseURL(UniString const & rTheBaseURIRef,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ return m_aBaseURIRef.SetURL(rTheBaseURIRef, eMechanism, eCharset);
+}
+
+//============================================================================
+// static
+UniString INetURLObject::GetBaseURL(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ return m_aBaseURIRef.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+UniString INetURLObject::GetPartBeforeLastName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+ const
+{
+ if (!getSchemeInfo().m_bHierarchical)
+ return UniString();
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ aTemp.clearQuery();
+ aTemp.removeSegment(LAST_SEGMENT, false);
+ aTemp.setFinalSlash();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+UniString INetURLObject::GetLastName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ return getName(LAST_SEGMENT, true, eMechanism, eCharset);
+}
+
+//============================================================================
+UniString INetURLObject::GetFileExtension(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ return getExtension(LAST_SEGMENT, false, eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::CutLastName()
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ aTemp.clearQuery();
+ if (!aTemp.removeSegment(LAST_SEGMENT, false))
+ return false;
+ *this = aTemp;
+ return true;
+}
+
+//============================================================================
+UniString INetURLObject::PathToFileName() const
+{
+ if (m_eScheme != INET_PROT_FILE)
+ return UniString();
+ rtl::OUString aNormalizedPath;
+ if (osl::FileBase::getNormalizedPathFromFileURL(
+ decode(m_aAbsURIRef.GetBuffer(),
+ m_aAbsURIRef.GetBuffer() + m_aPath.getEnd(),
+ getEscapePrefix(), NO_DECODE, RTL_TEXTENCODING_UTF8),
+ aNormalizedPath)
+ != osl::FileBase::E_None)
+ return UniString();
+ rtl::OUString aSystemPath;
+ if (osl::FileBase::getSystemPathFromNormalizedPath(aNormalizedPath,
+ aSystemPath)
+ != osl::FileBase::E_None)
+ return UniString();
+ return aSystemPath;
+}
+
+//============================================================================
+UniString INetURLObject::GetFull() const
+{
+ INetURLObject aTemp(*this);
+ aTemp.removeFinalSlash();
+ return aTemp.PathToFileName();
+}
+
+//============================================================================
+UniString INetURLObject::GetPath() const
+{
+ INetURLObject aTemp(*this);
+ aTemp.removeSegment(LAST_SEGMENT, true);
+ aTemp.removeFinalSlash();
+ return aTemp.PathToFileName();
+}
+
+//============================================================================
+void INetURLObject::SetBase(UniString const & rTheBase)
+{
+ setBase(rTheBase, LAST_SEGMENT, true, ENCODE_ALL);
+}
+
+//============================================================================
+UniString INetURLObject::GetBase() const
+{
+ return getBase(LAST_SEGMENT, true, DECODE_WITH_CHARSET);
+}
+
+//============================================================================
+void INetURLObject::SetName(UniString const & rTheName,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ INetURLObject aTemp(*this);
+ if (aTemp.removeSegment(LAST_SEGMENT, true)
+ && aTemp.insertName(rTheName, false, LAST_SEGMENT, true, eMechanism,
+ eCharset))
+ *this = aTemp;
+}
+
+//============================================================================
+UniString INetURLObject::CutName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ UniString aTheName(getName(LAST_SEGMENT, true, eMechanism, eCharset));
+ return removeSegment(LAST_SEGMENT, true) ? aTheName : UniString();
+}
+
+//============================================================================
+void INetURLObject::SetExtension(UniString const & rTheExtension,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ setExtension(rTheExtension, LAST_SEGMENT, false, eMechanism, eCharset);
+}
+
+//============================================================================
+UniString INetURLObject::CutExtension(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ UniString aTheExtension(getExtension(LAST_SEGMENT, false, eMechanism,
+ eCharset));
+ return removeExtension(LAST_SEGMENT, false) ? aTheExtension : UniString();
+}
+
+//============================================================================
+bool INetURLObject::IsCaseSensitive() const
+{
+ return true;
+}
diff --git a/tools/source/fsys/wldcrd.cxx b/tools/source/fsys/wldcrd.cxx
new file mode 100644
index 000000000000..8b8bd7c5950b
--- /dev/null
+++ b/tools/source/fsys/wldcrd.cxx
@@ -0,0 +1,177 @@
+/*************************************************************************
+ *
+ * $RCSfile: wldcrd.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _WLDCRD_HXX
+#include <wldcrd.hxx>
+#endif
+
+/*************************************************************************
+|*
+|* WildCard::Match()
+|*
+|* Beschreibung WLDCRD.SDW
+|* Ersterstellung MA 19.06.91
+|* Letzte Aenderung MA 03.07.91
+|*
+*************************************************************************/
+
+/* Diese Methode ueberprueft, ob die Wilde Karte in pWild mit dem String
+ * in pStr matscht.
+ * Vertragen sich die beiden, so wird 1 zurueckgegeben, sonst 0.
+ *
+ * ein '*' in pWild bedeutet n beliebige Zeichen, mit n>=0
+ * ein '?' in pWild bedeutet genau ein beliebiges Zeichen
+ *
+ */
+
+USHORT WildCard::ImpMatch( const char *pWild, const char *pStr ) const
+{
+ int pos=0;
+ int flag=0;
+
+ while ( *pWild || flag )
+ {
+ switch (*pWild)
+ {
+ case '?':
+ if ( *pStr == '\0' )
+ return 0;
+ break;
+
+ default:
+ if ( (*pWild == '\\') && ((*(pWild+1)=='?') || (*(pWild+1) == '*')) )
+ pWild++;
+ if ( *pWild != *pStr )
+ if ( !pos )
+ return 0;
+ else
+ pWild += pos;
+ else
+ break; // ACHTUNG laeuft unter bestimmten
+ // Umstaenden in den nachsten case rein!!
+ case '*':
+ while ( *pWild == '*' )
+ pWild++;
+ if ( *pWild == '\0' )
+ return 1;
+ flag = 1;
+ pos = 0;
+ if ( *pStr == '\0' )
+ return ( *pWild == '\0' );
+ while ( *pStr && *pStr != *pWild )
+ {
+ if ( *pWild == '?' ) {
+ pWild++;
+ while ( *pWild == '*' )
+ pWild++;
+ }
+ pStr++;
+ if ( *pStr == '\0' )
+ return ( *pWild == '\0' );
+ }
+ break;
+ }
+ if ( *pWild != '\0' )
+ pWild++;
+ if ( *pStr != '\0' )
+ pStr++;
+ else
+ flag = 0;
+ if ( flag )
+ pos--;
+ }
+ return ( *pStr == '\0' ) && ( *pWild == '\0' );
+}
+
+/*************************************************************************
+|*
+|* WildCard::Matches()
+|*
+|* Beschreibung WLDCRD.SDW
+|* Ersterstellung MA 19.06.91
+|* Letzte Aenderung TH 02.02.96
+|*
+*************************************************************************/
+
+BOOL WildCard::Matches( const String& rString ) const
+{
+ ByteString aTmpWild = aWildString;
+ ByteString aString(rString, osl_getThreadTextEncoding());
+
+ USHORT nSepPos;
+
+ if ( cSepSymbol != '\0' )
+ {
+ while ( (nSepPos = aTmpWild.Search( cSepSymbol )) != STRING_NOTFOUND )
+ {
+ // alle getrennten WildCard's pruefen
+ if ( ImpMatch( aTmpWild.Copy( 0, nSepPos ).GetBuffer(), aString.GetBuffer() ) )
+ return TRUE;
+ aTmpWild.Erase( 0, nSepPos + 1 ); // Trennsymbol entfernen
+ }
+ // und noch den hinter dem letzen Trennsymbol bzw. den einzigen
+ }
+
+ if ( ImpMatch( aTmpWild.GetBuffer(), aString.GetBuffer() ) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/tools/source/fsys/wntmsc.cxx b/tools/source/fsys/wntmsc.cxx
new file mode 100644
index 000000000000..b1ae509c6056
--- /dev/null
+++ b/tools/source/fsys/wntmsc.cxx
@@ -0,0 +1,1103 @@
+/*************************************************************************
+ *
+ * $RCSfile: wntmsc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "wntmsc.hxx"
+#include "errinf.hxx"
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _LIST_HXX
+#include <list.hxx>
+#endif
+#ifndef _WLDCRD_HXX
+#include <wldcrd.hxx>
+#endif
+#ifndef _FSYS_HXX
+#include <fsys.hxx>
+#endif
+#ifndef _BIGINT_HXX
+#include "bigint.hxx"
+#endif
+
+DECLARE_LIST( DirEntryList, DirEntry* );
+DECLARE_LIST( FSysSortList, FSysSort* );
+DECLARE_LIST( FileStatList, FileStat* );
+
+int Sys2SolarError_Impl( int nSysErr );
+
+static ByteString sLastCaseSensitiveDir = "";
+static BOOL bLastCaseSensitive = FALSE;
+
+//--------------------------------------------------------------------
+
+ByteString Upper_Impl( const ByteString &rStr )
+{
+ ByteString aRet( rStr.GetBuffer() ); // es muss ein neuer String entstehen!
+ CharUpperBuff( (char*) aRet.GetBuffer(), aRet.Len() );
+ return aRet;
+}
+
+//--------------------------------------------------------------------
+
+DIR *opendir( const char* pPfad )
+{
+ DIR *pDir = new DIR;
+ if ( pDir )
+ pDir->p = (char*) pPfad;
+ return pDir;
+}
+
+struct dirent *readdir( DIR *pDir )
+{
+ BOOL bOk = FALSE;
+ if ( pDir->p )
+ {
+ char *pBuf = new char[ strlen( pDir->p ) + 5 ];
+ if ( pBuf )
+ {
+ // *.* dahinter, ggf mit "\\" abtrennen (falls nicht schon da)
+ strcpy( pBuf, pDir->p );
+ strcat( pBuf, "\\*.*" + ( *(pBuf + strlen( pBuf ) - 1 ) == '\\' ) );
+ CharUpperBuff( pBuf, strlen(pBuf) );
+ pDir->h = FindFirstFile( pBuf, &pDir->aDirEnt );
+ bOk = pDir->h != INVALID_HANDLE_VALUE;
+ pDir->p = NULL;
+ delete pBuf;
+ }
+ else
+ pDir->h = INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ bOk = FindNextFile( pDir->h, &pDir->aDirEnt );
+ }
+
+ return bOk ? &pDir->aDirEnt : NULL;
+}
+
+int closedir( DIR *pDir )
+{
+ BOOL bOk = FALSE;
+ if ( pDir )
+ {
+ bOk = 0 != pDir->p || FindClose( pDir->h );
+ delete pDir;
+ }
+ return bOk;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+ErrCode GetPathStyle_Impl( const String &rDevice, FSysPathStyle &rStyle )
+{
+ ByteString aRootDir(rDevice, osl_getThreadTextEncoding());
+ if ( aRootDir.Len() && aRootDir.GetBuffer()[aRootDir.Len()-1] != '\\' )
+ aRootDir += '\\';
+
+ char sVolumeName[256];
+ char sFileSysName[16];
+ DWORD nSerial[2];
+ DWORD nMaxCompLen[2];
+ DWORD nFlags[2];
+
+ // Windows95 hat VFAT, WindowsNT nicht
+ DWORD nVer = GetVersion();
+ BOOL bW95 = ( nVer & 0xFF ) >= 4;
+
+ FSysFailOnErrorImpl();
+ rStyle = FSYS_STYLE_UNKNOWN;
+ if ( GetVolumeInformation(
+ (char*) aRootDir.GetBuffer(),
+ sVolumeName, 256, (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags, sFileSysName, 16 ) )
+ {
+ // FAT/VFAT?
+ if ( 0 == strcmp( "FAT", sFileSysName ) )
+ rStyle = bW95 ? FSYS_STYLE_VFAT : FSYS_STYLE_FAT;
+
+ // NTFS?
+ else if ( 0 == strcmp( "NTFS", sFileSysName ) )
+ rStyle = FSYS_STYLE_NTFS;
+
+ // HPFS?
+ else if ( 0 == strcmp( "HPFS", sFileSysName ) )
+ rStyle = FSYS_STYLE_HPFS;
+
+ // NWCOMPA/NWFS?
+ else if ( 0 == strncmp( "NW", sFileSysName, 2 ) )
+ rStyle = FSYS_STYLE_NWFS;
+
+ return ERRCODE_NONE;
+ }
+
+ return ERRCODE_IO_INVALIDDEVICE;
+}
+
+FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
+{
+
+ FSysPathStyle eStyle;
+ GetPathStyle_Impl( rDevice, eStyle );
+ return eStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsCaseSensitive()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 10.06.93
+|* Letzte Aenderung TPF 26.02.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+/*
+ DirEntry aRoot(*this);
+ aRoot.ToAbs();
+ aRoot = aRoot[Level()-1];
+ String aRootDir = aRoot.GetFull(FSYS_STYLE_HOST, TRUE);
+
+ char sVolumeName[256];
+ DWORD nVolumeSerial;
+ DWORD nMaxCompLen;
+ DWORD nFlags;
+ char sFileSysName[16];
+
+ if ( GetVolumeInformation( (char*) aRootDir.GetStr(),
+ sVolumeName,
+ 256,
+ (LPDWORD) &nVolumeSerial,
+ (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags,
+ sFileSysName,
+ 16 ))
+ {
+ return (nFlags & FS_CASE_SENSITIVE) ? TRUE : FALSE;
+ }
+ else
+ {
+ return FALSE;
+ }
+*/
+ //
+ // guter versuch, aber FS_CASE_SENSITIVE ist D?nnsinn in T?ten:
+ //
+ // sFileSysName FS_CASE_SENSITIVE
+ // FAT FALSE
+ // NTFS TRUE !!!
+ // NWCompat FALSE
+ // Samba FALSE
+ //
+ // NT spricht auch NTFS lediglich case preserving an, also ist unter NT alles case insensitiv
+ //
+
+ return FALSE;
+ }
+ else
+ {
+ BOOL isCaseSensitive = FALSE; // ich bin unter win32, also ist der default case insensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = FALSE; // ich bin unter win32, also ist der default case insensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ {
+ return TRUE;
+ }
+
+
+ char sBuf[256];
+ char *pOld;
+ ByteString aFullName( GetFull(), osl_getThreadTextEncoding() );
+ FSysFailOnErrorImpl();
+ if ( GetFullPathName((char*)aFullName.GetBuffer(),256,sBuf,&pOld) > 511 )
+ return FALSE;
+
+ *this = DirEntry( String(sBuf, osl_getThreadTextEncoding() ));
+ return TRUE;
+}
+
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ String aRet;
+ const DirEntry *pTop = ImpGetTopPtr();
+ ByteString aName = ByteString( pTop->aName ).ToLowerAscii();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME )
+ && aName != "a:" && aName != "b:" && Exists() )
+ {
+ char sFileSysName[256];
+ char sVolumeName[256];
+ DWORD nVolumeNameLen = 256;
+ DWORD nSerial[2];
+ DWORD nMaxCompLen[2];
+ DWORD nFlags[2];
+ ByteString aRootDir = pTop->aName;
+ FSysFailOnErrorImpl();
+
+ // Network-Device zuerst probieren wegen langsamer Samba-Drives
+ if ( !WNetGetConnection( (char*) aRootDir.GetBuffer(),
+ sVolumeName, &nVolumeNameLen ) )
+ aRet = String( sVolumeName, osl_getThreadTextEncoding());
+
+ // dann den VolumeNamen fuer lokale Drives
+ if ( aRet.Len() == 0 )
+ {
+ aRootDir += "\\";
+ if ( GetVolumeInformation( (char*) aRootDir.GetBuffer(),
+ sVolumeName, 256,
+ (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags, sFileSysName, 256 ) )
+ aRet = String( sVolumeName, osl_getThreadTextEncoding());
+ }
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ FSysFailOnErrorImpl();
+
+ if ( eFlag == FSYS_FLAG_CURRENT && !aName.Len() )
+ return TRUE;
+
+ if ( SetCurrentDirectory(ByteString(GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ if ( bSloppy && pParent &&
+ SetCurrentDirectory(ByteString(pParent->GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ nError = FSYS_ERR_NOTADIRECTORY;
+ return FALSE;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ // Block-Devices auflisten?
+ if ( pDir->eAttrMask & FSYS_KIND_BLOCK )
+ {
+ // CWD merken
+ DirEntry aCurrentDir;
+ aCurrentDir.ToAbs();
+
+ // einzeln auf Existenz und Masken-konformit"at pr"ufen
+ USHORT nRead = 0;
+ char sDrive[3] = { '?', ':', 0 };
+ char sRoot[4] = { '?', ':', '\\', 0 };
+ for ( char c = 'a'; c <= 'z'; c++ )
+ {
+ sDrive[0] = c;
+ sRoot[0] = c;
+ DirEntry* pDrive = new DirEntry( sDrive, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ if ( pDir->aNameMask.Matches( String( ByteString(sDrive), osl_getThreadTextEncoding())) && GetDriveType( sRoot ) != 1 )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( *pDrive );
+ pDir->ImpSortedInsert( pDrive, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pDrive, NULL );
+ ++nRead;
+ }
+ else
+ delete pDrive;
+ }
+
+ // CWD restaurieren
+ aCurrentDir.SetCWD();
+ return nRead;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR ||
+ pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ // Gross/Kleinschreibung nicht beruecksichtigen
+ ByteString aLowerName = pDosEntry->d_name;
+ CharLowerBuff( (char*) aLowerName.GetBuffer(), aLowerName.Len() );
+
+ // Flags pruefen
+ BOOL bIsDirAndWantsDir =
+ ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+#ifdef ICC
+ ( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") ||
+ strcmp(pDosEntry->d_name,"..")) ) );
+#else
+ ( pDosEntry->d_type & DOS_DIRECT ) );
+#endif
+ BOOL bIsFileAndWantsFile =
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+#ifdef ICC
+ !( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") ||
+ strcmp(pDosEntry->d_name,"..")) ) &&
+#else
+ !( pDosEntry->d_type & DOS_DIRECT ) &&
+#endif
+ !( pDosEntry->d_type & DOS_VOLUMEID ) );
+ BOOL bIsHidden = pDosEntry->d_type & _A_HIDDEN;
+ BOOL bWantsHidden = 0 == ( pDir->eAttrMask & FSYS_KIND_VISIBLE );
+ if ( ( bIsDirAndWantsDir || bIsFileAndWantsFile ) &&
+ ( bWantsHidden || !bIsHidden ) &&
+ pDir->aNameMask.Matches( String(aLowerName, osl_getThreadTextEncoding()) ) )
+ {
+#ifdef DBG_UTIL
+ DbgOutf( "%s %s flags:%x found",
+ pDosEntry->d_name,
+ bIsFileAndWantsFile ? "file" : "dir",
+ pDosEntry->d_type );
+#endif
+ DirEntryFlag eFlag =
+ 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
+ : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name),
+ eFlag, FSYS_STYLE_NTFS );
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pTemp->ImpSetStat( new FileStat( (void*) pDosDir, (void*) 0 ) );
+#endif
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE );
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( (void*) pDosDir, (void*) 0 );
+ pDir->ImpSortedInsert( pTemp, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );
+ return 1;
+ }
+#ifdef DBG_UTIL
+ else
+ DbgOutf( "%s flags:%x skipped",
+ pDosEntry->d_name,
+ pDosEntry->d_type );
+#endif
+
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* InitFileStat()
+|*
+|* Beschreibung gemeinsamer Teil der Ctoren fuer FileStat
+|* Ersterstellung MI 28.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+void FileStat::ImpInit( void* p )
+{
+ _WIN32_FIND_DATAA *pDirEnt = (_WIN32_FIND_DATAA*) p;
+
+ nError = FSYS_ERR_OK;
+ nSize = pDirEnt->nFileSizeLow;
+
+ SYSTEMTIME aSysTime;
+ FILETIME aLocTime;
+
+ FileTimeToLocalFileTime( &pDirEnt->ftCreationTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateCreated = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeCreated = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ FileTimeToLocalFileTime( &pDirEnt->ftLastWriteTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateModified = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeModified = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ FileTimeToLocalFileTime( &pDirEnt->ftLastAccessTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateAccessed = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeAccessed = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ nKindFlags = FSYS_KIND_FILE;
+ if ( pDirEnt->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ nKindFlags = FSYS_KIND_DIR;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *pInfo, // struct dirent
+ const void * ): // dummy
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+ ImpInit( ( (dirent*) pInfo ) );
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+#ifdef ENABLEUNICODE
+// #define UNICODE
+#endif
+
+#include <prewin.h>
+#include <shlobj.h>
+#include <postwin.h>
+
+#ifdef UNICODE
+#define lstrchr wcschr
+#define lstrncmp wcsncmp
+#else
+#define lstrchr strchr
+#define lstrncmp strncmp
+#endif
+
+//---------------------------------------------------------------------------
+
+void SHFreeMem( void *p )
+{
+ LPMALLOC pMalloc = NULL;
+
+ if ( SUCCEEDED(SHGetMalloc(&pMalloc)) )
+ {
+ pMalloc->Free( p );
+ pMalloc->Release();
+ }
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHGetIDListFromPath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl )
+{
+ if ( IsBadWritePtr(ppidl, sizeof(LPITEMIDLIST)) )
+ return E_INVALIDARG;
+
+ LPSHELLFOLDER pDesktopFolder = NULL;
+
+ HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder );
+ if ( FAILED(hResult) )
+ return hResult;
+
+ ULONG chEaten = lstrlen( pszPath );
+ DWORD dwAttributes = FILE_ATTRIBUTE_DIRECTORY;
+
+#ifdef UNICODE
+ LPOLESTR wszPath = pszPath;
+#else
+ WCHAR wszPath[MAX_PATH];
+ MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszPath, -1, wszPath, MAX_PATH );
+#endif
+
+ hResult = pDesktopFolder->ParseDisplayName( hwndOwner, (LPBC)NULL, wszPath, &chEaten, ppidl, &dwAttributes );
+ pDesktopFolder->Release();
+
+ return hResult;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHGetFolderFromIDList( LPCITEMIDLIST pidl, LPSHELLFOLDER *ppFolder )
+{
+ if ( IsBadWritePtr(ppFolder, sizeof(LPSHELLFOLDER)) )
+ return E_INVALIDARG;
+
+ *ppFolder = NULL;
+
+ LPSHELLFOLDER pDesktopFolder = NULL;
+
+ HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder );
+ if ( FAILED(hResult) )
+ return hResult;
+
+ hResult = pDesktopFolder->BindToObject( pidl, (LPBC)NULL, IID_IShellFolder, (LPVOID *)ppFolder );
+ pDesktopFolder->Release();
+
+ return hResult;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHResolvePath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl )
+{
+ // If hwndOwner is NULL, use the desktop window, because dialogs need a parent
+
+#ifdef BOOTSTRAP
+ return NO_ERROR;
+#else
+ if ( !hwndOwner )
+ hwndOwner = GetDesktopWindow();
+
+ HRESULT hResult = NOERROR;
+ LPTSTR pszPathCopy;
+ LPTSTR pszTrailingPath;
+ TCHAR cBackup;
+
+ // First make a copy of the path
+
+ pszPathCopy = new TCHAR[lstrlen(pszPath) + 1];
+ if ( pszPathCopy )
+ lstrcpy( pszPathCopy, pszPath );
+ else
+ return E_OUTOFMEMORY;
+
+ // Determine the first token
+
+ if ( !lstrncmp( pszPathCopy, "\\\\", 2 ) )
+ pszTrailingPath = lstrchr( pszPathCopy + 2, '\\' );
+ else
+ pszTrailingPath = lstrchr( pszPathCopy, '\\' );
+
+ // Now scan the path tokens
+
+ while ( SUCCEEDED(hResult) )
+ {
+ if ( pszTrailingPath )
+ {
+ cBackup = *(++pszTrailingPath);
+ *pszTrailingPath = 0;
+ }
+
+ LPITEMIDLIST pidl = NULL;
+
+ // Make item ID list from leading path
+
+ hResult = SHGetIDListFromPath( hwndOwner, pszPathCopy, &pidl );
+
+ // if path exists try to open it as folder
+
+ if ( SUCCEEDED(hResult) )
+ {
+ // Only open the folder if it was not the last token
+
+ if ( pszTrailingPath )
+ {
+ LPSHELLFOLDER pFolder;
+
+ // Create a folder instance
+ hResult = SHGetFolderFromIDList( pidl, &pFolder);
+
+ // Is it a folder ?
+ if ( SUCCEEDED(hResult) )
+ {
+ // No try to instantiate an enumerator.
+ // This should popup a login dialog if any
+
+ LPENUMIDLIST pEnum = NULL;
+
+ hResult = pFolder->EnumObjects( hwndOwner,
+ SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN,
+ &pEnum );
+
+ // Release the enumerator interface
+ if ( SUCCEEDED(hResult) )
+ pEnum->Release();
+
+ // Release the folder interface
+ pFolder->Release();
+ }
+
+ SHFreeMem( pidl );
+ }
+ else // It was the last token
+ {
+ if ( ppidl )
+ *ppidl = pidl;
+ else
+ SHFreeMem( pidl );
+ }
+ }
+
+
+ // Forward to next token
+
+ if ( pszTrailingPath )
+ {
+ *pszTrailingPath = cBackup;
+ pszTrailingPath = lstrchr( pszTrailingPath, '\\' );
+ }
+ else
+ break;
+ }
+
+ // Free the working copy of the path
+ delete pszPathCopy;
+
+ // NOERROR or OLE error code
+ return hResult;
+#endif
+}
+
+//---------------------------------------------------------------------------
+// The Wrapper
+//---------------------------------------------------------------------------
+
+BOOL Exists_Impl( const ByteString & crPath )
+{
+ // We do not know if OLE was initialized for this thread
+
+ CoInitialize( NULL );
+
+ BOOL bSuccess = SUCCEEDED( SHResolvePath(NULL, crPath.GetBuffer(), NULL) );
+
+ CoUninitialize();
+
+ return bSuccess;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL bForceAccess )
+{
+ nSize = 0;
+ nKindFlags = 0;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if ( !rDirEntry.IsValid() )
+ {
+ nError = FSYS_ERR_UNKNOWN;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root ohne Laufwerk handelt
+
+ if ( !rDirEntry.aName.Len() && rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ nKindFlags = FSYS_KIND_DIR;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // keine Error-Boxen anzeigen
+ FSysFailOnErrorImpl();
+
+ // Redirect
+ String aPath( rDirEntry.GetFull() );
+#ifndef BOOTSTRAP
+ BOOL bRedirected = FSysRedirector::DoRedirect( aPath );
+#endif
+ DirEntry aDirEntry( aPath );
+
+ // ist ein Medium im Laufwerk?
+ HACK("wie?")
+ BOOL bAccess = TRUE;
+ const DirEntry *pTop = aDirEntry.ImpGetTopPtr();
+ ByteString aName = ByteString(pTop->aName).ToLowerAscii();
+ if ( !bForceAccess &&
+ ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME ) )
+ if ( aName == "a:" || aName == "b:" )
+ bAccess = FALSE;
+ else
+ DBG_TRACE( "FSys: will access removable device!" );
+ if ( bAccess && ( aName == "a:" || aName == "b:" ) )
+ DBG_WARNING( "floppy will clatter" );
+
+ // Sonderbehandlung, falls es sich um ein Volume handelt
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME ||
+ aDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = FSYS_KIND_DEV | ( aDirEntry.aName.Len() == 2
+ ? FSYS_KIND_BLOCK
+ : FSYS_KIND_CHAR );
+ else
+ nKindFlags = FSYS_KIND_DIR;
+
+ if ( !bAccess )
+ {
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags |= FSYS_KIND_REMOVEABLE;
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ ByteString aRootDir = aDirEntry.aName;
+ aRootDir += ByteString( "\\" );
+ USHORT nType = GetDriveType( (char *) aRootDir.GetBuffer() ); //TPF: 2i
+ if ( nType == 1 || nType == 0 )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = nKindFlags |
+ ( ( nType == DRIVE_REMOVABLE ) ? FSYS_KIND_REMOVEABLE : 0 ) |
+ ( ( nType == DRIVE_FIXED ) ? FSYS_KIND_FIXED : 0 ) |
+ ( ( nType == DRIVE_REMOTE ) ? FSYS_KIND_REMOTE : 0 ) |
+ ( ( nType == DRIVE_RAMDISK ) ? FSYS_KIND_RAM : 0 ) |
+ ( ( nType == DRIVE_CDROM ) ? FSYS_KIND_CDROM : 0 ) |
+ ( ( nType == 0 ) ? FSYS_KIND_UNKNOWN : 0 );
+
+ nError = ERRCODE_NONE;
+
+ return TRUE;
+ }
+
+ // Statusinformation vom Betriebssystem holen
+ HANDLE h; //()
+ _WIN32_FIND_DATAA aEntry;
+ DirEntry aAbsEntry( aDirEntry );
+ if ( bAccess && aAbsEntry.ToAbs() )
+ {
+ // im Namen k"onnen auch ';*?' als normale Zeichen vorkommen
+ ByteString aFilePath( aAbsEntry.GetFull(), osl_getThreadTextEncoding() );
+
+ // MI: dann gehen Umlaute auf Novell-Servern nicht / wozu ueberhaupt
+ // CharUpperBuff( (char*) aFilePath.GetStr(), aFilePath.Len() );
+ DBG_TRACE1( "FileStat: %s", aFilePath.GetBuffer() );
+ h = aFilePath.Len() < 230
+ // die Win32-API ist hier sehr schwammig
+ ? FindFirstFile( (char *) aFilePath.GetBuffer(), &aEntry )//TPF: 2i
+ : INVALID_HANDLE_VALUE;
+
+ if ( INVALID_HANDLE_VALUE != h )
+ {
+ if ( !( aEntry.dwFileAttributes & 0x40 ) ) // com1: etc. e.g. not encrypted (means normal)
+ {
+ ByteString aUpperName = Upper_Impl(ByteString(aAbsEntry.GetName(), osl_getThreadTextEncoding()));
+
+ // HRO: #74051# Compare also with short alternate filename
+ if ( aUpperName != Upper_Impl( aEntry.cFileName ) && aUpperName != Upper_Impl( aEntry.cAlternateFileName ) )
+ h = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if ( INVALID_HANDLE_VALUE == h )
+ {
+ DWORD dwError = GetLastError();
+
+ if ( ERROR_BAD_NET_NAME == dwError )
+ {
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ // UNC-Volume?
+ DirEntry *pTop = aAbsEntry.ImpGetTopPtr();
+ if ( pTop->GetFlag() == FSYS_FLAG_ABSROOT &&
+ ( pTop->aName.Len() > 1 && (pTop->aName.GetBuffer()[1] != ':' )) )
+ {
+ if ( bForceAccess )
+ {
+ if ( Exists_Impl( aFilePath ) )
+ {
+ nKindFlags = FSYS_KIND_DIR|FSYS_KIND_REMOTE;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+ else
+ {
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+ else
+ h = INVALID_HANDLE_VALUE;
+
+ if ( h == INVALID_HANDLE_VALUE )
+ {
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ ByteString aTempName( aDirEntry.GetName(), osl_getThreadTextEncoding() );
+ if ( strchr( aTempName.GetBuffer(), '?' ) ||
+ strchr( aTempName.GetBuffer(), '*' ) ||
+ strchr( aTempName.GetBuffer(), ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ if ( bAccess )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ }
+ else
+ nKindFlags = FSYS_KIND_REMOVEABLE;
+ }
+ else
+ {
+ ImpInit( &aEntry );
+ FindClose( h );
+ }
+
+ if ( 0 != nError )
+ nKindFlags = 0;
+
+ return 0 == nError;
+
+}
+
+BOOL IsRedirectable_Impl( const ByteString &rPath )
+{
+ if ( rPath.Len() >= 3 && ':' == rPath.GetBuffer()[1] )
+ {
+ ByteString aVolume = rPath.Copy( 0, 3 );
+ USHORT nType = GetDriveType( (char *) aVolume.GetBuffer() );
+ SetLastError( ERROR_SUCCESS );
+ return DRIVE_FIXED != nType;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* TempDirImpl()
+|*
+|* Beschreibung liefert den Namens des Directories fuer temporaere
+|* Dateien
+|* Ersterstellung MI 16.03.94
+|* Letzte Aenderung MI 16.03.94
+|*
+*************************************************************************/
+
+const char* TempDirImpl( char *pBuf )
+{
+ if ( !GetTempPath( MAX_PATH, pBuf ) &&
+ !GetWindowsDirectory( pBuf, MAX_PATH ) &&
+ !GetEnvironmentVariable( "HOMEPATH", pBuf, MAX_PATH ) )
+ return 0;
+
+ return pBuf;
+}
+
+//=======================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &rPath,
+ BigInt &rFreeBytes, BigInt &rTotalBytes )
+{
+ DWORD nSectorsPerCluster; /* address of sectors per cluster */
+ DWORD nBytesPerSector; /* address of bytes per sector */
+ DWORD nFreeClusters; /* address of number of free clusters */
+ DWORD nClusters; /* address of total number of clusters */
+
+ ByteString aVol( DirEntry(rPath).ImpGetTopPtr()->GetName(), osl_getThreadTextEncoding());
+ BOOL bOK = GetDiskFreeSpace( aVol.GetBuffer(),
+ &nSectorsPerCluster, &nBytesPerSector,
+ &nFreeClusters, &nClusters );
+ if ( !bOK )
+ return Sys2SolarError_Impl( GetLastError() );
+
+ BigInt aBytesPerCluster( BigInt(nSectorsPerCluster) *
+ BigInt(nBytesPerSector) );
+ rFreeBytes = aBytesPerCluster * BigInt(nFreeClusters);
+ rTotalBytes = aBytesPerCluster * BigInt(nClusters);
+ return 0;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL bEnable )
+{ // Preserve other Bits!!
+ sal_uInt32 nErrorMode = SetErrorMode( bEnable ? 0 : SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX );
+ if ( bEnable )
+ nErrorMode &= ~(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ else
+ nErrorMode |= (SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ SetErrorMode( nErrorMode );
+}
+
+
+
diff --git a/tools/source/fsys/wntmsc.hxx b/tools/source/fsys/wntmsc.hxx
new file mode 100644
index 000000000000..e51931fc4173
--- /dev/null
+++ b/tools/source/fsys/wntmsc.hxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * $RCSfile: wntmsc.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _dosmsc_hxx
+#define _dosmsc_hxx
+
+#include <string.h>
+
+#ifndef ICC
+#include <io.h>
+#endif
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <direct.h>
+
+#include <svwin.h>
+#include <winbase.h>
+#include <solar.h>
+#include <string.hxx>
+
+//--------------------------------------------------------------------
+
+#define FSYS_UNIX FALSE
+
+#define DOS_DIRECT _A_SUBDIR
+#define DOS_VOLUMEID 0x08
+#ifndef S_IFBLK
+#define S_IFBLK 0x6000
+#endif
+#define setdrive(n,a) _chdrive(n)
+#define GETDRIVE(n) (n = _getdrive())
+
+#define dirent _WIN32_FIND_DATAA
+#define d_name cFileName
+#define d_type dwFileAttributes
+
+#if defined (TCPP) || defined (tcpp)
+#define _mkdir mkdir
+#define _rmdir rmdir
+#define _chdir chdir
+#define _unlink unlink
+#define _getcwd getcwd
+#define _access access
+#endif
+
+typedef struct
+{
+ _WIN32_FIND_DATAA aDirEnt;
+ HANDLE h;
+ const char *p;
+} DIR;
+
+#define PATHDELIMITER ";"
+#define DEFSTYLE FSYS_STYLE_NTFS
+#define MKDIR( p ) mkdir( p )
+#define CMP_LOWER(s) ( ByteString(s).ToLowerAscii() )
+
+#include <svwin.h>
+#define START_DRV 'a'
+
+inline BOOL DRIVE_EXISTS(char c)
+{
+ ByteString aDriveRoot( c );
+ aDriveRoot += ":\\";
+ return GetDriveType( aDriveRoot.GetBuffer() ) > 1;
+}
+
+const char* TempDirImpl( char *pBuf );
+
+#define FSysFailOnErrorImpl()
+
+#endif
diff --git a/tools/source/generic/bigint.cxx b/tools/source/generic/bigint.cxx
new file mode 100644
index 000000000000..352731311a6c
--- /dev/null
+++ b/tools/source/generic/bigint.cxx
@@ -0,0 +1,1187 @@
+/*************************************************************************
+ *
+ * $RCSfile: bigint.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <math.h>
+#include <tools.h>
+
+#define private public
+#include <bigint.hxx>
+#undef private
+
+#ifndef _STRING_HXX
+#include <string.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+static void SubLong( BigInt& rA, BigInt& rB, BigInt& rErg );
+
+static const long MY_MAXLONG = 0x3fffffff;
+static const long MY_MINLONG = -MY_MAXLONG;
+static const long MY_MAXSHORT = 0x00007fff;
+static const long MY_MINSHORT = -MY_MAXSHORT;
+
+/* Die ganzen Algorithmen zur Addition, Subtraktion, Multiplikation und
+ * Division von langen Zahlen stammen aus SEMINUMERICAL ALGORITHMS von
+ * DONALD E. KNUTH aus der Reihe The Art of Computer Programming. Zu finden
+ * sind diese Algorithmen im Kapitel 4.3.1. The Classical Algorithms.
+ */
+
+// Muss auf UINT16/INT16/UINT32/INT32 umgestellt werden !!! W.P.
+
+// -----------------------------------------------------------------------
+
+static void MakeBigInt( BigInt& rThis, const BigInt& rVal )
+{
+ if ( rVal.bIsBig )
+ {
+ memcpy( (void*)&rThis, (const void*)&rVal, sizeof( BigInt ) );
+ while ( rThis.nLen > 1 && rThis.nNum[rThis.nLen-1] == 0 )
+ rThis.nLen--;
+ }
+ else
+ {
+ long nTmp = rVal.nVal;
+
+ rThis.nVal = rVal.nVal;
+ rThis.bIsBig = TRUE;
+ if ( nTmp < 0 )
+ {
+ rThis.bIsNeg = TRUE;
+ nTmp = -nTmp;
+ }
+ else
+ rThis.bIsNeg = FALSE;
+
+ rThis.nNum[0] = (USHORT)(nTmp & 0xffffL);
+ rThis.nNum[1] = (USHORT)(nTmp >> 16);
+#ifndef _WIN16
+ if ( nTmp & 0xffff0000L )
+#else
+ long l = 0xffff0000L;
+ if ( nTmp & l )
+#endif
+ rThis.nLen = 2;
+ else
+ rThis.nLen = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void Normalize( BigInt& rThis )
+{
+ if ( rThis.bIsBig )
+ {
+ while ( rThis.nLen > 1 && rThis.nNum[rThis.nLen-1] == 0 )
+ rThis.nLen--;
+
+ if ( rThis.nLen < 3 )
+ {
+ if ( rThis.nLen < 2 )
+ rThis.nVal = rThis.nNum[0];
+ else if ( rThis.nNum[1] & 0x8000 )
+ return;
+ else
+ rThis.nVal = ((long)rThis.nNum[1] << 16) + rThis.nNum[0];
+
+ rThis.bIsBig = FALSE;
+
+ if ( rThis.bIsNeg )
+ rThis.nVal = -rThis.nVal;
+ }
+ // else ist nVal undefiniert !!! W.P.
+ }
+ // wozu, nLen ist doch undefiniert ??? W.P.
+ else if ( rThis.nVal & 0xFFFF0000L )
+ rThis.nLen = 2;
+ else
+ rThis.nLen = 1;
+}
+
+// -----------------------------------------------------------------------
+
+static void Mult( BigInt& rThis, const BigInt &rVal, USHORT nMul )
+{
+ USHORT nK = 0;
+ for ( int i = 0; i < rVal.nLen; i++ )
+ {
+ ULONG nTmp = (ULONG)rVal.nNum[i] * (ULONG)nMul + nK;
+ nK = (USHORT)(nTmp >> 16);
+ rThis.nNum[i] = (USHORT)nTmp;
+ }
+
+ if ( nK )
+ {
+ rThis.nNum[rVal.nLen] = nK;
+ rThis.nLen = rVal.nLen + 1;
+ }
+ else
+ rThis.nLen = rVal.nLen;
+
+ rThis.bIsBig = TRUE;
+ rThis.bIsNeg = rVal.bIsNeg;
+}
+
+// -----------------------------------------------------------------------
+
+static void Div( BigInt& rThis, USHORT nDiv, USHORT& rRem )
+{
+ ULONG nK = 0;
+ for ( int i = rThis.nLen - 1; i >= 0; i-- )
+ {
+ ULONG nTmp = (ULONG)rThis.nNum[i] + (nK << 16);
+ rThis.nNum[i] = (USHORT)(nTmp / nDiv);
+ nK = nTmp % nDiv;
+ }
+ rRem = (USHORT)nK;
+
+ if ( rThis.nNum[rThis.nLen-1] == 0 )
+ rThis.nLen -= 1;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL IsLess( const BigInt& rThis, const BigInt& rVal )
+{
+ if ( rVal.nLen < rThis.nLen)
+ return TRUE;
+ if ( rVal.nLen > rThis.nLen )
+ return FALSE;
+
+ int i;
+ for ( i = rThis.nLen - 1; i > 0 && rThis.nNum[i] == rVal.nNum[i]; i-- )
+ {
+ }
+ return rVal.nNum[i] < rThis.nNum[i];
+}
+
+// -----------------------------------------------------------------------
+
+static void AddLong( BigInt& rA, BigInt& rB, BigInt& rErg )
+{
+ if ( rA.bIsNeg == rB.bIsNeg )
+ {
+ int i;
+ char nLen;
+
+ // wenn die Zahlen unterschiedlich lang sind, sollte zunaechst bei
+ // der kleineren Zahl die fehlenden Ziffern mit 0 initialisert werden
+ if (rA.nLen >= rB.nLen)
+ {
+ nLen = rA.nLen;
+ for (i = rB.nLen; i < nLen; i++)
+ rB.nNum[i] = 0;
+ }
+ else
+ {
+ nLen = rB.nLen;
+ for (i = rA.nLen; i < nLen; i++)
+ rA.nNum[i] = 0;
+ }
+
+ // Die Ziffern werden von hinten nach vorne addiert
+ long k;
+ long nZ = 0;
+ for (i = 0, k = 0; i < nLen; i++) {
+ nZ = (long)rA.nNum[i] + (long)rB.nNum[i] + k;
+ if (nZ & 0xff0000L)
+ k = 1;
+ else
+ k = 0;
+ rErg.nNum[i] = (USHORT)(nZ & 0xffffL);
+ }
+ // Trat nach der letzten Addition ein Ueberlauf auf, muss dieser
+ // noch ins Ergebis uebernommen werden
+ if (nZ & 0xff0000L) // oder if(k)
+ {
+ rErg.nNum[i] = 1;
+ nLen++;
+ }
+ // Die Laenge und das Vorzeichen setzen
+ rErg.nLen = nLen;
+ rErg.bIsNeg = rA.bIsNeg && rB.bIsNeg;
+ rErg.bIsBig = TRUE;
+ }
+ // Wenn nur einer der beiden Operanten negativ ist, wird aus der
+ // Addition eine Subtaktion
+ else if (rA.bIsNeg)
+ {
+ rA.bIsNeg = FALSE;
+ SubLong(rB, rA, rErg);
+ rA.bIsNeg = TRUE;
+ }
+ else
+ {
+ rB.bIsNeg = FALSE;
+ SubLong(rA, rB, rErg);
+ rB.bIsNeg = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void SubLong( BigInt& rA, BigInt& rB, BigInt& rErg )
+{
+ if ( rA.bIsNeg == rB.bIsNeg )
+ {
+ int i;
+ char nLen;
+ long nZ, k;
+
+ // wenn die Zahlen unterschiedlich lang sind, sollte zunaechst bei
+ // der kleineren Zahl die fehlenden Ziffern mit 0 initialisert werden
+ if (rA.nLen >= rB.nLen)
+ {
+ nLen = rA.nLen;
+ for (i = rB.nLen; i < nLen; i++)
+ rB.nNum[i] = 0;
+ }
+ else
+ {
+ nLen = rB.nLen;
+ for (i = rA.nLen; i < nLen; i++)
+ rA.nNum[i] = 0;
+ }
+
+ if ( IsLess(rA, rB) )
+ {
+ for (i = 0, k = 0; i < nLen; i++)
+ {
+ nZ = (long)rA.nNum[i] - (long)rB.nNum[i] + k;
+ if (nZ < 0)
+ k = -1;
+ else
+ k = 0;
+ rErg.nNum[i] = (USHORT)(nZ & 0xffffL);
+ }
+ rErg.bIsNeg = rA.bIsNeg;
+ }
+ else
+ {
+ for (i = 0, k = 0; i < nLen; i++)
+ {
+ nZ = (long)rB.nNum[i] - (long)rA.nNum[i] + k;
+ if (nZ < 0)
+ k = -1;
+ else
+ k = 0;
+ rErg.nNum[i] = (USHORT)(nZ & 0xffffL);
+ }
+ // wenn a < b, dann Vorzeichen vom Ergebnis umdrehen
+ rErg.bIsNeg = !rA.bIsNeg;
+ }
+ rErg.nLen = nLen;
+ rErg.bIsBig = TRUE;
+ }
+ // Wenn nur einer der beiden Operanten negativ ist, wird aus der
+ // Subtaktion eine Addition
+ else if (rA.bIsNeg)
+ {
+ rA.bIsNeg = FALSE;
+ AddLong(rA, rB, rErg);
+ rA.bIsNeg = TRUE;
+ rErg.bIsNeg = TRUE;
+ }
+ else
+ {
+ rB.bIsNeg = FALSE;
+ AddLong(rA, rB, rErg);
+ rB.bIsNeg = TRUE;
+ rErg.bIsNeg = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void MultLong( const BigInt& rA, const BigInt& rB, BigInt& rErg )
+{
+ int i, j;
+ ULONG nZ, k;
+
+ rErg.bIsNeg = rA.bIsNeg != rB.bIsNeg;
+ rErg.bIsBig = TRUE;
+ rErg.nLen = rA.nLen + rB.nLen;
+
+ for (i = 0; i < rErg.nLen; i++)
+ rErg.nNum[i] = 0;
+
+ for (j = 0; j < rB.nLen; j++)
+ {
+ for (i = 0, k = 0; i < rA.nLen; i++)
+ {
+ nZ = (ULONG)rA.nNum[i] * (ULONG)rB.nNum[j] +
+ (ULONG)rErg.nNum[i + j] + k;
+ rErg.nNum[i + j] = (USHORT)(nZ & 0xffffUL);
+ k = nZ >> 16;
+ }
+ rErg.nNum[i + j] = (USHORT)k;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void DivLong( const BigInt& rA, const BigInt& rB, BigInt& rErg )
+{
+ int i, j;
+ long nTmp;
+ USHORT nK, nQ, nMult;
+ short nLenB = rB.nLen;
+ short nLenB1 = rB.nLen - 1;
+ BigInt aTmpA, aTmpB;
+
+ nMult = (USHORT)(0x10000L / ((long)rB.nNum[nLenB1] + 1));
+
+ Mult( aTmpA, rA, nMult );
+ if ( aTmpA.nLen == rA.nLen )
+ {
+ aTmpA.nNum[aTmpA.nLen] = 0;
+ aTmpA.nLen++;
+ }
+
+ Mult( aTmpB, rB, nMult );
+
+ for (j = aTmpA.nLen - 1; j >= nLenB; j--)
+ { // Raten des Divisors
+ nTmp = ( (long)aTmpA.nNum[j] << 16 ) + aTmpA.nNum[j - 1];
+ if (aTmpA.nNum[j] == aTmpB.nNum[nLenB1])
+ nQ = 0xFFFF;
+ else
+ nQ = (USHORT)(((ULONG)nTmp) / aTmpB.nNum[nLenB1]);
+
+ if ( ((ULONG)aTmpB.nNum[nLenB1 - 1] * nQ) >
+ ((((ULONG)nTmp) - aTmpB.nNum[nLenB1] * nQ) << 16) + aTmpA.nNum[j - 2])
+ nQ--;
+ // Und hier faengt das Teilen an
+ nK = 0;
+ nTmp = 0;
+ for (i = 0; i < nLenB; i++)
+ {
+ nTmp = (long)aTmpA.nNum[j - nLenB + i]
+ - ((long)aTmpB.nNum[i] * nQ)
+ - nK;
+ aTmpA.nNum[j - nLenB + i] = (USHORT)nTmp;
+ nK = (USHORT) (nTmp >> 16);
+ if ( nK )
+ nK = (USHORT)(0x10000UL - nK);
+ }
+ aTmpA.nNum[j - nLenB + i] -= nK;
+ if (aTmpA.nNum[j - nLenB + i] == 0)
+ rErg.nNum[j - nLenB] = nQ;
+ else
+ {
+ rErg.nNum[j - nLenB] = nQ - 1;
+ nK = 0;
+ for (i = 0; i < nLenB; i++)
+ {
+ nTmp = aTmpA.nNum[j - nLenB + i] + aTmpB.nNum[i] + nK;
+ aTmpA.nNum[j - nLenB + i] = (USHORT)(nTmp & 0xFFFFL);
+ if (nTmp & 0xFFFF0000L)
+ nK = 1;
+ else
+ nK = 0;
+ }
+ }
+ }
+
+ rErg.bIsNeg = rA.bIsNeg != rB.bIsNeg;
+ rErg.bIsBig = TRUE;
+ rErg.nLen = rA.nLen - rB.nLen + 1;
+}
+
+// -----------------------------------------------------------------------
+
+static void ModLong( const BigInt& rA, const BigInt& rB, BigInt& rErg )
+{
+ short i, j;
+ long nTmp;
+ USHORT nK, nQ, nMult;
+ short nLenB = rB.nLen;
+ short nLenB1 = rB.nLen - 1;
+ BigInt aTmpA, aTmpB;
+
+ nMult = (USHORT)(0x10000L / ((long)rB.nNum[nLenB1] + 1));
+
+ Mult( aTmpA, rA, nMult);
+ if ( aTmpA.nLen == rA.nLen )
+ {
+ aTmpA.nNum[aTmpA.nLen] = 0;
+ aTmpA.nLen++;
+ }
+
+ Mult( aTmpB, rB, nMult);
+
+ for (j = aTmpA.nLen - 1; j >= nLenB; j--)
+ { // Raten des Divisors
+ nTmp = ( (long)aTmpA.nNum[j] << 16 ) + aTmpA.nNum[j - 1];
+ if (aTmpA.nNum[j] == aTmpB.nNum[nLenB1])
+ nQ = 0xFFFF;
+ else
+ nQ = (USHORT)(((ULONG)nTmp) / aTmpB.nNum[nLenB1]);
+
+ if ( ((ULONG)aTmpB.nNum[nLenB1 - 1] * nQ) >
+ ((((ULONG)nTmp) - aTmpB.nNum[nLenB1] * nQ) << 16) + aTmpA.nNum[j - 2])
+ nQ--;
+ // Und hier faengt das Teilen an
+ nK = 0;
+ nTmp = 0;
+ for (i = 0; i < nLenB; i++)
+ {
+ nTmp = (long)aTmpA.nNum[j - nLenB + i]
+ - ((long)aTmpB.nNum[i] * nQ)
+ - nK;
+ aTmpA.nNum[j - nLenB + i] = (USHORT)nTmp;
+ nK = (USHORT) (nTmp >> 16);
+ if ( nK )
+ nK = (USHORT)(0x10000UL - nK);
+ }
+ aTmpA.nNum[j - nLenB + i] -= nK;
+ if (aTmpA.nNum[j - nLenB + i] == 0)
+ rErg.nNum[j - nLenB] = nQ;
+ else
+ {
+ rErg.nNum[j - nLenB] = nQ - 1;
+ nK = 0;
+ for (i = 0; i < nLenB; i++) {
+ nTmp = aTmpA.nNum[j - nLenB + i] + aTmpB.nNum[i] + nK;
+ aTmpA.nNum[j - nLenB + i] = (USHORT)(nTmp & 0xFFFFL);
+ if (nTmp & 0xFFFF0000L)
+ nK = 1;
+ else
+ nK = 0;
+ }
+ }
+ }
+
+ rErg = aTmpA;
+ Div( rErg, nMult, nQ );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ABS_IsLess( const BigInt& rA, const BigInt& rB )
+{
+ if (rA.bIsBig || rB.bIsBig)
+ {
+ BigInt nA, nB;
+ MakeBigInt( nA, rA );
+ MakeBigInt( nB, rB );
+ if (nA.nLen == nB.nLen)
+ {
+ int i;
+ for (i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i--)
+ {
+ }
+ return nA.nNum[i] < nB.nNum[i];
+ }
+ else
+ return nA.nLen < nB.nLen;
+ }
+ if ( rA.nVal < 0 )
+ if ( rB.nVal < 0 )
+ return rA.nVal > rB.nVal;
+ else
+ return rA.nVal > -rB.nVal;
+ else
+ if ( rB.nVal < 0 )
+ return rA.nVal < -rB.nVal;
+ else
+ return rA.nVal < rB.nVal;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::BigInt( const BigInt& rBigInt )
+{
+ if ( rBigInt.bIsBig )
+ memcpy( (void*)this, (const void*)&rBigInt, sizeof( BigInt ) );
+ else
+ {
+ bIsSet = rBigInt.bIsSet;
+ bIsBig = FALSE;
+ nVal = rBigInt.nVal;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::BigInt( const ByteString& rString )
+{
+ bIsSet = TRUE;
+ bIsNeg = FALSE;
+ bIsBig = FALSE;
+ nVal = 0;
+
+ BOOL bNeg = FALSE;
+ const sal_Char* p = rString.GetBuffer();
+ if ( *p == '-' )
+ {
+ bNeg = TRUE;
+ p++;
+ }
+ while( *p >= '0' && *p <= '9' )
+ {
+ *this *= 10;
+ *this += *p - '0';
+ p++;
+ }
+ if ( bIsBig )
+ bIsNeg = bNeg;
+ else if( bNeg )
+ nVal = -nVal;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::BigInt( const UniString& rString )
+{
+ bIsSet = TRUE;
+ bIsNeg = FALSE;
+ bIsBig = FALSE;
+ nVal = 0;
+
+ BOOL bNeg = FALSE;
+ const sal_Unicode* p = rString.GetBuffer();
+ if ( *p == '-' )
+ {
+ bNeg = TRUE;
+ p++;
+ }
+ while( *p >= '0' && *p <= '9' )
+ {
+ *this *= 10;
+ *this += *p - '0';
+ p++;
+ }
+ if ( bIsBig )
+ bIsNeg = bNeg;
+ else if( bNeg )
+ nVal = -nVal;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::BigInt( double nValue )
+{
+ bIsSet = TRUE;
+
+ if ( nValue < 0 )
+ {
+ nValue *= -1;
+ bIsNeg = TRUE;
+ }
+ else
+ {
+ bIsNeg = FALSE;
+ }
+
+ if ( nValue < 1 )
+ {
+ bIsBig = FALSE;
+ nVal = 0;
+ }
+ else
+ {
+ bIsBig = TRUE;
+
+ int i=0;
+
+ while ( ( nValue > 65536.0 ) && ( i < MAX_DIGITS ) )
+ {
+ nNum[i] = (USHORT) fmod( nValue, 65536.0 );
+ nValue -= nNum[i];
+ nValue /= 65536.0;
+ i++;
+ }
+ if ( i < MAX_DIGITS )
+ nNum[i++] = (USHORT) nValue;
+
+ nLen = i;
+
+ if ( i < 3 )
+ Normalize( *this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::BigInt( ULONG nValue )
+{
+#if __SIZEOFLONG != 4
+ #error sizeof (long) != 4: API auf INTxx umstellen
+#else
+ bIsSet = TRUE;
+ if ( nValue & 0x80000000UL )
+ {
+ bIsBig = TRUE;
+ bIsNeg = FALSE;
+ nNum[0] = (USHORT)(nValue & 0xffffUL);
+ nNum[1] = (USHORT)(nValue >> 16);
+ nLen = 2;
+ }
+ else
+ {
+ bIsBig = FALSE;
+ nVal = nValue;
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::operator ULONG() const
+{
+ if ( !bIsBig )
+ return (ULONG)nVal;
+ else if ( nLen == 2 )
+ {
+ ULONG nRet;
+ nRet = ((ULONG)nNum[1]) << 16;
+ nRet += nNum[0];
+ return nRet;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt::operator double() const
+{
+ if ( !bIsBig )
+ return (double) nVal;
+ else
+ {
+ int i = nLen-1;
+ double nRet = (double) ((ULONG)nNum[i]);
+
+ while ( i )
+ {
+ nRet *= 65536.0;
+ i--;
+ nRet += (double) ((ULONG)nNum[i]);
+ }
+
+ if ( bIsNeg )
+ nRet *= -1;
+
+ return nRet;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ByteString BigInt::GetByteString() const
+{
+ ByteString aString;
+
+ if ( !bIsBig )
+ aString = nVal;
+ else
+ {
+ BigInt aTmp( *this );
+ BigInt a1000000000( 1000000000L );
+ aTmp.Abs();
+
+ do
+ {
+ BigInt a = aTmp;
+ a %= a1000000000;
+ aTmp /= a1000000000;
+
+ ByteString aStr = aString;
+ if ( a.nVal < 100000000L )
+ { // leading 0s
+ aString = ByteString::CreateFromInt32( a.nVal + 1000000000L );
+ aString.Erase( 0, 1 );
+ }
+ else
+ aString = ByteString::CreateFromInt32( a.nVal );
+ aString += aStr;
+ }
+ while( aTmp.bIsBig );
+
+ ByteString aStr = aString;
+ if ( bIsNeg )
+ aString = ByteString::CreateFromInt32( -aTmp.nVal );
+ else
+ aString = ByteString::CreateFromInt32( aTmp.nVal );
+ aString += aStr;
+ }
+
+ return aString;
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef ENABLEUNICODE
+
+UniString BigInt::GetString() const
+{
+ UniString aString;
+
+ if ( !bIsBig )
+ aString = nVal;
+ else
+ {
+ BigInt aTmp( *this );
+ BigInt a1000000000( 1000000000L );
+ aTmp.Abs();
+
+ do
+ {
+ BigInt a = aTmp;
+ a %= a1000000000;
+ aTmp /= a1000000000;
+
+ UniString aStr = aString;
+ if ( a.nVal < 100000000L )
+ { // leading 0s
+ aString = UniString::CreateFromInt32( a.nVal + 1000000000L );
+ aString.Erase(0,1);
+ }
+ else
+ aString = UniString::CreateFromInt32( a.nVal );
+ aString += aStr;
+ }
+ while( aTmp.bIsBig );
+
+ UniString aStr = aString;
+ if ( bIsNeg )
+ aString = UniString::CreateFromInt32( -aTmp.nVal );
+ else
+ aString = UniString::CreateFromInt32( aTmp.nVal );
+ aString += aStr;
+ }
+
+ return aString;
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator=( const BigInt& rBigInt )
+{
+ if ( rBigInt.bIsBig )
+ memcpy( (void*)this, (const void*)&rBigInt, sizeof( BigInt ) );
+ else
+ {
+ bIsSet = rBigInt.bIsSet;
+ bIsBig = FALSE;
+ nVal = rBigInt.nVal;
+ }
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator+=( const BigInt& rVal )
+{
+ if ( !bIsBig && !rVal.bIsBig )
+ {
+ if( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG
+ && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
+ { // wir bewegen uns im ungefaehrlichem Bereich
+ nVal += rVal.nVal;
+ return *this;
+ }
+
+ if( (nVal < 0) != (rVal.nVal < 0) )
+ { // wir bewegen uns im ungefaehrlichem Bereich
+ nVal += rVal.nVal;
+ return *this;
+ }
+ }
+
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, *this );
+ MakeBigInt( aTmp2, rVal );
+ AddLong( aTmp1, aTmp2, *this );
+ Normalize( *this );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator-=( const BigInt& rVal )
+{
+ if ( !bIsBig && !rVal.bIsBig )
+ {
+ if ( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG &&
+ nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
+ { // wir bewegen uns im ungefaehrlichem Bereich
+ nVal -= rVal.nVal;
+ return *this;
+ }
+
+ if ( (nVal < 0) == (rVal.nVal < 0) )
+ { // wir bewegen uns im ungefaehrlichem Bereich
+ nVal -= rVal.nVal;
+ return *this;
+ }
+ }
+
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, *this );
+ MakeBigInt( aTmp2, rVal );
+ SubLong( aTmp1, aTmp2, *this );
+ Normalize( *this );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator*=( const BigInt& rVal )
+{
+ if ( !bIsBig && !rVal.bIsBig
+ && nVal <= MY_MAXSHORT && rVal.nVal <= MY_MAXSHORT
+ && nVal >= MY_MINSHORT && rVal.nVal >= MY_MINSHORT )
+ // nicht optimal !!! W.P.
+ { // wir bewegen uns im ungefaehrlichem Bereich
+ nVal *= rVal.nVal;
+ }
+ else
+ {
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, rVal );
+ MakeBigInt( aTmp2, *this );
+ MultLong(aTmp1, aTmp2, *this);
+ Normalize( *this );
+ }
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator/=( const BigInt& rVal )
+{
+ if ( !rVal.bIsBig )
+ {
+ if ( rVal.nVal == 0 )
+ {
+ DBG_ERROR( "BigInt::operator/ --> divide by zero" );
+ return *this;
+ }
+
+ if ( !bIsBig )
+ {
+ // wir bewegen uns im ungefaehrlichem Bereich
+ nVal /= rVal.nVal;
+ return *this;
+ }
+
+ if ( rVal.nVal == 1 )
+ return *this;
+
+ if ( rVal.nVal == -1 )
+ {
+ bIsNeg = !bIsNeg;
+ return *this;
+ }
+
+ if ( rVal.nVal <= (long)0xFFFF && rVal.nVal >= -(long)0xFFFF )
+ {
+ // ein BigInt durch ein USHORT teilen
+ USHORT nTmp;
+ if ( rVal.nVal < 0 )
+ {
+ nTmp = (USHORT) -rVal.nVal;
+ bIsNeg = !bIsNeg;
+ }
+ else
+ nTmp = (USHORT) rVal.nVal;
+
+ Div( *this, nTmp, nTmp );
+ Normalize( *this );
+ return *this;
+ }
+ }
+
+ if ( ABS_IsLess( *this, rVal ) )
+ {
+ *this = BigInt( (long)0 );
+ return *this;
+ }
+
+ // BigInt durch BigInt teilen
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, *this );
+ MakeBigInt( aTmp2, rVal );
+ DivLong(aTmp1, aTmp2, *this);
+ Normalize( *this );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void BigInt::DivMod( const BigInt& rVal, BigInt& rMod )
+{
+ if ( !rVal.bIsBig )
+ {
+ if ( rVal.nVal == 0 )
+ {
+ DBG_ERROR( "BigInt::operator/ --> divide by zero" );
+ return;
+ }
+
+ if ( !bIsBig )
+ {
+ // wir bewegen uns im ungefaehrlichem Bereich
+ rMod = BigInt( nVal % rVal.nVal );
+ nVal /= rVal.nVal;
+ return;
+ }
+
+ if ( rVal.nVal == 1 )
+ {
+ rMod = BigInt( (long)0 );
+ return;
+ }
+
+ if ( rVal.nVal == -1 )
+ {
+ rMod = BigInt( (long)0 );
+ bIsNeg = !bIsNeg;
+ return;
+ }
+
+ if ( rVal.nVal <= (long)0xFFFF && rVal.nVal >= -(long)0xFFFF )
+ {
+ // ein BigInt durch ein USHORT teilen
+ USHORT nTmp;
+ if ( rVal.nVal < 0 )
+ {
+ nTmp = (USHORT) -rVal.nVal;
+ bIsNeg = !bIsNeg;
+ }
+ else
+ nTmp = (USHORT) rVal.nVal;
+
+ Div( *this, nTmp, nTmp );
+ rMod = BigInt( (long)nTmp );
+ Normalize( *this );
+ return;
+ }
+ }
+
+ if ( ABS_IsLess( *this, rVal ) )
+ {
+ rMod = *this;
+ *this = BigInt( (long)0 );
+ return;
+ }
+
+ // BigInt durch BigInt teilen
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, *this );
+ MakeBigInt( aTmp2, rVal );
+ DivLong(aTmp1, aTmp2, *this);
+ Normalize( *this );
+ ModLong(aTmp1, aTmp2, rMod); // nicht optimal
+ Normalize( rMod );
+}
+
+// -----------------------------------------------------------------------
+
+BigInt& BigInt::operator%=( const BigInt& rVal )
+{
+ if ( !rVal.bIsBig )
+ {
+ if ( rVal.nVal == 0 )
+ {
+ DBG_ERROR( "BigInt::operator/ --> divide by zero" );
+ return *this;
+ }
+
+ if ( !bIsBig )
+ {
+ // wir bewegen uns im ungefaehrlichem Bereich
+ nVal %= rVal.nVal;
+ return *this;
+ }
+
+ if ( rVal.nVal <= (long)0xFFFF && rVal.nVal >= -(long)0xFFFF )
+ {
+ // ein BigInt durch ein short teilen
+ USHORT nTmp;
+ if ( rVal.nVal < 0 )
+ {
+ nTmp = (USHORT) -rVal.nVal;
+ bIsNeg = !bIsNeg;
+ }
+ else
+ nTmp = (USHORT) rVal.nVal;
+
+ Div( *this, nTmp, nTmp );
+ *this = BigInt( (long)nTmp );
+ return *this;
+ }
+ }
+
+ if ( ABS_IsLess( *this, rVal ) )
+ return *this;
+
+ // BigInt durch BigInt teilen
+ BigInt aTmp1, aTmp2;
+ MakeBigInt( aTmp1, *this );
+ MakeBigInt( aTmp2, rVal );
+ ModLong(aTmp1, aTmp2, *this);
+ Normalize( *this );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL operator==( const BigInt& rVal1, const BigInt& rVal2 )
+{
+ if ( rVal1.bIsBig || rVal2.bIsBig )
+ {
+ BigInt nA, nB;
+ MakeBigInt( nA, rVal1 );
+ MakeBigInt( nB, rVal2 );
+ if ( nA.bIsNeg == nB.bIsNeg )
+ {
+ if ( nA.nLen == nB.nLen )
+ {
+ int i;
+ for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
+ {
+ }
+
+ return nA.nNum[i] == nB.nNum[i];
+ }
+ return FALSE;
+ }
+ return FALSE;
+ }
+ return rVal1.nVal == rVal2.nVal;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL operator<( const BigInt& rVal1, const BigInt& rVal2 )
+{
+ if ( rVal1.bIsBig || rVal2.bIsBig )
+ {
+ BigInt nA, nB;
+ MakeBigInt( nA, rVal1 );
+ MakeBigInt( nB, rVal2 );
+ if ( nA.bIsNeg == nB.bIsNeg )
+ {
+ if ( nA.nLen == nB.nLen )
+ {
+ int i;
+ for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
+ {
+ }
+
+ if ( nA.bIsNeg )
+ return nA.nNum[i] > nB.nNum[i];
+ else
+ return nA.nNum[i] < nB.nNum[i];
+ }
+ if ( nA.bIsNeg )
+ return nA.nLen > nB.nLen;
+ else
+ return nA.nLen < nB.nLen;
+ }
+ return !nB.bIsNeg;
+ }
+ return rVal1.nVal < rVal2.nVal;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL operator >(const BigInt& rVal1, const BigInt& rVal2 )
+{
+ if ( rVal1.bIsBig || rVal2.bIsBig )
+ {
+ BigInt nA, nB;
+ MakeBigInt( nA, rVal1 );
+ MakeBigInt( nB, rVal2 );
+ if ( nA.bIsNeg == nB.bIsNeg )
+ {
+ if ( nA.nLen == nB.nLen )
+ {
+ int i;
+ for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
+ {
+ }
+
+ if ( nA.bIsNeg )
+ return nA.nNum[i] < nB.nNum[i];
+ else
+ return nA.nNum[i] > nB.nNum[i];
+ }
+ if ( nA.bIsNeg )
+ return nA.nLen < nB.nLen;
+ else
+ return nA.nLen > nB.nLen;
+ }
+ return !nA.bIsNeg;
+ }
+
+ return rVal1.nVal > rVal2.nVal;
+}
diff --git a/tools/source/generic/color.cxx b/tools/source/generic/color.cxx
new file mode 100644
index 000000000000..f3ca447bffb5
--- /dev/null
+++ b/tools/source/generic/color.cxx
@@ -0,0 +1,403 @@
+/*************************************************************************
+ *
+ * $RCSfile: color.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdlib.h>
+
+#ifndef _VOS_MACROS_HXX_
+#include <vos/macros.hxx>
+#endif
+
+#ifndef _TOOLS_COLOR_HXX
+#include <color.hxx>
+#endif
+#ifndef _TOOLS_DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <stream.hxx>
+#endif
+
+// -----------
+// - Inlines -
+// -----------
+
+static inline long _FRound( double fVal )
+{
+ return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
+}
+
+// ---------
+// - Color -
+// ---------
+
+UINT8 Color::GetColorError( const Color& rCompareColor ) const
+{
+ const long nErrAbs = labs( (long) rCompareColor.GetRed() - GetRed() ) +
+ labs( (long) rCompareColor.GetGreen() - GetGreen() ) +
+ labs( (long) rCompareColor.GetBlue() - GetBlue() );
+
+ return (UINT8) _FRound( nErrAbs * 0.3333333333 );
+}
+
+// -----------------------------------------------------------------------
+
+void Color::IncreaseLuminance( UINT8 cLumInc )
+{
+ SetRed( (UINT8) VOS_BOUND( (long) COLORDATA_RED( mnColor ) + cLumInc, 0L, 255L ) );
+ SetGreen( (UINT8) VOS_BOUND( (long) COLORDATA_GREEN( mnColor ) + cLumInc, 0L, 255L ) );
+ SetBlue( (UINT8) VOS_BOUND( (long) COLORDATA_BLUE( mnColor ) + cLumInc, 0L, 255L ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Color::DecreaseLuminance( UINT8 cLumDec )
+{
+ SetRed( (UINT8) VOS_BOUND( (long) COLORDATA_RED( mnColor ) - cLumDec, 0L, 255L ) );
+ SetGreen( (UINT8) VOS_BOUND( (long) COLORDATA_GREEN( mnColor ) - cLumDec, 0L, 255L ) );
+ SetBlue( (UINT8) VOS_BOUND( (long) COLORDATA_BLUE( mnColor ) - cLumDec, 0L, 255L ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Color::IncreaseContrast( UINT8 cContInc )
+{
+ if( cContInc)
+ {
+ const double fM = 128.0 / ( 128.0 - 0.4985 * cContInc );
+ const double fOff = 128.0 - fM * 128.0;
+
+ SetRed( (UINT8) VOS_BOUND( _FRound( COLORDATA_RED( mnColor ) * fM + fOff ), 0L, 255L ) );
+ SetGreen( (UINT8) VOS_BOUND( _FRound( COLORDATA_GREEN( mnColor ) * fM + fOff ), 0L, 255L ) );
+ SetBlue( (UINT8) VOS_BOUND( _FRound( COLORDATA_BLUE( mnColor ) * fM + fOff ), 0L, 255L ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Color::DecreaseContrast( UINT8 cContDec )
+{
+ if( cContDec )
+ {
+ const double fM = ( 128.0 - 0.4985 * cContDec ) / 128.0;
+ const double fOff = 128.0 - fM * 128.0;
+
+ SetRed( (UINT8) VOS_BOUND( _FRound( COLORDATA_RED( mnColor ) * fM + fOff ), 0L, 255L ) );
+ SetGreen( (UINT8) VOS_BOUND( _FRound( COLORDATA_GREEN( mnColor ) * fM + fOff ), 0L, 255L ) );
+ SetBlue( (UINT8) VOS_BOUND( _FRound( COLORDATA_BLUE( mnColor ) * fM + fOff ), 0L, 255L ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Color::Invert()
+{
+ SetRed( ~COLORDATA_RED( mnColor ) );
+ SetGreen( ~COLORDATA_GREEN( mnColor ) );
+ SetBlue( ~COLORDATA_BLUE( mnColor ) );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& Color::Read( SvStream& rIStm, BOOL bNewFormat )
+{
+ if ( bNewFormat )
+ rIStm >> mnColor;
+ else
+ rIStm >> *this;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& Color::Write( SvStream& rOStm, BOOL bNewFormat )
+{
+ if ( bNewFormat )
+ rOStm << mnColor;
+ else
+ rOStm << *this;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+#define COL_NAME_USER ((USHORT)0x8000)
+#define COL_RED_1B ((USHORT)0x0001)
+#define COL_RED_2B ((USHORT)0x0002)
+#define COL_GREEN_1B ((USHORT)0x0010)
+#define COL_GREEN_2B ((USHORT)0x0020)
+#define COL_BLUE_1B ((USHORT)0x0100)
+#define COL_BLUE_2B ((USHORT)0x0200)
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, Color& rColor )
+{
+ DBG_ASSERTWARNING( rIStream.GetVersion(), "Color::>> - Solar-Version not set on rIStream" );
+
+ USHORT nColorName;
+ USHORT nRed;
+ USHORT nGreen;
+ USHORT nBlue;
+
+ rIStream >> nColorName;
+
+ if ( nColorName & COL_NAME_USER )
+ {
+ if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cAry[6];
+ USHORT i = 0;
+
+ nRed = 0;
+ nGreen = 0;
+ nBlue = 0;
+
+ if ( nColorName & COL_RED_2B )
+ i += 2;
+ else if ( nColorName & COL_RED_1B )
+ i++;
+ if ( nColorName & COL_GREEN_2B )
+ i += 2;
+ else if ( nColorName & COL_GREEN_1B )
+ i++;
+ if ( nColorName & COL_BLUE_2B )
+ i += 2;
+ else if ( nColorName & COL_BLUE_1B )
+ i++;
+
+ rIStream.Read( cAry, i );
+ i = 0;
+
+ if ( nColorName & COL_RED_2B )
+ {
+ nRed = cAry[i];
+ nRed <<= 8;
+ i++;
+ nRed |= cAry[i];
+ i++;
+ }
+ else if ( nColorName & COL_RED_1B )
+ {
+ nRed = cAry[i];
+ nRed <<= 8;
+ i++;
+ }
+ if ( nColorName & COL_GREEN_2B )
+ {
+ nGreen = cAry[i];
+ nGreen <<= 8;
+ i++;
+ nGreen |= cAry[i];
+ i++;
+ }
+ else if ( nColorName & COL_GREEN_1B )
+ {
+ nGreen = cAry[i];
+ nGreen <<= 8;
+ i++;
+ }
+ if ( nColorName & COL_BLUE_2B )
+ {
+ nBlue = cAry[i];
+ nBlue <<= 8;
+ i++;
+ nBlue |= cAry[i];
+ i++;
+ }
+ else if ( nColorName & COL_BLUE_1B )
+ {
+ nBlue = cAry[i];
+ nBlue <<= 8;
+ i++;
+ }
+ }
+ else
+ {
+ rIStream >> nRed;
+ rIStream >> nGreen;
+ rIStream >> nBlue;
+ }
+
+ rColor.mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
+ }
+ else
+ {
+ static ColorData aColAry[] =
+ {
+ COL_BLACK, // COL_BLACK
+ COL_BLUE, // COL_BLUE
+ COL_GREEN, // COL_GREEN
+ COL_CYAN, // COL_CYAN
+ COL_RED, // COL_RED
+ COL_MAGENTA, // COL_MAGENTA
+ COL_BROWN, // COL_BROWN
+ COL_GRAY, // COL_GRAY
+ COL_LIGHTGRAY, // COL_LIGHTGRAY
+ COL_LIGHTBLUE, // COL_LIGHTBLUE
+ COL_LIGHTGREEN, // COL_LIGHTGREEN
+ COL_LIGHTCYAN, // COL_LIGHTCYAN
+ COL_LIGHTRED, // COL_LIGHTRED
+ COL_LIGHTMAGENTA, // COL_LIGHTMAGENTA
+ COL_YELLOW, // COL_YELLOW
+ COL_WHITE, // COL_WHITE
+ COL_WHITE, // COL_MENUBAR
+ COL_BLACK, // COL_MENUBARTEXT
+ COL_WHITE, // COL_POPUPMENU
+ COL_BLACK, // COL_POPUPMENUTEXT
+ COL_BLACK, // COL_WINDOWTEXT
+ COL_WHITE, // COL_WINDOWWORKSPACE
+ COL_BLACK, // COL_HIGHLIGHT
+ COL_WHITE, // COL_HIGHLIGHTTEXT
+ COL_BLACK, // COL_3DTEXT
+ COL_LIGHTGRAY, // COL_3DFACE
+ COL_WHITE, // COL_3DLIGHT
+ COL_GRAY, // COL_3DSHADOW
+ COL_LIGHTGRAY, // COL_SCROLLBAR
+ COL_WHITE, // COL_FIELD
+ COL_BLACK // COL_FIELDTEXT
+ };
+
+ if ( nColorName < (sizeof( aColAry )/sizeof(ColorData)) )
+ rColor.mnColor = aColAry[nColorName];
+ else
+ rColor.mnColor = COL_BLACK;
+ }
+
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const Color& rColor )
+{
+ DBG_ASSERTWARNING( rOStream.GetVersion(), "Color::<< - Solar-Version not set on rOStream" );
+
+ USHORT nColorName = COL_NAME_USER;
+ USHORT nRed = rColor.GetRed();
+ USHORT nGreen = rColor.GetGreen();
+ USHORT nBlue = rColor.GetBlue();
+ nRed = (nRed<<8) + nRed;
+ nGreen = (nGreen<<8) + nGreen;
+ nBlue = (nBlue<<8) + nBlue;
+
+ if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cAry[6];
+ USHORT i = 0;
+
+ if ( nRed & 0x00FF )
+ {
+ nColorName |= COL_RED_2B;
+ cAry[i] = (unsigned char)(nRed & 0xFF);
+ i++;
+ cAry[i] = (unsigned char)((nRed >> 8) & 0xFF);
+ i++;
+ }
+ else if ( nRed & 0xFF00 )
+ {
+ nColorName |= COL_RED_1B;
+ cAry[i] = (unsigned char)((nRed >> 8) & 0xFF);
+ i++;
+ }
+ if ( nGreen & 0x00FF )
+ {
+ nColorName |= COL_GREEN_2B;
+ cAry[i] = (unsigned char)(nGreen & 0xFF);
+ i++;
+ cAry[i] = (unsigned char)((nGreen >> 8) & 0xFF);
+ i++;
+ }
+ else if ( nGreen & 0xFF00 )
+ {
+ nColorName |= COL_GREEN_1B;
+ cAry[i] = (unsigned char)((nGreen >> 8) & 0xFF);
+ i++;
+ }
+ if ( nBlue & 0x00FF )
+ {
+ nColorName |= COL_BLUE_2B;
+ cAry[i] = (unsigned char)(nBlue & 0xFF);
+ i++;
+ cAry[i] = (unsigned char)((nBlue >> 8) & 0xFF);
+ i++;
+ }
+ else if ( nBlue & 0xFF00 )
+ {
+ nColorName |= COL_BLUE_1B;
+ cAry[i] = (unsigned char)((nBlue >> 8) & 0xFF);
+ i++;
+ }
+
+ rOStream << nColorName;
+ rOStream.Write( cAry, i );
+ }
+ else
+ {
+ rOStream << nColorName;
+ rOStream << nRed;
+ rOStream << nGreen;
+ rOStream << nBlue;
+ }
+
+ return rOStream;
+}
diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx
new file mode 100644
index 000000000000..6fc728df517f
--- /dev/null
+++ b/tools/source/generic/fract.cxx
@@ -0,0 +1,720 @@
+/*************************************************************************
+ *
+ * $RCSfile: fract.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+
+#ifndef _FRACT_HXX
+#include <fract.hxx>
+#endif
+
+#define private public
+#define bIsLong bIsBig
+#include <bigint.hxx>
+#include <stream.hxx>
+
+/*************************************************************************
+|*
+|* GetGGT()
+|*
+|* Beschreibung Berechnet den groessten gemeinsamen Teiler von
+|* nVal1 und nVal2
+|* Parameter long nVal1, long nVal2
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Die Funktion GetGGT berechnet den groessten gemeinsamen Teiler der
+// beiden als Parameter uebergebenen Werte nVal1 und nVal2 nach dem
+// Algorithmus von Euklid. Hat einer der beiden Parameter den Wert 0 oder
+// 1, so wird als Ergebnis der Wert 1 zurŸckgegeben. Da der Algorithmus
+// nur mit positiven Zahlen arbeitet, werden die beiden Parameter
+// entsprechend umgewandelt.
+// Zum Algorithmus: die beiden Parameter werden solange ducheinander
+// geteilt, bis sie beide gleich sind oder bis bei der Division
+// kein Rest bleibt. Der kleinere der beiden Werte ist dann der
+// GGT.
+
+static long GetGGT( long nVal1, long nVal2 )
+{
+ nVal1 = Abs( nVal1 );
+ nVal2 = Abs( nVal2 );
+
+ if ( nVal1 <= 1 || nVal2 <= 1 )
+ return 1;
+
+ while ( nVal1 != nVal2 )
+ {
+ if ( nVal1 > nVal2 )
+ {
+ nVal1 %= nVal2;
+ if ( nVal1 == 0 )
+ return nVal2;
+ }
+ else
+ {
+ nVal2 %= nVal1;
+ if ( nVal2 == 0 )
+ return nVal1;
+ }
+ }
+
+ return nVal1;
+}
+
+static void Reduce( BigInt &rVal1, BigInt &rVal2 )
+{
+ BigInt nA( rVal1 );
+ BigInt nB( rVal2 );
+ nA.Abs();
+ nB.Abs();
+
+ if ( nA.IsOne() || nB.IsOne() || nA.IsZero() || nB.IsZero() )
+ return;
+
+ while ( nA != nB )
+ {
+ if ( nA > nB )
+ {
+ nA %= nB;
+ if ( nA.IsZero() )
+ {
+ rVal1 /= nB;
+ rVal2 /= nB;
+ return;
+ }
+ }
+ else
+ {
+ nB %= nA;
+ if ( nB.IsZero() )
+ {
+ rVal1 /= nA;
+ rVal2 /= nA;
+ return;
+ }
+ }
+ }
+
+ rVal1 /= nA;
+ rVal2 /= nB;
+}
+
+/*************************************************************************
+|*
+|* Fraction::Fraction()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung WP 07.03.97
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+Fraction::Fraction( long nN1, long nN2, long nD1, long nD2 )
+{
+ long n;
+ int i = 1;
+
+ if( nN1 < 0 ) { i = -i; nN1 = -nN1; }
+ if( nN2 < 0 ) { i = -i; nN2 = -nN2; }
+ if( nD1 < 0 ) { i = -i; nD1 = -nD1; }
+ if( nD2 < 0 ) { i = -i; nD2 = -nD2; }
+
+ n = GetGGT( nN1, nD1 ); if( n > 1 ) { nN1 /= n; nD1 /= n; }
+ n = GetGGT( nN1, nD2 ); if( n > 1 ) { nN1 /= n; nD2 /= n; }
+ n = GetGGT( nN2, nD1 ); if( n > 1 ) { nN2 /= n; nD1 /= n; }
+ n = GetGGT( nN2, nD2 ); if( n > 1 ) { nN2 /= n; nD2 /= n; }
+
+ BigInt nN( nN1 );
+ nN *= BigInt( nN2 );
+
+ BigInt nD( nD1 );
+ nD *= BigInt( nD2 );
+
+ while ( nN.bIsLong || nD.bIsLong )
+ {
+ BigInt n1 = 1;
+ BigInt n2 = 2;
+
+ nN += n1;
+ nN /= n2;
+ nD += n1;
+ nD /= n2;
+
+ // Kuerzen ueber Groesste Gemeinsame Teiler
+ Reduce( nN, nD );
+ }
+
+ nNumerator = i * (long)nN;
+ nDenominator = (long)nD;
+}
+
+/*************************************************************************
+|*
+|* Fraction::Fraction()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Zur Initialisierung eines Bruches wird nNum dem Zaehler und nDen dem
+// Nenner zugewiesen. Da negative Werte des Nenners einen Bruch als
+// ungueltig kennzeichnen, wird bei der Eingabe eines negativen Nenners
+// sowohl das Vorzeichen des Nenners und des Zaehlers invertiert um wieder
+// einen gueltigen Wert fuer den Bruch zu erhalten.
+
+Fraction::Fraction( long nNum, long nDen )
+{
+ nNumerator = nNum;
+ nDenominator = nDen;
+ if ( nDenominator < 0 )
+ {
+ nDenominator = -nDenominator;
+ nNumerator = -nNumerator;
+ }
+
+ // Kuerzen ueber Groesste Gemeinsame Teiler
+ long n = GetGGT( nNumerator, nDenominator );
+ nNumerator /= n;
+ nDenominator /= n;
+}
+
+/*************************************************************************
+|*
+|* Fraction::Fraction()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Wenn der Wert von dVal groesser ist als LONG_MAX, dann wird der Bruch
+// auf den Wert ungueltig gesetzt, ansonsten werden dVal und der Nenner
+// solange mit 10 multipliziert, bis entweder der Zaehler oder der Nenner
+// groesser als LONG_MAX / 10 ist. Zum Schluss wird der so entstandene Bruch
+// gekuerzt.
+
+Fraction::Fraction( double dVal )
+{
+ long nDen = 1;
+ long nMAX = LONG_MAX / 10;
+
+ if ( dVal > LONG_MAX || dVal < LONG_MIN )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ return;
+ }
+
+ while ( Abs( (long)dVal ) < nMAX && nDen < nMAX )
+ {
+ dVal *= 10;
+ nDen *= 10;
+ }
+ nNumerator = (long)dVal;
+ nDenominator = nDen;
+
+ // Kuerzen ueber Groesste Gemeinsame Teiler
+ long n = GetGGT( nNumerator, nDenominator );
+ nNumerator /= n;
+ nDenominator /= n;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator double()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 14.05.91
+|*
+*************************************************************************/
+
+Fraction::operator double() const
+{
+ if ( nDenominator > 0 )
+ return (double)nNumerator / (double)nDenominator;
+ else
+ return (double)0;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator+=()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
+// Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
+// ungueltig. Zur Addition werden die beiden Brueche erst durch
+// Erweiterung mit den Nenner des jeweils anderen Bruches auf einen
+// gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler
+// addiert und das Ergebnis gekuerzt (durch Division von Zaehler und
+// Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp SLong
+// gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei
+// einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt.
+
+Fraction& Fraction::operator += ( const Fraction& rVal )
+{
+ if ( !rVal.IsValid() )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ if ( !IsValid() )
+ return *this;
+
+ // (a/b) + (c/d) = ( (a*d) + (c*b) ) / (b*d)
+ BigInt nN( nNumerator );
+ nN *= BigInt( rVal.nDenominator );
+ BigInt nW1Temp( nDenominator );
+ nW1Temp *= BigInt( rVal.nNumerator );
+ nN += nW1Temp;
+
+ BigInt nD( nDenominator );
+ nD *= BigInt( rVal.nDenominator );
+
+ Reduce( nN, nD );
+
+ if ( nN.bIsLong || nD.bIsLong )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ else
+ {
+ nNumerator = (long)nN,
+ nDenominator = (long)nD;
+ }
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator-=()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
+// Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
+// ungueltig. Zur Subtraktion werden die beiden Brueche erst durch
+// Erweiterung mit den Nenner des jeweils anderen Bruches auf einen
+// gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler
+// subtrahiert und das Ergebnis gekuerzt (durch Division von Zaehler und
+// Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp BigInt
+// gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei
+// einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt.
+
+Fraction& Fraction::operator -= ( const Fraction& rVal )
+{
+ if ( !rVal.IsValid() )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ if ( !IsValid() )
+ return *this;
+
+ // (a/b) - (c/d) = ( (a*d) - (c*b) ) / (b*d)
+ BigInt nN( nNumerator );
+ nN *= BigInt( rVal.nDenominator );
+ BigInt nW1Temp( nDenominator );
+ nW1Temp *= BigInt( rVal.nNumerator );
+ nN -= nW1Temp;
+
+ BigInt nD( nDenominator );
+ nD *= BigInt( rVal.nDenominator );
+
+ Reduce( nN, nD );
+
+ if ( nN.bIsLong || nD.bIsLong )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ else
+ {
+ nNumerator = (long)nN,
+ nDenominator = (long)nD;
+ }
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator*=()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung TH 19.08.92
+|*
+*************************************************************************/
+
+// Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
+// Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
+// ungueltig. Zur Multiplikation werden jeweils die beiden Zaehler und
+// Nenner miteinander multipliziert. Um Ueberlaufe zu vermeiden, werden
+// vorher jeweils der GGT zwischen dem Zaehler des einen und dem Nenner
+// des anderen Bruches bestimmt und bei der Multiplikation Zaehler und
+// Nenner durch die entsprechenden Werte geteilt.
+// Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um
+// einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf
+// wird das Ergebnis auf den Wert ungueltig gesetzt.
+
+Fraction& Fraction::operator *= ( const Fraction& rVal )
+{
+ if ( !rVal.IsValid() )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ if ( !IsValid() )
+ return *this;
+
+ long nGGT1 = GetGGT( nNumerator, rVal.nDenominator );
+ long nGGT2 = GetGGT( rVal.nNumerator, nDenominator );
+ BigInt nN( nNumerator / nGGT1 );
+ nN *= BigInt( rVal.nNumerator / nGGT2 );
+ BigInt nD( nDenominator / nGGT2 );
+ nD *= BigInt( rVal.nDenominator / nGGT1 );
+
+ if ( nN.bIsLong || nD.bIsLong )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ else
+ {
+ nNumerator = (long)nN,
+ nDenominator = (long)nD;
+ }
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator/=()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
+// Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
+// ungueltig.
+// Um den Bruch a durch b zu teilen, wird a mit dem Kehrwert von b
+// multipliziert. Analog zu Multiplikation wird jezt jeweils der Zaehler
+// des einen Bruches mit dem Nenner des anderen multipliziert.
+// Um Ueberlaufe zu vermeiden, werden vorher jeweils der GGT zwischen den
+// beiden Zaehlern und den beiden Nennern bestimmt und bei der
+// Multiplikation Zaehler und Nenner durch die entsprechenden Werte
+// geteilt.
+// Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um
+// einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf
+// wird das Ergebnis auf den Wert ungueltig gesetzt.
+
+Fraction& Fraction::operator /= ( const Fraction& rVal )
+{
+ if ( !rVal.IsValid() )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ if ( !IsValid() )
+ return *this;
+
+ long nGGT1 = GetGGT( nNumerator, rVal.nNumerator );
+ long nGGT2 = GetGGT( rVal.nDenominator, nDenominator );
+ BigInt nN( nNumerator / nGGT1 );
+ nN *= BigInt( rVal.nDenominator / nGGT2 );
+ BigInt nD( nDenominator / nGGT2 );
+ nD *= BigInt( rVal.nNumerator / nGGT1 );
+
+ if ( nN.bIsLong || nD.bIsLong )
+ {
+ nNumerator = 0;
+ nDenominator = -1;
+ }
+ else
+ {
+ nNumerator = (long)nN,
+ nDenominator = (long)nD;
+ if ( nDenominator < 0 )
+ {
+ nDenominator = -nDenominator;
+ nNumerator = -nNumerator;
+ }
+ }
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Fraction::ReduceInaccurate()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung JOE 17.09.95
+|* Letzte Aenderung JOE 17.09.95
+|*
+*************************************************************************/
+
+// Funktioniert z.Zt. nur fuer 32-Bit Werte !!!
+// Fehlerbehaftetes Kuerzen einer Fraction.
+// nSignificantBits gibt an, wieviele signifikante Binaerstellen
+// in Zaehler/Nenner mindestens erhalten bleiben sollen.
+// Beispiel: ReduceInaccurate(8) hat einen Fehler <1% [1/2^(8-1)]
+// dabei tritt der groesste Fehler bei folgendem Wertepaar auf:
+// Binaer 1000000011111111111111111111111b/1000000000000000000000000000000b
+// = 1082130431/1073741824
+// = ca. 1.007812499
+// Nach ReduceInaccurate( 8 ) wird daraus 1/1.
+
+void Fraction::ReduceInaccurate( unsigned nSignificantBits )
+{
+ if ( !nNumerator || !nDenominator )
+ return;
+
+ // Zaehler und Nenner auf den Stack fuer schnelleren Zugriff
+ UINT32 nMul;
+ UINT32 nDiv;
+ BOOL bNeg;
+ if ( nNumerator >= 0 )
+ {
+ nMul = (UINT32)nNumerator;
+ bNeg = FALSE;
+ }
+ else
+ {
+ nMul = (UINT32)(-nNumerator);
+ bNeg = TRUE;
+ }
+ nDiv=(UINT32)nDenominator;
+
+ UINT32 a=nMul; unsigned nMulZ=0; // Fuehrende Nullen zaehlen
+ while (a<0x00800000) { nMulZ+=8; a<<=8; }
+ while (a<0x80000000) { nMulZ++; a<<=1; }
+ a=nDiv; unsigned nDivZ=0; // Fuehrende Nullen zaehlen
+ while (a<0x00800000) { nDivZ+=8; a<<=8; }
+ while (a<0x80000000) { nDivZ++; a<<=1; }
+ // Anzahl der verwendeten Digits bestimmen
+ // Auch hier gehe ich davon aus, dass es sich um 32Bit-Werte handelt
+ int nMulDigits=32-nMulZ;
+ int nDivDigits=32-nDivZ;
+ // Nun bestimmen, wieviele Stellen hinten weg koennen
+ // Hier koennte man das Ergebnis noch etwas optimieren...
+ int nMulWeg=nMulDigits-nSignificantBits; if (nMulWeg<0) nMulWeg=0;
+ int nDivWeg=nDivDigits-nSignificantBits; if (nDivWeg<0) nDivWeg=0;
+ int nWeg=Min(nMulWeg,nDivWeg);
+ nMul>>=nWeg;
+ nDiv>>=nWeg;
+ if ( !nMul || !nDiv )
+ {
+ DBG_ERROR( "Oups, beim kuerzen einer Fraction hat sich Joe verrechnet." );
+ return;
+ }
+
+ // Nun noch kuerzen ueber GGT
+ long n1=GetGGT( nMul, nDiv );
+ if ( n1!=1 )
+ {
+ nMul/=n1;
+ nDiv/=n1;
+ }
+ if ( !bNeg )
+ nNumerator = (long)nMul;
+ else
+ nNumerator = -(long)nMul;
+ nDenominator = nDiv;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator ==()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung TH 19.08.92
+|*
+*************************************************************************/
+
+BOOL operator == ( const Fraction& rVal1, const Fraction& rVal2 )
+{
+ if ( !rVal1.IsValid() || !rVal2.IsValid() )
+ return FALSE;
+
+ return rVal1.nNumerator == rVal2.nNumerator
+ && rVal1.nDenominator == rVal2.nDenominator;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator <()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung DV 21.12.92
+|*
+*************************************************************************/
+
+// Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und
+// anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche
+// (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen
+// gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d)
+// und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird
+// zurueckgegeben.
+
+BOOL operator < ( const Fraction& rVal1, const Fraction& rVal2 )
+{
+ if ( !rVal1.IsValid() || !rVal2.IsValid() )
+ return FALSE;
+
+ BigInt nN( rVal1.nNumerator );
+ nN *= BigInt( rVal2.nDenominator );
+ BigInt nD( rVal1.nDenominator );
+ nD *= BigInt( rVal2.nNumerator );
+
+ return nN < nD;
+}
+
+/*************************************************************************
+|*
+|* Fraction::operator >()
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung DV 20.09.90
+|* Letzte Aenderung TH 19.08.92
+|*
+*************************************************************************/
+
+// Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und
+// anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche
+// (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen
+// gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d)
+// und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird
+// zurueckgegeben.
+
+BOOL operator > ( const Fraction& rVal1, const Fraction& rVal2 )
+{
+ if ( !rVal1.IsValid() || !rVal2.IsValid() )
+ return FALSE;
+
+ BigInt nN( rVal1.nNumerator );
+ nN *= BigInt( rVal2.nDenominator );
+ BigInt nD( rVal1.nDenominator);
+ nD *= BigInt( rVal2.nNumerator );
+
+ return nN > nD;
+}
+
+/*************************************************************************
+|*
+|* SvStream& operator>>( SvStream& rIStream, Fraction& rFract )
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung MM 08.01.96
+|* Letzte Aenderung MM 08.01.96
+|*
+*************************************************************************/
+SvStream& operator >> ( SvStream& rIStream, Fraction& rFract )
+{
+ rIStream >> rFract.nNumerator;
+ rIStream >> rFract.nDenominator;
+ return rIStream;
+}
+
+/*************************************************************************
+|*
+|* SvStream& operator<<( SvStream& rIStream, Fraction& rFract )
+|*
+|* Beschreibung FRACT.SDW
+|* Ersterstellung MM 08.01.96
+|* Letzte Aenderung MM 08.01.96
+|*
+*************************************************************************/
+SvStream& operator << ( SvStream& rOStream, const Fraction& rFract )
+{
+ rOStream << rFract.nNumerator;
+ rOStream << rFract.nDenominator;
+ return rOStream;
+}
diff --git a/tools/source/generic/gen.cxx b/tools/source/generic/gen.cxx
new file mode 100644
index 000000000000..3b340a558a3d
--- /dev/null
+++ b/tools/source/generic/gen.cxx
@@ -0,0 +1,699 @@
+/*************************************************************************
+ *
+ * $RCSfile: gen.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _TOOLS_DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _SV_GEN_HXX
+#include <gen.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <stream.hxx>
+#endif
+
+// =======================================================================
+
+SvStream& operator>>( SvStream& rIStream, Pair& rPair )
+{
+ DBG_ASSERTWARNING( rIStream.GetVersion(), "Pair::>> - Solar-Version not set on rIStream" );
+
+ if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cId;
+ unsigned char cAry[8];
+ int i;
+ int i1;
+ int i2;
+ UINT32 nNum;
+
+ rIStream >> cId;
+ i1 = (cId & 0x70) >> 4;
+ i2 = cId & 0x07;
+ rIStream.Read( cAry, i1+i2 );
+
+ nNum = 0;
+ i = i1;
+ while ( i )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ if ( cId & 0x80 )
+ nNum ^= 0xFFFFFFFF;
+ rPair.nA = (INT32)nNum;
+
+ nNum = 0;
+ i = i1+i2;
+ while ( i > i1 )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ if ( cId & 0x08 )
+ nNum ^= 0xFFFFFFFF;
+ rPair.nB = (INT32)nNum;
+ }
+ else
+ {
+ rIStream >> rPair.nA >> rPair.nB;
+ }
+
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const Pair& rPair )
+{
+ DBG_ASSERTWARNING( rOStream.GetVersion(), "Pair::<< - Solar-Version not set on rOStream" );
+
+ if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cAry[9];
+ int i = 1;
+ UINT32 nNum;
+
+ cAry[0] = 0;
+
+ nNum = (UINT32)(INT32)rPair.nA;
+ if ( rPair.nA < 0 )
+ {
+ cAry[0] |= 0x80;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[0] |= 0x40;
+ }
+ else
+ cAry[0] |= 0x30;
+ }
+ else
+ cAry[0] |= 0x20;
+ }
+ else
+ cAry[0] |= 0x10;
+ }
+
+ nNum = (UINT32)(INT32)rPair.nB;
+ if ( rPair.nB < 0 )
+ {
+ cAry[0] |= 0x08;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[0] |= 0x04;
+ }
+ else
+ cAry[0] |= 0x03;
+ }
+ else
+ cAry[0] |= 0x02;
+ }
+ else
+ cAry[0] |= 0x01;
+ }
+
+ rOStream.Write( cAry, i );
+ }
+ else
+ {
+ rOStream << rPair.nA << rPair.nB;
+ }
+
+ return rOStream;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::SetSize()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung DV 29.10.91
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+void Rectangle::SetSize( const Size& rSize )
+{
+ if ( rSize.Width() < 0 )
+ nRight = nLeft + rSize.Width() +1;
+ else if ( rSize.Width() > 0 )
+ nRight = nLeft + rSize.Width() -1;
+ else
+ nRight = RECT_EMPTY;
+
+ if ( rSize.Height() < 0 )
+ nBottom = nTop + rSize.Height() +1;
+ else if ( rSize.Height() > 0 )
+ nBottom = nTop + rSize.Height() -1;
+ else
+ nBottom = RECT_EMPTY;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::Union()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung TH 20.10.92
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+Rectangle& Rectangle::Union( const Rectangle& rRect )
+{
+ if ( rRect.IsEmpty() )
+ return *this;
+
+ if ( IsEmpty() )
+ *this = rRect;
+ else
+ {
+ nLeft = Min( Min( nLeft, rRect.nLeft ), Min( nRight, rRect.nRight ) );
+ nRight = Max( Max( nLeft, rRect.nLeft ), Max( nRight, rRect.nRight ) );
+ nTop = Min( Min( nTop, rRect.nTop ), Min( nBottom, rRect.nBottom ) );
+ nBottom = Max( Max( nTop, rRect.nTop ), Max( nBottom, rRect.nBottom ) );
+ }
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::Intersection()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung TH 20.10.92
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+Rectangle& Rectangle::Intersection( const Rectangle& rRect )
+{
+ if ( IsEmpty() )
+ return *this;
+ if ( rRect.IsEmpty() )
+ {
+ *this = Rectangle();
+ return *this;
+ }
+
+ // nicht mit umgedrehten Rechtecken arbeiten
+ Rectangle aTmpRect( rRect );
+ Justify();
+ aTmpRect.Justify();
+
+ // Schnitt bilden
+ nLeft = Max( nLeft, aTmpRect.nLeft );
+ nRight = Min( nRight, aTmpRect.nRight );
+ nTop = Max( nTop, aTmpRect.nTop );
+ nBottom= Min( nBottom, aTmpRect.nBottom );
+
+ // Feststellen ob Schnitt leer
+ if ( nRight < nLeft || nBottom < nTop )
+ *this = Rectangle();
+
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::Justify()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung DV 07.03.91
+|* Letzte Aenderung DV 07.03.91
+|*
+*************************************************************************/
+
+void Rectangle::Justify()
+{
+ long nHelp;
+
+ // Abfrage, ob Right kleiner Left
+ if ( (nRight < nLeft) && (nRight != RECT_EMPTY) )
+ {
+ nHelp = nLeft;
+ nLeft = nRight;
+ nRight = nHelp;
+ }
+
+ // Abfrage, ob Bottom kleiner Top
+ if ( (nBottom < nTop) && (nBottom != RECT_EMPTY) )
+ {
+ nHelp = nBottom;
+ nBottom = nTop;
+ nTop = nHelp;
+ }
+}
+
+/*************************************************************************
+|*
+|* Rectangle::IsInside()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung TH 19.03.90
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+BOOL Rectangle::IsInside( const Point& rPoint ) const
+{
+ if ( IsEmpty() )
+ return FALSE;
+
+ BOOL bRet = TRUE;
+ if ( nLeft <= nRight )
+ {
+ if ( (rPoint.X() < nLeft) || (rPoint.X() > nRight) )
+ bRet = FALSE;
+ }
+ else
+ {
+ if ( (rPoint.X() > nLeft) || (rPoint.X() < nRight) )
+ bRet = FALSE;
+ }
+ if ( nTop <= nBottom )
+ {
+ if ( (rPoint.Y() < nTop) || (rPoint.Y() > nBottom) )
+ bRet = FALSE;
+ }
+ else
+ {
+ if ( (rPoint.Y() > nTop) || (rPoint.Y() < nBottom) )
+ bRet = FALSE;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::IsInside()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung TH 19.03.90
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+BOOL Rectangle::IsInside( const Rectangle& rRect ) const
+{
+ if ( IsInside( rRect.TopLeft() ) && IsInside( rRect.BottomRight() ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* Rectangle::IsOver()
+|*
+|* Beschreibung GEN.SDW
+|* Ersterstellung TH 19.03.90
+|* Letzte Aenderung MM 21.04.94
+|*
+*************************************************************************/
+
+BOOL Rectangle::IsOver( const Rectangle& rRect ) const
+{
+ // Wenn sie sich nicht schneiden, ueberlappen sie auch nicht
+ return !GetIntersection( rRect ).IsEmpty();
+}
+
+// =======================================================================
+
+SvStream& operator>>( SvStream& rIStream, Rectangle& rRect )
+{
+ DBG_ASSERTWARNING( rIStream.GetVersion(), "Rectangle::>> - Solar-Version not set on rIStream" );
+
+ if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cIdAry[2];
+ unsigned char cAry[16];
+ int i;
+ int iLast;
+ int i1;
+ int i2;
+ int i3;
+ int i4;
+ UINT32 nNum;
+
+ rIStream.Read( cIdAry, 2 );
+ i1 = (cIdAry[0] & 0x70) >> 4;
+ i2 = cIdAry[0] & 0x07;
+ i3 = (cIdAry[1] & 0x70) >> 4;
+ i4 = cIdAry[1] & 0x07;
+ rIStream.Read( cAry, i1+i2+i3+i4 );
+
+ nNum = 0;
+ i = i1;
+ iLast = i;
+ while ( i )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ iLast = i1;
+ if ( cIdAry[0] & 0x80 )
+ nNum ^= 0xFFFFFFFF;
+ rRect.nLeft = (INT32)nNum;
+
+ nNum = 0;
+ i = iLast+i2;
+ while ( i > iLast )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ iLast += i2;
+ if ( cIdAry[0] & 0x08 )
+ nNum ^= 0xFFFFFFFF;
+ rRect.nTop = (INT32)nNum;
+
+ nNum = 0;
+ i = iLast+i3;
+ while ( i > iLast )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ iLast += i3;
+ if ( cIdAry[1] & 0x80 )
+ nNum ^= 0xFFFFFFFF;
+ rRect.nRight = (INT32)nNum;
+
+ nNum = 0;
+ i = iLast+i4;
+ while ( i > iLast )
+ {
+ i--;
+ nNum <<= 8;
+ nNum |= cAry[i];
+ }
+ if ( cIdAry[1] & 0x08 )
+ nNum ^= 0xFFFFFFFF;
+ rRect.nBottom = (INT32)nNum;
+ }
+ else
+ {
+ rIStream >> rRect.nLeft >> rRect.nTop >> rRect.nRight >> rRect.nBottom;
+ }
+
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const Rectangle& rRect )
+{
+ DBG_ASSERTWARNING( rOStream.GetVersion(), "Rectangle::<< - Solar-Version not set on rOStream" );
+
+ if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL )
+ {
+ unsigned char cAry[18];
+ int i = 2;
+ UINT32 nNum;
+
+ cAry[0] = 0;
+ cAry[1] = 0;
+
+ nNum = (UINT32)(INT32)rRect.nLeft;
+ if ( rRect.nLeft < 0 )
+ {
+ cAry[0] |= 0x80;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[0] |= 0x40;
+ }
+ else
+ cAry[0] |= 0x30;
+ }
+ else
+ cAry[0] |= 0x20;
+ }
+ else
+ cAry[0] |= 0x10;
+ }
+
+ nNum = (UINT32)(INT32)rRect.nTop;
+ if ( rRect.nTop < 0 )
+ {
+ cAry[0] |= 0x08;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[0] |= 0x04;
+ }
+ else
+ cAry[0] |= 0x03;
+ }
+ else
+ cAry[0] |= 0x02;
+ }
+ else
+ cAry[0] |= 0x01;
+ }
+
+ nNum = (UINT32)(INT32)rRect.nRight;
+ if ( rRect.nRight < 0 )
+ {
+ cAry[1] |= 0x80;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[1] |= 0x40;
+ }
+ else
+ cAry[1] |= 0x30;
+ }
+ else
+ cAry[1] |= 0x20;
+ }
+ else
+ cAry[1] |= 0x10;
+ }
+
+ nNum = (UINT32)(INT32)rRect.nBottom;
+ if ( rRect.nBottom < 0 )
+ {
+ cAry[1] |= 0x08;
+ nNum ^= 0xFFFFFFFF;
+ }
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+
+ if ( nNum )
+ {
+ cAry[i] = (unsigned char)(nNum & 0xFF);
+ nNum >>= 8;
+ i++;
+ cAry[1] |= 0x04;
+ }
+ else
+ cAry[1] |= 0x03;
+ }
+ else
+ cAry[1] |= 0x02;
+ }
+ else
+ cAry[1] |= 0x01;
+ }
+
+ rOStream.Write( cAry, i );
+ }
+ else
+ {
+ rOStream << rRect.nLeft << rRect.nTop << rRect.nRight << rRect.nBottom;
+ }
+
+ return rOStream;
+}
diff --git a/tools/source/generic/link.cxx b/tools/source/generic/link.cxx
new file mode 100644
index 000000000000..33248d3363cd
--- /dev/null
+++ b/tools/source/generic/link.cxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+ *
+ * $RCSfile: link.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _LINK_HXX
+#include <link.hxx>
+#endif
+
+/*************************************************************************
+|*
+|* Link::operator==()
+|*
+|* Beschreibung LINK.SDW
+|* Ersterstellung AM 14.02.91
+|* Letzte Aenderung TH 07.11.95
+|*
+*************************************************************************/
+
+BOOL Link::operator==( const Link& rLink ) const
+{
+ if ( pFunc == rLink.pFunc )
+ {
+ if ( pFunc )
+ {
+ if ( pInst == rLink.pInst )
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
diff --git a/tools/source/generic/makefile.mk b/tools/source/generic/makefile.mk
new file mode 100644
index 000000000000..6b6ce0d86eef
--- /dev/null
+++ b/tools/source/generic/makefile.mk
@@ -0,0 +1,98 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=gen
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/toolsin.obj \
+ $(SLO)$/link.obj \
+ $(SLO)$/bigint.obj \
+ $(SLO)$/fract.obj \
+ $(SLO)$/solmath.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/l2txtenc.obj \
+ $(SLO)$/gen.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/toolsin.obj \
+ $(OBJ)$/link.obj \
+ $(OBJ)$/bigint.obj \
+ $(OBJ)$/fract.obj \
+ $(OBJ)$/solmath.obj \
+ $(OBJ)$/color.obj \
+ $(OBJ)$/l2txtenc.obj \
+ $(OBJ)$/gen.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/generic/toolsin.cxx b/tools/source/generic/toolsin.cxx
new file mode 100644
index 000000000000..b37e14321d9e
--- /dev/null
+++ b/tools/source/generic/toolsin.cxx
@@ -0,0 +1,159 @@
+/*************************************************************************
+ *
+ * $RCSfile: toolsin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_TOOLSIN_CXX
+
+#include <string.h>
+
+#ifndef _SHL_HXX
+#include <shl.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _INTNTAB_HXX
+#include <intntab.hxx>
+#endif
+#ifndef _TOOLSIN_HXX
+#include <toolsin.hxx>
+#endif
+
+#if defined( WIN ) || defined( WNT ) || defined( OS2 )
+#include <dll.hxx>
+#endif
+#ifdef MAC
+void ImpDeInitMemMgr();
+#endif
+
+void ImplDeleteCharTabData();
+
+// =======================================================================
+
+// Hier drin, da DOS bisher kein eigenes TOOLS-Verzeichnis hat
+
+#if defined( DOS )
+
+static void* aAppData[SHL_COUNT];
+
+void** GetAppData( USHORT nSharedLib )
+{
+ return &(aAppData[nSharedLib]);
+}
+
+#endif
+
+// =======================================================================
+
+TOOLSINDATA* ImplGetToolsInData()
+{
+ TOOLSINDATA** ppData = (TOOLSINDATA**)GetAppData( SHL_TOOLS );
+ if ( !(*ppData) )
+ {
+ TOOLSINDATA* pData = new TOOLSINDATA;
+ memset( pData, 0, sizeof( TOOLSINDATA ) );
+ *ppData = pData;
+ }
+
+ return *ppData;
+}
+
+// =======================================================================
+
+void InitTools()
+{
+ DBG_DEBUGSTART();
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitTools()
+{
+ TOOLSINDATA** ppData = (TOOLSINDATA**)GetAppData( SHL_TOOLS );
+ TOOLSINDATA* pData = *ppData;
+
+ if ( pData )
+ {
+ ImplDeleteIntnListData();
+ ImplDeleteCharTabData();
+ delete pData;
+ *ppData = NULL;
+ }
+
+ DBG_DEBUGEND();
+}
+
+// -----------------------------------------------------------------------
+
+void GlobalDeInitTools()
+{
+ DBG_GLOBALDEBUGEND();
+
+#if defined( WIN ) || defined( WNT )
+ ImpDeInitWinTools();
+#endif
+#ifdef OS2
+ ImpDeInitOS2Tools();
+#endif
+#ifdef MAC
+ ImpDeInitMemMgr();
+#endif
+}
diff --git a/tools/source/inet/inetmime.cxx b/tools/source/inet/inetmime.cxx
new file mode 100644
index 000000000000..a1d70a045222
--- /dev/null
+++ b/tools/source/inet/inetmime.cxx
@@ -0,0 +1,4630 @@
+/*************************************************************************
+ *
+ * $RCSfile: inetmime.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <limits>
+
+#ifndef _DATETIME_HXX
+#include <datetime.hxx>
+#endif
+#ifndef TOOLS_INETMIME_HXX
+#include <inetmime.hxx>
+#endif
+
+#undef max // defined by <tools/solar.h>
+#undef min // defined by <tools/solar.h>
+
+namespace unnamed_tools_inetmime {} using namespace unnamed_tools_inetmime;
+ // unnamed namespaces don't work well yet
+
+//============================================================================
+namespace unnamed_tools_inetmime {
+
+class Charset
+{
+ rtl_TextEncoding m_eEncoding;
+ const sal_uInt32 * m_pRanges;
+
+public:
+ inline Charset(rtl_TextEncoding eTheEncoding,
+ const sal_uInt32 * pTheRanges);
+
+ rtl_TextEncoding getEncoding() const { return m_eEncoding; }
+
+ bool contains(sal_uInt32 nChar) const;
+};
+
+inline Charset::Charset(rtl_TextEncoding eTheEncoding,
+ const sal_uInt32 * pTheRanges):
+ m_eEncoding(eTheEncoding),
+ m_pRanges(pTheRanges)
+{
+ DBG_ASSERT(m_pRanges, "Charset::Charset(): Bad ranges");
+}
+
+//============================================================================
+void appendISO88591(UniString & rText, sal_Char const * pBegin,
+ sal_Char const * pEnd);
+
+}
+
+//============================================================================
+class INetMIMECharsetList_Impl
+{
+ struct Node
+ {
+ Charset m_aCharset;
+ bool m_bDisabled;
+ Node * m_pNext;
+
+ inline Node(const Charset & rTheCharset, bool bTheDisabled,
+ Node * pTheNext);
+ };
+
+ Node * m_pFirst;
+
+public:
+ INetMIMECharsetList_Impl(): m_pFirst(0) {}
+
+ ~INetMIMECharsetList_Impl();
+
+ void prepend(const Charset & rCharset)
+ { m_pFirst = new Node(rCharset, false, m_pFirst); }
+
+ void includes(sal_uInt32 nChar);
+
+ rtl_TextEncoding getPreferredEncoding(rtl_TextEncoding eDefault
+ = RTL_TEXTENCODING_DONTKNOW)
+ const;
+
+ void reset();
+};
+
+inline INetMIMECharsetList_Impl::Node::Node(const Charset & rTheCharset,
+ bool bTheDisabled,
+ Node * pTheNext):
+ m_aCharset(rTheCharset),
+ m_bDisabled(bTheDisabled),
+ m_pNext(pTheNext)
+{}
+
+//============================================================================
+namespace unnamed_tools_inetmime {
+
+struct Parameter
+{
+ Parameter * m_pNext;
+ ByteString m_aAttribute;
+ ByteString m_aCharset;
+ ByteString m_aLanguage;
+ ByteString m_aValue;
+ sal_uInt32 m_nSection;
+ bool m_bExtended;
+
+ inline Parameter(Parameter * pTheNext, ByteString const & rTheAttribute,
+ ByteString const & rTheCharset,
+ ByteString const & rTheLanguage,
+ ByteString const & rTheValue, sal_uInt32 nTheSection,
+ bool bTheExtended);
+};
+
+inline Parameter::Parameter(Parameter * pTheNext,
+ ByteString const & rTheAttribute,
+ ByteString const & rTheCharset,
+ ByteString const & rTheLanguage,
+ ByteString const & rTheValue,
+ sal_uInt32 nTheSection, bool bTheExtended):
+ m_pNext(pTheNext),
+ m_aAttribute(rTheAttribute),
+ m_aCharset(rTheCharset),
+ m_aLanguage(rTheLanguage),
+ m_aValue(rTheValue),
+ m_nSection(nTheSection),
+ m_bExtended(bTheExtended)
+{}
+
+//============================================================================
+struct ParameterList
+{
+ Parameter * m_pList;
+
+ ParameterList(): m_pList(0) {}
+
+ inline ~ParameterList();
+
+ Parameter ** find(ByteString const & rAttribute, sal_uInt32 nSection,
+ bool & rPresent);
+};
+
+inline ParameterList::~ParameterList()
+{
+ while (m_pList)
+ {
+ Parameter * pNext = m_pList->m_pNext;
+ delete m_pList;
+ m_pList = pNext;
+ }
+}
+
+//============================================================================
+bool parseParameters(ParameterList const & rInput,
+ INetContentTypeParameterList * pOutput);
+
+}
+
+//============================================================================
+//
+// Charset
+//
+//============================================================================
+
+bool Charset::contains(sal_uInt32 nChar) const
+{
+ for (const sal_uInt32 * p = m_pRanges;;)
+ {
+ if (nChar < *p++)
+ return false;
+ if (nChar <= *p++)
+ return true;
+ }
+}
+
+//============================================================================
+//
+// appendISO88591
+//
+//============================================================================
+
+namespace unnamed_tools_inetmime {
+
+void appendISO88591(UniString & rText, sal_Char const * pBegin,
+ sal_Char const * pEnd)
+{
+ sal_Size nLength = pEnd - pBegin;
+ sal_Unicode * pBuffer = new sal_Unicode[nLength];
+ for (sal_Unicode * p = pBuffer; pBegin != pEnd;)
+ *p++ = sal_uChar(*pBegin++);
+ rText.Append(pBuffer, nLength);
+ delete[] pBuffer;
+}
+
+}
+
+//============================================================================
+//
+// INetMIMECharsetList_Impl
+//
+//============================================================================
+
+INetMIMECharsetList_Impl::~INetMIMECharsetList_Impl()
+{
+ while (m_pFirst)
+ {
+ Node * pRemove = m_pFirst;
+ m_pFirst = m_pFirst->m_pNext;
+ delete pRemove;
+ }
+}
+
+//============================================================================
+void INetMIMECharsetList_Impl::includes(sal_uInt32 nChar)
+{
+ for (Node * p = m_pFirst; p; p = p->m_pNext)
+ if (!(p->m_bDisabled || p->m_aCharset.contains(nChar)))
+ p->m_bDisabled = true;
+}
+
+//============================================================================
+rtl_TextEncoding
+INetMIMECharsetList_Impl::getPreferredEncoding(rtl_TextEncoding eDefault)
+ const
+{
+ for (Node * p = m_pFirst; p; p = p->m_pNext)
+ if (!p->m_bDisabled)
+ return p->m_aCharset.getEncoding();
+ return eDefault;
+}
+
+//============================================================================
+void INetMIMECharsetList_Impl::reset()
+{
+ for (Node * p = m_pFirst; p; p = p->m_pNext)
+ p->m_bDisabled = false;
+}
+
+//============================================================================
+//
+// ParameterList
+//
+//============================================================================
+
+Parameter ** ParameterList::find(ByteString const & rAttribute,
+ sal_uInt32 nSection, bool & rPresent)
+{
+ Parameter ** p = &m_pList;
+ for (; *p; p = &(*p)->m_pNext)
+ {
+ StringCompare eCompare = rAttribute.CompareTo((*p)->m_aAttribute);
+ if (eCompare == COMPARE_GREATER)
+ break;
+ else if (eCompare == COMPARE_EQUAL)
+ if (nSection > (*p)->m_nSection)
+ break;
+ else if (nSection == (*p)->m_nSection)
+ {
+ rPresent = true;
+ return p;
+ }
+ }
+ rPresent = false;
+ return p;
+}
+
+//============================================================================
+//
+// parseParameters
+//
+//============================================================================
+
+namespace unnamed_tools_inetmime {
+
+bool parseParameters(ParameterList const & rInput,
+ INetContentTypeParameterList * pOutput)
+{
+ if (pOutput)
+ pOutput->Clear();
+
+ Parameter * pPrev = 0;
+ for (Parameter * p = rInput.m_pList; p; p = p->m_pNext)
+ {
+ if (p->m_nSection > 0
+ && (!pPrev
+ || pPrev->m_nSection != p->m_nSection - 1
+ || pPrev->m_aAttribute != p->m_aAttribute))
+ return false;
+ pPrev = p;
+ }
+
+ if (pOutput)
+ for (Parameter * p = rInput.m_pList; p;)
+ {
+ bool bCharset = p->m_aCharset.Len() != 0;
+ rtl_TextEncoding eEncoding;
+ if (bCharset)
+ eEncoding
+ = INetMIME::getCharsetEncoding(p->m_aCharset.GetBuffer(),
+ p->m_aCharset.GetBuffer()
+ + rInput.m_pList->
+ m_aCharset.
+ Len());
+ UniString aValue;
+ bool bBadEncoding = false;
+ Parameter * pNext = p;
+ do
+ {
+ sal_Size nSize;
+ sal_Unicode * pUnicode
+ = INetMIME::convertToUnicode(pNext->m_aValue.GetBuffer(),
+ pNext->m_aValue.GetBuffer()
+ + pNext->m_aValue.Len(),
+ bCharset && p->m_bExtended ?
+ eEncoding :
+ RTL_TEXTENCODING_UTF8,
+ nSize);
+ if (!pUnicode && !(bCharset && p->m_bExtended))
+ pUnicode = INetMIME::convertToUnicode(
+ pNext->m_aValue.GetBuffer(),
+ pNext->m_aValue.GetBuffer()
+ + pNext->m_aValue.Len(),
+ RTL_TEXTENCODING_ISO_8859_1, nSize);
+ if (!pUnicode)
+ {
+ bBadEncoding = true;
+ break;
+ }
+ aValue += UniString(pUnicode, nSize);
+ delete[] pUnicode;
+ pNext = pNext->m_pNext;
+ }
+ while (pNext && pNext->m_nSection > 0);
+ if (bBadEncoding)
+ {
+ aValue.Erase();
+ for (pNext = p;;)
+ {
+ if (pNext->m_bExtended)
+ for (xub_StrLen i = 0; i < pNext->m_aValue.Len(); ++i)
+ aValue
+ += sal_Unicode(sal_uChar
+ (pNext->
+ m_aValue.GetChar(i)))
+ | 0xF800;
+ else
+ for (xub_StrLen i = 0; i < pNext->m_aValue.Len(); ++i)
+ aValue
+ += sal_Unicode(sal_uChar
+ (pNext->
+ m_aValue.GetChar(i)));
+ pNext = pNext->m_pNext;
+ if (!pNext || pNext->m_nSection == 0)
+ break;
+ };
+ }
+ pOutput->Insert(new INetContentTypeParameter(p->m_aAttribute,
+ p->m_aCharset,
+ p->m_aLanguage,
+ aValue,
+ !bBadEncoding),
+ LIST_APPEND);
+ p = pNext;
+ }
+ return true;
+}
+
+}
+
+//============================================================================
+//
+// INetMIME
+//
+//============================================================================
+
+// static
+bool INetMIME::isAtomChar(sal_uInt32 nChar)
+{
+ static const bool aMap[128]
+ = { false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, true, false, true, true, true, true, true, // !"#$%&'
+ false, false, true, true, false, true, false, true, //()*+,-./
+ true, true, true, true, true, true, true, true, //01234567
+ true, true, false, false, false, true, false, true, //89:;<=>?
+ false, true, true, true, true, true, true, true, //@ABCDEFG
+ true, true, true, true, true, true, true, true, //HIJKLMNO
+ true, true, true, true, true, true, true, true, //PQRSTUVW
+ true, true, true, false, false, false, true, true, //XYZ[\]^_
+ true, true, true, true, true, true, true, true, //`abcdefg
+ true, true, true, true, true, true, true, true, //hijklmno
+ true, true, true, true, true, true, true, true, //pqrstuvw
+ true, true, true, true, true, true, true, false //xyz{|}~
+ };
+ return isUSASCII(nChar) && aMap[nChar];
+}
+
+//============================================================================
+// static
+bool INetMIME::isTokenChar(sal_uInt32 nChar)
+{
+ static const sal_Char aMap[128]
+ = { false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, true, false, true, true, true, true, true, // !"#$%&'
+ false, false, true, true, false, true, true, false, //()*+,-./
+ true, true, true, true, true, true, true, true, //01234567
+ true, true, false, false, false, false, false, false, //89:;<=>?
+ false, true, true, true, true, true, true, true, //@ABCDEFG
+ true, true, true, true, true, true, true, true, //HIJKLMNO
+ true, true, true, true, true, true, true, true, //PQRSTUVW
+ true, true, true, false, false, false, true, true, //XYZ[\]^_
+ true, true, true, true, true, true, true, true, //`abcdefg
+ true, true, true, true, true, true, true, true, //hijklmno
+ true, true, true, true, true, true, true, true, //pqrstuvw
+ true, true, true, true, true, true, true, false //xyz{|}~
+ };
+ return isUSASCII(nChar) && aMap[nChar];
+}
+
+//============================================================================
+// static
+bool INetMIME::isEncodedWordTokenChar(sal_uInt32 nChar)
+{
+ static const sal_Char aMap[128]
+ = { false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, true, false, true, true, true, true, true, // !"#$%&'
+ false, false, true, true, false, true, false, false, //()*+,-./
+ true, true, true, true, true, true, true, true, //01234567
+ true, true, false, false, false, false, false, false, //89:;<=>?
+ false, true, true, true, true, true, true, true, //@ABCDEFG
+ true, true, true, true, true, true, true, true, //HIJKLMNO
+ true, true, true, true, true, true, true, true, //PQRSTUVW
+ true, true, true, false, false, false, true, true, //XYZ[\]^_
+ true, true, true, true, true, true, true, true, //`abcdefg
+ true, true, true, true, true, true, true, true, //hijklmno
+ true, true, true, true, true, true, true, true, //pqrstuvw
+ true, true, true, true, true, true, true, false //xyz{|}~
+ };
+ return isUSASCII(nChar) && aMap[nChar];
+}
+
+//============================================================================
+// static
+bool INetMIME::isIMAPAtomChar(sal_uInt32 nChar)
+{
+ static const sal_Char aMap[128]
+ = { false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, true, false, true, true, false, true, true, // !"#$%&'
+ false, false, false, true, true, true, true, true, //()*+,-./
+ true, true, true, true, true, true, true, true, //01234567
+ true, true, true, true, true, true, true, true, //89:;<=>?
+ true, true, true, true, true, true, true, true, //@ABCDEFG
+ true, true, true, true, true, true, true, true, //HIJKLMNO
+ true, true, true, true, true, true, true, true, //PQRSTUVW
+ true, true, true, true, false, true, true, true, //XYZ[\]^_
+ true, true, true, true, true, true, true, true, //`abcdefg
+ true, true, true, true, true, true, true, true, //hijklmno
+ true, true, true, true, true, true, true, true, //pqrstuvw
+ true, true, true, false, true, true, true, false //xyz{|}~
+ };
+ return isUSASCII(nChar) && aMap[nChar];
+}
+
+//============================================================================
+// static
+sal_uInt32 INetMIME::getDigit(int nWeight)
+{
+ DBG_ASSERT(nWeight >= 0 && nWeight < 10,
+ "INetMIME::getDigit(): Bad weight");
+
+ static const sal_Char aDigits[16]
+ = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+ return aDigits[nWeight];
+}
+
+//============================================================================
+// static
+sal_uInt32 INetMIME::getHexDigit(int nWeight)
+{
+ DBG_ASSERT(nWeight >= 0 && nWeight < 16,
+ "INetMIME::getHexDigit(): Bad weight");
+
+ static const sal_Char aDigits[16]
+ = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
+ 'D', 'E', 'F' };
+ return aDigits[nWeight];
+}
+
+//============================================================================
+// static
+sal_uInt32 INetMIME::getBase64Digit(int nWeight)
+{
+ DBG_ASSERT(nWeight >= 0 && nWeight < 64,
+ "INetMIME::getBase64Digit(): Bad weight");
+
+ static const sal_Char aDigits[64]
+ = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
+ return aDigits[nWeight];
+}
+
+//============================================================================
+// static
+bool INetMIME::equalIgnoreCase(const sal_Char * pBegin1,
+ const sal_Char * pEnd1,
+ const sal_Char * pBegin2,
+ const sal_Char * pEnd2)
+{
+ DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pBegin2 && pBegin2 <= pEnd2,
+ "INetMIME::equalIgnoreCase(): Bad sequences");
+
+ if (pEnd1 - pBegin1 != pEnd2 - pBegin2)
+ return false;
+ while (pBegin1 != pEnd1)
+ if (toUpperCase(*pBegin1++) != toUpperCase(*pBegin2++))
+ return false;
+ return true;
+}
+
+//============================================================================
+// static
+bool INetMIME::equalIgnoreCase(const sal_Char * pBegin1,
+ const sal_Char * pEnd1,
+ const sal_Char * pString2)
+{
+ DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
+ "INetMIME::equalIgnoreCase(): Bad sequences");
+
+ while (*pString2 != 0)
+ if (pBegin1 == pEnd1
+ || toUpperCase(*pBegin1++) != toUpperCase(*pString2++))
+ return false;
+ return pBegin1 == pEnd1;
+}
+
+//============================================================================
+// static
+bool INetMIME::equalIgnoreCase(const sal_Unicode * pBegin1,
+ const sal_Unicode * pEnd1,
+ const sal_Char * pString2)
+{
+ DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
+ "INetMIME::equalIgnoreCase(): Bad sequences");
+
+ while (*pString2 != 0)
+ if (pBegin1 == pEnd1
+ || toUpperCase(*pBegin1++) != toUpperCase(*pString2++))
+ return false;
+ return pBegin1 == pEnd1;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::skipLinearWhiteSpace(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipLinearWhiteSpace(): Bad sequence");
+
+ while (pBegin != pEnd)
+ switch (*pBegin)
+ {
+ case '\t':
+ case ' ':
+ ++pBegin;
+ break;
+
+ case 0x0D: // CR
+ if (startsWithLineFolding(pBegin, pEnd))
+ pBegin += 3;
+ else
+ return pBegin;
+ break;
+
+ default:
+ return pBegin;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::skipLinearWhiteSpace(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipLinearWhiteSpace(): Bad sequence");
+
+ while (pBegin != pEnd)
+ switch (*pBegin)
+ {
+ case '\t':
+ case ' ':
+ ++pBegin;
+ break;
+
+ case 0x0D: // CR
+ if (startsWithLineFolding(pBegin, pEnd))
+ pBegin += 3;
+ else
+ return pBegin;
+ break;
+
+ default:
+ return pBegin;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::skipComment(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipComment(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == '(')
+ {
+ sal_uInt32 nLevel = 0;
+ for (const sal_Char * p = pBegin; p != pEnd;)
+ switch (*p++)
+ {
+ case '(':
+ ++nLevel;
+ break;
+
+ case ')':
+ if (--nLevel == 0)
+ return p;
+ break;
+
+ case '\\':
+ if (p != pEnd)
+ ++p;
+ break;
+ }
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::skipComment(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipComment(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == '(')
+ {
+ sal_uInt32 nLevel = 0;
+ for (const sal_Unicode * p = pBegin; p != pEnd;)
+ switch (*p++)
+ {
+ case '(':
+ ++nLevel;
+ break;
+
+ case ')':
+ if (--nLevel == 0)
+ return p;
+ break;
+
+ case '\\':
+ if (p != pEnd)
+ ++p;
+ break;
+ }
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::skipLinearWhiteSpaceComment(const sal_Char *
+ pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
+
+ while (pBegin != pEnd)
+ switch (*pBegin)
+ {
+ case '\t':
+ case ' ':
+ ++pBegin;
+ break;
+
+ case 0x0D: // CR
+ if (startsWithLineFolding(pBegin, pEnd))
+ pBegin += 3;
+ else
+ return pBegin;
+ break;
+
+ case '(':
+ {
+ const sal_Char * p = skipComment(pBegin, pEnd);
+ if (p == pBegin)
+ return pBegin;
+ pBegin = p;
+ break;
+ }
+
+ default:
+ return pBegin;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::skipLinearWhiteSpaceComment(const sal_Unicode *
+ pBegin,
+ const sal_Unicode *
+ pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
+
+ while (pBegin != pEnd)
+ switch (*pBegin)
+ {
+ case '\t':
+ case ' ':
+ ++pBegin;
+ break;
+
+ case 0x0D: // CR
+ if (startsWithLineFolding(pBegin, pEnd))
+ pBegin += 3;
+ else
+ return pBegin;
+ break;
+
+ case '(':
+ {
+ const sal_Unicode * p = skipComment(pBegin, pEnd);
+ if (p == pBegin)
+ return pBegin;
+ pBegin = p;
+ break;
+ }
+
+ default:
+ return pBegin;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::skipQuotedString(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipQuotedString(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == '"')
+ for (const sal_Char * p = pBegin + 1; p != pEnd;)
+ switch (*p++)
+ {
+ case 0x0D: // CR
+ if (pEnd - p < 2 || *p++ != 0x0A // LF
+ || !isWhiteSpace(*p++))
+ return pBegin;
+ break;
+
+ case '"':
+ return p;
+
+ case '\\':
+ if (p != pEnd)
+ ++p;
+ break;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::skipQuotedString(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::skipQuotedString(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == '"')
+ for (const sal_Unicode * p = pBegin + 1; p != pEnd;)
+ switch (*p++)
+ {
+ case 0x0D: // CR
+ if (pEnd - p < 2 || *p++ != 0x0A // LF
+ || !isWhiteSpace(*p++))
+ return pBegin;
+ break;
+
+ case '"':
+ return p;
+
+ case '\\':
+ if (p != pEnd)
+ ++p;
+ break;
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::scanAtom(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ while (pBegin != pEnd && isAtomChar(*pBegin))
+ ++pBegin;
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::scanAtom(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ while (pBegin != pEnd && isAtomChar(*pBegin))
+ ++pBegin;
+ return pBegin;
+}
+
+//============================================================================
+// static
+bool INetMIME::scanUnsigned(const sal_Char *& rBegin, const sal_Char * pEnd,
+ bool bLeadingZeroes, sal_uInt32 & rValue)
+{
+ sal_uInt64 nTheValue = 0;
+ for (const sal_Char * p = rBegin; p != pEnd; ++p)
+ {
+ int nWeight = getWeight(*p);
+ if (nWeight < 0)
+ break;
+ nTheValue = 10 * nTheValue + nWeight;
+ if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
+ return false;
+ }
+ if (nTheValue == 0 && (p == rBegin || !bLeadingZeroes && p - rBegin != 1))
+ return false;
+ rBegin = p;
+ rValue = sal_uInt32(nTheValue);
+ return true;
+}
+
+//============================================================================
+// static
+bool INetMIME::scanUnsigned(const sal_Unicode *& rBegin,
+ const sal_Unicode * pEnd, bool bLeadingZeroes,
+ sal_uInt32 & rValue)
+{
+ sal_uInt64 nTheValue = 0;
+ for (const sal_Unicode * p = rBegin; p != pEnd; ++p)
+ {
+ int nWeight = getWeight(*p);
+ if (nWeight < 0)
+ break;
+ nTheValue = 10 * nTheValue + nWeight;
+ if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
+ return false;
+ }
+ if (nTheValue == 0 && (p == rBegin || !bLeadingZeroes && p - rBegin != 1))
+ return false;
+ rBegin = p;
+ rValue = sal_uInt32(nTheValue);
+ return true;
+}
+
+//============================================================================
+// static
+bool INetMIME::scanUnsignedHex(const sal_Char *& rBegin,
+ const sal_Char * pEnd, bool bLeadingZeroes,
+ sal_uInt32 & rValue)
+{
+ sal_uInt64 nTheValue = 0;
+ for (const sal_Char * p = rBegin; p != pEnd; ++p)
+ {
+ int nWeight = getHexWeight(*p);
+ if (nWeight < 0)
+ break;
+ nTheValue = nTheValue << 4 | nWeight;
+ if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
+ return false;
+ }
+ if (nTheValue == 0 && (p == rBegin || !bLeadingZeroes && p - rBegin != 1))
+ return false;
+ rBegin = p;
+ rValue = sal_uInt32(nTheValue);
+ return true;
+}
+
+//============================================================================
+// static
+bool INetMIME::scanUnsignedHex(const sal_Unicode *& rBegin,
+ const sal_Unicode * pEnd, bool bLeadingZeroes,
+ sal_uInt32 & rValue)
+{
+ sal_uInt64 nTheValue = 0;
+ for (const sal_Unicode * p = rBegin; p != pEnd; ++p)
+ {
+ int nWeight = getHexWeight(*p);
+ if (nWeight < 0)
+ break;
+ nTheValue = nTheValue << 4 | nWeight;
+ if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
+ return false;
+ }
+ if (nTheValue == 0 && (p == rBegin || !bLeadingZeroes && p - rBegin != 1))
+ return false;
+ rBegin = p;
+ rValue = sal_uInt32(nTheValue);
+ return true;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::scanQuotedBlock(const sal_Char * pBegin,
+ const sal_Char * pEnd,
+ sal_uInt32 nOpening,
+ sal_uInt32 nClosing,
+ sal_uInt32 & rLength,
+ bool & rModify)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::scanQuotedBlock(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == nOpening)
+ {
+ ++rLength;
+ ++pBegin;
+ while (pBegin != pEnd)
+ if (*pBegin == nClosing)
+ {
+ ++rLength;
+ return ++pBegin;
+ }
+ else
+ {
+ sal_uInt32 c = *pBegin++;
+ switch (c)
+ {
+ case 0x0D: // CR
+ if (pBegin != pEnd && *pBegin == 0x0A) // LF
+ if (pEnd - pBegin >= 2 && isWhiteSpace(pBegin[1]))
+ {
+ ++rLength;
+ rModify = true;
+ pBegin += 2;
+ }
+ else
+ {
+ rLength += 3;
+ rModify = true;
+ ++pBegin;
+ }
+ else
+ ++rLength;
+ break;
+
+ case '\\':
+ ++rLength;
+ if (pBegin != pEnd)
+ if (startsWithLineBreak(pBegin, pEnd)
+ && (pEnd - pBegin < 3
+ || !isWhiteSpace(pBegin[2])))
+ {
+ rLength += 3;
+ rModify = true;
+ pBegin += 2;
+ }
+ else
+ ++pBegin;
+ break;
+
+ default:
+ ++rLength;
+ if (!isUSASCII(c))
+ rModify = true;
+ break;
+ }
+ }
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+const sal_Unicode * INetMIME::scanQuotedBlock(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd,
+ sal_uInt32 nOpening,
+ sal_uInt32 nClosing,
+ sal_uInt32 & rLength,
+ bool & rModify)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIME::scanQuotedBlock(): Bad sequence");
+
+ if (pBegin != pEnd && *pBegin == nOpening)
+ {
+ ++rLength;
+ ++pBegin;
+ while (pBegin != pEnd)
+ if (*pBegin == nClosing)
+ {
+ ++rLength;
+ return ++pBegin;
+ }
+ else
+ {
+ sal_uInt32 c = *pBegin++;
+ switch (c)
+ {
+ case 0x0D: // CR
+ if (pBegin != pEnd && *pBegin == 0x0A) // LF
+ if (pEnd - pBegin >= 2 && isWhiteSpace(pBegin[1]))
+ {
+ ++rLength;
+ rModify = true;
+ pBegin += 2;
+ }
+ else
+ {
+ rLength += 3;
+ rModify = true;
+ ++pBegin;
+ }
+ else
+ ++rLength;
+ break;
+
+ case '\\':
+ ++rLength;
+ if (pBegin != pEnd)
+ if (startsWithLineBreak(pBegin, pEnd)
+ && (pEnd - pBegin < 3
+ || !isWhiteSpace(pBegin[2])))
+ {
+ rLength += 3;
+ rModify = true;
+ pBegin += 2;
+ }
+ else
+ ++pBegin;
+ break;
+
+ default:
+ ++rLength;
+ if (!isUSASCII(c))
+ rModify = true;
+ break;
+ }
+ }
+ }
+ return pBegin;
+}
+
+//============================================================================
+// static
+sal_Char const * INetMIME::scanParameters(sal_Char const * pBegin,
+ sal_Char const * pEnd,
+ INetContentTypeParameterList *
+ pParameters)
+{
+ ParameterList aList;
+ sal_Char const * pParameterBegin = pBegin;
+ for (sal_Char const * p = pParameterBegin;; pParameterBegin = p)
+ {
+ pParameterBegin = skipLinearWhiteSpaceComment(p, pEnd);
+ if (pParameterBegin == pEnd || *pParameterBegin != ';')
+ break;
+ p = pParameterBegin + 1;
+
+ sal_Char const * pAttributeBegin = skipLinearWhiteSpaceComment(p,
+ pEnd);
+ sal_Char const * p = pAttributeBegin;
+ bool bDowncaseAttribute = false;
+ while (p != pEnd && isTokenChar(*p) && *p != '*')
+ {
+ bDowncaseAttribute = bDowncaseAttribute || isUpperCase(*p);
+ ++p;
+ }
+ if (p == pAttributeBegin)
+ break;
+ ByteString aAttribute(pAttributeBegin, p - pAttributeBegin);
+ if (bDowncaseAttribute)
+ aAttribute.ToLowerAscii();
+
+ sal_uInt32 nSection = 0;
+ if (p != pEnd && *p == '*')
+ {
+ ++p;
+ if (p != pEnd && isDigit(*p)
+ && !scanUnsigned(p, pEnd, false, nSection))
+ break;
+ }
+
+ bool bPresent;
+ Parameter ** pPos = aList.find(aAttribute, nSection, bPresent);
+ if (bPresent)
+ break;
+
+ bool bExtended = false;
+ if (p != pEnd && *p == '*')
+ {
+ ++p;
+ bExtended = true;
+ }
+
+ p = skipLinearWhiteSpaceComment(p, pEnd);
+
+ if (p == pEnd || *p != '=')
+ break;
+
+ p = skipLinearWhiteSpaceComment(p + 1, pEnd);
+
+ ByteString aCharset;
+ ByteString aLanguage;
+ ByteString aValue;
+ if (bExtended)
+ {
+ if (nSection == 0)
+ {
+ sal_Char const * pCharsetBegin = p;
+ bool bDowncaseCharset = false;
+ while (p != pEnd && isTokenChar(*p) && *p != '\'')
+ {
+ bDowncaseCharset = bDowncaseCharset || isUpperCase(*p);
+ ++p;
+ }
+ if (p == pCharsetBegin)
+ break;
+ if (pParameters)
+ {
+ aCharset = ByteString(pCharsetBegin, p - pCharsetBegin);
+ if (bDowncaseCharset)
+ aCharset.ToLowerAscii();
+ }
+
+ if (p == pEnd || *p != '\'')
+ break;
+ ++p;
+
+ sal_Char const * pLanguageBegin = p;
+ bool bDowncaseLanguage = false;
+ int nLetters = 0;
+ for (; p != pEnd; ++p)
+ if (isAlpha(*p))
+ {
+ if (++nLetters > 8)
+ break;
+ bDowncaseLanguage = bDowncaseLanguage
+ || isUpperCase(*p);
+ }
+ else if (*p == '-')
+ {
+ if (nLetters == 0)
+ break;
+ nLetters = 0;
+ }
+ else
+ break;
+ if (nLetters == 0 || nLetters > 8)
+ break;
+ if (pParameters)
+ {
+ aLanguage = ByteString(pLanguageBegin,
+ p - pLanguageBegin);
+ if (bDowncaseLanguage)
+ aLanguage.ToLowerAscii();
+ }
+
+ if (p == pEnd || *p != '\'')
+ break;
+ ++p;
+ }
+ if (pParameters)
+ while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
+ {
+ if (*p == '%')
+ {
+ if (p + 2 < pEnd)
+ {
+ int nWeight1 = getHexWeight(p[1]);
+ int nWeight2 = getHexWeight(p[2]);
+ if (nWeight1 >= 0 && nWeight2 >= 0)
+ {
+ aValue += sal_Char(nWeight1 << 4 | nWeight2);
+ p += 3;
+ continue;
+ }
+ }
+ }
+ aValue += *p++;
+ }
+ else
+ while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
+ ++p;
+ }
+ else if (p != pEnd && *p == '"')
+ if (pParameters)
+ {
+ bool bInvalid = false;
+ for (++p;;)
+ {
+ if (p == pEnd)
+ {
+ bInvalid = true;
+ break;
+ }
+ else if (*p == '"')
+ {
+ ++p;
+ break;
+ }
+ else if (*p == 0x0D) // CR
+ {
+ if (pEnd - p < 3 || p[1] != 0x0A // LF
+ || !isWhiteSpace(p[2]))
+ {
+ bInvalid = true;
+ break;
+ }
+ p += 2;
+ }
+ else if (*p == '\\' && ++p == pEnd)
+ {
+ bInvalid = true;
+ break;
+ }
+ aValue += *p++;
+ }
+ if (bInvalid)
+ break;
+ }
+ else
+ {
+ sal_Char const * pStringEnd = skipQuotedString(p, pEnd);
+ if (p == pStringEnd)
+ break;
+ p = pStringEnd;
+ }
+ else
+ {
+ sal_Char const * pTokenBegin = p;
+ while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
+ ++p;
+ if (p == pTokenBegin)
+ break;
+ if (pParameters)
+ aValue = ByteString(pTokenBegin, p - pTokenBegin);
+ }
+
+ *pPos = new Parameter(*pPos, aAttribute, aCharset, aLanguage, aValue,
+ nSection, bExtended);
+ }
+ return parseParameters(aList, pParameters) ? pParameterBegin : pBegin;
+}
+
+//============================================================================
+// static
+sal_Unicode const * INetMIME::scanParameters(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ INetContentTypeParameterList *
+ pParameters)
+{
+ ParameterList aList;
+ sal_Unicode const * pParameterBegin = pBegin;
+ for (sal_Unicode const * p = pParameterBegin;; pParameterBegin = p)
+ {
+ pParameterBegin = skipLinearWhiteSpaceComment(p, pEnd);
+ if (pParameterBegin == pEnd || *pParameterBegin != ';')
+ break;
+ p = pParameterBegin + 1;
+
+ sal_Unicode const * pAttributeBegin
+ = skipLinearWhiteSpaceComment(p, pEnd);
+ sal_Unicode const * p = pAttributeBegin;
+ bool bDowncaseAttribute = false;
+ while (p != pEnd && isTokenChar(*p) && *p != '*')
+ {
+ bDowncaseAttribute = bDowncaseAttribute || isUpperCase(*p);
+ ++p;
+ }
+ if (p == pAttributeBegin)
+ break;
+ ByteString aAttribute = ByteString(pAttributeBegin,
+ p - pAttributeBegin,
+ RTL_TEXTENCODING_ASCII_US);
+ if (bDowncaseAttribute)
+ aAttribute.ToLowerAscii();
+
+ sal_uInt32 nSection = 0;
+ if (p != pEnd && *p == '*')
+ {
+ ++p;
+ if (p != pEnd && isDigit(*p)
+ && !scanUnsigned(p, pEnd, false, nSection))
+ break;
+ }
+
+ bool bPresent;
+ Parameter ** pPos = aList.find(aAttribute, nSection, bPresent);
+ if (bPresent)
+ break;
+
+ bool bExtended = false;
+ if (p != pEnd && *p == '*')
+ {
+ ++p;
+ bExtended = true;
+ }
+
+ p = skipLinearWhiteSpaceComment(p, pEnd);
+
+ if (p == pEnd || *p != '=')
+ break;
+
+ p = skipLinearWhiteSpaceComment(p + 1, pEnd);
+
+ ByteString aCharset;
+ ByteString aLanguage;
+ ByteString aValue;
+ if (bExtended)
+ {
+ if (nSection == 0)
+ {
+ sal_Unicode const * pCharsetBegin = p;
+ bool bDowncaseCharset = false;
+ while (p != pEnd && isTokenChar(*p) && *p != '\'')
+ {
+ bDowncaseCharset = bDowncaseCharset || isUpperCase(*p);
+ ++p;
+ }
+ if (p == pCharsetBegin)
+ break;
+ if (pParameters)
+ {
+ aCharset = ByteString(pCharsetBegin, p - pCharsetBegin,
+ RTL_TEXTENCODING_ASCII_US);
+ if (bDowncaseCharset)
+ aCharset.ToLowerAscii();
+ }
+
+ if (p == pEnd || *p != '\'')
+ break;
+ ++p;
+
+ sal_Unicode const * pLanguageBegin = p;
+ bool bDowncaseLanguage = false;
+ int nLetters = 0;
+ for (; p != pEnd; ++p)
+ if (isAlpha(*p))
+ {
+ if (++nLetters > 8)
+ break;
+ bDowncaseLanguage = bDowncaseLanguage
+ || isUpperCase(*p);
+ }
+ else if (*p == '-')
+ {
+ if (nLetters == 0)
+ break;
+ nLetters = 0;
+ }
+ else
+ break;
+ if (nLetters == 0 || nLetters > 8)
+ break;
+ if (pParameters)
+ {
+ aLanguage = ByteString(pLanguageBegin, p - pLanguageBegin,
+ RTL_TEXTENCODING_ASCII_US);
+ if (bDowncaseLanguage)
+ aLanguage.ToLowerAscii();
+ }
+
+ if (p == pEnd || *p != '\'')
+ break;
+ ++p;
+ }
+ if (pParameters)
+ {
+ INetMIMEStringOutputSink
+ aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
+ while (p != pEnd)
+ {
+ sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
+ if (isUSASCII(nChar) && !isTokenChar(nChar))
+ break;
+ if (nChar == '%' && p + 1 < pEnd)
+ {
+ int nWeight1 = getHexWeight(p[0]);
+ int nWeight2 = getHexWeight(p[1]);
+ if (nWeight1 >= 0 && nWeight2 >= 0)
+ {
+ aSink << sal_Char(nWeight1 << 4 | nWeight2);
+ p += 2;
+ continue;
+ }
+ }
+ INetMIME::writeUTF8(aSink, nChar);
+ }
+ aValue = aSink.takeBuffer();
+ }
+ else
+ while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
+ ++p;
+ }
+ else if (p != pEnd && *p == '"')
+ if (pParameters)
+ {
+ INetMIMEStringOutputSink
+ aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
+ bool bInvalid = false;
+ for (++p;;)
+ {
+ if (p == pEnd)
+ {
+ bInvalid = true;
+ break;
+ }
+ sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
+ if (nChar == '"')
+ break;
+ else if (nChar == 0x0D) // CR
+ {
+ if (pEnd - p < 2 || *p++ != 0x0A // LF
+ || !isWhiteSpace(*p))
+ {
+ bInvalid = true;
+ break;
+ }
+ nChar = sal_uChar(*p++);
+ }
+ else if (nChar == '\\')
+ {
+ if (p == pEnd)
+ {
+ bInvalid = true;
+ break;
+ }
+ nChar = INetMIME::getUTF32Character(p, pEnd);
+ }
+ INetMIME::writeUTF8(aSink, nChar);
+ }
+ if (bInvalid)
+ break;
+ aValue = aSink.takeBuffer();
+ }
+ else
+ {
+ sal_Unicode const * pStringEnd = skipQuotedString(p, pEnd);
+ if (p == pStringEnd)
+ break;
+ p = pStringEnd;
+ }
+ else
+ {
+ sal_Unicode const * pTokenBegin = p;
+ while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
+ ++p;
+ if (p == pTokenBegin)
+ break;
+ if (pParameters)
+ aValue = ByteString(pTokenBegin, p - pTokenBegin,
+ RTL_TEXTENCODING_UTF8);
+ }
+
+ *pPos = new Parameter(*pPos, aAttribute, aCharset, aLanguage, aValue,
+ nSection, bExtended);
+ }
+ return parseParameters(aList, pParameters) ? pParameterBegin : pBegin;
+}
+
+//============================================================================
+// static
+const sal_Char * INetMIME::getCharsetName(rtl_TextEncoding eEncoding)
+{
+ if (eEncoding < RTL_TEXTENCODING_STD_COUNT)
+ {
+ // The source for the following table is <ftp://ftp.iana.org/in-notes/
+ // iana/assignments/character-sets> as of Jan, 21 2000 12:46:00,
+ // unless otherwise noted:
+ static const sal_Char * aMap[RTL_TEXTENCODING_STD_COUNT]
+ = { 0, // RTL_TEXTENCODING_DONTKNOW
+ 0, // RTL_TEXTENCODING_MS_1252
+ "macintosh", // RTL_TEXTENCODING_APPLE_ROMAN
+ "IBM437", // RTL_TEXTENCODING_IBM_437
+ "IBM850", // RTL_TEXTENCODING_IBM_850
+ "IBM860", // RTL_TEXTENCODING_IBM_860
+ "IBM861", // RTL_TEXTENCODING_IBM_861
+ "IBM863", // RTL_TEXTENCODING_IBM_863
+ "IBM865", // RTL_TEXTENCODING_IBM_865
+ 0, // CHARSET_SYSTEM
+ 0, // RTL_TEXTENCODING_SYMBOL
+ "US-ASCII", // RTL_TEXTENCODING_ASCII_US
+ "ISO-8859-1", // RTL_TEXTENCODING_ISO_8859_1
+ "ISO-8859-2", // RTL_TEXTENCODING_ISO_8859_2
+ "ISO-8859-3", // RTL_TEXTENCODING_ISO_8859_3
+ "ISO-8859-4", // RTL_TEXTENCODING_ISO_8859_4
+ "ISO-8859-5", // RTL_TEXTENCODING_ISO_8859_5
+ "ISO-8859-6", // RTL_TEXTENCODING_ISO_8859_6
+ "ISO-8859-7", // RTL_TEXTENCODING_ISO_8859_7
+ "ISO-8859-8", // RTL_TEXTENCODING_ISO_8859_8
+ "ISO-8859-9", // RTL_TEXTENCODING_ISO_8859_9
+ "ISO-8859-14", // RTL_TEXTENCODING_ISO_8859_14, RFC 2047
+ "ISO_8859-15", // RTL_TEXTENCODING_ISO_8859_15
+ 0, // RTL_TEXTENCODING_IBM_737
+ "IBM775", // RTL_TEXTENCODING_IBM_775
+ "IBM852", // RTL_TEXTENCODING_IBM_852
+ "IBM855", // RTL_TEXTENCODING_IBM_855
+ "IBM857", // RTL_TEXTENCODING_IBM_857
+ "IBM862", // RTL_TEXTENCODING_IBM_862
+ "IBM864", // RTL_TEXTENCODING_IBM_864
+ "IBM866", // RTL_TEXTENCODING_IBM_866
+ "IBM869", // RTL_TEXTENCODING_IBM_869
+ 0, // RTL_TEXTENCODING_MS_874
+ "windows-1250", // RTL_TEXTENCODING_MS_1250
+ "windows-1251", // RTL_TEXTENCODING_MS_1251
+ "windows-1253", // RTL_TEXTENCODING_MS_1253
+ "windows-1254", // RTL_TEXTENCODING_MS_1254
+ "windows-1255", // RTL_TEXTENCODING_MS_1255
+ "windows-1256", // RTL_TEXTENCODING_MS_1256
+ "windows-1257", // RTL_TEXTENCODING_MS_1257
+ "windows-1258", // RTL_TEXTENCODING_MS_1258
+ 0, // RTL_TEXTENCODING_APPLE_ARABIC
+ 0, // RTL_TEXTENCODING_APPLE_CENTEURO
+ 0, // RTL_TEXTENCODING_APPLE_CROATIAN
+ 0, // RTL_TEXTENCODING_APPLE_CYRILLIC
+ 0, // RTL_TEXTENCODING_APPLE_DEVANAGARI
+ 0, // RTL_TEXTENCODING_APPLE_FARSI
+ 0, // RTL_TEXTENCODING_APPLE_GREEK
+ 0, // RTL_TEXTENCODING_APPLE_GUJARATI
+ 0, // RTL_TEXTENCODING_APPLE_GURMUKHI
+ 0, // RTL_TEXTENCODING_APPLE_HEBREW
+ 0, // RTL_TEXTENCODING_APPLE_ICELAND
+ 0, // RTL_TEXTENCODING_APPLE_ROMANIAN
+ 0, // RTL_TEXTENCODING_APPLE_THAI
+ 0, // RTL_TEXTENCODING_APPLE_TURKISH
+ 0, // RTL_TEXTENCODING_APPLE_UKRAINIAN
+ 0, // RTL_TEXTENCODING_APPLE_CHINSIMP
+ 0, // RTL_TEXTENCODING_APPLE_CHINTRAD
+ 0, // RTL_TEXTENCODING_APPLE_JAPANESE
+ 0, // RTL_TEXTENCODING_APPLE_KOREAN
+ 0, // RTL_TEXTENCODING_MS_932
+ 0, // RTL_TEXTENCODING_MS_936
+ 0, // RTL_TEXTENCODING_MS_949
+ 0, // RTL_TEXTENCODING_MS_950
+ "Shift_JIS", // RTL_TEXTENCODING_SHIFT_JIS
+ "GB2312", // RTL_TEXTENCODING_GB_2312
+ 0, // RTL_TEXTENCODING_GBT_12345
+ 0, // RTL_TEXTENCODING_GBK
+ "Big5", // RTL_TEXTENCODING_BIG5
+ "EUC-JP", // RTL_TEXTENCODING_EUC_JP
+ 0, // RTL_TEXTENCODING_EUC_CN
+ 0, // RTL_TEXTENCODING_EUC_TW
+ "ISO-2022-JP", // RTL_TEXTENCODING_ISO_2022_JP
+ "ISO-2022-CN", // RTL_TEXTENCODING_ISO_2022_CN
+ "KOI8-R", // RTL_TEXTENCODING_KOI8_R
+ "UTF-7", // RTL_TEXTENCODING_UTF7
+ "UTF-8", // RTL_TEXTENCODING_UTF8
+ "ISO-8859-10", // RTL_TEXTENCODING_ISO_8859_10, RFC 2047
+ "ISO-8859-13", // RTL_TEXTENCODING_ISO_8859_13, RFC 2047
+ "EUC-KR", // RTL_TEXTENCODING_EUC_KR
+ "ISO-2022-KR" }; // RTL_TEXTENCODING_ISO_2022_KR
+ DBG_ASSERT(aMap[eEncoding],
+ "INetMIME::getCharsetName(): Unsupported encoding");
+ return aMap[eEncoding];
+ }
+ else
+ switch (eEncoding)
+ {
+ case RTL_TEXTENCODING_UCS4:
+ return "ISO-10646-UCS-4";
+
+ case RTL_TEXTENCODING_UCS2:
+ return "ISO-10646-UCS-2";
+
+ default:
+ DBG_ERROR("INetMIME::getCharsetName(): Unsupported encoding");
+ return 0;
+ }
+}
+
+//============================================================================
+namespace unnamed_tools_inetmime {
+
+struct EncodingEntry
+{
+ sal_Char const * m_aName;
+ rtl_TextEncoding m_eEncoding;
+};
+
+//============================================================================
+// The source for the following table is <ftp://ftp.iana.org/in-notes/iana/
+// assignments/character-sets> as of Jan, 21 2000 12:46:00, unless otherwise
+// noted:
+EncodingEntry const aEncodingMap[]
+ = { { "US-ASCII", RTL_TEXTENCODING_ASCII_US },
+ { "ANSI_X3.4-1968", RTL_TEXTENCODING_ASCII_US },
+ { "ISO-IR-6", RTL_TEXTENCODING_ASCII_US },
+ { "ANSI_X3.4-1986", RTL_TEXTENCODING_ASCII_US },
+ { "ISO_646.IRV:1991", RTL_TEXTENCODING_ASCII_US },
+ { "ASCII", RTL_TEXTENCODING_ASCII_US },
+ { "ISO646-US", RTL_TEXTENCODING_ASCII_US },
+ { "US", RTL_TEXTENCODING_ASCII_US },
+ { "IBM367", RTL_TEXTENCODING_ASCII_US },
+ { "CP367", RTL_TEXTENCODING_ASCII_US },
+ { "CSASCII", RTL_TEXTENCODING_ASCII_US },
+ { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ISO_8859-1:1987", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ISO-IR-100", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ISO_8859-1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "LATIN1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "L1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "IBM819", RTL_TEXTENCODING_ISO_8859_1 },
+ { "CP819", RTL_TEXTENCODING_ISO_8859_1 },
+ { "CSISOLATIN1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ISO_8859-2:1987", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ISO-IR-101", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ISO_8859-2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "LATIN2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "L2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "CSISOLATIN2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "ISO_8859-3:1988", RTL_TEXTENCODING_ISO_8859_3 },
+ { "ISO-IR-109", RTL_TEXTENCODING_ISO_8859_3 },
+ { "ISO_8859-3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "LATIN3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "L3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "CSISOLATIN3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "ISO_8859-4:1988", RTL_TEXTENCODING_ISO_8859_4 },
+ { "ISO-IR-110", RTL_TEXTENCODING_ISO_8859_4 },
+ { "ISO_8859-4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "LATIN4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "L4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "CSISOLATIN4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ISO_8859-5:1988", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ISO-IR-144", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ISO_8859-5", RTL_TEXTENCODING_ISO_8859_5 },
+ { "CYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
+ { "CSISOLATINCYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ISO_8859-6:1987", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ISO-IR-127", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ISO_8859-6", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ECMA-114", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ASMO-708", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ARABIC", RTL_TEXTENCODING_ISO_8859_6 },
+ { "CSISOLATINARABIC", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ISO_8859-7:1987", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ISO-IR-126", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ISO_8859-7", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ELOT_928", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ECMA-118", RTL_TEXTENCODING_ISO_8859_7 },
+ { "GREEK", RTL_TEXTENCODING_ISO_8859_7 },
+ { "GREEK8", RTL_TEXTENCODING_ISO_8859_7 },
+ { "CSISOLATINGREEK", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ISO_8859-8:1988", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ISO-IR-138", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ISO_8859-8", RTL_TEXTENCODING_ISO_8859_8 },
+ { "HEBREW", RTL_TEXTENCODING_ISO_8859_8 },
+ { "CSISOLATINHEBREW", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 },
+ { "ISO_8859-9:1989", RTL_TEXTENCODING_ISO_8859_9 },
+ { "ISO-IR-148", RTL_TEXTENCODING_ISO_8859_9 },
+ { "ISO_8859-9", RTL_TEXTENCODING_ISO_8859_9 },
+ { "LATIN5", RTL_TEXTENCODING_ISO_8859_9 },
+ { "L5", RTL_TEXTENCODING_ISO_8859_9 },
+ { "CSISOLATIN5", RTL_TEXTENCODING_ISO_8859_9 },
+ { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14 }, // RFC 2047
+ { "ISO_8859-15", RTL_TEXTENCODING_ISO_8859_15 },
+ { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15 }, // RFC 2047
+ { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
+ { "MAC", RTL_TEXTENCODING_APPLE_ROMAN },
+ { "CSMACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
+ { "IBM437", RTL_TEXTENCODING_IBM_437 },
+ { "CP437", RTL_TEXTENCODING_IBM_437 },
+ { "437", RTL_TEXTENCODING_IBM_437 },
+ { "CSPC8CODEPAGE437", RTL_TEXTENCODING_IBM_437 },
+ { "IBM850", RTL_TEXTENCODING_IBM_850 },
+ { "CP850", RTL_TEXTENCODING_IBM_850 },
+ { "850", RTL_TEXTENCODING_IBM_850 },
+ { "CSPC850MULTILINGUAL", RTL_TEXTENCODING_IBM_850 },
+ { "IBM860", RTL_TEXTENCODING_IBM_860 },
+ { "CP860", RTL_TEXTENCODING_IBM_860 },
+ { "860", RTL_TEXTENCODING_IBM_860 },
+ { "CSIBM860", RTL_TEXTENCODING_IBM_860 },
+ { "IBM861", RTL_TEXTENCODING_IBM_861 },
+ { "CP861", RTL_TEXTENCODING_IBM_861 },
+ { "861", RTL_TEXTENCODING_IBM_861 },
+ { "CP-IS", RTL_TEXTENCODING_IBM_861 },
+ { "CSIBM861", RTL_TEXTENCODING_IBM_861 },
+ { "IBM863", RTL_TEXTENCODING_IBM_863 },
+ { "CP863", RTL_TEXTENCODING_IBM_863 },
+ { "863", RTL_TEXTENCODING_IBM_863 },
+ { "CSIBM863", RTL_TEXTENCODING_IBM_863 },
+ { "IBM865", RTL_TEXTENCODING_IBM_865 },
+ { "CP865", RTL_TEXTENCODING_IBM_865 },
+ { "865", RTL_TEXTENCODING_IBM_865 },
+ { "CSIBM865", RTL_TEXTENCODING_IBM_865 },
+ { "IBM775", RTL_TEXTENCODING_IBM_775 },
+ { "CP775", RTL_TEXTENCODING_IBM_775 },
+ { "CSPC775BALTIC", RTL_TEXTENCODING_IBM_775 },
+ { "IBM852", RTL_TEXTENCODING_IBM_852 },
+ { "CP852", RTL_TEXTENCODING_IBM_852 },
+ { "852", RTL_TEXTENCODING_IBM_852 },
+ { "CSPCP852", RTL_TEXTENCODING_IBM_852 },
+ { "IBM855", RTL_TEXTENCODING_IBM_855 },
+ { "CP855", RTL_TEXTENCODING_IBM_855 },
+ { "855", RTL_TEXTENCODING_IBM_855 },
+ { "CSIBM855", RTL_TEXTENCODING_IBM_855 },
+ { "IBM857", RTL_TEXTENCODING_IBM_857 },
+ { "CP857", RTL_TEXTENCODING_IBM_857 },
+ { "857", RTL_TEXTENCODING_IBM_857 },
+ { "CSIBM857", RTL_TEXTENCODING_IBM_857 },
+ { "IBM862", RTL_TEXTENCODING_IBM_862 },
+ { "CP862", RTL_TEXTENCODING_IBM_862 },
+ { "862", RTL_TEXTENCODING_IBM_862 },
+ { "CSPC862LATINHEBREW", RTL_TEXTENCODING_IBM_862 },
+ { "IBM864", RTL_TEXTENCODING_IBM_864 },
+ { "CP864", RTL_TEXTENCODING_IBM_864 },
+ { "CSIBM864", RTL_TEXTENCODING_IBM_864 },
+ { "IBM866", RTL_TEXTENCODING_IBM_866 },
+ { "CP866", RTL_TEXTENCODING_IBM_866 },
+ { "866", RTL_TEXTENCODING_IBM_866 },
+ { "CSIBM866", RTL_TEXTENCODING_IBM_866 },
+ { "IBM869", RTL_TEXTENCODING_IBM_869 },
+ { "CP869", RTL_TEXTENCODING_IBM_869 },
+ { "869", RTL_TEXTENCODING_IBM_869 },
+ { "CP-GR", RTL_TEXTENCODING_IBM_869 },
+ { "CSIBM869", RTL_TEXTENCODING_IBM_869 },
+ { "WINDOWS-1250", RTL_TEXTENCODING_MS_1250 },
+ { "WINDOWS-1251", RTL_TEXTENCODING_MS_1251 },
+ { "WINDOWS-1253", RTL_TEXTENCODING_MS_1253 },
+ { "WINDOWS-1254", RTL_TEXTENCODING_MS_1254 },
+ { "WINDOWS-1255", RTL_TEXTENCODING_MS_1255 },
+ { "WINDOWS-1256", RTL_TEXTENCODING_MS_1256 },
+ { "WINDOWS-1257", RTL_TEXTENCODING_MS_1257 },
+ { "WINDOWS-1258", RTL_TEXTENCODING_MS_1258 },
+ { "SHIFT_JIS", RTL_TEXTENCODING_SHIFT_JIS },
+ { "MS_KANJI", RTL_TEXTENCODING_SHIFT_JIS },
+ { "CSSHIFTJIS", RTL_TEXTENCODING_SHIFT_JIS },
+ { "GB2312", RTL_TEXTENCODING_GB_2312 },
+ { "CSGB2312", RTL_TEXTENCODING_GB_2312 },
+ { "BIG5", RTL_TEXTENCODING_BIG5 },
+ { "CSBIG5", RTL_TEXTENCODING_BIG5 },
+ { "EUC-JP", RTL_TEXTENCODING_EUC_JP },
+ { "EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE",
+ RTL_TEXTENCODING_EUC_JP },
+ { "CSEUCPKDFMTJAPANESE", RTL_TEXTENCODING_EUC_JP },
+ { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP },
+ { "CSISO2022JP", RTL_TEXTENCODING_ISO_2022_JP },
+ { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN },
+ { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
+ { "CSKOI8R", RTL_TEXTENCODING_KOI8_R },
+ { "UTF-7", RTL_TEXTENCODING_UTF7 },
+ { "UTF-8", RTL_TEXTENCODING_UTF8 },
+ { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10 }, // RFC 2047
+ { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13 }, // RFC 2047
+ { "EUC-KR", RTL_TEXTENCODING_EUC_KR },
+ { "CSEUCKR", RTL_TEXTENCODING_EUC_KR },
+ { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR },
+ { "CSISO2022KR", RTL_TEXTENCODING_ISO_2022_KR },
+ { "ISO-10646-UCS-4", RTL_TEXTENCODING_UCS4 },
+ { "CSUCS4", RTL_TEXTENCODING_UCS4 },
+ { "ISO-10646-UCS-2", RTL_TEXTENCODING_UCS2 },
+ { "CSUNICODE", RTL_TEXTENCODING_UCS2 } };
+
+//============================================================================
+template< typename T >
+inline rtl_TextEncoding getCharsetEncoding_Impl(T const * pBegin,
+ T const * pEnd)
+{
+ for (sal_Size i = 0; i < sizeof aEncodingMap / sizeof (EncodingEntry);
+ ++i)
+ if (INetMIME::equalIgnoreCase(pBegin, pEnd, aEncodingMap[i].m_aName))
+ return aEncodingMap[i].m_eEncoding;
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+}
+
+//============================================================================
+// static
+rtl_TextEncoding INetMIME::getCharsetEncoding(sal_Char const * pBegin,
+ sal_Char const * pEnd)
+{
+ return getCharsetEncoding_Impl(pBegin, pEnd);
+}
+
+//============================================================================
+// static
+rtl_TextEncoding INetMIME::getCharsetEncoding(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd)
+{
+ return getCharsetEncoding_Impl(pBegin, pEnd);
+}
+
+//============================================================================
+// static
+INetMIMECharsetList_Impl *
+INetMIME::createPreferredCharsetList(rtl_TextEncoding eEncoding)
+{
+ static const sal_uInt32 aUSASCIIRanges[] = { 0, 0x7F, sal_uInt32(-1) };
+
+ static const sal_uInt32 aISO88591Ranges[] = { 0, 0xFF, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88592Ranges[]
+ = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
+ 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
+ 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xCE, 0xD3, 0xD4, 0xD6, 0xD7,
+ 0xDA, 0xDA, 0xDC, 0xDD, 0xDF, 0xDF, 0xE1, 0xE2, 0xE4, 0xE4,
+ 0xE7, 0xE7, 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF3, 0xF4,
+ 0xF6, 0xF7, 0xFA, 0xFA, 0xFC, 0xFD, 0x102, 0x107, 0x10C, 0x111,
+ 0x118, 0x11B, 0x139, 0x13A, 0x13D, 0x13E, 0x141, 0x144,
+ 0x147, 0x148, 0x150, 0x151, 0x154, 0x155, 0x158, 0x15B,
+ 0x15E, 0x165, 0x16E, 0x171, 0x179, 0x17E, 0x2C7, 0x2C7,
+ 0x2D8, 0x2D9, 0x2DB, 0x2DB, 0x2DD, 0x2DD, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88593Ranges[]
+ = { 0, 0xA0, 0xA3, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
+ 0xB2, 0xB5, 0xB7, 0xB8, 0xBD, 0xBD, 0xC0, 0xC2, 0xC4, 0xC4,
+ 0xC7, 0xCF, 0xD1, 0xD4, 0xD6, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
+ 0xE4, 0xE4, 0xE7, 0xEF, 0xF1, 0xF4, 0xF6, 0xF7, 0xF9, 0xFC,
+ 0x108, 0x10B, 0x11C, 0x121, 0x124, 0x127, 0x130, 0x131,
+ 0x134, 0x135, 0x15C, 0x15F, 0x16C, 0x16D, 0x17B, 0x17C,
+ 0x2D8, 0x2D9, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88594Ranges[]
+ = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xAF, 0xB0,
+ 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB,
+ 0xCD, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xDF, 0xDF, 0xE1, 0xE6,
+ 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF4, 0xF8, 0xFA, 0xFC,
+ 0x100, 0x101, 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113,
+ 0x116, 0x119, 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F,
+ 0x136, 0x138, 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D,
+ 0x156, 0x157, 0x160, 0x161, 0x166, 0x16B, 0x172, 0x173,
+ 0x17D, 0x17E, 0x2C7, 0x2C7, 0x2D9, 0x2D9, 0x2DB, 0x2DB,
+ sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88595Ranges[]
+ = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0x401, 0x40C, 0x40E, 0x44F,
+ 0x451, 0x45C, 0x45E, 0x45F, 0x2116, 0x2116, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88596Ranges[]
+ = { 0, 0xA0, 0xA4, 0xA4, 0xAD, 0xAD, 0x60C, 0x60C, 0x61B, 0x61B,
+ 0x61F, 0x61F, 0x621, 0x63A, 0x640, 0x652, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88597Ranges[]
+ = { 0, 0xA0, 0xA3, 0xA3, 0xA6, 0xA9, 0xAB, 0xAD, 0xB0, 0xB3,
+ 0xB7, 0xB7, 0xBB, 0xBB, 0xBD, 0xBD, 0x384, 0x386, 0x388, 0x38A,
+ 0x38C, 0x38C, 0x38E, 0x3A1, 0x3A3, 0x3CE, 0x2015, 0x2015,
+ 0x2018, 0x2019, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO88598Ranges[]
+ = { 0, 0xA0, 0xA2, 0xA9, 0xAB, 0xB9, 0xBB, 0xBE, 0xD7, 0xD7,
+ 0xF7, 0xF7, 0x5D0, 0x5EA, 0x200E, 0x200F, 0x2017, 0x2017,
+ sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT> version
+ // 1.1 of 2000-Jan-03
+
+ static const sal_uInt32 aISO88599Ranges[]
+ = { 0, 0xCF, 0xD1, 0xDC, 0xDF, 0xEF, 0xF1, 0xFC, 0xFF, 0xFF,
+ 0x11E, 0x11F, 0x130, 0x131, 0x15E, 0x15F, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO885910Ranges[]
+ = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0xB0, 0xB0, 0xB7, 0xB7,
+ 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xD0, 0xD3, 0xD6,
+ 0xD8, 0xD8, 0xDA, 0xDF, 0xE1, 0xE6, 0xE9, 0xE9, 0xEB, 0xEB,
+ 0xED, 0xF0, 0xF3, 0xF6, 0xF8, 0xF8, 0xFA, 0xFE, 0x100, 0x101,
+ 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113, 0x116, 0x119,
+ 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F, 0x136, 0x138,
+ 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D, 0x160, 0x161,
+ 0x166, 0x16B, 0x172, 0x173, 0x17D, 0x17E, 0x2015, 0x2015,
+ sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT> version
+ // 1.1 of 1999 October 11
+
+ static const sal_uInt32 aISO885913Ranges[]
+ = { 0, 0xA0, 0xA2, 0xA4, 0xA6, 0xA7, 0xA9, 0xA9, 0xAB, 0xAE,
+ 0xB0, 0xB3, 0xB5, 0xB7, 0xB9, 0xB9, 0xBB, 0xBE, 0xC4, 0xC6,
+ 0xC9, 0xC9, 0xD3, 0xD3, 0xD5, 0xD8, 0xDC, 0xDC, 0xDF, 0xDF,
+ 0xE4, 0xE6, 0xE9, 0xE9, 0xF3, 0xF3, 0xF5, 0xF8, 0xFC, 0xFC,
+ 0x100, 0x101, 0x104, 0x107, 0x10C, 0x10D, 0x112, 0x113,
+ 0x116, 0x119, 0x122, 0x123, 0x12A, 0x12B, 0x12E, 0x12F,
+ 0x136, 0x137, 0x13B, 0x13C, 0x141, 0x146, 0x14C, 0x14D,
+ 0x156, 0x157, 0x15A, 0x15B, 0x160, 0x161, 0x16A, 0x16B,
+ 0x172, 0x173, 0x179, 0x17E, 0x2019, 0x2019, 0x201C, 0x201E,
+ sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO885914Ranges[]
+ = { 0, 0xA0, 0xA3, 0xA3, 0xA7, 0xA7, 0xA9, 0xA9, 0xAD, 0xAE,
+ 0xB6, 0xB6, 0xC0, 0xCF, 0xD1, 0xD6, 0xD8, 0xDD, 0xDF, 0xEF,
+ 0xF1, 0xF6, 0xF8, 0xFD, 0xFF, 0xFF, 0x10A, 0x10B, 0x120, 0x121,
+ 0x174, 0x178, 0x1E02, 0x1E03, 0x1E0A, 0x1E0B, 0x1E1E, 0x1E1F,
+ 0x1E40, 0x1E41, 0x1E56, 0x1E57, 0x1E60, 0x1E61, 0x1E6A, 0x1E6B,
+ 0x1E80, 0x1E85, 0x1EF2, 0x1EF3, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aISO885915Ranges[]
+ = { 0, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xB3, 0xB5, 0xB7,
+ 0xB9, 0xBB, 0xBF, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
+ 0x17D, 0x17E, 0x20AC, 0x20AC, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT> version
+ // 1.0 of 1999 July 27
+
+ static const sal_uInt32 aKOI8RRanges[]
+ = { 0, 0x7F, 0xA0, 0xA0, 0xA9, 0xA9, 0xB0, 0xB0, 0xB2, 0xB2,
+ 0xB7, 0xB7, 0xF7, 0xF7, 0x401, 0x401, 0x410, 0x44F, 0x451, 0x451,
+ 0x2219, 0x221A, 0x2248, 0x2248, 0x2264, 0x2265, 0x2320, 0x2321,
+ 0x2500, 0x2500, 0x2502, 0x2502, 0x250C, 0x250C, 0x2510, 0x2510,
+ 0x2514, 0x2514, 0x2518, 0x2518, 0x251C, 0x251C, 0x2524, 0x2524,
+ 0x252C, 0x252C, 0x2534, 0x2534, 0x253C, 0x253C, 0x2550, 0x256C,
+ 0x2580, 0x2580, 0x2584, 0x2584, 0x2588, 0x2588, 0x258C, 0x258C,
+ 0x2590, 0x2593, 0x25A0, 0x25A0, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT>
+ // version 1.0 of 18 August 1999
+
+ static const sal_uInt32 aWindows1252Ranges[]
+ = { 0, 0x7F, 0xA0, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
+ 0x17D, 0x17E, 0x192, 0x192, 0x2C6, 0x2C6, 0x2DC, 0x2DC,
+ 0x2013, 0x2014, 0x2018, 0x201A, 0x201C, 0x201E, 0x2020, 0x2022,
+ 0x2026, 0x2026, 0x2030, 0x2030, 0x2039, 0x203A, 0x20AC, 0x20AC,
+ 0x2122, 0x2122, sal_uInt32(-1) };
+ // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/
+ // CP1252.TXT> version 2.01 of 04/15/98
+
+ INetMIMECharsetList_Impl * pList = new INetMIMECharsetList_Impl;
+ switch (eEncoding)
+ {
+ case RTL_TEXTENCODING_MS_1252:
+#if defined WNT
+ pList->prepend(Charset(RTL_TEXTENCODING_MS_1252,
+ aWindows1252Ranges));
+#endif // WNT
+ case RTL_TEXTENCODING_ISO_8859_1:
+ case RTL_TEXTENCODING_UTF7:
+ case RTL_TEXTENCODING_UTF8:
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_2:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
+ aISO88592Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_3:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_3,
+ aISO88593Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_4:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
+ aISO88594Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_5:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
+ aISO88595Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_6:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
+ aISO88596Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_7:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
+ aISO88597Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_8:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
+ aISO88598Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_9:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
+ aISO88599Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_10:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_10,
+ aISO885910Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_13:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_13,
+ aISO885913Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_14:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_14,
+ aISO885914Ranges));
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_15:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_15,
+ aISO885915Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1250:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
+ aISO88592Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1251:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
+ aISO88595Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1253:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
+ aISO88597Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1254:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
+ aISO88599Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1255:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
+ aISO88598Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1256:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
+ aISO88596Ranges));
+ break;
+
+ case RTL_TEXTENCODING_MS_1257:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
+ aISO88594Ranges));
+ break;
+
+ case RTL_TEXTENCODING_KOI8_R:
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
+ aISO88595Ranges));
+ pList->prepend(Charset(RTL_TEXTENCODING_KOI8_R, aKOI8RRanges));
+ break;
+
+ default: //@@@ more cases are missing!
+ DBG_ERROR("INetMIME::createPreferredCharsetList():"
+ " Unsupported encoding");
+ break;
+ }
+ pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_1, aISO88591Ranges));
+ pList->prepend(Charset(RTL_TEXTENCODING_ASCII_US, aUSASCIIRanges));
+ return pList;
+}
+
+//============================================================================
+// static
+sal_Unicode * INetMIME::convertToUnicode(const sal_Char * pBegin,
+ const sal_Char * pEnd,
+ rtl_TextEncoding eEncoding,
+ sal_Size & rSize)
+{
+ if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
+ return 0;
+ rtl_TextToUnicodeConverter hConverter
+ = rtl_createTextToUnicodeConverter(eEncoding);
+ rtl_TextToUnicodeContext hContext
+ = rtl_createTextToUnicodeContext(hConverter);
+ sal_Unicode * pBuffer;
+ sal_uInt32 nInfo;
+ for (sal_Size nBufferSize = pEnd - pBegin;;
+ nBufferSize += nBufferSize / 3 + 1)
+ {
+ pBuffer = new sal_Unicode[nBufferSize];
+ sal_Size nSrcCvtBytes;
+ rSize = rtl_convertTextToUnicode(
+ hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
+ nBufferSize,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
+ &nInfo, &nSrcCvtBytes);
+ if (nInfo != RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
+ break;
+ delete[] pBuffer;
+ rtl_resetTextToUnicodeContext(hConverter, hContext);
+ }
+ rtl_destroyTextToUnicodeContext(hConverter, hContext);
+ rtl_destroyTextToUnicodeConverter(hConverter);
+ if (nInfo != 0)
+ {
+ delete[] pBuffer;
+ pBuffer = 0;
+ }
+ return pBuffer;
+}
+
+//============================================================================
+// static
+sal_Char * INetMIME::convertFromUnicode(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd,
+ rtl_TextEncoding eEncoding,
+ sal_Size & rSize)
+{
+ if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
+ return 0;
+ rtl_UnicodeToTextConverter hConverter
+ = rtl_createUnicodeToTextConverter(eEncoding);
+ rtl_UnicodeToTextContext hContext
+ = rtl_createUnicodeToTextContext(hConverter);
+ sal_Char * pBuffer;
+ sal_uInt32 nInfo;
+ for (sal_Size nBufferSize = pEnd - pBegin;;
+ nBufferSize += nBufferSize / 3 + 1)
+ {
+ pBuffer = new sal_Char[nBufferSize];
+ sal_Size nSrcCvtBytes;
+ rSize = rtl_convertUnicodeToText(
+ hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
+ nBufferSize,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
+ | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR,
+ &nInfo, &nSrcCvtBytes);
+ if (nInfo != RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL)
+ break;
+ delete[] pBuffer;
+ rtl_resetUnicodeToTextContext(hConverter, hContext);
+ }
+ rtl_destroyUnicodeToTextContext(hConverter, hContext);
+ rtl_destroyUnicodeToTextConverter(hConverter);
+ if (nInfo != 0)
+ {
+ delete[] pBuffer;
+ pBuffer = 0;
+ }
+ return pBuffer;
+}
+
+//============================================================================
+// static
+void INetMIME::writeUTF8(INetMIMEOutputSink & rSink, sal_uInt32 nChar)
+{
+ // See RFC 2279 for a discussion of UTF-8.
+ DBG_ASSERT(nChar < 0x80000000, "INetMIME::writeUTF8(): Bad char");
+
+ if (nChar < 0x80)
+ rSink << sal_Char(nChar);
+ else if (nChar < 0x800)
+ rSink << sal_Char(nChar >> 6 | 0xC0)
+ << sal_Char(nChar & 0x3F | 0x80);
+ else if (nChar < 0x10000)
+ rSink << sal_Char(nChar >> 12 | 0xE0)
+ << sal_Char(nChar >> 6 & 0x3F | 0x80)
+ << sal_Char(nChar & 0x3F | 0x80);
+ else if (nChar < 0x200000)
+ rSink << sal_Char(nChar >> 18 | 0xF0)
+ << sal_Char(nChar >> 12 & 0x3F | 0x80)
+ << sal_Char(nChar >> 6 & 0x3F | 0x80)
+ << sal_Char(nChar & 0x3F | 0x80);
+ else if (nChar < 0x4000000)
+ rSink << sal_Char(nChar >> 24 | 0xF8)
+ << sal_Char(nChar >> 18 & 0x3F | 0x80)
+ << sal_Char(nChar >> 12 & 0x3F | 0x80)
+ << sal_Char(nChar >> 6 & 0x3F | 0x80)
+ << sal_Char(nChar & 0x3F | 0x80);
+ else
+ rSink << sal_Char(nChar >> 30 | 0xFC)
+ << sal_Char(nChar >> 24 & 0x3F | 0x80)
+ << sal_Char(nChar >> 18 & 0x3F | 0x80)
+ << sal_Char(nChar >> 12 & 0x3F | 0x80)
+ << sal_Char(nChar >> 6 & 0x3F | 0x80)
+ << sal_Char(nChar & 0x3F | 0x80);
+}
+
+//============================================================================
+// static
+void INetMIME::writeUnsigned(INetMIMEOutputSink & rSink, sal_uInt32 nValue,
+ int nMinDigits)
+{
+ sal_Char aBuffer[10];
+ // max unsigned 32 bit value (4294967295) has 10 places
+ sal_Char * p = aBuffer;
+ for (; nValue > 0; nValue /= 10)
+ *p++ = sal_Char(getDigit(nValue % 10));
+ nMinDigits -= p - aBuffer;
+ while (nMinDigits-- > 0)
+ rSink << '0';
+ while (p != aBuffer)
+ rSink << *--p;
+}
+
+//============================================================================
+// static
+void INetMIME::writeDateTime(INetMIMEOutputSink & rSink,
+ const DateTime & rUTC)
+{
+ static const sal_Char aDay[7][3]
+ = { { 'M', 'o', 'n' },
+ { 'T', 'u', 'e' },
+ { 'W', 'e', 'd' },
+ { 'T', 'h', 'u' },
+ { 'F', 'r', 'i' },
+ { 'S', 'a', 't' },
+ { 'S', 'u', 'n' } };
+ const sal_Char * pTheDay = aDay[rUTC.GetDayOfWeek()];
+ rSink.write(pTheDay, pTheDay + 3);
+ rSink << ", ";
+ writeUnsigned(rSink, rUTC.GetDay());
+ rSink << ' ';
+ static const sal_Char aMonth[12][3]
+ = { { 'J', 'a', 'n' },
+ { 'F', 'e', 'b' },
+ { 'M', 'a', 'r' },
+ { 'A', 'p', 'r' },
+ { 'M', 'a', 'y' },
+ { 'J', 'u', 'n' },
+ { 'J', 'u', 'l' },
+ { 'A', 'u', 'g' },
+ { 'S', 'e', 'p' },
+ { 'O', 'c', 't' },
+ { 'N', 'o', 'v' },
+ { 'D', 'e', 'c' } };
+ const sal_Char * pTheMonth = aMonth[rUTC.GetMonth() - 1];
+ rSink.write(pTheMonth, pTheMonth + 3);
+ rSink << ' ';
+ writeUnsigned(rSink, rUTC.GetYear());
+ rSink << ' ';
+ writeUnsigned(rSink, rUTC.GetHour(), 2);
+ rSink << ':';
+ writeUnsigned(rSink, rUTC.GetMin(), 2);
+ rSink << ':';
+ writeUnsigned(rSink, rUTC.GetSec(), 2);
+ rSink << " +0000";
+}
+
+//============================================================================
+// static
+void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink & rSink,
+ HeaderFieldType eType,
+ const ByteString & rBody,
+ rtl_TextEncoding ePreferredEncoding,
+ bool bInitialSpace)
+{
+ writeHeaderFieldBody(rSink, eType,
+ UniString(rBody, RTL_TEXTENCODING_UTF8),
+ ePreferredEncoding);
+}
+
+//============================================================================
+// static
+void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink & rSink,
+ HeaderFieldType eType,
+ const UniString & rBody,
+ rtl_TextEncoding ePreferredEncoding,
+ bool bInitialSpace)
+{
+ if (eType == HEADER_FIELD_TEXT)
+ {
+ INetMIMEEncodedWordOutputSink
+ aOutput(rSink, INetMIMEEncodedWordOutputSink::CONTEXT_TEXT,
+ bInitialSpace ?
+ INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
+ INetMIMEEncodedWordOutputSink::SPACE_NO,
+ ePreferredEncoding);
+ aOutput.write(rBody.GetBuffer(), rBody.GetBuffer() + rBody.Len());
+ aOutput.flush();
+ }
+ else
+ {
+ enum Brackets { BRACKETS_OUTSIDE, BRACKETS_OPENING, BRACKETS_INSIDE };
+ Brackets eBrackets = BRACKETS_OUTSIDE;
+
+ const sal_Unicode * pBodyPtr = rBody.GetBuffer();
+ const sal_Unicode * pBodyEnd = pBodyPtr + rBody.Len();
+ while (pBodyPtr != pBodyEnd)
+ switch (*pBodyPtr)
+ {
+ case '\t':
+ case ' ':
+ // A WSP adds to accumulated space:
+ bInitialSpace = true;
+ ++pBodyPtr;
+ break;
+
+ case '(':
+ {
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_INSIDE;
+ }
+
+ // Write the comment, introducing encoded-words where
+ // necessary:
+ int nLevel = 0;
+ INetMIMEEncodedWordOutputSink
+ aOutput(
+ rSink,
+ INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT,
+ INetMIMEEncodedWordOutputSink::SPACE_NO,
+ ePreferredEncoding);
+ while (pBodyPtr != pBodyEnd)
+ switch (*pBodyPtr)
+ {
+ case '(':
+ aOutput.flush();
+ if (rSink.getColumn()
+ + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '(';
+ bInitialSpace = false;
+ ++nLevel;
+ ++pBodyPtr;
+ break;
+
+ case ')':
+ aOutput.flush();
+ if (rSink.getColumn()
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ rSink << ')';
+ ++pBodyPtr;
+ if (--nLevel == 0)
+ goto comment_done;
+ break;
+
+ case '\\':
+ if (++pBodyPtr == pBodyEnd)
+ break;
+ default:
+ aOutput << *pBodyPtr++;
+ break;
+ }
+ comment_done:
+ break;
+ }
+
+ case '<':
+ // Write an already pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ }
+
+ // Remember this '<' as pending, and open a bracketed
+ // block:
+ eBrackets = BRACKETS_OPENING;
+ ++pBodyPtr;
+ break;
+
+ case '>':
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ }
+
+ // Write this '>', and close any bracketed block:
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '>';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_OUTSIDE;
+ ++pBodyPtr;
+ break;
+
+ case ',':
+ case ':':
+ case ';':
+ case '\\':
+ case ']':
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_INSIDE;
+ }
+
+ // Write this specials:
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << sal_Char(*pBodyPtr++);
+ bInitialSpace = false;
+ break;
+
+ case '\x0D': // CR
+ // A <CRLF WSP> adds to accumulated space, a <CR> not
+ // followed by <LF WSP> starts 'junk':
+ if (startsWithLineFolding(pBodyPtr, pBodyEnd))
+ {
+ bInitialSpace = true;
+ pBodyPtr += 3;
+ break;
+ }
+ default:
+ {
+ // The next token is either one of <"." / "@" / atom /
+ // quoted-string / domain-literal>, or it's 'junk'; if it
+ // is not 'junk', it is either a 'phrase' (i.e., it may
+ // contain encoded-words) or a 'non-phrase' (i.e., it may
+ // not contain encoded-words):
+ enum Entity { ENTITY_JUNK, ENTITY_NON_PHRASE,
+ ENTITY_PHRASE };
+ Entity eEntity;
+ switch (*pBodyPtr)
+ {
+ case '.':
+ case '@':
+ case '[':
+ // A token of <"." / "@" / domain-literal> always
+ // starts a 'non-phrase':
+ eEntity = ENTITY_NON_PHRASE;
+ break;
+
+ default:
+ if (isUSASCII(*pBodyPtr)
+ && !isAtomChar(*pBodyPtr))
+ {
+ eEntity = ENTITY_JUNK;
+ break;
+ }
+ case '"':
+ // A token of <atom / quoted-string> can either be
+ // a 'phrase' or a 'non-phrase':
+ switch (eType)
+ {
+ case HEADER_FIELD_STRUCTURED:
+ eEntity = ENTITY_NON_PHRASE;
+ break;
+
+ case HEADER_FIELD_PHRASE:
+ eEntity = ENTITY_PHRASE;
+ break;
+
+ case HEADER_FIELD_MESSAGE_ID:
+ // A 'phrase' if and only if outside any
+ // bracketed block:
+ eEntity
+ = eBrackets == BRACKETS_OUTSIDE ?
+ ENTITY_PHRASE :
+ ENTITY_NON_PHRASE;
+ break;
+
+ case HEADER_FIELD_ADDRESS:
+ {
+ // A 'non-phrase' if and only if, after
+ // skipping this token and any following
+ // <linear-white-space> and <comment>s,
+ // there is no token left, or the next
+ // token is any of <"." / "@" / ">" / ","
+ // / ";">, or the next token is <":"> and
+ // is within a bracketed block:
+ const sal_Unicode * pLookAhead = pBodyPtr;
+ if (*pLookAhead == '"')
+ {
+ pLookAhead
+ = skipQuotedString(pLookAhead,
+ pBodyEnd);
+ if (pLookAhead == pBodyPtr)
+ pLookAhead = pBodyEnd;
+ }
+ else
+ while (pLookAhead != pBodyEnd
+ && (isAtomChar(*pLookAhead)
+ || !isUSASCII(
+ *pLookAhead)))
+ ++pLookAhead;
+ while (pLookAhead != pBodyEnd)
+ switch (*pLookAhead)
+ {
+ case '\t':
+ case ' ':
+ ++pLookAhead;
+ break;
+
+ case '(':
+ {
+ const sal_Unicode * pPast
+ = skipComment(pLookAhead,
+ pBodyEnd);
+ pLookAhead
+ = pPast == pLookAhead ?
+ pBodyEnd : pPast;
+ break;
+ }
+
+ case ',':
+ case '.':
+ case ';':
+ case '>':
+ case '@':
+ eEntity = ENTITY_NON_PHRASE;
+ goto entity_determined;
+
+ case ':':
+ eEntity
+ = eBrackets
+ == BRACKETS_OUTSIDE ?
+ ENTITY_PHRASE :
+ ENTITY_NON_PHRASE;
+ goto entity_determined;
+
+ case '\x0D': // CR
+ if (startsWithLineFolding(
+ pLookAhead, pBodyEnd))
+ {
+ pLookAhead += 3;
+ break;
+ }
+ default:
+ eEntity = ENTITY_PHRASE;
+ goto entity_determined;
+ }
+ eEntity = ENTITY_NON_PHRASE;
+ entity_determined:
+ break;
+ }
+ }
+
+ // In a 'non-phrase', a non-US-ASCII character
+ // cannot be part of an <atom>, but instead the
+ // whole entity is 'junk' rather than 'non-
+ // phrase':
+ if (eEntity == ENTITY_NON_PHRASE
+ && !isUSASCII(*pBodyPtr))
+ eEntity = ENTITY_JUNK;
+ break;
+ }
+
+ switch (eEntity)
+ {
+ case ENTITY_JUNK:
+ {
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn()
+ + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_INSIDE;
+ }
+
+ // Calculate the length of in- and output:
+ const sal_Unicode * pStart = pBodyPtr;
+ sal_uInt32 nLength = 0;
+ bool bModify = false;
+ bool bEnd = false;
+ while (pBodyPtr != pBodyEnd && !bEnd)
+ switch (*pBodyPtr)
+ {
+ case '\x0D': // CR
+ if (startsWithLineFolding(pBodyPtr,
+ pBodyEnd))
+ bEnd = true;
+ else if (startsWithLineBreak(
+ pBodyPtr, pBodyEnd))
+ {
+ nLength += 3;
+ bModify = true;
+ pBodyPtr += 2;
+ }
+ else
+ {
+ ++nLength;
+ ++pBodyPtr;
+ }
+ break;
+
+ case '\t':
+ case ' ':
+ bEnd = true;
+ break;
+
+ default:
+ if (isVisible(*pBodyPtr))
+ bEnd = true;
+ else if (isUSASCII(*pBodyPtr))
+ {
+ ++nLength;
+ ++pBodyPtr;
+ }
+ else
+ {
+ nLength += getUTF8OctetCount(
+ *pBodyPtr++);
+ bModify = true;
+ }
+ break;
+ }
+
+ // Write the output:
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ + nLength
+ > rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ bInitialSpace = false;
+ if (bModify)
+ while (pStart != pBodyPtr)
+ if (startsWithLineBreak(pStart, pBodyPtr))
+ {
+ rSink << "\x0D\\\x0A"; // CR, '\', LF
+ pStart += 2;
+ }
+ else
+ writeUTF8(rSink, *pStart++);
+ else
+ rSink.write(pStart, pBodyPtr);
+ break;
+ }
+
+ case ENTITY_NON_PHRASE:
+ {
+ // Calculate the length of in- and output:
+ const sal_Unicode * pStart = pBodyPtr;
+ sal_uInt32 nLength = 0;
+ bool bBracketedBlock = false;
+ bool bSymbol = *pStart != '.' && *pStart != '@';
+ bool bModify = false;
+ bool bEnd = false;
+ while (pBodyPtr != pBodyEnd && !bEnd)
+ switch (*pBodyPtr)
+ {
+ case '\t':
+ case ' ':
+ case '\x0D': // CR
+ {
+ const sal_Unicode * pLookAhead
+ = skipLinearWhiteSpace(pBodyPtr,
+ pBodyEnd);
+ if (pLookAhead < pBodyEnd
+ && (bSymbol ?
+ isAtomChar(*pLookAhead)
+ || *pLookAhead == '"'
+ || *pLookAhead == '[' :
+ *pLookAhead == '.'
+ || *pLookAhead == '@'
+ || *pLookAhead == '>'
+ && eType
+ >= HEADER_FIELD_MESSAGE_ID
+ && eBrackets
+ == BRACKETS_OPENING))
+ {
+ bModify = true;
+ pBodyPtr = pLookAhead;
+ }
+ else
+ bEnd = true;
+ break;
+ }
+
+ case '"':
+ if (bSymbol)
+ {
+ pBodyPtr
+ = scanQuotedBlock(pBodyPtr,
+ pBodyEnd,
+ '"', '"',
+ nLength,
+ bModify);
+ bSymbol = false;
+ }
+ else
+ bEnd = true;
+ break;
+
+ case '[':
+ if (bSymbol)
+ {
+ pBodyPtr
+ = scanQuotedBlock(pBodyPtr,
+ pBodyEnd,
+ '[', ']',
+ nLength,
+ bModify);
+ bSymbol = false;
+ }
+ else
+ bEnd = true;
+ break;
+
+ case '.':
+ case '@':
+ if (bSymbol)
+ bEnd = true;
+ else
+ {
+ ++nLength;
+ bSymbol = true;
+ ++pBodyPtr;
+ }
+ break;
+
+ case '>':
+ if (eBrackets == BRACKETS_OPENING
+ && eType
+ >= HEADER_FIELD_MESSAGE_ID)
+ {
+ ++nLength;
+ bBracketedBlock = true;
+ ++pBodyPtr;
+ }
+ bEnd = true;
+ break;
+
+ default:
+ if (isAtomChar(*pBodyPtr) && bSymbol)
+ {
+ while (pBodyPtr != pBodyEnd
+ && isAtomChar(*pBodyPtr))
+ {
+ ++nLength;
+ ++pBodyPtr;
+ }
+ bSymbol = false;
+ }
+ else
+ {
+ if (!isUSASCII(*pBodyPtr))
+ bModify = true;
+ bEnd = true;
+ }
+ break;
+ }
+
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING
+ && !bBracketedBlock)
+ {
+ if (rSink.getColumn()
+ + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_INSIDE;
+ }
+
+ // Write the output:
+ if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
+ + nLength
+ > rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ bInitialSpace = false;
+ if (bBracketedBlock)
+ {
+ rSink << '<';
+ eBrackets = BRACKETS_OUTSIDE;
+ }
+ if (bModify)
+ {
+ enum Mode { MODE_PLAIN, MODE_QUOTED_STRING,
+ MODE_DOMAIN_LITERAL };
+ Mode eMode = MODE_PLAIN;
+ while (pStart != pBodyPtr)
+ switch (*pStart)
+ {
+ case '\x0D': // CR
+ if (startsWithLineFolding(
+ pStart, pBodyPtr))
+ {
+ if (eMode != MODE_PLAIN)
+ rSink << sal_Char(
+ pStart[2]);
+ pStart += 3;
+ }
+ else if (startsWithLineBreak(
+ pStart, pBodyPtr))
+ {
+ rSink << "\x0D\\\x0A";
+ // CR, '\', LF
+ pStart += 2;
+ }
+ else
+ {
+ rSink << '\x0D'; // CR
+ ++pStart;
+ }
+ break;
+
+ case '\t':
+ case ' ':
+ if (eMode != MODE_PLAIN)
+ rSink << sal_Char(*pStart);
+ ++pStart;
+ break;
+
+ case '"':
+ if (eMode == MODE_PLAIN)
+ eMode = MODE_QUOTED_STRING;
+ else if (eMode
+ == MODE_QUOTED_STRING)
+ eMode = MODE_PLAIN;
+ rSink << '"';
+ ++pStart;
+ break;
+
+ case '[':
+ if (eMode == MODE_PLAIN)
+ eMode = MODE_DOMAIN_LITERAL;
+ rSink << '[';
+ ++pStart;
+ break;
+
+ case ']':
+ if (eMode == MODE_DOMAIN_LITERAL)
+ eMode = MODE_PLAIN;
+ rSink << ']';
+ ++pStart;
+ break;
+
+ case '\\':
+ rSink << '\\';
+ if (++pStart < pBodyPtr)
+ writeUTF8(rSink, *pStart++);
+ break;
+
+ default:
+ writeUTF8(rSink, *pStart++);
+ break;
+ }
+ }
+ else
+ rSink.write(pStart, pBodyPtr);
+ break;
+ }
+
+ case ENTITY_PHRASE:
+ {
+ // Write a pending '<' if necessary:
+ if (eBrackets == BRACKETS_OPENING)
+ {
+ if (rSink.getColumn()
+ + (bInitialSpace ? 1 : 0)
+ >= rSink.getLineLengthLimit())
+ rSink << INetMIMEOutputSink::endl << ' ';
+ else if (bInitialSpace)
+ rSink << ' ';
+ rSink << '<';
+ bInitialSpace = false;
+ eBrackets = BRACKETS_INSIDE;
+ }
+
+ // Calculate the length of in- and output:
+ const sal_Unicode * pStart = pBodyPtr;
+ bool bQuotedString = false;
+ bool bEnd = false;
+ while (pBodyPtr != pBodyEnd && !bEnd)
+ switch (*pBodyPtr)
+ {
+ case '\t':
+ case ' ':
+ case '\x0D': // CR
+ if (bQuotedString)
+ ++pBodyPtr;
+ else
+ {
+ const sal_Unicode * pLookAhead
+ = skipLinearWhiteSpace(
+ pBodyPtr, pBodyEnd);
+ if (pLookAhead != pBodyEnd
+ && (isAtomChar(*pLookAhead)
+ || !isUSASCII(*pLookAhead)
+ || *pLookAhead == '"'))
+ pBodyPtr = pLookAhead;
+ else
+ bEnd = true;
+ }
+ break;
+
+ case '"':
+ bQuotedString = !bQuotedString;
+ ++pBodyPtr;
+ break;
+
+ case '\\':
+ if (bQuotedString)
+ {
+ if (++pBodyPtr != pBodyEnd)
+ ++pBodyPtr;
+ }
+ else
+ bEnd = true;
+ break;
+
+ default:
+ if (bQuotedString
+ || isAtomChar(*pBodyPtr)
+ || !isUSASCII(*pBodyPtr))
+ ++pBodyPtr;
+ else
+ bEnd = true;
+ break;
+ }
+
+ // Write the phrase, introducing encoded-words
+ // where necessary:
+ INetMIMEEncodedWordOutputSink
+ aOutput(
+ rSink,
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,
+ bInitialSpace ?
+ INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
+ INetMIMEEncodedWordOutputSink::SPACE_ENCODED,
+ ePreferredEncoding);
+ while (pStart != pBodyPtr)
+ switch (*pStart)
+ {
+ case '"':
+ ++pStart;
+ break;
+
+ case '\\':
+ if (++pStart != pBodyPtr)
+ aOutput << *pStart++;
+ break;
+
+ case '\x0D': // CR
+ pStart += 2;
+ aOutput << *pStart++;
+ break;
+
+ default:
+ aOutput << *pStart++;
+ break;
+ }
+ bInitialSpace = aOutput.flush();
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+//============================================================================
+// static
+bool INetMIME::translateUTF8Char(const sal_Char *& rBegin,
+ const sal_Char * pEnd,
+ rtl_TextEncoding eEncoding,
+ sal_uInt32 & rCharacter)
+{
+ if (rBegin == pEnd || *rBegin < 0x80 || *rBegin >= 0xFE)
+ return false;
+
+ int nCount;
+ sal_uInt32 nMin;
+ sal_uInt32 nUCS4;
+ const sal_Char * p = rBegin;
+ if (*p < 0xE0)
+ {
+ nCount = 1;
+ nMin = 0x80;
+ nUCS4 = *p & 0x1F;
+ }
+ else if (*p < 0xF0)
+ {
+ nCount = 2;
+ nMin = 0x800;
+ nUCS4 = *p & 0xF;
+ }
+ else if (*p < 0xF8)
+ {
+ nCount = 3;
+ nMin = 0x10000;
+ nUCS4 = *p & 7;
+ }
+ else if (*p < 0xFC)
+ {
+ nCount = 4;
+ nMin = 0x200000;
+ nUCS4 = *p & 3;
+ }
+ else
+ {
+ nCount = 5;
+ nMin = 0x4000000;
+ nUCS4 = *p & 1;
+ }
+ ++p;
+
+ for (; nCount-- > 0; ++p)
+ if ((*p & 0xC0) == 0x80)
+ nUCS4 = nUCS4 << 6 | *p & 0x3F;
+ else
+ return false;
+
+ if (nUCS4 < nMin || nUCS4 > 0x10FFFF)
+ return false;
+
+ if (eEncoding >= RTL_TEXTENCODING_UCS4)
+ rCharacter = nUCS4;
+ else
+ {
+ sal_Unicode aUTF16[2];
+ const sal_Unicode * pUTF16End = putUTF32Character(aUTF16, nUCS4);
+ sal_Size nSize;
+ sal_Char * pBuffer = convertFromUnicode(aUTF16, pUTF16End, eEncoding,
+ nSize);
+ if (!pBuffer)
+ return false;
+ DBG_ASSERT(nSize == 1,
+ "INetMIME::translateUTF8Char(): Bad conversion");
+ rCharacter = *pBuffer;
+ delete[] pBuffer;
+ }
+ rBegin = p;
+ return true;
+}
+
+//============================================================================
+// static
+ByteString INetMIME::decodeUTF8(const ByteString & rText,
+ rtl_TextEncoding eEncoding)
+{
+ const sal_Char * p = rText.GetBuffer();
+ const sal_Char * pEnd = p + rText.Len();
+ ByteString sDecoded;
+ while (p != pEnd)
+ {
+ sal_uInt32 nCharacter;
+ if (translateUTF8Char(p, pEnd, eEncoding, nCharacter))
+ sDecoded += sal_Char(nCharacter);
+ else
+ sDecoded += sal_Char(*p++);
+ }
+ return sDecoded;
+}
+
+//============================================================================
+// static
+UniString INetMIME::decodeHeaderFieldBody(HeaderFieldType eType,
+ const ByteString & rBody)
+{
+ // Due to a bug in INetCoreRFC822MessageStream::ConvertTo7Bit(), old
+ // versions of StarOffice send mails with header fields where encoded
+ // words can be preceded by '=', ',', '.', '"', or '(', and followed by
+ // '=', ',', '.', '"', ')', without any required white space in between.
+ // And there appear to exist some broken mailers that only encode single
+ // letters within words, like "Appel
+ // =?iso-8859-1?Q?=E0?=t=?iso-8859-1?Q?=E9?=moin", so it seems best to
+ // detect encoded words even when not propperly surrounded by white space.
+ //
+ // Non US-ASCII characters in rBody are treated as ISO-8859-1.
+ //
+ // encoded-word = "=?"
+ // 1*(%x21 / %x23-27 / %x2A-2B / %x2D / %30-39 / %x41-5A / %x5E-7E)
+ // ["*" 1*8ALPHA *("-" 1*8ALPHA)] "?"
+ // ("B?" *(4base64) (4base64 / 3base64 "=" / 2base64 "==")
+ // / "Q?" 1*(%x21-3C / %x3E / %x40-7E / "=" 2HEXDIG))
+ // "?="
+ //
+ // base64 = ALPHA / DIGIT / "+" / "/"
+
+ const sal_Char * pBegin = rBody.GetBuffer();
+ const sal_Char * pEnd = pBegin + rBody.Len();
+
+ UniString sDecoded;
+ const sal_Char * pCopyBegin = pBegin;
+
+ /* bool bStartEncodedWord = true; */
+ const sal_Char * pWSPBegin = pBegin;
+ UniString sEncodedText;
+ bool bQuotedEncodedText = false;
+ sal_uInt32 nCommentLevel = 0;
+
+ for (const sal_Char * p = pBegin; p != pEnd;)
+ {
+ if (p != pEnd && *p == '=' /* && bStartEncodedWord */)
+ {
+ const sal_Char * q = p + 1;
+ bool bEncodedWord = q != pEnd && *q++ == '?';
+
+ rtl_TextEncoding eCharsetEncoding;
+ if (bEncodedWord)
+ {
+ const sal_Char * pCharsetBegin = q;
+ const sal_Char * pLanguageBegin = 0;
+ int nAlphaCount;
+ for (bool bDone = false; !bDone;)
+ if (q == pEnd)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ }
+ else
+ {
+ sal_Char cChar = *q++;
+ switch (cChar)
+ {
+ case '*':
+ pLanguageBegin = q - 1;
+ nAlphaCount = 0;
+ break;
+
+ case '-':
+ if (pLanguageBegin != 0)
+ {
+ if (nAlphaCount == 0)
+ pLanguageBegin = 0;
+ else
+ nAlphaCount = 0;
+ }
+ break;
+
+ case '?':
+ if (pCharsetBegin == q - 1)
+ bEncodedWord = false;
+ else
+ {
+ eCharsetEncoding
+ = getCharsetEncoding(
+ pCharsetBegin,
+ pLanguageBegin == 0
+ || nAlphaCount == 0 ?
+ q - 1 : pLanguageBegin);
+ bEncodedWord = isMIMECharsetEncoding(
+ eCharsetEncoding);
+ eCharsetEncoding
+ = translateFromMIME(eCharsetEncoding);
+ }
+ bDone = true;
+ break;
+
+ default:
+ if (pLanguageBegin != 0
+ && (!isAlpha(cChar) || ++nAlphaCount > 8))
+ pLanguageBegin = 0;
+ break;
+ }
+ }
+ }
+
+ bool bEncodingB;
+ if (bEncodedWord)
+ if (q == pEnd)
+ bEncodedWord = false;
+ else
+ switch (*q++)
+ {
+ case 'B':
+ case 'b':
+ bEncodingB = true;
+ break;
+
+ case 'Q':
+ case 'q':
+ bEncodingB = false;
+ break;
+
+ default:
+ bEncodedWord = false;
+ break;
+ }
+
+ bEncodedWord = bEncodedWord && q != pEnd && *q++ == '?';
+
+ ByteString sText;
+ if (bEncodedWord)
+ if (bEncodingB)
+ for (bool bDone = false; !bDone;)
+ {
+ if (pEnd - q < 4)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ }
+ else
+ {
+ bool bFinal = false;
+ int nCount = 3;
+ sal_uInt32 nValue = 0;
+ for (int nShift = 18; nShift >= 0; nShift -= 6)
+ {
+ int nWeight = getBase64Weight(*q++);
+ if (nWeight == -2)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ break;
+ }
+ if (nWeight == -1)
+ {
+ if (!bFinal)
+ {
+ if (nShift >= 12)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ break;
+ }
+ bFinal = true;
+ nCount = nShift == 6 ? 2 : 1;
+ }
+ }
+ else
+ nValue |= nWeight << nShift;
+ }
+ if (bEncodedWord)
+ {
+ for (int nShift = 16; nCount-- > 0;
+ nShift -= 8)
+ sText += sal_Char(nValue >> nShift
+ & 0xFF);
+ if (*q == '?')
+ {
+ ++q;
+ bDone = true;
+ }
+ if (bFinal && !bDone)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ const sal_Char * pEncodedTextBegin = q;
+ const sal_Char * pEncodedTextCopyBegin = q;
+ for (bool bDone = false; !bDone;)
+ if (q == pEnd)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ }
+ else
+ {
+ sal_uInt32 nChar = *q++;
+ switch (nChar)
+ {
+ case '=':
+ {
+ if (pEnd - q < 2)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ break;
+ }
+ int nDigit1 = getHexWeight(q[0]);
+ int nDigit2 = getHexWeight(q[1]);
+ if (nDigit1 < 0 || nDigit2 < 0)
+ {
+ bEncodedWord = false;
+ bDone = true;
+ break;
+ }
+ sText
+ += rBody.
+ Copy(
+ pEncodedTextCopyBegin
+ - pBegin,
+ q - 1
+ - pEncodedTextCopyBegin);
+ sText += sal_Char(nDigit1 << 4 | nDigit2);
+ q += 2;
+ pEncodedTextCopyBegin = q;
+ break;
+ }
+
+ case '?':
+ if (q - pEncodedTextBegin > 1)
+ sText
+ += rBody.
+ Copy(
+ pEncodedTextCopyBegin
+ - pBegin,
+ q - 1
+ - pEncodedTextCopyBegin);
+ else
+ bEncodedWord = false;
+ bDone = true;
+ break;
+
+ case '_':
+ sText
+ += rBody.
+ Copy(
+ pEncodedTextCopyBegin
+ - pBegin,
+ q - 1
+ - pEncodedTextCopyBegin);
+ sText += ' ';
+ pEncodedTextCopyBegin = q;
+ break;
+
+ default:
+ if (!isVisible(nChar))
+ {
+ bEncodedWord = false;
+ bDone = true;
+ }
+ break;
+ }
+ }
+ }
+
+ bEncodedWord = bEncodedWord && q != pEnd && *q++ == '=';
+
+// if (bEncodedWord && q != pEnd)
+// switch (*q)
+// {
+// case '\t':
+// case ' ':
+// case '"':
+// case ')':
+// case ',':
+// case '.':
+// case '=':
+// break;
+//
+// default:
+// bEncodedWord = false;
+// break;
+// }
+
+ sal_Unicode * pUnicodeBuffer;
+ sal_Size nUnicodeSize;
+ if (bEncodedWord)
+ {
+ pUnicodeBuffer
+ = convertToUnicode(sText.GetBuffer(),
+ sText.GetBuffer() + sText.Len(),
+ eCharsetEncoding, nUnicodeSize);
+ if (pUnicodeBuffer == 0)
+ bEncodedWord = false;
+ }
+
+ if (bEncodedWord)
+ {
+ appendISO88591(sDecoded, pCopyBegin, pWSPBegin);
+ if (eType == HEADER_FIELD_TEXT)
+ sDecoded.Append(pUnicodeBuffer, nUnicodeSize);
+ else if (nCommentLevel == 0)
+ {
+ sEncodedText.Append(pUnicodeBuffer, nUnicodeSize);
+ if (!bQuotedEncodedText)
+ {
+ const sal_Unicode * pTextPtr = pUnicodeBuffer;
+ const sal_Unicode * pTextEnd = pTextPtr
+ + nUnicodeSize;
+ for (; pTextPtr != pTextEnd; ++pTextPtr)
+ if (!isEncodedWordTokenChar(*pTextPtr))
+ {
+ bQuotedEncodedText = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ const sal_Unicode * pTextPtr = pUnicodeBuffer;
+ const sal_Unicode * pTextEnd = pTextPtr + nUnicodeSize;
+ for (; pTextPtr != pTextEnd; ++pTextPtr)
+ {
+ switch (*pTextPtr)
+ {
+ case '(':
+ case ')':
+ case '\\':
+ case '\x0D':
+ case '=':
+ sDecoded += '\\';
+ break;
+ }
+ sDecoded += *pTextPtr;
+ }
+ }
+ delete[] pUnicodeBuffer;
+ p = q;
+ pCopyBegin = p;
+
+ pWSPBegin = p;
+ while (p != pEnd && isWhiteSpace(*p))
+ ++p;
+ /* bStartEncodedWord = p != pWSPBegin; */
+ continue;
+ }
+ }
+
+ if (sEncodedText.Len() != 0)
+ {
+ if (bQuotedEncodedText)
+ {
+ sDecoded += '"';
+ const sal_Unicode * pTextPtr = sEncodedText.GetBuffer();
+ const sal_Unicode * pTextEnd = pTextPtr + sEncodedText.Len();
+ for (;pTextPtr != pTextEnd; ++pTextPtr)
+ {
+ switch (*pTextPtr)
+ {
+ case '"':
+ case '\\':
+ case '\x0D':
+ sDecoded += '\\';
+ break;
+ }
+ sDecoded += *pTextPtr;
+ }
+ sDecoded += '"';
+ }
+ else
+ sDecoded += sEncodedText;
+ sEncodedText.Erase();
+ bQuotedEncodedText = false;
+ }
+
+ if (p == pEnd)
+ break;
+
+ switch (*p++)
+ {
+// case '\t':
+// case ' ':
+// case ',':
+// case '.':
+// case '=':
+// bStartEncodedWord = true;
+// break;
+
+ case '"':
+ if (eType != HEADER_FIELD_TEXT && nCommentLevel == 0)
+ {
+ const sal_Char * pQuotedStringEnd
+ = skipQuotedString(p - 1, pEnd);
+ p = pQuotedStringEnd == p - 1 ? pEnd : pQuotedStringEnd;
+ }
+ /* bStartEncodedWord = true; */
+ break;
+
+ case '(':
+ if (eType != HEADER_FIELD_TEXT)
+ ++nCommentLevel;
+ /* bStartEncodedWord = true; */
+ break;
+
+ case ')':
+ if (nCommentLevel > 0)
+ --nCommentLevel;
+ /* bStartEncodedWord = false; */
+ break;
+
+ default:
+ {
+ const sal_Char * pUTF8Begin = p - 1;
+ const sal_Char * pUTF8End = pUTF8Begin;
+ sal_uInt32 nCharacter;
+ if (translateUTF8Char(pUTF8End, pEnd, RTL_TEXTENCODING_UCS4,
+ nCharacter))
+ {
+ appendISO88591(sDecoded, pCopyBegin, p - 1);
+ sal_Unicode aUTF16Buf[2];
+ xub_StrLen nUTF16Len = putUTF32Character(aUTF16Buf,
+ nCharacter)
+ - aUTF16Buf;
+ sDecoded.Append(aUTF16Buf, nUTF16Len);
+ p = pUTF8End;
+ pCopyBegin = p;
+ }
+ /* bStartEncodedWord = false; */
+ break;
+ }
+ }
+ pWSPBegin = p;
+ }
+
+ appendISO88591(sDecoded, pCopyBegin, pEnd);
+ return sDecoded;
+}
+
+//============================================================================
+//
+// INetMIMEOutputSink
+//
+//============================================================================
+
+// virtual
+sal_Size INetMIMEOutputSink::writeSequence(const sal_Char * pSequence)
+{
+ sal_Size nLength = rtl_str_getLength(pSequence);
+ writeSequence(pSequence, pSequence + nLength);
+ return nLength;
+}
+
+//============================================================================
+// virtual
+void INetMIMEOutputSink::writeSequence(const sal_uInt32 * pBegin,
+ const sal_uInt32 * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEOutputSink::writeSequence(): Bad sequence");
+
+ sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
+ sal_Char * pBufferEnd = pBufferBegin;
+ while (pBegin != pEnd)
+ {
+ DBG_ASSERT(*pBegin < 256,
+ "INetMIMEOutputSink::writeSequence(): Bad octet");
+ *pBufferEnd++ = sal_Char(*pBegin++);
+ }
+ writeSequence(pBufferBegin, pBufferEnd);
+ delete[] pBufferBegin;
+}
+
+//============================================================================
+// virtual
+void INetMIMEOutputSink::writeSequence(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEOutputSink::writeSequence(): Bad sequence");
+
+ sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
+ sal_Char * pBufferEnd = pBufferBegin;
+ while (pBegin != pEnd)
+ {
+ DBG_ASSERT(*pBegin < 256,
+ "INetMIMEOutputSink::writeSequence(): Bad octet");
+ *pBufferEnd++ = sal_Char(*pBegin++);
+ }
+ writeSequence(pBufferBegin, pBufferEnd);
+ delete[] pBufferBegin;
+}
+
+//============================================================================
+// virtual
+ErrCode INetMIMEOutputSink::getError() const
+{
+ return ERRCODE_NONE;
+}
+
+//============================================================================
+void INetMIMEOutputSink::writeLineEnd()
+{
+ static const sal_Char aCRLF[2] = { 0x0D, 0x0A };
+ writeSequence(aCRLF, aCRLF + 2);
+ m_nColumn = 0;
+}
+
+//============================================================================
+//
+// INetMIMEStringOutputSink
+//
+//============================================================================
+
+// virtual
+void INetMIMEStringOutputSink::writeSequence(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEStringOutputSink::writeSequence(): Bad sequence");
+
+ m_bOverflow = m_bOverflow
+ || pEnd - pBegin > STRING_MAXLEN - m_aBuffer.Len();
+ if (!m_bOverflow)
+ m_aBuffer.Append(pBegin, pEnd - pBegin);
+}
+
+//============================================================================
+// virtual
+ErrCode INetMIMEStringOutputSink::getError() const
+{
+ return m_bOverflow ? ERRCODE_IO_OUTOFMEMORY : ERRCODE_NONE;
+}
+
+//============================================================================
+//
+// INetMIMEUnicodeOutputSink
+//
+//============================================================================
+
+// virtual
+void INetMIMEUnicodeOutputSink::writeSequence(const sal_Char * pBegin,
+ const sal_Char * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEUnicodeOutputSink::writeSequence(): Bad sequence");
+
+ sal_Unicode * pBufferBegin = new sal_Unicode[pEnd - pBegin];
+ sal_Unicode * pBufferEnd = pBufferBegin;
+ while (pBegin != pEnd)
+ *pBufferEnd++ = sal_uChar(*pBegin++);
+ writeSequence(pBufferBegin, pBufferEnd);
+ delete[] pBufferBegin;
+}
+
+//============================================================================
+// virtual
+void INetMIMEUnicodeOutputSink::writeSequence(const sal_uInt32 * pBegin,
+ const sal_uInt32 * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEUnicodeOutputSink::writeSequence(): Bad sequence");
+
+ sal_Unicode * pBufferBegin = new sal_Unicode[pEnd - pBegin];
+ sal_Unicode * pBufferEnd = pBufferBegin;
+ while (pBegin != pEnd)
+ {
+ DBG_ASSERT(*pBegin < 256,
+ "INetMIMEOutputSink::writeSequence(): Bad octet");
+ *pBufferEnd++ = sal_Unicode(*pBegin++);
+ }
+ writeSequence(pBufferBegin, pBufferEnd);
+ delete[] pBufferBegin;
+}
+
+//============================================================================
+// virtual
+void INetMIMEUnicodeOutputSink::writeSequence(const sal_Unicode * pBegin,
+ const sal_Unicode * pEnd)
+{
+ DBG_ASSERT(pBegin && pBegin <= pEnd,
+ "INetMIMEUnicodeOutputSink::writeSequence(): Bad sequence");
+
+ m_bOverflow = m_bOverflow
+ || pEnd - pBegin > STRING_MAXLEN - m_aBuffer.Len();
+ if (!m_bOverflow)
+ m_aBuffer.Append(pBegin, pEnd - pBegin);
+}
+
+//============================================================================
+// virtual
+ErrCode INetMIMEUnicodeOutputSink::getError() const
+{
+ return m_bOverflow ? ERRCODE_IO_OUTOFMEMORY : ERRCODE_NONE;
+}
+
+//============================================================================
+//
+// INetMIMEEncodedWordOutputSink
+//
+//============================================================================
+
+static const sal_Char aEscape[128]
+ = { INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x00
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x01
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x02
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x03
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x04
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x05
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x06
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x07
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x08
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x09
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0A
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0B
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0C
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0D
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0E
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0F
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x10
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x11
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x12
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x13
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x14
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x15
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x16
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x17
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x18
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x19
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1A
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1B
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1C
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1D
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1E
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1F
+ 0, // ' '
+ 0, // '!'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '"'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '#'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '$'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '%'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '&'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '''
+ INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '('
+ INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ')'
+ 0, // '*'
+ 0, // '+'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ','
+ 0, // '-'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '.'
+ 0, // '/'
+ 0, // '0'
+ 0, // '1'
+ 0, // '2'
+ 0, // '3'
+ 0, // '4'
+ 0, // '5'
+ 0, // '6'
+ 0, // '7'
+ 0, // '8'
+ 0, // '9'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ':'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ';'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '<'
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '='
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '>'
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '?'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '@'
+ 0, // 'A'
+ 0, // 'B'
+ 0, // 'C'
+ 0, // 'D'
+ 0, // 'E'
+ 0, // 'F'
+ 0, // 'G'
+ 0, // 'H'
+ 0, // 'I'
+ 0, // 'J'
+ 0, // 'K'
+ 0, // 'L'
+ 0, // 'M'
+ 0, // 'N'
+ 0, // 'O'
+ 0, // 'P'
+ 0, // 'Q'
+ 0, // 'R'
+ 0, // 'S'
+ 0, // 'T'
+ 0, // 'U'
+ 0, // 'V'
+ 0, // 'W'
+ 0, // 'X'
+ 0, // 'Y'
+ 0, // 'Z'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '['
+ INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '\'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ']'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '^'
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '_'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '`'
+ 0, // 'a'
+ 0, // 'b'
+ 0, // 'c'
+ 0, // 'd'
+ 0, // 'e'
+ 0, // 'f'
+ 0, // 'g'
+ 0, // 'h'
+ 0, // 'i'
+ 0, // 'j'
+ 0, // 'k'
+ 0, // 'l'
+ 0, // 'm'
+ 0, // 'n'
+ 0, // 'o'
+ 0, // 'p'
+ 0, // 'q'
+ 0, // 'r'
+ 0, // 's'
+ 0, // 't'
+ 0, // 'u'
+ 0, // 'v'
+ 0, // 'w'
+ 0, // 'x'
+ 0, // 'y'
+ 0, // 'z'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '{'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '|'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '}'
+ INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '~'
+ INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE }; // DEL
+
+inline bool
+INetMIMEEncodedWordOutputSink::needsEncodedWordEscape(sal_uInt32 nChar) const
+{
+ return !INetMIME::isUSASCII(nChar) || aEscape[nChar] & m_eContext;
+}
+
+//============================================================================
+void INetMIMEEncodedWordOutputSink::finish(bool bWriteTrailer)
+{
+ if (m_eInitialSpace == SPACE_ALWAYS && m_nExtraSpaces == 0)
+ m_nExtraSpaces = 1;
+
+ if (m_eEncodedWordState == STATE_SECOND_EQUALS)
+ {
+ // If the text is already an encoded word, copy it verbatim:
+ sal_uInt32 nSize = m_pBufferEnd - m_pBuffer;
+ switch (m_ePrevCoding)
+ {
+ case CODING_QUOTED:
+ m_rSink << '"';
+ case CODING_NONE:
+ if (m_eInitialSpace == SPACE_ENCODED && m_nExtraSpaces == 0)
+ m_nExtraSpaces = 1;
+ for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
+ {
+ if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ if (m_nExtraSpaces == 1)
+ {
+ if (m_rSink.getColumn() + nSize
+ >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ break;
+
+ case CODING_ENCODED:
+ {
+ const sal_Char * pCharsetName
+ = INetMIME::getCharsetName(m_ePrevMIMEEncoding);
+ while (m_nExtraSpaces-- > 0)
+ {
+ if (m_rSink.getColumn()
+ > m_rSink.getLineLengthLimit() - 3)
+ m_rSink << "?=" << INetMIMEOutputSink::endl << " =?"
+ << pCharsetName << "?Q?";
+ m_rSink << '_';
+ }
+ m_rSink << "?=";
+ }
+ case CODING_ENCODED_TERMINATED:
+ if (m_rSink.getColumn() + nSize
+ > m_rSink.getLineLengthLimit() - 1)
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ break;
+ }
+ m_rSink.write(m_pBuffer, m_pBufferEnd);
+ m_eCoding = CODING_ENCODED_TERMINATED;
+ }
+ else
+ {
+ // If the text itself is too long to fit into a single line, make it
+ // into multiple encoded words:
+ switch (m_eCoding)
+ {
+ case CODING_NONE:
+ if (m_nExtraSpaces == 0)
+ {
+ DBG_ASSERT(m_ePrevCoding == CODING_NONE
+ || m_pBuffer == m_pBufferEnd,
+ "INetMIMEEncodedWordOutputSink::finish():"
+ " Bad state");
+ if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
+ > m_rSink.getLineLengthLimit())
+ m_eCoding = CODING_ENCODED;
+ }
+ else if (m_pBufferEnd - m_pBuffer
+ > m_rSink.getLineLengthLimit() - 1)
+ m_eCoding = CODING_ENCODED;
+ break;
+
+ case CODING_QUOTED:
+ if (m_nExtraSpaces == 0)
+ {
+ DBG_ASSERT(m_ePrevCoding == CODING_NONE,
+ "INetMIMEEncodedWordOutputSink::finish():"
+ " Bad state");
+ if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
+ + m_nQuotedEscaped
+ > m_rSink.getLineLengthLimit() - 2)
+ m_eCoding = CODING_ENCODED;
+ }
+ else if ((m_pBufferEnd - m_pBuffer) + m_nQuotedEscaped
+ > m_rSink.getLineLengthLimit() - 3)
+ m_eCoding = CODING_ENCODED;
+ break;
+ }
+
+ switch (m_eCoding)
+ {
+ case CODING_NONE:
+ switch (m_ePrevCoding)
+ {
+ case CODING_QUOTED:
+ if (m_rSink.getColumn() + m_nExtraSpaces
+ + (m_pBufferEnd - m_pBuffer)
+ < m_rSink.getLineLengthLimit())
+ m_eCoding = CODING_QUOTED;
+ else
+ m_rSink << '"';
+ break;
+
+ case CODING_ENCODED:
+ m_rSink << "?=";
+ break;
+ }
+ for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
+ {
+ if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ if (m_nExtraSpaces == 1)
+ {
+ if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
+ >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ m_rSink.write(m_pBuffer, m_pBufferEnd);
+ if (m_eCoding == CODING_QUOTED && bWriteTrailer)
+ {
+ m_rSink << '"';
+ m_eCoding = CODING_NONE;
+ }
+ break;
+
+ case CODING_QUOTED:
+ {
+ bool bInsertLeadingQuote = true;
+ sal_uInt32 nSize = (m_pBufferEnd - m_pBuffer)
+ + m_nQuotedEscaped + 2;
+ switch (m_ePrevCoding)
+ {
+ case CODING_QUOTED:
+ if (m_rSink.getColumn() + m_nExtraSpaces + nSize - 1
+ < m_rSink.getLineLengthLimit())
+ {
+ bInsertLeadingQuote = false;
+ --nSize;
+ }
+ else
+ m_rSink << '"';
+ break;
+
+ case CODING_ENCODED:
+ m_rSink << "?=";
+ break;
+ }
+ for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
+ {
+ if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ if (m_nExtraSpaces == 1)
+ {
+ if (m_rSink.getColumn() + nSize
+ >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ if (bInsertLeadingQuote)
+ m_rSink << '"';
+ for (const sal_Unicode * p = m_pBuffer; p != m_pBufferEnd;
+ ++p)
+ {
+ if (INetMIME::needsQuotedStringEscape(*p))
+ m_rSink << '\\';
+ m_rSink << sal_Char(*p);
+ }
+ if (bWriteTrailer)
+ {
+ m_rSink << '"';
+ m_eCoding = CODING_NONE;
+ }
+ break;
+ }
+
+ case CODING_ENCODED:
+ {
+ rtl_TextEncoding eCharsetEncoding
+ = m_pEncodingList->
+ getPreferredEncoding(RTL_TEXTENCODING_UTF8);
+ rtl_TextEncoding eMIMEEncoding
+ = INetMIME::translateToMIME(eCharsetEncoding);
+
+ // The non UTF-8 code will only work for stateless single byte
+ // character encodings (see also below):
+ sal_Char * pTargetBuffer;
+ sal_Size nTargetSize;
+ sal_uInt32 nSize;
+ if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
+ {
+ nSize = 0;
+ for (sal_Unicode const * p = m_pBuffer;
+ p != m_pBufferEnd;)
+ {
+ sal_uInt32 nUTF32
+ = INetMIME::getUTF32Character(p, m_pBufferEnd);
+ nSize += needsEncodedWordEscape(nUTF32) ?
+ 3 * INetMIME::getUTF8OctetCount(nUTF32) :
+ 1;
+ // only US-ASCII characters (that are converted to
+ // a single byte by UTF-8) need no encoded word
+ // escapes...
+ }
+ }
+ else
+ {
+ rtl_UnicodeToTextConverter hConverter
+ = rtl_createUnicodeToTextConverter(eCharsetEncoding);
+ rtl_UnicodeToTextContext hContext
+ = rtl_createUnicodeToTextContext(hConverter);
+ for (sal_Size nBufferSize = m_pBufferEnd - m_pBuffer;;
+ nBufferSize += nBufferSize / 3 + 1)
+ {
+ pTargetBuffer = new sal_Char[nBufferSize];
+ sal_uInt32 nInfo;
+ sal_Size nSrcCvtBytes;
+ nTargetSize
+ = rtl_convertUnicodeToText(
+ hConverter, hContext, m_pBuffer,
+ m_pBufferEnd - m_pBuffer, pTargetBuffer,
+ nBufferSize,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_IGNORE
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_IGNORE,
+ &nInfo, &nSrcCvtBytes);
+ if (!(nInfo
+ & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
+ break;
+ delete[] pTargetBuffer;
+ rtl_resetUnicodeToTextContext(hConverter, hContext);
+ }
+ rtl_destroyUnicodeToTextContext(hConverter, hContext);
+ rtl_destroyUnicodeToTextConverter(hConverter);
+
+ nSize = nTargetSize;
+ for (sal_Size k = 0; k < nTargetSize; ++k)
+ if (needsEncodedWordEscape(sal_uChar(
+ pTargetBuffer[k])))
+ nSize += 2;
+ }
+
+ const sal_Char * pCharsetName
+ = INetMIME::getCharsetName(eMIMEEncoding);
+ sal_uInt32 nWrapperSize = rtl_str_getLength(pCharsetName) + 7;
+ // '=?', '?Q?', '?='
+
+ switch (m_ePrevCoding)
+ {
+ case CODING_QUOTED:
+ m_rSink << '"';
+ case CODING_NONE:
+ if (m_eInitialSpace == SPACE_ENCODED
+ && m_nExtraSpaces == 0)
+ m_nExtraSpaces = 1;
+ nSize += nWrapperSize;
+ for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
+ {
+ if (m_rSink.getColumn()
+ >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ if (m_nExtraSpaces == 1)
+ {
+ if (m_rSink.getColumn() + nSize
+ >= m_rSink.getLineLengthLimit())
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << ' ';
+ }
+ m_rSink << "=?" << pCharsetName << "?Q?";
+ break;
+
+ case CODING_ENCODED:
+ if (m_ePrevMIMEEncoding != eMIMEEncoding
+ || m_rSink.getColumn() + m_nExtraSpaces + nSize
+ > m_rSink.getLineLengthLimit() - 2)
+ {
+ m_rSink << "?=";
+ if (m_rSink.getColumn() + nWrapperSize
+ + m_nExtraSpaces + nSize
+ > m_rSink.getLineLengthLimit() - 1)
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << " =?" << pCharsetName << "?Q?";
+ }
+ while (m_nExtraSpaces-- > 0)
+ {
+ if (m_rSink.getColumn()
+ > m_rSink.getLineLengthLimit() - 3)
+ m_rSink << "?=" << INetMIMEOutputSink::endl
+ << " =?" << pCharsetName << "?Q?";
+ m_rSink << '_';
+ }
+ break;
+
+ case CODING_ENCODED_TERMINATED:
+ if (m_rSink.getColumn() + nWrapperSize
+ + m_nExtraSpaces + nSize
+ > m_rSink.getLineLengthLimit() - 1)
+ m_rSink << INetMIMEOutputSink::endl;
+ m_rSink << " =?" << pCharsetName << "?Q?";
+ while (m_nExtraSpaces-- > 0)
+ {
+ if (m_rSink.getColumn()
+ > m_rSink.getLineLengthLimit() - 3)
+ m_rSink << "?=" << INetMIMEOutputSink::endl
+ << " =?" << pCharsetName << "?Q?";
+ m_rSink << '_';
+ }
+ break;
+ }
+
+ // The non UTF-8 code will only work for stateless single byte
+ // character encodings (see also above):
+ if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
+ {
+ bool bInitial = true;
+ for (sal_Unicode const * p = m_pBuffer;
+ p != m_pBufferEnd;)
+ {
+ sal_uInt32 nUTF32
+ = INetMIME::getUTF32Character(p, m_pBufferEnd);
+ bool bEscape = needsEncodedWordEscape(nUTF32);
+ sal_uInt32 nWidth
+ = bEscape ?
+ 3 * INetMIME::getUTF8OctetCount(nUTF32) : 1;
+ // only US-ASCII characters (that are converted to
+ // a single byte by UTF-8) need no encoded word
+ // escapes...
+ if (!bInitial
+ && m_rSink.getColumn() + nWidth + 2
+ > m_rSink.getLineLengthLimit())
+ m_rSink << "?=" << INetMIMEOutputSink::endl
+ << " =?" << pCharsetName << "?Q?";
+ if (bEscape)
+ {
+ DBG_ASSERT(
+ nUTF32 < 0x10FFFF,
+ "INetMIMEEncodedWordOutputSink::finish():"
+ " Bad char");
+ if (nUTF32 < 0x80)
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32);
+ else if (nUTF32 < 0x800)
+ {
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 6
+ | 0xC0);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 & 0x3F
+ | 0x80);
+ }
+ else if (nUTF32 < 0x10000)
+ {
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 12
+ | 0xE0);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 6
+ & 0x3F
+ | 0x80);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 & 0x3F
+ | 0x80);
+ }
+ else
+ {
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 18
+ | 0xF0);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 12
+ & 0x3F
+ | 0x80);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 >> 6
+ & 0x3F
+ | 0x80);
+ INetMIME::writeEscapeSequence(m_rSink,
+ nUTF32 & 0x3F
+ | 0x80);
+ }
+ }
+ else
+ m_rSink << sal_Char(nUTF32);
+ bInitial = false;
+ }
+ }
+ else
+ {
+ for (sal_Size k = 0; k < nTargetSize; ++k)
+ {
+ sal_uInt32 nUCS4 = sal_uChar(pTargetBuffer[k]);
+ bool bEscape = needsEncodedWordEscape(nUCS4);
+ if (k > 0
+ && m_rSink.getColumn() + (bEscape ? 5 : 3)
+ > m_rSink.getLineLengthLimit())
+ m_rSink << "?=" << INetMIMEOutputSink::endl
+ << " =?" << pCharsetName << "?Q?";
+ if (bEscape)
+ INetMIME::writeEscapeSequence(m_rSink, nUCS4);
+ else
+ m_rSink << sal_Char(nUCS4);
+ }
+ delete[] pTargetBuffer;
+ }
+
+ if (bWriteTrailer)
+ {
+ m_rSink << "?=";
+ m_eCoding = CODING_ENCODED_TERMINATED;
+ }
+
+ m_ePrevMIMEEncoding = eMIMEEncoding;
+ break;
+ }
+ }
+ }
+
+ m_eInitialSpace = SPACE_NO;
+ m_nExtraSpaces = 0;
+ m_pEncodingList->reset();
+ m_pBufferEnd = m_pBuffer;
+ m_ePrevCoding = m_eCoding;
+ m_eCoding = CODING_NONE;
+ m_nQuotedEscaped = 0;
+ m_eEncodedWordState = STATE_INITIAL;
+}
+
+//============================================================================
+INetMIMEEncodedWordOutputSink::~INetMIMEEncodedWordOutputSink()
+{
+ rtl_freeMemory(m_pBuffer);
+ delete m_pEncodingList;
+}
+
+//============================================================================
+INetMIMEEncodedWordOutputSink &
+INetMIMEEncodedWordOutputSink::operator <<(sal_uInt32 nChar)
+{
+ if (nChar == ' ')
+ {
+ if (m_pBufferEnd != m_pBuffer)
+ finish(false);
+ ++m_nExtraSpaces;
+ }
+ else
+ {
+ // Check for an already encoded word:
+ switch (m_eEncodedWordState)
+ {
+ case STATE_INITIAL:
+ if (nChar == '=')
+ m_eEncodedWordState = STATE_FIRST_EQUALS;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_FIRST_EQUALS:
+ if (nChar == '?')
+ m_eEncodedWordState = STATE_FIRST_EQUALS;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_FIRST_QUESTION:
+ if (INetMIME::isEncodedWordTokenChar(nChar))
+ m_eEncodedWordState = STATE_CHARSET;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_CHARSET:
+ if (nChar == '?')
+ m_eEncodedWordState = STATE_SECOND_QUESTION;
+ else if (!INetMIME::isEncodedWordTokenChar(nChar))
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_SECOND_QUESTION:
+ if (nChar == 'B' || nChar == 'Q'
+ || nChar == 'b' || nChar == 'q')
+ m_eEncodedWordState = STATE_ENCODING;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_ENCODING:
+ if (nChar == '?')
+ m_eEncodedWordState = STATE_THIRD_QUESTION;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_THIRD_QUESTION:
+ if (INetMIME::isVisible(nChar) && nChar != '?')
+ m_eEncodedWordState = STATE_ENCODED_TEXT;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_ENCODED_TEXT:
+ if (nChar == '?')
+ m_eEncodedWordState = STATE_FOURTH_QUESTION;
+ else if (!INetMIME::isVisible(nChar))
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_FOURTH_QUESTION:
+ if (nChar == '=')
+ m_eEncodedWordState = STATE_SECOND_EQUALS;
+ else
+ m_eEncodedWordState = STATE_BAD;
+ break;
+
+ case STATE_SECOND_EQUALS:
+ m_eEncodedWordState = STATE_BAD;
+ break;
+ }
+
+ // Update encoding:
+ m_pEncodingList->includes(nChar);
+
+ // Update coding:
+ enum { TENQ = 1, // CONTEXT_TEXT, CODING_ENCODED
+ CENQ = 2, // CONTEXT_COMMENT, CODING_ENCODED
+ PQTD = 4, // CONTEXT_PHRASE, CODING_QUOTED
+ PENQ = 8 }; // CONTEXT_PHRASE, CODING_ENCODED
+ static const sal_Char aMinimal[128]
+ = { TENQ | CENQ | PENQ, // 0x00
+ TENQ | CENQ | PENQ, // 0x01
+ TENQ | CENQ | PENQ, // 0x02
+ TENQ | CENQ | PENQ, // 0x03
+ TENQ | CENQ | PENQ, // 0x04
+ TENQ | CENQ | PENQ, // 0x05
+ TENQ | CENQ | PENQ, // 0x06
+ TENQ | CENQ | PENQ, // 0x07
+ TENQ | CENQ | PENQ, // 0x08
+ TENQ | CENQ | PENQ, // 0x09
+ TENQ | CENQ | PENQ, // 0x0A
+ TENQ | CENQ | PENQ, // 0x0B
+ TENQ | CENQ | PENQ, // 0x0C
+ TENQ | CENQ | PENQ, // 0x0D
+ TENQ | CENQ | PENQ, // 0x0E
+ TENQ | CENQ | PENQ, // 0x0F
+ TENQ | CENQ | PENQ, // 0x10
+ TENQ | CENQ | PENQ, // 0x11
+ TENQ | CENQ | PENQ, // 0x12
+ TENQ | CENQ | PENQ, // 0x13
+ TENQ | CENQ | PENQ, // 0x14
+ TENQ | CENQ | PENQ, // 0x15
+ TENQ | CENQ | PENQ, // 0x16
+ TENQ | CENQ | PENQ, // 0x17
+ TENQ | CENQ | PENQ, // 0x18
+ TENQ | CENQ | PENQ, // 0x19
+ TENQ | CENQ | PENQ, // 0x1A
+ TENQ | CENQ | PENQ, // 0x1B
+ TENQ | CENQ | PENQ, // 0x1C
+ TENQ | CENQ | PENQ, // 0x1D
+ TENQ | CENQ | PENQ, // 0x1E
+ TENQ | CENQ | PENQ, // 0x1F
+ 0, // ' '
+ 0, // '!'
+ PQTD , // '"'
+ 0, // '#'
+ 0, // '$'
+ 0, // '%'
+ 0, // '&'
+ 0, // '''
+ CENQ | PQTD , // '('
+ CENQ | PQTD , // ')'
+ 0, // '*'
+ 0, // '+'
+ PQTD , // ','
+ 0, // '-'
+ PQTD , // '.'
+ 0, // '/'
+ 0, // '0'
+ 0, // '1'
+ 0, // '2'
+ 0, // '3'
+ 0, // '4'
+ 0, // '5'
+ 0, // '6'
+ 0, // '7'
+ 0, // '8'
+ 0, // '9'
+ PQTD , // ':'
+ PQTD , // ';'
+ PQTD , // '<'
+ 0, // '='
+ PQTD , // '>'
+ 0, // '?'
+ PQTD , // '@'
+ 0, // 'A'
+ 0, // 'B'
+ 0, // 'C'
+ 0, // 'D'
+ 0, // 'E'
+ 0, // 'F'
+ 0, // 'G'
+ 0, // 'H'
+ 0, // 'I'
+ 0, // 'J'
+ 0, // 'K'
+ 0, // 'L'
+ 0, // 'M'
+ 0, // 'N'
+ 0, // 'O'
+ 0, // 'P'
+ 0, // 'Q'
+ 0, // 'R'
+ 0, // 'S'
+ 0, // 'T'
+ 0, // 'U'
+ 0, // 'V'
+ 0, // 'W'
+ 0, // 'X'
+ 0, // 'Y'
+ 0, // 'Z'
+ PQTD , // '['
+ CENQ | PQTD , // '\'
+ PQTD , // ']'
+ 0, // '^'
+ 0, // '_'
+ 0, // '`'
+ 0, // 'a'
+ 0, // 'b'
+ 0, // 'c'
+ 0, // 'd'
+ 0, // 'e'
+ 0, // 'f'
+ 0, // 'g'
+ 0, // 'h'
+ 0, // 'i'
+ 0, // 'j'
+ 0, // 'k'
+ 0, // 'l'
+ 0, // 'm'
+ 0, // 'n'
+ 0, // 'o'
+ 0, // 'p'
+ 0, // 'q'
+ 0, // 'r'
+ 0, // 's'
+ 0, // 't'
+ 0, // 'u'
+ 0, // 'v'
+ 0, // 'w'
+ 0, // 'x'
+ 0, // 'y'
+ 0, // 'z'
+ 0, // '{'
+ 0, // '|'
+ 0, // '}'
+ 0, // '~'
+ TENQ | CENQ | PENQ }; // DEL
+ Coding eNewCoding = !INetMIME::isUSASCII(nChar) ? CODING_ENCODED :
+ m_eContext == CONTEXT_PHRASE ?
+ Coding(aMinimal[nChar] >> 2) :
+ aMinimal[nChar] & m_eContext ? CODING_ENCODED :
+ CODING_NONE;
+ if (eNewCoding > m_eCoding)
+ m_eCoding = eNewCoding;
+ if (m_eCoding == CODING_QUOTED
+ && INetMIME::needsQuotedStringEscape(nChar))
+ ++m_nQuotedEscaped;
+
+ // Append to buffer:
+ if (sal_uInt32(m_pBufferEnd - m_pBuffer) == m_nBufferSize)
+ {
+ m_pBuffer
+ = static_cast< sal_Unicode * >(
+ rtl_reallocateMemory(m_pBuffer,
+ (m_nBufferSize + BUFFER_SIZE)
+ * sizeof (sal_Unicode)));
+ m_pBufferEnd = m_pBuffer + m_nBufferSize;
+ m_nBufferSize += BUFFER_SIZE;
+ }
+ *m_pBufferEnd++ = sal_Unicode(nChar);
+ }
+ return *this;
+}
+
+//============================================================================
+//
+// INetContentTypeParameterList
+//
+//============================================================================
+
+void INetContentTypeParameterList::Clear()
+{
+ while (Count() > 0)
+ delete static_cast< INetContentTypeParameter * >(Remove(Count() - 1));
+}
+
+//============================================================================
+const INetContentTypeParameter *
+INetContentTypeParameterList::find(const ByteString & rAttribute) const
+{
+ for (ULONG i = 0; i < Count(); ++i)
+ {
+ const INetContentTypeParameter * pParameter = GetObject(i);
+ if (pParameter->m_sAttribute.EqualsIgnoreCaseAscii(rAttribute))
+ return pParameter;
+ }
+ return 0;
+}
+
diff --git a/tools/source/inet/inetmsg.cxx b/tools/source/inet/inetmsg.cxx
new file mode 100644
index 000000000000..d34513f62b6c
--- /dev/null
+++ b/tools/source/inet/inetmsg.cxx
@@ -0,0 +1,2945 @@
+/*************************************************************************
+ *
+ * $RCSfile: inetmsg.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:07 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SAL_TYPES_H_
+#include <sal/types.h>
+#endif
+
+#ifndef _RTL_CHAR_H_
+#include <rtl/char.h>
+#endif
+
+#ifndef _DATETIME_HXX
+#include <datetime.hxx>
+#endif
+#ifndef _TOOLS_INETMIME_HXX
+#include <inetmime.hxx>
+#endif
+#ifndef _TOOLS_INETMSG_HXX
+#include <inetmsg.hxx>
+#endif
+#ifndef _TOOLS_INETSTRM_HXX
+#include <inetstrm.hxx>
+#endif
+
+#include <stdio.h>
+
+/*=======================================================================
+ *
+ * INetMessage Implementation.
+ *
+ *=====================================================================*/
+#define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
+#define HEADERFIELD INetMessageHeader
+
+/*
+ * ~INetMessage.
+ */
+INetMessage::~INetMessage (void)
+{
+ ListCleanup_Impl();
+}
+
+/*
+ * ListCleanup_Impl.
+ */
+void INetMessage::ListCleanup_Impl (void)
+{
+ // Cleanup.
+ ULONG i, n = m_aHeaderList.Count();
+ for (i = 0; i < n; i++)
+ delete ((HEADERFIELD*)(m_aHeaderList.GetObject(i)));
+ m_aHeaderList.Clear();
+}
+
+/*
+ * ListCopy.
+ */
+void INetMessage::ListCopy (const INetMessage &rMsg)
+{
+ if (!(this == &rMsg))
+ {
+ // Cleanup.
+ ListCleanup_Impl();
+
+ // Copy.
+ ULONG i, n = rMsg.GetHeaderCount();
+ for (i = 0; i < n; i++)
+ {
+ HEADERFIELD *p = (HEADERFIELD*)(rMsg.m_aHeaderList.GetObject(i));
+ m_aHeaderList.Insert (new HEADERFIELD(*p), LIST_APPEND);
+ }
+ }
+}
+
+/*
+ * SetHeaderField_Impl.
+ */
+void INetMessage::SetHeaderField_Impl (
+ INetMIME::HeaderFieldType eType,
+ const ByteString &rName,
+ const UniString &rValue,
+ ULONG &rnIndex)
+{
+ INetMIMEStringOutputSink aSink (0, STRING_MAXLEN);
+ INetMIME::writeHeaderFieldBody (
+ aSink, eType, rValue, gsl_getSystemTextEncoding(), false);
+ SetHeaderField_Impl (
+ INetMessageHeader (rName, aSink.takeBuffer()), rnIndex);
+}
+
+/*
+ * SetHeaderField.
+ */
+ULONG INetMessage::SetHeaderField (
+ const UniString& rName, const UniString& rValue, ULONG nIndex)
+{
+ ULONG nResult = nIndex;
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ ByteString (rName, RTL_TEXTENCODING_ASCII_US), rValue,
+ nResult);
+ return nResult;
+}
+
+/*
+ * SetHeaderField.
+ */
+ULONG INetMessage::SetHeaderField (
+ const INetMessageHeader &rHeader, ULONG nIndex)
+{
+ ULONG nResult = nIndex;
+ SetHeaderField_Impl (rHeader, nResult);
+ return nResult;
+}
+
+
+/*
+ * operator<<
+ */
+SvStream& INetMessage::operator<< (SvStream& rStrm) const
+{
+ rStrm << m_nDocSize;
+ rStrm.WriteByteString (m_aDocName, RTL_TEXTENCODING_UTF8);
+
+ ULONG i, n = m_aHeaderList.Count();
+ rStrm << n;
+
+ for (i = 0; i < n; i++)
+ rStrm << *((HEADERFIELD *)(m_aHeaderList.GetObject(i)));
+
+ return rStrm;
+}
+
+/*
+ * operator>>
+ */
+SvStream& INetMessage::operator>> (SvStream& rStrm)
+{
+ // Cleanup.
+ m_nDocSize = 0;
+ m_xDocLB.Clear();
+ ListCleanup_Impl();
+
+ // Copy.
+ rStrm >> m_nDocSize;
+ rStrm.ReadByteString (m_aDocName, RTL_TEXTENCODING_UTF8);
+
+ ULONG i, n = 0;
+ rStrm >> n;
+
+ for (i = 0; i < n; i++)
+ {
+ HEADERFIELD *p = new HEADERFIELD();
+ rStrm >> *p;
+ m_aHeaderList.Insert (p, LIST_APPEND);
+ }
+
+ // Done.
+ return rStrm;
+}
+
+/*=======================================================================
+ *
+ * INetMessageHeaderIterator Implementation.
+ *
+ *=====================================================================*/
+INetMessageHeaderIterator::INetMessageHeaderIterator (
+ const INetMessage& rMsg, const UniString& rHdrName)
+{
+ ULONG i, n = rMsg.GetHeaderCount();
+ for (i = 0; i < n; i++)
+ {
+ if (rHdrName.CompareIgnoreCaseToAscii (rMsg.GetHeaderName(i)) == 0)
+ {
+ UniString *pValue = new UniString (rMsg.GetHeaderValue(i));
+ aValueList.Insert (pValue, LIST_APPEND);
+ }
+ }
+ nValueCount = aValueList.Count();
+}
+
+INetMessageHeaderIterator::~INetMessageHeaderIterator (void)
+{
+ ULONG i, n = aValueList.Count();
+ for (i = 0; i < n; i++)
+ delete ((UniString*)(aValueList.GetObject(i)));
+ aValueList.Clear();
+}
+
+/*=======================================================================
+ *
+ * INetRFC822Message Implementation.
+ *
+ *=====================================================================*/
+/*
+ * _ImplINetRFC822MessageHeaderData.
+ */
+static const ByteString _ImplINetRFC822MessageHeaderData[] =
+{
+ ByteString ("BCC"),
+ ByteString ("CC"),
+ ByteString ("Comments"),
+ ByteString ("Date"),
+ ByteString ("From"),
+ ByteString ("In-Reply-To"),
+ ByteString ("Keywords"),
+ ByteString ("Message-ID"),
+ ByteString ("References"),
+ ByteString ("Reply-To"),
+ ByteString ("Return-Path"),
+ ByteString ("Subject"),
+ ByteString ("Sender"),
+ ByteString ("To"),
+ ByteString ("X-Mailer"),
+ ByteString ("Return-Receipt-To")
+};
+
+#define HDR(n) _ImplINetRFC822MessageHeaderData[(n)]
+
+/*
+ * _ImplINetRFC822MessageHeaderState.
+ */
+enum _ImplINetRFC822MessageHeaderState
+{
+ INETMSG_RFC822_BEGIN,
+ INETMSG_RFC822_CHECK,
+ INETMSG_RFC822_OK,
+ INETMSG_RFC822_JUNK,
+
+ INETMSG_RFC822_TOKEN_RE,
+ INETMSG_RFC822_TOKEN_RETURNMINUS,
+ INETMSG_RFC822_TOKEN_XMINUS,
+ INETMSG_RFC822_LETTER_C,
+ INETMSG_RFC822_LETTER_S
+};
+
+/*
+ * INetRFC822Message.
+ */
+INetRFC822Message::INetRFC822Message (void)
+ : INetMessage()
+{
+ for (USHORT i = 0; i < INETMSG_RFC822_NUMHDR; i++)
+ m_nIndex[i] = LIST_ENTRY_NOTFOUND;
+}
+
+INetRFC822Message::INetRFC822Message (const INetRFC822Message& rMsg)
+ : INetMessage (rMsg)
+{
+ for (USHORT i = 0; i < INETMSG_RFC822_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+}
+
+/*
+ * operator=
+ */
+INetRFC822Message& INetRFC822Message::operator= (const INetRFC822Message& rMsg)
+{
+ if (this != &rMsg)
+ {
+ INetMessage::operator= (rMsg);
+
+ for (USHORT i = 0; i < INETMSG_RFC822_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+ }
+ return *this;
+}
+
+/*
+ * ~INetRFC822Message.
+ */
+INetRFC822Message::~INetRFC822Message (void)
+{
+}
+
+/*
+ * <Generate|Parse>DateField and local helper functions.
+ *
+ * GenerateDateField.
+ * Generates a String from Date and Time objects in format:
+ * Wkd, 00 Mon 0000 00:00:00 [GMT] (rfc822, rfc1123)
+ *
+ * ParseDateField.
+ * Parses a String in (implied) GMT format into class Date and Time objects.
+ * Four formats are accepted:
+ *
+ * [Wkd,] 1*2DIGIT Mon 2*4DIGIT 00:00:00 [GMT] (rfc1123)
+ * [Wkd,] 00 Mon 0000 00:00:00 [GMT]) (rfc822, rfc1123)
+ * Weekday, 00-Mon-00 00:00:00 [GMT] (rfc850, rfc1036)
+ * Wkd Mon 00 00:00:00 0000 [GMT] (ctime)
+ * 1*DIGIT (delta seconds)
+ *
+ */
+
+// Months and Weekdays.
+static const sal_Char *months[12] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static const sal_Char *wkdays[7] =
+{
+ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
+};
+
+/*
+ * GenerateDateField.
+ */
+BOOL INetRFC822Message::GenerateDateField (
+ const DateTime& rDateTime, UniString& rDateFieldW)
+{
+ // Check arguments.
+ if (!rDateTime.IsValid() ||
+ (rDateTime.GetSec() > 59) ||
+ (rDateTime.GetMin() > 59) ||
+ (rDateTime.GetHour() > 23) ) return FALSE;
+
+ // Prepare output string.
+ ByteString rDateField;
+
+ // Insert Date.
+ rDateField += wkdays[(USHORT)(rDateTime.GetDayOfWeek())];
+ rDateField += ", ";
+
+ USHORT nNum = rDateTime.GetDay();
+ if (nNum < 10) rDateField += '0';
+ rDateField += nNum;
+ rDateField += ' ';
+
+ rDateField += months[(USHORT)(rDateTime.GetMonth() - 1)];
+ rDateField += ' ';
+
+ rDateField += rDateTime.GetYear();
+ rDateField += ' ';
+
+ // Insert Time.
+ nNum = rDateTime.GetHour();
+ if (nNum < 10) rDateField += '0';
+ rDateField += nNum;
+ rDateField += ':';
+
+ nNum = rDateTime.GetMin();
+ if (nNum < 10) rDateField += '0';
+ rDateField += nNum;
+ rDateField += ':';
+
+ nNum = rDateTime.GetSec();
+ if (nNum < 10) rDateField += '0';
+ rDateField += nNum;
+ rDateField += " GMT";
+
+ // Done.
+ rDateFieldW = UniString (rDateField, RTL_TEXTENCODING_ASCII_US);
+ return TRUE;
+}
+
+/*
+ * ParseDateField and local helper functions.
+ */
+static USHORT ParseNumber (const ByteString& rStr, USHORT& nIndex)
+{
+ USHORT n = nIndex;
+ while ((n < rStr.Len()) && rtl_char_isDigit(rStr.GetChar(n))) n++;
+
+ ByteString aNum (rStr.Copy (nIndex, (n - nIndex)));
+ nIndex = n;
+
+ return (USHORT)(aNum.ToInt32());
+}
+
+static USHORT ParseMonth (const ByteString& rStr, USHORT& nIndex)
+{
+ USHORT n = nIndex;
+ while ((n < rStr.Len()) && rtl_char_isLetter(rStr.GetChar(n))) n++;
+
+ ByteString aMonth (rStr.Copy (nIndex, 3));
+ nIndex = n;
+
+ USHORT i;
+ for (i = 0; i < 12; i++)
+ if (aMonth.CompareIgnoreCaseToAscii (months[i]) == 0) break;
+ return (i + 1);
+}
+
+BOOL INetRFC822Message::ParseDateField (
+ const UniString& rDateFieldW, DateTime& rDateTime)
+{
+ ByteString rDateField (rDateFieldW, RTL_TEXTENCODING_ASCII_US);
+ if (rDateField.Len() == 0) return FALSE;
+
+ if (rDateField.Search (':') != STRING_NOTFOUND)
+ {
+ // Some DateTime format.
+ USHORT nIndex = 0;
+
+ // Skip over <Wkd> or <Weekday>, leading and trailing space.
+ while ((nIndex < rDateField.Len()) &&
+ (rDateField.GetChar(nIndex) == ' '))
+ nIndex++;
+
+ while (
+ (nIndex < rDateField.Len()) &&
+ (rtl_char_isLetter (rDateField.GetChar(nIndex)) ||
+ (rDateField.GetChar(nIndex) == ',') ))
+ nIndex++;
+
+ while ((nIndex < rDateField.Len()) &&
+ (rDateField.GetChar(nIndex) == ' '))
+ nIndex++;
+
+ if (rtl_char_isLetter (rDateField.GetChar(nIndex)))
+ {
+ // Format: ctime().
+ if ((rDateField.Len() - nIndex) < 20) return FALSE;
+
+ rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++;
+ rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++;
+
+ rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.Set100Sec (0);
+
+ USHORT nYear = ParseNumber (rDateField, nIndex);
+ if (nYear < 100) nYear += 1900;
+ rDateTime.SetYear (nYear);
+ }
+ else
+ {
+ // Format: RFC1036 or RFC1123.
+ if ((rDateField.Len() - nIndex) < 17) return FALSE;
+
+ rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++;
+
+ USHORT nYear = ParseNumber (rDateField, nIndex); nIndex++;
+ if (nYear < 100) nYear += 1900;
+ rDateTime.SetYear (nYear);
+
+ rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++;
+ rDateTime.Set100Sec (0);
+
+ if ((rDateField.GetChar(nIndex) == '+') ||
+ (rDateField.GetChar(nIndex) == '-') )
+ {
+ // Offset from GMT: "(+|-)HHMM".
+ BOOL bEast = (rDateField.GetChar(nIndex++) == '+');
+ USHORT nOffset = ParseNumber (rDateField, nIndex);
+ if (nOffset > 0)
+ {
+ Time aDiff;
+ aDiff.SetHour (nOffset / 100);
+ aDiff.SetMin (nOffset % 100);
+ aDiff.SetSec (0);
+ aDiff.Set100Sec (0);
+
+ if (bEast)
+ rDateTime -= aDiff;
+ else
+ rDateTime += aDiff;
+ }
+ }
+ }
+ }
+ else if (rDateField.IsNumericAscii())
+ {
+ // Format: delta seconds.
+ Time aDelta (0);
+ aDelta.SetTime (rDateField.ToInt32() * 100);
+
+ DateTime aNow;
+ aNow += aDelta;
+ aNow.ConvertToUTC();
+
+ rDateTime.SetDate (aNow.GetDate());
+ rDateTime.SetTime (aNow.GetTime());
+ }
+ else
+ {
+ // Junk.
+ return FALSE;
+ }
+
+ return (rDateTime.IsValid() &&
+ !((rDateTime.GetSec() > 59) ||
+ (rDateTime.GetMin() > 59) ||
+ (rDateTime.GetHour() > 23) ));
+}
+
+/*
+ * SetHeaderField.
+ * (Header Field Parser).
+ */
+ULONG INetRFC822Message::SetHeaderField (
+ const INetMessageHeader &rHeader, ULONG nNewIndex)
+{
+ ByteString aName (rHeader.GetName());
+ const sal_Char *pData = aName.GetBuffer();
+ const sal_Char *pStop = pData + aName.Len() + 1;
+ const sal_Char *check = "";
+
+ ULONG nIdx = LIST_APPEND;
+ int eState = INETMSG_RFC822_BEGIN;
+ int eOkState = INETMSG_RFC822_OK;
+
+ while (pData < pStop)
+ {
+ switch (eState)
+ {
+ case INETMSG_RFC822_BEGIN:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'b':
+ check = "cc";
+ nIdx = INETMSG_RFC822_BCC;
+ break;
+
+ case 'c':
+ eState = INETMSG_RFC822_LETTER_C;
+ break;
+
+ case 'd':
+ check = "ate";
+ nIdx = INETMSG_RFC822_DATE;
+ break;
+
+ case 'f':
+ check = "rom";
+ nIdx = INETMSG_RFC822_FROM;
+ break;
+
+ case 'i':
+ check = "n-reply-to";
+ nIdx = INETMSG_RFC822_IN_REPLY_TO;
+ break;
+
+ case 'k':
+ check = "eywords";
+ nIdx = INETMSG_RFC822_KEYWORDS;
+ break;
+
+ case 'm':
+ check = "essage-id";
+ nIdx = INETMSG_RFC822_MESSAGE_ID;
+ break;
+
+ case 'r':
+ check = "e";
+ eOkState = INETMSG_RFC822_TOKEN_RE;
+ break;
+
+ case 's':
+ eState = INETMSG_RFC822_LETTER_S;
+ break;
+
+ case 't':
+ check = "o";
+ nIdx = INETMSG_RFC822_TO;
+ break;
+
+ case 'x':
+ check = "-";
+ eOkState = INETMSG_RFC822_TOKEN_XMINUS;
+ break;
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_TOKEN_RE:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'f':
+ check = "erences";
+ nIdx = INETMSG_RFC822_REFERENCES;
+ break;
+
+ case 'p':
+ check = "ly-to";
+ nIdx = INETMSG_RFC822_REPLY_TO;
+ break;
+
+ case 't':
+ check = "urn-";
+ eOkState = INETMSG_RFC822_TOKEN_RETURNMINUS;
+ break;
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_TOKEN_RETURNMINUS:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'p':
+ check = "ath";
+ nIdx = INETMSG_RFC822_RETURN_PATH;
+ break;
+
+ case 'r':
+ check = "eceipt-to";
+ nIdx = INETMSG_RFC822_RETURN_RECEIPT_TO;
+ break;
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_TOKEN_XMINUS:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'm':
+ check = "ailer";
+ nIdx = INETMSG_RFC822_X_MAILER;
+ break;
+
+#if 0 /* NYI */
+ case 'p':
+ check = "riority";
+ eOkState = INETMSG_RFC822_X_PRIORITY;
+ break;
+#endif /* NYI */
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_LETTER_C:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'c':
+ check = "";
+ nIdx = INETMSG_RFC822_CC;
+ break;
+
+ case 'o':
+ check = "mments";
+ nIdx = INETMSG_RFC822_COMMENTS;
+ break;
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_LETTER_S:
+ eState = INETMSG_RFC822_CHECK;
+ eOkState = INETMSG_RFC822_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'e':
+ check = "nder";
+ nIdx = INETMSG_RFC822_SENDER;
+ break;
+
+ case 'u':
+ check = "bject";
+ nIdx = INETMSG_RFC822_SUBJECT;
+ break;
+
+ default:
+ eState = INETMSG_RFC822_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_RFC822_CHECK:
+ if (*check)
+ {
+ while (*pData && *check &&
+ (rtl_char_toLowerCase (*pData) == *check))
+ {
+ pData++;
+ check++;
+ }
+ }
+ else
+ {
+ check = pData;
+ }
+ eState = (*check == '\0') ? eOkState : INETMSG_RFC822_JUNK;
+ break;
+
+ case INETMSG_RFC822_OK:
+ pData = pStop;
+ SetHeaderField_Impl (
+ HEADERFIELD (HDR(nIdx), rHeader.GetValue()),
+ m_nIndex[nIdx]);
+ nNewIndex = m_nIndex[nIdx];
+ break;
+
+ default: // INETMSG_RFC822_JUNK
+ pData = pStop;
+ nNewIndex = INetMessage::SetHeaderField (rHeader, nNewIndex);
+ break;
+ }
+ }
+ return nNewIndex;
+}
+
+/*
+ * Specific Set-Methods.
+ */
+void INetRFC822Message::SetBCC (const UniString& rBCC)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_BCC), rBCC,
+ m_nIndex[INETMSG_RFC822_BCC]);
+}
+
+void INetRFC822Message::SetCC (const UniString& rCC)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_CC), rCC,
+ m_nIndex[INETMSG_RFC822_CC]);
+}
+
+void INetRFC822Message::SetComments (const UniString& rComments)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HDR(INETMSG_RFC822_COMMENTS), rComments,
+ m_nIndex[INETMSG_RFC822_COMMENTS]);
+}
+
+void INetRFC822Message::SetDate (const UniString& rDate)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_STRUCTURED,
+ HDR(INETMSG_RFC822_DATE), rDate,
+ m_nIndex[INETMSG_RFC822_DATE]);
+}
+
+void INetRFC822Message::SetFrom (const UniString& rFrom)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_FROM), rFrom,
+ m_nIndex[INETMSG_RFC822_FROM]);
+}
+
+void INetRFC822Message::SetInReplyTo (const UniString& rInReplyTo)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS, // ??? MESSAGE_ID ???
+ HDR(INETMSG_RFC822_IN_REPLY_TO), rInReplyTo,
+ m_nIndex[INETMSG_RFC822_IN_REPLY_TO]);
+}
+
+void INetRFC822Message::SetKeywords (const UniString& rKeywords)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_PHRASE,
+ HDR(INETMSG_RFC822_KEYWORDS), rKeywords,
+ m_nIndex[INETMSG_RFC822_KEYWORDS]);
+}
+
+void INetRFC822Message::SetMessageID (const UniString& rMessageID)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_MESSAGE_ID,
+ HDR(INETMSG_RFC822_MESSAGE_ID), rMessageID,
+ m_nIndex[INETMSG_RFC822_MESSAGE_ID]);
+}
+
+void INetRFC822Message::SetReferences (const UniString& rReferences)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_MESSAGE_ID,
+ HDR(INETMSG_RFC822_REFERENCES), rReferences,
+ m_nIndex[INETMSG_RFC822_REFERENCES]);
+}
+
+void INetRFC822Message::SetReplyTo (const UniString& rReplyTo)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_REPLY_TO), rReplyTo,
+ m_nIndex[INETMSG_RFC822_REPLY_TO]);
+}
+
+void INetRFC822Message::SetReturnPath (const UniString& rReturnPath)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_RETURN_PATH), rReturnPath,
+ m_nIndex[INETMSG_RFC822_RETURN_PATH]);
+}
+
+void INetRFC822Message::SetReturnReceiptTo (const UniString& rValue)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_RETURN_RECEIPT_TO), rValue,
+ m_nIndex[INETMSG_RFC822_RETURN_RECEIPT_TO]);
+}
+
+void INetRFC822Message::SetSender (const UniString& rSender)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_SENDER), rSender,
+ m_nIndex[INETMSG_RFC822_SENDER]);
+}
+
+void INetRFC822Message::SetSubject (const UniString& rSubject)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HDR(INETMSG_RFC822_SUBJECT), rSubject,
+ m_nIndex[INETMSG_RFC822_SUBJECT]);
+}
+
+void INetRFC822Message::SetTo (const UniString& rTo)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_ADDRESS,
+ HDR(INETMSG_RFC822_TO), rTo,
+ m_nIndex[INETMSG_RFC822_TO]);
+}
+
+void INetRFC822Message::SetXMailer (const UniString& rXMailer)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HDR(INETMSG_RFC822_X_MAILER), rXMailer,
+ m_nIndex[INETMSG_RFC822_X_MAILER]);
+}
+
+/*
+ * operator<<
+ */
+SvStream& INetRFC822Message::operator<< (SvStream& rStrm) const
+{
+ INetMessage::operator<< (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_RFC822_NUMHDR; i++)
+ rStrm << m_nIndex[i];
+
+ return rStrm;
+}
+
+/*
+ * operator>>
+ */
+SvStream& INetRFC822Message::operator>> (SvStream& rStrm)
+{
+ INetMessage::operator>> (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_RFC822_NUMHDR; i++)
+ rStrm >> m_nIndex[i];
+
+ return rStrm;
+}
+
+/*=======================================================================
+ *
+ * INetMIMEMessage Implementation.
+ *
+ *=====================================================================*/
+/*
+ * _ImplINetMIMEMessageHeaderData.
+ */
+static const ByteString _ImplINetMIMEMessageHeaderData[] =
+{
+ ByteString ("MIME-Version"),
+ ByteString ("Content-Description"),
+ ByteString ("Content-Disposition"),
+ ByteString ("Content-ID"),
+ ByteString ("Content-Type"),
+ ByteString ("Content-Transfer-Encoding")
+};
+
+#define MIMEHDR(n) _ImplINetMIMEMessageHeaderData[(n)]
+
+/*
+ * _ImplINetMIMEMessageHeaderState.
+ */
+enum _ImplINetMIMEMessageHeaderState
+{
+ INETMSG_MIME_BEGIN,
+ INETMSG_MIME_CHECK,
+ INETMSG_MIME_OK,
+ INETMSG_MIME_JUNK,
+
+ INETMSG_MIME_TOKEN_CONTENT,
+ INETMSG_MIME_TOKEN_CONTENT_D,
+ INETMSG_MIME_TOKEN_CONTENT_T
+};
+
+/*
+ * INetMIMEMessage.
+ */
+INetMIMEMessage::INetMIMEMessage (void)
+ : INetRFC822Message (),
+ nNumChildren (0),
+ pParent (NULL),
+ bHeaderParsed (FALSE)
+{
+ for (USHORT i = 0; i < INETMSG_MIME_NUMHDR; i++)
+ m_nIndex[i] = LIST_ENTRY_NOTFOUND;
+}
+
+INetMIMEMessage::INetMIMEMessage (const INetMIMEMessage& rMsg)
+ : INetRFC822Message (rMsg)
+{
+ // Copy.
+ CopyImp (rMsg);
+}
+
+/*
+ * operator=
+ */
+INetMIMEMessage& INetMIMEMessage::operator= (
+ const INetMIMEMessage& rMsg)
+{
+ if (this != &rMsg)
+ {
+ // Assign base.
+ INetRFC822Message::operator= (rMsg);
+
+ // Cleanup.
+ CleanupImp();
+
+ // Copy.
+ CopyImp (rMsg);
+ }
+ return *this;
+}
+
+/*
+ * ~INetMIMEMessage.
+ */
+INetMIMEMessage::~INetMIMEMessage (void)
+{
+ // Cleanup.
+ CleanupImp();
+}
+
+/*
+ * CleanupImp.
+ */
+void INetMIMEMessage::CleanupImp (void)
+{
+ INetMIMEMessage *pChild = NULL;
+ while ((pChild = (INetMIMEMessage *)(aChildren.Remove())) != NULL)
+ if (pChild->pParent == this) delete pChild;
+}
+
+/*
+ * CopyImp.
+ */
+void INetMIMEMessage::CopyImp (const INetMIMEMessage& rMsg)
+{
+ bHeaderParsed = rMsg.bHeaderParsed;
+
+ USHORT i;
+ for (i = 0; i < INETMSG_MIME_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+
+ m_aBoundary = rMsg.m_aBoundary;
+ nNumChildren = rMsg.nNumChildren;
+
+ for (i = 0; i < rMsg.aChildren.Count(); i++)
+ {
+ INetMIMEMessage *pChild =
+ (INetMIMEMessage *)(rMsg.aChildren.GetObject (i));
+
+ if (pChild->pParent == &rMsg)
+ {
+ pChild = pChild->CreateMessage (*pChild);
+ pChild->pParent = this;
+ }
+ aChildren.Insert (pChild, LIST_APPEND);
+ }
+}
+
+/*
+ * CreateMessage.
+ */
+INetMIMEMessage *INetMIMEMessage::CreateMessage (
+ const INetMIMEMessage& rMsg) const
+{
+ return (new INetMIMEMessage (rMsg));
+}
+
+/*
+ * SetHeaderField.
+ * (Header Field Parser).
+ */
+ULONG INetMIMEMessage::SetHeaderField (
+ const INetMessageHeader &rHeader, ULONG nNewIndex)
+{
+ ByteString aName (rHeader.GetName());
+ const sal_Char *pData = aName.GetBuffer();
+ const sal_Char *pStop = pData + aName.Len() + 1;
+ const sal_Char *check = "";
+
+ ULONG nIdx = LIST_APPEND;
+ int eState = INETMSG_MIME_BEGIN;
+ int eOkState = INETMSG_MIME_OK;
+
+ while (pData < pStop)
+ {
+ switch (eState)
+ {
+ case INETMSG_MIME_BEGIN:
+ eState = INETMSG_MIME_CHECK;
+ eOkState = INETMSG_MIME_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'c':
+ check = "ontent-";
+ eOkState = INETMSG_MIME_TOKEN_CONTENT;
+ break;
+
+ case 'm':
+ check = "ime-version";
+ nIdx = INETMSG_MIME_VERSION;
+ break;
+
+ default:
+ eState = INETMSG_MIME_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_MIME_TOKEN_CONTENT:
+ eState = INETMSG_MIME_CHECK;
+ eOkState = INETMSG_MIME_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'd':
+ eState = INETMSG_MIME_TOKEN_CONTENT_D;
+ break;
+
+ case 'i':
+ check = "d";
+ nIdx = INETMSG_MIME_CONTENT_ID;
+ break;
+
+ case 't':
+ eState = INETMSG_MIME_TOKEN_CONTENT_T;
+ break;
+
+ default:
+ eState = INETMSG_MIME_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_MIME_TOKEN_CONTENT_D:
+ eState = INETMSG_MIME_CHECK;
+ eOkState = INETMSG_MIME_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'e':
+ check = "scription";
+ nIdx = INETMSG_MIME_CONTENT_DESCRIPTION;
+ break;
+
+ case 'i':
+ check = "sposition";
+ nIdx = INETMSG_MIME_CONTENT_DISPOSITION;
+ break;
+
+ default:
+ eState = INETMSG_MIME_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_MIME_TOKEN_CONTENT_T:
+ eState = INETMSG_MIME_CHECK;
+ eOkState = INETMSG_MIME_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'r':
+ check = "ansfer-encoding";
+ nIdx = INETMSG_MIME_CONTENT_TRANSFER_ENCODING;
+ break;
+
+ case 'y':
+ check = "pe";
+ nIdx = INETMSG_MIME_CONTENT_TYPE;
+ break;
+
+ default:
+ eState = INETMSG_MIME_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_MIME_CHECK:
+ if (*check)
+ {
+ while (*pData && *check &&
+ (rtl_char_toLowerCase (*pData) == *check))
+ {
+ pData++;
+ check++;
+ }
+ }
+ else
+ {
+ check = pData;
+ }
+ eState = (*check == '\0') ? eOkState : INETMSG_MIME_JUNK;
+ break;
+
+ case INETMSG_MIME_OK:
+ pData = pStop;
+ SetHeaderField_Impl (
+ HEADERFIELD (MIMEHDR(nIdx), rHeader.GetValue()),
+ m_nIndex[nIdx]);
+ nNewIndex = m_nIndex[nIdx];
+ break;
+
+ default: // INETMSG_MIME_JUNK
+ pData = pStop;
+ nNewIndex = INetRFC822Message::SetHeaderField (
+ rHeader, nNewIndex);
+ break;
+ }
+ }
+ return nNewIndex;
+}
+
+/*
+ * Specific Set-Methods.
+ */
+void INetMIMEMessage::SetMIMEVersion (const UniString& rVersion)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_VERSION), rVersion,
+ m_nIndex[INETMSG_MIME_VERSION]);
+}
+
+void INetMIMEMessage::SetContentDescription (const String& rDescription)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_CONTENT_DESCRIPTION), rDescription,
+ m_nIndex[INETMSG_MIME_CONTENT_DESCRIPTION]);
+}
+
+void INetMIMEMessage::SetContentDisposition (const String& rDisposition)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_CONTENT_DISPOSITION), rDisposition,
+ m_nIndex[INETMSG_MIME_CONTENT_DISPOSITION]);
+}
+
+void INetMIMEMessage::SetContentID (const String& rID)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_CONTENT_ID), rID,
+ m_nIndex[INETMSG_MIME_CONTENT_ID]);
+}
+
+void INetMIMEMessage::SetContentType (const String& rType)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_CONTENT_TYPE), rType,
+ m_nIndex[INETMSG_MIME_CONTENT_TYPE]);
+}
+
+void INetMIMEMessage::SetContentTransferEncoding (
+ const String& rEncoding)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ MIMEHDR(INETMSG_MIME_CONTENT_TRANSFER_ENCODING), rEncoding,
+ m_nIndex[INETMSG_MIME_CONTENT_TRANSFER_ENCODING]);
+}
+
+/*
+ * GetDefaultContentType.
+ */
+void INetMIMEMessage::GetDefaultContentType (String& rContentType)
+{
+ String aDefaultCT (
+ "text/plain; charset=us-ascii", RTL_TEXTENCODING_ASCII_US);
+ if (pParent == NULL)
+ {
+ rContentType = aDefaultCT;
+ }
+ else
+ {
+ String aParentCT (pParent->GetContentType());
+ if (aParentCT.Len() == 0)
+ pParent->GetDefaultContentType (aParentCT);
+
+ if (aParentCT.CompareIgnoreCaseToAscii ("message/", 8) == 0)
+ {
+ rContentType = aDefaultCT;
+ }
+ else if (aParentCT.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
+ {
+ if (aParentCT.CompareIgnoreCaseToAscii ("multipart/digest") == 0)
+ rContentType.AssignAscii ("message/rfc822");
+ else
+ rContentType = aDefaultCT;
+ }
+ else
+ {
+ rContentType = aDefaultCT;
+ }
+ }
+}
+
+/*
+ * EnableAttachChild.
+ */
+BOOL INetMIMEMessage::EnableAttachChild (INetMessageContainerType eType)
+{
+ // Check context.
+ if (IsContainer())
+ return FALSE;
+
+ // Setup Content-Type header field.
+ ByteString aContentType;
+ switch (eType)
+ {
+ case INETMSG_MESSAGE_RFC822:
+ aContentType = "message/rfc822";
+ break;
+
+ case INETMSG_MULTIPART_ALTERNATIVE:
+ aContentType = "multipart/alternative";
+ break;
+
+ case INETMSG_MULTIPART_DIGEST:
+ aContentType = "multipart/digest";
+ break;
+
+ case INETMSG_MULTIPART_PARALLEL:
+ aContentType = "multipart/parallel";
+ break;
+
+ case INETMSG_MULTIPART_RELATED:
+ aContentType = "multipart/related";
+ break;
+
+ case INETMSG_MULTIPART_FORM_DATA:
+ aContentType = "multipart/form-data";
+ break;
+
+ default:
+ aContentType = "multipart/mixed";
+ break;
+ }
+
+ // Setup boundary for multipart types.
+ if (aContentType.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
+ {
+ // Generate a unique boundary from current time.
+ sal_Char sTail[16 + 1];
+ Time aCurTime;
+ sprintf (sTail, "%08X%08X", aCurTime.GetTime(), (ULONG)this);
+ m_aBoundary = "------------_4D48";
+ m_aBoundary += sTail;
+
+ // Append boundary as ContentType parameter.
+ aContentType += "; boundary=";
+ aContentType += m_aBoundary;
+ }
+
+ // Set header fields.
+ SetMIMEVersion (String (CONSTASCII_STRINGPARAM("1.0")));
+ SetContentType (String (aContentType, RTL_TEXTENCODING_ASCII_US));
+ SetContentTransferEncoding (String (CONSTASCII_STRINGPARAM("7bit")));
+
+ // Done.
+ return TRUE;
+}
+
+/*
+ * AttachChild.
+ */
+BOOL INetMIMEMessage::AttachChild (
+ INetMIMEMessage& rChildMsg, BOOL bOwner)
+{
+ if (IsContainer() /*&& rChildMsg.GetContentType().Len() */)
+ {
+ if (bOwner) rChildMsg.pParent = this;
+ aChildren.Insert (&rChildMsg, LIST_APPEND);
+ nNumChildren = aChildren.Count();
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * DetachChild.
+ */
+BOOL INetMIMEMessage::DetachChild (
+ ULONG nIndex, INetMIMEMessage& rChildMsg) const
+{
+ if (IsContainer())
+ {
+ // Check document stream.
+ if (GetDocumentLB() == NULL) return FALSE;
+ SvStream *pDocStrm = new SvStream (GetDocumentLB());
+
+ // Initialize message buffer.
+ char pMsgBuffer[1024];
+ char *pMsgRead, *pMsgWrite;
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ // Initialize message parser stream.
+ INetMIMEMessageStream *pMsgStrm = NULL;
+
+ // Check for "multipart/uvw" or "message/xyz".
+ if (IsMultipart())
+ {
+ // Multipart message body. Initialize multipart delimiters.
+ ByteString aDelim ("--");
+ aDelim += GetMultipartBoundary();
+ ByteString aClose = aDelim;
+ aClose += "--";
+
+ // Initialize line buffer.
+ SvMemoryStream aLineBuf;
+
+ // Initialize control variables.
+ INetMessageStreamState eState = INETMSG_EOL_SCR;
+ int nCurIndex = -1;
+
+ // Go!
+ while (nCurIndex < (int)(nIndex + 1))
+ {
+ if ((pMsgRead - pMsgWrite) > 0)
+ {
+ // Bytes still in buffer.
+ if (eState == INETMSG_EOL_FCR)
+ {
+ // Check for 2nd line break character.
+ if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n'))
+ aLineBuf << *pMsgWrite++;
+
+ // Check current index.
+ if (nCurIndex == (int)nIndex)
+ {
+ // Found requested part.
+ if (pMsgStrm == NULL)
+ {
+ // Create message parser stream.
+ pMsgStrm = new INetMIMEMessageStream;
+ pMsgStrm->SetTargetMessage (&rChildMsg);
+ }
+
+ // Put message down-stream.
+ int status = pMsgStrm->Write (
+ (const sal_Char *) aLineBuf.GetData(), aLineBuf.Tell());
+ if (status != INETSTREAM_STATUS_OK)
+ {
+ // Cleanup.
+ delete pDocStrm;
+ delete pMsgStrm;
+
+ // Finish.
+ return (!(status == INETSTREAM_STATUS_OK));
+ }
+ }
+
+ // Reset to <Begin-of-Line>.
+ aLineBuf.Seek (STREAM_SEEK_TO_BEGIN);
+ eState = INETMSG_EOL_SCR;
+ }
+ else if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n'))
+ {
+ /*
+ * Found any line break character.
+ * Compare buffered line with part/close delimiter.
+ * Increment current part index upon match.
+ */
+ USHORT nLen = (USHORT)(aLineBuf.Tell() & 0xffff);
+ if (nLen == aDelim.Len())
+ {
+ if (aDelim.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen)
+ == COMPARE_EQUAL) nCurIndex++;
+ }
+ else if (nLen == aClose.Len())
+ {
+ if (aClose.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen)
+ == COMPARE_EQUAL) nCurIndex++;
+ }
+ aLineBuf << *pMsgWrite++;
+ eState = INETMSG_EOL_FCR;
+ }
+ else
+ {
+ // Insert into line buffer.
+ aLineBuf << *pMsgWrite;
+ }
+ }
+ else
+ {
+ // Buffer empty. Reset to <Begin-of-Buffer>.
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ // Read document stream.
+ ULONG nRead = pDocStrm->Read (
+ pMsgBuffer, sizeof (pMsgBuffer));
+ if (nRead > 0)
+ {
+ // Set read pointer.
+ pMsgRead += nRead;
+ }
+ else
+ {
+ // Premature end.
+ if (pMsgStrm)
+ {
+ // Assume end of requested part.
+ nCurIndex++;
+ }
+ else
+ {
+ // Requested part not found.
+ delete pDocStrm;
+ return FALSE;
+ }
+ }
+ }
+ } // while (nCurIndex < (nIndex + 1))
+ }
+ else
+ {
+ // Encapsulated message body. Create message parser stream.
+ pMsgStrm = new INetMIMEMessageStream;
+ pMsgStrm->SetTargetMessage (&rChildMsg);
+
+ // Initialize control variables.
+ INetMessageStreamState eState = INETMSG_EOL_BEGIN;
+
+ // Go.
+ while (eState == INETMSG_EOL_BEGIN)
+ {
+ if ((pMsgRead - pMsgWrite) > 0)
+ {
+ // Bytes still in buffer. Put message down-stream.
+ int status = pMsgStrm->Write (
+ pMsgBuffer, (pMsgRead - pMsgWrite), NULL);
+ if (status != INETSTREAM_STATUS_OK)
+ {
+ // Cleanup.
+ delete pDocStrm;
+ delete pMsgStrm;
+
+ // Finish.
+ return (!(status == INETSTREAM_STATUS_ERROR));
+ }
+ pMsgWrite = pMsgBuffer + (pMsgRead - pMsgWrite);
+ }
+ else
+ {
+ // Buffer empty. Reset to <Begin-of-Buffer>.
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ // Read document stream.
+ ULONG nRead = pDocStrm->Read (
+ pMsgBuffer, sizeof (pMsgBuffer));
+ if (nRead > 0)
+ {
+ // Set read pointer.
+ pMsgRead += nRead;
+ }
+ else
+ {
+ // Mark we're done.
+ eState = INETMSG_EOL_DONE;
+ }
+ }
+ } // while (eState == INETMSG_EOL_BEGIN)
+ }
+
+ // Done.
+ if (pDocStrm) delete pDocStrm;
+ if (pMsgStrm) delete pMsgStrm;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * operator<<
+ */
+SvStream& INetMIMEMessage::operator<< (SvStream& rStrm) const
+{
+ INetRFC822Message::operator<< (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_MIME_NUMHDR; i++)
+ rStrm << m_nIndex[i];
+
+#ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
+ rStrm << m_aBoundary;
+#else
+ rStrm.WriteByteString (m_aBoundary);
+#endif
+ rStrm << nNumChildren;
+
+ return rStrm;
+}
+
+/*
+ * operator>>
+ */
+SvStream& INetMIMEMessage::operator>> (SvStream& rStrm)
+{
+ INetRFC822Message::operator>> (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_MIME_NUMHDR; i++)
+ rStrm >> m_nIndex[i];
+
+#ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
+ rStrm >> m_aBoundary;
+#else
+ rStrm.ReadByteString (m_aBoundary);
+#endif
+ rStrm >> nNumChildren;
+
+ return rStrm;
+}
+
+/*=======================================================================
+ *
+ * INetNewsMessage Implementation.
+ *
+ *=====================================================================*/
+/*
+ * _ImplINetNewsMessageHeaderData.
+ */
+static const ByteString _ImplINetNewsMessageHeaderData[] =
+{
+ ByteString ("Approved"),
+ ByteString ("Control"),
+ ByteString ("Distribution"),
+ ByteString ("Expires"),
+ ByteString ("Followup-To"),
+ ByteString ("Lines"),
+ ByteString ("Newsgroups"),
+ ByteString ("Organization"),
+ ByteString ("Path"),
+ ByteString ("Summary"),
+ ByteString ("Xref"),
+ ByteString ("X-Newsreader")
+};
+
+#define NEWSHDR(n) _ImplINetNewsMessageHeaderData[(n)]
+
+/*
+ * _ImplINetNewsMessageHeaderState.
+ */
+enum _ImplINetNewsMessageHeaderState
+{
+ INETMSG_NEWS_BEGIN,
+ INETMSG_NEWS_CHECK,
+ INETMSG_NEWS_OK,
+ INETMSG_NEWS_JUNK,
+
+ INETMSG_NEWS_LETTER_X
+};
+
+/*
+ * INetNewsMessage.
+ */
+INetNewsMessage::INetNewsMessage (void)
+ : INetMIMEMessage ()
+{
+ for (USHORT i = 0; i < INETMSG_NEWS_NUMHDR; i++)
+ m_nIndex[i] = LIST_ENTRY_NOTFOUND;
+}
+
+INetNewsMessage::INetNewsMessage (const INetNewsMessage& rMsg)
+ : INetMIMEMessage (rMsg)
+{
+ for (USHORT i = 0; i < INETMSG_NEWS_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+}
+
+/*
+ * operator=
+ */
+INetNewsMessage& INetNewsMessage::operator= (const INetNewsMessage& rMsg)
+{
+ if (this != &rMsg)
+ {
+ // Assign base.
+ INetMIMEMessage::operator= (rMsg);
+
+ // Cleanup and copy.
+ for (USHORT i = 0; i < INETMSG_NEWS_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+ }
+ return *this;
+}
+
+/*
+ * ~INetNewsMessage.
+ */
+INetNewsMessage::~INetNewsMessage (void)
+{
+}
+
+/*
+ * CreateMessage.
+ */
+INetNewsMessage *INetNewsMessage::CreateMessage (
+ const INetNewsMessage& rMsg) const
+{
+ return (new INetNewsMessage (rMsg));
+}
+
+/*
+ * SetHeaderField.
+ * (Header Field Parser).
+ */
+ULONG INetNewsMessage::SetHeaderField (
+ const INetMessageHeader &rHeader, ULONG nNewIndex)
+{
+ ByteString aName (rHeader.GetName());
+ const sal_Char *pData = aName.GetBuffer();
+ const sal_Char *pStop = pData + aName.Len() + 1;
+ const sal_Char *check = "";
+
+ ULONG nIdx = LIST_APPEND;
+ int eState = INETMSG_NEWS_BEGIN;
+ int eOkState = INETMSG_NEWS_OK;
+
+ while (pData < pStop)
+ {
+ switch (eState)
+ {
+ case INETMSG_NEWS_BEGIN:
+ eState = INETMSG_NEWS_CHECK;
+ eOkState = INETMSG_NEWS_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'a':
+ check = "pproved";
+ nIdx = INETMSG_NEWS_APPROVED;
+ break;
+
+ case 'c':
+ check = "ontrol";
+ nIdx = INETMSG_NEWS_CONTROL;
+ break;
+
+ case 'd':
+ check = "istribution";
+ nIdx = INETMSG_NEWS_DISTRIBUTION;
+ break;
+
+ case 'e':
+ check = "xpires";
+ nIdx = INETMSG_NEWS_EXPIRES;
+ break;
+
+ case 'f':
+ check = "ollowup-to";
+ nIdx = INETMSG_NEWS_FOLLOWUP_TO;
+ break;
+
+ case 'l':
+ check = "ines";
+ nIdx = INETMSG_NEWS_LINES;
+ break;
+
+ case 'n':
+ check = "ewsgroups";
+ nIdx = INETMSG_NEWS_NEWSGROUPS;
+ break;
+
+ case 'o':
+ check = "rganization";
+ nIdx = INETMSG_NEWS_ORGANIZATION;
+ break;
+
+ case 'p':
+ check = "ath";
+ nIdx = INETMSG_NEWS_PATH;
+ break;
+
+ case 's':
+ check = "ummary";
+ nIdx = INETMSG_NEWS_SUMMARY;
+ break;
+
+ case 'x':
+ eState = INETMSG_NEWS_LETTER_X;
+ break;
+
+ default:
+ eState = INETMSG_NEWS_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_NEWS_LETTER_X:
+ eState = INETMSG_NEWS_CHECK;
+ eOkState = INETMSG_NEWS_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'r':
+ check = "ef";
+ nIdx = INETMSG_NEWS_XREF;
+ break;
+
+ case '-':
+ check = "newsreader";
+ nIdx = INETMSG_NEWS_X_NEWSREADER;
+ break;
+
+ default:
+ eState = INETMSG_NEWS_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_NEWS_CHECK:
+ if (*check)
+ {
+ while (*pData && *check &&
+ (rtl_char_toLowerCase (*pData) == *check))
+ {
+ pData++;
+ check++;
+ }
+ }
+ else
+ {
+ check = pData;
+ }
+ eState = (*check == '\0') ? eOkState : INETMSG_NEWS_JUNK;
+ break;
+
+ case INETMSG_NEWS_OK:
+ pData = pStop;
+ SetHeaderField_Impl (
+ HEADERFIELD (NEWSHDR(nIdx), rHeader.GetValue()),
+ m_nIndex[nIdx]);
+ nNewIndex = m_nIndex[nIdx];
+ break;
+
+ default: // INETMSG_NEWS_JUNK
+ pData = pStop;
+ nNewIndex = INetMIMEMessage::SetHeaderField (
+ rHeader, nNewIndex);
+ break;
+ }
+ }
+ return nNewIndex;
+}
+
+/*
+ * Specific Set-Methods.
+ */
+void INetNewsMessage::SetApproved (const String& rApproved)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_APPROVED), rApproved,
+ m_nIndex[INETMSG_NEWS_APPROVED]);
+}
+
+void INetNewsMessage::SetControl (const String& rControl)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_CONTROL), rControl,
+ m_nIndex[INETMSG_NEWS_CONTROL]);
+}
+
+void INetNewsMessage::SetDistribution (const String& rDistribution)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_DISTRIBUTION), rDistribution,
+ m_nIndex[INETMSG_NEWS_DISTRIBUTION]);
+}
+
+void INetNewsMessage::SetExpires (const String& rExpires)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_EXPIRES), rExpires,
+ m_nIndex[INETMSG_NEWS_EXPIRES]);
+}
+
+void INetNewsMessage::SetFollowupTo (const String& rFollowupTo)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_FOLLOWUP_TO), rFollowupTo,
+ m_nIndex[INETMSG_NEWS_FOLLOWUP_TO]);
+}
+
+void INetNewsMessage::SetLines (const String& rLines)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_LINES), rLines,
+ m_nIndex[INETMSG_NEWS_LINES]);
+}
+
+void INetNewsMessage::SetNewsgroups (const String& rNewsgroups)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_NEWSGROUPS), rNewsgroups,
+ m_nIndex[INETMSG_NEWS_NEWSGROUPS]);
+}
+
+void INetNewsMessage::SetOrganization (const String& rOrganization)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_ORGANIZATION), rOrganization,
+ m_nIndex[INETMSG_NEWS_ORGANIZATION]);
+}
+
+void INetNewsMessage::SetPath (const String& rPath)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_PATH), rPath,
+ m_nIndex[INETMSG_NEWS_PATH]);
+}
+
+void INetNewsMessage::SetSummary (const String& rSummary)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_SUMMARY), rSummary,
+ m_nIndex[INETMSG_NEWS_SUMMARY]);
+}
+
+void INetNewsMessage::SetXref (const String& rXref)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_XREF), rXref,
+ m_nIndex[INETMSG_NEWS_XREF]);
+}
+
+void INetNewsMessage::SetXNewsreader (const String& rXNewsreader)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ NEWSHDR(INETMSG_NEWS_X_NEWSREADER), rXNewsreader,
+ m_nIndex[INETMSG_NEWS_X_NEWSREADER]);
+}
+
+/*
+ * operator<<
+ */
+SvStream& INetNewsMessage::operator<< (SvStream& rStrm) const
+{
+ INetMIMEMessage::operator<< (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_NEWS_NUMHDR; i++)
+ rStrm << m_nIndex[i];
+
+ return rStrm;
+}
+
+/*
+ * operator>>
+ */
+SvStream& INetNewsMessage::operator>> (SvStream& rStrm)
+{
+ INetMIMEMessage::operator>> (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_NEWS_NUMHDR; i++)
+ rStrm >> m_nIndex[i];
+
+ return rStrm;
+}
+
+/*=======================================================================
+ *
+ * INetHTTPMessage Implementation.
+ *
+ *=====================================================================*/
+/*
+ * _ImplINetHTTPMessageHeaderData.
+ */
+static const ByteString _ImplINetHTTPMessageHeaderData[] =
+{
+ ByteString ("Accept"),
+ ByteString ("Accept-Charset"),
+ ByteString ("Accept-Encoding"),
+ ByteString ("Accept-Language"),
+ ByteString ("Allow"),
+ ByteString ("Authorization"),
+ ByteString ("Cache-Control"),
+ ByteString ("Connection"),
+ ByteString ("Content-Encoding"),
+ ByteString ("Content-Language"),
+ ByteString ("Content-Length"),
+ ByteString ("Content-MD5"),
+ ByteString ("Content-Range"),
+ ByteString ("Content-Version"),
+ ByteString ("Cookie"),
+ ByteString ("Derived-From"),
+ ByteString ("Expires"),
+ ByteString ("Forwarded"),
+ ByteString ("Host"),
+ ByteString ("If-Modified-Since"),
+ ByteString ("Keep-Alive"),
+ ByteString ("Last-Modified"),
+ ByteString ("Link"),
+ ByteString ("Location"),
+ ByteString ("Proxy-Authenticate"),
+ ByteString ("Proxy-Authorization"),
+ ByteString ("Pragma"),
+ ByteString ("Public"),
+ ByteString ("Range"),
+ ByteString ("Referer"),
+ ByteString ("Retry-After"),
+ ByteString ("Server"),
+ ByteString ("Title"),
+ ByteString ("Transfer-Encoding"),
+ ByteString ("Unless"),
+ ByteString ("Upgrade"),
+ ByteString ("URI"),
+ ByteString ("User-Agent"),
+ ByteString ("WWW-Authenticate")
+};
+
+#define HTTPHDR(n) _ImplINetHTTPMessageHeaderData[(n)]
+
+/*
+ * _ImplINetHTTPMessageHeaderState.
+ */
+enum _ImplINetHTTPMessageHeaderState
+{
+ INETMSG_HTTP_BEGIN,
+ INETMSG_HTTP_CHECK,
+ INETMSG_HTTP_OK,
+ INETMSG_HTTP_JUNK,
+
+ INETMSG_HTTP_LETTER_A,
+ INETMSG_HTTP_LETTER_C,
+ INETMSG_HTTP_LETTER_L,
+ INETMSG_HTTP_LETTER_P,
+ INETMSG_HTTP_LETTER_R,
+ INETMSG_HTTP_LETTER_T,
+ INETMSG_HTTP_LETTER_U,
+ INETMSG_HTTP_TOKEN_CON,
+ INETMSG_HTTP_CONTENT,
+ INETMSG_HTTP_PROXY_AUTH
+};
+
+/*
+ * INetHTTPMessage.
+ */
+INetHTTPMessage::INetHTTPMessage (void)
+ : INetMIMEMessage ()
+{
+ for (USHORT i = 0; i < INETMSG_HTTP_NUMHDR; i++)
+ m_nIndex[i] = LIST_ENTRY_NOTFOUND;
+}
+
+INetHTTPMessage::INetHTTPMessage (const INetHTTPMessage& rMsg)
+ : INetMIMEMessage (rMsg)
+{
+ for (USHORT i = 0; i < INETMSG_HTTP_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+}
+
+/*
+ * operator=
+ */
+INetHTTPMessage& INetHTTPMessage::operator= (const INetHTTPMessage& rMsg)
+{
+ if (this != &rMsg)
+ {
+ // Assign base.
+ INetMIMEMessage::operator= (rMsg);
+
+ // Cleanup and copy.
+ for (USHORT i = 0; i < INETMSG_HTTP_NUMHDR; i++)
+ m_nIndex[i] = rMsg.m_nIndex[i];
+ }
+ return *this;
+}
+
+/*
+ * ~INetHTTPMessage.
+ */
+INetHTTPMessage::~INetHTTPMessage (void)
+{
+}
+
+/*
+ * CreateMessage.
+ */
+INetHTTPMessage *INetHTTPMessage::CreateMessage (
+ const INetHTTPMessage& rMsg) const
+{
+ return (new INetHTTPMessage (rMsg));
+}
+
+/*
+ * SetHeaderField.
+ * (Header Field Parser).
+ */
+ULONG INetHTTPMessage::SetHeaderField (
+ const INetMessageHeader &rHeader, ULONG nNewIndex)
+{
+ ByteString aName (rHeader.GetName());
+ const sal_Char *pData = aName.GetBuffer();
+ const sal_Char *pStop = pData + aName.Len() + 1;
+ const sal_Char *check = "";
+
+ ULONG nIdx = LIST_APPEND;
+ int eState = INETMSG_HTTP_BEGIN;
+ int eOkState = INETMSG_HTTP_OK;
+
+ while (pData < pStop)
+ {
+ switch (eState)
+ {
+ case INETMSG_HTTP_BEGIN:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'a':
+ eState = INETMSG_HTTP_LETTER_A;
+ break;
+
+ case 'c':
+ eState = INETMSG_HTTP_LETTER_C;
+ break;
+
+ case 'd':
+ check = "erived-from";
+ nIdx = INETMSG_HTTP_DERIVED_FROM;
+ break;
+
+ case 'e':
+ check = "xpires";
+ nIdx = INETMSG_HTTP_EXPIRES;
+ break;
+
+ case 'f':
+ check = "orwarded";
+ nIdx = INETMSG_HTTP_FORWARDED;
+ break;
+
+ case 'h':
+ check = "ost";
+ nIdx = INETMSG_HTTP_HOST;
+ break;
+
+ case 'i':
+ check = "f-modified-since";
+ nIdx = INETMSG_HTTP_IF_MODIFIED_SINCE;
+ break;
+
+ case 'k':
+ check = "eep-alive";
+ nIdx = INETMSG_HTTP_KEEP_ALIVE;
+ break;
+
+ case 'l':
+ eState = INETMSG_HTTP_LETTER_L;
+ break;
+
+ case 'p':
+ eState = INETMSG_HTTP_LETTER_P;
+ break;
+
+ case 'r':
+ eState = INETMSG_HTTP_LETTER_R;
+ break;
+
+ case 's':
+ check = "erver";
+ nIdx = INETMSG_HTTP_SERVER;
+ break;
+
+ case 't':
+ eState = INETMSG_HTTP_LETTER_T;
+ break;
+
+ case 'u':
+ eState = INETMSG_HTTP_LETTER_U;
+ break;
+
+ case 'w':
+ check = "ww-authenticate";
+ nIdx = INETMSG_HTTP_WWW_AUTHENTICATE;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_A:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'c':
+ if (INetMIME::equalIgnoreCase (
+ pData, pData + 14, "ccept-language"))
+ {
+ nIdx = INETMSG_HTTP_ACCEPT_LANGUAGE;
+ pData += 14;
+ }
+ else if (INetMIME::equalIgnoreCase (
+ pData, pData + 14, "ccept-encoding"))
+ {
+ nIdx = INETMSG_HTTP_ACCEPT_ENCODING;
+ pData += 14;
+ }
+ else if (INetMIME::equalIgnoreCase (
+ pData, pData + 13, "ccept-charset"))
+ {
+ nIdx = INETMSG_HTTP_ACCEPT_CHARSET;
+ pData += 13;
+ }
+ else if (INetMIME::equalIgnoreCase (
+ pData, pData + 5, "ccept"))
+ {
+ nIdx = INETMSG_HTTP_ACCEPT;
+ pData += 5;
+ }
+ else
+ {
+ eState = INETMSG_HTTP_JUNK;
+ }
+ break;
+
+ case 'l':
+ check = "low";
+ nIdx = INETMSG_HTTP_ALLOW;
+ break;
+
+ case 'u':
+ check = "thorization";
+ nIdx = INETMSG_HTTP_AUTHORIZATION;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_C:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'a':
+ check = "che-control";
+ nIdx = INETMSG_HTTP_CACHE_CONTROL;
+ break;
+
+ case 'o':
+ if (rtl_char_toLowerCase (*(pData + 1)) == 'n')
+ {
+ eState = INETMSG_HTTP_TOKEN_CON;
+ }
+ else if (rtl_char_toLowerCase (*(pData + 1)) == 'o')
+ {
+ check = "kie";
+ nIdx = INETMSG_HTTP_COOKIE;
+ }
+ else
+ {
+ eState = INETMSG_HTTP_JUNK;
+ }
+ pData++;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_L:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'a':
+ check = "st-modified";
+ nIdx = INETMSG_HTTP_LAST_MODIFIED;
+ break;
+
+ case 'i':
+ check = "nk";
+ nIdx = INETMSG_HTTP_LINK;
+ break;
+
+ case 'o':
+ check = "cation";
+ nIdx = INETMSG_HTTP_LOCATION;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_P:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'r':
+ switch (rtl_char_toLowerCase (*(pData + 1)))
+ {
+ case 'a':
+ check = "gma";
+ nIdx = INETMSG_HTTP_PRAGMA;
+ break;
+
+ case 'o':
+ check = "xy-auth";
+ eOkState = INETMSG_HTTP_PROXY_AUTH;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case 'u':
+ check = "blic";
+ nIdx = INETMSG_HTTP_PUBLIC;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_R:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'a':
+ check = "nge";
+ nIdx = INETMSG_HTTP_RANGE;
+ break;
+
+ case 'e':
+ switch (rtl_char_toLowerCase (*(pData + 1)))
+ {
+ case 'f':
+ check = "erer";
+ nIdx = INETMSG_HTTP_REFERER;
+ break;
+
+ case 't':
+ check = "ry-after";
+ nIdx = INETMSG_HTTP_RETRY_AFTER;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_T:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'i':
+ check = "tle";
+ nIdx = INETMSG_HTTP_TITLE;
+ break;
+
+ case 'r':
+ check = "ansfer-encoding";
+ nIdx = INETMSG_HTTP_TRANSFER_ENCODING;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_LETTER_U:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'n':
+ check = "less";
+ nIdx = INETMSG_HTTP_UNLESS;
+ break;
+
+ case 'p':
+ check = "grade";
+ nIdx = INETMSG_HTTP_UPGRADE;
+ break;
+
+ case 'r':
+ check = "i";
+ nIdx = INETMSG_HTTP_URI;
+ break;
+
+ case 's':
+ check = "er-agent";
+ nIdx = INETMSG_HTTP_USER_AGENT;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_TOKEN_CON:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'n':
+ check = "ection";
+ nIdx = INETMSG_HTTP_CONNECTION;
+ break;
+
+ case 't':
+ check = "ent-";
+ eOkState = INETMSG_HTTP_CONTENT;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_CONTENT:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'e':
+ check = "ncoding";
+ nIdx = INETMSG_HTTP_CONTENT_ENCODING;
+ break;
+
+ case 'l':
+ switch (rtl_char_toLowerCase (*(pData + 1)))
+ {
+ case 'a':
+ check = "nguage";
+ nIdx = INETMSG_HTTP_CONTENT_LANGUAGE;
+ break;
+
+ case 'e':
+ check = "ngth";
+ nIdx = INETMSG_HTTP_CONTENT_LENGTH;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case 'm':
+ check = "d5";
+ nIdx = INETMSG_HTTP_CONTENT_MD5;
+ break;
+
+ case 'r':
+ check = "ange";
+ nIdx = INETMSG_HTTP_CONTENT_RANGE;
+ break;
+
+ case 'v':
+ check = "ersion";
+ nIdx = INETMSG_HTTP_CONTENT_VERSION;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_PROXY_AUTH:
+ eState = INETMSG_HTTP_CHECK;
+ eOkState = INETMSG_HTTP_OK;
+
+ switch (rtl_char_toLowerCase (*pData))
+ {
+ case 'e':
+ check = "nticate";
+ nIdx = INETMSG_HTTP_PROXY_AUTHENTICATE;
+ break;
+
+ case 'o':
+ check = "rization";
+ nIdx = INETMSG_HTTP_PROXY_AUTHORIZATION;
+ break;
+
+ default:
+ eState = INETMSG_HTTP_JUNK;
+ break;
+ }
+ pData++;
+ break;
+
+ case INETMSG_HTTP_CHECK:
+ if (*check)
+ {
+ while (*pData && *check &&
+ (rtl_char_toLowerCase (*pData) == *check))
+ {
+ pData++;
+ check++;
+ }
+ }
+ else
+ {
+ check = pData;
+ }
+ eState = (*check == '\0') ? eOkState : INETMSG_HTTP_JUNK;
+ break;
+
+ case INETMSG_HTTP_OK:
+ pData = pStop;
+ SetHeaderField_Impl (
+ HEADERFIELD (HTTPHDR(nIdx), rHeader.GetValue()),
+ m_nIndex[nIdx]);
+ nNewIndex = m_nIndex[nIdx];
+ break;
+
+ default: // INETMSG_HTTP_JUNK
+ pData = pStop;
+ nNewIndex = INetMIMEMessage::SetHeaderField (
+ rHeader, nNewIndex);
+ break;
+ }
+ }
+ return nNewIndex;
+}
+
+/*
+ * Specific Set-Methods.
+ */
+void INetHTTPMessage::SetAccept (const String& rAccept)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_ACCEPT), rAccept,
+ m_nIndex[INETMSG_HTTP_ACCEPT]);
+}
+
+void INetHTTPMessage::SetAcceptCharset (const String& rAcceptCharset)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_ACCEPT_CHARSET), rAcceptCharset,
+ m_nIndex[INETMSG_HTTP_ACCEPT_CHARSET]);
+}
+
+void INetHTTPMessage::SetAcceptEncoding (const String& rAcceptEncoding)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_ACCEPT_ENCODING), rAcceptEncoding,
+ m_nIndex[INETMSG_HTTP_ACCEPT_ENCODING]);
+}
+
+void INetHTTPMessage::SetAcceptLanguage (const String& rAcceptLanguage)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_ACCEPT_LANGUAGE), rAcceptLanguage,
+ m_nIndex[INETMSG_HTTP_ACCEPT_LANGUAGE]);
+}
+
+void INetHTTPMessage::SetAllow (const String& rAllow)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_ALLOW), rAllow,
+ m_nIndex[INETMSG_HTTP_ALLOW]);
+}
+
+void INetHTTPMessage::SetAuthorization (const String& rAuthorization)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_AUTHORIZATION), rAuthorization,
+ m_nIndex[INETMSG_HTTP_AUTHORIZATION]);
+}
+
+void INetHTTPMessage::SetCacheControl (const String& rCacheControl)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CACHE_CONTROL), rCacheControl,
+ m_nIndex[INETMSG_HTTP_CACHE_CONTROL]);
+}
+
+void INetHTTPMessage::SetConnection (const String& rConnection)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONNECTION), rConnection,
+ m_nIndex[INETMSG_HTTP_CONNECTION]);
+}
+
+void INetHTTPMessage::SetContentEncoding (const String& rContentEncoding)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_ENCODING), rContentEncoding,
+ m_nIndex[INETMSG_HTTP_CONTENT_ENCODING]);
+}
+
+void INetHTTPMessage::SetContentLanguage (const String& rContentLanguage)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_LANGUAGE), rContentLanguage,
+ m_nIndex[INETMSG_HTTP_CONTENT_LANGUAGE]);
+}
+
+void INetHTTPMessage::SetContentLength (const String& rContentLength)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_LENGTH), rContentLength,
+ m_nIndex[INETMSG_HTTP_CONTENT_LENGTH]);
+}
+
+void INetHTTPMessage::SetContentMD5 (const String& rContentMD5)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_MD5), rContentMD5,
+ m_nIndex[INETMSG_HTTP_CONTENT_MD5]);
+}
+
+void INetHTTPMessage::SetContentRange (const String& rContentRange)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_RANGE), rContentRange,
+ m_nIndex[INETMSG_HTTP_CONTENT_RANGE]);
+}
+
+void INetHTTPMessage::SetContentVersion (const String& rContentVersion)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_CONTENT_VERSION), rContentVersion,
+ m_nIndex[INETMSG_HTTP_CONTENT_VERSION]);
+}
+
+void INetHTTPMessage::SetCookie (const String& rCookie)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_COOKIE), rCookie,
+ m_nIndex[INETMSG_HTTP_COOKIE]);
+}
+
+void INetHTTPMessage::SetDerivedFrom (const String& rDerivedFrom)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_DERIVED_FROM), rDerivedFrom,
+ m_nIndex[INETMSG_HTTP_DERIVED_FROM]);
+}
+
+void INetHTTPMessage::SetExpires (const String& rExpires)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_EXPIRES), rExpires,
+ m_nIndex[INETMSG_HTTP_EXPIRES]);
+}
+
+void INetHTTPMessage::SetForwarded (const String& rForwarded)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_FORWARDED), rForwarded,
+ m_nIndex[INETMSG_HTTP_FORWARDED]);
+}
+
+void INetHTTPMessage::SetHost (const String& rHost)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_HOST), rHost,
+ m_nIndex[INETMSG_HTTP_HOST]);
+}
+
+void INetHTTPMessage::SetIfModifiedSince (const String& rIfModifiedSince)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_IF_MODIFIED_SINCE), rIfModifiedSince,
+ m_nIndex[INETMSG_HTTP_IF_MODIFIED_SINCE]);
+}
+
+void INetHTTPMessage::SetKeepAlive (const String& rKeepAlive)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_KEEP_ALIVE), rKeepAlive,
+ m_nIndex[INETMSG_HTTP_KEEP_ALIVE]);
+}
+
+void INetHTTPMessage::SetLastModified (const String& rLastModified)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_LAST_MODIFIED), rLastModified,
+ m_nIndex[INETMSG_HTTP_LAST_MODIFIED]);
+}
+
+void INetHTTPMessage::SetLink (const String& rLink)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_LINK), rLink,
+ m_nIndex[INETMSG_HTTP_LINK]);
+}
+
+void INetHTTPMessage::SetLocation (const String& rLocation)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_LOCATION), rLocation,
+ m_nIndex[INETMSG_HTTP_LOCATION]);
+}
+
+void INetHTTPMessage::SetProxyAuthenticate (
+ const String& rProxyAuthenticate)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_PROXY_AUTHENTICATE), rProxyAuthenticate,
+ m_nIndex[INETMSG_HTTP_PROXY_AUTHENTICATE]);
+}
+
+void INetHTTPMessage::SetProxyAuthorization (
+ const String& rProxyAuthorization)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_PROXY_AUTHORIZATION), rProxyAuthorization,
+ m_nIndex[INETMSG_HTTP_PROXY_AUTHORIZATION]);
+}
+
+void INetHTTPMessage::SetPragma (const String& rPragma)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_PRAGMA), rPragma,
+ m_nIndex[INETMSG_HTTP_PRAGMA]);
+}
+
+void INetHTTPMessage::SetPublic (const String& rPublic)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_PUBLIC), rPublic,
+ m_nIndex[INETMSG_HTTP_PUBLIC]);
+}
+
+void INetHTTPMessage::SetRange (const String& rRange)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_RANGE), rRange,
+ m_nIndex[INETMSG_HTTP_RANGE]);
+}
+
+void INetHTTPMessage::SetReferer (const String& rReferer)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_REFERER), rReferer,
+ m_nIndex[INETMSG_HTTP_REFERER]);
+}
+
+void INetHTTPMessage::SetRetryAfter (const String& rRetryAfter)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_RETRY_AFTER), rRetryAfter,
+ m_nIndex[INETMSG_HTTP_RETRY_AFTER]);
+}
+
+void INetHTTPMessage::SetServer (const String& rServer)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_SERVER), rServer,
+ m_nIndex[INETMSG_HTTP_SERVER]);
+}
+
+void INetHTTPMessage::SetTitle (const String& rTitle)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_TITLE), rTitle,
+ m_nIndex[INETMSG_HTTP_TITLE]);
+}
+
+void INetHTTPMessage::SetTransferEncoding (
+ const String& rTransferEncoding)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_TRANSFER_ENCODING), rTransferEncoding,
+ m_nIndex[INETMSG_HTTP_TRANSFER_ENCODING]);
+}
+
+void INetHTTPMessage::SetUnless (const String& rUnless)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_UNLESS), rUnless,
+ m_nIndex[INETMSG_HTTP_UNLESS]);
+}
+
+void INetHTTPMessage::SetUpgrade (const String& rUpgrade)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_UPGRADE), rUpgrade,
+ m_nIndex[INETMSG_HTTP_UPGRADE]);
+}
+
+void INetHTTPMessage::SetURI (const String& rURI)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_URI), rURI,
+ m_nIndex[INETMSG_HTTP_URI]);
+}
+
+void INetHTTPMessage::SetUserAgent (const String& rUserAgent)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_USER_AGENT), rUserAgent,
+ m_nIndex[INETMSG_HTTP_USER_AGENT]);
+}
+
+void INetHTTPMessage::SetWWWAuthenticate (const String& rWWWAuthenticate)
+{
+ SetHeaderField_Impl (
+ INetMIME::HEADER_FIELD_TEXT,
+ HTTPHDR(INETMSG_HTTP_WWW_AUTHENTICATE), rWWWAuthenticate,
+ m_nIndex[INETMSG_HTTP_WWW_AUTHENTICATE]);
+}
+
+/*
+ * operator<<
+ */
+SvStream& INetHTTPMessage::operator<< (SvStream& rStrm) const
+{
+ INetMIMEMessage::operator<< (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_HTTP_NUMHDR; i++)
+ rStrm << m_nIndex[i];
+
+ return rStrm;
+}
+
+/*
+ * operator>>
+ */
+SvStream& INetHTTPMessage::operator>> (SvStream& rStrm)
+{
+ INetMIMEMessage::operator>> (rStrm);
+
+ for (USHORT i = 0; i < INETMSG_HTTP_NUMHDR; i++)
+ rStrm >> m_nIndex[i];
+
+ return rStrm;
+}
+
diff --git a/tools/source/inet/inetstrm.cxx b/tools/source/inet/inetstrm.cxx
new file mode 100644
index 000000000000..04072d617642
--- /dev/null
+++ b/tools/source/inet/inetstrm.cxx
@@ -0,0 +1,2059 @@
+/*************************************************************************
+ *
+ * $RCSfile: inetstrm.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SAL_TYPES_H_
+#include <sal/types.h>
+#endif
+
+#ifndef _RTL_CHAR_H_
+#include <rtl/char.h>
+#endif
+#ifndef _RTL_MEMORY_H_
+#include <rtl/memory.h>
+#endif
+
+#ifndef _CACHESTR_HXX
+#include <cachestr.hxx>
+#endif
+#ifndef _TOOLS_DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _TOOLS_INETMSG_HXX
+#include <inetmsg.hxx>
+#endif
+#ifndef _TOOLS_INETSTRM_HXX
+#include <inetstrm.hxx>
+#endif
+#ifndef _ZCODEC_HXX
+#include <zcodec.hxx>
+#endif
+
+#include <ctype.h> // toupper
+
+#define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
+
+/*=======================================================================
+ *
+ * INetMessageEncodeQPStream Interface.
+ * (Quoted-Printable Encoding)
+ *
+ *=====================================================================*/
+class INetMessageEncodeQPStream_Impl : public INetMessageIStream
+{
+ SvStream *pMsgStrm;
+
+ ULONG nMsgBufSiz;
+ sal_Char *pMsgBuffer;
+ sal_Char *pMsgRead;
+ sal_Char *pMsgWrite;
+
+ ULONG nTokBufSiz;
+ sal_Char *pTokBuffer;
+ sal_Char *pTokRead;
+ sal_Char *pTokWrite;
+
+ INetMessageStreamState eState;
+ BOOL bDone;
+
+ virtual int GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx = NULL);
+
+public:
+ INetMessageEncodeQPStream_Impl (ULONG nMsgBufferSize = 1024);
+ virtual ~INetMessageEncodeQPStream_Impl (void);
+};
+
+/*=====================================================================
+ *
+ * INetMessageDecodeQPStream Interface.
+ * (Quoted-Printable Decoding)
+ *
+ *====================================================================*/
+class INetMessageDecodeQPStream_Impl : public INetMessageOStream
+{
+ INetMessageStreamState eState;
+ SvMemoryStream *pMsgBuffer;
+
+ ULONG nTokBufLen;
+ sal_Char pTokBuffer[4];
+
+ virtual int PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx = NULL);
+
+public:
+ INetMessageDecodeQPStream_Impl (void);
+ virtual ~INetMessageDecodeQPStream_Impl (void);
+};
+
+/*======================================================================
+ *
+ * INetMessageEncode64Stream Interface.
+ * (Base64 Encoding)
+ *
+ *====================================================================*/
+class INetMessageEncode64Stream_Impl : public INetMessageIStream
+{
+ SvStream *pMsgStrm;
+
+ ULONG nMsgBufSiz;
+ sal_uInt8 *pMsgBuffer;
+ sal_uInt8 *pMsgRead;
+ sal_uInt8 *pMsgWrite;
+
+ ULONG nTokBufSiz;
+ sal_Char *pTokBuffer;
+ sal_Char *pTokRead;
+ sal_Char *pTokWrite;
+
+ BOOL bDone;
+
+ virtual int GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx = NULL);
+
+public:
+ INetMessageEncode64Stream_Impl (ULONG nMsgBufferSize = 2048);
+ virtual ~INetMessageEncode64Stream_Impl (void);
+};
+
+/*======================================================================
+ *
+ * INetMessageDecode64Stream Interface.
+ * (Base64 Decoding)
+ *
+ *====================================================================*/
+class INetMessageDecode64Stream_Impl : public INetMessageOStream
+{
+ INetMessageStreamState eState;
+
+ ULONG nMsgBufSiz;
+ sal_Char *pMsgBuffer;
+ sal_Char *pMsgRead;
+ sal_Char *pMsgWrite;
+
+ virtual int PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx = NULL);
+
+public:
+ INetMessageDecode64Stream_Impl (ULONG nMsgBufferSize = 128);
+ virtual ~INetMessageDecode64Stream_Impl (void);
+};
+
+/*=========================================================================
+ *
+ * INetIStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetIStream.
+ */
+INetIStream::INetIStream (ULONG nIBufferSize)
+{
+}
+
+/*
+ * ~INetIStream.
+ */
+INetIStream::~INetIStream (void)
+{
+}
+
+/*
+ * Read.
+ */
+int INetIStream::Read (sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ return GetData (pData, nSize, pCtx);
+}
+
+/*
+ * Decode64.
+ */
+void INetIStream::Decode64 (SvStream& rIn, SvStream& rOut)
+{
+ INetMessage aMsg;
+ aMsg.SetDocumentLB(new SvAsyncLockBytes(&rOut, FALSE));
+
+ INetMessageDecode64Stream_Impl aStream (8192);
+ aStream.SetTargetMessage (&aMsg);
+
+ sal_Char* pBuf = new sal_Char[8192];
+
+ int nRead = 0;
+ while ((nRead = rIn.Read (pBuf, 8192)) > 0)
+ aStream.Write( pBuf, nRead );
+ aStream.Write ("\r\n", 2);
+
+ delete[] pBuf;
+}
+
+/*
+ * Encode64.
+ */
+void INetIStream::Encode64 (SvStream& rIn, SvStream& rOut)
+{
+ INetMessage aMsg;
+ aMsg.SetDocumentLB (
+ new SvLockBytes (&rIn, FALSE));
+
+ INetMessageEncode64Stream_Impl aStream (8192);
+ aStream.SetSourceMessage (&aMsg);
+
+ sal_Char* pBuf = new sal_Char[8192];
+
+ int nRead = 0;
+ while ((nRead = aStream.Read (pBuf, 8192)) > 0)
+ rOut.Write( pBuf, nRead );
+
+ delete[] pBuf;
+}
+
+/*=========================================================================
+ *
+ * INetOStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetOStream.
+ */
+INetOStream::INetOStream (ULONG nOBufferSize)
+{
+}
+
+/*
+ * ~INetOStream.
+ */
+INetOStream::~INetOStream (void)
+{
+}
+
+/*
+ * Write.
+ */
+int INetOStream::Write (const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ return PutData (pData, nSize, pCtx);
+}
+
+/*=========================================================================
+ *
+ * INetMessageIStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetMessageIStream.
+ */
+INetMessageIStream::INetMessageIStream (ULONG nBufferSize)
+ : INetIStream (0),
+ pSourceMsg (NULL),
+ bHeaderGenerated (FALSE),
+ nBufSiz (nBufferSize),
+ pMsgStrm (NULL),
+ pMsgBuffer (new SvMemoryStream)
+{
+ pMsgBuffer->SetStreamCharSet (RTL_TEXTENCODING_ASCII_US);
+ pBuffer = new sal_Char[nBufSiz];
+ pRead = pWrite = pBuffer;
+}
+
+/*
+ * ~INetMessageIStream.
+ */
+INetMessageIStream::~INetMessageIStream (void)
+{
+ delete [] pBuffer;
+ delete pMsgBuffer;
+ delete pMsgStrm;
+}
+
+/*
+ * GetData.
+ */
+int INetMessageIStream::GetData (sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ sal_Char *pWBuf = pData;
+ sal_Char *pWEnd = pData + nSize;
+
+ while (pWBuf < pWEnd)
+ {
+ // Caller's buffer not yet filled.
+ ULONG n = pRead - pWrite;
+ if (n > 0)
+ {
+ // Bytes still in buffer.
+ ULONG m = pWEnd - pWBuf;
+ if (m < n) n = m;
+ for (ULONG i = 0; i < n; i++) *pWBuf++ = *pWrite++;
+ }
+ else
+ {
+ // Buffer empty. Reset to <Begin-of-Buffer>.
+ pRead = pWrite = pBuffer;
+
+ // Read next message line.
+ int nRead = GetMsgLine (pBuffer, nBufSiz, pCtx);
+ if (nRead > 0)
+ {
+ // Set read pointer.
+ pRead = pBuffer + nRead;
+ }
+ else
+ {
+ if (!bHeaderGenerated)
+ {
+ // Header generated. Insert empty line.
+ bHeaderGenerated = TRUE;
+ *pRead++ = '\r';
+ *pRead++ = '\n';
+ }
+ else
+ {
+ // Body generated.
+ return (pWBuf - pData);
+ }
+ }
+ }
+ }
+ return (pWBuf - pData);
+}
+
+/*
+ * GetMsgLine.
+ */
+int INetMessageIStream::GetMsgLine (sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ sal_Char *pWBuf = pData;
+ sal_Char *pWEnd = pData + nSize;
+
+ if (!bHeaderGenerated)
+ {
+ ULONG i, n;
+
+ if (pMsgBuffer->Tell() == 0)
+ {
+ // Insert formatted header into buffer.
+ n = pSourceMsg->GetHeaderCount();
+ for (i = 0; i < n; i++)
+ {
+ INetMessageHeader aHeader (pSourceMsg->GetHeaderField(i));
+ if (aHeader.GetValue().Len())
+ {
+ // NYI: Folding long lines.
+ *pMsgBuffer << (sal_Char*)(aHeader.GetName().GetBuffer());
+ *pMsgBuffer << ": ";
+ *pMsgBuffer << (sal_Char*)(aHeader.GetValue().GetBuffer());
+ *pMsgBuffer << "\r\n";
+ }
+ }
+
+ pMsgWrite = (sal_Char *)(pMsgBuffer->GetData());
+ pMsgRead = pMsgWrite + pMsgBuffer->Tell();
+ }
+
+ n = pMsgRead - pMsgWrite;
+ if (n > 0)
+ {
+ // Move to caller.
+ if (nSize < n) n = nSize;
+ for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
+ }
+ else
+ {
+ // Reset buffer.
+ pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
+ }
+ }
+ else
+ {
+ if (pSourceMsg->GetDocumentLB())
+ {
+ if (pMsgStrm == NULL)
+ pMsgStrm = new SvStream (pSourceMsg->GetDocumentLB());
+
+ ULONG nRead = pMsgStrm->Read (pWBuf, (pWEnd - pWBuf));
+ pWBuf += nRead;
+ }
+ }
+ return (pWBuf - pData);
+}
+
+/*=========================================================================
+ *
+ * INetMessageOStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetMessageOStream.
+ */
+INetMessageOStream::INetMessageOStream (void)
+ : INetOStream (0),
+ pTargetMsg (NULL),
+ bHeaderParsed (FALSE),
+ eOState (INETMSG_EOL_BEGIN),
+ pMsgBuffer (new SvMemoryStream)
+{
+}
+
+/*
+ * ~INetMessageOStream.
+ */
+INetMessageOStream::~INetMessageOStream (void)
+{
+ if (pMsgBuffer->Tell() > 0)
+ PutMsgLine ((const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell());
+ delete pMsgBuffer;
+
+ if (pTargetMsg)
+ {
+ SvOpenLockBytes *pLB =
+ PTR_CAST (SvOpenLockBytes, pTargetMsg->GetDocumentLB());
+ if (pLB)
+ {
+ pLB->Flush();
+ pLB->Terminate();
+ }
+ }
+}
+
+/*
+ * PutData.
+ * (Simple Field Parsing (RFC822, Appendix B)).
+ */
+int INetMessageOStream::PutData (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ const sal_Char *pStop = (pData + nSize);
+
+ while (!bHeaderParsed && (pData < pStop))
+ {
+ if (eOState == INETMSG_EOL_BEGIN)
+ {
+ if ((*pData == '\r') || (*pData == '\n'))
+ {
+ /*
+ * Empty Line. Separates header fields from message body.
+ * Skip this and any 2nd line break character (if any).
+ */
+ pData++;
+ if ((pData < pStop) && ((*pData == '\r') || (*pData == '\n')))
+ pData++;
+
+ // Emit any buffered last header field.
+ if (pMsgBuffer->Tell() > 0)
+ {
+ *pMsgBuffer << '\0';
+ int status = PutMsgLine (
+ (const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell(), pCtx);
+ if (status != INETSTREAM_STATUS_OK) return status;
+ }
+
+ // Reset to begin.
+ eOState = INETMSG_EOL_BEGIN;
+ pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
+
+ // Mark header parsed.
+ bHeaderParsed = TRUE;
+ }
+ else if ((*pData == ' ') || (*pData == '\t'))
+ {
+ // Continuation line. Unfold multi-line field-body.
+ *pMsgBuffer << ' ';
+ pData++;
+ }
+ else
+ {
+ // Begin of new header field.
+ if (pMsgBuffer->Tell() > 0)
+ {
+ // Emit buffered header field now.
+ *pMsgBuffer << '\0';
+ int status = PutMsgLine (
+ (const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell(), pCtx);
+ if (status != INETSTREAM_STATUS_OK) return status;
+ }
+
+ // Reset to begin of buffer.
+ pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
+
+ // Insert current character into buffer.
+ *pMsgBuffer << *pData++;
+ }
+
+ // Search for next line break character.
+ if (!bHeaderParsed) eOState = INETMSG_EOL_SCR;
+ }
+ else if (eOState == INETMSG_EOL_FCR)
+ {
+ // Skip line break character.
+ pData++;
+
+ // Mark begin of line.
+ eOState = INETMSG_EOL_BEGIN;
+ }
+ else if ((*pData == '\r') || (*pData == '\n'))
+ {
+ if (*pData == '\r') pData++;
+ eOState = INETMSG_EOL_FCR;
+ }
+ else if (rtl_char_isWhitespace (*pData & 0x7f))
+ {
+ // Any <LWS> is folded into a single <SP> character.
+ sal_Char c = *((const sal_Char *) pMsgBuffer->GetData() + pMsgBuffer->Tell() - 1);
+ if (!rtl_char_isWhitespace (c & 0x7f)) *pMsgBuffer << ' ';
+
+ // Skip over this <LWS> character.
+ pData++;
+ }
+ else
+ {
+ // Any other character is inserted into line buffer.
+ *pMsgBuffer << *pData++;
+ }
+ }
+
+ if (bHeaderParsed && (pData < pStop))
+ {
+ // Put message body down-stream.
+ return PutMsgLine (pData, (pStop - pData), pCtx);
+ }
+
+ return INETSTREAM_STATUS_OK;
+}
+
+/*
+ * PutMsgLine.
+ */
+int INetMessageOStream::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ // Check for message container.
+ if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ // Check for header or body.
+ if (!IsHeaderParsed())
+ {
+ ByteString aField (pData);
+ USHORT nPos = aField.Search (':');
+ if (nPos != STRING_NOTFOUND)
+ {
+ ByteString aName (
+ aField.Copy (0, nPos));
+ ByteString aValue (
+ aField.Copy (nPos + 1, aField.Len() - nPos + 1));
+ aValue.EraseLeadingChars (' ');
+
+ pTargetMsg->SetHeaderField (
+ INetMessageHeader (aName, aValue));
+ }
+ }
+ else
+ {
+ SvOpenLockBytes *pLB =
+ PTR_CAST(SvOpenLockBytes, pTargetMsg->GetDocumentLB());
+ if (pLB == NULL)
+ return INETSTREAM_STATUS_WOULDBLOCK;
+
+ ULONG nDocSiz = pTargetMsg->GetDocumentSize();
+ ULONG nWrite = 0;
+
+ ErrCode status = pLB->FillAppend ((sal_Char *)pData, nSize, &nWrite);
+ pTargetMsg->SetDocumentSize (nDocSiz + nWrite);
+
+ if (nWrite < nSize) return INETSTREAM_STATUS_ERROR;
+ }
+ return INETSTREAM_STATUS_OK;
+}
+
+/*=========================================================================
+ *
+ * INetMessageIOStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetMessageIOStream.
+ */
+INetMessageIOStream::INetMessageIOStream (ULONG nBufferSize)
+ : INetMessageIStream (nBufferSize),
+ INetMessageOStream ()
+{
+}
+
+/*
+ * ~INetMessageIOStream.
+ */
+INetMessageIOStream::~INetMessageIOStream (void)
+{
+}
+
+/*=======================================================================
+ *
+ * INetMessageEncodeQPStream_Impl Implementation.
+ * (Quoted-Printable Encoding)
+ *
+ *=====================================================================*/
+static const sal_Char hex2pr[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+static const sal_Char ebcdic[] = {
+ '!', '"', '#', '$', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'
+};
+
+/*
+ * INetMessageEncodeQPStream_Impl.
+ */
+INetMessageEncodeQPStream_Impl::INetMessageEncodeQPStream_Impl (
+ ULONG nMsgBufferSize)
+ : INetMessageIStream (),
+ pMsgStrm (NULL),
+ nMsgBufSiz (nMsgBufferSize),
+ nTokBufSiz (80),
+ eState (INETMSG_EOL_SCR),
+ bDone (FALSE)
+{
+ GenerateHeader (FALSE);
+
+ pMsgBuffer = new sal_Char[nMsgBufSiz];
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ pTokBuffer = new sal_Char[nTokBufSiz];
+ pTokRead = pTokWrite = pTokBuffer;
+}
+
+/*
+ * ~INetMessageEncodeQPStream_Impl.
+ */
+INetMessageEncodeQPStream_Impl::~INetMessageEncodeQPStream_Impl (void)
+{
+ delete pMsgStrm;
+ delete [] pMsgBuffer;
+ delete [] pTokBuffer;
+}
+
+/*
+ * GetMsgLine.
+ */
+int INetMessageEncodeQPStream_Impl::GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ INetMessage *pMsg = GetSourceMessage ();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ if (pMsg->GetDocumentLB() == NULL) return 0;
+ if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
+
+ sal_Char *pWBuf = pData;
+ while (pWBuf < (pData + nSize))
+ {
+ // Caller's buffer not yet filled.
+ if ((pMsgRead - pMsgWrite) > 0)
+ {
+ // Bytes still in message buffer.
+ if ((eState != INETMSG_EOL_BEGIN) &&
+ ((pTokRead - pTokBuffer) < 72))
+ {
+ // Token buffer not yet filled.
+ if (eState == INETMSG_EOL_FCR)
+ {
+ eState = INETMSG_EOL_BEGIN;
+ if (*pMsgWrite != '\n')
+ {
+ // Convert orphant <CR> into <CR><LF> sequence.
+ *pTokRead++ = '\n';
+ }
+ *pTokRead++ = *pMsgWrite++;
+ }
+ else if ((*pMsgWrite == ' ') || (*pMsgWrite == '\t'))
+ {
+ eState = INETMSG_EOL_FSP;
+ *pTokRead++ = *pMsgWrite++;
+ }
+ else if (*pMsgWrite == '\r')
+ {
+ // Found <CR>.
+ if (eState == INETMSG_EOL_FSP)
+ {
+ // Encode last (trailing space) character.
+ sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
+ *pTokRead++ = '=';
+ *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
+ *pTokRead++ = hex2pr[((c & 0x0f) )];
+ }
+ eState = INETMSG_EOL_FCR;
+ *pTokRead++ = *pMsgWrite++;
+ }
+ else if (*pMsgWrite == '\n')
+ {
+ // Found <LF> only.
+ if (eState == INETMSG_EOL_FSP)
+ {
+ // Encode last (trailing space) character.
+ sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
+ *pTokRead++ = '=';
+ *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
+ *pTokRead++ = hex2pr[((c & 0x0f) )];
+ }
+ eState = INETMSG_EOL_BEGIN;
+
+ // Convert orphant <LF> into <CR><LF> sequence.
+ *pTokRead++ = '\r';
+ *pTokRead++ = *pMsgWrite++;
+ }
+ else if (*pMsgWrite == '=')
+ {
+ // Escape character itself MUST be encoded, of course.
+ sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
+ *pTokRead++ = '=';
+ *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
+ *pTokRead++ = hex2pr[((c & 0x0f) )];
+
+ eState = INETMSG_EOL_SCR;
+ }
+ else if (((sal_uInt8)(*pMsgWrite) > 0x20) &&
+ ((sal_uInt8)(*pMsgWrite) < 0x7f) )
+ {
+ /*
+ * Some printable ASCII character.
+ * (Encode EBCDIC special characters (NYI)).
+ */
+ *pTokRead++ = *pMsgWrite++;
+ eState = INETMSG_EOL_SCR;
+ }
+ else
+ {
+ // Encode any other character.
+ sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
+ *pTokRead++ = '=';
+ *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
+ *pTokRead++ = hex2pr[((c & 0x0f) )];
+
+ eState = INETMSG_EOL_SCR;
+ }
+ }
+ else
+ {
+ // Check for maximum line length.
+ if (eState != INETMSG_EOL_BEGIN)
+ {
+ // Insert soft line break.
+ *pTokRead++ = '=';
+ *pTokRead++ = '\r';
+ *pTokRead++ = '\n';
+
+ eState = INETMSG_EOL_BEGIN;
+ }
+
+ // Copy to caller's buffer.
+ if ((pTokRead - pTokWrite) > 0)
+ {
+ // Bytes still in token buffer.
+ *pWBuf++ = *pTokWrite++;
+ }
+ else
+ {
+ // Token buffer empty. Reset to <Begin-of-Buffer>.
+ pTokRead = pTokWrite = pTokBuffer;
+ eState = INETMSG_EOL_SCR;
+ }
+ }
+ }
+ else
+ {
+ // Message buffer empty. Reset to <Begin-of-Buffer>.
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ // Read next message block.
+ ULONG nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
+ if (nRead > 0)
+ {
+ // Set read pointer.
+ pMsgRead = (pMsgBuffer + nRead);
+ }
+ else
+ {
+ // Nothing more ro read.
+ if (!bDone)
+ {
+ // Append final <CR><LF> and mark we're done.
+ *pTokRead++ = '\r';
+ *pTokRead++ = '\n';
+
+ bDone = TRUE;
+ }
+ else
+ {
+ // Already done all encoding.
+ if ((pTokRead - pTokWrite) > 0)
+ {
+ // Bytes still in token buffer.
+ *pWBuf++ = *pTokWrite++;
+ }
+ else
+ {
+ // Token buffer empty. Reset to <Begin-of-Buffer>.
+ pTokRead = pTokWrite = pTokBuffer;
+
+ // Return.
+ return (pWBuf - pData);
+ }
+ }
+ }
+ }
+ }
+ return (pWBuf - pData);
+}
+
+/*=====================================================================
+ *
+ * INetMessageDecodeQPStream_Impl Implementation.
+ * (Quoted-Printable Decoding)
+ *
+ *====================================================================*/
+static const sal_uInt8 pr2hex[128] = {
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+ 0x10, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
+};
+
+/*
+ * INetMessageDecodeQPStream_Impl.
+ */
+INetMessageDecodeQPStream_Impl::INetMessageDecodeQPStream_Impl (void)
+ : INetMessageOStream (),
+ eState (INETMSG_EOL_BEGIN),
+ pMsgBuffer (new SvMemoryStream),
+ nTokBufLen (0)
+{
+ ParseHeader (FALSE);
+}
+
+/*
+ * ~INetMessageDecodeQPStream_Impl.
+ */
+INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
+{
+ delete pMsgBuffer;
+}
+
+/*
+ * PutMsgLine.
+ */
+int INetMessageDecodeQPStream_Impl::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ INetMessage *pMsg = GetTargetMessage();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
+ if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
+
+ const sal_Char *pStop = pData + nSize;
+ while (pData < pStop)
+ {
+ if (eState == INETMSG_EOL_FESC)
+ {
+ *(pTokBuffer + nTokBufLen++) = toupper (*pData);
+ pData++;
+ if (nTokBufLen == 2)
+ {
+ if ((*pTokBuffer == '\r') || (*pTokBuffer == '\n'))
+ {
+ // Soft line break (=<CR><LF>). Emit buffer now.
+ eState = INETMSG_EOL_BEGIN;
+ }
+ else
+ {
+ // Decode token.
+ *pMsgBuffer << sal_uInt8 (
+ (pr2hex[(int)(pTokBuffer[0] & 0x7f)] << 4) |
+ (pr2hex[(int)(pTokBuffer[1] & 0x7f)] & 15) );
+
+ // Search for next <CR>.
+ eState = INETMSG_EOL_SCR;
+ }
+
+ // Reset token buffer.
+ nTokBufLen = 0;
+ }
+ }
+ else if (*pData == '=')
+ {
+ // Found escape character.
+ pData++;
+ eState = INETMSG_EOL_FESC;
+ }
+ else if (eState == INETMSG_EOL_FCR)
+ {
+ *pMsgBuffer << *pData++;
+ eState = INETMSG_EOL_BEGIN;
+ }
+ else if (*pData == '\r')
+ {
+ *pMsgBuffer << *pData++;
+ eState = INETMSG_EOL_FCR;
+ }
+ else
+ {
+ *pMsgBuffer << *pData++;
+ }
+
+ if (eState == INETMSG_EOL_BEGIN)
+ {
+ ULONG nRead = pMsgBuffer->Tell();
+ if (nRead > 0)
+ {
+ // Emit buffer.
+ ULONG nDocSiz = pMsg->GetDocumentSize();
+ ULONG nWrite = 0;
+
+ pLB->FillAppend (
+ (sal_Char *)(pMsgBuffer->GetData()), nRead, &nWrite);
+ pMsg->SetDocumentSize (nDocSiz + nWrite);
+
+ if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
+
+ pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
+ }
+ eState = INETMSG_EOL_SCR;
+ }
+ }
+ return INETSTREAM_STATUS_OK;
+}
+
+/*======================================================================
+ *
+ * INetMessageEncode64Stream_Impl Implementation.
+ * (Base64 Encoding)
+ *
+ *====================================================================*/
+static const sal_Char six2pr[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+};
+
+/*
+ * INetMessageEncode64Stream_Impl.
+ */
+INetMessageEncode64Stream_Impl::INetMessageEncode64Stream_Impl (
+ ULONG nMsgBufferSize)
+ : INetMessageIStream (),
+ pMsgStrm (NULL),
+ nMsgBufSiz (nMsgBufferSize),
+ nTokBufSiz (80),
+ bDone (FALSE)
+{
+ GenerateHeader (FALSE);
+
+ pMsgBuffer = new sal_uInt8[nMsgBufSiz];
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ pTokBuffer = new sal_Char[nTokBufSiz];
+ pTokRead = pTokWrite = pTokBuffer;
+}
+
+/*
+ * ~INetMessageEncode64Stream_Impl.
+ */
+INetMessageEncode64Stream_Impl::~INetMessageEncode64Stream_Impl (void)
+{
+ delete pMsgStrm;
+ delete [] pMsgBuffer;
+ delete [] pTokBuffer;
+}
+
+/*
+ * GetMsgLine.
+ */
+int INetMessageEncode64Stream_Impl::GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ INetMessage *pMsg = GetSourceMessage ();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ if (pMsg->GetDocumentLB() == NULL) return 0;
+ if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
+
+ sal_Char *pWBuf = pData;
+ while (pWBuf < (pData + nSize))
+ {
+ // Caller's buffer not yet filled.
+ if ((pMsgRead - pMsgWrite) > 0)
+ {
+ // Bytes still in message buffer.
+ if ((pTokRead - pTokBuffer) < 72)
+ {
+ // Token buffer not yet filled.
+ switch ((pTokRead - pTokBuffer) % 4)
+ {
+ case 0:
+ *pTokRead++ = six2pr[(int)(*pMsgWrite >> 2)];
+ break;
+
+ case 1:
+ *pTokRead++ = six2pr[
+ (int)(((*pMsgWrite << 4) & 060) |
+ (((*(pMsgWrite + 1)) >> 4) & 017))];
+ pMsgWrite++;
+ break;
+
+ case 2:
+ *pTokRead++ = six2pr[
+ (int)(((*pMsgWrite << 2) & 074) |
+ (((*(pMsgWrite + 1)) >> 6) & 003))];
+ pMsgWrite++;
+ break;
+
+ default: // == case 3
+ *pTokRead++ = six2pr[(int)(*pMsgWrite & 077)];
+ pMsgWrite++;
+ break;
+ }
+ }
+ else if ((pTokRead - pTokBuffer) == 72)
+ {
+ // Maximum line length. Append <CR><LF>.
+ *pTokRead++ = '\r';
+ *pTokRead++ = '\n';
+ }
+ else
+ {
+ if ((pTokRead - pTokWrite) > 0)
+ {
+ // Bytes still in token buffer.
+ *pWBuf++ = *pTokWrite++;
+ }
+ else
+ {
+ // Token buffer empty. Reset to <Begin-of-Buffer>.
+ pTokRead = pTokWrite = pTokBuffer;
+ }
+ }
+ }
+ else
+ {
+ // Message buffer empty. Reset to <Begin-of-Buffer>.
+ pMsgRead = pMsgWrite = pMsgBuffer;
+
+ // Read next message block.
+ ULONG nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
+ if (nRead > 0)
+ {
+ // Set read pointer.
+ pMsgRead = (pMsgBuffer + nRead);
+ }
+ else
+ {
+ // Nothing more to read.
+ if (!bDone)
+ {
+ // Append pad character(s) and final <CR><LF>.
+ switch ((pTokRead - pTokBuffer) % 4)
+ {
+ case 2:
+ *pTokRead++ = '=';
+ // Fall through for 2nd pad character.
+
+ case 3:
+ *pTokRead++ = '=';
+ break;
+
+ default:
+ break;
+ }
+ *pTokRead++ = '\r';
+ *pTokRead++ = '\n';
+
+ // Mark we're done.
+ bDone = TRUE;
+ }
+ else
+ {
+ // Already done all encoding.
+ if ((pTokRead - pTokWrite) > 0)
+ {
+ // Bytes still in token buffer.
+ *pWBuf++ = *pTokWrite++;
+ }
+ else
+ {
+ // Token buffer empty. Reset to <Begin-of-Buffer>.
+ pTokRead = pTokWrite = pTokBuffer;
+
+ // Reset done flag, if everything has been done.
+ // if (pWBuf == pData) bDone = FALSE;
+
+ // Return.
+ return (pWBuf - pData);
+ }
+ }
+ }
+ }
+ } // while (pWBuf < (pData + nSize))
+ return (pWBuf - pData);
+}
+
+/*======================================================================
+ *
+ * INetMessageDecode64Stream_Impl Implementation.
+ * (Base64 Decoding)
+ *
+ *====================================================================*/
+static const sal_uInt8 pr2six[256] = {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+ 0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+};
+
+/*
+ * INetMessageDecode64Stream_Impl.
+ */
+INetMessageDecode64Stream_Impl::INetMessageDecode64Stream_Impl (
+ ULONG nMsgBufferSize)
+ : INetMessageOStream (),
+ eState (INETMSG_EOL_SCR),
+ nMsgBufSiz (nMsgBufferSize)
+{
+ ParseHeader (FALSE);
+
+ pMsgBuffer = new sal_Char[nMsgBufSiz];
+ pMsgRead = pMsgWrite = pMsgBuffer;
+}
+
+/*
+ * ~INetMessageDecode64Stream_Impl.
+ */
+INetMessageDecode64Stream_Impl::~INetMessageDecode64Stream_Impl (void)
+{
+ delete [] pMsgBuffer;
+}
+
+/*
+ * PutMsgLine.
+ */
+int INetMessageDecode64Stream_Impl::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ INetMessage *pMsg = GetTargetMessage ();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
+ if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
+
+ const sal_Char *pStop = (pData + nSize);
+ while (pData < pStop)
+ {
+ if (pr2six[(int)(*pData)] > 63)
+ {
+ /*
+ * Character not in base64 alphabet.
+ * Check for <End-of-Stream> or Junk.
+ */
+ if (*pData == '=')
+ {
+ // Final pad character -> Done.
+ ULONG nDocSiz = pMsg->GetDocumentSize();
+ ULONG nRead = pMsgWrite - pMsgBuffer;
+ ULONG nWrite = 0;
+
+ pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
+ pMsg->SetDocumentSize (nDocSiz + nWrite);
+
+ if (nWrite < nRead)
+ return INETSTREAM_STATUS_ERROR;
+ else
+ return INETSTREAM_STATUS_LOADED;
+ }
+ else if (eState == INETMSG_EOL_FCR)
+ {
+ // Skip any line break character.
+ if ((*pData == '\r') || (*pData == '\n')) pData++;
+
+ // Store decoded message buffer contents.
+ ULONG nDocSiz = pMsg->GetDocumentSize();
+ ULONG nRead = pMsgWrite - pMsgBuffer;
+ ULONG nWrite = 0;
+
+ pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
+ pMsg->SetDocumentSize (nDocSiz + nWrite);
+
+ if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
+
+ // Reset to <Begin-of-Buffer>.
+ pMsgWrite = pMsgBuffer;
+ eState = INETMSG_EOL_SCR;
+ }
+ else if ((*pData == '\r') || (*pData == '\n'))
+ {
+ // Skip any line break character.
+ pData++;
+ eState = INETMSG_EOL_FCR;
+ }
+ else
+ {
+ // Skip any junk character (may be transmission error).
+ pData++;
+ }
+ }
+ else
+ {
+ // Decode any other character into message buffer.
+ switch ((pMsgRead - pMsgBuffer) % 4)
+ {
+ case 0:
+ *pMsgWrite = (pr2six[(int)(*pData++)] << 2);
+ pMsgRead++;
+ break;
+
+ case 1:
+ *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 4);
+ *pMsgWrite = (pr2six[(int)(*pData++)] << 4);
+ pMsgRead++;
+ break;
+
+ case 2:
+ *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 2);
+ *pMsgWrite = (pr2six[(int)(*pData++)] << 6);
+ pMsgRead++;
+ break;
+
+ default: // == case 3
+ *pMsgWrite++ |= (pr2six[(int)(*pData++)]);
+ pMsgRead = pMsgBuffer;
+ break;
+ } // switch ((pMsgRead - pMsgBuffer) % 4)
+ }
+ } // while (pData < pStop)
+ return INETSTREAM_STATUS_OK;
+}
+
+/*=========================================================================
+ *
+ * INetMIMEMessageStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetMIMEMessageStream.
+ */
+INetMIMEMessageStream::INetMIMEMessageStream (ULONG nBufferSize)
+ : INetMessageIOStream (nBufferSize),
+ eState (INETMSG_EOL_BEGIN),
+ nChildIndex (0),
+ pChildStrm (NULL),
+ eEncoding (INETMSG_ENCODING_BINARY),
+ pEncodeStrm (NULL),
+ pDecodeStrm (NULL),
+ pMsgBuffer (NULL)
+{
+}
+
+/*
+ * ~INetMIMEMessageStream.
+ */
+INetMIMEMessageStream::~INetMIMEMessageStream (void)
+{
+ delete pChildStrm;
+ delete pEncodeStrm;
+ delete pDecodeStrm;
+ delete pMsgBuffer;
+}
+
+/*
+ * GetMsgEncoding.
+ */
+INetMessageEncoding
+INetMIMEMessageStream::GetMsgEncoding (const String& rContentType)
+{
+ if ((rContentType.CompareIgnoreCaseToAscii ("message" , 7) == 0) ||
+ (rContentType.CompareIgnoreCaseToAscii ("multipart", 9) == 0) )
+ return INETMSG_ENCODING_7BIT;
+
+ if (rContentType.CompareIgnoreCaseToAscii ("text", 4) == 0)
+ {
+ if (rContentType.CompareIgnoreCaseToAscii ("text/plain", 10) == 0)
+ {
+ if (rContentType.GetTokenCount ('=') > 1)
+ {
+ String aCharset (rContentType.GetToken (1, '='));
+ aCharset.EraseLeadingChars (' ');
+ aCharset.EraseLeadingChars ('"');
+
+ if (aCharset.CompareIgnoreCaseToAscii ("us-ascii", 8) == 0)
+ return INETMSG_ENCODING_7BIT;
+ else
+ return INETMSG_ENCODING_QUOTED;
+ }
+ else
+ return INETMSG_ENCODING_7BIT;
+ }
+ else
+ return INETMSG_ENCODING_QUOTED;
+ }
+
+ return INETMSG_ENCODING_BASE64;
+}
+
+/*
+ * GetMsgLine.
+ * (Message Generator).
+ */
+int INetMIMEMessageStream::GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ // Check for message container.
+ INetMIMEMessage *pMsg = GetSourceMessage();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ // Check for header or body.
+ if (!IsHeaderGenerated())
+ {
+ if (eState == INETMSG_EOL_BEGIN)
+ {
+ // Prepare special header fields.
+ if (pMsg->GetParent())
+ {
+ String aPCT (pMsg->GetParent()->GetContentType());
+ if (aPCT.CompareIgnoreCaseToAscii ("message/rfc822", 14) == 0)
+ pMsg->SetMIMEVersion (
+ String(CONSTASCII_STRINGPARAM("1.0")));
+ else
+ pMsg->SetMIMEVersion (String());
+ }
+ else
+ {
+ pMsg->SetMIMEVersion (String(CONSTASCII_STRINGPARAM("1.0")));
+ }
+
+ // Check ContentType.
+ String aContentType (pMsg->GetContentType());
+ if (aContentType.Len())
+ {
+ // Determine default Content-Type.
+ String aDefaultType;
+ pMsg->GetDefaultContentType (aDefaultType);
+
+ if (aDefaultType.CompareIgnoreCaseToAscii (
+ aContentType, aContentType.Len()) == 0)
+ {
+ // No need to specify default.
+ pMsg->SetContentType (String());
+ }
+ }
+
+ // Check Encoding.
+ String aEncoding (pMsg->GetContentTransferEncoding());
+ if (aEncoding.Len())
+ {
+ // Use given Encoding.
+ if (aEncoding.CompareIgnoreCaseToAscii (
+ "base64", 6) == 0)
+ eEncoding = INETMSG_ENCODING_BASE64;
+ else if (aEncoding.CompareIgnoreCaseToAscii (
+ "quoted-printable", 16) == 0)
+ eEncoding = INETMSG_ENCODING_QUOTED;
+ else
+ eEncoding = INETMSG_ENCODING_7BIT;
+ }
+ else
+ {
+ // Use default Encoding for (given|default) Content-Type.
+ if (aContentType.Len() == 0)
+ {
+ // Determine default Content-Type.
+ pMsg->GetDefaultContentType (aContentType);
+ }
+ eEncoding = GetMsgEncoding (aContentType);
+ }
+
+ // Set Content-Transfer-Encoding header.
+ if (eEncoding == INETMSG_ENCODING_BASE64)
+ {
+ // Base64.
+ pMsg->SetContentTransferEncoding (
+ String(CONSTASCII_STRINGPARAM("base64")));
+ }
+ else if (eEncoding == INETMSG_ENCODING_QUOTED)
+ {
+ // Quoted-Printable.
+ pMsg->SetContentTransferEncoding (
+ String(CONSTASCII_STRINGPARAM("quoted-printable")));
+ }
+ else
+ {
+ // No need to specify default.
+ pMsg->SetContentTransferEncoding (String());
+ }
+
+ // Mark we're done.
+ eState = INETMSG_EOL_DONE;
+ }
+
+ // Generate the message header.
+ int nRead = INetMessageIOStream::GetMsgLine (pData, nSize, pCtx);
+ if (nRead <= 0)
+ {
+ // Reset state.
+ eState = INETMSG_EOL_BEGIN;
+ }
+ return nRead;
+ }
+ else
+ {
+ // Generate the message body.
+ if (pMsg->IsContainer())
+ {
+ // Encapsulated message body.
+ while (eState == INETMSG_EOL_BEGIN)
+ {
+ if (pChildStrm == NULL)
+ {
+ INetMIMEMessage *pChild = pMsg->GetChild (nChildIndex);
+ if (pChild)
+ {
+ // Increment child index.
+ nChildIndex++;
+
+ // Create child stream.
+ pChildStrm = new INetMIMEMessageStream;
+ pChildStrm->SetSourceMessage (pChild);
+
+ if (pMsg->IsMultipart())
+ {
+ // Insert multipart delimiter.
+ ByteString aDelim ("--");
+ aDelim += pMsg->GetMultipartBoundary();
+ aDelim += "\r\n";
+
+ rtl_copyMemory (
+ pData, aDelim.GetBuffer(), aDelim.Len());
+ return aDelim.Len();
+ }
+ }
+ else
+ {
+ // No more parts. Mark we're done.
+ eState = INETMSG_EOL_DONE;
+ nChildIndex = 0;
+
+ if (pMsg->IsMultipart())
+ {
+ // Insert close delimiter.
+ ByteString aDelim ("--");
+ aDelim += pMsg->GetMultipartBoundary();
+ aDelim += "--\r\n";
+
+ rtl_copyMemory (
+ pData, aDelim.GetBuffer(), aDelim.Len());
+ return aDelim.Len();
+ }
+ }
+ }
+ else
+ {
+ // Read current child stream.
+ int nRead = pChildStrm->Read (pData, nSize, pCtx);
+ if (nRead > 0)
+ {
+ return nRead;
+ }
+ else
+ {
+ // Cleanup exhausted child stream.
+ delete pChildStrm;
+ pChildStrm = NULL;
+ }
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ // Single part message body.
+ if (pMsg->GetDocumentLB() == NULL)
+ {
+ // Empty message body.
+ return 0;
+ }
+ else
+ {
+ // Check whether message body needs to be encoded.
+ if (eEncoding == INETMSG_ENCODING_7BIT)
+ {
+ // No Encoding.
+ return INetMessageIOStream::GetMsgLine (
+ pData, nSize, pCtx);
+ }
+ else
+ {
+ // Apply appropriate Encoding.
+ while (eState == INETMSG_EOL_BEGIN)
+ {
+ if (pEncodeStrm == NULL)
+ {
+ // Create encoder stream.
+ if (eEncoding == INETMSG_ENCODING_QUOTED)
+ {
+ // Quoted-Printable Encoding.
+ pEncodeStrm
+ = new INetMessageEncodeQPStream_Impl;
+ }
+ else
+ {
+ // Base64 Encoding.
+ pEncodeStrm
+ = new INetMessageEncode64Stream_Impl;
+ }
+ pEncodeStrm->SetSourceMessage (pMsg);
+ }
+
+ // Read encoded message.
+ int nRead = pEncodeStrm->Read (pData, nSize, pCtx);
+ if (nRead > 0)
+ {
+ return nRead;
+ }
+ else
+ {
+ // Cleanup exhausted encoder stream.
+ delete pEncodeStrm;
+ pEncodeStrm = NULL;
+
+ // Mark we're done.
+ eState = INETMSG_EOL_DONE;
+ }
+ }
+ return 0;
+ }
+ }
+ }
+ }
+ return INETSTREAM_STATUS_ERROR; // Never reached.
+}
+
+/*
+ * PutMsgLine.
+ * (Message Parser).
+ */
+int INetMIMEMessageStream::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ // Check for message container.
+ INetMIMEMessage *pMsg = GetTargetMessage();
+ if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
+
+ // Check for header or body.
+ if (!IsHeaderParsed())
+ {
+ // Parse the message header.
+ int nRet = INetMessageIOStream::PutMsgLine (pData, nSize, pCtx);
+ return nRet;
+ }
+ else
+ {
+ pMsg->SetHeaderParsed();
+ // Parse the message body.
+ if (pMsg->IsContainer())
+ {
+
+ // Content-Transfer-Encoding MUST be "7bit" (RFC1521).
+ if (pMsg->IsMessage())
+ {
+ if( !pChildStrm )
+ {
+ // Encapsulated message.
+ pMsg->SetChildCount( pMsg->GetChildCount() + 1);
+ INetMIMEMessage* pNewMessage = new INetMIMEMessage;
+ pNewMessage->SetDocumentLB (
+ new SvAsyncLockBytes(new SvCacheStream, FALSE));
+ pMsg->AttachChild( *pNewMessage, TRUE );
+
+ // Encapsulated message body. Create message parser stream.
+ pChildStrm = new INetMIMEMessageStream;
+ pChildStrm->SetTargetMessage ( pNewMessage );
+
+ // Initialize control variables.
+ eState = INETMSG_EOL_BEGIN;
+ }
+ if ( nSize > 0)
+ {
+ // Bytes still in buffer. Put message down-stream.
+ int status = pChildStrm->Write(
+ pData, nSize, NULL );
+ if (status != INETSTREAM_STATUS_OK)
+ return status;
+ }
+
+ return INetMessageIOStream::PutMsgLine (
+ pData, nSize, pCtx);
+ }
+ else
+ {
+
+ // Multipart message body. Initialize multipart delimiters.
+ // Multipart message.
+ if (pMsg->GetMultipartBoundary().Len() == 0)
+ {
+ // Determine boundary.
+ ByteString aType (
+ pMsg->GetContentType(), RTL_TEXTENCODING_ASCII_US);
+ ByteString aLowerType (aType);
+ aLowerType.ToLowerAscii();
+
+ USHORT nPos = aLowerType.Search ("boundary=");
+ ByteString aBoundary (aType.Copy (nPos + 9));
+
+ aBoundary.EraseLeadingAndTrailingChars (' ');
+ aBoundary.EraseLeadingAndTrailingChars ('"');
+
+ // Save boundary.
+ pMsg->SetMultipartBoundary (aBoundary);
+ }
+
+ ByteString aPlainDelim (pMsg->GetMultipartBoundary());
+ ByteString aDelim ("--");
+ aDelim += aPlainDelim;
+
+ ByteString aPlainClose (aPlainDelim);
+ aPlainClose += "--";
+
+ ByteString aClose (aDelim);
+ aClose += "--";
+
+ if (pMsgBuffer == NULL) pMsgBuffer = new SvMemoryStream;
+ pMsgBuffer->Write (pData, nSize);
+ ULONG nBufSize = pMsgBuffer->Tell();
+
+ const sal_Char* pChar;
+ const sal_Char* pOldPos;
+ for( pOldPos = pChar = (const sal_Char *) pMsgBuffer->GetData(); nBufSize--;
+ pChar++ )
+ {
+ int status;
+ if( *pChar == '\r' || *pChar == '\n' )
+ {
+ if( aDelim.CompareTo (pOldPos, aDelim.Len())
+ != COMPARE_EQUAL &&
+ aClose.CompareTo (pOldPos, aClose.Len())
+ != COMPARE_EQUAL &&
+ aPlainDelim.CompareTo (pOldPos, aPlainDelim.Len())
+ != COMPARE_EQUAL &&
+ aPlainClose.CompareTo(pOldPos, aPlainClose.Len())
+ != COMPARE_EQUAL )
+ {
+ if( nBufSize &&
+ ( pChar[1] == '\r' || pChar[1] == '\n' ) )
+ nBufSize--, pChar++;
+ if( pChildStrm )
+ {
+ status = pChildStrm->Write(
+ pOldPos, pChar - pOldPos + 1 );
+ if( status != INETSTREAM_STATUS_OK )
+ return status;
+ }
+ else
+ DBG_ERRORFILE( "Die Boundary nicht gefunden" );
+ status = INetMessageIOStream::PutMsgLine(
+ pOldPos, pChar - pOldPos + 1, pCtx );
+ if( status != INETSTREAM_STATUS_OK )
+ return status;
+ pOldPos = pChar + 1;
+ }
+ else
+ {
+ if( nBufSize &&
+ ( pChar[1] == '\r' || pChar[1] == '\n' ) )
+ nBufSize--, pChar++;
+ pOldPos = pChar + 1;
+ DELETEZ( pChildStrm );
+
+ if (aClose.CompareTo (pOldPos, aClose.Len())
+ != COMPARE_EQUAL &&
+ aPlainClose.CompareTo (pOldPos, aClose.Len())
+ != COMPARE_EQUAL )
+ {
+ // Encapsulated message.
+ pMsg->SetChildCount(pMsg->GetChildCount() + 1);
+ INetMIMEMessage* pNewMessage =
+ new INetMIMEMessage;
+ pNewMessage->SetDocumentLB (
+ new SvAsyncLockBytes (
+ new SvCacheStream, FALSE));
+
+ pMsg->AttachChild( *pNewMessage, TRUE );
+
+ // Encapsulated message body. Create message parser stream.
+ pChildStrm = new INetMIMEMessageStream;
+ pChildStrm->SetTargetMessage ( pNewMessage );
+
+ // Initialize control variables.
+ }
+ eState = INETMSG_EOL_BEGIN;
+ status = INetMessageIOStream::PutMsgLine(
+ pOldPos, pChar - pOldPos + 1, pCtx );
+ if( status != INETSTREAM_STATUS_OK )
+ return status;
+ }
+ }
+ }
+ if( pOldPos < pChar )
+ {
+ SvMemoryStream* pNewStream = new SvMemoryStream;
+ pNewStream->Write( pOldPos, pChar - pOldPos );
+ SvMemoryStream* pTmp = pMsgBuffer;
+ pMsgBuffer = pNewStream;
+ delete pTmp;
+ }
+ else
+ {
+ pMsgBuffer->Seek( 0L );
+ pMsgBuffer->SetStreamSize( 0 );
+ }
+ return INETSTREAM_STATUS_OK;
+ }
+ }
+ else
+ {
+ /*
+ * Single part message.
+ * Remove any ContentTransferEncoding.
+ */
+ if (pMsg->GetContentType().Len() == 0)
+ {
+ String aDefaultCT;
+ pMsg->GetDefaultContentType (aDefaultCT);
+ pMsg->SetContentType (aDefaultCT);
+ }
+
+ if (eEncoding == INETMSG_ENCODING_BINARY)
+ {
+ String aEncoding (pMsg->GetContentTransferEncoding());
+ if (aEncoding.CompareIgnoreCaseToAscii (
+ "base64", 6) == COMPARE_EQUAL)
+ eEncoding = INETMSG_ENCODING_BASE64;
+ else if (aEncoding.CompareIgnoreCaseToAscii (
+ "quoted-printable", 16) == COMPARE_EQUAL)
+ eEncoding = INETMSG_ENCODING_QUOTED;
+ else
+ eEncoding = INETMSG_ENCODING_7BIT;
+ }
+
+ if (eEncoding == INETMSG_ENCODING_7BIT)
+ {
+ // No decoding necessary.
+ return INetMessageIOStream::PutMsgLine (
+ pData, nSize, pCtx);
+ }
+ else
+ {
+ if (pDecodeStrm == NULL)
+ {
+ if (eEncoding == INETMSG_ENCODING_QUOTED)
+ pDecodeStrm = new INetMessageDecodeQPStream_Impl;
+ else
+ pDecodeStrm = new INetMessageDecode64Stream_Impl;
+
+ pDecodeStrm->SetTargetMessage (pMsg);
+ }
+ return pDecodeStrm->Write (pData, nSize, pCtx);
+ }
+ }
+ }
+}
+
+/*=========================================================================
+ *
+ * INetMessageDecodeGZStream_Impl Implementation.
+ * (GZIP Decoding).
+ *
+ *=======================================================================*/
+class INetMessageDecodeGZStream_Impl : public INetMessageOStream
+{
+ SvMemoryStream m_aStrm;
+ GZCodec m_aCodec;
+ sal_uInt8 m_pBuffer[1024];
+
+ virtual int PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx = NULL);
+
+public:
+ INetMessageDecodeGZStream_Impl (void);
+};
+
+/*
+ * INetMessageDecodeGZStream_Impl.
+ */
+INetMessageDecodeGZStream_Impl::INetMessageDecodeGZStream_Impl (void)
+ : INetMessageOStream()
+{
+ ParseHeader (FALSE);
+ m_aCodec.BeginCompression();
+}
+
+/*
+ * PutMsgLine.
+ */
+int INetMessageDecodeGZStream_Impl::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ INetMessage *pMsg = GetTargetMessage();
+ if (pMsg == NULL)
+ return INETSTREAM_STATUS_ERROR;
+
+ SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
+ if (pLB == NULL)
+ return INETSTREAM_STATUS_WOULDBLOCK;
+
+ m_aStrm.Seek (STREAM_SEEK_TO_BEGIN);
+ m_aStrm.Write (pData, nSize);
+
+ m_aStrm.Seek (STREAM_SEEK_TO_BEGIN);
+ long nRead = 0;
+
+ // Decode into buffer.
+ m_aCodec.SetBreak (nSize);
+ while ((nRead = m_aCodec.Read (m_aStrm, m_pBuffer, sizeof(m_pBuffer))) > 0)
+ {
+ // Emit Buffer.
+ ULONG nDocSize = pMsg->GetDocumentSize();
+ ULONG nWrite = 0;
+
+ pLB->FillAppend (m_pBuffer, nRead, &nWrite);
+ pMsg->SetDocumentSize (nDocSize + nWrite);
+
+ if ((long)nWrite < nRead)
+ return INETSTREAM_STATUS_ERROR;
+ }
+
+ if (m_aCodec.IsFinished())
+ return INETSTREAM_STATUS_LOADED;
+ else if (nRead < 0)
+ return INETSTREAM_STATUS_ERROR;
+ else
+ return INETSTREAM_STATUS_OK;
+}
+
+/*=========================================================================
+ *
+ * INetHTTPMessageStream Implementation.
+ *
+ *=======================================================================*/
+/*
+ * INetHTTPMessageStream.
+ */
+INetHTTPMessageStream::INetHTTPMessageStream (ULONG nBufferSize)
+ : INetMIMEMessageStream (nBufferSize),
+ m_eState (INETMSG_EOL_BEGIN),
+ m_pDecodeStrm (NULL)
+{
+}
+
+/*
+ * ~INetHTTPMessageStream.
+ */
+INetHTTPMessageStream::~INetHTTPMessageStream (void)
+{
+ delete m_pDecodeStrm;
+}
+
+/*
+ * GetMsgLine.
+ * (Message Generator).
+ */
+int INetHTTPMessageStream::GetMsgLine (
+ sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ // Check for header generation.
+ if (!IsHeaderGenerated())
+ {
+ if (m_eState == INETMSG_EOL_BEGIN)
+ {
+ // Check for message container.
+ INetHTTPMessage *pMsg = GetSourceMessage();
+ if (pMsg == NULL)
+ return INETSTREAM_STATUS_ERROR;
+
+ // Set Accept-Encoding header.
+ pMsg->SetAcceptEncoding (
+ String ("gzip", RTL_TEXTENCODING_ASCII_US));
+
+ // Mark done.
+ m_eState = INETMSG_EOL_DONE;
+ }
+ }
+
+ // Initial approximation: Generate as plain message (w/o encoding).
+ return INetMessageIOStream::GetMsgLine (pData, nSize, pCtx);
+}
+
+/*
+ * PutMsgLine.
+ * (Message Parser).
+ */
+int INetHTTPMessageStream::PutMsgLine (
+ const sal_Char *pData, ULONG nSize, void *pCtx)
+{
+ // Check for header or body.
+ if (!IsHeaderParsed())
+ {
+ // Parse the message header.
+ return INetMessageIOStream::PutMsgLine (pData, nSize, pCtx);
+ }
+ else
+ {
+ // Parse the message body.
+ if (m_eState == INETMSG_EOL_BEGIN)
+ {
+ // Check for message container.
+ INetHTTPMessage *pMsg = GetTargetMessage();
+ if (pMsg == NULL)
+ return INETSTREAM_STATUS_ERROR;
+
+ // Obtain ContentEncoding.
+ String aEncoding (pMsg->GetContentEncoding());
+ aEncoding.EraseLeadingChars (' ');
+
+ // Check for supported encoding.
+ if ((aEncoding.CompareIgnoreCaseToAscii ("gzip") == 0) ||
+ (aEncoding.CompareIgnoreCaseToAscii ("x-gzip") == 0) )
+ {
+ // Initialize decode stream.
+ m_pDecodeStrm = new INetMessageDecodeGZStream_Impl;
+ m_pDecodeStrm->SetTargetMessage (pMsg);
+ }
+
+ // Mark done.
+ m_eState = INETMSG_EOL_DONE;
+ }
+
+ // Check for Decode stream.
+ if (m_pDecodeStrm)
+ {
+ // Decode.
+ return m_pDecodeStrm->Write (pData, nSize, pCtx);
+ }
+ else
+ {
+ // No decoding necessary.
+ return INetMessageIOStream::PutMsgLine (pData, nSize, pCtx);
+ }
+ }
+}
+
diff --git a/tools/source/inet/makefile.mk b/tools/source/inet/makefile.mk
new file mode 100644
index 000000000000..74926210cd36
--- /dev/null
+++ b/tools/source/inet/makefile.mk
@@ -0,0 +1,83 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ = ..$/..
+PRJNAME = tools
+TARGET = inet
+
+.INCLUDE: svpre.mk
+.INCLUDE: settings.mk
+.INCLUDE: sv.mk
+
+SLOFILES=\
+ $(SLO)$/inetmime.obj \
+ $(SLO)$/inetmsg.obj \
+ $(SLO)$/inetstrm.obj
+
+.IF "$(UPDATER)" != ""
+OBJFILES=\
+ $(OBJ)$/inetmime.obj \
+ $(OBJ)$/inetmsg.obj \
+ $(OBJ)$/inetstrm.obj
+.ENDIF
+
+.INCLUDE: target.mk
diff --git a/tools/source/makefile.mk b/tools/source/makefile.mk
new file mode 100644
index 000000000000..d340637a4f27
--- /dev/null
+++ b/tools/source/makefile.mk
@@ -0,0 +1,96 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:05 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..
+
+TARGET=source
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUI)" == "UNX"
+SUBDIRS+= solar
+.ENDIF
+
+SUBDIRS+= \
+ datetime \
+ timestamp \
+ debug \
+ fsys \
+ generic \
+ intntl \
+ memmgr \
+ memtools \
+ misc \
+ rc \
+ ref \
+ stream \
+ zcodec
+
+
+.INCLUDE : target.mk
+
diff --git a/tools/source/memtools/contnr.cxx b/tools/source/memtools/contnr.cxx
new file mode 100644
index 000000000000..8228ecb4c880
--- /dev/null
+++ b/tools/source/memtools/contnr.cxx
@@ -0,0 +1,1754 @@
+/*************************************************************************
+ *
+ * $RCSfile: contnr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define private public
+#define protected public
+
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef _STRING_H
+#include <string.h>
+#endif
+
+#ifndef _STDIO_H
+#include <stdio.h>
+#endif
+
+#ifndef _SOLAR_H
+#include <solar.h>
+#endif
+
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+
+#ifndef _CONTNR_HXX
+#include <contnr.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+
+// -----------------------------------------------------------------------
+
+DBG_NAME( CBlock );
+DBG_NAME( Container );
+
+/*************************************************************************
+|*
+|* DbgCheckCBlock()
+|*
+|* Beschreibung Pruefung eines CBlock fuer Debug-Utilities
+|* Ersterstellung MI 30.01.92
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* DbgCheckCBlock( const void* pBlock )
+{
+ CBlock* p = (CBlock*)pBlock;
+
+ if ( p->nCount > p->nSize )
+ return "nCount > nSize";
+
+ if ( p->nSize && !p->pNodes )
+ return "nSize > 0 && pNodes == NULL";
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( USHORT nInitSize, CBlock* _pPrev, CBlock* _pNext )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+
+ pPrev = _pPrev;
+ pNext = _pNext;
+ nSize = nInitSize;
+ nCount = 0;
+
+ // Datenpuffer anlegen
+ pNodes = (void**)new PVOID[nSize];
+}
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( USHORT _nSize, CBlock* _pPrev )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( _nSize, "CBlock::CBlock(): nSize == 0" );
+
+ pPrev = _pPrev;
+ pNext = NULL;
+ nSize = _nSize;
+ nCount = _nSize;
+
+ // Datenpuffer anlegen und initialisieren
+ pNodes = (void**)new PVOID[nSize];
+ memset( pNodes, 0, nSize*sizeof(PVOID) );
+}
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Copy-Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( const CBlock& r, CBlock* _pPrev )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+ DBG_CHKOBJ( &r, CBlock, DbgCheckCBlock );
+
+ pPrev = _pPrev;
+ pNext = NULL;
+ nSize = r.nSize;
+ nCount = r.nCount;
+
+ // Datenpuffer anlegen und Daten kopieren
+ pNodes = (void**)new PVOID[nSize];
+ memcpy( pNodes, r.pNodes, nCount*sizeof(PVOID) );
+}
+
+/*************************************************************************
+|*
+|* CBlock::~CBlock()
+|*
+|* Beschreibung Destruktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+inline CBlock::~CBlock()
+{
+ DBG_DTOR( CBlock, DbgCheckCBlock );
+
+ // Daten loeschen
+ delete pNodes;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Insert()
+|*
+|* Beschreibung Fuegt einen Pointer ein
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void CBlock::Insert( void* p, USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" );
+
+ // Muss Block realokiert werden
+ if ( nCount == nSize )
+ {
+ // Neue Daten anlegen
+ nSize += nReSize;
+ void** pNewNodes = (void**)new PVOID[nSize];
+
+ // Wird angehaengt
+ if ( nCount == nIndex )
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ }
+ else
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
+ memcpy( pNewNodes + nIndex + 1,
+ pNodes + nIndex,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+
+ // Alte Daten loeschen und neue setzen
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+ else
+ {
+ if ( nIndex < nCount )
+ {
+ memmove( pNodes + nIndex + 1,
+ pNodes + nIndex,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+ }
+
+ // Neuen Pointer setzen und Elementgroesse erhoehen
+ pNodes[nIndex] = p;
+ nCount++;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Split()
+|*
+|* Beschreibung Fuegt einen Pointer ein und splittet den Block
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock* CBlock::Split( void* p, USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ USHORT nNewSize;
+ USHORT nMiddle;
+ CBlock* pNewBlock;
+
+ nMiddle = nCount/2;
+
+ if ( ( nIndex == nCount ) || ( nIndex == 0 ) )
+ nNewSize = nReSize;
+ else
+ {
+ // Der aktuelle Block wird in der Mitte geteilt
+ nNewSize = (nCount+1) / 2;
+
+ if ( nNewSize < nReSize )
+ nNewSize = nReSize;
+ else
+ {
+ // Neue Groesse muss ein vielfaches von Resize sein
+ if ( nNewSize % nReSize )
+ nNewSize += nReSize - (nNewSize % nReSize);
+ else
+ nNewSize += nReSize;
+ }
+ }
+
+ // Vor oder hinter dem aktuellem Block einfuegen?
+ if ( nIndex > nMiddle )
+ {
+ // Neuen Split-Block anlegen und hinter dem aktuellem Block einfuegen
+ pNewBlock = new CBlock( nNewSize, this, pNext );
+
+ if ( pNext )
+ pNext->pPrev = pNewBlock;
+ pNext = pNewBlock;
+
+ if ( nIndex == nCount )
+ {
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[0] = p;
+ pNewBlock->nCount = 1;
+ }
+ else
+ {
+ nIndex -= nMiddle;
+ // Alles von Mitte bis Index kopieren
+ if ( nIndex )
+ memcpy( pNewBlock->pNodes, pNodes+nMiddle, nIndex*sizeof(PVOID) );
+
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[nIndex] = p;
+
+ // Alles von Mitte bis Ende hinter Index kopieren
+ memcpy( pNewBlock->pNodes+nIndex+1,
+ pNodes+nMiddle+nIndex,
+ (nCount-nMiddle-nIndex) * sizeof(PVOID) );
+
+ pNewBlock->nCount = (nCount-nMiddle+1);
+ nCount = nMiddle;
+
+ // Den aktuellen Datenbereich auch halbieren
+ if ( nSize != nNewSize )
+ {
+ void** pNewNodes = (void**)new PVOID[nNewSize];
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ delete pNodes;
+ pNodes = pNewNodes;
+ nSize = nNewSize;
+ }
+ }
+ }
+ else
+ {
+ // Neuen Split-Block anlegen und vor dem aktuellem Block einfuegen
+ pNewBlock = new CBlock( nNewSize, pPrev, this );
+
+ if ( pPrev )
+ pPrev->pNext = pNewBlock;
+ pPrev = pNewBlock;
+
+ if ( nIndex == 0 )
+ {
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[0] = p;
+ pNewBlock->nCount = 1;
+ }
+ else
+ {
+ // Alles von Anfang bis Index kopieren
+ memcpy( pNewBlock->pNodes, pNodes, nIndex*sizeof(PVOID) );
+
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[nIndex] = p;
+
+ // Alles von Index bis Mitte hinter Index kopieren
+ if ( nIndex != nMiddle )
+ {
+ memcpy( pNewBlock->pNodes+nIndex+1,
+ pNodes+nIndex,
+ (nMiddle-nIndex) * sizeof(PVOID) );
+ }
+
+ pNewBlock->nCount = nMiddle+1;
+ nCount -= nMiddle;
+
+ // Die zweite Haelfte in einen neuen Block kopieren
+ if ( nSize != nNewSize )
+ {
+ void** pNewNodes = (void**)new PVOID[nNewSize];
+ memcpy( pNewNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
+ delete pNodes;
+ pNodes = pNewNodes;
+ nSize = nNewSize;
+ }
+ else
+ memmove( pNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
+ }
+ }
+
+ // Neu angelegten Block zurueckgeben, da gegebenfalls die Blockpointer
+ // im Container angepast werden koennen
+ return pNewBlock;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Remove()
+|*
+|* Beschreibung Entfernt einen Pointer
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* CBlock::Remove( USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ // Alten Pointer sichern
+ void* pOld = pNodes[nIndex];
+
+ // 1 Element weniger
+ nCount--;
+
+ // Block verkleinern (wenn Reallokationsgroesse um 4 unterschritten wird)
+ if ( nCount == (nSize-nReSize-4) )
+ {
+ // Neue Daten anlegen
+ nSize -= nReSize;
+ void** pNewNodes = (void**)new PVOID[nSize];
+
+ // Wird letzter Eintrag geloescht
+ if ( nIndex == nCount )
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ }
+ else
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
+ memcpy( pNewNodes + nIndex, pNodes + nIndex+1,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+
+ // Alte Daten loeschen und neue setzen
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+ else
+ {
+ // Wenn nicht das letzte Element, dann zusammenschieben
+ if ( nIndex < nCount )
+ {
+ memmove( pNodes + nIndex, pNodes + nIndex + 1,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+ }
+
+ // Alten Pointer zurueckgeben
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Replace()
+|*
+|* Beschreibung Ersetzt einen Pointer
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+inline void* CBlock::Replace( void* p, USHORT nIndex )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ // Alten Pointer sichern, neuen setzen und alten zurueckgeben
+ void* pOld = pNodes[nIndex];
+ pNodes[nIndex] = p;
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* CBlock::GetObjectPtr()
+|*
+|* Beschreibung Gibt einen Pointer auf den Pointer aus dem Block
+|* zurueck
+|* Ersterstellung TH 26.01.93
+|* Letzte Aenderung TH 26.01.93
+|*
+*************************************************************************/
+
+inline void** CBlock::GetObjectPtr( USHORT nIndex )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ return &(pNodes[nIndex]);
+}
+
+/*************************************************************************
+|*
+|* CBlock::SetSize()
+|*
+|* Beschreibung Aendert die Groesse des Blocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void CBlock::SetSize( USHORT nNewSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( nNewSize, "CBlock::SetSize(): nNewSize == 0" );
+
+ // Unterscheidet sich die Groesse
+ if ( nNewSize != nCount )
+ {
+ // Array erweitern
+ void** pNewNodes = new PVOID[nNewSize];
+
+ // Alte Tabelle in die Neue kopieren
+ if ( nNewSize < nCount )
+ memcpy( pNewNodes, pNodes, nNewSize*sizeof(PVOID) );
+ else
+ {
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+
+ // Array mit 0 initialisieren
+ memset( pNewNodes+nCount, 0, (nNewSize-nCount)*sizeof(PVOID) );
+ }
+
+ // Altes Array loeschen und neue Werte setzen
+ nSize = nNewSize;
+ nCount = nSize;
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+}
+
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* DbgCheckContainer()
+|*
+|* Beschreibung Pruefung eines Container fuer Debug-Utilities
+|* Ersterstellung MI 30.01.92
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* DbgCheckContainer( const void* pCont )
+{
+ Container* p = (Container*)pCont;
+
+ if ( p->nCount && (!p->pFirstBlock || !p->pLastBlock || !p->pCurBlock) )
+ return "nCount > 0 but no CBlocks";
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* ImpCopyContainer()
+|*
+|* Beschreibung Kopiert alle Daten des Containers
+|* Ersterstellung TH 24.01.96
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+static void ImpCopyContainer( Container* pCont1, const Container* pCont2 )
+{
+ // Werte vom uebergebenen Container uebernehmen
+ pCont1->nCount = pCont2->nCount;
+ pCont1->nCurIndex = pCont2->nCurIndex;
+ pCont1->nInitSize = pCont2->nInitSize;
+ pCont1->nReSize = pCont2->nReSize;
+ pCont1->nBlockSize = pCont2->nBlockSize;
+
+ // Alle Bloecke kopieren
+ if ( pCont2->nCount )
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+ CBlock* pTempBlock;
+
+ // Erstmal ersten Block kopieren
+ pBlock2 = pCont2->pFirstBlock;
+ pCont1->pFirstBlock = new CBlock( *pBlock2, NULL );
+ // Ist erster Block der Current-Block, dann Current-Block setzen
+ if ( pBlock2 == pCont2->pCurBlock )
+ pCont1->pCurBlock = pCont1->pFirstBlock;
+ pBlock1 = pCont1->pFirstBlock;
+ pBlock2 = pBlock2->GetNextBlock();
+ while ( pBlock2 )
+ {
+ // Neuen Block anlegen und aus der uebergebenen Liste kopieren
+ pTempBlock = new CBlock( *pBlock2, pBlock1 );
+ pBlock1->SetNextBlock( pTempBlock );
+ pBlock1 = pTempBlock;
+
+ // Current-Block beruecksichtigen
+ if ( pBlock2 == pCont2->pCurBlock )
+ pCont1->pCurBlock = pBlock1;
+
+ // Auf naechsten Block weitersetzen
+ pBlock2 = pBlock2->GetNextBlock();
+ }
+
+ // Letzten Block setzen
+ pCont1->pLastBlock = pBlock1;
+ }
+ else
+ {
+ pCont1->pFirstBlock = NULL;
+ pCont1->pLastBlock = NULL;
+ pCont1->pCurBlock = NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( USHORT _nBlockSize, USHORT _nInitSize, USHORT _nReSize )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ // BlockSize muss mindestens 4 sein und kleiner als 64 KB
+ if ( _nBlockSize < 4 )
+ nBlockSize = 4;
+ else
+ {
+ if ( _nBlockSize < CONTAINER_MAXBLOCKSIZE )
+ nBlockSize = _nBlockSize;
+ else
+ nBlockSize = CONTAINER_MAXBLOCKSIZE;
+ }
+
+ // ReSize muss mindestens 2 sein und kleiner als BlockSize
+ if ( _nReSize >= nBlockSize )
+ nReSize = nBlockSize;
+ else
+ {
+ if ( _nReSize < 2 )
+ nReSize = 2;
+ else
+ nReSize = _nReSize;
+
+ // BlockSize muss ein vielfaches der Resizegroesse sein
+ if ( nBlockSize % nReSize )
+ nBlockSize -= nReSize - (nBlockSize % nReSize);
+ }
+
+ // InitSize muss groesser gleich ReSize sein und kleiner als BlockSize
+ if ( _nInitSize <= nReSize )
+ nInitSize = nReSize;
+ else
+ {
+ if ( _nInitSize >= nBlockSize )
+ nInitSize = nBlockSize;
+ else
+ {
+ nInitSize = _nInitSize;
+
+ // InitSize muss ein vielfaches der Resizegroesse sein
+ if ( nInitSize % nReSize )
+ nInitSize -= nReSize - (nInitSize % nReSize);
+ }
+ }
+
+ // Werte initialisieren
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ nCount = 0;
+ nCurIndex = 0;
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( ULONG nSize )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ nCount = nSize;
+ nCurIndex = 0;
+ nBlockSize = CONTAINER_MAXBLOCKSIZE;
+ nInitSize = 1;
+ nReSize = 1;
+
+ if ( !nSize )
+ {
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ }
+ else
+ {
+ // Muss mehr als ein Block angelegt werden
+ if ( nSize <= nBlockSize )
+ {
+ pFirstBlock = new CBlock( (USHORT)nSize, NULL );
+ pLastBlock = pFirstBlock;
+ }
+ else
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+
+ pFirstBlock = new CBlock( nBlockSize, NULL );
+ pBlock1 = pFirstBlock;
+ nSize -= nBlockSize;
+
+ // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
+ while ( nSize > nBlockSize )
+ {
+ pBlock2 = new CBlock( nBlockSize, pBlock1 );
+ pBlock1->SetNextBlock( pBlock2 );
+ pBlock1 = pBlock2;
+ nSize -= nBlockSize;
+ }
+
+ pLastBlock = new CBlock( (USHORT)nSize, pBlock1 );
+ pBlock1->SetNextBlock( pLastBlock );
+ }
+
+ pCurBlock = pFirstBlock;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( const Container& r )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ // Daten kopieren
+ ImpCopyContainer( this, &r );
+}
+
+/*************************************************************************
+|*
+|* Container::~Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::~Container()
+{
+ DBG_DTOR( Container, DbgCheckContainer );
+
+ // Alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::ImpInsert()
+|*
+|* Beschreibung Interne Methode zum Einfuegen eines Pointers
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung DV 01.07.97
+|*
+*************************************************************************/
+
+void Container::ImpInsert( void* p, CBlock* pBlock, USHORT nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( !nCount )
+ {
+ if ( !pBlock )
+ {
+ pFirstBlock = new CBlock( nInitSize, NULL, NULL );
+ pLastBlock = pFirstBlock;
+ pCurBlock = pFirstBlock;
+ }
+ pFirstBlock->Insert( p, nIndex, nReSize );
+ }
+ else
+ {
+ // Ist im Block die maximale Blockgroesse erreicht,
+ // dann neuen Block anlegen
+ if ( pBlock->Count() == nBlockSize )
+ {
+ // Block auftrennen
+ CBlock* pNewBlock = pBlock->Split( p, nIndex, nReSize );
+
+ // Wurde Block dahinter angehaegnt
+ if ( pBlock->pNext == pNewBlock )
+ {
+ // Gegebenenfalls LastBlock anpassen
+ if ( pBlock == pLastBlock )
+ pLastBlock = pNewBlock;
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( pBlock->nCount <= nCurIndex )
+ {
+ if ( nIndex <= nCurIndex )
+ nCurIndex++;
+ pCurBlock = pNewBlock;
+ nCurIndex -= pBlock->nCount;
+ }
+ }
+ }
+ else
+ {
+ // Gegebenenfalls FirstBlock anpassen
+ if ( pBlock == pFirstBlock )
+ pFirstBlock = pNewBlock;
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( nIndex <= nCurIndex )
+ nCurIndex++;
+ if ( pNewBlock->nCount <= nCurIndex )
+ nCurIndex -= pNewBlock->nCount;
+ else
+ pCurBlock = pNewBlock;
+ }
+ }
+ }
+ else
+ {
+ // Sonst reicht normales einfuegen in den Block
+ pBlock->Insert( p, nIndex, nReSize );
+
+ // Current-Position nachfuehren
+ if ( (pBlock == pCurBlock) && (nIndex <= nCurIndex) )
+ nCurIndex++;
+ }
+ }
+
+ // Ein neues Item im Container
+ nCount++;
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* p )
+{
+ ImpInsert( p, pCurBlock, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* p, ULONG nIndex )
+{
+ if ( nCount <= nIndex )
+ {
+ if ( pLastBlock )
+ ImpInsert( p, pLastBlock, pLastBlock->Count() );
+ else
+ ImpInsert( p, NULL, 0 );
+ }
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() < nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ ImpInsert( p, pTemp, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* pNew, void* pOld )
+{
+ ULONG nIndex = GetPos( pOld );
+ if ( nIndex != CONTAINER_ENTRY_NOTFOUND )
+ Insert( pNew, nIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::ImpRemove()
+|*
+|* Beschreibung Interne Methode zum Entfernen eines Pointers
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::ImpRemove( CBlock* pBlock, USHORT nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ void* pOld;
+
+ // Ist Liste danach leer
+ if ( nCount == 1 )
+ {
+ // Block und CurIndex zuruecksetzen
+ pOld = pBlock->GetObject( nIndex );
+ pBlock->Reset();
+ nCurIndex = 0;
+ }
+ else
+ {
+ // Ist Block nach Remove leer
+ if ( pBlock->Count() == 1 )
+ {
+ // dann Block entfernen und Block-Pointer umsetzen
+ if ( pBlock->GetPrevBlock() )
+ (pBlock->GetPrevBlock())->SetNextBlock( pBlock->GetNextBlock() );
+ else
+ pFirstBlock = pBlock->GetNextBlock();
+
+ if ( pBlock->GetNextBlock() )
+ (pBlock->GetNextBlock())->SetPrevBlock( pBlock->GetPrevBlock() );
+ else
+ pLastBlock = pBlock->GetPrevBlock();
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( pBlock->GetNextBlock() )
+ {
+ pCurBlock = pBlock->GetNextBlock();
+ nCurIndex = 0;
+ }
+ else
+ {
+ pCurBlock = pBlock->GetPrevBlock();
+ nCurIndex = pCurBlock->Count()-1;
+ }
+ }
+
+ pOld = pBlock->GetObject( nIndex );
+ delete pBlock;
+ }
+ else
+ {
+ // Sonst Item aus dem Block entfernen
+ pOld = pBlock->Remove( nIndex, nReSize );
+
+ // Current-Position nachfuehren
+ if ( (pBlock == pCurBlock) &&
+ ((nIndex < nCurIndex) || ((nCurIndex == pBlock->Count()) && nCurIndex)) )
+ nCurIndex--;
+ }
+ }
+
+ // Jetzt gibt es ein Item weniger
+ nCount--;
+
+ // Und den Pointer zurueckgeben, der entfernt wurde
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* Container::Remove()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Remove()
+{
+ // Wenn kein Item vorhanden ist, NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ return ImpRemove( pCurBlock, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Remove()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Remove( ULONG nIndex )
+{
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return ImpRemove( pTemp, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Replace()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Replace( void* p )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( !nCount )
+ return NULL;
+ else
+ return pCurBlock->Replace( p, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Replace()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Replace( void* p, ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return pTemp->Replace( p, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::SetSize()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::SetSize( ULONG nNewSize )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( nNewSize )
+ {
+ // Unterscheiden sich die Groessen
+ if ( nNewSize != nCount )
+ {
+ CBlock* pTemp;
+ ULONG nTemp;
+
+ // Wird verkleinert
+ if ( nNewSize < nCount )
+ {
+ pTemp = pFirstBlock;
+ nTemp = 0;
+ while ( (nTemp+pTemp->Count()) < nNewSize )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Alle folgenden Bloecke loeschen
+ BOOL bLast = FALSE;
+ CBlock* pDelNext;
+ CBlock* pDelBlock = pTemp->GetNextBlock();
+ while ( pDelBlock )
+ {
+ // Muss CurrentBlock umgesetzt werden
+ if ( pDelBlock == pCurBlock )
+ bLast = TRUE;
+ pDelNext = pDelBlock->GetNextBlock();
+ delete pDelBlock;
+ pDelBlock = pDelNext;
+ }
+
+ // Block in der Groesse anpassen, oder bei Groesse 0 loeschen
+ if ( nNewSize > nTemp )
+ {
+ pLastBlock = pTemp;
+ pTemp->SetNextBlock( NULL );
+ pTemp->SetSize( (USHORT)(nNewSize-nTemp) );
+ }
+ else
+ {
+ pLastBlock = pTemp->GetPrevBlock();
+ pLastBlock->SetNextBlock( NULL );
+ delete pTemp;
+ }
+
+ nCount = nNewSize;
+ if ( bLast )
+ {
+ pCurBlock = pLastBlock;
+ nCurIndex = pCurBlock->Count()-1;
+ }
+ }
+ else
+ {
+ // Auf den letzen Puffer setzen
+ pTemp = pLastBlock;
+ nTemp = nNewSize - nCount;
+
+ if ( !pTemp )
+ {
+ // Muss mehr als ein Block angelegt werden
+ if ( nNewSize <= nBlockSize )
+ {
+ pFirstBlock = new CBlock( (USHORT)nNewSize, NULL );
+ pLastBlock = pFirstBlock;
+ }
+ else
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+
+ pFirstBlock = new CBlock( nBlockSize, NULL );
+ pBlock1 = pFirstBlock;
+ nNewSize -= nBlockSize;
+
+ // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
+ while ( nNewSize > nBlockSize )
+ {
+ pBlock2 = new CBlock( nBlockSize, pBlock1 );
+ pBlock1->SetNextBlock( pBlock2 );
+ pBlock1 = pBlock2;
+ nNewSize -= nBlockSize;
+ }
+
+ pLastBlock = new CBlock( (USHORT)nNewSize, pBlock1 );
+ pBlock1->SetNextBlock( pLastBlock );
+ }
+
+ pCurBlock = pFirstBlock;
+ }
+ // Reicht es, den letzen Puffer in der Groesse anzupassen
+ else if ( (nTemp+pTemp->Count()) <= nBlockSize )
+ pTemp->SetSize( (USHORT)(nTemp+pTemp->Count()) );
+ else
+ {
+ // Puffer auf max. Blockgroesse setzen
+ nTemp -= nBlockSize - pTemp->GetSize();
+ pTemp->SetSize( nBlockSize );
+
+ CBlock* pTemp2;
+ // Solange die Blockgroesse ueberschritten wird,
+ // neue Bloecke anlegen
+ while ( nTemp > nBlockSize )
+ {
+ pTemp2 = new CBlock( nBlockSize, pTemp );
+ pTemp->SetNextBlock( pTemp2 );
+ pTemp = pTemp2;
+ nTemp -= nBlockSize;
+ }
+
+ // Den letzten Block anlegen
+ if ( nTemp )
+ {
+ pLastBlock = new CBlock( (USHORT)nTemp, pTemp );
+ pTemp->SetNextBlock( pLastBlock );
+ }
+ else
+ pLastBlock = pTemp;
+ }
+
+ nCount = nNewSize;
+ }
+ }
+ }
+ else
+ Clear();
+}
+
+/*************************************************************************
+|*
+|* Container::Clear()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Clear()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Erst alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+
+ // Werte zuruecksetzen
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ nCount = 0;
+ nCurIndex = 0;
+}
+
+/*************************************************************************
+|*
+|* Container::GetCurObject()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::GetCurObject() const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // NULL, wenn Container leer
+ if ( !nCount )
+ return NULL;
+ else
+ return pCurBlock->GetObject( nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::GetCurPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+ULONG Container::GetCurPos() const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // CONTAINER_ENTRY_NOTFOUND, wenn Container leer
+ if ( !nCount )
+ return CONTAINER_ENTRY_NOTFOUND;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ ULONG nTemp = 0;
+ while ( pTemp != pCurBlock )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return nTemp+nCurIndex;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetObjectPtr()
+|*
+|* Beschreibung Interne Methode fuer Referenz-Container
+|* Ersterstellung TH 26.01.93
+|* Letzte Aenderung TH 26.01.93
+|*
+*************************************************************************/
+
+void** Container::GetObjectPtr( ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ return pTemp->GetObjectPtr( (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetObject()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::GetObject( ULONG nIndex ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ return pTemp->GetObject( (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+ULONG Container::GetPos( const void* p ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ void** pNodes;
+ CBlock* pTemp;
+ ULONG nTemp;
+ USHORT nBlockCount;
+ USHORT i;
+
+ // Block suchen
+ pTemp = pFirstBlock;
+ nTemp = 0;
+ while ( pTemp )
+ {
+ pNodes = pTemp->GetNodes();
+ i = 0;
+ nBlockCount = pTemp->Count();
+ while ( i < nBlockCount )
+ {
+ if ( p == *pNodes )
+ return nTemp+i;
+ pNodes++;
+ i++;
+ }
+ nTemp += nBlockCount;
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return CONTAINER_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* Container::GetPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 14.09.94
+|* Letzte Aenderung TH 14.09.94
+|*
+*************************************************************************/
+
+ULONG Container::GetPos( const void* p, ULONG nStartIndex,
+ BOOL bForward ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NOTFOUND zurueckgeben
+ if ( nCount <= nStartIndex )
+ return CONTAINER_ENTRY_NOTFOUND;
+ else
+ {
+ void** pNodes;
+ USHORT nBlockCount;
+ USHORT i;
+
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ ULONG nTemp = 0;
+ while ( nTemp+pTemp->Count() <= nStartIndex )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Jetzt den Pointer suchen
+ if ( bForward )
+ {
+ // Alle Bloecke durchrsuchen
+ i = (USHORT)(nStartIndex - nTemp);
+ pNodes = pTemp->GetObjectPtr( i );
+ do
+ {
+ nBlockCount = pTemp->Count();
+ while ( i < nBlockCount )
+ {
+ if ( p == *pNodes )
+ return nTemp+i;
+ pNodes++;
+ i++;
+ }
+ nTemp += nBlockCount;
+ pTemp = pTemp->GetNextBlock();
+ if ( pTemp )
+ {
+ i = 0;
+ pNodes = pTemp->GetNodes();
+ }
+ else
+ break;
+ }
+ while ( TRUE );
+ }
+ else
+ {
+ // Alle Bloecke durchrsuchen
+ i = (USHORT)(nStartIndex-nTemp)+1;
+ pNodes = pTemp->GetObjectPtr( i-1 );
+ do
+ {
+ do
+ {
+ if ( p == *pNodes )
+ return nTemp+i-1;
+ pNodes--;
+ i--;
+ }
+ while ( i );
+ nTemp -= pTemp->Count();
+ pTemp = pTemp->GetPrevBlock();
+ if ( pTemp )
+ {
+ i = pTemp->Count();
+ // Leere Bloecke in der Kette darf es nicht geben. Nur
+ // wenn ein Block existiert, darf dieser leer sein
+ pNodes = pTemp->GetObjectPtr( i-1 );
+ }
+ else
+ break;
+ }
+ while ( TRUE );
+ }
+ }
+
+ return CONTAINER_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* Container::Seek()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Seek( ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist der Container leer, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ pCurBlock = pTemp;
+ nCurIndex = (USHORT)nIndex;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::First()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::First()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ {
+ // Block und Index setzen und ersten Pointer zurueckgeben
+ pCurBlock = pFirstBlock;
+ nCurIndex = 0;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Last()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Last()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ {
+ // Block und Index setzen und ersten Pointer zurueckgeben
+ pCurBlock = pLastBlock;
+ nCurIndex = pCurBlock->Count()-1;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Next()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Next()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
+ // naechste Position noch im aktuellen Block ist. Falls nicht, dann
+ // einen Block weiterschalten (geht ohne Gefahr, da leere Bloecke
+ // nicht vorkommen duerfen, es sein denn, es ist der einzige).
+ if ( !nCount )
+ return NULL;
+ else if ( (nCurIndex+1) < pCurBlock->Count() )
+ return pCurBlock->GetObject( ++nCurIndex );
+ else if ( pCurBlock->GetNextBlock() )
+ {
+ pCurBlock = pCurBlock->GetNextBlock();
+ nCurIndex = 0;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* Container::Prev()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Prev()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
+ // vorherige Position noch im aktuellen Block ist. Falls nicht, dann
+ // einen Block zurueckschalten (geht ohne Gefahr, da leere Bloecke
+ // nicht vorkommen duerfen, es sein denn, es ist der einzige).
+ if ( !nCount )
+ return NULL;
+ else if ( nCurIndex )
+ return pCurBlock->GetObject( --nCurIndex );
+ else if ( pCurBlock->GetPrevBlock() )
+ {
+ pCurBlock = pCurBlock->GetPrevBlock();
+ nCurIndex = pCurBlock->Count() - 1;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* Container::operator =()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container& Container::operator =( const Container& r )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Erst alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+
+ // Daten kopieren
+ ImpCopyContainer( this, &r );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Container::operator ==()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+BOOL Container::operator ==( const Container& r ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( nCount != r.nCount )
+ return FALSE;
+
+ ULONG i = 0;
+ while ( i < nCount )
+ {
+ if ( GetObject( i ) != r.GetObject( i ) )
+ return FALSE;
+ i++;
+ }
+
+ return TRUE;
+}
diff --git a/tools/source/memtools/makefile.mk b/tools/source/memtools/makefile.mk
new file mode 100644
index 000000000000..bc8e84bf15b1
--- /dev/null
+++ b/tools/source/memtools/makefile.mk
@@ -0,0 +1,92 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=mtools
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/contnr.obj \
+ $(SLO)$/table.obj \
+ $(SLO)$/unqidx.obj \
+ $(SLO)$/mempool.obj \
+ $(SLO)$/multisel.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/contnr.obj \
+ $(OBJ)$/table.obj \
+ $(OBJ)$/unqidx.obj \
+ $(OBJ)$/mempool.obj \
+ $(OBJ)$/multisel.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/memtools/mempool.cxx b/tools/source/memtools/mempool.cxx
new file mode 100644
index 000000000000..25d4149bcdb4
--- /dev/null
+++ b/tools/source/memtools/mempool.cxx
@@ -0,0 +1,323 @@
+/*************************************************************************
+ *
+ * $RCSfile: mempool.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define private public
+
+#include <limits.h>
+
+#include <debug.hxx>
+#include <mempool.hxx>
+
+// -----------------------------------------------------------------------
+
+#if ( __ALIGNMENT8 > 4 )
+#define MEMPOOL_ALIGNMENT __ALIGNMENT8
+#else
+#define MEMPOOL_ALIGNMENT 4
+#endif
+
+// -----------------
+// - FixedMemBlock -
+// -----------------
+
+struct FixedMemBlock
+{
+ USHORT nSize;
+ USHORT nFree;
+ USHORT nFirst;
+ USHORT nDummyAlign1;
+ FixedMemBlock* pNext;
+#if (__SIZEOFPOINTER == 4) && (__ALIGNMENT8 == 8)
+ void* pDummyAlign2;
+#endif
+ char aData[1];
+};
+
+/*************************************************************************
+|*
+|* ImpDbgPoolTest()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 30.11.94
+|* Letzte Aenderung TH 30.11.94
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+
+static void ImpDbgPoolTest( FixedMemPool* pMemPool )
+{
+ DbgData* pData = DbgGetData();
+
+ if ( !pData )
+ return;
+
+ if ( !(pData->nTestFlags & (DBG_TEST_MEM_OVERWRITE | DBG_TEST_MEM_OVERWRITEFREE)) )
+ return;
+
+ FixedMemBlock* pFirst = pMemPool->pFirst;
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ if ( pBlock->nFree )
+ {
+ USHORT i = pBlock->nFree;
+ USHORT n = pBlock->nFirst;
+ char* pData = pBlock->aData;
+ while ( i )
+ {
+ if ( !(n < (pBlock->nSize/pMemPool->nTypeSize)) )
+ DbgError( "MemPool: Memory Overwrite" );
+
+ char* pNext = pData+(n*pMemPool->nTypeSize);
+ n = *((USHORT*)pNext);
+ i--;
+ }
+ }
+
+ pBlock = pBlock->pNext;
+ }
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* FixedMemPool::FixedMemPool()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+FixedMemPool::FixedMemPool( USHORT _nTypeSize,
+ USHORT _nInitSize, USHORT _nGrowSize )
+{
+ pFirst = NULL;
+ nInitSize = _nInitSize;
+ nGrowSize = _nGrowSize;
+
+ if ( _nTypeSize > 4 )
+ nTypeSize = (_nTypeSize + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);
+ else if ( _nTypeSize <= 2 )
+ nTypeSize = 2;
+ else
+ nTypeSize = 4;
+
+ DBG_ASSERT( (ULONG)nTypeSize*nInitSize <= USHRT_MAX,
+ "FixedMemPool: TypeSize*nInitSize > USHRT_MAX" );
+ DBG_ASSERT( (ULONG)nTypeSize*nGrowSize <= USHRT_MAX,
+ "FixedMemPool: TypeSize*GrowSize > USHRT_MAX" );
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::~FixedMemPool()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+FixedMemPool::~FixedMemPool()
+{
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ FixedMemBlock* pTemp = pBlock;
+ pBlock = pBlock->pNext;
+ delete pTemp;
+ }
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::Alloc()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+void* FixedMemPool::Alloc()
+{
+#ifdef DBG_UTIL
+ ImpDbgPoolTest( this );
+#endif
+
+ USHORT i;
+ char* pData;
+
+ if ( !pFirst )
+ {
+ pFirst = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nInitSize*nTypeSize)];
+
+ if ( !pFirst )
+ return NULL;
+
+ pFirst->pNext = NULL;
+ pFirst->nSize = nInitSize*nTypeSize;;
+ pFirst->nFree = nInitSize-1;
+ pFirst->nFirst = 1;
+
+ pData = pFirst->aData;
+ for ( i = 1; i < nInitSize; i++ )
+ {
+ *((USHORT*)pData) = i;
+ pData += nTypeSize;
+ }
+
+ return (void*)(pFirst->aData);
+ }
+
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock && !pBlock->nFree )
+ pBlock = pBlock->pNext;
+
+ if ( pBlock )
+ {
+ pData = pBlock->aData;
+ char* pFree = pData+(pBlock->nFirst*nTypeSize);
+ pBlock->nFirst = *((USHORT*)pFree); // UMR, wenn letzter freier Block, ist OK
+ pBlock->nFree--;
+ return (void*)pFree;
+ }
+ else
+ {
+ if ( !nGrowSize )
+ return NULL;
+
+ pBlock = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nGrowSize*nTypeSize)];
+
+ if ( !pBlock )
+ return NULL;
+
+ pData = pBlock->aData;
+ for ( i = 1; i < nGrowSize; i++ )
+ {
+ *((USHORT*)pData) = i;
+ pData += nTypeSize;
+ }
+
+ pBlock->pNext = pFirst->pNext;
+ pBlock->nSize = nGrowSize*nTypeSize;
+ pBlock->nFree = nGrowSize-1;
+ pBlock->nFirst = 1;
+ pFirst->pNext = pBlock;
+
+ return (void*)(pBlock->aData);
+ }
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::Free()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+void FixedMemPool::Free( void* pFree )
+{
+ if ( !pFree )
+ return;
+
+#ifdef DBG_UTIL
+ ImpDbgPoolTest( this );
+#endif
+
+ FixedMemBlock* pBlock = pFirst;
+ FixedMemBlock* pPrev = NULL;
+ while ( ((ULONG)pBlock->aData > (ULONG)pFree) ||
+ ((ULONG)pFree >= ((ULONG)pBlock->aData+pBlock->nSize)) )
+ {
+ pPrev = pBlock;
+ pBlock = pBlock->pNext;
+
+#ifdef DBG_UTIL
+ DBG_ASSERT( pBlock, "FixedMemPool - Delete: Wrong Pointer" );
+#endif
+ }
+
+ pBlock->nFree++;
+ *((USHORT*)pFree) = pBlock->nFirst;
+ pBlock->nFirst = (USHORT)(((ULONG)pFree-(ULONG)(pBlock->aData)) / nTypeSize);
+
+ if ( pPrev && (pBlock->nFree*nTypeSize == pBlock->nSize) )
+ {
+ pPrev->pNext = pBlock->pNext;
+ delete pBlock;
+ }
+ else
+ {
+ if ( pPrev )
+ {
+ pPrev->pNext = pBlock->pNext;
+ pBlock->pNext = pFirst->pNext;
+ pFirst->pNext = pBlock;
+ }
+ }
+}
diff --git a/tools/source/memtools/multisel.cxx b/tools/source/memtools/multisel.cxx
new file mode 100644
index 000000000000..8bd47a028019
--- /dev/null
+++ b/tools/source/memtools/multisel.cxx
@@ -0,0 +1,897 @@
+/*************************************************************************
+ *
+ * $RCSfile: multisel.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MULTISEL_CXX
+
+#ifdef MI_DEBUG
+#define private public
+#include <stdio.h>
+#endif
+
+#include <debug.hxx>
+#include <multisel.hxx>
+
+#pragma hdrstop
+
+#ifdef MI_DEBUG
+#define DBG(x) x
+#else
+#define DBG(x)
+#endif
+
+//==================================================================
+
+#ifdef MI_DEBUG
+
+static void Print( const MultiSelection* pSel )
+{
+ DbgOutf( "TotRange: %4ld-%4ld\n",
+ pSel->aTotRange.Min(), pSel->aTotRange.Max() );
+ if ( pSel->bCurValid )
+ {
+ DbgOutf( "CurSubSel: %4ld\n", pSel->nCurSubSel );
+ DbgOutf( "CurIndex: %4ld\n", pSel->nCurIndex );
+ }
+ DbgOutf( "SelCount: %4ld\n", pSel->nSelCount );
+ DbgOutf( "SubCount: %4ld\n", pSel->aSels.Count() );
+ for ( ULONG nPos = 0; nPos < pSel->aSels.Count(); ++nPos )
+ {
+ DbgOutf( "SubSel #%2ld: %4ld-%4ld\n", nPos,
+ pSel->aSels.GetObject(nPos)->Min(),
+ pSel->aSels.GetObject(nPos)->Max() );
+ }
+ DbgOutf( "\n" );
+ fclose( pFile );
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::ImplClear()
+{
+ // no selected indexes
+ nSelCount = 0;
+
+ Range* pRange = aSels.First();
+ while ( pRange )
+ {
+ delete pRange;
+ pRange = aSels.Next();
+ }
+ aSels.Clear();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG MultiSelection::ImplFindSubSelection( long nIndex ) const
+{
+ // iterate through the sub selections
+ ULONG n = 0;
+ for ( ;
+ n < aSels.Count() && nIndex > aSels.GetObject(n)->Max();
+ ++n ) {} /* empty loop */
+ return n;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::ImplMergeSubSelections( ULONG nPos1, ULONG nPos2 )
+{
+ // didn't a sub selection at nPos2 exist?
+ if ( nPos2 >= aSels.Count() )
+ return FALSE;
+
+ // did the sub selections touch each other?
+ if ( (aSels.GetObject(nPos1)->Max() + 1) == aSels.GetObject(nPos2)->Min() )
+ {
+ // merge them
+ aSels.GetObject(nPos1)->Max() = aSels.GetObject(nPos2)->Max();
+ delete aSels.Remove(nPos2);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection():
+ aTotRange( 0, -1 ),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const UniString& rString, sal_Unicode cRange, sal_Unicode cSep ):
+ aTotRange(0,RANGE_MAX),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+ // Dies ist nur ein Schnellschuss und sollte bald optimiert,
+ // an die verschiedenen Systeme (MAC, UNIX etc.)
+ // und die gewuenschte Eingabe-Syntax angepasst werden.
+
+ UniString aStr( rString );
+ sal_Unicode* pStr = aStr.GetBufferAccess();
+ sal_Unicode* pOld = pStr;
+ BOOL bReady = FALSE;
+ BOOL bUntil = FALSE;
+ xub_StrLen nCut = 0;
+
+ // Hier normieren wir den String, sodass nur Ziffern,
+ // Semikola als Trenn- und Minus als VonBis-Zeichen
+ // uebrigbleiben, z.B. "99-117;55;34;-17;37-43"
+ while ( *pOld )
+ {
+ switch( *pOld )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ DBG_ASSERT( *pOld != cRange, "digit for range char not allowed" );
+ DBG_ASSERT( *pOld != cSep, "digit for separator not allowed" );
+ if( bReady )
+ {
+ *pStr++ = ';';
+ nCut++;
+ bReady = FALSE;
+ }
+ *pStr++ = *pOld;
+ nCut++;
+ bUntil = FALSE;
+ break;
+
+ case '-':
+ case ':':
+ case '/':
+ if ( *pOld != cSep )
+ {
+ if ( !bUntil )
+ {
+ *pStr++ = '-';
+ nCut++;
+ bUntil = TRUE;
+ }
+ bReady = FALSE;
+ }
+ else
+ bReady = TRUE;
+ break;
+
+ case ' ':
+ DBG_ASSERT( *pOld != cRange, "SPACE for range char not allowed" );
+ DBG_ASSERT( *pOld != cSep, "SPACE for separator not allowed" );
+ bReady = !bUntil;
+ break;
+
+ default:
+ if ( *pOld == cRange )
+ {
+ if ( !bUntil )
+ {
+ *pStr++ = '-';
+ nCut++;
+ bUntil = TRUE;
+ }
+ bReady = FALSE;
+ }
+ else
+ bReady = TRUE;
+ break;
+ }
+
+ pOld++;
+ }
+ aStr.ReleaseBufferAccess( nCut );
+
+ // Jetzt wird der normierte String ausgewertet ..
+ UniString aNumStr;
+ Range aRg( 1, RANGE_MAX );
+ const sal_Unicode* pCStr = aStr.GetBuffer();
+ long nPage = 1;
+ long nNum = 1;
+ bUntil = FALSE;
+ while ( *pCStr )
+ {
+ switch ( *pCStr )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ aNumStr += *pCStr;
+ break;
+ case ';':
+ nNum = aNumStr.ToInt32();
+ if ( bUntil )
+ {
+ if ( !aNumStr.Len() )
+ nNum = RANGE_MAX;
+ aRg.Min() = nPage;
+ aRg.Max() = nNum;
+ aRg.Justify();
+ Select( aRg );
+ }
+ else
+ Select( nNum );
+ nPage = 0;
+ aNumStr.Erase();
+ bUntil = FALSE;
+ break;
+
+ case '-':
+ nPage = aNumStr.ToInt32();
+ aNumStr.Erase();
+ bUntil = TRUE;
+ break;
+ }
+
+ pCStr++;
+ }
+
+ nNum = aNumStr.ToInt32();
+ if ( bUntil )
+ {
+ if ( !aNumStr.Len() )
+ nNum = RANGE_MAX;
+ aRg.Min() = nPage;
+ aRg.Max() = nNum;
+ aRg.Justify();
+ Select( aRg );
+ }
+ else
+ Select( nNum );
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const MultiSelection& rOrig ) :
+ aTotRange(rOrig.aTotRange),
+ bCurValid(rOrig.bCurValid),
+ nSelCount(rOrig.nSelCount),
+ bSelectNew(FALSE)
+{
+ if ( bCurValid )
+ {
+ nCurSubSel = rOrig.nCurSubSel;
+ nCurIndex = rOrig.nCurIndex;
+ }
+
+ // copy the sub selections
+ for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n )
+ aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND );
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const Range& rRange ):
+ aTotRange(rRange),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::~MultiSelection()
+{
+ Range* pRange = aSels.First();
+ while ( pRange )
+ {
+ delete pRange;
+ pRange = aSels.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig )
+{
+ aTotRange = rOrig.aTotRange;
+ bCurValid = rOrig.bCurValid;
+ if ( bCurValid )
+ {
+ nCurSubSel = rOrig.nCurSubSel;
+ nCurIndex = rOrig.nCurIndex;
+ }
+
+ // clear the old and copy the sub selections
+ ImplClear();
+ for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n )
+ aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND );
+ nSelCount = rOrig.nSelCount;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::operator== ( MultiSelection& rWith )
+{
+ if ( aTotRange != rWith.aTotRange || nSelCount != rWith.nSelCount ||
+ aSels.Count() != rWith.aSels.Count() )
+ return FALSE;
+
+ // compare the sub seletions
+ for ( ULONG n = 0; n < aSels.Count(); ++n )
+ if ( *aSels.GetObject(n) != *rWith.aSels.GetObject(n) )
+ return FALSE;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::SelectAll( BOOL bSelect )
+{
+ DBG(DbgOutf( "::SelectAll(%s)\n", bSelect ? "TRUE" : "FALSE" ));
+
+ ImplClear();
+ if ( bSelect )
+ {
+ aSels.Insert( new Range(aTotRange), LIST_APPEND );
+ nSelCount = aTotRange.Len();
+ }
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::Select( long nIndex, BOOL bSelect )
+{
+ DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" );
+
+ // out of range?
+ if ( !aTotRange.IsInside(nIndex) )
+ return FALSE;
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ if ( bSelect )
+ {
+ // is it included in the found sub selection?
+ if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside( nIndex ) )
+ // already selected, nothing to do
+ return FALSE;
+
+ // it will become selected
+ ++nSelCount;
+
+ // is it at the end of the previous sub selection
+ if ( nSubSelPos > 0 &&
+ aSels.GetObject(nSubSelPos-1)->Max() == (nIndex-1) )
+ {
+ // expand the previous sub selection
+ aSels.GetObject(nSubSelPos-1)->Max() = nIndex;
+
+ // try to merge the previous sub selection
+ ImplMergeSubSelections( nSubSelPos-1, nSubSelPos );
+ }
+ // is is at the beginning of the found sub selection
+ else if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->Min() == (nIndex+1) )
+ // expand the found sub selection
+ aSels.GetObject(nSubSelPos)->Min() = nIndex;
+ else
+ {
+ // create a new sub selection
+ aSels.Insert( new Range( nIndex, nIndex ), nSubSelPos );
+ if ( bCurValid && nCurSubSel >= nSubSelPos )
+ ++nCurSubSel;
+ }
+ }
+ else
+ {
+ // is it excluded from the found sub selection?
+ if ( nSubSelPos >= aSels.Count() ||
+ !aSels.GetObject(nSubSelPos)->IsInside( nIndex ) )
+ {
+ // not selected, nothing to do
+ DBG(Print( this ));
+ return FALSE;
+ }
+
+ // it will become deselected
+ --nSelCount;
+
+ // is it the only index in the found sub selection?
+ if ( aSels.GetObject(nSubSelPos)->Len() == 1 )
+ {
+ // remove the complete sub selection
+ delete aSels.Remove( nSubSelPos );
+ DBG(Print( this ));
+ return TRUE;
+ }
+
+ // is it at the beginning of the found sub selection?
+ if ( aSels.GetObject(nSubSelPos)->Min() == nIndex )
+ ++aSels.GetObject(nSubSelPos)->Min();
+ // is it at the end of the found sub selection?
+ else if ( aSels.GetObject(nSubSelPos)->Max() == nIndex )
+ --aSels.GetObject(nSubSelPos)->Max();
+ // it is in the middle of the found sub selection?
+ else
+ {
+ // split the sub selection
+ aSels.Insert(
+ new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ),
+ nSubSelPos );
+ aSels.GetObject(nSubSelPos+1)->Min() = nIndex + 1;
+ }
+ }
+
+ DBG(Print( this ));
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Select( const Range& rIndexRange, BOOL bSelect )
+{
+ Range* pRange;
+ long nOld;
+
+ ULONG nTmpMin = rIndexRange.Min();
+ ULONG nTmpMax = rIndexRange.Max();
+ ULONG nCurMin = FirstSelected();
+ ULONG nCurMax = LastSelected();
+ DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" );
+ DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" );
+
+ // gesamte Selektion ersetzen ?
+ if( nTmpMin <= nCurMin && nTmpMax >= nCurMax )
+ {
+ ImplClear();
+ if ( bSelect )
+ {
+ aSels.Insert( new Range(rIndexRange), LIST_APPEND );
+ nSelCount = rIndexRange.Len();
+ }
+ return;
+ }
+ // links erweitern ?
+ if( nTmpMax < nCurMin )
+ {
+ if( bSelect )
+ {
+ // ersten Range erweitern ?
+ if( nCurMin > (nTmpMax+1) )
+ {
+ pRange = new Range( rIndexRange );
+ aSels.Insert( pRange, (ULONG)0 );
+ nSelCount += pRange->Len();
+ }
+ else
+ {
+ pRange = aSels.First();
+ nOld = pRange->Min();
+ pRange->Min() = (long)nTmpMin;
+ nSelCount += ( nOld - nTmpMin );
+ }
+ bCurValid = FALSE;
+ }
+ return;
+ }
+ // rechts erweitern ?
+ else if( nTmpMin > nCurMax )
+ {
+ if( bSelect )
+ {
+ // letzten Range erweitern ?
+ if( nTmpMin > (nCurMax+1) )
+ {
+ pRange = new Range( rIndexRange );
+ aSels.Insert( pRange, LIST_APPEND );
+ nSelCount += pRange->Len();
+ }
+ else
+ {
+ pRange = aSels.Last();
+ nOld = pRange->Max();
+ pRange->Max() = (long)nTmpMax;
+ nSelCount += ( nTmpMax - nOld );
+ }
+ bCurValid = FALSE;
+ }
+ return;
+ }
+
+ //HACK(Hier muss noch optimiert werden)
+ while( nTmpMin <= nTmpMax )
+ {
+ Select( nTmpMin, bSelect );
+ nTmpMin++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::IsSelected( long nIndex ) const
+{
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ return nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex);
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Insert( long nIndex, long nCount )
+{
+ DBG(DbgOutf( "::Insert(%ld, %ld)\n", nIndex, nCount ));
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ // did we need to shift the sub selections?
+ if ( nSubSelPos < aSels.Count() )
+ {
+ // did we insert an unselected into an existing sub selection?
+ if ( !bSelectNew && aSels.GetObject(nSubSelPos)->Min() != nIndex &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex) )
+ {
+ // split the sub selection
+ aSels.Insert(
+ new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ),
+ nSubSelPos );
+ ++nSubSelPos;
+ aSels.GetObject(nSubSelPos)->Min() = nIndex;
+ }
+
+ // did we append an selected to an existing sub selection?
+ else if ( bSelectNew && nSubSelPos > 0 &&
+ aSels.GetObject(nSubSelPos)->Max() == nIndex-1 )
+ // expand the previous sub selection
+ aSels.GetObject(nSubSelPos-1)->Max() += nCount;
+
+ // did we insert an selected into an existing sub selection?
+ else if ( bSelectNew && aSels.GetObject(nSubSelPos)->Min() == nIndex )
+ {
+ // expand the sub selection
+ aSels.GetObject(nSubSelPos)->Max() += nCount;
+ ++nSubSelPos;
+ }
+
+ // shift the sub selections behind the inserting position
+ for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos )
+ {
+ aSels.GetObject(nPos)->Min() += nCount;
+ aSels.GetObject(nPos)->Max() += nCount;
+ }
+ }
+
+ bCurValid = FALSE;
+ aTotRange.Max() += nCount;
+ if ( bSelectNew )
+ nSelCount += nCount;
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Remove( long nIndex )
+{
+ DBG(DbgOutf( "::Remove(%ld)\n", nIndex ));
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ // did we remove from an existing sub selection?
+ if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex) )
+ {
+ // does this sub selection only contain the index to be deleted
+ if ( aSels.GetObject(nSubSelPos)->Len() == 1 )
+ // completely remove the sub selection
+ aSels.Remove(nSubSelPos);
+ else
+ // shorten this sub selection
+ --( aSels.GetObject(nSubSelPos++)->Max() );
+
+ // adjust the selected counter
+ --nSelCount;
+ }
+
+ // shift the sub selections behind the removed index
+ for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos )
+ {
+ --( aSels.GetObject(nPos)->Min() );
+ --( aSels.GetObject(nPos)->Max() );
+ }
+
+ bCurValid = FALSE;
+ aTotRange.Max() -= 1;
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Append( long nCount )
+{
+ long nPrevLast = aTotRange.Max();
+ aTotRange.Max() += nCount;
+ if ( bSelectNew )
+ {
+ nSelCount += nCount;
+ aSels.Insert( new Range( nPrevLast+1, nPrevLast + nCount ),
+ LIST_APPEND );
+ if ( aSels.Count() > 1 )
+ ImplMergeSubSelections( aSels.Count() - 2, aSels.Count() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::ImplFwdUnselected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( ( nCurSubSel < aSels.Count() ) &&
+ ( aSels.GetObject(nCurSubSel)->Min() <= nCurIndex ) )
+ nCurIndex = aSels.GetObject(nCurSubSel++)->Max() + 1;
+
+ if ( nCurIndex <= aTotRange.Max() )
+ return nCurIndex;
+ else
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::ImplBwdUnselected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( aSels.GetObject(nCurSubSel)->Max() < nCurIndex )
+ return nCurIndex;
+
+ nCurIndex = aSels.GetObject(nCurSubSel--)->Min() - 1;
+ if ( nCurIndex >= 0 )
+ return nCurIndex;
+ else
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::FirstSelected( BOOL bInverse )
+{
+ bInverseCur = bInverse;
+ nCurSubSel = 0;
+
+ if ( bInverseCur )
+ {
+ bCurValid = nSelCount < ULONG(aTotRange.Len());
+ if ( bCurValid )
+ {
+ nCurIndex = 0;
+ return ImplFwdUnselected();
+ }
+ }
+ else
+ {
+ bCurValid = aSels.Count() > 0;
+ if ( bCurValid )
+ return nCurIndex = aSels.GetObject(0)->Min();
+ }
+
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::LastSelected( BOOL bInverse )
+{
+ nCurSubSel = aSels.Count() - 1;
+ bCurValid = aSels.Count() > 0;
+
+ if ( bCurValid )
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Max();
+
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::NextSelected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( bInverseCur )
+ {
+ ++nCurIndex;
+ return ImplFwdUnselected();
+ }
+ else
+ {
+ // is the next index in the current sub selection too?
+ if ( nCurIndex < aSels.GetObject(nCurSubSel)->Max() )
+ return ++nCurIndex;
+
+ // are there further sub selections?
+ if ( ++nCurSubSel < aSels.Count() )
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Min();
+
+ // we are at the end!
+ return SFX_ENDOFSELECTION;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::PrevSelected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( bInverseCur )
+ {
+ --nCurIndex;
+ return ImplBwdUnselected();
+ }
+ else
+ {
+ // is the previous index in the current sub selection too?
+ if ( nCurIndex > aSels.GetObject(nCurSubSel)->Min() )
+ return --nCurIndex;
+
+ // are there previous sub selections?
+ if ( nCurSubSel > 0 )
+ {
+ --nCurSubSel;
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Max();
+ }
+
+ // we are at the beginning!
+ return SFX_ENDOFSELECTION;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::SetTotalRange( const Range& rTotRange )
+{
+ aTotRange = rTotRange;
+
+ // die untere Bereichsgrenze anpassen
+ Range* pRange = aSels.GetObject( 0 );
+ while( pRange )
+ {
+ if( pRange->Max() < aTotRange.Min() )
+ {
+ delete pRange;
+ aSels.Remove( (ULONG)0 );
+ }
+ else if( pRange->Min() < aTotRange.Min() )
+ {
+ pRange->Min() = aTotRange.Min();
+ break;
+ }
+ else
+ break;
+
+ pRange = aSels.GetObject( 0 );
+ }
+
+ // die obere Bereichsgrenze anpassen
+ ULONG nCount = aSels.Count();
+ while( nCount )
+ {
+ pRange = aSels.GetObject( nCount - 1 );
+ if( pRange->Min() > aTotRange.Max() )
+ {
+ delete pRange;
+ aSels.Remove( (ULONG)(nCount - 1) );
+ }
+ else if( pRange->Max() > aTotRange.Max() )
+ {
+ pRange->Max() = aTotRange.Max();
+ break;
+ }
+ else
+ break;
+
+ nCount = aSels.Count();
+ }
+
+ // Selection-Count neu berechnen
+ nSelCount = 0;
+ pRange = aSels.First();
+ while( pRange )
+ {
+ nSelCount += pRange->Len();
+ pRange = aSels.Next();
+ }
+
+ bCurValid = FALSE;
+ nCurIndex = 0;
+}
diff --git a/tools/source/memtools/table.cxx b/tools/source/memtools/table.cxx
new file mode 100644
index 000000000000..d84676f2c052
--- /dev/null
+++ b/tools/source/memtools/table.cxx
@@ -0,0 +1,442 @@
+/*************************************************************************
+ *
+ * $RCSfile: table.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_TABLE_CXX
+
+// -----------------------------------------------------------------------
+
+#define protected public
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+#ifndef _TOOLS_TABLE_HXX
+#include <table.hxx>
+#endif
+
+// =======================================================================
+
+ULONG Table::ImplGetIndex( ULONG nKey, ULONG* pIndex ) const
+{
+ // Abpruefen, ob der erste Key groesser als der Vergleichskey ist
+ if ( !nCount || (nKey < (ULONG)Container::ImpGetObject(0)) )
+ return TABLE_ENTRY_NOTFOUND;
+
+ ULONG nLow;
+ ULONG nHigh;
+ ULONG nMid;
+ ULONG nCompareKey;
+ void** pNodes = Container::ImpGetOnlyNodes();
+
+ // Binaeres Suchen
+ nLow = 0;
+ nHigh = nCount-1;
+ if ( pNodes )
+ {
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareKey = (ULONG)pNodes[nMid*2];
+ if ( nKey < nCompareKey )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nKey > nCompareKey )
+ nLow = nMid + 1;
+ else
+ return nMid*2;
+ }
+ }
+ while ( nLow <= nHigh );
+ }
+ else
+ {
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareKey = (ULONG)Container::ImpGetObject( nMid*2 );
+ if ( nKey < nCompareKey )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nKey > nCompareKey )
+ nLow = nMid + 1;
+ else
+ return nMid*2;
+ }
+ }
+ while ( nLow <= nHigh );
+ }
+
+ if ( pIndex )
+ {
+ if ( nKey > nCompareKey )
+ *pIndex = (nMid+1)*2;
+ else
+ *pIndex = nMid*2;
+ }
+
+ return TABLE_ENTRY_NOTFOUND;
+}
+
+// =======================================================================
+
+Table::Table( USHORT _nInitSize, USHORT _nReSize ) :
+ Container( CONTAINER_MAXBLOCKSIZE, _nInitSize*2, _nReSize*2 )
+{
+ DBG_ASSERT( _nInitSize <= 32767, "Table::Table(): InitSize > 32767" );
+ DBG_ASSERT( _nReSize <= 32767, "Table::Table(): ReSize > 32767" );
+ nCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Table::Insert( ULONG nKey, void* p )
+{
+ // Tabellenelement einsortieren
+ ULONG i;
+ if ( nCount )
+ {
+ if ( nCount <= 24 )
+ {
+ USHORT n = 0;
+ USHORT nTempCount = (USHORT)nCount * 2;
+ void** pNodes = Container::ImpGetOnlyNodes();
+ ULONG nCompareKey = (ULONG)(*pNodes);
+ while ( nKey > nCompareKey )
+ {
+ n += 2;
+ pNodes += 2;
+ if ( n < nTempCount )
+ nCompareKey = (ULONG)(*pNodes);
+ else
+ {
+ nCompareKey = 0;
+ break;
+ }
+ }
+
+ // Testen, ob sich der Key schon in der Tabelle befindet
+ if ( nKey == nCompareKey )
+ return FALSE;
+
+ i = n;
+ }
+ else
+ {
+ i = 0;
+ if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND )
+ return FALSE;
+ }
+ }
+ else
+ i = 0;
+
+ // Eintrag einfuegen (Key vor Pointer)
+ Container::Insert( (void*)nKey, i );
+ Container::Insert( p, i+1 );
+
+ // Ein neuer Eintrag
+ nCount++;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Remove( ULONG nKey )
+{
+ // Index besorgen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Testen, ob sich der Key in der Tabelle befindet
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+
+ // Itemanzahl erniedrigen
+ nCount--;
+
+ // Key entfernen
+ Container::Remove( nIndex );
+
+ // Pointer entfernen und zurueckgeben
+ return Container::Remove( nIndex );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Replace( ULONG nKey, void* p )
+{
+ // Index abfragen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Existiert kein Eintrag mit dem Schluessel
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ return Container::Replace( p, nIndex+1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Get( ULONG nKey ) const
+{
+ // Index besorgen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Testen, ob sich der Key in der Tabelle befindet
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ return Container::ImpGetObject( nIndex+1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::GetCurObject() const
+{
+ return Container::ImpGetObject( Container::GetCurPos()+1 );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::GetKey( const void* p ) const
+{
+ ULONG nIndex = 0;
+
+ // Solange noch Eintraege Vorhanden sind
+ while ( nIndex < nCount )
+ {
+ // Stimmt der Pointer ueberein, wird der Key zurueckgegeben
+ if ( p == Container::ImpGetObject( (nIndex*2)+1 ) )
+ return (ULONG)Container::ImpGetObject( nIndex*2 );
+
+ nIndex++;
+ }
+
+ return TABLE_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Table::IsKeyValid( ULONG nKey ) const
+{
+ return (ImplGetIndex( nKey ) != TABLE_ENTRY_NOTFOUND) ? TRUE : FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::GetUniqueKey( ULONG nStartKey ) const
+{
+ DBG_ASSERT( (nStartKey > 1) && (nStartKey < 0xFFFFFFFF),
+ "Table::GetUniqueKey() - nStartKey == 0 or nStartKey >= 0xFFFFFFFF" );
+
+ if ( !nCount )
+ return nStartKey;
+
+ ULONG nLastKey = (ULONG)Container::GetObject( (nCount*2)-2 );
+ if ( nLastKey < nStartKey )
+ return nStartKey;
+ else
+ {
+ if ( nLastKey < 0xFFFFFFFE )
+ return nLastKey+1;
+ else
+ {
+ ULONG nPos;
+ ULONG nTempPos = ImplGetIndex( nStartKey, &nPos );
+ if ( nTempPos != TABLE_ENTRY_NOTFOUND )
+ nPos = nTempPos;
+ nLastKey = (ULONG)Container::GetObject( nPos );
+ if ( nStartKey < nLastKey )
+ return nStartKey;
+ while ( nLastKey < 0xFFFFFFFE )
+ {
+ nPos += 2;
+ nLastKey++;
+ if ( nLastKey != (ULONG)Container::GetObject( nPos ) )
+ return nLastKey;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::SearchKey( ULONG nKey, ULONG* pPos ) const
+{
+ *pPos = 0;
+ ULONG nPos = ImplGetIndex( nKey, pPos );
+ if ( nPos != TABLE_ENTRY_NOTFOUND )
+ {
+ nPos /= 2;
+ *pPos = nPos;
+ }
+ else
+ *pPos /= 2;
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Seek( ULONG nKey )
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Ist Key nicht enthalten
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ {
+ // Index setzen
+ Container::Seek( nIndex );
+
+ // Pointer zurueckgeben
+ return Container::ImpGetObject( Container::GetCurPos() + 1 );
+ }
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Seek( void* p )
+{
+ ULONG nKey = GetKey( p );
+
+ // Ist Key vorhanden, dann als aktuellen Eintrag setzen
+ if ( nKey != TABLE_ENTRY_NOTFOUND )
+ return Seek( nKey );
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::First()
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ // Auf ersten Eintag setzen
+ Container::First();
+
+ // Pointer zurueckgeben
+ return Container::ImpGetObject( 1 );
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Last()
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ // Last auf letzten Eintrag setzen
+ void* p = Container::Last();
+ Container::Prev();
+
+ // Pointer zurueckgeben
+ return p;
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Next()
+{
+ // Ueber den Pointer weiterschalten
+ Container::Next();
+
+ // Nachsten Eintag
+ Container::Next();
+
+ // Pointer vom naechsten Key zurueckgeben
+ return Container::ImpGetObject( Container::GetCurPos() + 1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Prev()
+{
+ // Ueber den Pointer weiterschalten
+ void* p = Container::Prev();
+
+ // Nachsten Eintag
+ Container::Prev();
+
+ // Pointer vom vorherigen Key zurueckgeben
+ return p;
+}
diff --git a/tools/source/memtools/unqidx.cxx b/tools/source/memtools/unqidx.cxx
new file mode 100644
index 000000000000..435e5fc117be
--- /dev/null
+++ b/tools/source/memtools/unqidx.cxx
@@ -0,0 +1,643 @@
+/*************************************************************************
+ *
+ * $RCSfile: unqidx.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define protected public
+
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+
+#ifndef _UNQIDX_HXX
+#include <unqidx.hxx>
+#endif
+
+#ifndef _UNQID_HXX
+#include <unqid.hxx>
+#endif
+
+/*************************************************************************
+|*
+|* UniqueIndex::UniqueIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex::UniqueIndex( ULONG _nStartIndex,
+ ULONG _nInitSize, ULONG _nReSize ) :
+ Container( _nInitSize )
+{
+ nReSize = _nReSize;
+ nStartIndex = _nStartIndex;
+ nUniqIndex = 0;
+ nCount = 0;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::UniqueIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex::UniqueIndex( const UniqueIndex& rIdx ) :
+ Container( rIdx )
+{
+ nReSize = rIdx.nReSize;
+ nStartIndex = rIdx.nStartIndex;
+ nUniqIndex = rIdx.nUniqIndex;
+ nCount = rIdx.nCount;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Insert()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::Insert( void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ // Ist Array voll, dann expandieren
+ if ( nCount == Container::GetSize() )
+ SetSize( nCount + nReSize );
+
+ // Damit UniqIndex nicht ueberlaeuft, wenn Items geloescht wurden
+ nUniqIndex = nUniqIndex % Container::GetSize();
+
+ // Leeren Eintrag suchen
+ while ( Container::ImpGetObject( nUniqIndex ) != NULL )
+ nUniqIndex = (nUniqIndex+1) % Container::GetSize();
+
+ // Object im Array speichern
+ Container::Replace( p, nUniqIndex );
+
+ // Anzahl der Eintraege erhoehen und Index zurueckgeben
+ nCount++;
+ nUniqIndex++;
+ return ( nUniqIndex + nStartIndex - 1 );
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Insert()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 21.04.96
+|* Letzte Aenderung MM 21.04.96
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::Insert( ULONG nIndex, void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ ULONG nContIndex = nIndex - nStartIndex;
+ // Ist Array voll, dann expandieren
+ if ( nContIndex >= Container::GetSize() )
+ SetSize( nContIndex + nReSize );
+
+ // Object im Array speichern
+ Container::Replace( p, nContIndex );
+
+ // Anzahl der Eintraege erhoehen und Index zurueckgeben
+ nCount++;
+ return nIndex;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Remove()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Remove( ULONG nIndex )
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ {
+ // Index-Eintrag als leeren Eintrag setzen und Anzahl der
+ // gespeicherten Indexe erniedriegen, wenn Eintrag belegt war
+ void* p = Container::Replace( NULL, nIndex-nStartIndex );
+ if ( p )
+ nCount--;
+ return p;
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Replace()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Replace( ULONG nIndex, void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return NULL;
+
+ // Ist Index zulaessig
+ if ( IsIndexValid( nIndex ) )
+ {
+ // Index-Eintrag ersetzen und alten zurueckgeben
+ return Container::Replace( p, nIndex-nStartIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Get()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Get( ULONG nIndex ) const
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ return Container::ImpGetObject( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::GetCurIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::GetCurIndex() const
+{
+ ULONG nPos = Container::GetCurPos();
+
+ // Ist der Current-Index nicht belegt, dann gibt es keinen Current-Index
+ if ( !Container::ImpGetObject( nPos ) )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+ else
+ return nPos+nStartIndex;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::GetIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::GetIndex( const void* p ) const
+{
+ // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ ULONG nIndex = Container::GetPos( p );
+
+ if ( nIndex != CONTAINER_ENTRY_NOTFOUND )
+ return nIndex+nStartIndex;
+ else
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::IsIndexValid()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+BOOL UniqueIndex::IsIndexValid( ULONG nIndex ) const
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ {
+ // Index ist nur zulaessig, wenn Eintrag auch belegt ist
+ if ( Container::ImpGetObject( nIndex-nStartIndex ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Seek()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Seek( ULONG nIndex )
+{
+ // Index-Eintrag als aktuellen setzten, wenn er gueltig ist
+ if ( IsIndexValid( nIndex ) )
+ return Container::Seek( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Seek()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Seek( void* p )
+{
+ // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden
+ if ( !p )
+ return NULL;
+
+ ULONG nIndex = GetIndex( p );
+
+ // Ist Index vorhanden, dann als aktuellen Eintrag setzen
+ if ( nIndex != UNIQUEINDEX_ENTRY_NOTFOUND )
+ return Container::Seek( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::First()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::First()
+{
+ void* p = Container::First();
+
+ while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) )
+ p = Container::Next();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Last()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Last()
+{
+ void* p = Container::Last();
+
+ while ( !p && Container::GetCurPos() )
+ p = Container::Prev();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Next()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Next()
+{
+ void* p = NULL;
+
+ while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) )
+ p = Container::Next();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Prev()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Prev()
+{
+ void* p = NULL;
+
+ while ( !p && Container::GetCurPos() )
+ p = Container::Prev();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::operator =()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex& UniqueIndex::operator =( const UniqueIndex& rIdx )
+{
+ // Neue Werte zuweisen
+ Container::operator =( rIdx );
+ nReSize = rIdx.nReSize;
+ nStartIndex = rIdx.nStartIndex;
+ nUniqIndex = rIdx.nUniqIndex;
+ nCount = rIdx.nCount;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::operator ==()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+BOOL UniqueIndex::operator ==( const UniqueIndex& rIdx ) const
+{
+ // Neue Werte zuweisen
+ if ( (nStartIndex == rIdx.nStartIndex) &&
+ (nCount == rIdx.nCount) &&
+ (Container::operator ==( rIdx )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+/*************************************************************************
+|*
+|* UniqueIdContainer::UniqueIdContainer ()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 29.04.96
+|* Letzte Aenderung MM 29.04.96
+|*
+*************************************************************************/
+
+UniqueIdContainer::UniqueIdContainer( const UniqueIdContainer& rObj )
+ : UniqueIndex( rObj )
+ , nCollectCount( rObj.nCollectCount )
+{
+ ULONG nCur = GetCurIndex();
+
+ ImpUniqueId * pEle = (ImpUniqueId *)First();
+ while( pEle )
+ {
+ pEle->nRefCount++;
+ pEle = (ImpUniqueId *)Next();
+ }
+ Seek( nCur );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::operator = ()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueIdContainer& UniqueIdContainer::operator = ( const UniqueIdContainer & rObj )
+{
+ UniqueIndex::operator = ( rObj );
+ nCollectCount = rObj.nCollectCount;
+
+ ULONG nCur = GetCurIndex();
+
+ ImpUniqueId * pEle = (ImpUniqueId *)First();
+ while( pEle )
+ {
+ pEle->nRefCount++;
+ pEle = (ImpUniqueId *)Next();
+ }
+ Seek( nCur );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::Clear()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+void UniqueIdContainer::Clear( BOOL bAll )
+{
+ USHORT nFree = bAll ? 0xFFFF : 1;
+
+ ImpUniqueId* pId = (ImpUniqueId*)Last();
+ BOOL bLast = TRUE;
+ while ( pId )
+ {
+ if ( pId->nRefCount <= nFree )
+ {
+ ((ImpUniqueId *)Remove( pId->nId ))->Release();
+ if( bLast )
+ pId = (ImpUniqueId *)Last();
+ else
+ pId = (ImpUniqueId *)Prev();
+ }
+ else
+ {
+ pId = (ImpUniqueId *)Prev();
+ bLast = FALSE;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateId()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateId()
+{
+ if( nCollectCount > 50 )
+ { // aufraeumen
+ Clear( FALSE );
+ nCollectCount = 0;
+ }
+ nCollectCount++;
+
+ ImpUniqueId * pId = new ImpUniqueId;
+ pId->nRefCount = 1;
+ pId->nId = Insert( pId );
+ return UniqueItemId( pId );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateIdProt()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateFreeId( ULONG nId )
+{
+ // Einfach erzeugen, fuer abgeleitete Klasse
+ ImpUniqueId * pId = new ImpUniqueId;
+ pId->nRefCount = 0;
+ pId->nId = nId;
+ return UniqueItemId( pId );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateIdProt()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateIdProt( ULONG nId )
+{
+ if ( IsIndexValid( nId ) )
+ return UniqueItemId( (ImpUniqueId *)Get( nId ) );
+
+ ImpUniqueId * pId;
+ do
+ {
+ pId = new ImpUniqueId;
+ pId->nRefCount = 1;
+ pId->nId = Insert( pId );
+ }
+ while( pId->nId != nId );
+ return UniqueItemId( pId );
+}
diff --git a/tools/source/rc/makefile.mk b/tools/source/rc/makefile.mk
new file mode 100644
index 000000000000..8aadfce6a2b0
--- /dev/null
+++ b/tools/source/rc/makefile.mk
@@ -0,0 +1,89 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=rc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES= rc.cxx \
+ resmgr.cxx
+
+SLOFILES= $(SLO)$/rc.obj \
+ $(SLO)$/resmgr.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/rc.obj \
+ $(OBJ)$/resmgr.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/rc/rc.cxx b/tools/source/rc/rc.cxx
new file mode 100644
index 000000000000..daa5ffdb71d9
--- /dev/null
+++ b/tools/source/rc/rc.cxx
@@ -0,0 +1,311 @@
+/*************************************************************************
+ *
+ * $RCSfile: rc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_RC_CXX
+
+#include <string.h>
+
+#ifndef _DATE_HXX
+#include <date.hxx>
+#endif
+#ifndef _TIME_HXX
+#include <time.hxx>
+#endif
+#ifndef _INTN_HXX
+#include <intn.hxx>
+#endif
+
+#ifndef _TOOLS_RC_HXX
+#include <rc.hxx>
+#endif
+#ifndef _TOOLS_RCID_H
+#include <rcid.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+ImplSVResourceData aResData;
+
+inline ImplSVResourceData* GetResData()
+{
+ //return &ImplGetSVData()->maResourceData;
+ return &aResData;
+}
+
+// =======================================================================
+
+Resource::Resource( const ResId& rResId )
+{
+ GetRes( rResId.SetRT( RSC_RESOURCE ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Resource::GetRes( const ResId& rResId )
+{
+ if ( rResId.GetResMgr() )
+ rResId.GetResMgr()->GetResource( rResId, this );
+ else
+ GetResManager()->GetResource( rResId, this );
+
+ IncrementRes( sizeof( RSHEADER_TYPE ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Resource::TestRes()
+{
+ ImplSVResourceData* pSVInData = GetResData();
+ if( pSVInData->pAppResMgr )
+ GetResManager()->TestStack( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Resource::SetResManager( ResMgr* pNewResMgr )
+{
+ ImplSVResourceData * pSVInData = GetResData();
+ pSVInData->pAppResMgr = pNewResMgr;
+}
+
+// -----------------------------------------------------------------------
+
+ResMgr* Resource::GetResManager()
+{
+ ImplSVResourceData* pSVInData = GetResData();
+
+ return pSVInData->pAppResMgr;
+}
+
+// =======================================================================
+
+#ifndef ENABLEUNICODE
+
+String::String( const ResId& rResId )
+{
+ rResId.SetRT( RSC_STRING );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // String laden
+ RSHEADER_TYPE * pResHdr = (RSHEADER_TYPE*)pResMgr->GetClass();
+ USHORT nLen = pResHdr->GetLocalOff() - sizeof( RSHEADER_TYPE );
+
+ USHORT nStringLen = strlen( (char*)(pResHdr+1) );
+ UniString aWString( (const char*)(pResHdr+1), RTL_TEXTENCODING_UTF8,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
+ InitStringRes( aWString );
+
+ USHORT nSize = sizeof( RSHEADER_TYPE ) + nStringLen + 1;
+ nSize += nSize % 2;
+ pResMgr->Increment( nSize );
+ }
+}
+
+#endif
+
+// =======================================================================
+
+UniString::UniString( const ResId& rResId )
+{
+ rResId.SetRT( RSC_STRING );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // String laden
+ RSHEADER_TYPE * pResHdr = (RSHEADER_TYPE*)pResMgr->GetClass();
+ USHORT nLen = pResHdr->GetLocalOff() - sizeof( RSHEADER_TYPE );
+
+ USHORT nStringLen = strlen( (char*)(pResHdr+1) );
+ InitStringRes( (const char*)(pResHdr+1), nStringLen );
+
+ USHORT nSize = sizeof( RSHEADER_TYPE ) + nStringLen + 1;
+ nSize += nSize % 2;
+ pResMgr->Increment( nSize );
+ }
+}
+
+// =======================================================================
+
+Time::Time( const ResId& rResId )
+{
+ nTime = 0;
+ rResId.SetRT( RSC_TIME );
+ ResMgr* pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId, &pResMgr );
+
+ USHORT nObjMask = (USHORT)pResMgr->ReadShort();
+
+ if ( 0x01 & nObjMask )
+ SetHour( (USHORT)pResMgr->ReadShort() );
+ if ( 0x02 & nObjMask )
+ SetMin( (USHORT)pResMgr->ReadShort() );
+ if ( 0x04 & nObjMask )
+ SetSec( (USHORT)pResMgr->ReadShort() );
+ if ( 0x08 & nObjMask )
+ Set100Sec( (USHORT)pResMgr->ReadShort() );
+}
+
+// =======================================================================
+
+Date::Date( const ResId& rResId )
+{
+ rResId.SetRT( RSC_DATE );
+ ResMgr* pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId, &pResMgr );
+
+ USHORT nObjMask = (USHORT)pResMgr->ReadShort();
+
+ if ( 0x01 & nObjMask )
+ SetYear( (USHORT)pResMgr->ReadShort() );
+ if ( 0x02 & nObjMask )
+ SetMonth( (USHORT)pResMgr->ReadShort() );
+ if ( 0x04 & nObjMask )
+ SetDay( (USHORT)pResMgr->ReadShort() );
+}
+
+// =======================================================================
+
+International::International( const ResId& rResId )
+{
+ rResId.SetRT( RSC_INTERNATIONAL );
+ ResMgr* pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId, &pResMgr );
+
+ USHORT nObjMask = (USHORT)pResMgr->ReadShort();
+
+ LanguageType eLangType = LANGUAGE_SYSTEM;
+ LanguageType eFormatType = LANGUAGE_SYSTEM;
+
+ if ( 0x0001 & nObjMask )
+ {
+ eLangType = (LanguageType)(USHORT)pResMgr->ReadShort();
+ eFormatType = eLangType;
+ }
+ if ( 0x0002 & nObjMask )
+ eFormatType = (LanguageType)(USHORT)pResMgr->ReadShort();
+ Init( eLangType, eFormatType );
+
+ if ( 0x0004 & nObjMask )
+ SetDateFormat( (DateFormat)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0008 & nObjMask )
+ SetDateDayLeadingZero( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0010 & nObjMask )
+ SetDateMonthLeadingZero( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0020 & nObjMask )
+ SetDateCentury( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0040 & nObjMask )
+ SetLongDateFormat( (DateFormat)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0080 & nObjMask )
+ SetLongDateDayOfWeekFormat( (DayOfWeekFormat)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0100 & nObjMask )
+ SetLongDateDayOfWeekSep( pResMgr->ReadString() );
+ if ( 0x0200 & nObjMask )
+ SetLongDateDayLeadingZero( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0400 & nObjMask )
+ SetLongDateDaySep( pResMgr->ReadString() );
+ if ( 0x0800 & nObjMask )
+ SetLongDateMonthFormat( (MonthFormat)(USHORT)pResMgr->ReadShort() );
+ if ( 0x1000 & nObjMask )
+ SetLongDateMonthSep( pResMgr->ReadString() );
+ if ( 0x2000 & nObjMask )
+ SetLongDateCentury( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x4000 & nObjMask )
+ SetLongDateYearSep( pResMgr->ReadString() );
+ if ( 0x8000 & nObjMask )
+ SetTimeFormat( (TimeFormat)(USHORT)pResMgr->ReadShort() );
+
+ // Zweite Maske holen
+ nObjMask = (USHORT)pResMgr->ReadShort();
+ if ( 0x0001 & nObjMask )
+ SetTimeLeadingZero( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0002 & nObjMask )
+ SetTimeAM( pResMgr->ReadString() );
+ if ( 0x0004 & nObjMask )
+ SetTimePM( pResMgr->ReadString() );
+ if ( 0x0008 & nObjMask )
+ SetNumLeadingZero( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0010 & nObjMask )
+ SetNumDigits( (USHORT)pResMgr->ReadShort() );
+ if ( 0x0020 & nObjMask )
+ SetCurrPositiveFormat( (USHORT)pResMgr->ReadShort() );
+ if ( 0x0040 & nObjMask )
+ SetCurrNegativeFormat( (USHORT)pResMgr->ReadShort() );
+ if ( 0x0080 & nObjMask )
+ SetCurrDigits( (USHORT)pResMgr->ReadShort() );
+ if ( 0x0100 & nObjMask )
+ SetNumTrailingZeros( (BOOL)(USHORT)pResMgr->ReadShort() );
+ if ( 0x0200 & nObjMask )
+ SetMeasurementSystem( (MeasurementSystem)(USHORT)pResMgr->ReadShort() );
+}
diff --git a/tools/source/rc/resmgr.cxx b/tools/source/rc/resmgr.cxx
new file mode 100644
index 000000000000..610f884b9b2b
--- /dev/null
+++ b/tools/source/rc/resmgr.cxx
@@ -0,0 +1,1364 @@
+/*************************************************************************
+ *
+ * $RCSfile: resmgr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:06 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef _VOS_SIGNAL_HXX_
+#include <vos/signal.hxx>
+#endif
+
+#ifndef _NEW_HXX
+#include <new.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _TABLE_HXX
+#include <table.hxx>
+#endif
+#ifndef _FSYS_HXX
+#include <fsys.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <stream.hxx>
+#endif
+#ifndef _INTN_HXX
+#include <intn.hxx>
+#endif
+#ifndef _TOOLS_RESMGR_HXX
+#include <resmgr.hxx>
+#endif
+#ifndef _TOOLS_RC_HXX
+#include <rc.hxx>
+#endif
+#ifndef _TOOLS_RCID_H
+#include <rcid.h>
+#endif
+
+#ifndef _TOOLS_SIMPLERESMGR_HXX_
+#include "simplerm.hxx"
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+extern ImplSVResourceData aResData;
+inline ImplSVResourceData* GetResData()
+{
+ return &aResData;
+}
+
+static List & GetResMgrList()
+{
+ ImplSVResourceData * pRD = GetResData();
+ if ( !pRD->pInternalResMgrList )
+ pRD->pInternalResMgrList = new List();
+ return *pRD->pInternalResMgrList;
+}
+
+struct ImpContent
+{
+ ULONG nTypeAndId;
+ ULONG nOffset;
+};
+
+#if defined( OS2 ) && defined( ICC )
+static int _Optlink Compare( const void * pFirst, const void * pSecond )
+#elif S390
+extern "C" { int Compare( const void * pFirst, const void * pSecond )
+#else
+static int __LOADONCALLAPI Compare( const void * pFirst, const void * pSecond )
+#endif
+{
+ if( ((ImpContent *)pFirst)->nTypeAndId > ((ImpContent *)pSecond)->nTypeAndId )
+ return( 1 );
+ else if( ((ImpContent *)pFirst)->nTypeAndId < ((ImpContent *)pSecond)->nTypeAndId )
+ return( -1 );
+ else
+ return( 0 );
+}
+
+#ifdef S390
+}
+#endif
+
+#if defined( OS2 ) && defined( ICC )
+static int _Optlink Search( const void * nTypeAndId, const void * pSecond )
+#elif S390
+extern "C" { int Search( const void * nTypeAndId, const void * pSecond )
+#else
+static int __LOADONCALLAPI Search( const void * nTypeAndId, const void * pSecond )
+#endif
+{
+ if( (ULONG)nTypeAndId > (((ImpContent *)pSecond)->nTypeAndId) )
+ return( 1 );
+ else if( (ULONG)nTypeAndId < (((ImpContent *)pSecond)->nTypeAndId) )
+ return( -1 );
+ else
+ return( 0 );
+}
+
+#ifdef S390
+}
+#endif
+
+// =======================================================================
+
+SvStream * InternalResMgr::GetBitmapStream( USHORT nId )
+{
+ // Anfang der Strings suchen
+ ImpContent * pFind = (ImpContent *)
+ bsearch( (void *)((ULONG(RT_SYS_BITMAP) << 16) | nId), pContent, nEntries,
+ sizeof( ImpContent ), Search );
+
+ if ( pFind )
+ {
+ pStm->Seek( pFind->nOffset );
+ return pStm;
+ }
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void InternalResMgr::GetResMgrPath( InternalResMgr* pThis,
+ const UniString& rFileName,
+ const UniString* pAppFileName,
+ const UniString* pResourcePath )
+{
+ UniString aResFile;
+ if ( rFileName.Len() )
+ {
+ UniString aResPath;
+ if( pResourcePath )
+ aResPath += *pResourcePath;
+ if ( pAppFileName )
+ {
+ DirEntry aAppDir( *pAppFileName );
+ aAppDir.CutName();
+ UniString aAppPath = aAppDir.GetFull();
+ DirEntry aResSubPath( UniString( RTL_CONSTASCII_USTRINGPARAM( "resource" ) ) );
+ aAppDir += aResSubPath;
+ UniString aAppResPath = aAppDir.GetFull();
+
+ // Default resource path is bin\resource
+ if ( aResPath.Len() )
+ aResPath += DirEntry::GetSearchDelimiter();
+ aResPath += aAppResPath;
+
+ // we a search also in the bin path
+ aResPath += DirEntry::GetSearchDelimiter();
+ aResPath += aAppPath;
+ }
+ const sal_Char* pEnv = getenv( "STAR_RESOURCEPATH" );
+ if( pEnv )
+ {
+ if ( aResPath.Len() )
+ aResPath += DirEntry::GetSearchDelimiter();
+ aResPath.AppendAscii( pEnv );
+ }
+
+ DirEntry aFullName( rFileName );
+ if ( aFullName.Find( aResPath ) )
+ aResFile = aFullName.GetFull();
+ else
+ aResFile = rFileName;
+ }
+ else if ( pAppFileName )
+ {
+ // Default Resourcefile ist die Anwendung
+ aResFile = *pAppFileName;
+#if defined( OS2 ) || defined( WIN ) || defined( WNT )
+ aResFile.Erase( aResFile.Len() - 4 );
+#endif
+ aResFile.AppendAscii( ".res" );
+ }
+
+ if( aResFile.Len() )
+ {
+ DirEntry aEntry = aResFile;
+
+ FileStat aStat( aEntry );
+ if( aStat.IsKind( FSYS_KIND_FILE ) )
+ {
+ pThis->aFileName = aEntry.GetFull();
+ pThis->aShortFileName = aEntry.GetName();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+InternalResMgr::InternalResMgr()
+ : pContent( NULL )
+ , pStringBlock( NULL )
+ , pStm( NULL )
+ , bEqual2Content( TRUE )
+ , nEntries( 0 )
+ , pResUseDump( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+InternalResMgr::~InternalResMgr()
+{
+ SvMemFree(pContent);
+ SvMemFree(pStringBlock);
+ delete pStm;
+
+#ifdef DBG_UTIL
+ if( pResUseDump )
+ {
+ const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
+ if ( pLogFile )
+ {
+ SvFileStream aStm( UniString( pLogFile, RTL_TEXTENCODING_ASCII_US ), STREAM_WRITE );
+ aStm.Seek( STREAM_SEEK_TO_END );
+ ByteString aLine( "FileName: " );
+ aLine.Append( ByteString( aFileName, RTL_TEXTENCODING_UTF8 ) );
+ aStm.WriteLine( aLine );
+
+ for( ULONG i = 0; i < pResUseDump->Count(); i++ )
+ {
+ ULONG nKeyId = pResUseDump->GetObjectKey( i );
+ aLine.Assign( "Type/Id: " );
+ aLine.Append( ByteString::CreateFromInt32( (nKeyId >> 16) & 0xFFFF ) );
+ aLine.Append( '/' );
+ aLine.Append( ByteString::CreateFromInt32( nKeyId & 0xFFFF ) );
+ aStm.WriteLine( aLine );
+ }
+ }
+ }
+#endif
+
+ delete pResUseDump;
+}
+
+// -----------------------------------------------------------------------
+
+InternalResMgr* InternalResMgr::Create( const UniString& rName,
+ const UniString* pAppName,
+ const UniString* pResPath )
+{
+ InternalResMgr* pThis = new InternalResMgr();
+
+ GetResMgrPath( pThis, rName, pAppName, pResPath );
+
+ if ( pThis->aFileName.Len() && pThis->Create() )
+ return pThis;
+
+ delete pThis;
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL InternalResMgr::Create()
+{
+ BOOL bDone = FALSE;
+
+ pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
+ if( pStm->GetError() == 0 )
+ {
+ INT32 lContLen = 0;
+
+ pStm->Seek( STREAM_SEEK_TO_END );
+ /*
+ if( ( pInternalResMgr->pHead = (RSHEADER_TYPE *)mmap( 0, nResourceFileSize,
+ PROT_READ, MAP_PRIVATE,
+ fRes, 0 ) ) != (RSHEADER_TYPE *)-1)
+ */
+ pStm->SeekRel( - (int)sizeof( lContLen ) );
+ pStm->Read( &lContLen, sizeof( lContLen ) );
+ // is bigendian, swab to the right endian
+ lContLen = ResMgr::GetLong( &lContLen );
+ pStm->SeekRel( -lContLen );
+ pContent = (ImpContent *)SvMemAlloc( lContLen );
+ pStm->Read( pContent, lContLen );
+ // Auf die Anzahl der ImpContent kürzen
+ nEntries = (UINT32)lContLen / sizeof( ImpContent );
+ bEqual2Content = TRUE; // Die Daten der Resourcen liegen
+ // genauso wie das Inhaltsverzeichnis
+ BOOL bSorted = TRUE;
+ if( nEntries )
+ {
+#ifdef DBG_UTIL
+ const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
+ if ( pLogFile )
+ {
+ pResUseDump = new Table();
+ for( ULONG i = 0; i < nEntries; i++ )
+ pResUseDump->Insert( pContent[i].nTypeAndId, NULL );
+ }
+#endif
+ // swap the content to the right endian
+ pContent[0].nTypeAndId = ResMgr::GetLong( &pContent[0].nTypeAndId );
+ pContent[0].nOffset = ResMgr::GetLong( &pContent[0].nOffset );
+ for( ULONG i = 0; i < nEntries -1; i++ )
+ {
+ // swap the content to the right endian
+ pContent[i+1].nTypeAndId = ResMgr::GetLong( &pContent[i+1].nTypeAndId );
+ pContent[i+1].nOffset = ResMgr::GetLong( &pContent[i+1].nOffset );
+ if( pContent[i].nTypeAndId >= pContent[i +1].nTypeAndId )
+ bSorted = FALSE;
+ if( (pContent[i].nTypeAndId & 0xFFFF0000) == (pContent[i +1].nTypeAndId & 0xFFFF0000)
+ && pContent[i].nOffset >= pContent[i +1].nOffset )
+ bEqual2Content = FALSE;
+ }
+ }
+ DBG_ASSERT( bSorted, "content not sorted" )
+ DBG_ASSERT( bEqual2Content, "resource structure wrong" )
+ if( !bSorted )
+ qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
+
+ bDone = TRUE;
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+InternalResMgr* InternalResMgr::GetInternalResMgr( const UniString& rFileName,
+ const UniString* pAppName,
+ const UniString* pResPath )
+{
+ ImplSVResourceData* pSVInData = GetResData();
+
+ // Nur InternalResMgr's mit FileNamen stehen in der Liste
+ if ( rFileName.Len() )
+ {
+ List& rMgrList = GetResMgrList();
+
+ InternalResMgr* pEle = (InternalResMgr*)rMgrList.First();
+ while( pEle )
+ {
+ if ( rFileName.EqualsIgnoreCaseAscii( pEle->aFileName ) ||
+ rFileName.EqualsIgnoreCaseAscii( pEle->aShortFileName ) )
+ {
+ pEle->AddRef();
+ return pEle;
+ }
+ pEle = (InternalResMgr*)rMgrList.Next();
+ }
+
+#ifdef DBG_UTIL
+ ByteString aTraceStr( "Search/Load-RESDLL:" );
+ aTraceStr += ByteString( rFileName, RTL_TEXTENCODING_UTF8 );
+ DBG_TRACE( aTraceStr.GetBuffer() );
+#endif
+
+ pEle = Create( rFileName, pAppName, pResPath );
+
+ if ( pEle )
+ {
+ pEle->AddRef();
+ rMgrList.Insert( pEle );
+ }
+
+ return pEle;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void InternalResMgr::FreeInternalResMgr( InternalResMgr* pFreeInternalResMgr )
+{
+ // Nur InternalResMgr's mit FileNamen stehen in der Liste und werden vor dem
+ // Programmende freigegeben
+ if( pFreeInternalResMgr->aFileName.Len() )
+ {
+ if( pFreeInternalResMgr->ReleaseRef() == 0 )
+ GetResMgrList().Remove( pFreeInternalResMgr );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, USHORT nId ) const
+{
+ // Anfang der Strings suchen
+ ImpContent * pFind = (ImpContent *)
+ bsearch( (void *)((ULONG(nRT) << 16) | nId), pContent, nEntries,
+ sizeof( ImpContent ), Search );
+ return pFind != NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* InternalResMgr::LoadGlobalRes( RESOURCE_TYPE nRT, USHORT nId,
+ void **pResHandle )
+{
+#ifdef DBG_UTIL
+ if( pResUseDump )
+ pResUseDump->Remove( (ULONG(nRT) << 16) | nId );
+#endif
+ // Anfang der Strings suchen
+ ImpContent * pFind = (ImpContent *)
+ bsearch( (void *)((ULONG(nRT) << 16) | nId), pContent, nEntries,
+ sizeof( ImpContent ), Search );
+ if( nRT == RSC_STRING && bEqual2Content && pFind )
+ {
+ // String Optimierung
+ if( !pStringBlock )
+ {
+ // Anfang der Strings suchen
+ ImpContent * pFirst = pFind;
+ ImpContent * pLast = pFirst;
+ while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 16) == RSC_STRING )
+ pFirst--;
+ while( pLast < (pContent + nEntries) && (pLast->nTypeAndId >> 16) == RSC_STRING )
+ pLast++;
+ nOffCorrection = pFirst->nOffset;
+ UINT32 nSize;
+ --pLast;
+ pStm->Seek( pLast->nOffset );
+ RSHEADER_TYPE aHdr;
+ pStm->Read( &aHdr, sizeof( aHdr ) );
+ nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
+ pStringBlock = (BYTE*)SvMemAlloc( nSize );
+ pStm->Seek( pFirst->nOffset );
+ pStm->Read( pStringBlock, nSize );
+ }
+ *pResHandle = pStringBlock;
+ return (BYTE*)pStringBlock + pFind->nOffset - nOffCorrection;
+ }
+ *pResHandle = 0;
+ if( pFind )
+ {
+ RSHEADER_TYPE aHeader;
+ pStm->Seek( pFind->nOffset );
+ pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
+ void * pRes = new BYTE[ aHeader.GetGlobOff() ];
+ memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
+ pStm->Read( (BYTE*)pRes + sizeof( RSHEADER_TYPE ),
+ aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
+ return pRes;
+ }
+ //Resource holen
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
+{
+ if ( !pResHandle )
+ // REsource wurde extra allokiert
+ delete pResource;
+}
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+UniString GetTypeRes_Impl( const ResId& rTypeId )
+{
+ // Funktion verlassen, falls Resourcefehler in dieser Funktion
+ static bInUse = FALSE;
+ UniString aTypStr( rTypeId.GetId() );
+
+ if ( !bInUse )
+ {
+ bInUse = TRUE;
+
+ ResId aResId( RSCVERSION_ID );
+ aResId.SetRT( RSC_VERSIONCONTROL );
+
+ if ( rTypeId.GetResMgr()->GetResource( aResId ) )
+ {
+ rTypeId.SetRT( RSC_STRING );
+ if ( rTypeId.GetResMgr()->IsAvailable( rTypeId ) )
+ {
+ aTypStr = UniString( rTypeId );
+ // Versions Resource Klassenzeiger ans Ende setzen
+ Resource::GetResManager()->Increment( sizeof( RSHEADER_TYPE ) );
+ }
+ }
+ bInUse = FALSE;
+ }
+
+ return aTypStr;
+}
+
+// -----------------------------------------------------------------------
+
+static void RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
+ RESOURCE_TYPE nRT, USHORT nId,
+ ImpRCStack* pResStack, short nStackTop )
+{
+ // neuen ResourceMgr erzeugen
+ ResMgr* pNewResMgr = new ResMgr( pResMgr->GetFileName() );
+
+ ByteString aStr = ByteString( pResMgr->GetFileName(), RTL_TEXTENCODING_UTF8 );
+ if ( aStr.Len() )
+ aStr += '\n';
+
+ aStr.Append( "Class: " );
+ aStr.Append( ByteString( GetTypeRes_Impl( ResId( nRT, pNewResMgr ) ), RTL_TEXTENCODING_UTF8 ) );
+ aStr.Append( ", Id: " );
+ aStr.Append( ByteString::CreateFromInt32( (long)nId ) );
+ aStr.Append( ". " );
+ aStr.Append( pMessage );
+
+ aStr.Append( "\nResource Stack\n" );
+ while( nStackTop > 0 )
+ {
+ aStr.Append( "Class: " );
+ aStr.Append( ByteString( GetTypeRes_Impl( ResId( (pResStack + nStackTop)->pResource->GetRT(), pNewResMgr ) ), RTL_TEXTENCODING_UTF8 ) );
+ aStr.Append( ", Id: " );
+ aStr.Append( ByteString::CreateFromInt32( (long)(pResStack + nStackTop)->pResource->GetId() ) );
+ nStackTop--;
+ }
+
+ delete pNewResMgr;
+
+ DBG_ERROR( aStr.GetBuffer() );
+}
+
+#endif
+
+// =======================================================================
+
+static void RscException_Impl()
+{
+ switch ( NAMESPACE_VOS(OSignalHandler)::raise( OSL_SIGNAL_USER_RESOURCEFAILURE, (void*)"" ) )
+ {
+ case NAMESPACE_VOS(OSignalHandler)::TAction_CallNextHandler:
+ abort();
+ break;
+
+ case NAMESPACE_VOS(OSignalHandler)::TAction_Ignore:
+ return;
+ break;
+
+ case NAMESPACE_VOS(OSignalHandler)::TAction_AbortApplication:
+ abort();
+ break;
+
+ case NAMESPACE_VOS(OSignalHandler)::TAction_KillApplication:
+ exit(-1);
+ break;
+ }
+}
+
+// =======================================================================
+
+void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, USHORT Id )
+{
+ pResource = NULL;
+ pClassRes = NULL;
+ Flags = RC_NOTYPE;
+ aResHandle = NULL;
+ pResObj = pObj;
+ nId = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
+ pResMgr = pMgr;
+ if ( !(Id & RSC_DONTRELEASE) )
+ Flags |= RC_AUTORELEASE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpRCStack::Clear()
+{
+ pResource = NULL;
+ pClassRes = NULL;
+ Flags = RC_NOTYPE;
+ aResHandle = NULL;
+ pResObj = NULL;
+ nId = 0;
+ pResMgr = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static RSHEADER_TYPE* LocalResource( const ImpRCStack* pStack,
+ RESOURCE_TYPE nRTType,
+ USHORT nId )
+{
+ // Gibt die Position der Resource zurueck, wenn sie gefunden wurde.
+ // Ansonsten gibt die Funktion Null zurueck.
+ RSHEADER_TYPE* pTmp; // Zeiger auf Kind-Resourceobjekte
+ RSHEADER_TYPE* pEnd; // Zeiger auf das Ende der Resource
+
+ if ( pStack->pResource && pStack->pClassRes )
+ {
+ pTmp = (RSHEADER_TYPE*)
+ ((BYTE*)pStack->pResource + pStack->pResource->GetLocalOff());
+ pEnd = (RSHEADER_TYPE*)
+ ((BYTE*)pStack->pResource + pStack->pResource->GetGlobOff());
+ while ( pTmp != pEnd )
+ {
+ if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
+ return pTmp;
+ pTmp = (RSHEADER_TYPE*)((BYTE*)pTmp + pTmp->GetGlobOff());
+ }
+ }
+
+ return NULL;
+}
+
+// =======================================================================
+
+void ResMgr::DestroyAllResMgr()
+{
+ ImplSVResourceData* pSVInData = GetResData();
+
+ // Da auch von Abort gerufen werden kann, geben wir alle
+ // ResMgr's und alle InternalResMgr's hier frei
+ List* pMgrList = pSVInData->pInternalResMgrList;
+ if ( pMgrList )
+ {
+ InternalResMgr* pEle = (InternalResMgr*)pMgrList->First();
+ while ( pEle )
+ {
+ DBG_WARNING1( "ResMgr's not destroyed: %s",
+ ByteString( pEle->aFileName, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ pEle->ReleaseReference();
+ pEle = (InternalResMgr*)pMgrList->Next();
+ }
+ delete pMgrList;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ResMgr::Init( const UniString& rFileName )
+{
+ if ( !pImpRes )
+ {
+#ifdef DBG_UTIL
+ ByteString aStr( "Resourcefile not found:\n" );
+ aStr += ByteString( rFileName, RTL_TEXTENCODING_UTF8 );
+ DBG_ERROR( aStr.GetBuffer() );
+#endif
+ RscException_Impl();
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ void* aResHandle = 0; // Hilfvariable fuer Resource
+ void* pVoid; // Zeiger auf die Resource
+
+ pVoid = pImpRes->LoadGlobalRes( RSC_VERSIONCONTROL, RSCVERSION_ID,
+ &aResHandle );
+ if ( pVoid )
+ pImpRes->FreeGlobalRes( aResHandle, pVoid );
+ else
+ {
+ ByteString aStr( "Wrong version:\n" );
+ aStr += ByteString( pImpRes->aFileName, RTL_TEXTENCODING_UTF8 );
+ DbgError( aStr.GetBuffer() );
+ }
+ }
+#endif
+
+ nTopRes = 0;
+ aStack[0].Clear();
+}
+
+// -----------------------------------------------------------------------
+
+ResMgr::ResMgr( const UniString& rFileName,
+ const UniString* pAppName,
+ const UniString* pResPath )
+{
+ pImpRes = InternalResMgr::GetInternalResMgr( rFileName, pAppName, pResPath );
+ Init( pImpRes ? (const UniString&)pImpRes->aFileName : rFileName );
+}
+
+// -----------------------------------------------------------------------
+
+ResMgr::ResMgr( InternalResMgr * pImpMgr )
+{
+ pImpRes = pImpMgr;
+ Init( pImpMgr->aFileName );
+}
+
+// -----------------------------------------------------------------------
+
+ResMgr::~ResMgr()
+{
+ InternalResMgr::FreeInternalResMgr( pImpRes );
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+
+void ResMgr::TestStack( const Resource* pResObj )
+{
+ if ( DbgIsResource() )
+ {
+ for( short i = 1; i <= nTopRes; i++ )
+ {
+ if ( aStack[i].pResObj == pResObj )
+ {
+#ifdef DBG_UTIL
+ RscError_Impl( "Resource not freed! ", this,
+ aStack[i].pResource->GetRT(),
+ aStack[i].pResource->GetId(),
+ aStack, i -1 );
+#endif
+ }
+ }
+ }
+}
+
+#else
+
+void ResMgr::TestStack( const Resource* )
+{
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+BOOL ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
+{
+ BOOL bAvailable = FALSE;
+ RSHEADER_TYPE* pClassRes = rId.GetpResource();
+ RESOURCE_TYPE nRT = rId.GetRT2();
+ USHORT nId = rId.GetId();
+ const ResMgr* pMgr = rId.GetResMgr();
+
+ if ( !pMgr )
+ pMgr = this;
+
+ if ( !pResObj || pResObj == pMgr->aStack[pMgr->nTopRes].pResObj )
+ {
+ if ( !pClassRes )
+ pClassRes = LocalResource( &pMgr->aStack[pMgr->nTopRes], nRT, nId );
+ if ( pClassRes )
+ {
+ if ( pClassRes->GetRT() == nRT )
+ bAvailable = TRUE;
+ }
+ }
+
+ // vieleicht globale Resource
+ if ( !pClassRes )
+ bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
+
+ return bAvailable;
+}
+
+// -----------------------------------------------------------------------
+
+inline ResMgr* GetActualResMgr()
+{
+ return GetResData()->pAppResMgr;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
+{
+ DBG_TESTSOLARMUTEX();
+
+ ResMgr* pMgr = rId.GetResMgr();
+ if ( pMgr && (this != pMgr) )
+ return pMgr->GetResource( rId, pResObj );
+
+ RSHEADER_TYPE* pClassRes = rId.GetpResource();
+ RESOURCE_TYPE nRT = rId.GetRT2();
+ USHORT nId = rId.GetId();
+
+ ResMgr* pLastMgr = GetActualResMgr();
+ if ( pLastMgr != this )
+ Resource::SetResManager( this );
+
+ nTopRes++; // Stackzeiger erhoehen
+ ImpRCStack* pTop = &aStack[nTopRes];
+ pTop->Init( pLastMgr, pResObj, nId |
+ (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
+
+ if ( pClassRes )
+ {
+ if ( pClassRes->GetRT() == nRT )
+ pTop->pClassRes = pClassRes;
+ else
+ {
+#ifdef DBG_UTIL
+ RscError_Impl( "Different class and resource type!",
+ this, nRT, nId, aStack, nTopRes -1 );
+#endif
+ RscException_Impl();
+ nTopRes--;
+ return FALSE;
+ }
+ }
+ else
+ pTop->pClassRes = LocalResource( pTop -1, nRT, nId );
+
+ if ( pTop->pClassRes )
+ // lokale Resource, nicht system Resource
+ pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
+ else
+ {
+ pTop->Flags |= RC_GLOBAL;
+ pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
+ if ( pTop->pClassRes )
+ pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
+ else
+ {
+#ifdef DBG_UTIL
+ RscError_Impl( "Cannot load resource! ",
+ this, nRT, nId, aStack, nTopRes -1 );
+#endif
+ RscException_Impl();
+ ImplSVResourceData * pRD = GetResData();
+ nTopRes--;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
+{
+ if ( rResId.GetResMgr() )
+ *ppResMgr = rResId.GetResMgr();
+ else
+ *ppResMgr = Resource::GetResManager();
+ (*ppResMgr)->GetResource( rResId );
+ (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
+ return (*ppResMgr)->GetClass();
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+void ResMgr::PopContext( const Resource* pResObj )
+#else
+void ResMgr::PopContext( const Resource* )
+#endif
+{
+#ifdef DBG_UTIL
+ if ( DbgIsResource() )
+ {
+ if ( (aStack[nTopRes].pResObj != pResObj) || !nTopRes )
+ {
+ RscError_Impl( "Cannot free resource! ", this,
+ RSC_NOTYPE, 0, aStack, nTopRes );
+ }
+ }
+#endif
+
+ if ( nTopRes )
+ {
+ ImpRCStack* pTop = &aStack[nTopRes];
+#ifdef DBG_UTIL
+ if ( DbgIsResource() )
+ {
+ void* pRes = (BYTE*)pTop->pResource +
+ pTop->pResource->GetLocalOff();
+
+ if ( pTop->pClassRes != pRes )
+ {
+ RscError_Impl( "Classpointer not at the end!",
+ this, pTop->pResource->GetRT(),
+ pTop->pResource->GetId(),
+ aStack, nTopRes -1 );
+ }
+ }
+#endif
+
+ // Resource freigeben
+ if ( pTop->Flags & RC_GLOBAL )
+ // kann auch Fremd-Ressource sein
+ pImpRes->FreeGlobalRes( pTop->aResHandle, pTop->pResource );
+ if ( pTop->pResMgr != this )
+ // wurde durch ResId gesetzt, automatisch zuruecksetzen
+ Resource::SetResManager( pTop->pResMgr );
+ nTopRes--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+RSHEADER_TYPE* ResMgr::CreateBlock( const ResId& rId )
+{
+ RSHEADER_TYPE* pHeader = NULL;
+ if ( GetResource( rId ) )
+ {
+ // Der Zeiger steht am Anfang, deswegen zeigt der Klassen-Pointer
+ // auf den Header und die restliche Groesse ist die Gesammte.
+ pHeader = (RSHEADER_TYPE*)new BYTE[ GetRemainSize() ];
+ memcpy( pHeader, GetClass(), GetRemainSize() );
+ Increment( pHeader->GetLocalOff() ); //ans Ende setzen
+ if ( pHeader->GetLocalOff() != pHeader->GetGlobOff() )
+ // Hat Sub-Ressourcen, deshalb extra freigeben
+ PopContext();
+ }
+
+ return pHeader;
+}
+
+// ------------------------------------------------------------------
+
+INT16 ResMgr::GetShort( void * pShort )
+{
+#ifdef __BIGENDIAN
+ return *(UINT16*)pShort;
+#else
+ return SWAPSHORT( *(UINT16*)pShort );
+#endif
+}
+
+// ------------------------------------------------------------------
+
+INT32 ResMgr::GetLong( void * pLong )
+{
+#ifdef __BIGENDIAN
+ return (long)(((INT32)(*(UINT16*)pLong) << 16) | *(((UINT16*)pLong) + 1));
+#else
+ return ((INT32)(*(BYTE*)pLong) << 24)
+ | ((INT32)(*((BYTE*)pLong +1)) << 16)
+ | ((INT32)(*((BYTE*)pLong +2)) << 8)
+ | (INT32)(*((BYTE*)pLong +3));
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ResMgr::GetString( UniString& rStr, const BYTE* pStr )
+{
+ UniString aString( (sal_Char*)pStr, RTL_TEXTENCODING_UTF8,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
+ rStr = aString;
+ return GetStringSize( pStr );
+}
+
+// ------------------------------------------------------------------
+
+USHORT ResMgr::GetStringSize( const BYTE* pStr )
+{
+ return GetStringSize( strlen( (const char*)pStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ResMgr::GetRemainSize()
+{
+ return (USHORT)((long)(BYTE *)aStack[nTopRes].pResource +
+ aStack[nTopRes].pResource->GetLocalOff() -
+ (long)(BYTE *)aStack[nTopRes].pClassRes);
+}
+
+// -----------------------------------------------------------------------
+
+void* ResMgr::Increment( USHORT nSize )
+{
+ BYTE* pClassRes = (BYTE*)aStack[nTopRes].pClassRes + nSize;
+
+ aStack[nTopRes].pClassRes = pClassRes;
+
+ RSHEADER_TYPE* pRes = aStack[nTopRes].pResource;
+
+ if ( (pRes->GetGlobOff() == pRes->GetLocalOff()) &&
+ (((char*)pRes + pRes->GetLocalOff()) == aStack[nTopRes].pClassRes) &&
+ (aStack[nTopRes].Flags & RC_AUTORELEASE))
+ {
+ PopContext( aStack[nTopRes].pResObj );
+ }
+
+ return pClassRes;
+}
+
+// -----------------------------------------------------------------------
+
+const char* ResMgr::GetLang( LanguageType& nType, USHORT nPrio )
+{
+ static sal_Char const aDefEng[] = "44";
+ static sal_Char const aDefUSEng[] = "01";
+ static sal_Char const aDefGerman[] = "49";
+ static sal_Char const aDefFrench[] = "33";
+ static sal_Char const aDefPortuguese[] = "03";
+
+ if ( nType == LANGUAGE_SYSTEM || nType == LANGUAGE_DONTKNOW )
+ nType = ::GetSystemLanguage();
+
+ if ( nPrio == 0 )
+ {
+ switch ( nType )
+ {
+ case LANGUAGE_DANISH:
+ return "45";
+
+ case LANGUAGE_DUTCH:
+ case LANGUAGE_DUTCH_BELGIAN:
+ return "31";
+
+ case LANGUAGE_ENGLISH:
+ case LANGUAGE_ENGLISH_UK:
+ case LANGUAGE_ENGLISH_EIRE:
+ case LANGUAGE_ENGLISH_SAFRICA:
+ case LANGUAGE_ENGLISH_JAMAICA:
+ case LANGUAGE_ENGLISH_BELIZE:
+ case LANGUAGE_ENGLISH_TRINIDAD:
+ case LANGUAGE_ENGLISH_ZIMBABWE:
+ case LANGUAGE_ENGLISH_PHILIPPINES:
+ return aDefEng;
+
+ case LANGUAGE_ENGLISH_US:
+ case LANGUAGE_ENGLISH_CAN:
+ return aDefUSEng;
+
+ case LANGUAGE_ENGLISH_AUS:
+ case LANGUAGE_ENGLISH_NZ:
+ return "61";
+
+ case LANGUAGE_FINNISH:
+ return "05";
+
+ case LANGUAGE_FRENCH_CANADIAN:
+ return "02";
+
+ case LANGUAGE_FRENCH:
+ case LANGUAGE_FRENCH_BELGIAN:
+ case LANGUAGE_FRENCH_SWISS:
+ case LANGUAGE_FRENCH_LUXEMBOURG:
+ case LANGUAGE_FRENCH_MONACO:
+ return aDefFrench;
+
+ case LANGUAGE_GERMAN:
+ case LANGUAGE_GERMAN_SWISS:
+ case LANGUAGE_GERMAN_AUSTRIAN:
+ case LANGUAGE_GERMAN_LUXEMBOURG:
+ case LANGUAGE_GERMAN_LIECHTENSTEIN:
+ return aDefGerman;
+
+ case LANGUAGE_ITALIAN:
+ case LANGUAGE_ITALIAN_SWISS:
+ return "39";
+
+ case LANGUAGE_NORWEGIAN:
+ case LANGUAGE_NORWEGIAN_BOKMAL:
+ return "47";
+
+ case LANGUAGE_PORTUGUESE:
+ return aDefPortuguese;
+
+ case LANGUAGE_PORTUGUESE_BRAZILIAN:
+ return "55";
+
+ case LANGUAGE_SPANISH:
+ case LANGUAGE_SPANISH_MEXICAN:
+ case LANGUAGE_SPANISH_MODERN:
+ case LANGUAGE_SPANISH_GUATEMALA:
+ case LANGUAGE_SPANISH_COSTARICA:
+ case LANGUAGE_SPANISH_PANAMA:
+ case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
+ case LANGUAGE_SPANISH_VENEZUELA:
+ case LANGUAGE_SPANISH_COLOMBIA:
+ case LANGUAGE_SPANISH_PERU:
+ case LANGUAGE_SPANISH_ARGENTINA:
+ case LANGUAGE_SPANISH_ECUADOR:
+ case LANGUAGE_SPANISH_CHILE:
+ case LANGUAGE_SPANISH_URUGUAY:
+ case LANGUAGE_SPANISH_PARAGUAY:
+ case LANGUAGE_SPANISH_BOLIVIA:
+ return "34";
+
+ case LANGUAGE_SWEDISH:
+ return "46";
+
+ case LANGUAGE_POLISH:
+ return "48";
+ case LANGUAGE_CZECH:
+ return "42";
+ case LANGUAGE_HUNGARIAN:
+ return "36";
+ case LANGUAGE_RUSSIAN:
+ return "07";
+ case LANGUAGE_SLOVAK:
+ return "04";
+ case LANGUAGE_GREEK:
+ return "30";
+ case LANGUAGE_TURKISH:
+ return "90";
+
+ case LANGUAGE_CHINESE_SIMPLIFIED:
+ return "86";
+ case LANGUAGE_CHINESE_TRADITIONAL:
+ return "88";
+ case LANGUAGE_JAPANESE:
+ return "81";
+ case LANGUAGE_KOREAN:
+ case LANGUAGE_KOREAN_JOHAB:
+ return "82";
+
+ case LANGUAGE_ARABIC:
+ case LANGUAGE_ARABIC_IRAQ:
+ case LANGUAGE_ARABIC_EGYPT:
+ case LANGUAGE_ARABIC_LIBYA:
+ case LANGUAGE_ARABIC_ALGERIA:
+ case LANGUAGE_ARABIC_MOROCCO:
+ case LANGUAGE_ARABIC_TUNISIA:
+ case LANGUAGE_ARABIC_OMAN:
+ case LANGUAGE_ARABIC_YEMEN:
+ case LANGUAGE_ARABIC_SYRIA:
+ case LANGUAGE_ARABIC_JORDAN:
+ case LANGUAGE_ARABIC_LEBANON:
+ case LANGUAGE_ARABIC_KUWAIT:
+ case LANGUAGE_ARABIC_UAE:
+ case LANGUAGE_ARABIC_BAHRAIN:
+ case LANGUAGE_ARABIC_QATAR:
+ return "96";
+
+ default:
+ return aDefUSEng;
+ }
+ }
+ else if ( nPrio == 1 )
+ {
+ switch ( nType )
+ {
+ case LANGUAGE_FRENCH_CANADIAN:
+ return aDefFrench;
+
+ case LANGUAGE_PORTUGUESE_BRAZILIAN:
+ return aDefPortuguese;
+
+ default:
+ return NULL;
+ }
+ }
+ else if ( nPrio == 2 )
+ return aDefUSEng;
+ else if ( nPrio == 3 )
+ return aDefEng;
+ else
+ return aDefGerman;
+}
+
+// -----------------------------------------------------------------------
+
+ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
+ LanguageType nType,
+ const UniString* pAppName,
+ const UniString* pResPath )
+{
+ // Suchreihenfolge festlegen
+ const sal_Char* pLang[5];
+
+ // Resourcefile suchen
+ UniString aName;
+ InternalResMgr* pInternalResMgr = NULL;
+ for ( int i = 0; i < 5; i++ )
+ {
+ pLang[i] = GetLang( nType, i );
+
+ if ( pLang[i] && (i == 0 || pLang[i] != pLang[0]) )
+ {
+ aName.AssignAscii( pPrefixName );
+ aName.AppendAscii( pLang[i] );
+ aName.AppendAscii( ".res" );
+ pInternalResMgr = InternalResMgr::GetInternalResMgr( aName, pAppName, pResPath );
+ if ( pInternalResMgr )
+ break;
+ }
+ }
+
+ if ( pInternalResMgr )
+ return new ResMgr( pInternalResMgr );
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+INT16 ResMgr::ReadShort()
+{
+ INT16 n = GetShort( GetClass() );
+ Increment( sizeof( INT16 ) );
+ return n;
+}
+
+// -----------------------------------------------------------------------
+
+INT32 ResMgr::ReadLong()
+{
+ INT32 n = GetLong( GetClass() );
+ Increment( sizeof( INT32 ) );
+ return n;
+}
+
+// -----------------------------------------------------------------------
+
+UniString ResMgr::ReadString()
+{
+ UniString aRet;
+ Increment( GetString( aRet, (const BYTE*)GetClass() ) );
+ return aRet;
+}
+
+// =======================================================================
+
+SimpleResMgr::SimpleResMgr( const sal_Char* pPrefixName,
+ LanguageType nType,
+ const UniString* pAppName,
+ const UniString* pResPath )
+{
+ // Suchreihenfolge festlegen
+ const sal_Char* pLang[5];
+
+ // Resourcefile suchen
+ UniString aName;
+ for ( int i = 0; i < 5; i++ )
+ {
+ pLang[i] = ResMgr::GetLang( nType, i );
+
+ if ( pLang[i] && (i == 0 || pLang[i] != pLang[0]) )
+ {
+ aName.AssignAscii( pPrefixName );
+ aName.AppendAscii( pLang[i] );
+ aName.AppendAscii( ".res" );
+ m_pResImpl = InternalResMgr::Create( aName, pAppName, pResPath );
+ if ( m_pResImpl )
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SimpleResMgr::~SimpleResMgr()
+{
+ delete m_pResImpl;
+}
+
+// -----------------------------------------------------------------------
+
+UniString SimpleResMgr::ReadString( USHORT nId )
+{
+ NAMESPACE_VOS(OGuard) aGuard(m_aAccessSafety);
+
+ DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadString : have no impl class !" );
+ // perhaps constructed with an invalid filename ?
+
+ UniString sReturn;
+ if ( !m_pResImpl )
+ return sReturn;
+
+ void* pResHandle = NULL;
+ RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
+ if ( !pResHeader )
+ // no such resource
+ return sReturn;
+
+ USHORT nLen = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
+ ResMgr::GetString( sReturn, (const BYTE*)(pResHeader+1) );
+
+ // not neccessary with te current implementation which holds the string table permanently, but to be sure ....
+ m_pResImpl->FreeGlobalRes( pResHeader, pResHandle );
+ return sReturn;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SimpleResMgr::ReadBlob( USHORT nId, void** pBuffer )
+{
+ NAMESPACE_VOS(OGuard) aGuard(m_aAccessSafety);
+
+ DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadBlob : have no impl class !" );
+
+ // perhaps constructed with an invalid filename ?
+ DBG_ASSERT( pBuffer, "SimpleResMgr::ReadBlob : invalid argument !" );
+ *pBuffer = NULL;
+
+ void* pResHandle = NULL;
+ RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_RESOURCE, nId, &pResHandle );
+ DBG_ASSERT( pResHeader, "SimpleResMgr::ReadBlob : couldn't find the resource with the given id !" );
+
+ // no exception handling, this would require the locking of the solar mutex which isn't allowed within this class
+ if ( !pResHeader )
+ return 0;
+
+ DBG_ASSERT( pResHandle == NULL, "SimpleResMgr::ReadBlob : behaviour of LoadGlobalRes changed !" );
+ // if pResHandle is not NULL the FreeBlob wouldn't have to delete the pointer given as pBuffer, but
+ // FreeBlob doesn't know that so it would probably crash ....
+
+ USHORT nRemaining = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
+ *pBuffer = (void*)(((BYTE*)pResHeader) + sizeof(RSHEADER_TYPE));
+ return nRemaining;
+}
+
+// -----------------------------------------------------------------------
+
+void SimpleResMgr::FreeBlob( void* pBuffer )
+{
+ void* pCompleteBuffer = (void*)(((BYTE*)pBuffer) - sizeof(RSHEADER_TYPE));
+ delete pCompleteBuffer;
+}
diff --git a/tools/source/ref/errinf.cxx b/tools/source/ref/errinf.cxx
new file mode 100644
index 000000000000..3db59910725c
--- /dev/null
+++ b/tools/source/ref/errinf.cxx
@@ -0,0 +1,443 @@
+/*************************************************************************
+ *
+ * $RCSfile: errinf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <limits.h>
+#include <shl.hxx>
+#include <debug.hxx>
+#include <errinf.hxx>
+#include <string.hxx>
+
+class ErrorHandler;
+
+struct EDcrData
+{
+ public:
+
+ ErrorHandler *pFirstHdl;
+ ErrorContext *pFirstCtx;
+ void *pDsp;
+ BOOL bIsWindowDsp;
+
+
+ DynamicErrorInfo *ppDcr[ERRCODE_DYNAMIC_COUNT];
+ USHORT nNextDcr;
+ EDcrData();
+
+static EDcrData *GetData();
+
+};
+
+class EDcr_Impl
+{
+ ULONG lErrId;
+ USHORT nMask;
+
+ void RegisterEDcr(DynamicErrorInfo *);
+ void UnRegisterEDcr(DynamicErrorInfo *);
+ static ErrorInfo *GetDynamicErrorInfo(ULONG lId);
+
+friend class DynamicErrorInfo;
+friend class ErrorInfo;
+};
+
+
+EDcrData::EDcrData()
+{
+ for(USHORT n=0;n<ERRCODE_DYNAMIC_COUNT;n++)
+ ppDcr[n]=0;
+ nNextDcr=0;
+ pFirstHdl=0;
+ pDsp=0;
+ pFirstCtx=0;
+}
+
+
+EDcrData *EDcrData::GetData()
+{
+#ifdef BOOTSTRAP
+ return 0x0;
+#else
+ EDcrData **ppDat=(EDcrData **)GetAppData(SHL_ERR);
+ if(!*ppDat)
+ {
+ return (*ppDat=new EDcrData);
+ }
+ else
+ return *ppDat;
+#endif
+}
+
+void EDcr_Impl::RegisterEDcr(DynamicErrorInfo *pDcr)
+{
+ //Vergibt eine dynamische Id
+
+ EDcrData* pData=EDcrData::GetData();
+ lErrId= (((ULONG)pData->nNextDcr + 1) << ERRCODE_DYNAMIC_SHIFT) +
+ pDcr->GetErrorCode();
+ DynamicErrorInfo **ppDcr=pData->ppDcr;
+ USHORT nNext=pData->nNextDcr;
+
+ // bei einem Ringbuffer koennen wir uns das ASSERT wohl sparen!
+ // DBG_ASSERT(ppDcr[nNext]==0,"ErrHdl: Alle Errors belegt");
+ if(ppDcr[nNext])
+ {
+ delete ppDcr[nNext];
+ }
+ ppDcr[nNext]=pDcr;
+ if(++pData->nNextDcr>=ERRCODE_DYNAMIC_COUNT)
+ pData->nNextDcr=0;
+}
+
+
+void EDcr_Impl::UnRegisterEDcr(DynamicErrorInfo *pDcr)
+{
+
+ EDcrData* pData=EDcrData::GetData();
+ DynamicErrorInfo **ppDcr=pData->ppDcr;
+ ULONG lIdx=(
+ ((ULONG)(*pDcr) & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
+ DBG_ASSERT(ppDcr[lIdx]==pDcr,"ErrHdl: Error nicht gefunden");
+ if(ppDcr[lIdx]==pDcr)
+ ppDcr[lIdx]=0;
+}
+
+TYPEINIT0(ErrorInfo);
+TYPEINIT1(DynamicErrorInfo, ErrorInfo);
+TYPEINIT1(StandardErrorInfo, DynamicErrorInfo);
+TYPEINIT1(StringErrorInfo, DynamicErrorInfo);
+TYPEINIT1(TwoStringErrorInfo, DynamicErrorInfo);
+TYPEINIT1(MessageInfo, DynamicErrorInfo);
+
+
+ErrorInfo *ErrorInfo::GetErrorInfo(ULONG lId)
+{
+ if(lId & ERRCODE_DYNAMIC_MASK)
+ return EDcr_Impl::GetDynamicErrorInfo(lId);
+ else
+ return new ErrorInfo(lId);
+}
+
+DynamicErrorInfo::operator ULONG() const
+{
+ return pImpl->lErrId;
+}
+
+DynamicErrorInfo::DynamicErrorInfo(ULONG lArgUserId, USHORT nMask)
+: ErrorInfo(lArgUserId)
+{
+ pImpl=new EDcr_Impl;
+ pImpl->RegisterEDcr(this);
+ pImpl->nMask=nMask;
+}
+
+DynamicErrorInfo::~DynamicErrorInfo()
+{
+ pImpl->UnRegisterEDcr(this);
+ delete pImpl;
+}
+
+ErrorInfo* EDcr_Impl::GetDynamicErrorInfo(ULONG lId)
+{
+ ULONG lIdx=((lId & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
+ DynamicErrorInfo* pDcr=EDcrData::GetData()->ppDcr[lIdx];
+ if(pDcr && (ULONG)(*pDcr)==lId)
+ return pDcr;
+ else
+ return new ErrorInfo(lId & ~ERRCODE_DYNAMIC_MASK);
+}
+
+
+USHORT DynamicErrorInfo::GetDialogMask() const
+{
+ return pImpl->nMask;
+}
+
+
+StandardErrorInfo::StandardErrorInfo(
+ ULONG lUserId, ULONG lArgExtId, USHORT nFlags)
+: DynamicErrorInfo(lUserId, nFlags), lExtId(lArgExtId)
+{
+}
+
+
+StringErrorInfo::StringErrorInfo(
+ ULONG lUserId, const String& aStringP, USHORT nFlags)
+: DynamicErrorInfo(lUserId, nFlags), aString(aStringP)
+{
+}
+
+
+class ErrHdl_Impl
+{
+ public:
+
+ ErrorHandler *pNext;
+ static BOOL CreateString(const ErrorHandler *pStart,
+ const ErrorInfo*, String&, USHORT&);
+};
+
+
+static void aDspFunc(const String &rErr, const String &rAction)
+{
+ ByteString aErr("Aktion: ");
+ aErr+= ByteString( rAction, RTL_TEXTENCODING_ASCII_US );
+ aErr+=" Fehler: ";
+ aErr+= ByteString( rErr, RTL_TEXTENCODING_ASCII_US );
+ DBG_ERROR(aErr.GetBuffer());
+}
+
+
+ErrorContext::ErrorContext(Window *pWinP)
+{
+ EDcrData *pData=EDcrData::GetData();
+ ErrorContext *&pHdl=pData->pFirstCtx;
+ pWin=pWinP;
+ pNext=pHdl;
+ pHdl=this;
+}
+
+ErrorContext::~ErrorContext()
+{
+ ErrorContext **ppCtx=&(EDcrData::GetData()->pFirstCtx);
+ while(*ppCtx && *ppCtx!=this)
+ ppCtx=&((*ppCtx)->pNext);
+ if(*ppCtx)
+ *ppCtx=(*ppCtx)->pNext;
+}
+
+ErrorContext *ErrorContext::GetContext()
+{
+ return EDcrData::GetData()->pFirstCtx;
+}
+
+ErrorHandler::ErrorHandler()
+{
+ pImpl=new ErrHdl_Impl;
+ EDcrData *pData=EDcrData::GetData();
+ ErrorHandler *&pHdl=pData->pFirstHdl;
+ pImpl->pNext=pHdl;
+ pHdl=this;
+ if(!pData->pDsp)
+ RegisterDisplay(&aDspFunc);
+}
+
+ErrorHandler::~ErrorHandler()
+{
+ ErrorHandler **ppHdl=&(EDcrData::GetData()->pFirstHdl);
+ while(*ppHdl && *ppHdl!=this)
+ ppHdl=&((*ppHdl)->pImpl->pNext);
+ if(*ppHdl)
+ *ppHdl=(*ppHdl)->pImpl->pNext;
+ delete pImpl;
+}
+
+void ErrorHandler::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
+{
+ EDcrData *pData=EDcrData::GetData();
+ pData->bIsWindowDsp=TRUE;
+ pData->pDsp=(void*)aDsp;
+}
+
+void ErrorHandler::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
+{
+ EDcrData *pData=EDcrData::GetData();
+ pData->bIsWindowDsp=FALSE;
+ pData->pDsp=(void*)aDsp;
+}
+
+USHORT ErrorHandler::HandleError(ULONG lId, USHORT nFlags)
+{
+
+/* [Beschreibung]
+ Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die
+ ErrorFlags. Werden nFlags nicht abgegeben, so werden die in
+ der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource
+ verwendet.
+
+ Also:
+
+ 1. nFlags,
+ 2. Resource Flags
+ 3. Dynamic Flags
+ 4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR
+
+
+ */
+
+ String aErr;
+ String aAction;
+ if(!lId || lId == ERRCODE_ABORT)
+ return 0;
+ EDcrData *pData=EDcrData::GetData();
+ ErrorInfo *pInfo=ErrorInfo::GetErrorInfo(lId);
+ ErrorContext *pCtx=ErrorContext::GetContext();
+ if(pCtx)
+ pCtx->GetString(pInfo->GetErrorCode(), aAction);
+ Window *pParent=0;
+ //Nimm den Parent aus dem Konext
+ for(;pCtx;pCtx=pCtx->pNext)
+ if(pCtx->GetParent())
+ {
+ pParent=pCtx->GetParent();
+ break;
+ }
+
+ USHORT nErrFlags = ERRCODE_BUTTON_DEF_OK | ERRCODE_BUTTON_OK |
+ ERRCODE_MSG_ERROR;
+
+ DynamicErrorInfo* pDynPtr=PTR_CAST(DynamicErrorInfo,pInfo);
+ if(pDynPtr)
+ {
+ USHORT nDynFlags = pDynPtr->GetDialogMask();
+ if( nDynFlags )
+ nErrFlags = nDynFlags;
+ }
+
+ if(ErrHdl_Impl::CreateString(pData->pFirstHdl,pInfo,aErr,nErrFlags))
+ {
+ delete pInfo;
+ if(!pData->pDsp)
+ {
+
+ ByteString aStr("Action: ");
+ aStr += ByteString( aAction, RTL_TEXTENCODING_ASCII_US );
+ aStr += ByteString("\nFehler: ");
+ aStr += ByteString( aErr, RTL_TEXTENCODING_ASCII_US );
+ DBG_ERROR( aStr.GetBuffer() );
+ }
+ else
+ if(!pData->bIsWindowDsp)
+ {
+ (*(BasicDisplayErrorFunc*)pData->pDsp)(aErr,aAction);
+ return 0;
+ }
+ else
+ {
+ if( nFlags != USHRT_MAX )
+ nErrFlags = nFlags;
+ return (*(WindowDisplayErrorFunc*)pData->pDsp)(
+ pParent, nErrFlags, aErr, aAction);
+ }
+ }
+
+ DBG_ERROR("Error nicht behandelt");
+ // Error 1 ist General Error im Sfx
+ if(pInfo->GetErrorCode()!=1)
+ HandleError(1, USHRT_MAX);
+ else
+ DBG_ERROR("Error 1 nicht gehandeled");
+ delete pInfo;
+ return 0;
+}
+
+BOOL ErrorHandler::ForwCreateString(const ErrorInfo* pInfo, String& rStr, USHORT &rFlags) const
+{
+ return ErrHdl_Impl::CreateString(this->pImpl->pNext, pInfo, rStr, rFlags);
+}
+
+BOOL ErrHdl_Impl::CreateString( const ErrorHandler *pStart,
+ const ErrorInfo* pInfo, String& pStr,
+ USHORT &rFlags)
+{
+ for(const ErrorHandler *pHdl=pStart;pHdl;pHdl=pHdl->pImpl->pNext)
+ {
+ if(pHdl->CreateString( pInfo, pStr, rFlags))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SimpleErrorHandler::CreateString(
+ const ErrorInfo *pInfo, String &rStr, USHORT &) const
+{
+ ULONG nId = pInfo->GetErrorCode();
+ ByteString aStr;
+ aStr="Id ";
+ aStr+=ByteString::CreateFromInt32(nId);
+ aStr+=" only handled by SimpleErrorHandler";
+ aStr+="\nErrorCode: ";
+ aStr+=ByteString::CreateFromInt32(nId & ((1L << ERRCODE_CLASS_SHIFT) - 1 ));
+ aStr+="\nErrorClass: ";
+ aStr+=ByteString::CreateFromInt32((nId & ERRCODE_CLASS_MASK) >> ERRCODE_CLASS_SHIFT);
+ aStr+="\nErrorArea: ";
+ aStr+=ByteString::CreateFromInt32((nId & ERRCODE_ERROR_MASK &
+ ~((1 << ERRCODE_AREA_SHIFT ) -1 ) ) >> ERRCODE_AREA_SHIFT);
+ DynamicErrorInfo *pDyn=PTR_CAST(DynamicErrorInfo,pInfo);
+ if(pDyn)
+ {
+ aStr+="\nDId ";
+ aStr+=ByteString::CreateFromInt32((ULONG)*pDyn);
+ }
+ StandardErrorInfo *pStd=PTR_CAST(StandardErrorInfo,pInfo);
+ if(pStd)
+ {
+ aStr+="\nXId ";
+ aStr+=ByteString::CreateFromInt32(pStd->GetExtendedErrorCode());
+ }
+ rStr = String( aStr, RTL_TEXTENCODING_ASCII_US );
+ return TRUE;
+}
+
+SimpleErrorHandler::SimpleErrorHandler()
+ : ErrorHandler()
+{
+}
+
diff --git a/tools/source/ref/globname.cxx b/tools/source/ref/globname.cxx
new file mode 100644
index 000000000000..f19c0e5fa805
--- /dev/null
+++ b/tools/source/ref/globname.cxx
@@ -0,0 +1,441 @@
+/*************************************************************************
+ *
+ * $RCSfile: globname.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <stream.hxx>
+#include <globname.hxx>
+
+#pragma hdrstop
+
+/************** class ImpSvGlobalName ************************************/
+ImpSvGlobalName::ImpSvGlobalName( const ImpSvGlobalName & rObj )
+{
+ nRefCount = 0;
+ memcpy( szData, rObj.szData, sizeof( szData ) );
+}
+
+/************** class ImpSvGlobalName ************************************/
+ImpSvGlobalName::ImpSvGlobalName( int )
+{
+ nRefCount = 1;
+ memset( szData, 0, sizeof( szData ) );
+}
+
+/*************************************************************************
+|* ImpSvGlobalName::operator ==()
+*************************************************************************/
+BOOL ImpSvGlobalName::operator == ( const ImpSvGlobalName & rObj ) const
+{
+ return !memcmp( szData, rObj.szData, sizeof( szData ) );
+}
+
+/*************************************************************************
+|* SvGlobalName::SvGlobalName()
+*************************************************************************/
+SvGlobalName::SvGlobalName()
+{
+ static ImpSvGlobalName aNoName( 0 );
+
+ pImp = &aNoName;
+ pImp->nRefCount++;
+}
+
+// locker die Struktur von Windows kopiert
+#ifdef WNT
+struct _GUID
+#else
+struct GUID
+#endif
+{
+ UINT32 Data1;
+ UINT16 Data2;
+ UINT16 Data3;
+ BYTE Data4[8];
+};
+SvGlobalName::SvGlobalName( const CLSID & rId )
+{
+ pImp = new ImpSvGlobalName();
+ pImp->nRefCount++;
+ memcpy( pImp->szData, &rId, sizeof( pImp->szData ) );
+}
+
+SvGlobalName::SvGlobalName( UINT32 n1, USHORT n2, USHORT n3,
+ BYTE b8, BYTE b9, BYTE b10, BYTE b11,
+ BYTE b12, BYTE b13, BYTE b14, BYTE b15 )
+{
+ pImp = new ImpSvGlobalName();
+ pImp->nRefCount++;
+
+ *(UINT32 *)pImp->szData = n1;
+ *(USHORT *)&pImp->szData[ 4 ] = n2;
+ *(USHORT *)&pImp->szData[ 6 ] = n3;
+ pImp->szData[ 8 ] = b8;
+ pImp->szData[ 9 ] = b9;
+ pImp->szData[ 10 ] = b10;
+ pImp->szData[ 11 ] = b11;
+ pImp->szData[ 12 ] = b12;
+ pImp->szData[ 13 ] = b13;
+ pImp->szData[ 14 ] = b14;
+ pImp->szData[ 15 ] = b15;
+}
+
+/*************************************************************************
+|* SvGlobalName::~SvGlobalName()
+*************************************************************************/
+SvGlobalName::~SvGlobalName()
+{
+ pImp->nRefCount--;
+ if( !pImp->nRefCount )
+ delete pImp;
+}
+
+/*************************************************************************
+|* SvGlobalName::operator = ()
+*************************************************************************/
+SvGlobalName & SvGlobalName::operator = ( const SvGlobalName & rObj )
+{
+ rObj.pImp->nRefCount++;
+ pImp->nRefCount--;
+ if( !pImp->nRefCount )
+ delete pImp;
+ pImp = rObj.pImp;
+ return *this;
+}
+
+/*************************************************************************
+|* SvGlobalName::NewImp()
+*************************************************************************/
+void SvGlobalName::NewImp()
+{
+ if( pImp->nRefCount > 1 )
+ {
+ pImp->nRefCount--;
+ pImp = new ImpSvGlobalName( *pImp );
+ pImp->nRefCount++;
+ }
+}
+
+/*************************************************************************
+|* SvGlobalName::operator << ()
+|* SvGlobalName::operator >> ()
+*************************************************************************/
+SvStream& operator << ( SvStream& rOStr, const SvGlobalName & rObj )
+{
+ rOStr << *(UINT32 *)rObj.pImp->szData;
+ rOStr << *(USHORT *)&rObj.pImp->szData[ 4 ];
+ rOStr << *(USHORT *)&rObj.pImp->szData[ 6 ];
+ rOStr.Write( (sal_Char *)&rObj.pImp->szData[ 8 ], 8 );
+ return rOStr;
+}
+
+SvStream& operator >> ( SvStream& rStr, SvGlobalName & rObj )
+{
+ rObj.NewImp(); // kopieren, falls noetig
+ rStr >> *(UINT32 *)rObj.pImp->szData;
+ rStr >> *(USHORT *)&rObj.pImp->szData[ 4 ];
+ rStr >> *(USHORT *)&rObj.pImp->szData[ 6 ];
+ rStr.Read( (sal_Char *)&rObj.pImp->szData[ 8 ], 8 );
+ return rStr;
+}
+
+
+/*************************************************************************
+|* SvGlobalName::operator < ()
+*************************************************************************/
+BOOL SvGlobalName::operator < ( const SvGlobalName & rObj ) const
+{
+ int n = memcmp( pImp->szData +6, rObj.pImp->szData +6,
+ sizeof( pImp->szData ) -6);
+ if( n < 0 )
+ return TRUE;
+ else if( n > 0 )
+ return FALSE;
+ else if( *(USHORT *)&pImp->szData[ 4 ] < *(USHORT *)&rObj.pImp->szData[ 4 ] )
+ return TRUE;
+ else if( *(USHORT *)&pImp->szData[ 4 ] == *(USHORT *)&rObj.pImp->szData[ 4 ] )
+ return *(UINT32 *)pImp->szData < *(UINT32 *)rObj.pImp->szData;
+ else
+ return FALSE;
+
+}
+
+/*************************************************************************
+|* SvGlobalName::operator +=()
+*************************************************************************/
+SvGlobalName & SvGlobalName::operator += ( UINT32 n )
+{
+ NewImp();
+ UINT32 nOld = (*(UINT32 *)pImp->szData);
+ (*(UINT32 *)pImp->szData) += n;
+ if( nOld > *(UINT32 *)pImp->szData )
+ // ueberlauf
+ (*(USHORT *)&pImp->szData[ 4 ])++;
+ return *this;
+}
+
+/*************************************************************************
+|* SvGlobalName::operator ==()
+*************************************************************************/
+BOOL SvGlobalName::operator == ( const SvGlobalName & rObj ) const
+{
+ return *pImp == *rObj.pImp;
+}
+
+void SvGlobalName::MakeFromMemory( void * pData )
+{
+ NewImp();
+ memcpy( pImp->szData, pData, sizeof( pImp->szData ) );
+}
+
+/*************************************************************************
+|* SvGlobalName::MakeId()
+*************************************************************************/
+BOOL SvGlobalName::MakeId( const String & rIdStr )
+{
+ ByteString aStr( rIdStr, RTL_TEXTENCODING_ASCII_US );
+ sal_Char * pStr = (sal_Char *)aStr.GetBuffer();
+ if( rIdStr.Len() == 36
+ && '-' == pStr[ 8 ] && '-' == pStr[ 13 ]
+ && '-' == pStr[ 18 ] && '-' == pStr[ 23 ] )
+ {
+ UINT32 nFirst = 0;
+ int i = 0;
+ for( i = 0; i < 8; i++ )
+ {
+ if( isxdigit( *pStr ) )
+ if( isdigit( *pStr ) )
+ nFirst = nFirst * 16 + (*pStr - '0');
+ else
+ nFirst = nFirst * 16 + (toupper( *pStr ) - 'A' + 10 );
+ else
+ return FALSE;
+ pStr++;
+ }
+
+ UINT16 nSec = 0;
+ pStr++;
+ for( i = 0; i < 4; i++ )
+ {
+ if( isxdigit( *pStr ) )
+ if( isdigit( *pStr ) )
+ nSec = nSec * 16 + (*pStr - '0');
+ else
+ nSec = nSec * 16 + (toupper( *pStr ) - 'A' + 10 );
+ else
+ return FALSE;
+ pStr++;
+ }
+
+ UINT16 nThird = 0;
+ pStr++;
+ for( i = 0; i < 4; i++ )
+ {
+ if( isxdigit( *pStr ) )
+ if( isdigit( *pStr ) )
+ nThird = nThird * 16 + (*pStr - '0');
+ else
+ nThird = nThird * 16 + (toupper( *pStr ) - 'A' + 10 );
+ else
+ return FALSE;
+ pStr++;
+ }
+
+ BYTE szRemain[ 8 ];
+ memset( szRemain, 0, sizeof( szRemain ) );
+ pStr++;
+ for( i = 0; i < 16; i++ )
+ {
+ if( isxdigit( *pStr ) )
+ if( isdigit( *pStr ) )
+ szRemain[i/2] = szRemain[i/2] * 16 + (*pStr - '0');
+ else
+ szRemain[i/2] = szRemain[i/2] * 16 + (toupper( *pStr ) - 'A' + 10 );
+ else
+ return FALSE;
+ pStr++;
+ if( i == 3 )
+ pStr++;
+ }
+
+ NewImp();
+ *(UINT32 *)pImp->szData = nFirst;
+ *(USHORT *)&pImp->szData[ 4 ] = nSec;
+ *(USHORT *)&pImp->szData[ 6 ] = nThird;
+ memcpy( &pImp->szData[ 8 ], szRemain, 8 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|* SvGlobalName::GetctorName()
+*************************************************************************/
+String SvGlobalName::GetctorName() const
+{
+ ByteString aRet;
+
+ sal_Char buf[ 20 ];
+ sprintf( buf, "0x%8.8lX", (ULONG)*(UINT32 *)pImp->szData );
+ aRet += buf;
+ USHORT i;
+ for( i = 4; i < 8; i += 2 )
+ {
+ aRet += ',';
+ sprintf( buf, "0x%4.4X", *(USHORT *)&pImp->szData[ i ] );
+ aRet += buf;
+ }
+ for( i = 8; i < 16; i++ )
+ {
+ aRet += ',';
+ sprintf( buf, "0x%2.2x", pImp->szData[ i ] );
+ aRet += buf;
+ }
+ return String( aRet, RTL_TEXTENCODING_ASCII_US );
+}
+
+/*************************************************************************
+|* SvGlobalName::GetHexName()
+*************************************************************************/
+String SvGlobalName::GetHexName() const
+{
+ ByteString aRet;
+
+ sal_Char buf[ 10 ];
+ sprintf( buf, "%8.8lX", (ULONG)*(UINT32 *)pImp->szData );
+ aRet += buf;
+ aRet += '-';
+ USHORT i ;
+ for( i = 4; i < 8; i += 2 )
+ {
+ sprintf( buf, "%4.4X", *(USHORT *)&pImp->szData[ i ] );
+ aRet += buf;
+ aRet += '-';
+ }
+ for( i = 8; i < 10; i++ )
+ {
+ sprintf( buf, "%2.2x", pImp->szData[ i ] );
+ aRet += buf;
+ }
+ aRet += '-';
+ for( i = 10; i < 16; i++ )
+ {
+ sprintf( buf, "%2.2x", pImp->szData[ i ] );
+ aRet += buf;
+ }
+ return String( aRet, RTL_TEXTENCODING_ASCII_US );
+}
+
+/************** SvGlobalNameList ****************************************/
+/************************************************************************/
+/*************************************************************************
+|* SvGlobalNameList::SvGlobalNameList()
+*************************************************************************/
+SvGlobalNameList::SvGlobalNameList()
+ : aList( 1, 1 )
+{
+}
+
+/*************************************************************************
+|* SvGlobalNameList::~SvGlobalNameList()
+*************************************************************************/
+SvGlobalNameList::~SvGlobalNameList()
+{
+ for( ULONG i = Count(); i > 0; i-- )
+ {
+ ImpSvGlobalName * pImp = (ImpSvGlobalName *)aList.GetObject( i -1 );
+ pImp->nRefCount--;
+ if( !pImp->nRefCount )
+ delete pImp;
+ }
+}
+
+/*************************************************************************
+|* SvGlobalNameList::Append()
+*************************************************************************/
+void SvGlobalNameList::Append( const SvGlobalName & rName )
+{
+ rName.pImp->nRefCount++;
+ aList.Insert( rName.pImp, LIST_APPEND );
+}
+
+/*************************************************************************
+|* SvGlobalNameList::GetObject()
+*************************************************************************/
+SvGlobalName SvGlobalNameList::GetObject( ULONG nPos )
+{
+ return SvGlobalName( (ImpSvGlobalName *)aList.GetObject( nPos ) );
+}
+
+/*************************************************************************
+|* SvGlobalNameList::IsEntry()
+*************************************************************************/
+BOOL SvGlobalNameList::IsEntry( const SvGlobalName & rName )
+{
+ for( ULONG i = Count(); i > 0; i-- )
+ {
+ if( *rName.pImp == *(ImpSvGlobalName *)aList.GetObject( i -1 ) )
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/tools/source/ref/makefile.mk b/tools/source/ref/makefile.mk
new file mode 100644
index 000000000000..ad85f0accd62
--- /dev/null
+++ b/tools/source/ref/makefile.mk
@@ -0,0 +1,90 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=ref
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/ref.obj \
+ $(SLO)$/pstm.obj \
+ $(SLO)$/globname.obj \
+ $(SLO)$/errinf.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/ref.obj \
+ $(OBJ)$/pstm.obj \
+ $(OBJ)$/globname.obj \
+ $(OBJ)$/errinf.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/ref/pstm.cxx b/tools/source/ref/pstm.cxx
new file mode 100644
index 000000000000..93ba671a2da1
--- /dev/null
+++ b/tools/source/ref/pstm.cxx
@@ -0,0 +1,945 @@
+/*************************************************************************
+ *
+ * $RCSfile: pstm.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <debug.hxx>
+#include <pstm.hxx>
+
+#pragma hdrstop
+
+#define STOR_NO_OPTIMIZE
+
+/***********************************************************************/
+/************************************************************************
+|* SvClassManager::Register()
+*************************************************************************/
+void SvClassManager::Register( USHORT nClassId, SvCreateInstancePersist pFunc )
+{
+#ifdef DBG_UTIL
+ SvCreateInstancePersist p;
+ p = (SvCreateInstancePersist)aAssocTable.Get( nClassId );
+ DBG_ASSERT( !p || p == pFunc, "register class with same id" )
+#endif
+ aAssocTable.Insert( nClassId, (void *)pFunc );
+}
+
+/************************************************************************
+|* SvClassManager::Get()
+*************************************************************************/
+SvCreateInstancePersist SvClassManager::Get( USHORT nClassId )
+{
+ return (SvCreateInstancePersist)aAssocTable.Get( nClassId );
+}
+
+/****************** SvRttiBase *******************************************/
+TYPEINIT0( SvRttiBase );
+
+/****************** SvPersistBaseMemberList ******************************/
+#define inline
+SV_IMPL_REF_LIST(SuperSvPersistBase,SuperSvPersistBase*)
+#undef inline
+
+#define PERSIST_LIST_VER (BYTE)0
+#define PERSIST_LIST_DBGUTIL (BYTE)0x80
+
+/************************************************************************
+|* SvPersistBaseMemberList::WriteOnlyStreamedObjects()
+*************************************************************************/
+void SvPersistBaseMemberList::WriteObjects( SvPersistStream & rStm,
+ BOOL bOnlyStreamed ) const
+{
+#ifdef STOR_NO_OPTIMIZE
+ rStm << (BYTE)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL);
+ UINT32 nObjPos = rStm.WriteDummyLen();
+#else
+ BYTE bTmp = PERSIST_LIST_VER;
+ rStm << bTmp;
+#endif
+ UINT32 nCount = Count();
+ ULONG nCountPos = rStm.Tell();
+ UINT32 nWriteCount = 0;
+ rStm << nCount;
+ //bloss die Liste nicht veraendern,
+ //wegen Seiteneffekten beim Save
+ for( ULONG n = 0; n < nCount; n++ )
+ {
+ SvPersistBase * pObj = GetObject( n );
+ if( !bOnlyStreamed || rStm.IsStreamed( pObj ) )
+ { // Objekt soll geschrieben werden
+ rStm << GetObject( n );
+ nWriteCount++;
+ }
+ }
+ if( nWriteCount != nCount )
+ {
+ // nicht alle Objekte geschrieben, Count anpassen
+ ULONG nPos = rStm.Tell();
+ rStm.Seek( nCountPos );
+ rStm << nWriteCount;
+ rStm.Seek( nPos );
+ }
+#ifdef STOR_NO_OPTIMIZE
+ rStm.WriteLen( nObjPos );
+#endif
+}
+
+/************************************************************************
+|* operator << ()
+*************************************************************************/
+SvPersistStream& operator << ( SvPersistStream & rStm,
+ const SvPersistBaseMemberList & rLst )
+{
+ rLst.WriteObjects( rStm );
+ return rStm;
+}
+
+/************************************************************************
+|* operator >> ()
+*************************************************************************/
+SvPersistStream& operator >> ( SvPersistStream & rStm,
+ SvPersistBaseMemberList & rLst )
+{
+ BYTE nVer;
+ rStm >> nVer;
+
+ if( (nVer & ~PERSIST_LIST_DBGUTIL) != PERSIST_LIST_VER )
+ {
+ rStm.SetError( SVSTREAM_GENERALERROR );
+ DBG_ERROR( "persist list, false version" )
+ }
+
+ UINT32 nObjLen, nObjPos;
+ if( nVer & PERSIST_LIST_DBGUTIL )
+ nObjLen = rStm.ReadLen( &nObjPos );
+
+ ULONG nCount;
+ rStm >> nCount;
+ for( ULONG n = 0; n < nCount && rStm.GetError() == SVSTREAM_OK; n++ )
+ {
+ SvPersistBase * pObj;
+ rStm >> pObj;
+ if( pObj )
+ rLst.Append( pObj );
+ }
+#ifdef DBG_UTIL
+ if( nObjLen + nObjPos != rStm.Tell() )
+ {
+ ByteString aStr( "false list len: read = " );
+ aStr += ByteString::CreateFromInt32( (long)(rStm.Tell() - nObjPos) );
+ aStr += ", should = ";
+ aStr += nObjLen;
+ DBG_ERROR( aStr.GetBuffer() )
+ }
+#endif
+ return rStm;
+}
+
+//=========================================================================
+SvPersistStream::SvPersistStream
+(
+ SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und
+ gespeichert werdn k"onnen */
+ SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf
+ dem der PersistStream arbeitet */
+ UINT32 nStartIdxP /* Ab diesem Index werden die Id's f"ur
+ die Objekte vergeben, er muss gr"osser
+ als Null sein. */
+)
+ : rClassMgr( rMgr )
+ , pStm( pStream )
+ , aPUIdx( nStartIdxP )
+ , nStartIdx( nStartIdxP )
+ , pRefStm( NULL )
+ , nFlags( 0 )
+/* [Beschreibung]
+
+ Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und
+ pStream d"urfen nicht ver"andert werden, solange sie in einem
+ SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur
+ pStream (siehe <SvPersistStream::SetStream>).
+*/
+{
+ DBG_ASSERT( nStartIdx != 0, "zero index not allowed" )
+ bIsWritable = TRUE;
+ if( pStm )
+ {
+ SetVersion( pStm->GetVersion() );
+ SetError( pStm->GetError() );
+ SyncSvStream( pStm->Tell() );
+ }
+}
+
+//=========================================================================
+SvPersistStream::SvPersistStream
+(
+ SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und
+ gespeichert werdn k"onnen */
+ SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf
+ dem der PersistStream arbeitet */
+ const SvPersistStream & rPersStm
+ /* Wenn PersistStream's verschachtelt werden,
+ dann ist dies der Parent-Stream. */
+)
+ : rClassMgr( rMgr )
+ , pStm( pStream )
+ // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe
+ , aPUIdx( rPersStm.GetCurMaxIndex() +1 )
+ , nStartIdx( rPersStm.GetCurMaxIndex() +1 )
+ , pRefStm( &rPersStm )
+ , nFlags( 0 )
+/* [Beschreibung]
+
+ Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und
+ pStream d"urfen nicht ver"andert werden, solange sie in einem
+ SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur
+ pStream (siehe <SvPersistStream::SetStream>).
+ Durch diesen Konstruktor wird eine Hierarchiebildung unterst"utzt.
+ Alle Objekte aus einer Hierarchie m"ussen erst geladen werden,
+ wenn das erste aus dieser Hierarchie benutzt werden soll.
+*/
+{
+ bIsWritable = TRUE;
+ if( pStm )
+ {
+ SetVersion( pStm->GetVersion() );
+ SetError( pStm->GetError() );
+ SyncSvStream( pStm->Tell() );
+ }
+}
+
+//=========================================================================
+SvPersistStream::~SvPersistStream()
+/* [Beschreibung]
+
+ Der Detruktor ruft die Methode <SvPersistStream::SetStream>
+ mit NULL.
+*/
+{
+ SetStream( NULL );
+}
+
+//=========================================================================
+void SvPersistStream::SetStream
+(
+ SvStream * pStream /* auf diesem Stream arbeitet der PersistStream */
+
+)
+/* [Beschreibung]
+
+ Es wird ein Medium (pStream) eingesetzt, auf dem PersistStream arbeitet.
+ Dieses darf nicht von aussen modifiziert werden, solange es
+ eingesetzt ist. Es sei denn, w"ahrend auf dem Medium gearbeitet
+ wird, wird keine Methode von SvPersistStream gerufen, bevor
+ nicht <SvPersistStream::SetStream> mit demselben Medium gerufen
+ wurde.
+*/
+{
+ if( pStm != pStream )
+ {
+ if( pStm )
+ {
+ SyncSysStream();
+ pStm->SetError( GetError() );
+ }
+ pStm = pStream;
+ }
+ if( pStm )
+ {
+ SetVersion( pStm->GetVersion() );
+ SetError( pStm->GetError() );
+ SyncSvStream( pStm->Tell() );
+ }
+}
+
+//=========================================================================
+USHORT SvPersistStream::IsA() const
+/* [Beschreibung]
+
+ Gibt den Identifier dieses Streamklasse zur"uck.
+
+ [R"uckgabewert]
+
+ USHORT ID_PERSISTSTREAM wird zur"uckgegeben.
+
+
+ [Querverweise]
+
+ <SvStream::IsA>
+*/
+{
+ return ID_PERSISTSTREAM;
+}
+
+
+/*************************************************************************
+|* SvPersistStream::ResetError()
+*************************************************************************/
+void SvPersistStream::ResetError()
+{
+ SvStream::ResetError();
+ DBG_ASSERT( pStm, "stream not set" )
+ pStm->ResetError();
+}
+
+/*************************************************************************
+|* SvPersistStream::GetData()
+*************************************************************************/
+ULONG SvPersistStream::GetData( void* pData, ULONG nSize )
+{
+ DBG_ASSERT( pStm, "stream not set" )
+ ULONG nRet = pStm->Read( pData, nSize );
+ SetError( pStm->GetError() );
+ return nRet;
+}
+
+/*************************************************************************
+|* SvPersistStream::PutData()
+*************************************************************************/
+ULONG SvPersistStream::PutData( const void* pData, ULONG nSize )
+{
+ DBG_ASSERT( pStm, "stream not set" )
+ ULONG nRet = pStm->Write( pData, nSize );
+ SetError( pStm->GetError() );
+ return nRet;
+}
+
+/*************************************************************************
+|* SvPersistStream::Seek()
+*************************************************************************/
+ULONG SvPersistStream::SeekPos( ULONG nPos )
+{
+ DBG_ASSERT( pStm, "stream not set" )
+ ULONG nRet = pStm->Seek( nPos );
+ SetError( pStm->GetError() );
+ return nRet;
+}
+
+/*************************************************************************
+|* SvPersistStream::FlushData()
+*************************************************************************/
+void SvPersistStream::FlushData()
+{
+}
+
+/*************************************************************************
+|* SvPersistStream::GetCurMaxIndex()
+*************************************************************************/
+ULONG SvPersistStream::GetCurMaxIndex( const SvPersistUIdx & rIdx ) const
+{
+ // const bekomme ich nicht den hoechsten Index
+ SvPersistUIdx * p = (SvPersistUIdx *)&rIdx;
+ // alten merken
+ ULONG nCurIdx = p->GetCurIndex();
+ p->Last();
+ // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe
+ ULONG nMaxIdx = p->GetCurIndex();
+ // wieder herstellen
+ p->Seek( nCurIdx );
+ return nMaxIdx;
+}
+
+/*************************************************************************
+|* SvPersistStream::GetIndex()
+*************************************************************************/
+ULONG SvPersistStream::GetIndex( SvPersistBase * pObj ) const
+{
+ ULONG nId = (ULONG)aPTable.Get( (ULONG)pObj );
+ if( !nId && pRefStm )
+ return pRefStm->GetIndex( pObj );
+ return nId;
+}
+
+/*************************************************************************
+|* SvPersistStream::GetObject)
+*************************************************************************/
+SvPersistBase * SvPersistStream::GetObject( ULONG nIdx ) const
+{
+ if( nIdx >= nStartIdx )
+ return aPUIdx.Get( nIdx );
+ else if( pRefStm )
+ return pRefStm->GetObject( nIdx );
+ return NULL;
+}
+
+//=========================================================================
+#define LEN_1 0x80
+#define LEN_2 0x40
+#define LEN_4 0x20
+#define LEN_5 0x10
+UINT32 SvPersistStream::ReadCompressed
+(
+ SvStream & rStm /* Aus diesem Stream werden die komprimierten Daten
+ gelesen */
+)
+/* [Beschreibung]
+
+ Ein im Stream komprimiert abgelegtes Wort wird gelesen. In welchem
+ Format komprimiert wird, siehe <SvPersistStream::WriteCompressed>.
+
+ [R"uckgabewert]
+
+ UINT32 Das nicht komprimierte Wort wird zur"uckgegeben.
+
+ [Querverweise]
+
+*/
+{
+ UINT32 nRet;
+ BYTE nMask;
+ rStm >> nMask;
+ if( nMask & LEN_1 )
+ nRet = ~LEN_1 & nMask;
+ else if( nMask & LEN_2 )
+ {
+ nRet = ~LEN_2 & nMask;
+ nRet <<= 8;
+ rStm >> nMask;
+ nRet |= nMask;
+ }
+ else if( nMask & LEN_4 )
+ {
+ nRet = ~LEN_4 & nMask;
+ nRet <<= 8;
+ rStm >> nMask;
+ nRet |= nMask;
+ nRet <<= 16;
+ USHORT n;
+ rStm >> n;
+ nRet |= n;
+ }
+ else if( nMask & LEN_5 )
+ {
+ if( nMask & 0x0F )
+ {
+ rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ DBG_ERROR( "format error" )
+ }
+ rStm >> nRet;
+ }
+ else
+ {
+ rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ DBG_ERROR( "format error" )
+ }
+ return nRet;
+}
+
+//=========================================================================
+void SvPersistStream::WriteCompressed
+(
+ SvStream & rStm,/* Aus diesem Stream werden die komprimierten Daten
+ gelesen */
+ UINT32 nVal /* Dieser Wert wird komprimiert geschrieben */
+)
+/* [Beschreibung]
+
+ Das "ubergebene Wort wird komprimiert und in den Stream
+ geschrieben. Folgendermassen wir komprimiert.
+ nVal < 0x80 => 0x80 + nVal ist 1 Byte gross.
+ nVal < 0x4000 => 0x4000 + nVal ist 2 Byte gross.
+ nVal < 0x20000000 => 0x20000000 + nVal ist 4 Byte gross.
+ nVal > 0x1FFFFFFF => 0x1000000000+ nVal ist 5 Byte gross.
+
+ [Querverweise]
+
+ <SvPersistStream::ReadCompressed>
+*/
+{
+#ifdef STOR_NO_OPTIMIZE
+ if( nVal < 0x80 )
+ rStm << (BYTE)(LEN_1 | nVal);
+ else if( nVal < 0x4000 )
+ {
+ rStm << (BYTE)(LEN_2 | (nVal >> 8));
+ rStm << (BYTE)nVal;
+ }
+ else if( nVal < 0x20000000 )
+ {
+ // hoechstes BYTE
+ rStm << (BYTE)(LEN_4 | (nVal >> 24));
+ // 2. hoechstes BYTE
+ rStm << (BYTE)(nVal >> 16);
+ rStm << (USHORT)(nVal);
+ }
+ else
+#endif
+ {
+ rStm << (BYTE)LEN_5;
+ rStm << nVal;
+ }
+}
+
+//=========================================================================
+UINT32 SvPersistStream::WriteDummyLen()
+/* [Beschreibung]
+
+ Die Methode schreibt 4 Byte in den Stream und gibt die Streamposition
+ zur"uck.
+
+ [R"uckgabewert]
+
+ UINT32 Die Position hinter der L"angenangabe wird zur"uckgegeben.
+
+ [Beispiel]
+
+ UINT32 nObjPos = rStm.WriteDummyLen();
+ ...
+ // Daten schreiben
+ ...
+ rStm.WriteLen( nObjPos );
+
+ [Querverweise]
+
+ <SvPersistStream::ReadLen>, <SvPersistStream::WriteLen>
+
+*/
+{
+#ifdef DBG_UTIL
+ UINT32 nPos = Tell();
+#endif
+ UINT32 n0 = 0;
+ *this << n0; // wegen Sun sp
+ // keine Assertion bei Streamfehler
+ DBG_ASSERT( GetError() != SVSTREAM_OK
+ || (sizeof( UINT32 ) == Tell() -nPos),
+ "keine 4-Byte fuer Langenangabe" );
+ return Tell();
+}
+
+//=========================================================================
+void SvPersistStream::WriteLen
+(
+ UINT32 nObjPos /* die Position + 4, an der die L"ange geschrieben
+ wird. */
+)
+/* [Beschreibung]
+
+ Die Methode schreibt die Differenz zwischen der aktuellen und
+ nObjPos als UINT32 an die Position nObjPos -4 im Stream. Danach
+ wird der Stream wieder auf die alte Position gestellt.
+
+ [Beispiel]
+
+ Die Differenz enth"alt nicht die L"angenangabe.
+
+ UINT32 nObjPos = rStm.WriteDummyLen();
+ ...
+ // Daten schreiben
+ ...
+ rStm.WriteLen( nObjPos );
+ // weitere Daten schreiben
+
+ [Querverweise]
+
+ <SvPersistStream::ReadLen>, <SvPersistStream::WriteDummyLen>
+*/
+{
+ UINT32 nPos = Tell();
+ UINT32 nLen = nPos - nObjPos;
+ // die Laenge muá im stream 4-Byte betragen
+ Seek( nObjPos - sizeof( UINT32 ) );
+ // Laenge schreiben
+ *this << nLen;
+ Seek( nPos );
+}
+
+//=========================================================================
+UINT32 SvPersistStream::ReadLen
+(
+ UINT32 * pTestPos /* Die Position des Streams, nach dem Lesen der
+ L"ange, wird zur"uckgegeben. Es darf auch NULL
+ "ubergeben werden. */
+)
+/* [Beschreibung]
+
+ Liest die L"ange die vorher mit <SvPersistStream::WriteDummyLen>
+ und <SvPersistStream::WriteLen> geschrieben wurde.
+*/
+{
+ UINT32 nLen;
+ *this >> nLen;
+ if( pTestPos )
+ *pTestPos = Tell();
+ return nLen;
+}
+
+//=========================================================================
+// Dateirormat abw"arts kompatibel
+#ifdef STOR_NO_OPTIMIZE
+#define P_VER (BYTE)0x00
+#else
+#define P_VER (BYTE)0x01
+#endif
+#define P_VER_MASK (BYTE)0x0F
+#define P_ID_0 (BYTE)0x80
+#define P_OBJ (BYTE)0x40
+#define P_DBGUTIL (BYTE)0x20
+#define P_ID (BYTE)0x10
+#ifdef STOR_NO_OPTIMIZE
+#define P_STD P_DBGUTIL
+#else
+#define P_STD 0
+#endif
+
+static void WriteId
+(
+ SvStream & rStm,
+ BYTE nHdr,
+ UINT32 nId,
+ USHORT nClassId
+)
+{
+#ifdef STOR_NO_OPTIMIZE
+ nHdr |= P_ID;
+#endif
+ nHdr |= P_VER;
+ if( nHdr & P_ID )
+ {
+ if( (nHdr & P_OBJ) || nId != 0 )
+ { // Id nur bei Zeiger, oder DBGUTIL
+ rStm << (BYTE)(nHdr);
+ SvPersistStream::WriteCompressed( rStm, nId );
+ }
+ else
+ { // NULL Pointer
+ rStm << (BYTE)(nHdr | P_ID_0);
+ return;
+ }
+ }
+ else
+ rStm << nHdr;
+
+ if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
+ // Objekte haben immer eine Klasse,
+ // Pointer nur bei DBG_UTIL und != NULL
+ SvPersistStream::WriteCompressed( rStm, nClassId );
+}
+
+//=========================================================================
+static void ReadId
+(
+ SvStream & rStm,
+ BYTE & nHdr,
+ UINT32 & nId,
+ USHORT & nClassId
+)
+{
+ nClassId = 0;
+ rStm >> nHdr;
+ if( nHdr & P_ID_0 )
+ nId = 0;
+ else
+ {
+ if( (nHdr & P_VER_MASK) == 0 )
+ {
+ if( (nHdr & P_DBGUTIL) || !(nHdr & P_OBJ) )
+ nId = SvPersistStream::ReadCompressed( rStm );
+ else
+ nId = 0;
+ }
+ else if( nHdr & P_ID )
+ nId = SvPersistStream::ReadCompressed( rStm );
+
+ if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
+ nClassId = (USHORT)SvPersistStream::ReadCompressed( rStm );
+ }
+}
+
+//=========================================================================
+void SvPersistStream::WriteObj
+(
+ BYTE nHdr,
+ SvPersistBase * pObj
+)
+{
+#ifdef STOR_NO_OPTIMIZE
+ UINT32 nObjPos;
+ if( nHdr & P_DBGUTIL )
+ // Position fuer Laenge merken
+ nObjPos = WriteDummyLen();
+#endif
+ pObj->Save( *this );
+#ifdef STOR_NO_OPTIMIZE
+ if( nHdr & P_DBGUTIL )
+ WriteLen( nObjPos );
+#endif
+}
+
+//=========================================================================
+SvPersistStream& SvPersistStream::WritePointer
+(
+ SvPersistBase * pObj
+)
+{
+ BYTE nP = P_STD;
+
+ if( pObj )
+ {
+ ULONG nId = GetIndex( pObj );
+ if( nId )
+ nP |= P_ID;
+ else
+ {
+ nId = aPUIdx.Insert( pObj );
+ aPTable.Insert( (ULONG)pObj, (void *)nId );
+ nP |= P_OBJ;
+ }
+ WriteId( *this, nP, nId, pObj->GetClassId() );
+ if( nP & P_OBJ )
+ WriteObj( nP, pObj );
+ }
+ else
+ { // NULL Pointer
+ WriteId( *this, nP | P_ID, 0, 0 );
+ }
+ return *this;
+}
+
+//=========================================================================
+UINT32 SvPersistStream::ReadObj
+(
+ SvPersistBase * & rpObj,
+ BOOL bRegister
+)
+{
+ BYTE nHdr;
+ UINT32 nId = 0;
+ USHORT nClassId;
+
+ rpObj = NULL; // Spezifikation: Im Fehlerfall 0.
+ ReadId( *this, nHdr, nId, nClassId );
+
+ // reine Versionsnummer durch maskieren
+ if( P_VER < (nHdr & P_VER_MASK) )
+ {
+ SetError( SVSTREAM_FILEFORMAT_ERROR );
+ DBG_ERROR( "false version" )
+ }
+
+ if( !(nHdr & P_ID_0) && GetError() == SVSTREAM_OK )
+ {
+ if( P_OBJ & nHdr )
+ { // read object, nId nur bei P_DBGUTIL gesetzt
+ DBG_ASSERT( !(nHdr & P_DBGUTIL) || NULL == aPUIdx.Get( nId ),
+ "object already exist" )
+ SvCreateInstancePersist pFunc = rClassMgr.Get( nClassId );
+
+ UINT32 nObjLen, nObjPos;
+ if( nHdr & P_DBGUTIL )
+ nObjLen = ReadLen( &nObjPos );
+ if( !pFunc )
+ {
+#ifdef DBG_UTIL
+ ByteString aStr( "no class with id: " );
+ aStr += ByteString::CreateFromInt32( nClassId );
+ aStr += " registered";
+ DBG_WARNING( aStr.GetBuffer() );
+#endif
+ SetError( ERRCODE_IO_NOFACTORY );
+ return 0;
+ }
+ pFunc( &rpObj );
+ // Sichern
+ rpObj->AddRef();
+
+ if( bRegister )
+ {
+ // unbedingt erst in Tabelle eintragen
+ ULONG nNewId = aPUIdx.Insert( rpObj );
+ // um den gleichen Zustand, wie nach dem Speichern herzustellen
+ aPTable.Insert( (ULONG)rpObj, (void *)nNewId );
+ DBG_ASSERT( !(nHdr & P_DBGUTIL) || nId == nNewId,
+ "read write id conflict: not the same" )
+ }
+ // und dann Laden
+ rpObj->Load( *this );
+#ifdef DBG_UTIL
+ if( nObjLen + nObjPos != Tell() )
+ {
+ ByteString aStr( "false object len: read = " );
+ aStr += ByteString::CreateFromInt32( (long)(Tell() - nObjPos) );
+ aStr += ", should = ";
+ aStr += ByteString::CreateFromInt32( nObjLen );
+ DBG_ERROR( aStr.GetBuffer() )
+ }
+#endif
+ rpObj->RestoreNoDelete();
+ rpObj->ReleaseRef();
+ }
+ else
+ {
+ rpObj = GetObject( nId );
+ DBG_ASSERT( rpObj != NULL, "object does not exist" )
+ DBG_ASSERT( rpObj->GetClassId() == nClassId, "class mismatch" )
+ }
+ }
+ return nId;
+}
+
+//=========================================================================
+SvPersistStream& SvPersistStream::ReadPointer
+(
+ SvPersistBase * & rpObj
+)
+{
+ ReadObj( rpObj, TRUE );
+ return *this;
+}
+
+//=========================================================================
+SvPersistStream& operator <<
+(
+ SvPersistStream & rStm,
+ SvPersistBase * pObj
+)
+{
+ return rStm.WritePointer( pObj );
+}
+
+//=========================================================================
+SvPersistStream& operator >>
+(
+ SvPersistStream & rStm,
+ SvPersistBase * & rpObj
+)
+{
+ return rStm.ReadPointer( rpObj );
+}
+
+//=========================================================================
+SvStream& operator <<
+(
+ SvStream & rStm,
+ SvPersistStream & rThis
+)
+{
+ SvStream * pOldStm = rThis.GetStream();
+ rThis.SetStream( &rStm );
+
+ BYTE bTmp = 0;
+ rThis << bTmp; // Version
+ UINT32 nCount = (UINT32)rThis.aPUIdx.Count();
+ rThis << nCount;
+ SvPersistBase * pEle = rThis.aPUIdx.First();
+ for( UINT32 i = 0; i < nCount; i++ )
+ {
+ BYTE nP = P_OBJ | P_ID | P_STD;
+ WriteId( rThis, nP, rThis.aPUIdx.GetCurIndex(),
+ pEle->GetClassId() );
+ rThis.WriteObj( nP, pEle );
+ pEle = rThis.aPUIdx.Next();
+ }
+ rThis.SetStream( pOldStm );
+ return rStm;
+}
+
+//=========================================================================
+SvStream& operator >>
+(
+ SvStream & rStm,
+ SvPersistStream & rThis
+)
+{
+ SvStream * pOldStm = rThis.GetStream();
+ rThis.SetStream( &rStm );
+
+ BYTE nVers;
+ rThis >> nVers; // Version
+ if( 0 == nVers )
+ {
+ UINT32 nCount = 0;
+ rThis >> nCount;
+ for( UINT32 i = 0; i < nCount; i++ )
+ {
+ SvPersistBase * pEle;
+ // Lesen, ohne in die Tabellen einzutragen
+ UINT32 nId = rThis.ReadObj( pEle, FALSE );
+ if( rThis.GetError() )
+ break;
+
+ // Die Id eines Objektes wird nie modifiziert
+ rThis.aPUIdx.Insert( nId, pEle );
+ rThis.aPTable.Insert( (ULONG)pEle, (void *)nId );
+ }
+ }
+ else
+ rThis.SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ rThis.SetStream( pOldStm );
+ return rStm;
+}
+
+//=========================================================================
+ULONG SvPersistStream::InsertObj( SvPersistBase * pObj )
+{
+ ULONG nId = aPUIdx.Insert( pObj );
+ aPTable.Insert( (ULONG)pObj, (void *)nId );
+ return nId;
+}
+
+//=========================================================================
+ULONG SvPersistStream::RemoveObj( SvPersistBase * pObj )
+{
+ ULONG nIdx = GetIndex( pObj );
+ aPUIdx.Remove( nIdx );
+ aPTable.Remove( (ULONG)pObj );
+ return nIdx;
+}
+
diff --git a/tools/source/ref/ref.cxx b/tools/source/ref/ref.cxx
new file mode 100644
index 000000000000..bfaa76fe9641
--- /dev/null
+++ b/tools/source/ref/ref.cxx
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * $RCSfile: ref.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <ref.hxx>
+#pragma hdrstop
+
+/****************** SvRefBaseMemberList **********************************/
+#define inline
+SV_IMPL_REF_LIST( SvRefBase,SvRefBase* )
+#undef inline
+
+/**************************************************************************
+#* SvRefBase::~SvRefBase()
+**************************************************************************/
+SvRefBase::~SvRefBase()
+{
+}
+
+/**************************************************************************
+#* SvRefBase::QueryDelete()
+**************************************************************************/
+void SvRefBase::QueryDelete()
+{
+ nRefCount = SV_NO_DELETE_REFCOUNT / 2;
+ delete this;
+}
+
+SvCompatRefBase::~SvCompatRefBase()
+{
+ (*pFunc)( pObj );
+}
+
diff --git a/tools/source/solar/makefile.mk b/tools/source/solar/makefile.mk
new file mode 100644
index 000000000000..f38364e9f623
--- /dev/null
+++ b/tools/source/solar/makefile.mk
@@ -0,0 +1,100 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=mksvconf
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+CFILES= solar.c
+
+OBJFILES= $(OBJ)$/solar.obj
+
+APP1TARGET= $(TARGET)
+APP1OBJS= $(OBJFILES)
+APP1STDLIBS=
+APP1DEPN=
+APP1DEF=
+
+.IF "$(depend)" == ""
+ALL: \
+ $(INCCOM)$/svconf.h \
+ ALLTAR
+
+$(INCCOM)$/svconf.h : $(BIN)$/$(TARGET)
+ $(BIN)$/$(TARGET) $@
+
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/tools/source/solar/solar.c b/tools/source/solar/solar.c
new file mode 100644
index 000000000000..a119ce84304d
--- /dev/null
+++ b/tools/source/solar/solar.c
@@ -0,0 +1,590 @@
+/*************************************************************************
+ *
+ * $RCSfile: solar.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include <stdio.h>
+
+#ifdef UNX
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef HPUX
+#include <stdlib.h>
+#endif
+
+#define I_STDARG
+#ifdef I_STDARG
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#define NO_USE_FORK_TO_CHECK
+#ifdef USE_FORK_TO_CHECK
+#include <sys/wait.h>
+#else
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
+#else
+#endif
+
+#define printTypeSize(Type,Name) printf( "sizeof(%s)\t= %d\n", Name, sizeof (Type) )
+
+#define isSignedType(Type) (((Type)-1) < 0)
+#define printTypeSign(Type,Name) printf( "%s\t= %s %s\n", Name, ( isSignedType(Type) ? "signed" : "unsigned" ), Name )
+
+
+/*************************************************************************
+|*
+|* IsBigEndian()
+|*
+|* Beschreibung True, wenn CPU BigEndian ist
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int IsBigEndian()
+{
+ long l = 1;
+ return ! *(char*)&l;
+}
+
+/*************************************************************************
+|*
+|* IsStackGrowingDown()
+|*
+|* Beschreibung True, wenn der Stack nach unten waechst
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int IsStackGrowingDown_2( int * pI )
+{
+ int i = 1;
+ return ((unsigned long)&i) < (unsigned long)pI;
+}
+
+int IsStackGrowingDown()
+{
+ int i = 1;
+ return IsStackGrowingDown_2(&i);
+}
+
+/*************************************************************************
+|*
+|* IsStackGrowingDown()
+|*
+|* Beschreibung Alignment von char Parametern, die (hoffentlich)
+|* ueber den Stack uebergeben werden
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int GetStackAlignment_3( char*p, long l, int i, short s, char b, char c, ... )
+{
+ if ( IsStackGrowingDown() )
+ return &c - &b;
+ else
+ return &b - &c;
+}
+
+int GetStackAlignment_2( char*p, long l, int i, short s, char b, char c )
+{
+ if ( IsStackGrowingDown() )
+ return &c - &b;
+ else
+ return &b - &c;
+}
+
+int GetStackAlignment()
+{
+ int nStackAlignment = GetStackAlignment_3(0,1,2,3,4,5);
+ if ( nStackAlignment != GetStackAlignment_2(0,1,2,3,4,5) )
+ printf( "Pascal calling convention\n" );
+ return nStackAlignment;
+}
+
+
+/*************************************************************************
+|*
+|* Typdeclarations for memory access test functions
+|*
+*************************************************************************/
+typedef enum { t_char, t_short, t_int, t_long, t_double } Type;
+typedef int (*TestFunc)( Type, void* );
+
+
+#ifdef UNX
+
+/*************************************************************************
+|*
+|* PrintArgs()
+|*
+|* Beschreibung Testfunktion fuer variable Parameter
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+#ifdef I_STDARG
+void PrintArgs( int p, ... )
+#else
+void PrintArgs( p, va_alist )
+int p;
+va_dcl
+#endif
+{
+ int value;
+ va_list ap;
+
+#ifdef I_STDARG
+ va_start( ap, p );
+#else
+ va_start( ap );
+#endif
+
+ printf( "value = %d", p );
+
+ while ( ( value = va_arg(ap, int) ) != 0 )
+ printf( " %d", value );
+
+ printf( "\n" );
+ va_end(ap);
+}
+
+#ifndef USE_FORK_TO_CHECK
+/*************************************************************************
+|*
+|* SignalHdl()
+|*
+|* Beschreibung faengt SIGBUS und SIGSEGV in check() ab
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+static jmp_buf check_env;
+static int bSignal;
+void SignalHdl( int sig )
+{
+ bSignal = 1;
+ /*
+ fprintf( stderr, "Signal %d caught\n", sig );
+ signal( sig, SignalHdl );
+ /**/
+ longjmp( check_env, sig );
+}
+#endif
+
+/*************************************************************************
+|*
+|* check()
+|*
+|* Beschreibung Testet MemoryZugriff (read/write)
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int check( TestFunc func, Type eT, void* p )
+{
+#ifdef USE_FORK_TO_CHECK
+ pid_t nChild = fork();
+ if ( nChild )
+ {
+ int exitVal;
+ wait( &exitVal );
+ if ( exitVal & 0xff )
+ return -1;
+ else
+ return exitVal >> 8;
+ }
+ else
+ {
+ exit( func( eT, p ) );
+ }
+#else
+ int result;
+
+ bSignal = 0;
+
+ if ( !setjmp( check_env ) )
+ {
+ signal( SIGSEGV, SignalHdl );
+ signal( SIGBUS, SignalHdl );
+ result = func( eT, p );
+ signal( SIGSEGV, SIG_DFL );
+ signal( SIGBUS, SIG_DFL );
+ }
+
+ if ( bSignal )
+ return -1;
+ else
+ return 0;
+#endif
+}
+
+#endif
+
+
+/*************************************************************************
+|*
+|* GetAtAddress()
+|*
+|* Beschreibung memory read access
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int GetAtAddress( Type eT, void* p )
+{
+ switch ( eT )
+ {
+ case t_char: return *((char*)p);
+ case t_short: return *((short*)p);
+ case t_int: return *((int*)p);
+ case t_long: return *((long*)p);
+ case t_double: return *((double*)p);
+ }
+ abort();
+}
+
+/*************************************************************************
+|*
+|* SetAtAddress()
+|*
+|* Beschreibung memory write access
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int SetAtAddress( Type eT, void* p )
+{
+ switch ( eT )
+ {
+ case t_char: return *((char*)p) = 0;
+ case t_short: return *((short*)p) = 0;
+ case t_int: return *((int*)p) = 0;
+ case t_long: return *((long*)p) = 0;
+ case t_double: return *((double*)p)= 0;
+ }
+ abort();
+}
+
+char* TypeName( Type eT )
+{
+ switch ( eT )
+ {
+ case t_char: return "char";
+ case t_short: return "short";
+ case t_int: return "int";
+ case t_long: return "long";
+ case t_double: return "double";
+ }
+ abort();
+}
+
+/*************************************************************************
+|*
+|* Check(Get|Set)Access()
+|*
+|* Beschreibung Testet MemoryZugriff (read/write)
+|* Zugriffsverletzungen werden abgefangen
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int CheckGetAccess( Type eT, void* p )
+{
+ int b;
+ b = -1 != check( (TestFunc)GetAtAddress, eT, p );
+#ifdef DEBUG
+ fprintf( stderr,
+ "%s read %s at %p\n",
+ (b? "can" : "can not" ), TypeName(eT), p );
+#endif
+ return b;
+}
+int CheckSetAccess( Type eT, void* p )
+{
+ int b;
+ b = -1 != check( (TestFunc)SetAtAddress, eT, p );
+#ifdef DEBUG
+ fprintf( stderr,
+ "%s write %s at %p\n",
+ (b? "can" : "can not" ), TypeName(eT), p );
+#endif
+ return b;
+}
+
+/*************************************************************************
+|*
+|* GetAlignment()
+|*
+|* Beschreibung Bestimmt das Alignment verschiedener Typen
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+int GetAlignment( Type eT )
+{
+ char a[ 16*8 ];
+ long p = (long)(void*)a;
+ int i;
+
+ /* clear a[...] to set legal value for double access */
+ for ( i = 0; i < 16*8; i++ )
+ a[i] = 0;
+
+ p = ( p + 0xF ) & ~0xF;
+ for ( i = 1; i < 16; i++ )
+ if ( CheckGetAccess( eT, (void*)(p+i) ) )
+ return i;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* struct Description
+|*
+|* Beschreibung Beschreibt die Parameter der Architektur
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+struct Description
+{
+ int bBigEndian;
+ int bStackGrowsDown;
+ int nStackAlignment;
+ int nAlignment[3]; /* 2,4,8 */
+};
+
+/*************************************************************************
+|*
+|* Description_Ctor()
+|*
+|* Beschreibung Bestimmt die Parameter der Architektur
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+Description_Ctor( struct Description* pThis )
+{
+ pThis->bBigEndian = IsBigEndian();
+ pThis->bStackGrowsDown = IsStackGrowingDown();
+ pThis->nStackAlignment = GetStackAlignment();
+
+ if ( sizeof(short) != 2 )
+ abort();
+ pThis->nAlignment[0] = GetAlignment( t_short );
+ if ( sizeof(int) != 4 )
+ abort();
+ pThis->nAlignment[1] = GetAlignment( t_int );
+
+ if ( sizeof(long) == 8 )
+ pThis->nAlignment[2] = GetAlignment( t_long );
+ else if ( sizeof(double) == 8 )
+ pThis->nAlignment[2] = GetAlignment( t_double );
+ else
+ abort();
+}
+
+/*************************************************************************
+|*
+|* Description_Print()
+|*
+|* Beschreibung Schreibt die Parameter der Architektur als Header
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+Description_Print( struct Description* pThis, char* name )
+{
+ int i;
+ FILE* f = fopen( name, "w" );
+ fprintf( f, "#define __%s\n",
+ pThis->bBigEndian ? "BIGENDIAN" : "LITTLEENDIAN" );
+ for ( i = 0; i < 3; i++ )
+ fprintf( f, "#define __ALIGNMENT%d\t%d\n",
+ 1 << i+1, pThis->nAlignment[i] );
+ fprintf( f, "#define __STACKALIGNMENT wird nicht benutzt\t%d\n", pThis->nStackAlignment );
+ fprintf( f, "#define __STACKDIRECTION\t%d\n",
+ pThis->bStackGrowsDown ? -1 : 1 );
+ fprintf( f, "#define __SIZEOFCHAR\t%d\n", sizeof( char ) );
+ fprintf( f, "#define __SIZEOFSHORT\t%d\n", sizeof( short ) );
+ fprintf( f, "#define __SIZEOFINT\t%d\n", sizeof( int ) );
+ fprintf( f, "#define __SIZEOFLONG\t%d\n", sizeof( long ) );
+ fprintf( f, "#define __SIZEOFPOINTER\t%d\n", sizeof( void* ) );
+ fprintf( f, "#define __SIZEOFDOUBLE\t%d\n", sizeof( double ) );
+ fprintf( f, "#define __IEEEDOUBLE\n" );
+ fclose( f );
+}
+
+/*************************************************************************
+|*
+|* InfoMemoryAccess()
+|*
+|* Beschreibung Informeller Bytezugriffstest
+|*
+|* Ersterstellung EG 26.06.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+void InfoMemoryAccess( char* p )
+{
+ if ( CheckGetAccess( t_char, p ) )
+ printf( "can read address %p\n", p );
+ else
+ printf( "can not read address %p\n", p );
+
+ if ( CheckSetAccess( t_char, p ) )
+ printf( "can write address %p\n", p );
+ else
+ printf( "can not write address %p\n", p );
+}
+
+/*************************************************************************
+|*
+|* InfoMemoryTypeAccess()
+|*
+|* Beschreibung Informeller Zugriffstest verschiedener Typen
+|*
+|* Ersterstellung EG 15.08.96
+|* Letzte Aenderung
+|*
+*************************************************************************/
+void InfoMemoryTypeAccess( Type eT )
+{
+ char a[64];
+ int i;
+
+ /* clear a[...] to set legal value for double access */
+ for ( i = 0; i < 64; i++ )
+ a[i] = 0;
+
+ for ( i = 56; i >= 7; i >>= 1 )
+ {
+ printf( "Zugriff %s auf %i-Aligned Adresse : ", TypeName( eT ), i / 7 );
+ printf( ( CheckGetAccess( eT, (long*)&a[i] ) ? "OK\n" : "ERROR\n" ) );
+ }
+}
+
+main( int argc, char* argv[] )
+{
+ printTypeSign( char, "char" );
+ printTypeSign( short, "short" );
+ printTypeSign( int, "int" );
+ printTypeSign( long, "long" );
+
+ printTypeSize( char, "char" );
+ printTypeSize( short, "short" );
+ printTypeSize( int, "int" );
+ printTypeSize( long, "long" );
+ printTypeSize( float, "float" );
+ printTypeSize( double, "double" );
+ printTypeSize( void *, "void *" );
+
+ if ( IsBigEndian() )
+ printf( "BIGENDIAN (Sparc, MC680x0, RS6000, IP22, IP32, g3)\n" );
+ else
+ printf( "LITTLEENDIAN (Intel, VAX, PowerPC)\n" );
+
+ if( IsStackGrowingDown() )
+ printf( "Stack waechst nach unten\n" );
+ else
+ printf( "Stack waechst nach oben\n" );
+
+ printf( "STACKALIGNMENT : %d\n", GetStackAlignment() );
+
+ /* PrintArgs( 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ); */
+
+ if ( argc > 1 )
+ {
+ struct Description description;
+ Description_Ctor( &description );
+ Description_Print( &description, argv[1] );
+ }
+
+ {
+ char* p = NULL;
+ InfoMemoryAccess( p );
+ p = (char*)&p;
+ InfoMemoryAccess( p );
+ InfoMemoryTypeAccess( t_short );
+ InfoMemoryTypeAccess( t_int );
+ InfoMemoryTypeAccess( t_long );
+ InfoMemoryTypeAccess( t_double );
+ }
+
+ exit( 0 );
+}
diff --git a/tools/source/stream/cachestr.cxx b/tools/source/stream/cachestr.cxx
new file mode 100644
index 000000000000..f4533f76515b
--- /dev/null
+++ b/tools/source/stream/cachestr.cxx
@@ -0,0 +1,329 @@
+/*************************************************************************
+ *
+ * $RCSfile: cachestr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <debug.hxx>
+#include <stream.hxx>
+#include <cachestr.hxx>
+#include <tempfile.hxx>
+
+/*************************************************************************
+|*
+|* SvCacheStream::SvCacheStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+SvCacheStream::SvCacheStream( ULONG nMaxMemSize )
+{
+ if( !nMaxMemSize )
+#if defined WIN || defined WNT || defined OS2 || defined MAC || defined UNX
+ nMaxMemSize = 20480;
+#else
+ nMaxMemSize = 20480;
+#endif
+ SvStream::bIsWritable = TRUE;
+ nMaxSize = nMaxMemSize;
+ bPersistent = FALSE;
+ pSwapStream = 0;
+ pCurrentStream = new SvMemoryStream( nMaxMemSize );
+ pTempFile = 0;
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::SvCacheStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+SvCacheStream::SvCacheStream( const String &rFileName,
+ ULONG nExpectedSize,
+ ULONG nMaxMemSize )
+{
+ if( !nMaxMemSize )
+#if defined WIN || defined WNT || defined OS2 || defined MAC || defined UNX
+ nMaxMemSize = 20480;
+#else
+ nMaxMemSize = 20480;
+#endif
+
+ if( nExpectedSize > nMaxMemSize )
+ nExpectedSize = nMaxMemSize; // oder gleich in File schreiben
+ else if( !nExpectedSize )
+ nExpectedSize = 4096;
+
+ SvStream::bIsWritable = TRUE;
+ nMaxSize = nMaxMemSize;
+ bPersistent = TRUE;
+ aFileName = rFileName;
+ pSwapStream = 0;
+ pCurrentStream = new SvMemoryStream( nExpectedSize );
+ pTempFile = 0;
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::~SvCacheStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+SvCacheStream::~SvCacheStream()
+{
+ if( pCurrentStream != pSwapStream )
+ delete pSwapStream;
+ delete pCurrentStream;
+
+ if( pSwapStream && !bPersistent && pTempFile )
+ {
+ // temporaeres File loeschen
+ pTempFile->EnableKillingFile( TRUE );
+ }
+
+ delete pTempFile;
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::SwapOut()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+void SvCacheStream::SwapOut()
+{
+ if( pCurrentStream != pSwapStream )
+ {
+ if( !pSwapStream && !aFileName.Len() )
+ {
+ if (aFilenameLinkHdl.IsSet())
+ {
+ // pSwapStream wird zum Schutz gegen Reentranz genutzt
+ pSwapStream = pCurrentStream;
+ Link aLink( aFilenameLinkHdl );
+ aFilenameLinkHdl = Link();
+ aLink.Call(this);
+ // pSwapStream nur zuruecksetzen, wenn nicht ueber
+ // SetSwapStream geaendert
+ if( pSwapStream == pCurrentStream ) pSwapStream = 0;
+ }
+ else
+ {
+ pTempFile = new TempFile;
+ aFileName = pTempFile->GetName();
+ }
+ }
+
+ ULONG nPos = pCurrentStream->Tell();
+ pCurrentStream->Seek( 0 );
+ if( !pSwapStream )
+ pSwapStream = new SvFileStream( aFileName, STREAM_READWRITE | STREAM_TRUNC );
+ *pSwapStream << *pCurrentStream;
+ pSwapStream->Flush();
+ delete pCurrentStream;
+ pCurrentStream = pSwapStream;
+ pCurrentStream->Seek( nPos );
+ }
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::GetData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+ULONG SvCacheStream::GetData( void* pData, ULONG nSize )
+{
+ return pCurrentStream->Read( pData, nSize );
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+ULONG SvCacheStream::PutData( const void* pData, ULONG nSize )
+{
+ // lieber unnoetig auslagern als unnoetig umkopieren
+ if( pCurrentStream != pSwapStream
+ && pCurrentStream->Tell() + nSize > nMaxSize )
+ SwapOut();
+ return pCurrentStream->Write( pData, nSize );
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::SeekPos()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+ULONG SvCacheStream::SeekPos( ULONG nPos )
+{
+ return pCurrentStream->Seek( nPos );
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::FlushData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+void SvCacheStream::FlushData()
+{
+ pCurrentStream->Flush();
+ if( pCurrentStream != pSwapStream
+ && ((SvMemoryStream*)pCurrentStream)->GetSize() > nMaxSize )
+ SwapOut();
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::GetStr()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+const void* SvCacheStream::GetBuffer()
+{
+ Flush();
+ if( pCurrentStream != pSwapStream )
+ return ((SvMemoryStream*)pCurrentStream)->GetData();
+ else
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::SetSize()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+void SvCacheStream::SetSize( ULONG nSize )
+{
+ pCurrentStream->SetStreamSize( nSize );
+}
+
+/*************************************************************************
+|*
+|* SvCacheStream::GetSize()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 27.09.94
+|* Letzte Aenderung OV 27.09.94
+|*
+*************************************************************************/
+
+ULONG SvCacheStream::GetSize()
+{
+ // ACHTUNG: SvMemoryStream::GetSize() gibt Groesse
+ // des allozierten Buffers zurueck
+ Flush();
+ ULONG nTemp = Tell();
+ ULONG nLength = Seek( STREAM_SEEK_TO_END );
+ Seek( nTemp );
+ return nLength;
+}
+
+void SvCacheStream::SetFilenameHdl( const Link& rLink)
+{
+ aFilenameLinkHdl = rLink;
+}
+
+const Link& SvCacheStream::GetFilenameHdl() const
+{
+ return aFilenameLinkHdl;
+}
diff --git a/tools/source/stream/makefile.mk b/tools/source/stream/makefile.mk
new file mode 100644
index 000000000000..da71d3c408bc
--- /dev/null
+++ b/tools/source/stream/makefile.mk
@@ -0,0 +1,103 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=stream
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/stream.obj \
+ $(SLO)$/strmsys.obj \
+ $(SLO)$/cachestr.obj \
+ $(SLO)$/vcompat.obj
+
+.IF "$(UPDATER)" != ""
+.IF "$(GUI)" != "MAC"
+OBJFILES= $(OBJ)$/stdstrm.obj
+.ENDIF
+
+OBJFILES+= $(OBJ)$/stream.obj \
+ $(OBJ)$/strmsys.obj \
+ $(OBJ)$/cachestr.obj \
+ $(OBJ)$/vcompat.obj
+.ENDIF
+
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
+$(SLO)$/strmsys.obj : \
+ strmos2.cxx \
+ strmwnt.cxx \
+ strmwin.cxx \
+ strmmac.cxx \
+ strmunx.cxx \
+ strmstd.cxx
+
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
new file mode 100644
index 000000000000..adca76dfd39e
--- /dev/null
+++ b/tools/source/stream/stream.cxx
@@ -0,0 +1,2905 @@
+/*************************************************************************
+ *
+ * $RCSfile: stream.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// ToDo:
+// - Read->RefreshBuffer->Auf Aenderungen von nBufActualLen reagieren
+
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h> // isspace
+#include <stdlib.h> // strtol, _crotl
+
+/*
+#if defined( DBG_UTIL ) && defined( DEBUG )
+// prueft Synchronisation des Buffers nach allen Read, Write, Seek
+#define OV_DEBUG
+#endif
+*/
+
+#ifdef WIN
+#include <dll.hxx>
+#include <svwin.h>
+#ifndef SEG
+#define SEG(fp) (*((size_t*)&(fp) + 1))
+#endif
+#include <solar.h>
+#endif
+
+#if defined(BLC)
+#define SWAPNIBBLES(c) c=_crotl(c,4);
+#else
+#define SWAPNIBBLES(c) \
+unsigned char nSwapTmp=c; \
+nSwapTmp <<= 4; \
+c >>= 4; \
+c |= nSwapTmp;
+#endif
+
+#include <new.hxx>
+#include <debug.hxx>
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+#include <stream.hxx>
+#include <osl/thread.h>
+
+// -----------------------------------------------------------------------
+
+DBG_NAME( Stream );
+
+// -----------------------------------------------------------------------
+
+// sprintf Param-Mode
+#define SPECIAL_PARAM_NONE 0 // Format-Str, Number
+#define SPECIAL_PARAM_WIDTH 1 // Format-Str, Width, Number
+#define SPECIAL_PARAM_PRECISION 2 // Format-Str, Precision, Number
+#define SPECIAL_PARAM_BOTH 3 // Format-Str, Width, Precision, Number
+
+#if SUPD <= 344
+#define _CR '\n'
+#define _LF '\r'
+#endif
+
+// -----------------------------------------------------------------------
+
+// !!! Nicht inline, wenn Operatoren <<,>> inline sind
+inline static void SwapUShort( USHORT& r )
+ { r = SWAPSHORT(r); }
+inline static void SwapShort( short& r )
+ { r = SWAPSHORT(r); }
+inline static void SwapInt( int& r )
+ { r = SWAPSHORT(r); }
+inline static void SwapUInt( unsigned int& r )
+ { r = SWAPSHORT(r); }
+inline static void SwapLong( long& r )
+ { r = SWAPLONG(r); }
+inline static void SwapULong( ULONG& r )
+ { r = SWAPLONG(r); }
+inline static void SwapLongInt( int& r )
+ { r = SWAPLONG(r); }
+inline static void SwapLongUInt( unsigned int& r )
+ { r = SWAPLONG(r); }
+#ifdef UNX
+inline static void SwapFloat( float& r )
+ {
+ DBG_ASSERT( FALSE, "SwapFloat noch nicht implementiert!\n" );
+ }
+inline static void SwapDouble( double& r )
+ {
+ if( sizeof(double) != 8 )
+ {
+ DBG_ASSERT( FALSE, "Can only swap 8-Byte-doubles\n" );
+ }
+ else
+ {
+ UINT32* c = (UINT32*)(void*)&r;
+ c[0] ^= c[1]; // zwei 32-Bit-Werte in situ vertauschen
+ c[1] ^= c[0];
+ c[0] ^= c[1];
+ c[0] = SWAPLONG(c[0]); // und die beiden 32-Bit-Werte selbst in situ drehen
+ c[1] = SWAPLONG(c[1]);
+ }
+ }
+
+#elif MAC
+
+inline static void SwapFloat( float& r )
+ {
+ DBG_ASSERT( FALSE, "SwapFloat noch nicht implementiert!\n" );
+ }
+
+inline static void SwapDouble( double& r )
+ {
+#ifdef DBG_UTIL
+ if( sizeof(double) != 8 )
+ DBG_ASSERT( FALSE, "Can only swap 8-Byte-doubles\n" );
+#endif
+
+ UINT32* c = (UINT32*)(void*)&r;
+ UINT32 nHelp;
+ // zwei 32-Bit-Werte in situ vertauschen
+ // und die beiden 32-Bit-Werte selbst in situ drehen
+ nHelp = SWAPLONG(c[0]);
+ c[0] = SWAPLONG(c[1]);
+ c[1] = nHelp;
+ }
+#endif // #ifdef UNX / elif MAC
+
+//SDO
+
+#define READNUMBER_WITHOUT_SWAP(datatype,value) \
+{\
+int tmp = eIOMode; \
+if( (tmp == STREAM_IO_READ) && sizeof(datatype)<=nBufFree) \
+{\
+ for (int i = 0; i < sizeof(datatype); i++)\
+ ((char *)&r)[i] = pBufPos[i];\
+ nBufActualPos += sizeof(datatype);\
+ pBufPos += sizeof(datatype);\
+ nBufFree -= sizeof(datatype);\
+}\
+else\
+ Read( (char*)&value, sizeof(datatype) );\
+}
+
+#define WRITENUMBER_WITHOUT_SWAP(datatype,value) \
+{\
+int tmp = eIOMode; \
+if( (tmp==STREAM_IO_WRITE) && sizeof(datatype) <= nBufFree)\
+{\
+ for (int i = 0; i < sizeof(datatype); i++)\
+ pBufPos[i] = ((char *)&value)[i];\
+ nBufFree -= sizeof(datatype);\
+ nBufActualPos += sizeof(datatype);\
+ if( nBufActualPos > nBufActualLen )\
+ nBufActualLen = nBufActualPos;\
+ pBufPos += sizeof(datatype);\
+ bIsDirty = TRUE;\
+}\
+else\
+ Write( (char*)&value, sizeof(datatype) );\
+}
+
+//============================================================================
+//
+// class SvLockBytes
+//
+//============================================================================
+
+void SvLockBytes::close()
+{
+ if (m_bOwner)
+ delete m_pStream;
+ m_pStream = 0;
+}
+
+//============================================================================
+TYPEINIT0(SvLockBytes);
+
+//============================================================================
+// virtual
+ErrCode SvLockBytes::ReadAt(ULONG nPos, void * pBuffer, ULONG nCount,
+ ULONG * pRead) const
+{
+ if (!m_pStream)
+ {
+ DBG_ERROR("SvLockBytes::ReadAt(): Bad stream");
+ return ERRCODE_NONE;
+ }
+
+ m_pStream->Seek(nPos);
+ ULONG nTheRead = m_pStream->Read(pBuffer, nCount);
+ if (pRead)
+ *pRead = nTheRead;
+ return m_pStream->GetErrorCode();
+}
+
+//============================================================================
+// virtual
+ErrCode SvLockBytes::WriteAt(ULONG nPos, const void * pBuffer, ULONG nCount,
+ ULONG * pWritten)
+{
+ if (!m_pStream)
+ {
+ DBG_ERROR("SvLockBytes::WriteAt(): Bad stream");
+ return ERRCODE_NONE;
+ }
+
+ m_pStream->Seek(nPos);
+ ULONG nTheWritten = m_pStream->Write(pBuffer, nCount);
+ if (pWritten)
+ *pWritten = nTheWritten;
+ return m_pStream->GetErrorCode();
+}
+
+//============================================================================
+// virtual
+ErrCode SvLockBytes::Flush() const
+{
+ if (!m_pStream)
+ {
+ DBG_ERROR("SvLockBytes::Flush(): Bad stream");
+ return ERRCODE_NONE;
+ }
+
+ m_pStream->Flush();
+ return m_pStream->GetErrorCode();
+}
+
+//============================================================================
+// virtual
+ErrCode SvLockBytes::SetSize(ULONG nSize)
+{
+ if (!m_pStream)
+ {
+ DBG_ERROR("SvLockBytes::SetSize(): Bad stream");
+ return ERRCODE_NONE;
+ }
+
+ m_pStream->SetStreamSize(nSize);
+ return m_pStream->GetErrorCode();
+}
+
+//============================================================================
+ErrCode SvLockBytes::LockRegion(ULONG, ULONG, LockType)
+{
+ DBG_ERROR("SvLockBytes::LockRegion(): Not implemented");
+ return ERRCODE_NONE;
+}
+
+//============================================================================
+
+ErrCode SvLockBytes::UnlockRegion(ULONG, ULONG, LockType)
+{
+ DBG_ERROR("SvLockBytes::UnlockRegion(): Not implemented");
+ return ERRCODE_NONE;
+}
+
+//============================================================================
+ErrCode SvLockBytes::Stat(SvLockBytesStat * pStat, SvLockBytesStatFlag) const
+{
+ if (!m_pStream)
+ {
+ DBG_ERROR("SvLockBytes::Stat(): Bad stream");
+ return ERRCODE_NONE;
+ }
+
+ if (pStat)
+ {
+ ULONG nPos = m_pStream->Tell();
+ pStat->nSize = m_pStream->Seek(STREAM_SEEK_TO_END);
+ m_pStream->Seek(nPos);
+ }
+ return ERRCODE_NONE;
+}
+
+//============================================================================
+//
+// class SvOpenLockBytes
+//
+//============================================================================
+
+TYPEINIT1(SvOpenLockBytes, SvLockBytes);
+
+//============================================================================
+//
+// class SvAsyncLockBytes
+//
+//============================================================================
+
+TYPEINIT1(SvAsyncLockBytes, SvOpenLockBytes);
+
+//============================================================================
+// virtual
+ErrCode SvAsyncLockBytes::ReadAt(ULONG nPos, void * pBuffer, ULONG nCount,
+ ULONG * pRead) const
+{
+ if (m_bTerminated)
+ return SvOpenLockBytes::ReadAt(nPos, pBuffer, nCount, pRead);
+ else
+ {
+ ULONG nTheCount = min(nPos < m_nSize ? m_nSize - nPos : 0, nCount);
+ ErrCode nError = SvOpenLockBytes::ReadAt(nPos, pBuffer, nTheCount,
+ pRead);
+ return !nCount || nTheCount == nCount || nError ? nError :
+ ERRCODE_IO_PENDING;
+ }
+}
+
+//============================================================================
+// virtual
+ErrCode SvAsyncLockBytes::WriteAt(ULONG nPos, const void * pBuffer,
+ ULONG nCount, ULONG * pWritten)
+{
+ if (m_bTerminated)
+ return SvOpenLockBytes::WriteAt(nPos, pBuffer, nCount, pWritten);
+ else
+ {
+ ULONG nTheCount = min(nPos < m_nSize ? m_nSize - nPos : 0, nCount);
+ ErrCode nError = SvOpenLockBytes::WriteAt(nPos, pBuffer, nTheCount,
+ pWritten);
+ return !nCount || nTheCount == nCount || nError ? nError :
+ ERRCODE_IO_PENDING;
+ }
+}
+
+//============================================================================
+// virtual
+ErrCode SvAsyncLockBytes::FillAppend(const void * pBuffer, ULONG nCount,
+ ULONG * pWritten)
+{
+ ULONG nTheWritten;
+ ErrCode nError = SvOpenLockBytes::WriteAt(m_nSize, pBuffer, nCount,
+ &nTheWritten);
+ if (!nError)
+ m_nSize += nTheWritten;
+ if (pWritten)
+ *pWritten = nTheWritten;
+ return nError;
+}
+
+//============================================================================
+// virtual
+ULONG SvAsyncLockBytes::Seek(ULONG nPos)
+{
+ if (nPos != STREAM_SEEK_TO_END)
+ m_nSize = nPos;
+ return m_nSize;
+}
+
+//============================================================================
+//
+// class SvStream
+//
+//============================================================================
+
+ULONG SvStream::GetData( void* pData, ULONG nSize )
+{
+ if( !GetError() )
+ {
+ DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
+ ULONG nRet;
+ nError = xLockBytes->ReadAt( nActPos, pData, nSize, &nRet );
+ nActPos += nRet;
+ return nRet;
+ }
+ else return 0;
+}
+
+ErrCode SvStream::SetLockBytes( SvLockBytesRef& rLB )
+{
+ xLockBytes = rLB;
+ RefreshBuffer();
+ return ERRCODE_NONE;
+}
+
+//========================================================================
+
+ULONG SvStream::PutData( const void* pData, ULONG nSize )
+{
+ if( !GetError() )
+ {
+ DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
+ ULONG nRet;
+ nError = xLockBytes->WriteAt( nActPos, pData, nSize, &nRet );
+ nActPos += nRet;
+ return nRet;
+ }
+ else return 0;
+}
+
+//========================================================================
+
+ULONG SvStream::SeekPos( ULONG nPos )
+{
+ if( !GetError() && nPos == STREAM_SEEK_TO_END )
+ {
+ DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
+ SvLockBytesStat aStat;
+ xLockBytes->Stat( &aStat, SVSTATFLAG_DEFAULT );
+ nActPos = aStat.nSize;
+ }
+ else
+ nActPos = nPos;
+ return nActPos;
+}
+
+//========================================================================
+
+void SvStream::FlushData()
+{
+ if( !GetError() )
+ {
+ DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
+ nError = xLockBytes->Flush();
+ }
+}
+
+//========================================================================
+
+void SvStream::SetSize( ULONG nSize )
+{
+ DBG_ASSERT( xLockBytes.Is(), "pure virtual function" );
+ nError = xLockBytes->SetSize( nSize );
+}
+
+void SvStream::ImpInit()
+{
+ nActPos = 0;
+ nCompressMode = COMPRESSMODE_NONE;
+ eStreamCharSet = osl_getThreadTextEncoding();
+// eTargetCharSet = osl_getThreadTextEncoding();
+ nCryptMask = 0;
+ bIsEof = FALSE;
+#if defined( MAC )
+ eLineDelimiter = LINEEND_CR; // MAC-Format
+#elif defined( UNX )
+ eLineDelimiter = LINEEND_LF; // UNIX-Format
+#else
+ eLineDelimiter = LINEEND_CRLF; // DOS-Format
+#endif
+
+ SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ nBufFilePos = 0;
+ nBufActualPos = 0;
+ bIsDirty = FALSE;
+ bIsConsistent = TRUE;
+ bIsWritable = TRUE;
+
+ pRWBuf = 0;
+ pBufPos = 0;
+ nBufSize = 0;
+ nBufActualLen = 0;
+ eIOMode = STREAM_IO_DONTKNOW;
+ nBufFree = 0;
+
+ nRadix = 10;
+ nPrecision = 0; // all significant digits
+ nWidth = 0; // default width
+ cFiller = ' ';
+ nJustification = JUSTIFY_RIGHT;
+ eStreamMode = 0;
+ CreateFormatString();
+
+ nVersion = 0;
+
+ ClearError();
+}
+
+/*************************************************************************
+|*
+|* Stream::Stream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvStream::SvStream( SvLockBytes* pLockBytesP )
+{
+ DBG_CTOR( Stream, NULL );
+
+ ImpInit();
+ xLockBytes = pLockBytesP;
+ const SvStream* pStrm;
+ if( pLockBytesP && (pStrm = pLockBytesP->GetStream() ) )
+ SetError( pStrm->GetErrorCode() );
+ SetBufferSize( 256 );
+}
+
+SvStream::SvStream()
+{
+ DBG_CTOR( Stream, NULL );
+
+ ImpInit();
+}
+
+/*************************************************************************
+|*
+|* Stream::~Stream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvStream::~SvStream()
+{
+ DBG_DTOR( Stream, NULL );
+
+ if ( xLockBytes.Is() )
+ Flush();
+
+ if( pRWBuf )
+ delete pRWBuf;
+}
+
+/*************************************************************************
+|*
+|* Stream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+USHORT SvStream::IsA() const
+{
+ return (USHORT)ID_STREAM;
+}
+
+/*************************************************************************
+|*
+|* Stream::ClearError()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::ClearError()
+{
+ bIsEof = FALSE;
+ nError = SVSTREAM_OK;
+}
+
+/*************************************************************************
+|*
+|* Stream::SetError()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::SetError( ULONG nErrorCode )
+{
+ if ( nError == SVSTREAM_OK )
+ nError = nErrorCode;
+}
+
+
+/*************************************************************************
+|*
+|* Stream::SetNumberFormatInt()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::SetNumberFormatInt( USHORT nNewFormat )
+{
+ nNumberFormatInt = nNewFormat;
+ bSwap = FALSE;
+#ifdef __BIGENDIAN
+ if( nNumberFormatInt == NUMBERFORMAT_INT_LITTLEENDIAN )
+ bSwap = TRUE;
+#else
+ if( nNumberFormatInt == NUMBERFORMAT_INT_BIGENDIAN )
+ bSwap = TRUE;
+#endif
+}
+
+/*************************************************************************
+|*
+|* Stream::SetBufferSize()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::SetBufferSize( USHORT nBufferSize )
+{
+ ULONG nActualFilePos = Tell();
+ BOOL bDontSeek = (BOOL)(pRWBuf == 0);
+
+ if( bIsDirty && bIsConsistent && bIsWritable ) // wg. Windows NT: Access denied
+ Flush();
+
+ if( nBufSize )
+ {
+ delete pRWBuf;
+ nBufFilePos += nBufActualPos;
+ }
+
+ pRWBuf = 0;
+ nBufActualLen = 0;
+ nBufActualPos = 0;
+ nBufSize = nBufferSize;
+ if( nBufSize )
+ pRWBuf = new BYTE[ nBufSize ];
+ bIsConsistent = TRUE;
+ pBufPos = pRWBuf;
+ eIOMode = STREAM_IO_DONTKNOW;
+ if( !bDontSeek )
+ SeekPos( nActualFilePos );
+}
+
+/*************************************************************************
+|*
+|* Stream::ClearBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::ClearBuffer()
+{
+ nBufActualLen = 0;
+ nBufActualPos = 0;
+ nBufFilePos = 0;
+ pBufPos = pRWBuf;
+ bIsDirty = FALSE;
+ bIsConsistent = TRUE;
+ eIOMode = STREAM_IO_DONTKNOW;
+
+ bIsEof = FALSE;
+}
+
+/*************************************************************************
+|*
+|* Stream::ResetError()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::ResetError()
+{
+ ClearError();
+}
+
+/*************************************************************************
+|*
+|* Stream::ReadLine()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+BOOL SvStream::ReadByteStringLine( String& rStr, rtl_TextEncoding eSrcCharSet )
+{
+ BOOL bRet;
+ ByteString aStr;
+
+ bRet = ReadLine(aStr);
+ rStr = UniString( aStr, eSrcCharSet );
+ return bRet;
+}
+
+BOOL SvStream::ReadLine( ByteString& rStr )
+{
+ sal_Char buf[256+1];
+ BOOL bEnd = FALSE;
+ ULONG nOldFilePos = Tell();
+ sal_Char c = 0;
+
+ rStr.Erase();
+ while( !bEnd && !GetError() ) // !!! nicht auf EOF testen,
+ // !!! weil wir blockweise
+ // !!! lesen
+ {
+ USHORT nLen = (USHORT)Read( buf, sizeof(buf)-1 );
+ if ( !nLen )
+ {
+ if ( rStr.Len() == 0 )
+ {
+ // der allererste Blockread hat fehlgeschlagen -> Abflug
+ bIsEof = TRUE;
+ return FALSE;
+ }
+ else
+ break;
+ }
+
+ for( USHORT n = 0; n < nLen ; n++ )
+ {
+ c = buf[n];
+ if ( c != '\n' && c != '\r' )
+ rStr += c;
+ else
+ {
+ bEnd = TRUE;
+ break;
+ }
+ }
+ }
+
+ if ( !bEnd && !GetError() && rStr.Len() )
+ bEnd = TRUE;
+
+ nOldFilePos += rStr.Len();
+ if( Tell() > nOldFilePos )
+ nOldFilePos++;
+ Seek( nOldFilePos ); // seeken wg. obigem BlockRead!
+
+ if ( bEnd && (c=='\r' || c=='\n') ) // Sonderbehandlung DOS-Dateien
+ {
+ char cTemp;
+ Read((char*)&cTemp , sizeof(cTemp) );
+ if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
+ Seek( nOldFilePos );
+ }
+
+ if ( bEnd )
+ bIsEof = FALSE;
+ return bEnd;
+}
+
+/*************************************************************************
+|*
+|* Stream::WriteLine()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+BOOL SvStream::WriteByteStringLine( const String& rStr, rtl_TextEncoding eDestCharSet )
+{
+ return WriteLine( ByteString( rStr, eDestCharSet ) );
+}
+
+BOOL SvStream::WriteLine( const ByteString& rStr )
+{
+ Write( rStr.GetBuffer(), rStr.Len() );
+ endl(*this);
+ return nError == SVSTREAM_OK;
+}
+
+/*************************************************************************
+|*
+|* Stream::WriteLines()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 17.07.95
+|* Letzte Aenderung OV 17.07.95
+|*
+*************************************************************************/
+
+BOOL SvStream::WriteByteStringLines( const String& rStr, rtl_TextEncoding eDestCharSet )
+{
+ return WriteLines( ByteString( rStr, eDestCharSet ) );
+}
+
+BOOL SvStream::WriteLines( const ByteString& rStr )
+{
+ ByteString aStr( rStr );
+ aStr.ConvertLineEnd( eLineDelimiter );
+ Write( aStr.GetBuffer(), aStr.Len() );
+ endl( *this );
+ return (BOOL)(nError == SVSTREAM_OK);
+}
+
+/*************************************************************************
+|*
+|* Stream::SeekRel()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+ULONG SvStream::SeekRel( long nPos )
+{
+ ULONG nActualPos = Tell();
+ nActualPos += nPos;
+ pBufPos = pRWBuf + nActualPos;
+ return Seek( nActualPos );
+}
+
+/*************************************************************************
+|*
+|* Stream::operator>>()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvStream& SvStream::operator >> ( USHORT& r )
+{
+ READNUMBER_WITHOUT_SWAP(USHORT,r)
+ if( bSwap )
+ SwapUShort(r);
+ return *this;
+}
+
+SvStream& SvStream::operator>> ( ULONG& r)
+{
+#if(__SIZEOFLONG != 4)
+ unsigned int tmp = r;
+ READNUMBER_WITHOUT_SWAP(ULONG,tmp)
+ r = tmp;
+ if( bSwap )
+ SwapULong(r);
+#else
+ READNUMBER_WITHOUT_SWAP(ULONG,r)
+ if( bSwap )
+ SwapULong(r);
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator >> ( long& r )
+{
+#if(__SIZEOFLONG != 4)
+ unsigned int tmp = r;
+ READNUMBER_WITHOUT_SWAP(long,tmp)
+ r = tmp;
+ if( bSwap )
+ SwapLong(r);
+#else
+ READNUMBER_WITHOUT_SWAP(long,r)
+ if( bSwap )
+ SwapLong(r);
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator >> ( short& r)
+{
+ READNUMBER_WITHOUT_SWAP(short,r)
+ if( bSwap )
+ SwapShort(r);
+ return *this;
+}
+
+SvStream& SvStream::operator >> ( int& r)
+{
+ READNUMBER_WITHOUT_SWAP(int,r)
+ if( bSwap )
+ {
+#if(__SIZEOFINT == 2)
+ SwapInt(r);
+#else
+ SwapLongInt(r);
+#endif
+ }
+ return *this;
+}
+
+SvStream& SvStream::operator>>( unsigned int& r)
+{
+ READNUMBER_WITHOUT_SWAP(unsigned int,r)
+ if( bSwap )
+ {
+#if(__SIZEOFINT == 2)
+ SwapUInt(r);
+#else
+ SwapLongUInt(r);
+#endif
+ }
+ return *this;
+}
+
+SvStream& SvStream::operator>>( signed char& r)
+{
+ if( (eIOMode == STREAM_IO_READ || !bIsConsistent) &&
+ sizeof(signed char) <= nBufFree )
+ {
+ r = *pBufPos;
+ nBufActualPos += sizeof(signed char);
+ pBufPos += sizeof(signed char);
+ nBufFree -= sizeof(signed char);
+ }
+ else
+ Read( (char*)&r, sizeof(signed char) );
+ return *this;
+}
+
+// Sonderbehandlung fuer Chars wegen PutBack
+
+SvStream& SvStream::operator>>( char& r)
+{
+ if( (eIOMode == STREAM_IO_READ || !bIsConsistent) &&
+ sizeof(char) <= nBufFree )
+ {
+ r = *pBufPos;
+ nBufActualPos += sizeof(char);
+ pBufPos += sizeof(char);
+ nBufFree -= sizeof(char);
+ }
+ else
+ Read( (char*)&r, sizeof(char) );
+ return *this;
+}
+
+SvStream& SvStream::operator>>( unsigned char& r)
+{
+ if( (eIOMode == STREAM_IO_READ || !bIsConsistent) &&
+ sizeof(char) <= nBufFree )
+ {
+ r = *pBufPos;
+ nBufActualPos += sizeof(char);
+ pBufPos += sizeof(char);
+ nBufFree -= sizeof(char);
+ }
+ else
+ Read( (char*)&r, sizeof(char) );
+ return *this;
+}
+
+SvStream& SvStream::operator>>( float& r)
+{
+ // Read( (char*)&r, sizeof(float) );
+ READNUMBER_WITHOUT_SWAP(float,r)
+#ifdef UNX
+ if( bSwap )
+ SwapFloat(r);
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator>>( double& r)
+{
+ // Read( (char*)&r, sizeof(double) );
+ READNUMBER_WITHOUT_SWAP(double,r)
+#if defined( UNX ) || defined ( MAC )
+ if( bSwap )
+ SwapDouble(r);
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator>> ( SvStream& rStream )
+{
+ const ULONG cBufLen = 0x8000;
+ char* pBuf = new char[ cBufLen ];
+
+ ULONG nCount;
+ do {
+ nCount = Read( pBuf, cBufLen );
+ rStream.Write( pBuf, nCount );
+ } while( nCount == cBufLen );
+
+ delete pBuf;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Stream::operator<<()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvStream& SvStream::operator<< ( USHORT v )
+{
+ if( bSwap )
+ SwapUShort(v);
+ WRITENUMBER_WITHOUT_SWAP(USHORT,v)
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( ULONG v)
+{
+#if(__SIZEOFLONG != 4)
+ unsigned int tmp = v;
+ if( bSwap )
+ SwapUInt(tmp);
+ WRITENUMBER_WITHOUT_SWAP(unsigned int,tmp)
+#else
+ if( bSwap )
+ SwapULong(v);
+ WRITENUMBER_WITHOUT_SWAP(ULONG,v)
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( long v )
+{
+#if(__SIZEOFLONG != 4)
+ int tmp = v;
+ if( bSwap )
+ SwapInt(tmp);
+ WRITENUMBER_WITHOUT_SWAP(int,tmp)
+#else
+ if( bSwap )
+ SwapLong(v);
+ WRITENUMBER_WITHOUT_SWAP(long,v)
+#endif
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( short v)
+{
+ if( bSwap )
+ SwapShort(v);
+ WRITENUMBER_WITHOUT_SWAP(short,v)
+ return *this;
+}
+
+SvStream& SvStream::operator<<( int v)
+{
+ if( bSwap )
+ {
+#if( __SIZEOFINT == 2 )
+ SwapInt( v );
+#else
+ SwapLongInt( v );
+#endif
+ }
+ WRITENUMBER_WITHOUT_SWAP(int,v)
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( signed char v)
+{
+ //SDO
+ int tmp = eIOMode;
+ if(tmp == STREAM_IO_WRITE && sizeof(signed char) <= nBufFree )
+ {
+ *pBufPos = v;
+ pBufPos++; // sizeof(char);
+ nBufActualPos++;
+ if( nBufActualPos > nBufActualLen ) // Append ?
+ nBufActualLen = nBufActualPos;
+ nBufFree--; // = sizeof(char);
+ bIsDirty = TRUE;
+ }
+ else
+ Write( (char*)&v, sizeof(signed char) );
+ return *this;
+}
+
+
+SvStream& SvStream::operator<< ( unsigned int v)
+{
+ if( bSwap )
+ {
+#if( __SIZEOFINT == 2 )
+ SwapUInt( v );
+#else
+ SwapLongUInt( v );
+#endif
+ }
+ WRITENUMBER_WITHOUT_SWAP(int,v)
+ return *this;
+}
+
+// Sonderbehandlung fuer chars wegen PutBack
+
+SvStream& SvStream::operator<< ( char v)
+{
+ //SDO
+ int tmp = eIOMode;
+ if(tmp == STREAM_IO_WRITE && sizeof(char) <= nBufFree )
+ {
+ *pBufPos = v;
+ pBufPos++; // sizeof(char);
+ nBufActualPos++;
+ if( nBufActualPos > nBufActualLen ) // Append ?
+ nBufActualLen = nBufActualPos;
+ nBufFree--; // = sizeof(char);
+ bIsDirty = TRUE;
+ }
+ else
+ Write( (char*)&v, sizeof(char) );
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( unsigned char v)
+{
+//SDO
+ int tmp = eIOMode;
+ if(tmp == STREAM_IO_WRITE && sizeof(char) <= nBufFree )
+ {
+ *(unsigned char*)pBufPos = v;
+ pBufPos++; // = sizeof(char);
+ nBufActualPos++; // = sizeof(char);
+ if( nBufActualPos > nBufActualLen ) // Append ?
+ nBufActualLen = nBufActualPos;
+ nBufFree--;
+ bIsDirty = TRUE;
+ }
+ else
+ Write( (char*)&v, sizeof(char) );
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( float v)
+{
+#ifdef UNX
+ if( bSwap )
+ SwapFloat(v);
+#endif
+ WRITENUMBER_WITHOUT_SWAP(float,v)
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( const double& r)
+{
+// Write( (char*)&r, sizeof( double ) );
+#if defined( UNX ) || defined ( MAC )
+ if( bSwap )
+ {
+ double nHelp = r;
+ SwapDouble(nHelp);
+ WRITENUMBER_WITHOUT_SWAP(double,nHelp)
+ return *this;
+ }
+ else
+#endif
+ WRITENUMBER_WITHOUT_SWAP(double,r)
+
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( const char* pBuf )
+{
+ Write( pBuf, strlen( pBuf ) );
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( const unsigned char* pBuf )
+{
+ Write( (char*)pBuf, strlen( (char*)pBuf ) );
+ return *this;
+}
+
+SvStream& SvStream::operator<< ( SvStream& rStream)
+{
+ const ULONG cBufLen = 0x8000;
+ char* pBuf = new char[ cBufLen ];
+ ULONG nCount;
+ do {
+ nCount = rStream.Read( pBuf, cBufLen );
+ Write( pBuf, nCount );
+ } while( nCount == cBufLen );
+
+ delete pBuf;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& SvStream::ReadByteString( UniString& rStr, rtl_TextEncoding eSrcCharSet )
+{
+ // read UTF-16 string directly from stream ?
+ if (eSrcCharSet == RTL_TEXTENCODING_UNICODE)
+ {
+ sal_uInt32 nLen;
+ operator>> (nLen);
+ if (nLen)
+ {
+ sal_Unicode *pStr = rStr.AllocBuffer(nLen);
+ Read( pStr, nLen << 1 );
+
+ if (bSwap)
+ for (sal_Unicode *pEnd = pStr + nLen; pStr < pEnd; pStr++)
+ SwapUShort(*pStr);
+ }
+ else
+ rStr.Erase();
+
+ return *this;
+ }
+
+ ByteString aStr;
+ ReadByteString( aStr );
+ rStr = UniString( aStr, eSrcCharSet );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& SvStream::ReadByteString( ByteString& rStr )
+{
+ USHORT nLen = 0;
+ operator>>( nLen );
+ if( nLen )
+ {
+ char* pTmp = rStr.AllocBuffer( nLen );
+ nLen = (USHORT)Read( pTmp, nLen );
+ }
+ else
+ rStr.Erase();
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& SvStream::WriteByteString( const UniString& rStr, rtl_TextEncoding eDestCharSet )
+{
+ // write UTF-16 string directly into stream ?
+ if (eDestCharSet == RTL_TEXTENCODING_UNICODE)
+ {
+ sal_uInt32 nLen = rStr.Len();
+ operator<< (nLen);
+ if (nLen)
+ {
+ if (bSwap)
+ {
+ const sal_Unicode *pStr = rStr.GetBuffer();
+ const sal_Unicode *pEnd = pStr + nLen;
+
+ for (; pStr < pEnd; pStr++)
+ {
+ sal_Unicode c = *pStr;
+ SwapUShort(c);
+ WRITENUMBER_WITHOUT_SWAP(USHORT,c)
+ }
+ }
+ else
+ Write( rStr.GetBuffer(), nLen << 1 );
+ }
+
+ return *this;
+ }
+
+ return WriteByteString(ByteString( rStr, eDestCharSet ));
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& SvStream::WriteByteString( const ByteString& rStr)
+{
+ USHORT nLen = rStr.Len();
+ operator<< ( nLen );
+ if( nLen != 0 )
+ Write( rStr.GetBuffer(), nLen );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Stream::Read()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+ULONG SvStream::Read( void* pData, ULONG nCount )
+{
+ ULONG nSaveCount = nCount;
+ if( !bIsConsistent )
+ RefreshBuffer();
+
+ if( !pRWBuf )
+ {
+ nCount = GetData( (char*)pData,nCount);
+ if( nCryptMask )
+ EncryptBuffer(pData, nCount);
+ nBufFilePos += nCount;
+ }
+ else
+ {
+ // ist Block komplett im Puffer
+ eIOMode = STREAM_IO_READ;
+ if( nCount <= (ULONG)(nBufActualLen - nBufActualPos ) )
+ {
+ // Ja!
+#ifdef WIN
+ hmemcpy( pData, pBufPos, nCount );
+#else
+ memcpy(pData, pBufPos, (size_t) nCount);
+#endif
+ nBufActualPos += (USHORT)nCount;
+ pBufPos += nCount;
+ nBufFree -= (USHORT)nCount;
+ }
+ else
+ {
+ if( bIsDirty ) // Flushen ?
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer(pRWBuf, nBufActualLen);
+ else
+ PutData( pRWBuf, nBufActualLen );
+ bIsDirty = FALSE;
+ }
+
+ // passt der Datenblock in den Puffer ?
+ if( nCount > nBufSize )
+ {
+ // Nein! Deshalb ohne Umweg ueber den Puffer direkt
+ // in den Zielbereich einlesen
+
+ eIOMode = STREAM_IO_DONTKNOW;
+
+ SeekPos( nBufFilePos + nBufActualPos );
+ nBufActualLen = 0;
+ pBufPos = pRWBuf;
+ nCount = GetData( (char*)pData, nCount );
+ if( nCryptMask )
+ EncryptBuffer(pData, nCount);
+ nBufFilePos += nCount;
+ nBufFilePos += nBufActualPos;
+ nBufActualPos = 0;
+ }
+ else
+ {
+ // Der Datenblock passt komplett in den Puffer. Deshalb
+ // Puffer fuellen und dann die angeforderten Daten in den
+ // Zielbereich kopieren.
+
+ nBufFilePos += nBufActualPos;
+ SeekPos( nBufFilePos );
+
+ // TODO: Typecast vor GetData, USHORT nCountTmp
+ ULONG nCountTmp = GetData( pRWBuf, nBufSize );
+ if( nCryptMask )
+ EncryptBuffer(pRWBuf, nCountTmp);
+ nBufActualLen = (USHORT)nCountTmp;
+ if( nCount > nCountTmp )
+ {
+ nCount = nCountTmp; // zurueckstutzen, Eof siehe unten
+ }
+#ifdef WIN
+ hmemcpy( pData, pRWBuf, nCount );
+#else
+ memcpy( pData, pRWBuf, (size_t)nCount );
+#endif
+ nBufActualPos = (USHORT)nCount;
+ pBufPos = pRWBuf + nCount;
+ }
+ }
+ }
+ bIsEof = FALSE;
+ nBufFree = nBufActualLen - nBufActualPos;
+ if( nCount != nSaveCount && nError != ERRCODE_IO_PENDING )
+ bIsEof = TRUE;
+ if( nCount == nSaveCount && nError == ERRCODE_IO_PENDING )
+ nError = ERRCODE_NONE;
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* Stream::Write()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+ULONG SvStream::Write( const void* pData, ULONG nCount )
+{
+ if( !nCount )
+ return 0;
+ if( !bIsWritable )
+ {
+ SetError( ERRCODE_IO_CANTWRITE );
+ return 0;
+ }
+ if( !bIsConsistent )
+ RefreshBuffer(); // Aenderungen des Puffers durch PutBack loeschen
+
+ if( !pRWBuf )
+ {
+ if( nCryptMask )
+ nCount = CryptAndWriteBuffer( pData, nCount );
+ else
+ nCount = PutData( (char*)pData, nCount );
+ nBufFilePos += nCount;
+ return nCount;
+ }
+
+ eIOMode = STREAM_IO_WRITE;
+ if( nCount <= (ULONG)(nBufSize - nBufActualPos) )
+ {
+#ifdef WIN
+ hmemcpy( pBufPos, pData, nCount );
+#else
+ memcpy( pBufPos, pData, (size_t)nCount );
+#endif
+ nBufActualPos += (USHORT)nCount;
+ // wurde der Puffer erweitert ?
+ if( nBufActualPos > nBufActualLen )
+ nBufActualLen = nBufActualPos;
+
+ pBufPos += nCount;
+ bIsDirty = TRUE;
+ }
+ else
+ {
+ // Flushen ?
+ if( bIsDirty )
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer( pRWBuf, (ULONG)nBufActualLen );
+ else
+ PutData( pRWBuf, nBufActualLen );
+ bIsDirty = FALSE;
+ }
+
+ // passt der Block in den Puffer ?
+ if( nCount > nBufSize )
+ {
+ eIOMode = STREAM_IO_DONTKNOW;
+ nBufFilePos += nBufActualPos;
+ nBufActualLen = 0;
+ nBufActualPos = 0;
+ pBufPos = pRWBuf;
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ nCount = CryptAndWriteBuffer( pData, nCount );
+ else
+ nCount = PutData( (char*)pData, nCount );
+ nBufFilePos += nCount;
+ }
+ else
+ {
+ // Block in Puffer stellen
+#ifdef WIN
+ hmemcpy( pRWBuf, pData, nCount );
+#else
+ memcpy( pRWBuf, pData, (size_t)nCount );
+#endif
+ // Reihenfolge!
+ nBufFilePos += nBufActualPos;
+ nBufActualPos = (USHORT)nCount;
+ pBufPos = pRWBuf + nCount;
+ nBufActualLen = (USHORT)nCount;
+ bIsDirty = TRUE;
+ }
+ }
+ nBufFree = nBufSize - nBufActualPos;
+ return nCount;
+}
+
+
+/*************************************************************************
+|*
+|* Stream::Seek()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+ULONG SvStream::Seek( ULONG nFilePos )
+{
+ eIOMode = STREAM_IO_DONTKNOW;
+
+ bIsEof = FALSE;
+ if( !pRWBuf )
+ {
+ nBufFilePos = SeekPos( nFilePos );
+ DBG_ASSERT(Tell()==nBufFilePos,"Out Of Sync!")
+ return nBufFilePos;
+ }
+
+ // Ist Position im Puffer ?
+ if( nFilePos >= nBufFilePos && nFilePos <= (nBufFilePos + nBufActualLen))
+ {
+ nBufActualPos = (USHORT)(nFilePos - nBufFilePos);
+ pBufPos = pRWBuf + nBufActualPos;
+ // nBufFree korrigieren, damit wir nicht von einem
+ // PutBack (ignoriert den StreamMode) getoetet werden
+ nBufFree = nBufActualLen - nBufActualPos;
+ }
+ else
+ {
+ if( bIsDirty && bIsConsistent)
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer( pRWBuf, nBufActualLen );
+ else
+ PutData( pRWBuf, nBufActualLen );
+ bIsDirty = FALSE;
+ }
+ nBufActualLen = 0;
+ nBufActualPos = 0;
+ pBufPos = pRWBuf;
+ nBufFilePos = SeekPos( nFilePos );
+ }
+#ifdef OV_DEBUG
+ {
+ ULONG nDebugTemp = nBufFilePos + nBufActualPos;
+ DBG_ASSERT(Tell()==nDebugTemp,"Sync?")
+ }
+#endif
+ return nBufFilePos + nBufActualPos;
+}
+
+/*************************************************************************
+|*
+|* Stream::Flush()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::Flush()
+{
+ if( bIsDirty && bIsConsistent )
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer( pRWBuf, (ULONG)nBufActualLen );
+ else
+ if( PutData( pRWBuf, nBufActualLen ) != nBufActualLen )
+ SetError( SVSTREAM_WRITE_ERROR );
+ bIsDirty = FALSE;
+ }
+ if( bIsWritable )
+ FlushData();
+}
+
+
+/*************************************************************************
+|*
+|* Stream::PutBack()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 01.08.94
+|* Letzte Aenderung OV 01.08.94
+|*
+*************************************************************************/
+
+/*
+ 4 Faelle :
+
+ 1. Datenzeiger steht mitten im Puffer (nBufActualPos >= 1)
+ 2. Datenzeiger auf Position 0, Puffer ist voll
+ 3. Datenzeiger auf Position 0, Puffer ist teilweise gefuellt
+ 4. Datenzeiger auf Position 0, Puffer ist leer -> Fehler!
+*/
+
+SvStream& SvStream::PutBack( char aCh )
+{
+ // wenn kein Buffer oder Zurueckscrollen nicht moeglich -> Fehler
+ if( !pRWBuf || !nBufActualLen || ( !nBufActualPos && !nBufFilePos ) )
+ {
+ // 4. Fall
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+
+ // Flush() (Phys. Flushen aber nicht notwendig, deshalb selbst schreiben)
+ if( bIsConsistent && bIsDirty )
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer( pRWBuf, nBufActualLen );
+ else
+ PutData( pRWBuf, nBufActualLen );
+ bIsDirty = FALSE;
+ }
+ bIsConsistent = FALSE; // Puffer enthaelt jetzt TRASH
+ if( nBufActualPos )
+ {
+ // 1. Fall
+ nBufActualPos--;
+ pBufPos--;
+ *pBufPos = aCh;
+ nBufFree++;
+ }
+ else // Puffer muss verschoben werden
+ {
+ // Ist Puffer am Anschlag ?
+ if( nBufSize == nBufActualLen )
+ {
+ // 2. Fall
+ memmove( pRWBuf+1, pRWBuf, nBufSize-1 );
+ // nBufFree behaelt den Wert!
+ }
+ else
+ {
+ // 3. Fall -> Puffer vergroessern
+ memmove( pRWBuf+1, pRWBuf, (USHORT)nBufActualLen );
+ nBufActualLen++;
+ nBufFree++;
+ }
+ nBufFilePos--;
+ *pRWBuf = aCh;
+ }
+ eIOMode = STREAM_IO_DONTKNOW;
+ bIsEof = FALSE;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Stream::EatWhite()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 01.08.94
+|* Letzte Aenderung OV 01.08.94
+|*
+*************************************************************************/
+
+void SvStream::EatWhite()
+{
+ char aCh;
+ Read(&aCh, sizeof(char) );
+ while( !bIsEof && isspace((int)aCh) ) //( aCh == ' ' || aCh == '\t' ) )
+ Read(&aCh, sizeof(char) );
+ if( !bIsEof ) // konnte das letzte Char gelesen werden ?
+ SeekRel( -1L );
+}
+
+/*************************************************************************
+|*
+|* Stream::RefreshBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 01.08.94
+|* Letzte Aenderung OV 01.08.94
+|*
+*************************************************************************/
+
+void SvStream::RefreshBuffer()
+{
+ if( bIsDirty && bIsConsistent )
+ {
+ SeekPos( nBufFilePos );
+ if( nCryptMask )
+ CryptAndWriteBuffer( pRWBuf, (ULONG)nBufActualLen );
+ else
+ PutData( pRWBuf, nBufActualLen );
+ bIsDirty = FALSE;
+ }
+ SeekPos( nBufFilePos );
+ nBufActualLen = (USHORT)GetData( pRWBuf, nBufSize );
+ if( nBufActualLen && nError == ERRCODE_IO_PENDING )
+ nError = ERRCODE_NONE;
+ if( nCryptMask )
+ EncryptBuffer(pRWBuf, (ULONG)nBufActualLen);
+ bIsConsistent = TRUE;
+ eIOMode = STREAM_IO_DONTKNOW;
+}
+
+
+/*************************************************************************
+|*
+|* Stream::CreateFormatString()
+|*
+|* Beschreibung Baut Formatstring zusammen
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::CreateFormatString()
+{
+ aFormatString = '%';
+ nPrintfParams = SPECIAL_PARAM_NONE;
+
+ if( nJustification )
+ {
+ aFormatString += '-';
+ }
+
+ if( nWidth )
+ {
+ if( cFiller != ' ' )
+ aFormatString += '0';
+ aFormatString += '*';
+ nPrintfParams = SPECIAL_PARAM_WIDTH;
+ }
+
+ if( nPrecision )
+ {
+ aFormatString += ".*";
+ if( nWidth )
+ nPrintfParams = SPECIAL_PARAM_BOTH;
+ else
+ nPrintfParams = SPECIAL_PARAM_PRECISION;
+ }
+}
+
+/*************************************************************************
+|*
+|* Stream::ReadNumber()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+#define BUFSIZE_LONG 21 // log( 2 hoch 64 ) + 1
+
+SvStream& SvStream::ReadNumber( long& rLong )
+{
+ EatWhite();
+ if( bIsEof || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ ULONG nFPtr = Tell();
+ char buf[ BUFSIZE_LONG ];
+ memset( buf, 0, BUFSIZE_LONG );
+ ULONG nTemp = Read( buf, BUFSIZE_LONG-1 );
+ if( !nTemp || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ char *pEndPtr;
+ rLong = strtol( buf, &pEndPtr, (int)nRadix );
+ nFPtr += ( (ULONG)pEndPtr - (ULONG)(&(buf[0])) );
+ Seek( nFPtr );
+ bIsEof = FALSE;
+ return *this;
+}
+
+SvStream& SvStream::ReadNumber( ULONG& rULong )
+{
+ EatWhite();
+ if( bIsEof || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ ULONG nFPtr = Tell();
+ char buf[ BUFSIZE_LONG ];
+ memset( buf, 0, BUFSIZE_LONG );
+ ULONG nTemp = Read( buf, BUFSIZE_LONG-1 );
+ if( !nTemp || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ char *pEndPtr;
+ rULong = strtoul( buf, &pEndPtr, (int)nRadix );
+ nFPtr += ( (ULONG)pEndPtr - (ULONG)buf );
+ Seek( nFPtr );
+ bIsEof = FALSE;
+ return *this;
+}
+
+SvStream& SvStream::ReadNumber( double& rDouble )
+{
+ EatWhite();
+ if( bIsEof || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ ULONG nFPtr = Tell();
+ char buf[ BUFSIZE_LONG ];
+ memset( buf, 0, BUFSIZE_LONG );
+ ULONG nTemp = Read( buf, BUFSIZE_LONG-1 );
+ if( !nTemp || nError )
+ {
+ SetError( SVSTREAM_GENERALERROR );
+ return *this;
+ }
+ char *pEndPtr;
+ rDouble = strtod( buf, &pEndPtr );
+ nFPtr += ( (ULONG)pEndPtr - (ULONG)buf );
+ Seek( nFPtr );
+ bIsEof = FALSE;
+ return *this;
+}
+
+
+/*************************************************************************
+|*
+|* Stream::WriteNumber()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvStream& SvStream::WriteNumber( long nLong )
+{
+ char buffer[256+12];
+ char pType[] = "ld"; // Nicht static!
+ if( nRadix == 16 )
+ pType[1] = 'x';
+ else if( nRadix == 8 )
+ pType[1] = 'o';
+ ByteString aFStr( aFormatString);
+ aFStr += pType;
+ int nLen;
+ switch ( nPrintfParams )
+ {
+ case SPECIAL_PARAM_NONE :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nLong );
+ break;
+ case SPECIAL_PARAM_WIDTH :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nWidth, nLong );
+ break;
+ case SPECIAL_PARAM_PRECISION :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nPrecision,nLong);
+ break;
+ default:
+ nLen=sprintf(buffer, aFStr.GetBuffer(),nWidth,nPrecision,nLong);
+ }
+ Write( buffer, (long)nLen );
+ return *this;
+}
+
+SvStream& SvStream::WriteNumber( ULONG nULong )
+{
+ char buffer[256+12];
+ char pType[] = "lu"; // Nicht static!
+ if( nRadix == 16 )
+ pType[1] = 'x';
+ else if( nRadix == 8 )
+ pType[1] = 'o';
+ ByteString aFStr( aFormatString);
+ aFStr += pType;
+ int nLen;
+ switch ( nPrintfParams )
+ {
+ case SPECIAL_PARAM_NONE :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nULong );
+ break;
+ case SPECIAL_PARAM_WIDTH :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nWidth, nULong );
+ break;
+ case SPECIAL_PARAM_PRECISION :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nPrecision,nULong);
+ break;
+ default:
+ nLen=sprintf(buffer,aFStr.GetBuffer(),nWidth,nPrecision,nULong);
+ }
+ Write( buffer, (long)nLen );
+ return *this;
+}
+
+
+SvStream& SvStream::WriteNumber( const double& rDouble )
+{
+ char buffer[256+24];
+ ByteString aFStr( aFormatString);
+ aFStr += "lf";
+ int nLen;
+ switch ( nPrintfParams )
+ {
+ case SPECIAL_PARAM_NONE :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), rDouble );
+ break;
+ case SPECIAL_PARAM_WIDTH :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nWidth, rDouble );
+ break;
+ case SPECIAL_PARAM_PRECISION :
+ nLen = sprintf( buffer, aFStr.GetBuffer(), nPrecision, rDouble);
+ break;
+ default:
+ nLen=sprintf(buffer, aFStr.GetBuffer(),nWidth,nPrecision,rDouble);
+ }
+ Write( buffer, (long)nLen );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Stream::CryptAndWriteBuffer()
+|*
+|* Beschreibung Verschluesseln und Schreiben
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+#define CRYPT_BUFSIZE 1024
+
+ULONG SvStream::CryptAndWriteBuffer( const void* pStart, ULONG nLen)
+{
+ unsigned char* pTemp = new unsigned char[CRYPT_BUFSIZE];
+ unsigned char* pDataPtr = (unsigned char*)pStart;
+ ULONG nCount = 0;
+ ULONG nBufCount;
+ unsigned char nMask = nCryptMask;
+ do
+ {
+ if( nLen >= CRYPT_BUFSIZE )
+ nBufCount = CRYPT_BUFSIZE;
+ else
+ nBufCount = nLen;
+ nLen -= nBufCount;
+ memcpy( pTemp, pDataPtr, (USHORT)nBufCount );
+ // **** Verschluesseln *****
+ for ( USHORT n=0; n < CRYPT_BUFSIZE; n++ )
+ {
+ unsigned char aCh = pTemp[n];
+ aCh ^= nMask;
+ SWAPNIBBLES(aCh)
+ pTemp[n] = aCh;
+ }
+ // *************************
+ nCount += PutData( (char*)pTemp, nBufCount );
+ pDataPtr += nBufCount;
+ }
+ while ( nLen );
+ delete pTemp;
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* Stream::EncryptBuffer()
+|*
+|* Beschreibung Buffer entschluesseln
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+BOOL SvStream::EncryptBuffer(void* pStart, ULONG nLen)
+{
+ unsigned char* pTemp = (unsigned char*)pStart;
+ unsigned char nMask = nCryptMask;
+
+ for ( ULONG n=0; n < nLen; n++, pTemp++ )
+ {
+ unsigned char aCh = *pTemp;
+ SWAPNIBBLES(aCh)
+ aCh ^= nMask;
+ *pTemp = aCh;
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* Stream::SetKey()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+unsigned char implGetCryptMask(const sal_Char* pStr, sal_Int32 nLen, long nVersion)
+{
+ unsigned char nCryptMask = 0;
+
+ if (!nLen)
+ return nCryptMask;
+
+ if( nVersion <= SOFFICE_FILEFORMAT_31 )
+ {
+ while( nLen )
+ {
+ nCryptMask ^= *pStr;
+ pStr++;
+ nLen--;
+ }
+ }
+ else // BugFix #25888#
+ {
+ for( USHORT i = 0; i < nLen; i++ ) {
+ nCryptMask ^= pStr[i];
+ if( nCryptMask & 0x80 ) {
+ nCryptMask <<= 1;
+ nCryptMask++;
+ }
+ else
+ nCryptMask <<= 1;
+ }
+ }
+
+ if( !nCryptMask )
+ nCryptMask = 67;
+
+ return nCryptMask;
+}
+
+void SvStream::SetKey( const ByteString& rKey )
+{
+ aKey = rKey;
+ nCryptMask = implGetCryptMask( aKey.GetBuffer(), aKey.Len(), GetVersion() );
+}
+
+/*************************************************************************
+|*
+|* Stream::SyncSvStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::SyncSvStream( ULONG nNewStreamPos )
+{
+ ClearBuffer();
+ SvStream::nBufFilePos = nNewStreamPos;
+}
+
+/*************************************************************************
+|*
+|* Stream::SyncSysStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+void SvStream::SyncSysStream()
+{
+ Flush();
+ SeekPos( Tell() );
+}
+
+/*************************************************************************
+|*
+|* Stream::SetStreamSize()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+BOOL SvStream::SetStreamSize( ULONG nSize )
+{
+#ifdef DBG_UTIL
+ ULONG nFPos = Tell();
+#endif
+ USHORT nBuf = nBufSize;
+ SetBufferSize( 0 );
+ SetSize( nSize );
+ SetBufferSize( nBuf );
+ DBG_ASSERT(Tell()==nFPos,"SetStreamSize failed")
+ return (BOOL)(nError == 0);
+}
+
+//============================================================================
+
+void SvStream::AddMark( ULONG nPos )
+{
+}
+
+//============================================================================
+
+void SvStream::RemoveMark( ULONG nPos )
+{
+}
+
+/*************************************************************************
+|*
+|* endl()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung TH 13.11.96
+|*
+*************************************************************************/
+
+SvStream& endl( SvStream& rStr )
+{
+ LineEnd eDelim = rStr.GetLineDelimiter();
+ if ( eDelim == LINEEND_CR )
+ rStr << _CR;
+ else if( eDelim == LINEEND_LF )
+ rStr << _LF;
+ else
+ rStr << _CR << _LF;
+ return rStr;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::SvMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+SvMemoryStream::SvMemoryStream( void* pBuffer, ULONG nBufSize,
+ StreamMode eMode )
+{
+ if( eMode & STREAM_WRITE )
+ bIsWritable = TRUE;
+ else
+ bIsWritable = FALSE;
+ nEndOfData = nBufSize;
+ bOwnsData = FALSE;
+ pBuf = (BYTE *) pBuffer;
+ nResize = 0L;
+ nSize = nBufSize;
+ nPos = 0L;
+ SetBufferSize( 0 );
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::SvMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+SvMemoryStream::SvMemoryStream( ULONG nInitSize, ULONG nResizeOffset )
+{
+ bIsWritable = TRUE;
+ bOwnsData = TRUE;
+ nEndOfData = 0L;
+ nResize = nResizeOffset;
+ nPos = 0;
+ pBuf = 0;
+ if( nResize != 0 && nResize < 16 )
+ nResize = 16;
+ if( nInitSize && !AllocateMemory( nInitSize ) )
+ {
+ SetError( SVSTREAM_OUTOFMEMORY );
+ nSize = 0;
+ }
+ else
+ nSize = nInitSize;
+ SetBufferSize( 64 );
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::~SvMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+SvMemoryStream::~SvMemoryStream()
+{
+ if( pBuf )
+ {
+ if( bOwnsData )
+ FreeMemory();
+ else
+ Flush();
+ }
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+USHORT SvMemoryStream::IsA() const
+{
+ return (USHORT)ID_MEMORYSTREAM;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::SetBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+void* SvMemoryStream::SetBuffer( void* pNewBuf, ULONG nCount,
+ BOOL bOwnsDat, ULONG nEOF )
+{
+ void* pResult;
+ SetBufferSize( 0 ); // Buffering in der Basisklasse initialisieren
+ Seek( 0 );
+ if( bOwnsData )
+ {
+ pResult = 0;
+ if( pNewBuf != pBuf )
+ FreeMemory();
+ }
+ else
+ pResult = pBuf;
+
+ pBuf = (BYTE *) pNewBuf;
+ nPos = 0;
+ nSize = nCount;
+ nResize = 0;
+ bOwnsData = bOwnsDat;
+
+ if( nEOF > nCount )
+ nEOF = nCount;
+ nEndOfData = nEOF;
+
+ ResetError();
+
+ DBG_ASSERT( nEndOfData<STREAM_SEEK_TO_END,"Invalid EOF");
+ return pResult;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::GetData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+ULONG SvMemoryStream::GetData( void* pData, ULONG nCount )
+{
+ ULONG nMaxCount = nEndOfData-nPos;
+ if( nCount > nMaxCount )
+ nCount = nMaxCount;
+#ifdef WIN
+ void _huge* pTmp = (void _huge*)((char _huge*)pBuf + nPos);
+ hmemcpy( (void _huge*)pData, pTmp, (long)nCount);
+#else
+ memcpy( pData, pBuf+nPos, (size_t)nCount );
+#endif
+ nPos += nCount;
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+ULONG SvMemoryStream::PutData( const void* pData, ULONG nCount )
+{
+ if( GetError() )
+ return 0L;
+
+ ULONG nMaxCount = nSize-nPos;
+
+ // auf Ueberlauf testen
+ if( nCount > nMaxCount )
+ {
+ if( nResize == 0 )
+ {
+ // soviel wie moeglich rueberschaufeln
+ nCount = nMaxCount;
+ SetError( SVSTREAM_OUTOFMEMORY );
+ }
+ else
+ {
+ long nNewResize;
+ if( nSize && nSize > nResize )
+ nNewResize = nSize;
+ else
+ nNewResize = nResize;
+
+ if( (nCount-nMaxCount) < nResize )
+ {
+ // fehlender Speicher ist kleiner als Resize-Offset,
+ // deshalb um Resize-Offset vergroessern
+ if( !ReAllocateMemory( nNewResize) )
+ {
+ nCount = 0;
+ SetError( SVSTREAM_WRITE_ERROR );
+ }
+ }
+ else
+ {
+ // fehlender Speicher ist groesser als Resize-Offset
+ // deshalb um Differenz+ResizeOffset vergroessern
+ if( !ReAllocateMemory( nCount-nMaxCount+nNewResize ) )
+ {
+ nCount = 0;
+ SetError( SVSTREAM_WRITE_ERROR );
+ }
+ }
+ }
+ }
+ DBG_ASSERT(pBuf,"Possibly Reallocate failed");
+#ifdef WIN
+ void _huge* pTmp = (void _huge*)((char _huge*)pBuf + nPos);
+ hmemcpy( pTmp, (void _huge*)pData,(long)nCount);
+#else
+ memcpy( pBuf+nPos, pData, (size_t)nCount);
+#endif
+
+ nPos += nCount;
+ if( nPos > nEndOfData )
+ nEndOfData = nPos;
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::SeekPos()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+// nEndOfData: Erste Position im Stream, die nicht gelesen werden darf
+// nSize: Groesse des allozierten Speichers
+
+ULONG SvMemoryStream::SeekPos( ULONG nNewPos )
+{
+ if( nNewPos < nEndOfData )
+ nPos = nNewPos;
+ else if( nNewPos == STREAM_SEEK_TO_END )
+ nPos = nEndOfData;
+ else
+ {
+ if( nNewPos >= nSize ) // muss Buffer vergroessert werden ?
+ {
+ if( nResize ) // ist vergroeseern erlaubt ?
+ {
+ long nDiff = (long)(nNewPos - nSize + 1);
+ nDiff += (long)nResize;
+ ReAllocateMemory( nDiff );
+ nPos = nNewPos;
+ nEndOfData = nNewPos;
+ }
+ else // vergroessern ist nicht erlaubt -> ans Ende setzen
+ {
+ // SetError( SVSTREAM_OUTOFMEMORY );
+ nPos = nEndOfData;
+ }
+ }
+ else // gueltigen Bereich innerhalb des Buffers vergroessern
+ {
+ nPos = nNewPos;
+ nEndOfData = nNewPos;
+ }
+ }
+ return nPos;
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::FlushData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+void SvMemoryStream::FlushData()
+{
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::ResetError()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+void SvMemoryStream::ResetError()
+{
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::AllocateMemory()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+BOOL SvMemoryStream::AllocateMemory( ULONG nNewSize )
+{
+ pBuf = (BYTE*)SvMemAlloc( nNewSize, MEM_NOCALLNEWHDL );
+ return( pBuf != 0 );
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::ReAllocateMemory() (Bozo-Algorithmus)
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 20.06.94
+|* Letzte Aenderung OV 20.06.94
+|*
+*************************************************************************/
+
+BOOL SvMemoryStream::ReAllocateMemory( long nDiff )
+{
+ BOOL bRetVal = FALSE;
+ long nTemp = (long)nSize;
+ nTemp += nDiff;
+ ULONG nNewSize = (ULONG)nTemp;
+
+ if( nNewSize )
+ {
+ BYTE* pNewBuf = (BYTE *) SvMemAlloc( nNewSize,MEM_NOCALLNEWHDL );
+
+ if( pNewBuf )
+ {
+ bRetVal = TRUE; // Success!
+ if( nNewSize < nSize ) // Verkleinern ?
+ {
+#ifdef WIN
+ hmemcpy((void _huge*)pNewBuf,(void _huge*)pBuf,(long)nNewSize );
+#else
+ memcpy( pNewBuf, pBuf, (size_t)nNewSize );
+#endif
+ if( nPos > nNewSize )
+ nPos = 0L;
+ if( nEndOfData >= nNewSize )
+ nEndOfData = nNewSize-1L;
+ }
+ else
+ {
+#ifdef WIN
+ hmemcpy( (void _huge*)pNewBuf, (void _huge*)pBuf, (long)nSize );
+#else
+ memcpy( pNewBuf, pBuf, (size_t)nSize );
+#endif
+ }
+
+ FreeMemory();
+
+ pBuf = pNewBuf;
+ nSize = nNewSize;
+ }
+ }
+ else
+ {
+ bRetVal = TRUE;
+ pBuf = 0;
+ nSize = 0;
+ nEndOfData = 0;
+ nPos = 0;
+ }
+
+ return bRetVal;
+}
+
+void SvMemoryStream::FreeMemory()
+{
+ SvMemFree( pBuf );
+}
+
+/*************************************************************************
+|*
+|* SvMemoryStream::SwitchBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 26.07.94
+|* Letzte Aenderung OV 26.07.94
+|*
+*************************************************************************/
+
+void* SvMemoryStream::SwitchBuffer( ULONG nInitSize, ULONG nResizeOffset)
+{
+ Flush();
+ if( !bOwnsData )
+ return 0;
+ Seek( STREAM_SEEK_TO_BEGIN );
+
+ void* pRetVal = pBuf;
+ pBuf = 0;
+ nEndOfData = 0L;
+ nResize = nResizeOffset;
+ nPos = 0;
+
+ if( nResize != 0 && nResize < 16 )
+ nResize = 16;
+
+ ResetError();
+
+ if( nInitSize && !AllocateMemory(nInitSize) )
+ {
+ SetError( SVSTREAM_OUTOFMEMORY );
+ nSize = 0;
+ }
+ else
+ nSize = nInitSize;
+
+ SetBufferSize( 64 );
+ return pRetVal;
+}
+
+void SvMemoryStream::SetSize( ULONG nNewSize )
+{
+ long nDiff = (long)nNewSize - (long)nSize;
+ ReAllocateMemory( nDiff );
+}
+
+// *********************************************************************
+// Mac implementierung (mit Handles) in StrmMac.cxx
+// *********************************************************************
+
+#ifndef MAC
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SvSharedMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+SvSharedMemoryStream::SvSharedMemoryStream( void* pBuffer,ULONG nBufSize,
+ StreamMode eMode ) :
+ SvMemoryStream( (char*)pBuffer, nBufSize, eMode )
+{
+ aHandle = 0;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SvSharedMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+SvSharedMemoryStream::SvSharedMemoryStream( ULONG nInitSize,
+ ULONG nResizeOffset) :
+ SvMemoryStream( (void*)NULL )
+{
+ if( !nInitSize )
+ nInitSize = 1024;
+
+ aHandle = 0;
+ bIsWritable = TRUE;
+ bOwnsData = TRUE;
+ nEndOfData = 0L;
+ nResize = nResizeOffset;
+ nPos = 0;
+ pBuf = 0;
+
+ if( nResize != 0 && nResize < 16 )
+ nResize = 16;
+
+ if( nInitSize && !AllocateMemory( nInitSize ) )
+ {
+ SetError( SVSTREAM_OUTOFMEMORY );
+ nSize = 0;
+ }
+ else
+ nSize = nInitSize;
+
+ SetBufferSize( 64 );
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::~SvSharedMemoryStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+SvSharedMemoryStream::~SvSharedMemoryStream()
+{
+ if( bOwnsData )
+ {
+ FreeMemory();
+ pBuf = 0; // damit der Dtor von SvMemoryStream nicht mehr zuschlaegt
+ }
+ else
+ Flush();
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::GetData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+const void* SvSharedMemoryStream::GetData()
+{
+ Flush();
+ return pBuf;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::operator const char*()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvSharedMemoryStream::operator const void*()
+{
+ Flush();
+ return pBuf;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+USHORT SvSharedMemoryStream::IsA() const
+{
+ return (USHORT)ID_SHAREDMEMORYSTREAM;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SwitchBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung KH 16.06.95
+|* Letzte Aenderung KH 16.06.95
+|*
+*************************************************************************/
+
+void* SvSharedMemoryStream::SwitchBuffer( ULONG nInitSize, ULONG nResize )
+{
+ return (void*)SvMemoryStream::SwitchBuffer(nInitSize, nResize);
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SetBuffer()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung KH 16.06.95
+|* Letzte Aenderung KH 16.06.95
+|*
+*************************************************************************/
+
+void* SvSharedMemoryStream::SetBuffer( void* pBuf, ULONG nSize, BOOL bOwnsData,
+ ULONG nEof)
+{
+ return (void*)SvMemoryStream::SetBuffer((char*)pBuf,nSize,bOwnsData,nEof);
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::GetData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung KH 19.06.95
+|* Letzte Aenderung KH 19.06.95
+|*
+*************************************************************************/
+
+ULONG SvSharedMemoryStream::GetData( void* pData, ULONG nCount )
+{
+ return SvMemoryStream::GetData(pData, nCount);
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung KH 19.06.95
+|* Letzte Aenderung KH 19.06.95
+|*
+*************************************************************************/
+
+ULONG SvSharedMemoryStream::PutData( const void* pData, ULONG nCount )
+{
+ return SvMemoryStream::PutData(pData, nCount);
+}
+
+
+//
+// Speicherverwaltung (Alloc, Free, Realloc, SetHandle)
+// Standardimplementation DOS & UNIX
+//
+
+#if defined(DOS) || defined(UNX)
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SetHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 05.10.95
+|* Letzte Aenderung OV 05.10.95
+|*
+*************************************************************************/
+
+void* SvSharedMemoryStream::SetHandle( void* aHandle, ULONG nSize,
+ BOOL bOwnsData, ULONG nEOF)
+{
+ DBG_ERROR("SvSharedMemoryStream::SetHandle not implemented");
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::AllocateMemory()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::AllocateMemory( ULONG nNewSize )
+{
+ pBuf = new BYTE[ nNewSize ];
+ return( pBuf != 0 );
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::ReAllocateMemory() (Bozo-Algorithmus)
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::ReAllocateMemory( long nDiff )
+{
+ BOOL bRetVal = FALSE;
+ ULONG nNewSize = nSize + nDiff;
+ if( nNewSize )
+ {
+ BYTE* pNewBuf = new BYTE[ nNewSize ];
+ if( pNewBuf )
+ {
+ bRetVal = TRUE; // Success!
+ if( nNewSize < nSize ) // Verkleinern ?
+ {
+ memcpy( pNewBuf, pBuf, (size_t)nNewSize );
+ if( nPos > nNewSize )
+ nPos = 0L;
+ if( nEndOfData >= nNewSize )
+ nEndOfData = nNewSize-1L;
+ }
+ else
+ memcpy( pNewBuf, pBuf, (size_t)nSize );
+
+ FreeMemory();
+
+ pBuf = pNewBuf;
+ nSize = nNewSize;
+ }
+ }
+ else
+ {
+ FreeMemory();
+ bRetVal = TRUE;
+ pBuf = 0;
+ nSize = 0;
+ nPos = 0;
+ nEndOfData = 0;
+ }
+ return bRetVal;
+}
+
+void SvSharedMemoryStream::FreeMemory()
+{
+ delete pBuf;
+}
+
+
+#endif
+
+#endif
+
+TYPEINIT0 ( SvDataCopyStream )
+
+// --------------------
+
+// Diese Methoden muessen fuer die Win16-Version implementiert werden,
+// da sonst der Compiler Aerger macht. (?)
+/*
+TypeId SvDataCopyStream::Type() const
+{
+ return 0;
+}
+
+BOOL SvDataCopyStream::IsA(TypeId aId) const
+{
+ return FALSE;
+}
+*/
+
+void SvDataCopyStream::Assign( const SvDataCopyStream& rHack)
+{
+}
diff --git a/tools/source/stream/strmos2.cxx b/tools/source/stream/strmos2.cxx
new file mode 100644
index 000000000000..7f96a70ba194
--- /dev/null
+++ b/tools/source/stream/strmos2.cxx
@@ -0,0 +1,870 @@
+/*************************************************************************
+ *
+ * $RCSfile: strmos2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <limits.h>
+
+#define INCL_PM
+#define INCL_DOS
+#include <svpm.h>
+#include <bseerr.h>
+
+#include <debug.hxx>
+#include <fsys.hxx>
+#include <stream.hxx>
+#include <fastfsys.hxx>
+
+// -----------------------------------------------------------------------
+
+// --------------
+// - StreamData -
+// --------------
+
+class StreamData
+{
+public:
+ HFILE hFile;
+ BOOL bIsEof;
+
+ StreamData()
+ {
+ hFile = 0;
+ bIsEof = TRUE;
+ }
+};
+
+// -----------------------------------------------------------------------
+
+ULONG GetSvError( APIRET nPMError )
+{
+ static struct { APIRET pm; ULONG sv; } errArr[] =
+ {
+ { ERROR_FILE_NOT_FOUND, SVSTREAM_FILE_NOT_FOUND },
+ { ERROR_PATH_NOT_FOUND, SVSTREAM_PATH_NOT_FOUND },
+ { ERROR_TOO_MANY_OPEN_FILES, SVSTREAM_TOO_MANY_OPEN_FILES },
+ { ERROR_ACCESS_DENIED, SVSTREAM_ACCESS_DENIED },
+ { ERROR_INVALID_ACCESS, SVSTREAM_INVALID_ACCESS },
+ { ERROR_SHARING_VIOLATION, SVSTREAM_SHARING_VIOLATION },
+ { ERROR_SHARING_BUFFER_EXCEEDED,SVSTREAM_SHARE_BUFF_EXCEEDED },
+ { ERROR_CANNOT_MAKE, SVSTREAM_CANNOT_MAKE },
+ { ERROR_INVALID_PARAMETER, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_DRIVE_LOCKED, SVSTREAM_LOCKING_VIOLATION },
+ { ERROR_LOCK_VIOLATION, SVSTREAM_LOCKING_VIOLATION },
+ { ERROR_FILENAME_EXCED_RANGE, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_ATOMIC_LOCK_NOT_SUPPORTED, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_READ_LOCKS_NOT_SUPPORTED, SVSTREAM_INVALID_PARAMETER },
+
+
+ { 0xFFFF, SVSTREAM_GENERALERROR }
+ };
+
+ ULONG nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
+ int i=0;
+ do
+ {
+ if( errArr[i].pm == nPMError )
+ {
+ nRetVal = errArr[i].sv;
+ break;
+ }
+ i++;
+ }
+ while( errArr[i].pm != 0xFFFF );
+ return nRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+
+ SetBufferSize( 8192 );
+ Open( rFileName, nOpenMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 22.11.94
+|* Letzte Aenderung OV 22.11.94
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream()
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+ SetBufferSize( 8192 );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::~SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+SvFileStream::~SvFileStream()
+{
+ Close();
+ if( pInstanceData )
+ delete pInstanceData;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetFileHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetFileHandle() const
+{
+ return (ULONG)pInstanceData->hFile;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+USHORT SvFileStream::IsA() const
+{
+ return ID_FILESTREAM;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetData()
+|*
+|* Beschreibung STREAM.SDW, Prueft nicht Eof; IsEof danach rufbar
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetData( char* pData, ULONG nSize )
+{
+#ifdef DBG_UTIL
+ String aTraceStr( "SvFileStream::GetData(): " );
+ aTraceStr += nSize;
+ aTraceStr += " Bytes from ";
+ aTraceStr += aFilename;
+ DBG_TRACE( aTraceStr );
+#endif
+
+ ULONG nCount = 0L;
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ nResult = DosRead( pInstanceData->hFile,(PVOID)pData,nSize,&nCount );
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ }
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::PutData( const char* pData, ULONG nSize )
+{
+#ifdef DBG_UTIL
+ String aTraceStr( "SvFileStrean::PutData: " );
+ aTraceStr += nSize;
+ aTraceStr += " Bytes to ";
+ aTraceStr += aFilename;
+ DBG_TRACE( aTraceStr );
+#endif
+
+ ULONG nCount = 0L;
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ nResult = DosWrite( pInstanceData->hFile,(PVOID)pData,nSize,&nCount );
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ else if( !nCount )
+ SetError( SVSTREAM_DISK_FULL );
+ }
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SeekPos()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::SeekPos( ULONG nPos )
+{
+ ULONG nNewPos = 0L;
+ if( IsOpen() )
+ {
+ APIRET nResult;
+
+ if( nPos != STREAM_SEEK_TO_END )
+ nResult = DosSetFilePtr( pInstanceData->hFile,(long)nPos,
+ FILE_BEGIN, &nNewPos );
+ else
+ nResult = DosSetFilePtr( pInstanceData->hFile,0L,
+ FILE_END, &nNewPos );
+
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ }
+ else
+ SetError( SVSTREAM_GENERALERROR );
+ return nNewPos;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Tell()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+/*
+ULONG SvFileStream::Tell()
+{
+ ULONG nPos = 0L;
+
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ nResult = DosSetFilePtr(pInstanceData->hFile,0L,FILE_CURRENT,&nPos);
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ }
+ return nPos;
+}
+*/
+
+/*************************************************************************
+|*
+|* SvFileStream::FlushData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::FlushData()
+{
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ nResult = DosResetBuffer(pInstanceData->hFile );
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ }
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::LockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockRange( ULONG nByteOffset, ULONG nBytes )
+{
+ BOOL bRetVal = FALSE;
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ FILELOCK aLockArea, aUnlockArea;
+ aUnlockArea.lOffset = 0L;
+ aUnlockArea.lRange = 0L;
+ aLockArea.lOffset = (long)nByteOffset;
+ aLockArea.lRange = (long)nBytes;
+
+ nResult = DosSetFileLocks(pInstanceData->hFile,
+ &aUnlockArea, &aLockArea,
+ 1000UL, // Zeit in ms bis Abbruch
+ 0L // kein Atomic-Lock
+ );
+
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ else
+ bRetVal = TRUE;
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockRange( ULONG nByteOffset, ULONG nBytes )
+{
+ BOOL bRetVal = FALSE;
+ if( IsOpen() )
+ {
+ APIRET nResult;
+ FILELOCK aLockArea, aUnlockArea;
+ aLockArea.lOffset = 0L;
+ aLockArea.lRange = 0L;
+ aUnlockArea.lOffset = (long)nByteOffset;
+ aUnlockArea.lRange = (long)nBytes;
+
+ nResult = DosSetFileLocks(pInstanceData->hFile,
+ &aUnlockArea, &aLockArea,
+ 1000UL, // Zeit in ms bis Abbruch
+ 0L // kein Atomic-Lock
+ );
+
+ if( nResult )
+ SetError(::GetSvError(nResult) );
+ else
+ bRetVal = TRUE;
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::LockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockFile()
+{
+ BOOL bRetVal = FALSE;
+ if( !nLockCounter )
+ {
+ if( LockRange( 0L, LONG_MAX ) )
+ {
+ nLockCounter = 1;
+ bRetVal = TRUE;
+ }
+ }
+ else
+ {
+ nLockCounter++;
+ bRetVal = TRUE;
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockFile()
+{
+ BOOL bRetVal = FALSE;
+ if( nLockCounter > 0)
+ {
+ if( nLockCounter == 1)
+ {
+ if( UnlockRange( 0L, LONG_MAX ) )
+ {
+ nLockCounter = 0;
+ bRetVal = TRUE;
+ }
+ }
+ else
+ {
+ nLockCounter--;
+ bRetVal = TRUE;
+ }
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Open()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL createLongNameEA ( const PCSZ pszPath, ULONG ulAttributes, const String& aLongName );
+
+void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
+{
+ String aParsedFilename;
+
+ if ( Folder::IsAvailable() && (rFilename.Search("{") < 9) )
+ {
+ String aVirtualPart;
+ String aRealPart;
+ String aVirtualPath;
+ ItemIDPath aVirtualURL;
+ ULONG nDivider = 0;
+
+ String aVirtualString(rFilename);
+
+ for (int x=aVirtualString.Len(); x>0; x--)
+ {
+ if (aVirtualString.Copy(x,1).Compare("}")==COMPARE_EQUAL)
+ {
+ nDivider = x;
+ break;
+ }
+ }
+
+ aVirtualPart = aVirtualString.Copy(0,nDivider+1);
+ aRealPart = aVirtualString.Copy(nDivider+2);
+
+ aVirtualURL = aVirtualPart;
+ aVirtualPath = aVirtualURL.GetHostNotationPath();
+
+ DirEntry aTempDirEntry(aVirtualPath);
+
+ aTempDirEntry += aRealPart;
+
+ aParsedFilename = aTempDirEntry.GetFull();
+ }
+ else
+ {
+ aParsedFilename = rFilename;
+ }
+
+ Close();
+ SvStream::ClearBuffer();
+
+ ULONG nActionTaken;
+ ULONG nOpenAction = 0L;
+ ULONG nShareBits = 0L;
+ ULONG nReadWriteBits = 0L;
+
+ eStreamMode = nOpenMode;
+ eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
+
+ nOpenMode |= STREAM_SHARE_DENYNONE; // definierten Zustand garantieren
+
+ // ********* Zugriffsflags ***********
+ if( nOpenMode & STREAM_SHARE_DENYNONE)
+ nShareBits = OPEN_SHARE_DENYNONE;
+
+ if( nOpenMode & STREAM_SHARE_DENYREAD)
+ nShareBits = OPEN_SHARE_DENYREAD;
+
+ if( nOpenMode & STREAM_SHARE_DENYWRITE)
+ nShareBits = OPEN_SHARE_DENYWRITE;
+
+ if( nOpenMode & STREAM_SHARE_DENYALL)
+ nShareBits = OPEN_SHARE_DENYREADWRITE;
+
+ if( (nOpenMode & STREAM_READ) )
+ {
+ if( nOpenMode & STREAM_WRITE )
+ nReadWriteBits |= OPEN_ACCESS_READWRITE;
+ else
+ {
+ nReadWriteBits |= OPEN_ACCESS_READONLY;
+ nOpenMode |= STREAM_NOCREATE;
+ }
+ }
+ else
+ nReadWriteBits |= OPEN_ACCESS_WRITEONLY;
+
+
+ if( nOpenMode & STREAM_NOCREATE )
+ {
+ // Datei nicht erzeugen
+ nOpenAction = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+ else
+ {
+ // Datei erzeugen, wenn nicht vorhanden
+ nOpenAction = OPEN_ACTION_CREATE_IF_NEW;
+ if( nOpenMode & STREAM_TRUNC )
+ // Auf Nullaenge kuerzen, wenn existiert
+ nOpenAction |= OPEN_ACTION_REPLACE_IF_EXISTS;
+ else
+ // Inhalt der Datei nicht wegwerfen
+ nOpenAction |= OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+
+ //
+ // resolves long FAT names used by OS2
+ //
+ BOOL bIsLongOS2=FALSE;
+ if (Folder::IsAvailable())
+ {
+ DirEntry aDirEntry(rFilename);
+ if (aDirEntry.IsLongNameOnFAT())
+ {
+ // in kurzen Pfad wandeln
+ ItemIDPath aItemIDPath(rFilename);
+ aParsedFilename = aItemIDPath.GetHostNotationPath();
+ bIsLongOS2 = TRUE;
+ }
+ }
+
+ aFilename = aParsedFilename;
+ FSysRedirector::DoRedirect( aFilename );
+
+#ifdef DBG_UTIL
+ String aTraceStr( "SvFileStream::Open(): " );
+ aTraceStr += aFilename;
+ DBG_TRACE( aTraceStr );
+#endif
+
+ APIRET nRet = DosOpen( (const char*)aFilename, &pInstanceData->hFile,
+ &nActionTaken, 0L, FILE_NORMAL, nOpenAction,
+ nReadWriteBits | nShareBits | OPEN_FLAGS_NOINHERIT, 0L);
+
+ if( nRet == ERROR_TOO_MANY_OPEN_FILES )
+ {
+ long nToAdd = 10;
+ ULONG nCurMaxFH;
+ nRet = DosSetRelMaxFH( &nToAdd, &nCurMaxFH );
+ nRet = DosOpen( (const char*)aFilename, &pInstanceData->hFile,
+ &nActionTaken, 0L, FILE_NORMAL, nOpenAction,
+ nReadWriteBits | nShareBits | OPEN_FLAGS_NOINHERIT, 0L);
+ }
+
+ // Bei Fehler pruefen, ob wir lesen duerfen
+ if( nRet==ERROR_ACCESS_DENIED || nRet==ERROR_SHARING_VIOLATION )
+ {
+ nReadWriteBits = OPEN_ACCESS_READONLY;
+ nRet = DosOpen( (const char*)aFilename, &pInstanceData->hFile,
+ &nActionTaken, 0L, FILE_NORMAL, nOpenAction,
+ nReadWriteBits | nShareBits | OPEN_FLAGS_NOINHERIT, 0L);
+ }
+
+ if( nRet )
+ {
+ bIsOpen = FALSE;
+ SetError(::GetSvError(nRet) );
+ }
+ else
+ {
+ bIsOpen = TRUE;
+ pInstanceData->bIsEof = FALSE;
+ if( nReadWriteBits != OPEN_ACCESS_READONLY )
+ bIsWritable = TRUE;
+ }
+
+ if (bIsOpen && bIsLongOS2)
+ {
+ //file schließen, da sonst createLongName u.U. nicht möglich
+ Close();
+
+ // erzeugtem File langen Namen geben
+ DirEntry aDirEntry(rFilename);
+ createLongNameEA((const char*)aFilename, FILE_NORMAL, aDirEntry.GetName());
+
+ // und wieder oeffnen
+ ReOpen();
+ }
+
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ReOpen()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ReOpen()
+{
+ if( !bIsOpen && aFilename.Len() )
+ Open( aFilename, eStreamMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Close()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::Close()
+{
+ if( IsOpen() )
+ {
+#ifdef DBG_UTIL
+ String aTraceStr( "SvFileStream::Close(): " );
+ aTraceStr += aFilename;
+ DBG_TRACE( aTraceStr );
+#endif
+
+ if( nLockCounter )
+ {
+ nLockCounter = 1;
+ UnlockFile();
+ }
+ Flush();
+ DosClose( pInstanceData->hFile );
+ }
+
+ bIsOpen = FALSE;
+ nLockCounter= 0;
+ bIsWritable = FALSE;
+ pInstanceData->bIsEof = TRUE;
+ SvStream::ClearBuffer();
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ResetError()
+|*
+|* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ResetError()
+{
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SetSize()
+|*
+|* Beschreibung
+|* Ersterstellung OV 19.10.95
+|* Letzte Aenderung OV 19.10.95
+|*
+*************************************************************************/
+
+void SvFileStream::SetSize( ULONG nSize )
+{
+ if( IsOpen() )
+ {
+ APIRET nRet = DosSetFileSize( pInstanceData->hFile, nSize );
+ if( nRet )
+ SetError( ::GetSvError( nRet ) );
+ }
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::AllocateMemory()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::AllocateMemory( ULONG nNewSize )
+{
+ DBG_ASSERT(aHandle==0,"Keine Handles unter OS/2");
+ DBG_ASSERT(nNewSize,"Cannot allocate zero Bytes");
+ APIRET nRet = DosAllocSharedMem( (void**)&pBuf, (PSZ)NULL, nNewSize,
+ PAG_READ | PAG_WRITE | PAG_COMMIT |
+ OBJ_GIVEABLE | OBJ_GETTABLE );
+ return( nRet == 0 );
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::ReAllocateMemory() (Bozo-Algorithmus)
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::ReAllocateMemory( long nDiff )
+{
+ DBG_ASSERT(aHandle==0,"Keine Handles unter OS/2");
+ BOOL bRetVal = FALSE;
+ ULONG nNewSize = nSize + nDiff;
+ if( nNewSize )
+ {
+ // neuen Speicher nicht ueber AllocateMemory holen, da wir den
+ // alten Speicher behalten wollen, falls nicht genuegend Platz
+ // fuer den neuen Block da ist
+ char* pNewBuf;
+ APIRET nRet = DosAllocSharedMem( (void**)&pNewBuf,(PSZ)NULL,nNewSize,
+ PAG_READ | PAG_WRITE | PAG_COMMIT |
+ OBJ_GIVEABLE | OBJ_GETTABLE );
+ DBG_ASSERT(!nRet,"DosAllocSharedMem failed");
+
+ if( !nRet )
+ {
+ bRetVal = TRUE; // Success!
+ if( nNewSize < nSize ) // Verkleinern ?
+ {
+ memcpy( pNewBuf, pBuf, (size_t)nNewSize );
+ if( nPos > nNewSize )
+ nPos = 0L;
+ if( nEndOfData >= nNewSize )
+ nEndOfData = nNewSize-1L;
+ }
+ else
+ memcpy( pNewBuf, pBuf, (size_t)nSize );
+
+ FreeMemory(); // den alten Block loeschen ...
+
+ // und den neuen Block in Dienst stellen
+ pBuf = pNewBuf;
+ nSize = nNewSize;
+ }
+ }
+ else
+ {
+ bRetVal = TRUE;
+ FreeMemory();
+ pBuf = 0;
+ nSize = 0;
+ nEndOfData = 0;
+ }
+ return bRetVal;
+}
+
+void SvSharedMemoryStream::FreeMemory()
+{
+ DBG_ASSERT(aHandle==0,"Keine Handles unter OS/2");
+ DosFreeMem( pBuf );
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SetHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 05.10.95
+|* Letzte Aenderung OV 05.10.95
+|*
+*************************************************************************/
+
+void* SvSharedMemoryStream::SetHandle( void*, ULONG,BOOL, ULONG )
+{
+ DBG_ERROR("OS/2 does not support memory handles");
+ // return SetBuffer(aNewHandle, nSize, bOwnsData, nEOF );
+ return 0;
+}
+
+
diff --git a/tools/source/stream/strmsys.cxx b/tools/source/stream/strmsys.cxx
new file mode 100644
index 000000000000..5639174d3fec
--- /dev/null
+++ b/tools/source/stream/strmsys.cxx
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * $RCSfile: strmsys.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#if defined( OS2 )
+#include "strmos2.cxx"
+#elif defined( WNT )
+#include "strmwnt.cxx"
+#elif defined( WIN )
+#include "strmwin.cxx"
+#elif defined( MAC )
+#include "strmmac.cxx"
+#elif defined( UNX )
+#include "strmunx.cxx"
+#else
+#include "strmstd.cxx"
+#endif
diff --git a/tools/source/stream/strmunx.cxx b/tools/source/stream/strmunx.cxx
new file mode 100644
index 000000000000..cab977989456
--- /dev/null
+++ b/tools/source/stream/strmunx.cxx
@@ -0,0 +1,897 @@
+/*************************************************************************
+ *
+ * $RCSfile: strmunx.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h> // fuer getenv()
+
+#include <debug.hxx>
+#include <fsys.hxx>
+#include <stream.hxx>
+
+#include <vos/mutex.hxx>
+#include <osl/thread.h> // osl_getThreadTextEncoding
+
+// class FileBase
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+using namespace osl;
+
+// -----------------------------------------------------------------------
+
+// ----------------
+// - InternalLock -
+// ----------------
+
+class InternalStreamLock;
+DECLARE_LIST( InternalStreamLockList, InternalStreamLock* );
+
+class InternalStreamLock
+{
+ ULONG m_nStartPos;
+ ULONG m_nEndPos;
+ SvFileStream* m_pStream;
+ struct stat m_aStat;
+
+ static InternalStreamLockList LockList;
+#ifndef BOOTSTRAP
+ static NAMESPACE_VOS(OMutex) LockMutex;
+#endif
+
+ InternalStreamLock( ULONG, ULONG, SvFileStream* );
+ ~InternalStreamLock();
+public:
+ static BOOL LockFile( ULONG nStart, ULONG nEnd, SvFileStream* );
+ static void UnlockFile( ULONG nStart, ULONG nEnd, SvFileStream* );
+};
+
+InternalStreamLockList InternalStreamLock::LockList;
+#ifndef BOOTSTRAP
+NAMESPACE_VOS(OMutex) InternalStreamLock::LockMutex;
+#endif
+
+InternalStreamLock::InternalStreamLock(
+ ULONG nStart,
+ ULONG nEnd,
+ SvFileStream* pStream ) :
+ m_nStartPos( nStart ),
+ m_nEndPos( nEnd ),
+ m_pStream( pStream )
+{
+ ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
+ stat( aFileName.GetBuffer(), &m_aStat );
+ LockList.Insert( this, LIST_APPEND );
+#ifdef DEBUG
+ fprintf( stderr, "locked %s", aFileName.GetBuffer() );
+ if( m_nStartPos || m_nEndPos )
+ fprintf(stderr, " [ %d ... %d ]", m_nStartPos, m_nEndPos );
+ fprintf( stderr, "\n" );
+#endif
+}
+
+InternalStreamLock::~InternalStreamLock()
+{
+ LockList.Remove( this );
+#ifdef DEBUG
+ ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
+ fprintf( stderr, "unlocked %s", aFileName.GetBuffer() );
+ if( m_nStartPos || m_nEndPos )
+ fprintf(stderr, " [ %d ... %d ]", m_nStartPos, m_nEndPos );
+ fprintf( stderr, "\n" );
+#endif
+}
+
+BOOL InternalStreamLock::LockFile( ULONG nStart, ULONG nEnd, SvFileStream* pStream )
+{
+#ifndef BOOTSTRAP
+ NAMESPACE_VOS( OGuard ) aGuard( LockMutex );
+#endif
+ ByteString aFileName(pStream->GetFileName(), osl_getThreadTextEncoding());
+ struct stat aStat;
+ if( stat( aFileName.GetBuffer(), &aStat ) )
+ return FALSE;
+
+ if( S_ISDIR( aStat.st_mode ) )
+ return TRUE;
+
+ InternalStreamLock* pLock = NULL;
+ for( int i = 0; i < LockList.Count(); i++ )
+ {
+ pLock = LockList.GetObject( i );
+ if( aStat.st_ino == pLock->m_aStat.st_ino )
+ {
+ BOOL bDenyByOptions = FALSE;
+ StreamMode nLockMode = pLock->m_pStream->GetStreamMode();
+ StreamMode nNewMode = pStream->GetStreamMode();
+
+ if( nLockMode & STREAM_SHARE_DENYALL )
+ bDenyByOptions = TRUE;
+ else if( ( nLockMode & STREAM_SHARE_DENYWRITE ) &&
+ ( nNewMode & STREAM_WRITE ) )
+ bDenyByOptions = TRUE;
+ else if( ( nLockMode & STREAM_SHARE_DENYREAD ) &&
+ ( nNewMode & STREAM_READ ) )
+ bDenyByOptions = TRUE;
+
+ if( bDenyByOptions )
+ {
+ if( pLock->m_nStartPos == 0 && pLock->m_nEndPos == 0 ) // whole file is already locked
+ return FALSE;
+ if( nStart == 0 && nEnd == 0) // cannot lock whole file
+ return FALSE;
+
+ if( ( nStart < pLock->m_nStartPos && nEnd > pLock->m_nStartPos ) ||
+ ( nStart < pLock->m_nEndPos && nEnd > pLock->m_nEndPos ) )
+ return FALSE;
+ }
+ }
+ }
+ pLock = new InternalStreamLock( nStart, nEnd, pStream );
+ return TRUE;
+}
+
+void InternalStreamLock::UnlockFile( ULONG nStart, ULONG nEnd, SvFileStream* pStream )
+{
+#ifndef BOOTSTRAP
+ NAMESPACE_VOS( OGuard ) aGuard( LockMutex );
+#endif
+ InternalStreamLock* pLock = NULL;
+ if( nStart == 0 && nEnd == 0 )
+ {
+ for( int i = 0; i < LockList.Count(); i++ )
+ {
+ if( ( pLock = LockList.GetObject( i ) )->m_pStream == pStream )
+ {
+ delete pLock;
+ i--;
+ }
+ }
+ return;
+ }
+ for( int i = 0; i < LockList.Count(); i++ )
+ {
+ if( ( pLock = LockList.GetObject( i ) )->m_pStream == pStream &&
+ nStart == pLock->m_nStartPos && nEnd == pLock->m_nEndPos )
+ {
+ delete pLock;
+ return;
+ }
+ }
+}
+
+// --------------
+// - StreamData -
+// --------------
+
+class StreamData
+{
+public:
+ int nHandle;
+
+ StreamData() { nHandle = 0; }
+};
+
+// -----------------------------------------------------------------------
+
+static ULONG GetSvError( int nErrno )
+{
+ static struct { int nErr; ULONG sv; } errArr[] =
+ {
+ { 0, SVSTREAM_OK },
+ { EACCES, SVSTREAM_ACCESS_DENIED },
+ { EBADF, SVSTREAM_INVALID_HANDLE },
+#if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined( S390 ) || defined(FREEBSD) || defined(MACOSX)
+ { EDEADLK, SVSTREAM_LOCKING_VIOLATION },
+#else
+ { EDEADLOCK, SVSTREAM_LOCKING_VIOLATION },
+#endif
+ { EINVAL, SVSTREAM_INVALID_PARAMETER },
+ { EMFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
+ { ENFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
+ { ENOENT, SVSTREAM_FILE_NOT_FOUND },
+ { EPERM, SVSTREAM_ACCESS_DENIED },
+ { EROFS, SVSTREAM_ACCESS_DENIED },
+ { EAGAIN, SVSTREAM_LOCKING_VIOLATION },
+ { EISDIR, SVSTREAM_PATH_NOT_FOUND },
+ { ELOOP, SVSTREAM_PATH_NOT_FOUND },
+#if ! defined( RS6000 ) && ! defined( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX)
+ { EMULTIHOP, SVSTREAM_PATH_NOT_FOUND },
+ { ENOLINK, SVSTREAM_PATH_NOT_FOUND },
+#endif
+ { ENOTDIR, SVSTREAM_PATH_NOT_FOUND },
+ { ETXTBSY, SVSTREAM_ACCESS_DENIED },
+ { EEXIST, SVSTREAM_CANNOT_MAKE },
+ { ENOSPC, SVSTREAM_DISK_FULL },
+ { (int)0xFFFF, SVSTREAM_GENERALERROR }
+ };
+
+ ULONG nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
+ int i=0;
+ do
+ {
+ if ( errArr[i].nErr == nErrno )
+ {
+ nRetVal = errArr[i].sv;
+ break;
+ }
+ i++;
+ }
+ while( errArr[i].nErr != 0xFFFF );
+ return nRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 08.06.94
+|* Letzte Aenderung OV 08.06.94
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+
+ SetBufferSize( 1024 );
+ // convert URL to SystemPath, if necessary
+ ::rtl::OUString aFileName, aNormPath;
+ if ( FileBase::getNormalizedPathFromFileURL( rFileName, aNormPath ) == FileBase::E_None )
+ FileBase::getSystemPathFromNormalizedPath( aNormPath, aFileName );
+ else
+ aFileName = rFileName;
+ Open( aFileName, nOpenMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 22.11.94
+|* Letzte Aenderung OV 22.11.94
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream()
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+ SetBufferSize( 1024 );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::~SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 22.11.94
+|* Letzte Aenderung OV 22.11.94
+|*
+*************************************************************************/
+
+SvFileStream::~SvFileStream()
+{
+ Close();
+
+ InternalStreamLock::UnlockFile( 0, 0, this );
+
+ if (pInstanceData)
+ delete pInstanceData;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetFileHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 22.11.94
+|* Letzte Aenderung OV 22.11.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetFileHandle() const
+{
+ return (ULONG)pInstanceData->nHandle;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+USHORT SvFileStream::IsA() const
+{
+ return ID_FILESTREAM;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetData( void* pData, ULONG nSize )
+{
+#ifdef DBG_UTIL
+ ByteString aTraceStr( "SvFileStream::GetData(): " );
+ aTraceStr += nSize;
+ aTraceStr += " Bytes from ";
+ aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
+ DBG_TRACE( aTraceStr.GetBuffer() );
+#endif
+
+ int nRead = 0;
+ if ( IsOpen() )
+ {
+ nRead= read(pInstanceData->nHandle,pData,(unsigned)nSize);
+ if ( nRead == -1 )
+ SetError( ::GetSvError( errno ));
+ }
+ return (ULONG)nRead;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::PutData( const void* pData, ULONG nSize )
+{
+#ifdef DBG_UTIL
+ ByteString aTraceStr( "SvFileStrean::PutData: " );
+ aTraceStr += nSize;
+ aTraceStr += " Bytes to ";
+ aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
+ DBG_TRACE( aTraceStr.GetBuffer() );
+#endif
+
+ int nWrite = 0;
+ if ( IsOpen() )
+ {
+ nWrite= write(pInstanceData->nHandle,pData,(unsigned)nSize);
+ if ( nWrite == -1 )
+ SetError( ::GetSvError( errno ) );
+ else if( !nWrite )
+ SetError( SVSTREAM_DISK_FULL );
+ }
+ return (ULONG)nWrite;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SeekPos()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::SeekPos( ULONG nPos )
+{
+ if ( IsOpen() )
+ {
+ long nNewPos;
+ if ( nPos != STREAM_SEEK_TO_END )
+ nNewPos = lseek( pInstanceData->nHandle, (long)nPos, SEEK_SET );
+ else
+ nNewPos = lseek( pInstanceData->nHandle, 0L, SEEK_END );
+
+ if ( nNewPos == -1 )
+ {
+ SetError( SVSTREAM_SEEK_ERROR );
+ return 0L;
+ }
+ // langsam aber sicherer als return nNewPos
+ return lseek(pInstanceData->nHandle,0L,SEEK_CUR);
+ // return nNewPos;
+ }
+ SetError( SVSTREAM_GENERALERROR );
+ return 0L;
+}
+
+
+/*************************************************************************
+|*
+|* SvFileStream::FlushData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::FlushData()
+{
+// lokal gibt es nicht
+}
+
+static char *pFileLockEnvVar = (char*)1;
+
+/*************************************************************************
+|*
+|* SvFileStream::LockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockRange( ULONG nByteOffset, ULONG nBytes )
+{
+ struct flock aflock;
+ aflock.l_start = nByteOffset;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_len = nBytes;
+
+ int nLockMode = 0;
+
+ if ( ! IsOpen() )
+ return FALSE;
+
+ if ( eStreamMode & STREAM_SHARE_DENYALL )
+ if (bIsWritable)
+ nLockMode = F_WRLCK;
+ else
+ nLockMode = F_RDLCK;
+
+ if ( eStreamMode & STREAM_SHARE_DENYREAD )
+ if (bIsWritable)
+ nLockMode = F_WRLCK;
+ else
+ {
+ SetError(SVSTREAM_LOCKING_VIOLATION);
+ return FALSE;
+ }
+
+ if ( eStreamMode & STREAM_SHARE_DENYWRITE )
+ if (bIsWritable)
+ nLockMode = F_WRLCK;
+ else
+ nLockMode = F_RDLCK;
+
+ if (!nLockMode)
+ return TRUE;
+
+ if( ! InternalStreamLock::LockFile( nByteOffset, nByteOffset+nBytes, this ) )
+ {
+#ifdef DEBUG
+ fprintf( stderr, "InternalLock on %s [ %d ... %d ] failed\n",
+ ByteString(aFilename, osl_getThreadTextEncoding()).GetBuffer(), nByteOffset, nByteOffset+nBytes );
+#endif
+ return FALSE;
+ }
+
+ // HACK: File-Locking nur via Environmentvariable einschalten
+ // um einen Haenger im Zusammenspiel mit einem Linux
+ // NFS-2-Server (kein Lockdaemon) zu verhindern.
+ // File-Locking ?ber NFS ist generell ein Performancekiller.
+ // HR, 22.10.1997 fuer SOLARIS
+ // CP, 30.11.1997 fuer HPUX
+ // ER, 18.12.1997 fuer IRIX
+ // HR, 18.05.1998 Environmentvariable
+
+ if ( pFileLockEnvVar == (char*)1 )
+ pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
+ if ( ! pFileLockEnvVar )
+ return TRUE;
+
+ aflock.l_type = nLockMode;
+ if (fcntl(pInstanceData->nHandle, F_GETLK, &aflock) == -1)
+ {
+ #if ( defined HPUX && defined BAD_UNION )
+ #ifdef DBG_UTIL
+ fprintf( stderr, "***** FCNTL(lock):errno = %d\n", errno );
+ #endif
+ if ( errno == EINVAL || errno == ENOSYS )
+ return TRUE;
+ #endif
+ #if defined SINIX
+ if (errno == EINVAL)
+ return TRUE;
+ #endif
+ #if defined SOLARIS
+ if (errno == ENOSYS)
+ return TRUE;
+ #endif
+ SetError( ::GetSvError( errno ));
+ return FALSE;
+ }
+ if (aflock.l_type != F_UNLCK)
+ {
+ SetError(SVSTREAM_LOCKING_VIOLATION);
+ return FALSE;
+ }
+
+ aflock.l_type = nLockMode;
+ if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) == -1)
+ {
+ SetError( ::GetSvError( errno ));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockRange( ULONG nByteOffset, ULONG nBytes )
+{
+
+ struct flock aflock;
+ aflock.l_type = F_UNLCK;
+ aflock.l_start = nByteOffset;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_len = nBytes;
+
+ if ( ! IsOpen() )
+ return FALSE;
+
+ InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
+
+ if ( ! (eStreamMode &
+ (STREAM_SHARE_DENYALL | STREAM_SHARE_DENYREAD | STREAM_SHARE_DENYWRITE)))
+ return TRUE;
+
+ // wenn File Locking ausgeschaltet, siehe SvFileStream::LockRange
+ if ( ! pFileLockEnvVar )
+ return TRUE;
+
+ if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) != -1)
+ return TRUE;
+
+#if ( defined HPUX && defined BAD_UNION )
+#ifdef DBG_UTIL
+ fprintf( stderr, "***** FCNTL(unlock):errno = %d\n", errno );
+#endif
+ if ( errno == EINVAL || errno == ENOSYS )
+ return TRUE;
+#endif
+#if ( defined SINIX )
+ if (errno == EINVAL)
+ return TRUE;
+#endif
+
+ SetError( ::GetSvError( errno ));
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::LockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockFile()
+{
+ return LockRange( 0UL, 0UL );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockFile()
+{
+ return UnlockRange( 0UL, 0UL );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Open()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
+{
+ int nAccess, nAccessRW;
+ int nMode;
+ int nHandleTmp;
+ struct stat buf;
+ BOOL bStatValid = FALSE;
+
+ Close();
+ errno = 0;
+ eStreamMode = nOpenMode;
+ eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
+
+// !!! NoOp: Ansonsten ToAbs() verwendern
+// !!! DirEntry aDirEntry( rFilename );
+// !!! aFilename = aDirEntry.GetFull();
+ aFilename = rFilename;
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aFilename );
+#endif
+ ByteString aLocalFilename(aFilename, osl_getThreadTextEncoding());
+
+#ifdef DBG_UTIL
+ ByteString aTraceStr( "SvFileStream::Open(): " );
+ aTraceStr += aLocalFilename;
+ DBG_TRACE( aTraceStr.GetBuffer() );
+#endif
+
+ if ( lstat( aLocalFilename.GetBuffer(), &buf ) == 0 )
+ {
+ bStatValid = TRUE;
+ // SvFileStream soll kein Directory oeffnen
+ if( S_ISDIR( buf.st_mode ) )
+ {
+ SetError( ::GetSvError( EISDIR ) );
+ return;
+ }
+ }
+
+
+ if ( !( nOpenMode & STREAM_WRITE ) )
+ nAccessRW = O_RDONLY;
+ else if ( !( nOpenMode & STREAM_READ ) )
+ nAccessRW = O_WRONLY;
+ else
+ nAccessRW = O_RDWR;
+
+ nAccess = 0;
+ // Fix (MDA, 18.01.95): Bei RD_ONLY nicht mit O_CREAT oeffnen
+ // Wichtig auf Read-Only-Dateisystemen (wie CDROM)
+ if ( (!( nOpenMode & STREAM_NOCREATE )) && ( nAccessRW != O_RDONLY ) )
+ nAccess |= O_CREAT;
+ if ( nOpenMode & STREAM_TRUNC )
+ nAccess |= O_TRUNC;
+
+ nMode = S_IREAD | S_IROTH | S_IRGRP;
+ if ( nOpenMode & STREAM_WRITE)
+ {
+ nMode |= (S_IWRITE | S_IWOTH | S_IWGRP);
+
+ if ( nOpenMode & STREAM_COPY_ON_SYMLINK )
+ {
+ if ( bStatValid && S_ISLNK( buf.st_mode ) < 0 )
+ {
+ char *pBuf = new char[ 1024+1 ];
+ if ( readlink( aLocalFilename.GetBuffer(), pBuf, 1024 ) > 0 )
+ {
+ if ( unlink(aLocalFilename.GetBuffer()) == 0 )
+ {
+#ifdef DBG_UTIL
+ fprintf( stderr,
+ "Copying file on symbolic link (%s).\n",
+ aLocalFilename.GetBuffer() );
+#endif
+ String aTmpString( pBuf, osl_getThreadTextEncoding() );
+ const DirEntry aSourceEntry( aTmpString );
+ const DirEntry aTargetEntry( aFilename );
+ FileCopier aFileCopier( aSourceEntry, aTargetEntry );
+ aFileCopier.Execute();
+ }
+ }
+ delete pBuf;
+ }
+ }
+ }
+
+
+ nHandleTmp = open(aLocalFilename.GetBuffer(),nAccessRW|nAccess, nMode );
+
+ if ( nHandleTmp == -1 )
+ {
+ if ( nAccessRW != O_RDONLY )
+ {
+ // auf Lesen runterschalten
+ nAccessRW = O_RDONLY;
+ nAccess = 0;
+ nMode = S_IREAD | S_IROTH | S_IRGRP;
+ nHandleTmp =open( aLocalFilename.GetBuffer(),
+ nAccessRW|nAccess,
+ nMode );
+ }
+ }
+ if ( nHandleTmp != -1 )
+ {
+ pInstanceData->nHandle = nHandleTmp;
+ bIsOpen = TRUE;
+ if ( nAccessRW != O_RDONLY )
+ bIsWritable = TRUE;
+
+ if ( !LockFile() ) // ganze Datei
+ {
+ close( nHandleTmp );
+ bIsOpen = FALSE;
+ bIsWritable = FALSE;
+ pInstanceData->nHandle = 0;
+ }
+ }
+ else
+ SetError( ::GetSvError( errno ) );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ReOpen()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ReOpen()
+{
+ if ( !bIsOpen && aFilename.Len() )
+ Open( aFilename, eStreamMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Close()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::Close()
+{
+ InternalStreamLock::UnlockFile( 0, 0, this );
+
+ if ( IsOpen() )
+ {
+#ifdef DBG_UTIL
+ ByteString aTraceStr( "SvFileStream::Close(): " );
+ aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
+ DBG_TRACE( aTraceStr.GetBuffer() );
+#endif
+
+ Flush();
+ close( pInstanceData->nHandle );
+ pInstanceData->nHandle = 0;
+ }
+
+ bIsOpen = FALSE;
+ bIsWritable = FALSE;
+ SvStream::ClearBuffer();
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ResetError()
+|*
+|* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ResetError()
+{
+ SvStream::ClearError();
+}
+
+
+/*************************************************************************
+|*
+|* SvFileStream::SetSize()
+|*
+|* Beschreibung STREAM.SDW;
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::SetSize (ULONG nSize)
+{
+ if ( IsOpen() )
+ {
+ if ( ftruncate ( pInstanceData->nHandle, (off_t) nSize ) == -1 )
+ SetError ( ::GetSvError( errno ));
+ }
+}
+
+
diff --git a/tools/source/stream/strmwnt.cxx b/tools/source/stream/strmwnt.cxx
new file mode 100644
index 000000000000..3d219a84bfd4
--- /dev/null
+++ b/tools/source/stream/strmwnt.cxx
@@ -0,0 +1,892 @@
+/*************************************************************************
+ *
+ * $RCSfile: strmwnt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+/*
+ Todo: StreamMode <-> AllocateMemory
+*/
+
+#include <string.h>
+#include <limits.h>
+
+#include <svwin.h>
+
+#include <debug.hxx>
+#include <fsys.hxx>
+#include <stream.hxx>
+
+// class FileBase
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+using namespace osl;
+
+// -----------------------------------------------------------------------
+
+// --------------
+// - StreamData -
+// --------------
+
+class StreamData
+{
+public:
+ HANDLE hFile;
+
+ StreamData()
+ {
+ hFile = 0;
+ }
+};
+
+// -----------------------------------------------------------------------
+
+static ULONG GetSvError( DWORD nWntError )
+{
+ static struct { DWORD wnt; ULONG sv; } errArr[] =
+ {
+ { ERROR_SUCCESS, SVSTREAM_OK },
+ { ERROR_ACCESS_DENIED, SVSTREAM_ACCESS_DENIED },
+ { ERROR_ACCOUNT_DISABLED, SVSTREAM_ACCESS_DENIED },
+ { ERROR_ACCOUNT_EXPIRED, SVSTREAM_ACCESS_DENIED },
+ { ERROR_ACCOUNT_RESTRICTION, SVSTREAM_ACCESS_DENIED },
+ { ERROR_ATOMIC_LOCKS_NOT_SUPPORTED, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_BAD_PATHNAME, SVSTREAM_PATH_NOT_FOUND },
+ // Filename too long
+ { ERROR_BUFFER_OVERFLOW, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_DIRECTORY, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_DRIVE_LOCKED, SVSTREAM_LOCKING_VIOLATION },
+ { ERROR_FILE_NOT_FOUND, SVSTREAM_FILE_NOT_FOUND },
+ { ERROR_FILENAME_EXCED_RANGE, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_INVALID_ACCESS, SVSTREAM_INVALID_ACCESS },
+ { ERROR_INVALID_DRIVE, SVSTREAM_PATH_NOT_FOUND },
+ { ERROR_INVALID_HANDLE, SVSTREAM_INVALID_HANDLE },
+ { ERROR_INVALID_NAME, SVSTREAM_PATH_NOT_FOUND },
+ { ERROR_INVALID_PARAMETER, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_IS_SUBST_PATH, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_IS_SUBST_TARGET, SVSTREAM_INVALID_PARAMETER },
+ { ERROR_LOCK_FAILED, SVSTREAM_LOCKING_VIOLATION },
+ { ERROR_LOCK_VIOLATION, SVSTREAM_LOCKING_VIOLATION },
+ { ERROR_NEGATIVE_SEEK, SVSTREAM_SEEK_ERROR },
+ { ERROR_PATH_NOT_FOUND, SVSTREAM_PATH_NOT_FOUND },
+ { ERROR_READ_FAULT, SVSTREAM_READ_ERROR },
+ { ERROR_SEEK, SVSTREAM_SEEK_ERROR },
+ { ERROR_SEEK_ON_DEVICE, SVSTREAM_SEEK_ERROR },
+ { ERROR_SHARING_BUFFER_EXCEEDED,SVSTREAM_SHARE_BUFF_EXCEEDED },
+ { ERROR_SHARING_PAUSED, SVSTREAM_SHARING_VIOLATION },
+ { ERROR_SHARING_VIOLATION, SVSTREAM_SHARING_VIOLATION },
+ { ERROR_TOO_MANY_OPEN_FILES, SVSTREAM_TOO_MANY_OPEN_FILES },
+ { ERROR_WRITE_FAULT, SVSTREAM_WRITE_ERROR },
+ { ERROR_WRITE_PROTECT, SVSTREAM_ACCESS_DENIED },
+ { ERROR_DISK_FULL, SVSTREAM_DISK_FULL },
+
+ { (DWORD)0xFFFFFFFF, SVSTREAM_GENERALERROR }
+ };
+
+ ULONG nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
+ int i=0;
+ do
+ {
+ if( errArr[i].wnt == nWntError )
+ {
+ nRetVal = errArr[i].sv;
+ break;
+ }
+ i++;
+ } while( errArr[i].wnt != (DWORD)0xFFFFFFFF );
+ return nRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 17.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream( const String& rFileName, StreamMode nMode )
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+
+ SetBufferSize( 8192 );
+ // convert URL to SystemPath, if necessary
+ ::rtl::OUString aFileName, aNormPath;
+ if ( FileBase::getNormalizedPathFromFileURL( rFileName, aNormPath ) == FileBase::E_None )
+ FileBase::getSystemPathFromNormalizedPath( aNormPath, aFileName );
+ else
+ aFileName = rFileName;
+ Open( aFileName, nMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 22.11.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+SvFileStream::SvFileStream()
+{
+ bIsOpen = FALSE;
+ nLockCounter = 0;
+ bIsWritable = FALSE;
+ pInstanceData = new StreamData;
+
+ SetBufferSize( 8192 );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::~SvFileStream()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+SvFileStream::~SvFileStream()
+{
+ Close();
+ if (pInstanceData)
+ delete pInstanceData;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetFileHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetFileHandle() const
+{
+ return (ULONG)pInstanceData->hFile;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::IsA()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 14.06.94
+|* Letzte Aenderung OV 14.06.94
+|*
+*************************************************************************/
+
+USHORT SvFileStream::IsA() const
+{
+ return ID_FILESTREAM;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::GetData()
+|*
+|* Beschreibung STREAM.SDW, Prueft nicht Eof; IsEof danach rufbar
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+ULONG SvFileStream::GetData( void* pData, ULONG nSize )
+{
+ DWORD nCount = 0;
+ if( IsOpen() )
+ {
+ BOOL bResult = ReadFile(pInstanceData->hFile,(LPVOID)pData,nSize,&nCount,NULL);
+ if( !bResult )
+ {
+ ULONG nTestError = GetLastError();
+ SetError(::GetSvError( nTestError ) );
+ }
+ }
+ return (DWORD)nCount;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::PutData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+ULONG SvFileStream::PutData( const void* pData, ULONG nSize )
+{
+ DWORD nCount = 0;
+ if( IsOpen() )
+ {
+ if(!WriteFile(pInstanceData->hFile,(LPVOID)pData,nSize,&nCount,NULL))
+ SetError(::GetSvError( GetLastError() ) );
+ }
+ return nCount;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SeekPos()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+ULONG SvFileStream::SeekPos( ULONG nPos )
+{
+ DWORD nNewPos = 0;
+ if( IsOpen() )
+ {
+ if( nPos != STREAM_SEEK_TO_END )
+ // 64-Bit files werden nicht unterstuetzt
+ nNewPos=SetFilePointer(pInstanceData->hFile,nPos,NULL,FILE_BEGIN);
+ else
+ nNewPos=SetFilePointer(pInstanceData->hFile,0L,NULL,FILE_END);
+
+ if( nNewPos == 0xFFFFFFFF )
+ {
+ SetError(::GetSvError( GetLastError() ) );
+ nNewPos = 0L;
+ }
+ }
+ else
+ SetError( SVSTREAM_GENERALERROR );
+ return (ULONG)nNewPos;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Tell()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+/*
+ULONG SvFileStream::Tell()
+{
+ ULONG nPos = 0L;
+
+ if( IsOpen() )
+ {
+ DWORD nPos;
+ nPos = SetFilePointer(pInstanceData->hFile,0L,NULL,FILE_CURRENT);
+ if( nPos = 0xFFFFFFFF )
+ {
+ SetError( ::GetSvError( GetLastError() ) );
+ nPos = 0L;
+ }
+ }
+ return nPos;
+}
+*/
+
+/*************************************************************************
+|*
+|* SvFileStream::FlushData()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+void SvFileStream::FlushData()
+{
+ if( IsOpen() )
+ {
+ if( !FlushFileBuffers(pInstanceData->hFile) )
+ SetError(::GetSvError(GetLastError()));
+ }
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::LockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockRange( ULONG nByteOffset, ULONG nBytes )
+{
+ BOOL bRetVal = FALSE;
+ if( IsOpen() )
+ {
+ bRetVal = ::LockFile(pInstanceData->hFile,nByteOffset,0L,nBytes,0L );
+ if( !bRetVal )
+ SetError(::GetSvError(GetLastError()));
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockRange()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockRange( ULONG nByteOffset, ULONG nBytes )
+{
+ BOOL bRetVal = FALSE;
+ if( IsOpen() )
+ {
+ bRetVal = ::UnlockFile(pInstanceData->hFile,nByteOffset,0L,nBytes,0L );
+ if( !bRetVal )
+ SetError(::GetSvError(GetLastError()));
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::LockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::LockFile()
+{
+ BOOL bRetVal = FALSE;
+ if( !nLockCounter )
+ {
+ if( LockRange( 0L, LONG_MAX ) )
+ {
+ nLockCounter = 1;
+ bRetVal = TRUE;
+ }
+ }
+ else
+ {
+ nLockCounter++;
+ bRetVal = TRUE;
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::UnlockFile()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+BOOL SvFileStream::UnlockFile()
+{
+ BOOL bRetVal = FALSE;
+ if( nLockCounter > 0)
+ {
+ if( nLockCounter == 1)
+ {
+ if( UnlockRange( 0L, LONG_MAX ) )
+ {
+ nLockCounter = 0;
+ bRetVal = TRUE;
+ }
+ }
+ else
+ {
+ nLockCounter--;
+ bRetVal = TRUE;
+ }
+ }
+ return bRetVal;
+}
+
+
+/*************************************************************************
+|*
+|* SvFileStream::Open()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+/*
+ NOCREATE TRUNC NT-Action
+ ----------------------------------------------
+ 0 (Create) 0 OPEN_ALWAYS
+ 0 (Create) 1 CREATE_ALWAYS
+ 1 0 OPEN_EXISTING
+ 1 1 TRUNCATE_EXISTING
+*/
+
+void SvFileStream::Open( const String& rFilename, StreamMode nMode )
+{
+ String aParsedFilename(rFilename);
+
+ SetLastError( ERROR_SUCCESS );
+ Close();
+ SvStream::ClearBuffer();
+
+ eStreamMode = nMode;
+ eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
+
+ // !!! NoOp: Ansonsten ToAbs() verwendern
+ // !!! DirEntry aDirEntry( rFilename );
+ // !!! aFilename = aDirEntry.GetFull();
+ aFilename = aParsedFilename;
+#ifdef BOOTSTRAP
+ ByteString aFileNameA( aFilename, gsl_getSystemTextEncoding());
+#else
+ ByteString aFileNameA( aFilename, osl_getThreadTextEncoding());
+ FSysRedirector::DoRedirect( aFilename );
+#endif
+ SetLastError( ERROR_SUCCESS ); // ggf. durch Redirector geaendert!
+
+ /*
+ #ifdef DBG_UTIL
+ String aTraceStr( "SvFileStream::Open(): " );
+ aTraceStr += aFilename;
+ DBG_TRACE( aTraceStr );
+ #endif
+ */
+
+ DWORD nOpenAction;
+ DWORD nShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ DWORD nAccessMode = 0L;
+ UINT nOldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX );
+
+ if( nMode & STREAM_SHARE_DENYREAD)
+ nShareMode &= ~FILE_SHARE_READ;
+
+ if( nMode & STREAM_SHARE_DENYWRITE)
+ nShareMode &= ~FILE_SHARE_WRITE;
+
+ if( nMode & STREAM_SHARE_DENYALL)
+ nShareMode = 0;
+
+ if( (nMode & STREAM_READ) )
+ nAccessMode |= GENERIC_READ;
+ if( (nMode & STREAM_WRITE) )
+ nAccessMode |= GENERIC_WRITE;
+
+ if( nAccessMode == GENERIC_READ ) // ReadOnly ?
+ nMode |= STREAM_NOCREATE; // wenn ja, nicht erzeugen
+
+ // Zuordnung siehe obige Wahrheitstafel
+ if( !(nMode & STREAM_NOCREATE) )
+ {
+ if( nMode & STREAM_TRUNC )
+ nOpenAction = CREATE_ALWAYS;
+ else
+ nOpenAction = OPEN_ALWAYS;
+ }
+ else
+ {
+ if( nMode & STREAM_TRUNC )
+ nOpenAction = TRUNCATE_EXISTING;
+ else
+ nOpenAction = OPEN_EXISTING;
+ }
+
+ pInstanceData->hFile = CreateFile(
+ aFileNameA.GetBuffer(),
+ nAccessMode,
+ nShareMode,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ nOpenAction,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ (HANDLE) NULL
+ );
+
+ if( pInstanceData->hFile!=INVALID_HANDLE_VALUE && (
+ // Hat Create Always eine existierende Datei ueberschrieben ?
+ GetLastError() == ERROR_ALREADY_EXISTS ||
+ // Hat Open Always eine neue Datei angelegt ?
+ GetLastError() == ERROR_FILE_NOT_FOUND ))
+ {
+ // wenn ja, dann alles OK
+ if( nOpenAction == OPEN_ALWAYS || nOpenAction == CREATE_ALWAYS )
+ SetLastError( ERROR_SUCCESS );
+ }
+
+ // Bei Fehler pruefen, ob wir lesen duerfen
+ if( (pInstanceData->hFile==INVALID_HANDLE_VALUE) &&
+ (nAccessMode & GENERIC_WRITE))
+ {
+ ULONG nErr = ::GetSvError( GetLastError() );
+ if(nErr==SVSTREAM_ACCESS_DENIED || nErr==SVSTREAM_SHARING_VIOLATION)
+ {
+ nMode &= (~STREAM_WRITE);
+ nAccessMode = GENERIC_READ;
+ // OV, 28.1.97: Win32 setzt die Datei auf 0-Laenge, wenn
+ // die Openaction CREATE_ALWAYS ist!!!!
+ nOpenAction = OPEN_EXISTING;
+ SetLastError( ERROR_SUCCESS );
+ pInstanceData->hFile = CreateFile(
+ aFileNameA.GetBuffer(),
+ GENERIC_READ,
+ nShareMode,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ nOpenAction,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ (HANDLE) NULL
+ );
+ if( GetLastError() == ERROR_ALREADY_EXISTS )
+ SetLastError( ERROR_SUCCESS );
+ }
+ }
+
+ if( GetLastError() != ERROR_SUCCESS )
+ {
+ bIsOpen = FALSE;
+ SetError(::GetSvError( GetLastError() ) );
+ }
+ else
+ {
+ bIsOpen = TRUE;
+ // pInstanceData->bIsEof = FALSE;
+ if( nAccessMode & GENERIC_WRITE )
+ bIsWritable = TRUE;
+ }
+ SetErrorMode( nOldErrorMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ReOpen()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ReOpen()
+{
+ if( !bIsOpen && aFilename.Len() )
+ Open( aFilename, eStreamMode );
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::Close()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+void SvFileStream::Close()
+{
+ if( IsOpen() )
+ {
+ if( nLockCounter )
+ {
+ nLockCounter = 1;
+ UnlockFile();
+ }
+ Flush();
+ CloseHandle( pInstanceData->hFile );
+ }
+ bIsOpen = FALSE;
+ nLockCounter= 0;
+ bIsWritable = FALSE;
+ SvStream::ClearBuffer();
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::ResetError()
+|*
+|* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
+|* Ersterstellung OV 15.06.94
+|* Letzte Aenderung OV 15.06.94
+|*
+*************************************************************************/
+
+void SvFileStream::ResetError()
+{
+ SvStream::ClearError();
+}
+
+/*************************************************************************
+|*
+|* SvFileStream::SetSize()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 19.10.95
+|* Letzte Aenderung TPF 15.07.98
+|*
+*************************************************************************/
+
+void SvFileStream::SetSize( ULONG nSize )
+{
+
+ if( IsOpen() )
+ {
+ int bError = FALSE;
+ HANDLE hFile = pInstanceData->hFile;
+ ULONG nOld = SetFilePointer( hFile, 0L, NULL, FILE_CURRENT );
+ if( nOld != 0xffffffff )
+ {
+ if( SetFilePointer(hFile,nSize,NULL,FILE_BEGIN ) != 0xffffffff)
+ {
+ BOOL bSucc = SetEndOfFile( hFile );
+ if( !bSucc )
+ bError = TRUE;
+ }
+ if( SetFilePointer( hFile,nOld,NULL,FILE_BEGIN ) == 0xffffffff)
+ bError = TRUE;
+ }
+ if( bError )
+ SetError(::GetSvError( GetLastError() ) );
+ }
+}
+
+/*************************************************************************
+|*
+|* ImpAlloc()
+|*
+|* Beschreibung Legt SharedMemory an
+|* Ersterstellung OV 28.09.95
+|* Letzte Aenderung OV 28.09.95
+|*
+*************************************************************************/
+
+static BYTE* ImpAlloc( ULONG nSize, HANDLE& rHandle )
+{
+ rHandle = 0;
+ HANDLE aHandle = CreateFileMapping((HANDLE)0xffffffff,
+ (LPSECURITY_ATTRIBUTES)0,PAGE_READWRITE,0,nSize,0);
+ if( !aHandle )
+ return 0;
+ BYTE* pBuf = (BYTE*)MapViewOfFile(aHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ if( !pBuf )
+ {
+ CloseHandle( aHandle );
+ return 0;
+ }
+ rHandle = aHandle;
+ return pBuf;
+}
+
+/*************************************************************************
+|*
+|* ImpFree()
+|*
+|* Beschreibung Gibt SharedMemory frei
+|* Ersterstellung OV 28.09.95
+|* Letzte Aenderung OV 28.09.95
+|*
+*************************************************************************/
+
+static void ImpFree( BYTE* pBuf, HANDLE aHandle )
+{
+ if( pBuf )
+ {
+ UnmapViewOfFile( pBuf );
+ pBuf = 0;
+ }
+ CloseHandle( aHandle );
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::AllocateMemory()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 28.09.95
+|* Letzte Aenderung OV 28.09.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::AllocateMemory( ULONG nNewSize )
+{
+ HANDLE aWNTHandle;
+ pBuf = ImpAlloc( nNewSize, aWNTHandle );
+ if( !pBuf )
+ return FALSE;
+ aHandle = (void*)aWNTHandle;
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::ReAllocateMemory()
+|*
+|* Beschreibung STREAM.SDW (Bozo-Algorithmus)
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+BOOL SvSharedMemoryStream::ReAllocateMemory( long nDiff )
+{
+ BOOL bRetVal = FALSE;
+ ULONG nNewSize = nSize + nDiff;
+ if( nNewSize )
+ {
+ HANDLE aNewHandle;
+ BYTE* pNewBuf = ImpAlloc( nNewSize, aNewHandle );
+ if( pNewBuf )
+ {
+ bRetVal = TRUE; // Success!
+ if( nNewSize < nSize ) // Verkleinern ?
+ {
+ memcpy( pNewBuf, pBuf, (size_t)nNewSize );
+ if( nPos > nNewSize )
+ nPos = 0L;
+ if( nEndOfData >= nNewSize )
+ nEndOfData = nNewSize-1L;
+ }
+ else
+ memcpy( pNewBuf, pBuf, (size_t)nSize );
+
+ ImpFree( pBuf, (HANDLE)aHandle );
+ pBuf = pNewBuf;
+ nSize = nNewSize;
+ aHandle = (void*)aNewHandle;
+ }
+ }
+ else
+ {
+ FreeMemory();
+ bRetVal = TRUE;
+ pBuf = 0;
+ nSize = 0;
+ nEndOfData = 0;
+ nPos = 0;
+ aHandle = 0;
+ }
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::FreeMemory()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung CL 05.05.95
+|* Letzte Aenderung CL 05.05.95
+|*
+*************************************************************************/
+
+void SvSharedMemoryStream::FreeMemory()
+{
+ ImpFree( pBuf, (HANDLE)aHandle );
+ aHandle = 0;
+}
+
+
+/*************************************************************************
+|*
+|* SvSharedMemoryStream::SetHandle()
+|*
+|* Beschreibung STREAM.SDW
+|* Ersterstellung OV 05.10.95
+|* Letzte Aenderung OV 05.10.95
+|*
+*************************************************************************/
+
+
+void* SvSharedMemoryStream::SetHandle( void* aNewHandle, ULONG nSize,
+ BOOL bOwnsData, ULONG nEOF )
+{
+ void* pLocalBuf = MapViewOfFile(aNewHandle,FILE_MAP_ALL_ACCESS,0,0,0);
+ if( !pLocalBuf )
+ {
+ SetError( SVSTREAM_OUTOFMEMORY );
+ return 0;
+ }
+ if( aNewHandle == aHandle )
+ {
+ // den aktuellen Handle temporaer auf Null setzen, damit FreeMemory
+ // (wird u.U. von SetBuffer aufgerufen) nicht den Handle schliesst,
+ // sondern nur die View loescht
+ aHandle = 0;
+ }
+ pLocalBuf = SetBuffer( pLocalBuf, nSize, bOwnsData, nEOF );
+ aHandle = aNewHandle;
+ return pLocalBuf;
+}
+
+
diff --git a/tools/source/stream/vcompat.cxx b/tools/source/stream/vcompat.cxx
new file mode 100644
index 000000000000..2e80897db707
--- /dev/null
+++ b/tools/source/stream/vcompat.cxx
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * $RCSfile: vcompat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _VCOMPAT_CXX
+
+#ifndef _STREAM_HXX
+#include "stream.hxx"
+#endif
+#ifndef _VCOMPAT_HXX
+#include "vcompat.hxx"
+#endif
+
+// -----------------
+// - VersionCompat -
+// -----------------
+
+VersionCompat::VersionCompat( SvStream& rStm, USHORT nStreamMode, USHORT nVersion ) :
+ mpRWStm ( &rStm ),
+ mnStmMode ( nStreamMode ),
+ mnVersion ( nVersion )
+{
+ if( !mpRWStm->GetError() )
+ {
+ if( STREAM_WRITE == mnStmMode )
+ {
+ *mpRWStm << mnVersion;
+ mnTotalSize = ( mnCompatPos = mpRWStm->Tell() ) + 4UL;
+ mpRWStm->SeekRel( 4L );
+ }
+ else
+ {
+ *mpRWStm >> mnVersion;
+ *mpRWStm >> mnTotalSize;
+ mnCompatPos = mpRWStm->Tell();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+VersionCompat::~VersionCompat()
+{
+ if( STREAM_WRITE == mnStmMode )
+ {
+ const UINT32 nEndPos = mpRWStm->Tell();
+
+ mpRWStm->Seek( mnCompatPos );
+ *mpRWStm << ( nEndPos - mnTotalSize );
+ mpRWStm->Seek( nEndPos );
+ }
+ else
+ {
+ const UINT32 nReadSize = mpRWStm->Tell() - mnCompatPos;
+
+ if( mnTotalSize > nReadSize )
+ mpRWStm->SeekRel( mnTotalSize - nReadSize );
+ }
+}
diff --git a/tools/source/string/makefile.mk b/tools/source/string/makefile.mk
new file mode 100644
index 000000000000..a0005f53cec4
--- /dev/null
+++ b/tools/source/string/makefile.mk
@@ -0,0 +1,88 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=str
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/tstring.obj \
+ $(SLO)$/tustring.obj \
+ $(SLO)$/charset.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/tstring.obj \
+ $(OBJ)$/tustring.obj \
+ $(OBJ)$/charset.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/string/strascii.cxx b/tools/source/string/strascii.cxx
new file mode 100644
index 000000000000..9b54b920a2c2
--- /dev/null
+++ b/tools/source/string/strascii.cxx
@@ -0,0 +1,773 @@
+/*************************************************************************
+ *
+ * $RCSfile: strascii.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+static BOOL ImplDbgCheckAsciiStr( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ while ( nLen && *pAsciiStr )
+ {
+ if ( ((unsigned char)*pAsciiStr) > 127 )
+ return FALSE;
+ pAsciiStr++;
+ nLen--;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+// =======================================================================
+
+static void ImplCopyAsciiStr( sal_Unicode* pDest, const sal_Char* pSrc,
+ xub_StrLen nLen )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pSrc, nLen ),
+ "UniString::CopyAsciiStr() - pAsciiStr include characters > 127" );
+
+ while ( nLen )
+ {
+ *pDest = (unsigned char)*pSrc;
+ pDest++;
+ pSrc++;
+ nLen--;
+ }
+}
+
+// =======================================================================
+
+static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 )
+{
+ sal_Int32 nRet;
+ while ( ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) &&
+ *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+ while ( nCount &&
+ ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) &&
+ *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringCompareWithoutZeroAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+ while ( nCount &&
+ ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) )
+ {
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 )
+{
+ sal_Int32 nRet;
+ sal_Unicode c1;
+ sal_Char c2;
+ do
+ {
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ c1 = *pStr1;
+ c2 = *pStr2;
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2));
+ if ( nRet != 0 )
+ break;
+
+ pStr1++;
+ pStr2++;
+ }
+ while ( c2 );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+ sal_Unicode c1;
+ sal_Char c2;
+ do
+ {
+ if ( !nCount )
+ break;
+
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ c1 = *pStr1;
+ c2 = *pStr2;
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2));
+ if ( nRet != 0 )
+ break;
+
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+ while ( c2 );
+
+ return nRet;
+}
+
+// =======================================================================
+
+UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr )
+{
+ DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nLen = ImplStringLen( pAsciiStr );
+
+ UniString aTempStr;
+ if ( nLen )
+ {
+ if ( nLen > STRING_MAXLEN )
+ nLen = STRING_MAXLEN;
+ ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen );
+ }
+ return aTempStr;
+}
+
+// -----------------------------------------------------------------------
+
+UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" );
+
+ // Stringlaenge ermitteln
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pAsciiStr );
+
+ UniString aTempStr;
+
+ if ( nLen )
+ {
+ if ( nLen > STRING_MAXLEN )
+ nLen = STRING_MAXLEN;
+ ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen );
+ }
+ return aTempStr;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::AssignAscii( const sal_Char* pAsciiStr )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nLen = ImplStringLen( pAsciiStr );
+
+ if ( !nLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ else
+ {
+ // Wenn String genauso lang ist, wie der String, dann direkt kopieren
+ if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
+ ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
+ else
+ {
+ // Alte Daten loeschen
+ ImplDeleteData( mpData );
+
+ // Daten initialisieren und String kopieren
+ mpData = ImplAllocData( nLen );
+ ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::AssignAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pAsciiStr );
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ for ( xub_StrLen i = 0; i < nLen; i++ )
+ {
+ if ( !pAsciiStr[i] )
+ {
+ DBG_ERROR( "UniString::AssignAscii() : nLen is wrong" );
+ }
+ }
+ }
+#endif
+
+ if ( !nLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ else
+ {
+ // Wenn String genauso lang ist, wie der String, dann direkt kopieren
+ if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
+ ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
+ else
+ {
+ // Alte Daten loeschen
+ ImplDeleteData( mpData );
+
+ // Daten initialisieren und String kopieren
+ mpData = ImplAllocData( nLen );
+ ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::AppendAscii( const sal_Char* pAsciiStr )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nCopyLen = ImplStringLen( pAsciiStr );
+
+ // Ueberlauf abfangen
+ nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
+
+ // Ist es kein leerer String
+ if ( nCopyLen )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) );
+ ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::AppendAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pAsciiStr );
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ for ( xub_StrLen i = 0; i < nLen; i++ )
+ {
+ if ( !pAsciiStr[i] )
+ {
+ DBG_ERROR( "UniString::AppendAscii() : nLen is wrong" );
+ }
+ }
+ }
+#endif
+
+ // Ueberlauf abfangen
+ xub_StrLen nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
+
+ // Ist es kein leerer String
+ if ( nCopyLen )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) );
+ ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::InsertAscii( const char* pAsciiStr, xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::InsertAscii() - pAsciiStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nCopyLen = ImplStringLen( pAsciiStr );
+
+ // Ueberlauf abfangen
+ nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
+
+ // Ist der einzufuegende String ein Leerstring
+ if ( !nCopyLen )
+ return *this;
+
+ // Index groesser als Laenge
+ if ( nIndex > mpData->mnLen )
+ nIndex = mpData->mnLen;
+
+ // Neue Laenge ermitteln und neuen String anlegen
+ UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( sal_Unicode ) );
+ ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, nCopyLen );
+ memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
+ (mpData->mnLen-nIndex)*sizeof( sal_Unicode ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::ReplaceAscii( xub_StrLen nIndex, xub_StrLen nCount,
+ const sal_Char* pAsciiStr, xub_StrLen nStrLen )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( pAsciiStr, "UniString::ReplaceAscii() - pAsciiStr is NULL" );
+
+ // Wenn Index groessergleich Laenge ist, dann ist es ein Append
+ if ( nIndex >= mpData->mnLen )
+ {
+ AppendAscii( pAsciiStr, nStrLen );
+ return *this;
+ }
+
+ // Ist es eine Zuweisung
+ if ( (nIndex == 0) && (nCount >= mpData->mnLen) )
+ {
+ AssignAscii( pAsciiStr, nStrLen );
+ return *this;
+ }
+
+ // Reicht ein Erase
+ if ( nStrLen == STRING_LEN )
+ nStrLen = ImplStringLen( pAsciiStr );
+ if ( !nStrLen )
+ return Erase( nIndex, nCount );
+
+ // nCount darf nicht ueber das Stringende hinnausgehen
+ if ( (ULONG)nIndex+nCount > mpData->mnLen )
+ nCount = mpData->mnLen-nIndex;
+
+ // Reicht eine zeichenweise Zuweisung
+ if ( nCount == nStrLen )
+ {
+ ImplCopyData( this );
+ ImplCopyAsciiStr( mpData->maStr+nIndex, pAsciiStr, nStrLen );
+ return *this;
+ }
+
+ // Ueberlauf abfangen
+ nStrLen = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen );
+
+ // Neue Daten anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+nStrLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, nStrLen );
+ memcpy( pNewData->maStr+nIndex+nStrLen, mpData->maStr+nIndex+nCount,
+ (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare UniString::CompareToAscii( const sal_Char* pAsciiStr,
+ xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "UniString::CompareToAscii() - pAsciiStr include characters > 127" );
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringCompareAscii( mpData->maStr, pAsciiStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare UniString::CompareIgnoreCaseToAscii( const sal_Char* pAsciiStr,
+ xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "UniString::CompareIgnoreCaseToAscii() - pAsciiStr include characters > 127" );
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringICompareAscii( mpData->maStr, pAsciiStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL UniString::EqualsAscii( const sal_Char* pAsciiStr ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
+
+ return (ImplStringCompareAscii( mpData->maStr, pAsciiStr ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
+
+ return (ImplStringICompareAscii( mpData->maStr, pAsciiStr ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL UniString::EqualsAscii( const sal_Char* pAsciiStr,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (*pAsciiStr == 0);
+
+ return (ImplStringCompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (*pAsciiStr == 0);
+
+ return (ImplStringICompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen UniString::SearchAscii( const sal_Char* pAsciiStr, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "UniString::SearchAscii() - pAsciiStr include characters > 127" );
+
+ xub_StrLen nLen = mpData->mnLen;
+ xub_StrLen nStrLen = ImplStringLen( pAsciiStr );
+
+ // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
+ // hinter dem String liegt, dann wurde der String nicht gefunden
+ if ( !nStrLen || (nIndex >= nLen) )
+ return STRING_NOTFOUND;
+
+ const sal_Unicode* pStr = mpData->maStr;
+ pStr += nIndex;
+
+ if ( nStrLen == 1 )
+ {
+ sal_Unicode cSearch = (unsigned char)*pAsciiStr;
+ while ( nIndex < nLen )
+ {
+ if ( *pStr == cSearch )
+ return nIndex;
+ pStr++;
+ nIndex++;
+ }
+ }
+ else
+ {
+ // Nur innerhalb des Strings suchen
+ while ( (ULONG)nIndex+nStrLen <= nLen )
+ {
+ // Stimmt der String ueberein
+ if ( ImplStringCompareWithoutZeroAscii( pStr, pAsciiStr, nStrLen ) == 0 )
+ return nIndex;
+ pStr++;
+ nIndex++;
+ }
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen UniString::SearchAndReplaceAscii( const sal_Char* pAsciiStr, const UniString& rRepStr,
+ xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "UniString::SearchAndReplaceAscii() - pAsciiStr include characters > 127" );
+
+ xub_StrLen nSPos = SearchAscii( pAsciiStr, nIndex );
+ if ( nSPos != STRING_NOTFOUND )
+ Replace( nSPos, ImplStringLen( pAsciiStr ), rRepStr );
+
+ return nSPos;
+}
+
+// -----------------------------------------------------------------------
+
+void UniString::SearchAndReplaceAllAscii( const sal_Char* pAsciiStr, const UniString& rRepStr )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "UniString::SearchAndReplaceAllAscii() - pAsciiStr include characters > 127" );
+
+ xub_StrLen nCharLen = ImplStringLen( pAsciiStr );
+ xub_StrLen nSPos = SearchAscii( pAsciiStr, 0 );
+ while ( nSPos != STRING_NOTFOUND )
+ {
+ Replace( nSPos, nCharLen, rRepStr );
+ nSPos += rRepStr.Len();
+ nSPos = SearchAscii( pAsciiStr, nSPos );
+ }
+}
+
+// =======================================================================
+
+#ifndef ENABLEUNICODE
+
+ByteString ByteString::CreateFromAscii( const sal_Char* pAsciiStr )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "ByteString::CreateFromAscii() - pAsciiStr include characters > 127" );
+
+ return ByteString( pAsciiStr );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString ByteString::CreateFromAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "ByteString::CreateFromAscii() - pAsciiStr include characters > 127" );
+
+ return ByteString( pAsciiStr, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString& ByteString::AssignAscii( const sal_Char* pAsciiStr )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "ByteString::AssignAscii() - pAsciiStr include characters > 127" );
+
+ return Assign( pAsciiStr );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString& ByteString::AssignAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "ByteString::AssignAscii() - pAsciiStr include characters > 127" );
+
+ return Assign( pAsciiStr, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString& ByteString::AppendAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "ByteString::AppendAscii() - pAsciiStr include characters > 127" );
+
+ return Append( pAsciiStr, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare ByteString::CompareToAscii( const sal_Char* pAsciiStr,
+ xub_StrLen nLen ) const
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
+ "ByteString::CompareToAscii() - pAsciiStr include characters > 127" );
+
+ return CompareTo( pAsciiStr, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::EqualsAscii( const sal_Char* pAsciiStr ) const
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "ByteString::EqualsAscii() - pAsciiStr include characters > 127" );
+
+ return Equals( pAsciiStr );
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen ByteString::SearchAscii( const sal_Char* pAsciiStr, xub_StrLen nIndex ) const
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "ByteString::SearchAscii() - pAsciiStr include characters > 127" );
+
+ return Search( pAsciiStr, nIndex );
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen ByteString::SearchAndReplaceAscii( const sal_Char* pAsciiStr, const ByteString& rRepStr,
+ xub_StrLen nIndex )
+{
+ DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
+ "ByteString::SearchAscii() - pAsciiStr include characters > 127" );
+
+ return SearchAndReplace( pAsciiStr, rRepStr, nIndex );
+}
+
+#endif
diff --git a/tools/source/string/strcvt.cxx b/tools/source/string/strcvt.cxx
new file mode 100644
index 000000000000..cd6e84a918c8
--- /dev/null
+++ b/tools/source/string/strcvt.cxx
@@ -0,0 +1,757 @@
+/*************************************************************************
+ *
+ * $RCSfile: strcvt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// =======================================================================
+
+static ByteStringData* ImplGetStringDataFromUniString( const sal_Unicode* pUniStr, sal_Size nUniLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_ASSERT( (eTextEncoding != 9) &&
+ (eTextEncoding != RTL_TEXTENCODING_DONTKNOW) &&
+ (eTextEncoding != RTL_TEXTENCODING_UCS2) &&
+ (eTextEncoding != RTL_TEXTENCODING_UCS4),
+ "UniString-->ByteString: Wrong TextEncoding" );
+
+ if ( !nUniLen )
+ {
+ ImplIncRefCount( &aImplEmptyStrData );
+ return &aImplEmptyStrData;
+ }
+
+#ifndef NOOLDSTRING
+ if ( eTextEncoding == CHARSET_SYSTEM )
+ eTextEncoding = GetSystemCharSet();
+#endif
+ nCvtFlags |= RTL_UNICODETOTEXT_FLAGS_FLUSH;
+
+ ByteStringData* pData;
+ rtl_TextEncodingInfo aTextEncInfo;
+ rtl_UnicodeToTextConverter hConverter = rtl_createUnicodeToTextConverter( eTextEncoding );
+ sal_uInt32 nInfo;
+ sal_Size nSrcChars;
+ sal_Size nDestBytes;
+ sal_Size nNewLen;
+
+ // get TextEncodingInfo
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ rtl_getTextEncodingInfo( eTextEncoding, &aTextEncInfo );
+
+ // Zuerst konvertieren wir mit der wahrscheinlichen Anzahl
+ // der zu konvertierenden Zeichen
+ nNewLen = nUniLen*aTextEncInfo.AverageCharSize;
+ if ( nNewLen > STRING_MAXLEN )
+ nNewLen = STRING_MAXLEN;
+ pData = ImplAllocData( (xub_StrLen)nNewLen );
+ nDestBytes = rtl_convertUnicodeToText( hConverter, 0,
+ pUniStr, nUniLen,
+ (sal_Char*)pData->maStr, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcChars );
+ // Solange versuchen zu konvertieren, bis der Buffer ausreicht, oder
+ // die maximale Stringlaenge erreicht ist
+ while ( (nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) &&
+ (nNewLen != STRING_MAXLEN) )
+ {
+ rtl_freeMemory( pData );
+
+ // Dann mit der maximalen Anzahl der Zeichen versuchen
+ // und etwas mehr Overhead geben, falls nicht zu konvertierende
+ // Zeichen durch mehrere Ersatzzeichen ersetzt werden
+ sal_Size nNotConvertedChars = nUniLen-nSrcChars;
+ nNewLen = nDestBytes+(nNotConvertedChars*aTextEncInfo.MaximumCharSize)+
+ nNotConvertedChars+4;
+ if ( nNewLen > STRING_MAXLEN )
+ nNewLen = STRING_MAXLEN;
+ pData = ImplAllocData( (xub_StrLen)nNewLen );
+ nDestBytes = rtl_convertUnicodeToText( hConverter, 0,
+ pUniStr, nUniLen,
+ (sal_Char*)pData->maStr, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcChars );
+ }
+
+ // String entsprechend der durch das Konvertieren tatsaechlich
+ // entstehenden Bytes anpassen
+ if ( !nDestBytes )
+ {
+ rtl_freeMemory( pData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ pData = &aImplEmptyStrData;
+ }
+ else if ( nNewLen > nDestBytes+8 )
+ {
+ ByteStringData* pTempData = ImplAllocData( (xub_StrLen)nDestBytes );
+ memcpy( pTempData->maStr, pData->maStr, nDestBytes );
+ rtl_freeMemory( pData );
+ pData = pTempData;
+ }
+ else
+ {
+ pData->mnLen = (xub_StrLen)nDestBytes;
+ pData->maStr[nDestBytes] = '\0';
+ }
+ rtl_destroyUnicodeToTextConverter( hConverter );
+ return pData;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplUpdateStringFromUniString( ByteString* pString,
+ const sal_Unicode* pUniStr, sal_Size nUniLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ ByteStringData* pNewStringData;
+ pNewStringData = ImplGetStringDataFromUniString( pUniStr, nUniLen, eTextEncoding, nCvtFlags );
+ ImplDeleteData( pString->mpData );
+ pString->mpData = pNewStringData;
+}
+
+// =======================================================================
+
+#ifndef ENABLEUNICODE
+void ByteString::InitStringRes( const UniString& rUniStr )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+ DBG_CHKOBJ( &rUniStr, UniString, DbgCheckUniString );
+
+ mpData = ImplGetStringDataFromUniString( rUniStr.mpData->maStr, rUniStr.mpData->mnLen,
+ gsl_getSystemTextEncoding(),
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR |
+ RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 |
+ RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
+ RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE );
+}
+#endif
+
+// =======================================================================
+
+ByteString::ByteString( const UniString& rUniStr, rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+ DBG_CHKOBJ( &rUniStr, UniString, DbgCheckUniString );
+
+ mpData = ImplGetStringDataFromUniString( rUniStr.mpData->maStr, rUniStr.mpData->mnLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString::ByteString( const UniString& rUniStr, xub_StrLen nPos, xub_StrLen nLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+ DBG_CHKOBJ( &rUniStr, UniString, DbgCheckUniString );
+
+ // Stringlaenge ermitteln
+ if ( nPos > rUniStr.mpData->mnLen )
+ nLen = 0;
+ else
+ {
+ // Laenge korrigieren, wenn noetig
+ xub_StrLen nMaxLen = rUniStr.mpData->mnLen-nPos;
+ if ( nLen > nMaxLen )
+ nLen = nMaxLen;
+ }
+
+ mpData = ImplGetStringDataFromUniString( rUniStr.mpData->maStr+nPos, nLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString::ByteString( const sal_Unicode* pUniStr,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+ DBG_ASSERT( pUniStr, "ByteString::ByteString() - pUniStr is NULL" );
+
+ mpData = ImplGetStringDataFromUniString( pUniStr, ImplStringLen( pUniStr ),
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString::ByteString( const sal_Unicode* pUniStr, xub_StrLen nLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+ DBG_ASSERT( pUniStr, "ByteString::ByteString() - pUniStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pUniStr );
+
+ mpData = ImplGetStringDataFromUniString( pUniStr, nLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// =======================================================================
+
+static sal_uChar aImplByteTab[256] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255
+};
+
+// =======================================================================
+
+struct Impl1ByteUnicodeTabData
+{
+ rtl_TextEncoding meTextEncoding;
+ sal_Unicode maUniTab[256];
+ Impl1ByteUnicodeTabData* mpNext;
+};
+
+// -----------------------------------------------------------------------
+
+struct Impl1ByteConvertTabData
+{
+ rtl_TextEncoding meSrcTextEncoding;
+ rtl_TextEncoding meDestTextEncoding;
+ sal_uChar maConvertTab[256];
+ sal_uChar maRepConvertTab[256];
+ Impl1ByteConvertTabData* mpNext;
+};
+
+// =======================================================================
+
+sal_Unicode* ImplGet1ByteUnicodeTab( rtl_TextEncoding eTextEncoding )
+{
+#ifndef BOOTSTRAP
+ TOOLSINDATA* pToolsData = ImplGetToolsInData();
+#else
+ TOOLSINDATA* pToolsData = 0x0;
+#endif
+ Impl1ByteUnicodeTabData* pTab = pToolsData->mpFirstUniTabData;
+
+ while ( pTab )
+ {
+ if ( pTab->meTextEncoding == eTextEncoding )
+ return pTab->maUniTab;
+ pTab = pTab->mpNext;
+ }
+
+ // get TextEncodingInfo
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ rtl_getTextEncodingInfo( eTextEncoding, &aTextEncInfo );
+
+ if ( aTextEncInfo.MaximumCharSize == 1 )
+ {
+ pTab = new Impl1ByteUnicodeTabData;
+ pTab->meTextEncoding = eTextEncoding;
+ pTab->mpNext = pToolsData->mpFirstUniTabData;
+
+ rtl_TextToUnicodeConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ (const sal_Char*)aImplByteTab, 256,
+ pTab->maUniTab, 256,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
+ &nInfo, &nSrcBytes );
+ rtl_destroyTextToUnicodeConverter( hConverter );
+
+ if ( (nSrcBytes != 256) || (nDestChars != 256) )
+ delete pTab;
+ else
+ {
+ pToolsData->mpFirstUniTabData = pTab;
+ return pTab->maUniTab;
+ }
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_uChar* ImplGet1ByteConvertTab( rtl_TextEncoding eSrcTextEncoding,
+ rtl_TextEncoding eDestTextEncoding,
+ BOOL bReplace )
+{
+#ifndef BOOTSTRAP
+ TOOLSINDATA* pToolsData = ImplGetToolsInData();
+#else
+ TOOLSINDATA* pToolsData = 0x0;
+#endif
+ Impl1ByteConvertTabData* pTab = pToolsData->mpFirstConvertTabData;
+
+ while ( pTab )
+ {
+ if ( (pTab->meSrcTextEncoding == eSrcTextEncoding) &&
+ (pTab->meDestTextEncoding == eDestTextEncoding) )
+ {
+ if ( bReplace )
+ return pTab->maRepConvertTab;
+ else
+ return pTab->maConvertTab;
+ }
+ pTab = pTab->mpNext;
+ }
+
+ // get TextEncodingInfo
+ rtl_TextEncodingInfo aTextEncInfo1;
+ aTextEncInfo1.StructSize = sizeof( aTextEncInfo1 );
+ rtl_getTextEncodingInfo( eSrcTextEncoding, &aTextEncInfo1 );
+ rtl_TextEncodingInfo aTextEncInfo2;
+ aTextEncInfo2.StructSize = sizeof( aTextEncInfo2 );
+ rtl_getTextEncodingInfo( eDestTextEncoding, &aTextEncInfo2 );
+
+ if ( (aTextEncInfo1.MaximumCharSize == 1) &&
+ (aTextEncInfo2.MaximumCharSize == 1) )
+ {
+ pTab = new Impl1ByteConvertTabData;
+ pTab->meSrcTextEncoding = eSrcTextEncoding;
+ pTab->meDestTextEncoding = eDestTextEncoding;
+ pTab->mpNext = pToolsData->mpFirstConvertTabData;
+
+ rtl_TextToUnicodeConverter hConverter;
+ rtl_UnicodeToTextConverter hConverter2;
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ sal_Size nSrcChars;
+ sal_Size nDestBytes;
+ sal_Unicode aTempBuf[256];
+ hConverter = rtl_createTextToUnicodeConverter( eSrcTextEncoding );
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ (const sal_Char*)aImplByteTab, 256,
+ aTempBuf, 256,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
+ &nInfo, &nSrcBytes );
+ rtl_destroyTextToUnicodeConverter( hConverter );
+ if ( (nSrcBytes != 256) || (nDestChars != 256) )
+ delete pTab;
+ else
+ {
+ hConverter2 = rtl_createUnicodeToTextConverter( eDestTextEncoding );
+ nDestBytes = rtl_convertUnicodeToText( hConverter2, 0,
+ aTempBuf, 256,
+ (sal_Char*)pTab->maConvertTab, 256,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_0 |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT,
+ &nInfo, &nSrcChars );
+ if ( (nDestBytes == 256) || (nSrcChars == 256) )
+ {
+ nDestBytes = rtl_convertUnicodeToText( hConverter2, 0,
+ aTempBuf, 256,
+ (sal_Char*)pTab->maRepConvertTab, 256,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE,
+ &nInfo, &nSrcChars );
+ }
+ rtl_destroyUnicodeToTextConverter( hConverter2 );
+ if ( (nDestBytes != 256) || (nSrcChars != 256) )
+ delete pTab;
+ else
+ {
+ pToolsData->mpFirstConvertTabData = pTab;
+ if ( bReplace )
+ return pTab->maRepConvertTab;
+ else
+ return pTab->maConvertTab;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// =======================================================================
+
+void ImplDeleteCharTabData()
+{
+#ifndef BOOTSTRAP
+ TOOLSINDATA* pToolsData = ImplGetToolsInData();
+#else
+ TOOLSINDATA* pToolsData = 0x0;
+#endif
+ Impl1ByteUnicodeTabData* pTempUniTab;
+ Impl1ByteUnicodeTabData* pUniTab = pToolsData->mpFirstUniTabData;
+ while ( pUniTab )
+ {
+ pTempUniTab = pUniTab->mpNext;
+ delete pUniTab;
+ pUniTab = pTempUniTab;
+ }
+ pToolsData->mpFirstUniTabData = NULL;
+
+ Impl1ByteConvertTabData* pTempConvertTab;
+ Impl1ByteConvertTabData* pConvertTab = pToolsData->mpFirstConvertTabData;
+ while ( pConvertTab )
+ {
+ pTempConvertTab = pConvertTab->mpNext;
+ delete pConvertTab;
+ pConvertTab = pTempConvertTab;
+ }
+ pToolsData->mpFirstConvertTabData = NULL;
+}
+
+// =======================================================================
+
+static void ImplStringConvert( ByteString* pString,
+ rtl_TextEncoding eSource, rtl_TextEncoding eTarget,
+ BOOL bReplace )
+{
+ sal_uChar* pConvertTab = ImplGet1ByteConvertTab( eSource, eTarget, bReplace );
+ if ( pConvertTab )
+ {
+ char* pStr = pString->mpData->maStr;
+ while ( *pStr )
+ {
+ sal_uChar c = (sal_uChar)*pStr;
+ sal_uChar cConv = pConvertTab[c];
+ if ( c != cConv )
+ {
+ pStr = ImplCopyStringData( pString, pStr );
+ *pStr = (char)cConv;
+ }
+
+ pStr++;
+ }
+ }
+ else
+ {
+ rtl_UnicodeToTextConverter hSrcConverter = rtl_createTextToUnicodeConverter( eSource );
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ sal_Size nTempLen;
+ sal_Unicode* pTempBuf;
+ nTempLen = pString->mpData->mnLen;
+ pTempBuf = new sal_Unicode[nTempLen];
+ nDestChars = rtl_convertTextToUnicode( hSrcConverter, 0,
+ pString->mpData->maStr, pString->mpData->mnLen,
+ pTempBuf, nTempLen,
+ RTL_TEXTTOUNICODE_FLAGS_FLUSH |
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
+ &nInfo, &nSrcBytes );
+ rtl_destroyTextToUnicodeConverter( hSrcConverter );
+ // Hier werten wir bReplace nicht aus, da fuer MultiByte-Textencodings
+ // sowieso keine Ersatzdarstellung moeglich ist. Da sich der String
+ // sowieso in der Laenge aendern kann, nehmen wir auch sonst keine
+ // Ruecksicht darauf, das die Laenge erhalten bleibt.
+ ImplUpdateStringFromUniString( pString, pTempBuf, nDestChars, eTarget,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR |
+ RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 |
+ RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
+ RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE );
+ delete pTempBuf;
+ }
+}
+
+// =======================================================================
+
+ByteString& ByteString::Convert( rtl_TextEncoding eSource, rtl_TextEncoding eTarget, BOOL bReplace )
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ // rtl_TextEncoding Dontknow kann nicht konvertiert werden
+ if ( (eSource == RTL_TEXTENCODING_DONTKNOW) || (eTarget == RTL_TEXTENCODING_DONTKNOW) )
+ return *this;
+
+#ifndef NOOLDSTRING
+ if ( eSource == CHARSET_SYSTEM )
+ eSource = GetSystemCharSet();
+ if ( eTarget == CHARSET_SYSTEM )
+ eTarget = GetSystemCharSet();
+#endif
+
+ // Wenn Source und Target gleich sind, muss nicht konvertiert werden
+ if ( eSource == eTarget )
+ return *this;
+
+ // rtl_TextEncoding Symbol nur nach Unicode oder von Unicode wandeln, ansonsten
+ // wollen wir die Zeichencodes beibehalten
+ if ( (eSource == RTL_TEXTENCODING_SYMBOL) &&
+ (eTarget != RTL_TEXTENCODING_UTF7) &&
+ (eTarget != RTL_TEXTENCODING_UTF8) )
+ return *this;
+ if ( (eTarget == RTL_TEXTENCODING_SYMBOL) &&
+ (eSource != RTL_TEXTENCODING_UTF7) &&
+ (eSource != RTL_TEXTENCODING_UTF8) )
+ return *this;
+
+ // Zeichensatz umwandeln
+ ImplStringConvert( this, eSource, eTarget, bReplace );
+
+ return *this;
+}
+
+// =======================================================================
+
+char ByteString::Convert( char c,
+ rtl_TextEncoding eSource, rtl_TextEncoding eTarget,
+ BOOL bReplace )
+{
+ // TextEncoding Dontknow kann nicht konvertiert werden
+ if ( (eSource == RTL_TEXTENCODING_DONTKNOW) || (eTarget == RTL_TEXTENCODING_DONTKNOW) )
+ return '\0';
+
+#ifndef NOOLDSTRING
+ if ( eSource == CHARSET_SYSTEM )
+ eSource = GetSystemCharSet();
+ if ( eTarget == CHARSET_SYSTEM )
+ eTarget = GetSystemCharSet();
+#endif
+
+ // Wenn Source und Target gleich sind, muss nicht konvertiert werden
+ if ( eSource == eTarget )
+ return c;
+
+ // TextEncoding Symbol nur nach Unicode oder von Unicode wandeln, ansonsten
+ // wollen wir die Zeichencodes beibehalten
+ if ( (eSource == RTL_TEXTENCODING_SYMBOL) &&
+ (eTarget != RTL_TEXTENCODING_UTF7) &&
+ (eTarget != RTL_TEXTENCODING_UTF8) )
+ return '\0';
+ if ( (eTarget == RTL_TEXTENCODING_SYMBOL) &&
+ (eSource != RTL_TEXTENCODING_UTF7) &&
+ (eSource != RTL_TEXTENCODING_UTF8) )
+ return '\0';
+
+ sal_uChar* pConvertTab = ImplGet1ByteConvertTab( eSource, eTarget, bReplace );
+ if ( pConvertTab )
+ return (char)pConvertTab[(sal_uChar)c];
+ else
+ return '\0';
+}
+
+// =======================================================================
+
+sal_Unicode ByteString::ConvertToUnicode( char c, rtl_TextEncoding eTextEncoding )
+{
+ sal_Size nLen = 1;
+ return ConvertToUnicode( &c, &nLen, eTextEncoding );
+}
+
+// -----------------------------------------------------------------------
+
+char ByteString::ConvertFromUnicode( sal_Unicode c, rtl_TextEncoding eTextEncoding, BOOL bReplace )
+{
+ sal_Size nLen;
+ char aBuf[30];
+ nLen = ConvertFromUnicode( c, aBuf, sizeof( aBuf ), eTextEncoding, bReplace );
+ if ( nLen == 1 )
+ return aBuf[0];
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Unicode ByteString::ConvertToUnicode( const char* pChar, sal_Size* pLen, rtl_TextEncoding eTextEncoding )
+{
+ // TextEncoding Dontknow wird nicht konvertiert
+ if ( eTextEncoding == RTL_TEXTENCODING_DONTKNOW )
+ return 0;
+#ifndef NOOLDSTRING
+ else if ( eTextEncoding == CHARSET_SYSTEM )
+ eTextEncoding = GetSystemCharSet();
+#endif
+
+ rtl_TextToUnicodeConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ sal_Unicode nConvChar;
+ hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ (const sal_Char*)pChar, *pLen,
+ &nConvChar, 1,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_FLUSH,
+ &nInfo, &nSrcBytes );
+ rtl_destroyTextToUnicodeConverter( hConverter );
+
+ if ( nDestChars == 1 )
+ {
+ *pLen = nSrcBytes;
+ return nConvChar;
+ }
+ else
+ {
+ *pLen = 0;
+ return 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Size ByteString::ConvertFromUnicode( sal_Unicode c, char* pBuf, sal_Size nBufLen, rtl_TextEncoding eTextEncoding,
+ BOOL bReplace )
+{
+ // TextEncoding Dontknow wird nicht konvertiert
+ if ( eTextEncoding == RTL_TEXTENCODING_DONTKNOW )
+ return '\0';
+#ifndef NOOLDSTRING
+ else if ( eTextEncoding == CHARSET_SYSTEM )
+ eTextEncoding = GetSystemCharSet();
+#endif
+
+ rtl_UnicodeToTextConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcChars;
+ sal_Size nDestBytes;
+ sal_Unicode cUni = c;
+ sal_uInt32 nFlags = RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
+ RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
+ RTL_UNICODETOTEXT_FLAGS_FLUSH;
+ if ( bReplace )
+ {
+ nFlags |= RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT;
+ nFlags |= RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
+ if ( nBufLen > 1 )
+ nFlags |= RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR;
+ }
+ else
+ {
+ nFlags |= RTL_UNICODETOTEXT_FLAGS_UNDEFINED_0 |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_0;
+ }
+
+ hConverter = rtl_createUnicodeToTextConverter( eTextEncoding );
+ nDestBytes = rtl_convertUnicodeToText( hConverter, 0,
+ &cUni, 1,
+ (sal_Char*)pBuf, nBufLen,
+ nFlags,
+ &nInfo, &nSrcChars );
+ rtl_destroyUnicodeToTextConverter( hConverter );
+ return nDestBytes;
+}
+
+// =======================================================================
+
+ByteString::ByteString( const NAMESPACE_RTL(OString)& rStr )
+{
+ DBG_CTOR( ByteString, DbgCheckByteString );
+
+ mpData = (ByteStringData*)rStr.pData;
+ ImplIncRefCount( mpData );
+}
+
+// -----------------------------------------------------------------------
+
+NAMESPACE_RTL(OString)::OString( const ByteString& rStr )
+{
+ pData = (rtl_String*)rStr.mpData;
+ rtl_string_acquire( pData );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString& ByteString::Assign( const NAMESPACE_RTL(OString)& rStr )
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ rtl_string_acquire( rStr.pData );
+ ImplDeleteData( mpData );
+ mpData = (ByteStringData*)rStr.pData;
+ return *this;
+}
diff --git a/tools/source/string/strimp.cxx b/tools/source/string/strimp.cxx
new file mode 100644
index 000000000000..0b667f14e6c4
--- /dev/null
+++ b/tools/source/string/strimp.cxx
@@ -0,0 +1,2306 @@
+/*************************************************************************
+ *
+ * $RCSfile: strimp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// =======================================================================
+
+// Daten des Strings fuer einen NULL-String
+static STRINGDATA aImplEmptyStrData = { 1, 0, 0 };
+
+// =======================================================================
+
+static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2 )
+{
+ sal_Int32 nRet;
+#if STRCODE == sal_Unicode
+ while ( ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)*pStr2)) == 0) &&
+ *pStr2 )
+#else
+ while ( ((nRet = ((sal_Int32)((unsigned STRCODE)*pStr1))-((sal_Int32)((unsigned STRCODE)*pStr2))) == 0) &&
+ *pStr2 )
+#endif
+ {
+ pStr1++;
+ pStr2++;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+#if STRCODE == sal_Unicode
+ while ( nCount &&
+ ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)*pStr2)) == 0) &&
+ *pStr2 )
+#else
+ while ( nCount &&
+ ((nRet = ((sal_Int32)((unsigned STRCODE)*pStr1))-((sal_Int32)((unsigned STRCODE)*pStr2))) == 0) &&
+ *pStr2 )
+#endif
+ {
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringCompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+#if STRCODE == sal_Unicode
+ while ( nCount &&
+ ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)*pStr2)) == 0) )
+#else
+ while ( nCount &&
+ ((nRet = ((sal_Int32)((unsigned STRCODE)*pStr1))-((sal_Int32)((unsigned STRCODE)*pStr2))) == 0) )
+#endif
+ {
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
+{
+ sal_Int32 nRet;
+ STRCODE c1;
+ STRCODE c2;
+ do
+ {
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ c1 = *pStr1;
+ c2 = *pStr2;
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+#if STRCODE == sal_Unicode
+ nRet = ((sal_Int32)c1)-((sal_Int32)c2);
+#else
+ nRet = ((sal_Int32)((unsigned STRCODE)c1))-((sal_Int32)((unsigned STRCODE)c2));
+#endif
+ if ( nRet != 0 )
+ break;
+
+ pStr1++;
+ pStr2++;
+ }
+ while ( c2 );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+ STRCODE c1;
+ STRCODE c2;
+ do
+ {
+ if ( !nCount )
+ break;
+
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ c1 = *pStr1;
+ c2 = *pStr2;
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+#if STRCODE == sal_Unicode
+ nRet = ((sal_Int32)c1)-((sal_Int32)c2);
+#else
+ nRet = ((sal_Int32)((unsigned STRCODE)c1))-((sal_Int32)((unsigned STRCODE)c2));
+#endif
+ if ( nRet != 0 )
+ break;
+
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+ while ( c2 );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
+ xub_StrLen nCount )
+{
+ sal_Int32 nRet = 0;
+ STRCODE c1;
+ STRCODE c2;
+ do
+ {
+ if ( !nCount )
+ break;
+
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ c1 = *pStr1;
+ c2 = *pStr2;
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+#if STRCODE == sal_Unicode
+ nRet = ((sal_Int32)c1)-((sal_Int32)c2);
+#else
+ nRet = ((sal_Int32)((unsigned STRCODE)c1))-((sal_Int32)((unsigned STRCODE)c2));
+#endif
+
+ pStr1++;
+ pStr2++;
+ nCount--;
+ }
+ while ( nRet == 0 );
+
+ return nRet;
+}
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+const char* DBGCHECKSTRING( const void* pString )
+{
+ STRING* p = (STRING*)pString;
+
+ if ( p->mpData->maStr[p->mpData->mnLen] != 0 )
+ return "String damaged: aStr[nLen] != 0";
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+static STRINGDATA* ImplAllocData( xub_StrLen nLen )
+{
+ // Dann kopiere die Daten
+ STRINGDATA* pData = (STRINGDATA*)rtl_allocateMemory( sizeof(STRINGDATA)+(nLen*sizeof( STRCODE )) );
+ pData->mnRefCount = 1;
+ pData->mnLen = nLen;
+ pData->maStr[nLen] = 0;
+ return pData;
+}
+
+// -----------------------------------------------------------------------
+
+static void _ImplDeleteData( STRINGDATA* pStrData )
+{
+ // alle referenzierten Strings koennen zur gleichen Zeit geloescht
+ // wurden sein, somit muss hier noch geprueft werden, ob ich
+ // der letzte gleichzeitig zerstoerte String bin
+ if ( !osl_decrementInterlockedCount(&pStrData->mnRefCount) )
+ {
+ DBG_ASSERT( aImplEmptyStrData.mnRefCount != 0, "String::ImplIncRefCount() - EmptyStr RefCount == 0" );
+ rtl_freeMemory( pStrData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplDeleteData( STRINGDATA* pStrData )
+{
+ DBG_ASSERT( aImplEmptyStrData.mnRefCount != 0, "String::ImplIncRefCount() - EmptyStr RefCount == 0" );
+
+ // Ist der ReferenzCounter groesser 0
+ if ( pStrData->mnRefCount == 1 )
+ rtl_freeMemory( pStrData );
+ else
+ _ImplDeleteData( pStrData );
+}
+
+// -----------------------------------------------------------------------
+
+static STRINGDATA* _ImplCopyData( STRINGDATA* pData )
+{
+ xub_StrLen nSize = sizeof(STRINGDATA)+(pData->mnLen*sizeof( STRCODE ));
+ STRINGDATA* pNewData = (STRINGDATA*)rtl_allocateMemory( nSize );
+ memcpy( pNewData, pData, nSize );
+ pNewData->mnRefCount = 1;
+ _ImplDeleteData( pData );
+ return pNewData;
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplCopyData( STRING* pString )
+{
+ DBG_ASSERT( (pString->mpData->mnRefCount > 0), "String::ImplCopyData() - RefCount == 0" );
+ DBG_ASSERT( aImplEmptyStrData.mnRefCount != 0, "String::ImplIncRefCount() - EmptyStr RefCount == 0" );
+
+ // ist es ein referenzierter String, dann die Daten abkoppeln
+ if ( pString->mpData->mnRefCount != 1 )
+ pString->mpData = _ImplCopyData( pString->mpData );
+}
+
+// -----------------------------------------------------------------------
+
+static STRCODE* _ImplCopyStringData( STRING* pString, STRCODE* pStr )
+{
+ DBG_ASSERT( (pStr >= pString->mpData->maStr) &&
+ ((pStr-pString->mpData->maStr) < pString->mpData->mnLen),
+ "ImplCopyStringData - pStr from other String-Instanz" );
+
+ unsigned int nIndex = (unsigned int)(pStr-pString->mpData->maStr);
+ pString->mpData = _ImplCopyData( pString->mpData );
+ pStr = pString->mpData->maStr + nIndex;
+ return pStr;
+}
+
+// -----------------------------------------------------------------------
+
+inline STRCODE* ImplCopyStringData( STRING* pString, STRCODE* pStr )
+{
+ // Ist der Referenzzaehler groesser 0
+ if ( pString->mpData->mnRefCount != 1 )
+ pStr = _ImplCopyStringData( pString, pStr );
+ return pStr;
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplIncRefCount( STRINGDATA* pData )
+{
+ osl_incrementInterlockedCount( &pData->mnRefCount );
+}
+
+// -----------------------------------------------------------------------
+
+inline xub_StrLen ImplGetCopyLen( xub_StrLen nStrLen, xub_StrLen nCopyLen )
+{
+ if ( (ULONG)nStrLen+nCopyLen > STRING_MAXLEN )
+ nCopyLen = STRING_MAXLEN-nStrLen;
+ return nCopyLen;
+}
+
+// =======================================================================
+
+STRING::STRING()
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+
+ // Leerer String
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+}
+
+// -----------------------------------------------------------------------
+
+STRING::STRING( const STRING& rStr )
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Pointer auf die Daten des uebergebenen Strings setzen und
+ // Referenzzaehler erhoehen
+ ImplIncRefCount( rStr.mpData );
+ mpData = rStr.mpData;
+}
+
+// -----------------------------------------------------------------------
+
+STRING::STRING( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen )
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Stringlaenge ermitteln
+ if ( nPos > rStr.mpData->mnLen )
+ nLen = 0;
+ else
+ {
+ // Laenge korrigieren, wenn noetig
+ xub_StrLen nMaxLen = rStr.mpData->mnLen-nPos;
+ if ( nLen > nMaxLen )
+ nLen = nMaxLen;
+ }
+
+ // Ist es kein leerer String
+ if ( nLen )
+ {
+ // Reicht ein einfaches erhoehen des Referenzcounters
+ if ( (nPos == 0) && (nLen == rStr.mpData->mnLen) )
+ {
+ ImplIncRefCount( rStr.mpData );
+ mpData = rStr.mpData;
+ }
+ else
+ {
+ // Verwaltungsdaten anlegen und String kopieren
+ mpData = ImplAllocData( nLen );
+ memcpy( mpData->maStr, rStr.mpData->maStr+nPos, nLen*sizeof( STRCODE ) );
+ }
+ }
+ else
+ {
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+STRING::STRING( const STRCODE* pCharStr )
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+
+ // Stringlaenge ermitteln
+ // Bei diesem Ctor darf NULL uebergeben werden
+ xub_StrLen nLen;
+ if ( pCharStr )
+ nLen = ImplStringLen( pCharStr );
+ else
+ nLen = 0;
+
+ // Ist es kein leerer String
+ if ( nLen )
+ {
+ if ( nLen > STRING_MAXLEN )
+ nLen = STRING_MAXLEN;
+
+ // Verwaltungsdaten anlegen und String kopieren
+ mpData = ImplAllocData( nLen );
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ }
+ else
+ {
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+STRING::STRING( const STRCODE* pCharStr, xub_StrLen nLen )
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::String() - pCharStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pCharStr );
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ for ( xub_StrLen i = 0; i < nLen; i++ )
+ {
+ if ( !pCharStr[i] )
+ {
+ DBG_ERROR( "String::String() : nLen is wrong" );
+ }
+ }
+ }
+#endif
+
+ // Ist es kein leerer String
+ if ( nLen )
+ {
+ if ( nLen > STRING_MAXLEN )
+ nLen = STRING_MAXLEN;
+
+ // Verwaltungsdaten anlegen und String kopieren
+ mpData = ImplAllocData( nLen );
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ }
+ else
+ {
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+STRING::STRING( STRCODE c )
+{
+ DBG_CTOR( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( c, "String::String() - c is 0" );
+
+ // Verwaltungsdaten anlegen und initialisieren
+ mpData = ImplAllocData( 1 );
+ mpData->maStr[0] = c;
+}
+
+// -----------------------------------------------------------------------
+
+STRING::~STRING()
+{
+ DBG_DTOR( STRING, DBGCHECKSTRING );
+
+ // Daten loeschen
+ ImplDeleteData( mpData );
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Assign( const STRING& rStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ ImplIncRefCount( rStr.mpData );
+ ImplDeleteData( mpData );
+ mpData = rStr.mpData;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Assign( const STRCODE* pCharStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
+
+ // Stringlaenge ermitteln
+#ifdef NOOLDSTRING
+ xub_StrLen nLen = ImplStringLen( pCharStr );
+#else
+ xub_StrLen nLen;
+ if ( pCharStr )
+ nLen = ImplStringLen( pCharStr );
+ else
+ nLen = 0;
+#endif
+
+ if ( !nLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ else
+ {
+ // Wenn String genauso lang ist, wie der String, dann direkt kopieren
+ if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ else
+ {
+ // Alte Daten loeschen
+ ImplDeleteData( mpData );
+
+ // Daten initialisieren und String kopieren
+ mpData = ImplAllocData( nLen );
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Assign( const STRCODE* pCharStr, xub_StrLen nLen )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pCharStr );
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ for ( xub_StrLen i = 0; i < nLen; i++ )
+ {
+ if ( !pCharStr[i] )
+ {
+ DBG_ERROR( "String::Assign() : nLen is wrong" );
+ }
+ }
+ }
+#endif
+
+ if ( !nLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ else
+ {
+ // Wenn String genauso lang ist, wie der String, dann direkt kopieren
+ if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ else
+ {
+ // Alte Daten loeschen
+ ImplDeleteData( mpData );
+
+ // Daten initialisieren und String kopieren
+ mpData = ImplAllocData( nLen );
+ memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Assign( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( c, "String::Assign() - c is 0" );
+
+ // Verwaltungsdaten anlegen und initialisieren
+ ImplDeleteData( mpData );
+ mpData = ImplAllocData( 1 );
+ mpData->maStr[0] = c;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Append( const STRING& rStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Wenn String leer, dann reicht eine Zuweisung
+ xub_StrLen nLen = mpData->mnLen;
+ if ( !nLen )
+ {
+ ImplIncRefCount( rStr.mpData );
+ ImplDeleteData( mpData );
+ mpData = rStr.mpData;
+ }
+ else
+ {
+ // Ueberlauf abfangen
+ xub_StrLen nCopyLen = ImplGetCopyLen( nLen, rStr.mpData->mnLen );
+
+ // Ist der uebergebene String kein Leerstring
+ if ( nCopyLen )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nLen, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Append( const STRCODE* pCharStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nLen = mpData->mnLen;
+#ifdef NOOLDSTRING
+ xub_StrLen nCopyLen = ImplStringLen( pCharStr );
+#else
+ xub_StrLen nCopyLen;
+ if ( pCharStr )
+ nCopyLen = ImplStringLen( pCharStr );
+ else
+ nCopyLen = 0;
+#endif
+
+ // Ueberlauf abfangen
+ nCopyLen = ImplGetCopyLen( nLen, nCopyLen );
+
+ // Ist es kein leerer String
+ if ( nCopyLen )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
+
+ if ( nCharLen == STRING_LEN )
+ nCharLen = ImplStringLen( pCharStr );
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ for ( xub_StrLen i = 0; i < nCharLen; i++ )
+ {
+ if ( !pCharStr[i] )
+ {
+ DBG_ERROR( "String::Append() : nLen is wrong" );
+ }
+ }
+ }
+#endif
+
+ // Ueberlauf abfangen
+ xub_StrLen nLen = mpData->mnLen;
+ xub_StrLen nCopyLen = ImplGetCopyLen( nLen, nCharLen );
+
+ // Ist es kein leerer String
+ if ( nCopyLen )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Append( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // kein 0-Character und maximale Stringlaenge nicht ueberschreiten
+ xub_StrLen nLen = mpData->mnLen;
+ if ( c && (nLen < STRING_MAXLEN) )
+ {
+ // Neue Datenstruktur und neuen String erzeugen
+ STRINGDATA* pNewData = ImplAllocData( nLen+1 );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+ pNewData->maStr[nLen] = c;
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::SetChar( xub_StrLen nIndex, STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( nIndex < mpData->mnLen, "String::SetChar() - nIndex > String.Len()" );
+
+ // Daten kopieren, wenn noetig und Character zuweisen
+ ImplCopyData( this );
+ mpData->maStr[nIndex] = c;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Insert( const STRING& rStr, xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Ueberlauf abfangen
+ xub_StrLen nCopyLen = ImplGetCopyLen( mpData->mnLen, rStr.mpData->mnLen );
+
+ // Ist der einzufuegende String ein Leerstring
+ if ( !nCopyLen )
+ return *this;
+
+ // Index groesser als Laenge
+ if ( nIndex > mpData->mnLen )
+ nIndex = mpData->mnLen;
+
+ // Neue Laenge ermitteln und neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
+ (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Insert( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen,
+ xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Stringlaenge ermitteln
+ if ( nPos > rStr.mpData->mnLen )
+ nLen = 0;
+ else
+ {
+ // Laenge korrigieren, wenn noetig
+ xub_StrLen nMaxLen = rStr.mpData->mnLen-nPos;
+ if ( nLen > nMaxLen )
+ nLen = nMaxLen;
+ }
+
+ // Ueberlauf abfangen
+ xub_StrLen nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
+
+ // Ist der einzufuegende String ein Leerstring
+ if ( !nCopyLen )
+ return *this;
+
+ // Index groesser als Laenge
+ if ( nIndex > mpData->mnLen )
+ nIndex = mpData->mnLen;
+
+ // Neue Laenge ermitteln und neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
+ (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Insert( const STRCODE* pCharStr, xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_ASSERT( pCharStr, "String::Insert() - pCharStr is NULL" );
+
+ // Stringlaenge ermitteln
+ xub_StrLen nCopyLen = ImplStringLen( pCharStr );
+
+ // Ueberlauf abfangen
+ nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
+
+ // Ist der einzufuegende String ein Leerstring
+ if ( !nCopyLen )
+ return *this;
+
+ // Index groesser als Laenge
+ if ( nIndex > mpData->mnLen )
+ nIndex = mpData->mnLen;
+
+ // Neue Laenge ermitteln und neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex, pCharStr, nCopyLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
+ (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Ist es kein 0-Character
+ if ( !c || (mpData->mnLen == STRING_MAXLEN) )
+ return *this;
+
+ // Index groesser als Laenge
+ if ( nIndex > mpData->mnLen )
+ nIndex = mpData->mnLen;
+
+ // Neue Laenge ermitteln und neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ pNewData->maStr[nIndex] = c;
+ memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
+ (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Replace( xub_StrLen nIndex, xub_StrLen nCount, const STRING& rStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Wenn Index groessergleich Laenge ist, dann ist es ein Append
+ if ( nIndex >= mpData->mnLen )
+ {
+ Append( rStr );
+ return *this;
+ }
+
+ // Ist es eine Zuweisung
+ if ( (nIndex == 0) && (nCount >= mpData->mnLen) )
+ {
+ Assign( rStr );
+ return *this;
+ }
+
+ // Reicht ein Erase
+ xub_StrLen nStrLen = rStr.mpData->mnLen;
+ if ( !nStrLen )
+ return Erase( nIndex, nCount );
+
+ // nCount darf nicht ueber das Stringende hinnausgehen
+ if ( (ULONG)nIndex+nCount > mpData->mnLen )
+ nCount = mpData->mnLen-nIndex;
+
+ // Reicht ein Insert
+ if ( !nCount )
+ return Insert( rStr, nIndex );
+
+ // Reicht eine zeichenweise Zuweisung
+ if ( nCount == nStrLen )
+ {
+ ImplCopyData( this );
+ memcpy( mpData->maStr+nIndex, rStr.mpData->maStr, nCount*sizeof( STRCODE ) );
+ return *this;
+ }
+
+ // Ueberlauf abfangen
+ nStrLen = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen );
+
+ // Neue Daten anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+nStrLen );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nStrLen*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex+nStrLen, mpData->maStr+nIndex+nCount,
+ (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Erase( xub_StrLen nIndex, xub_StrLen nCount )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Ist der Index ausserhalb des Strings oder ist nCount == 0
+ if ( (nIndex > mpData->mnLen) || !nCount )
+ return *this;
+
+ // nCount darf nicht ueber das Stringende hinnausgehen
+ if ( (ULONG)nIndex+nCount > mpData->mnLen )
+ nCount = mpData->mnLen-nIndex;
+
+ // Ist das Ergebnis kein Leerstring
+ if ( mpData->mnLen - nCount )
+ {
+ // Neue Daten anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
+
+ // String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
+ memcpy( pNewData->maStr+nIndex, mpData->maStr+nIndex+nCount,
+ (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+ else
+ {
+ // Leerer String
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Fill( xub_StrLen nCount, STRCODE cFillChar )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ if ( !nCount )
+ return *this;
+
+ // Ist nCount groesser wie der jetzige String, dann verlaengern
+ if ( nCount > mpData->mnLen )
+ {
+ // Auf max. Laenge beschraenken
+ if ( nCount > STRING_MAXLEN )
+ nCount = STRING_MAXLEN;
+
+ // dann neuen String mit der neuen Laenge anlegen
+ STRINGDATA* pNewData = ImplAllocData( nCount );
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+ else
+ ImplCopyData( this );
+
+ STRCODE* pStr = mpData->maStr;
+ do
+ {
+ *pStr = cFillChar;
+ pStr++;
+ nCount--;
+ }
+ while ( nCount );
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Expand( xub_StrLen nCount, STRCODE cExpandChar )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Muss der String erweitert werden
+ xub_StrLen nLen = mpData->mnLen;
+ if ( nCount <= nLen )
+ return *this;
+
+ // Neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( nCount );
+
+ // Alten String kopieren
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+
+ // und initialisieren
+ STRCODE* pStr = pNewData->maStr;
+ pStr += nLen;
+ nCount -= nLen;
+ do
+ {
+ *pStr = cExpandChar;
+ pStr++;
+ nCount--;
+ }
+ while ( nCount );
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::EraseLeadingChars( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ if ( mpData->maStr[0] != c )
+ return *this;
+
+ xub_StrLen nStart = 0;
+ while ( mpData->maStr[nStart] == c )
+ nStart++;
+
+ return Erase( 0, nStart );
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::EraseTrailingChars( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nEnd = mpData->mnLen;
+ while ( nEnd && (mpData->maStr[nEnd-1] == c) )
+ nEnd--;
+
+ if ( nEnd != mpData->mnLen )
+ Erase( nEnd );
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::EraseLeadingAndTrailingChars( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nStart = 0;
+ while ( mpData->maStr[nStart] == c )
+ nStart++;
+ if ( nStart )
+ Erase( 0, nStart );
+
+ xub_StrLen nEnd = mpData->mnLen;
+ while ( nEnd && (mpData->maStr[nEnd-1] == c) )
+ nEnd--;
+ if ( nEnd != mpData->mnLen )
+ Erase( nEnd );
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::EraseAllChars( STRCODE c )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nCount = 0;
+ xub_StrLen i = 0;
+ while ( i < mpData->mnLen )
+ {
+ if ( mpData->maStr[i] == c )
+ nCount++;
+ i++;
+ }
+
+ if ( nCount )
+ {
+ if ( nCount == mpData->mnLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ else
+ {
+ // Neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
+
+ // Alten String kopieren und initialisieren
+ nCount = 0;
+ for( xub_StrLen i = 0; i < mpData->mnLen; i++ )
+ {
+ if ( mpData->maStr[i] != c )
+ {
+ pNewData->maStr[nCount] = mpData->maStr[i];
+ nCount++;
+ }
+ }
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::Reverse()
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ if ( !mpData->mnLen )
+ return *this;
+
+ // Daten kopieren, wenn noetig
+ ImplCopyData( this );
+
+ // Reverse
+ STRCODE cTemp;
+ xub_StrLen nCount = mpData->mnLen / 2;
+ for ( xub_StrLen i = 0; i < nCount; i++ )
+ {
+ cTemp = mpData->maStr[i];
+ mpData->maStr[i] = mpData->maStr[mpData->mnLen-i-1];
+ mpData->maStr[mpData->mnLen-i-1] = cTemp;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::ToLowerAscii()
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ STRCODE* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
+ if ( (*pStr >= 65) && (*pStr <= 90) )
+ {
+ // Daten kopieren, wenn noetig
+ pStr = ImplCopyStringData( this, pStr );
+ *pStr += 32;
+ }
+
+ pStr++;
+ nIndex++;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::ToUpperAscii()
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ STRCODE* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ // Ist das Zeichen zwischen 'a' und 'z' dann umwandeln
+ if ( (*pStr >= 97) && (*pStr <= 122) )
+ {
+ // Daten kopieren, wenn noetig
+ pStr = ImplCopyStringData( this, pStr );
+ *pStr -= 32;
+ }
+
+ pStr++;
+ nIndex++;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+STRING& STRING::ConvertLineEnd( LineEnd eLineEnd )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Zeilenumbrueche ermitteln und neue Laenge berechnen
+ BOOL bConvert = FALSE; // Muss konvertiert werden
+ const STRCODE* pStr = mpData->maStr; // damit es schneller geht
+ xub_StrLen nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
+ xub_StrLen nLen = 0; // Ziel-Laenge
+ xub_StrLen i = 0; // Source-Zaehler
+
+ while ( i < mpData->mnLen )
+ {
+ // Bei \r oder \n gibt es neuen Zeilenumbruch
+ if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
+ {
+ nLen += nLineEndLen;
+
+ // Wenn schon gesetzt, dann brauchen wir keine aufwendige Abfrage
+ if ( !bConvert )
+ {
+ // Muessen wir Konvertieren
+ if ( ((eLineEnd != LINEEND_LF) && (pStr[i] == _LF)) ||
+ ((eLineEnd == LINEEND_CRLF) && (pStr[i+1] != _LF)) ||
+ ((eLineEnd == LINEEND_LF) &&
+ ((pStr[i] == _CR) || (pStr[i+1] == _CR))) ||
+ ((eLineEnd == LINEEND_CR) &&
+ ((pStr[i] == _LF) || (pStr[i+1] == _LF))) )
+ bConvert = TRUE;
+ }
+
+ // \r\n oder \n\r, dann Zeichen ueberspringen
+ if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
+ (pStr[i] != pStr[i+1]) )
+ i++;
+ }
+ else
+ nLen++;
+ i++;
+
+ // Wenn String zu lang, dann konvertieren wir nicht
+ if ( nLen >= STRING_MAXLEN )
+ return *this;
+ }
+
+ // Zeilenumbrueche konvertieren
+ if ( bConvert )
+ {
+ // Neuen String anlegen
+ STRINGDATA* pNewData = ImplAllocData( nLen );
+ xub_StrLen j = 0;
+ i = 0;
+ while ( i < mpData->mnLen )
+ {
+ // Bei \r oder \n gibt es neuen Zeilenumbruch
+ if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
+ {
+ if ( eLineEnd == LINEEND_CRLF )
+ {
+ pNewData->maStr[j] = _CR;
+ pNewData->maStr[j+1] = _LF;
+ j += 2;
+ }
+ else
+ {
+ if ( eLineEnd == LINEEND_CR )
+ pNewData->maStr[j] = _CR;
+ else
+ pNewData->maStr[j] = _LF;
+ j++;
+ }
+
+ if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
+ (pStr[i] != pStr[i+1]) )
+ i++;
+ }
+ else
+ {
+ pNewData->maStr[j] = mpData->maStr[i];
+ j++;
+ }
+
+ i++;
+ }
+
+ // Alte Daten loeschen und Neue zuweisen
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Auf Gleichheit der Pointer testen
+ if ( mpData == rStr.mpData )
+ return COMPARE_EQUAL;
+
+ // Maximale Laenge ermitteln
+ if ( mpData->mnLen < nLen )
+ nLen = mpData->mnLen+1;
+ if ( rStr.mpData->mnLen < nLen )
+ nLen = rStr.mpData->mnLen+1;
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare STRING::CompareTo( const STRCODE* pCharStr, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringCompare( mpData->maStr, pCharStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr,
+ xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Auf Gleichheit der Pointer testen
+ if ( mpData == rStr.mpData )
+ return COMPARE_EQUAL;
+
+ // Maximale Laenge ermitteln
+ if ( mpData->mnLen < nLen )
+ nLen = mpData->mnLen+1;
+ if ( rStr.mpData->mnLen < nLen )
+ nLen = rStr.mpData->mnLen+1;
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+StringCompare STRING::CompareIgnoreCaseToAscii( const STRCODE* pCharStr,
+ xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // String vergleichen
+ sal_Int32 nCompare = ImplStringICompare( mpData->maStr, pCharStr, nLen );
+
+ // Rueckgabewert anpassen
+ if ( nCompare == 0 )
+ return COMPARE_EQUAL;
+ else if ( nCompare < 0 )
+ return COMPARE_LESS;
+ else
+ return COMPARE_GREATER;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::Equals( const STRING& rStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Sind die Daten gleich
+ if ( mpData == rStr.mpData )
+ return TRUE;
+
+ // Gleiche Laenge
+ if ( mpData->mnLen != rStr.mpData->mnLen )
+ return FALSE;
+
+ // String vergleichen
+ return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::Equals( const STRCODE* pCharStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ return (ImplStringCompare( mpData->maStr, pCharStr ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Sind die Daten gleich
+ if ( mpData == rStr.mpData )
+ return TRUE;
+
+ // Gleiche Laenge
+ if ( mpData->mnLen != rStr.mpData->mnLen )
+ return FALSE;
+
+ // String vergleichen
+ return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (rStr.mpData->mnLen == 0);
+ xub_StrLen nMaxLen = mpData->mnLen-nIndex;
+ if ( nMaxLen < nLen )
+ {
+ if ( rStr.mpData->mnLen != nMaxLen )
+ return FALSE;
+ nLen = nMaxLen;
+ }
+
+ // String vergleichen
+ return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (*pCharStr == 0);
+
+ return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (rStr.mpData->mnLen == 0);
+ xub_StrLen nMaxLen = mpData->mnLen-nIndex;
+ if ( nMaxLen < nLen )
+ {
+ if ( rStr.mpData->mnLen != nMaxLen )
+ return FALSE;
+ nLen = nMaxLen;
+ }
+
+ // String vergleichen
+ return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Are there enough codes for comparing?
+ if ( nIndex > mpData->mnLen )
+ return (*pCharStr == 0);
+
+ return (ImplStringICompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::Match( const STRING& rStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ // Ist dieser String leer
+ if ( !mpData->mnLen )
+ return STRING_MATCH;
+
+ // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
+ const STRCODE* pStr1 = mpData->maStr;
+ const STRCODE* pStr2 = rStr.mpData->maStr;
+ xub_StrLen i = 0;
+ while ( i < mpData->mnLen )
+ {
+ // Stimmt das Zeichen nicht ueberein, dann abbrechen
+ if ( *pStr1 != *pStr2 )
+ return i;
+ pStr1++;
+ pStr2++;
+ i++;
+ }
+
+ return STRING_MATCH;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::Match( const STRCODE* pCharStr ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Ist dieser String leer
+ if ( !mpData->mnLen )
+ return STRING_MATCH;
+
+ // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen i = 0;
+ while ( i < mpData->mnLen )
+ {
+ // Stimmt das Zeichen nicht ueberein, dann abbrechen
+ if ( *pStr != *pCharStr )
+ return i;
+ pStr++;
+ pCharStr++;
+ i++;
+ }
+
+ return STRING_MATCH;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::Search( STRCODE c, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+ while ( nIndex < nLen )
+ {
+ if ( *pStr == c )
+ return nIndex;
+ pStr++;
+ nIndex++;
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::Search( const STRING& rStr, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ xub_StrLen nStrLen = rStr.mpData->mnLen;
+
+ // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
+ // hinter dem String liegt, dann wurde der String nicht gefunden
+ if ( !nStrLen || (nIndex >= nLen) )
+ return STRING_NOTFOUND;
+
+ const STRCODE* pStr1 = mpData->maStr;
+ pStr1 += nIndex;
+
+ if ( nStrLen == 1 )
+ {
+ STRCODE cSearch = rStr.mpData->maStr[0];
+ while ( nIndex < nLen )
+ {
+ if ( *pStr1 == cSearch )
+ return nIndex;
+ pStr1++;
+ nIndex++;
+ }
+ }
+ else
+ {
+ const STRCODE* pStr2 = rStr.mpData->maStr;
+
+ // Nur innerhalb des Strings suchen
+ while ( (ULONG)nIndex+nStrLen <= nLen )
+ {
+ // Stimmt der String ueberein
+ if ( ImplStringCompareWithoutZero( pStr1, pStr2, nStrLen ) == 0 )
+ return nIndex;
+ pStr1++;
+ nIndex++;
+ }
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::Search( const STRCODE* pCharStr, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ xub_StrLen nStrLen = ImplStringLen( pCharStr );
+
+ // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
+ // hinter dem String liegt, dann wurde der String nicht gefunden
+ if ( !nStrLen || (nIndex >= nLen) )
+ return STRING_NOTFOUND;
+
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+
+ if ( nStrLen == 1 )
+ {
+ STRCODE cSearch = *pCharStr;
+ while ( nIndex < nLen )
+ {
+ if ( *pStr == cSearch )
+ return nIndex;
+ pStr++;
+ nIndex++;
+ }
+ }
+ else
+ {
+ // Nur innerhalb des Strings suchen
+ while ( (ULONG)nIndex+nStrLen <= nLen )
+ {
+ // Stimmt der String ueberein
+ if ( ImplStringCompareWithoutZero( pStr, pCharStr, nStrLen ) == 0 )
+ return nIndex;
+ pStr++;
+ nIndex++;
+ }
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ if ( nIndex > mpData->mnLen )
+ nIndex = (xub_StrLen)mpData->mnLen;
+
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+
+ while ( nIndex )
+ {
+ nIndex--;
+ pStr--;
+ if ( *pStr == c )
+ return nIndex;
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+ while ( nIndex < nLen )
+ {
+ STRCODE c = *pStr;
+ const STRCODE* pCompStr = pChars;
+ while ( *pCompStr )
+ {
+ if ( *pCompStr == c )
+ return nIndex;
+ pCompStr++;
+ }
+ pStr++;
+ nIndex++;
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchCharBackward( const STRCODE* pChars, xub_StrLen nIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ if ( nIndex > mpData->mnLen )
+ nIndex = (xub_StrLen)mpData->mnLen;
+
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+
+ while ( nIndex )
+ {
+ nIndex--;
+ pStr--;
+
+ STRCODE c =*pStr;
+ const STRCODE* pCompStr = pChars;
+ while ( *pCompStr )
+ {
+ if ( *pCompStr == c )
+ return nIndex;
+ pCompStr++;
+ }
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ const STRCODE* pStr = mpData->maStr;
+ pStr += nIndex;
+ while ( nIndex < nLen )
+ {
+ if ( *pStr == c )
+ {
+ ImplCopyData( this );
+ mpData->maStr[nIndex] = cRep;
+ return nIndex;
+ }
+ pStr++;
+ nIndex++;
+ }
+
+ return STRING_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
+ xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
+
+ xub_StrLen nSPos = Search( rStr, nIndex );
+ if ( nSPos != STRING_NOTFOUND )
+ Replace( nSPos, rStr.Len(), rRepStr );
+
+ return nSPos;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::SearchAndReplace( const STRCODE* pCharStr, const STRING& rRepStr,
+ xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
+
+ xub_StrLen nSPos = Search( pCharStr, nIndex );
+ if ( nSPos != STRING_NOTFOUND )
+ Replace( nSPos, ImplStringLen( pCharStr ), rRepStr );
+
+ return nSPos;
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::SearchAndReplaceAll( STRCODE c, STRCODE cRep )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ xub_StrLen nLen = mpData->mnLen;
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen nIndex = 0;
+ while ( nIndex < nLen )
+ {
+ if ( *pStr == c )
+ {
+ ImplCopyData( this );
+ mpData->maStr[nIndex] = cRep;
+ }
+ pStr++;
+ nIndex++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::SearchAndReplaceAll( const STRCODE* pCharStr, const STRING& rRepStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
+
+ xub_StrLen nCharLen = ImplStringLen( pCharStr );
+ xub_StrLen nSPos = Search( pCharStr, 0 );
+ while ( nSPos != STRING_NOTFOUND )
+ {
+ Replace( nSPos, nCharLen, rRepStr );
+ nSPos += rRepStr.Len();
+ nSPos = Search( pCharStr, nSPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
+
+ xub_StrLen nSPos = Search( rStr, 0 );
+ while ( nSPos != STRING_NOTFOUND )
+ {
+ Replace( nSPos, rStr.Len(), rRepStr );
+ nSPos += rRepStr.Len();
+ nSPos = Search( rStr, nSPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::GetTokenCount( STRCODE cTok ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Leerer String: TokenCount per Definition 0
+ if ( !mpData->mnLen )
+ return 0;
+
+ xub_StrLen nTokCount = 1;
+ xub_StrLen nLen = mpData->mnLen;
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen nIndex = 0;
+ while ( nIndex < nLen )
+ {
+ // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
+ if ( *pStr == cTok )
+ nTokCount++;
+ pStr++;
+ nIndex++;
+ }
+
+ return nTokCount;
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
+ xub_StrLen nIndex )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
+ xub_StrLen nTok = 0;
+ xub_StrLen nFirstChar = nIndex;
+ xub_StrLen i = nFirstChar;
+
+ // Bestimme die Token-Position und Laenge
+ pStr += i;
+ while ( i < nLen )
+ {
+ // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
+ if ( *pStr == cTok )
+ {
+ nTok++;
+
+ if ( nTok == nToken )
+ nFirstChar = i+1;
+ else
+ {
+ if ( nTok > nToken )
+ break;
+ }
+ }
+
+ pStr++;
+ i++;
+ }
+
+ if ( nTok >= nToken )
+ Replace( nFirstChar, i-nFirstChar, rStr );
+}
+
+// -----------------------------------------------------------------------
+
+STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
+ xub_StrLen nTok = 0;
+ xub_StrLen nFirstChar = rIndex;
+ xub_StrLen i = nFirstChar;
+
+ // Bestimme die Token-Position und Laenge
+ pStr += i;
+ while ( i < nLen )
+ {
+ // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
+ if ( *pStr == cTok )
+ {
+ nTok++;
+
+ if ( nTok == nToken )
+ nFirstChar = i+1;
+ else
+ {
+ if ( nTok > nToken )
+ break;
+ }
+ }
+
+ pStr++;
+ i++;
+ }
+
+ if ( nTok >= nToken )
+ {
+ if ( i < nLen )
+ rIndex = i+1;
+ else
+ rIndex = STRING_NOTFOUND;
+ return Copy( nFirstChar, i-nFirstChar );
+ }
+ else
+ {
+ rIndex = STRING_NOTFOUND;
+ return STRING();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen STRING::GetQuotedTokenCount( const STRING& rQuotedPairs, STRCODE cTok ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
+ DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedTokenCount() - QuotedString%2 != 0" );
+ DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedTokenCount() - cTok in QuotedString" );
+
+ // Leerer String: TokenCount per Definition 0
+ if ( !mpData->mnLen )
+ return 0;
+
+ xub_StrLen nTokCount = 1;
+ xub_StrLen nLen = mpData->mnLen;
+ xub_StrLen nQuotedLen = rQuotedPairs.Len();
+ STRCODE cQuotedEndChar = 0;
+ const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr;
+ const STRCODE* pStr = mpData->maStr;
+ xub_StrLen nIndex = 0;
+ while ( nIndex < nLen )
+ {
+ STRCODE c = *pStr;
+ if ( cQuotedEndChar )
+ {
+ // Ende des Quotes erreicht ?
+ if ( c == cQuotedEndChar )
+ cQuotedEndChar = 0;
+ }
+ else
+ {
+ // Ist das Zeichen ein Quote-Anfang-Zeichen ?
+ xub_StrLen nQuoteIndex = 0;
+ while ( nQuoteIndex < nQuotedLen )
+ {
+ if ( pQuotedStr[nQuoteIndex] == c )
+ {
+ cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
+ break;
+ }
+ else
+ nQuoteIndex += 2;
+ }
+
+ // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
+ if ( c == cTok )
+ nTokCount++;
+ }
+
+ pStr++;
+ nIndex++;
+ }
+
+ return nTokCount;
+}
+
+// -----------------------------------------------------------------------
+
+STRING STRING::GetQuotedToken( xub_StrLen nToken, const STRING& rQuotedPairs,
+ STRCODE cTok, xub_StrLen& rIndex ) const
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
+ DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedToken() - QuotedString%2 != 0" );
+ DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedToken() - cTok in QuotedString" );
+
+ const STRCODE* pStr = mpData->maStr;
+ const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr;
+ STRCODE cQuotedEndChar = 0;
+ xub_StrLen nQuotedLen = rQuotedPairs.Len();
+ xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
+ xub_StrLen nTok = 0;
+ xub_StrLen nFirstChar = rIndex;
+ xub_StrLen i = nFirstChar;
+
+ // Bestimme die Token-Position und Laenge
+ pStr += i;
+ while ( i < nLen )
+ {
+ STRCODE c = *pStr;
+ if ( cQuotedEndChar )
+ {
+ // Ende des Quotes erreicht ?
+ if ( c == cQuotedEndChar )
+ cQuotedEndChar = 0;
+ }
+ else
+ {
+ // Ist das Zeichen ein Quote-Anfang-Zeichen ?
+ xub_StrLen nQuoteIndex = 0;
+ while ( nQuoteIndex < nQuotedLen )
+ {
+ if ( pQuotedStr[nQuoteIndex] == c )
+ {
+ cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
+ break;
+ }
+ else
+ nQuoteIndex += 2;
+ }
+
+ // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
+ if ( c == cTok )
+ {
+ nTok++;
+
+ if ( nTok == nToken )
+ nFirstChar = i+1;
+ else
+ {
+ if ( nTok > nToken )
+ break;
+ }
+ }
+ }
+
+ pStr++;
+ i++;
+ }
+
+ if ( nTok >= nToken )
+ {
+ if ( i < nLen )
+ rIndex = i+1;
+ else
+ rIndex = STRING_NOTFOUND;
+ return Copy( nFirstChar, i-nFirstChar );
+ }
+ else
+ {
+ rIndex = STRING_NOTFOUND;
+ return STRING();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+STRCODE* STRING::GetBufferAccess()
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Daten kopieren, wenn noetig
+ if ( mpData->mnLen )
+ ImplCopyData( this );
+
+ // Pointer auf den String zurueckgeben
+ return mpData->maStr;
+}
+
+// -----------------------------------------------------------------------
+
+void STRING::ReleaseBufferAccess( xub_StrLen nLen )
+{
+ // Hier ohne Funktionstest, da String nicht konsistent
+ DBG_CHKTHIS( STRING, NULL );
+ DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
+
+ if ( nLen > mpData->mnLen )
+ nLen = ImplStringLen( mpData->maStr );
+
+ if ( !nLen )
+ {
+ ImplDeleteData( mpData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ mpData = &aImplEmptyStrData;
+ }
+ // Bei mehr als 8 Zeichen unterschied, kuerzen wir den Buffer
+ else if ( ((ULONG)nLen)+8 < mpData->mnLen )
+ {
+ STRINGDATA* pNewData = ImplAllocData( nLen );
+ memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
+ ImplDeleteData( mpData );
+ mpData = pNewData;
+ }
+ else
+ mpData->mnLen = nLen;
+}
+
+// -----------------------------------------------------------------------
+
+STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
+{
+ DBG_CHKTHIS( STRING, DBGCHECKSTRING );
+
+ // Vorhandene Daten loeschen und neue anlegen
+ ImplDeleteData( mpData );
+ if ( nLen )
+ mpData = ImplAllocData( nLen );
+ else
+ mpData = &aImplEmptyStrData;
+
+ // Pointer auf den angelegten Buffer zurueckgeben
+ return mpData->maStr;
+}
+
+// -----------------------------------------------------------------------
+#ifndef NOOLDSTRING
+STRING operator + ( const STRING& rStr1, const STRING& rStr2 )
+{
+ DBG_CHKOBJ( &rStr1, STRING, DBGCHECKSTRING );
+ DBG_CHKOBJ( &rStr2, STRING, DBGCHECKSTRING );
+ DBG_WARNING( "String::operator+(): Use String::operator+=() for better performence and smaller code" );
+
+ STRING aTmpStr( rStr1 );
+ aTmpStr += rStr2;
+ return aTmpStr;
+}
+
+// -----------------------------------------------------------------------
+
+STRING operator + ( const STRING& rStr, const STRCODE* pCharStr )
+{
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+ DBG_WARNING( "String::operator+(): Use String::operator+=() for better performence and smaller code" );
+
+ STRING aTmpStr( rStr );
+ aTmpStr += pCharStr;
+ return aTmpStr;
+}
+
+// -----------------------------------------------------------------------
+
+STRING operator + ( const STRCODE* pCharStr, const STRING& rStr )
+{
+ DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
+ DBG_WARNING( "String::operator+(): - Use String::operator+=() for better performence and smaller code" );
+
+ STRING aTmpStr( pCharStr );
+ aTmpStr += rStr;
+ return aTmpStr;
+}
+#endif
diff --git a/tools/source/string/strucvt.cxx b/tools/source/string/strucvt.cxx
new file mode 100644
index 000000000000..ab7190c662ff
--- /dev/null
+++ b/tools/source/string/strucvt.cxx
@@ -0,0 +1,251 @@
+/*************************************************************************
+ *
+ * $RCSfile: strucvt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// =======================================================================
+
+static UniStringData* ImplGetUniStringDataFromString( const char* pStr, sal_Size nLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_ASSERT( (eTextEncoding != 9) &&
+ (eTextEncoding != RTL_TEXTENCODING_DONTKNOW) &&
+ (eTextEncoding != RTL_TEXTENCODING_UCS2) &&
+ (eTextEncoding != RTL_TEXTENCODING_UCS4),
+ "ByteString-->UniString: Wrong TextEncoding" );
+
+ if ( !nLen )
+ {
+ ImplIncRefCount( &aImplEmptyStrData );
+ return &aImplEmptyStrData;
+ }
+
+#ifndef NOOLDSTRING
+ if ( eTextEncoding == CHARSET_SYSTEM )
+ eTextEncoding = GetSystemCharSet();
+#endif
+ nCvtFlags |= RTL_TEXTTOUNICODE_FLAGS_FLUSH;
+
+ UniStringData* pData;
+ rtl_TextEncodingInfo aTextEncInfo;
+ rtl_TextToUnicodeConverter hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ sal_Size nNewLen;
+
+ // get TextEncodingInfo
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ rtl_getTextEncodingInfo( eTextEncoding, &aTextEncInfo );
+
+ // Zuerst konvertieren wir mit der wahrscheinlichen Anzahl
+ // der zu konvertierenden Zeichen
+ nNewLen = nLen/aTextEncInfo.AverageCharSize;
+ if ( nNewLen > STRING_MAXLEN )
+ nNewLen = STRING_MAXLEN;
+ pData = ImplAllocData( (xub_StrLen)nNewLen );
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ pStr, nLen,
+ pData->maStr, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcBytes );
+
+ // Buffer hat nicht gereicht, dann mit maximaler Buffergroesse
+ if ( (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL) &&
+ (nNewLen != STRING_MAXLEN) )
+ {
+ rtl_freeMemory( pData );
+ nNewLen = nLen;
+ if ( nNewLen > STRING_MAXLEN )
+ nNewLen = STRING_MAXLEN;
+ pData = ImplAllocData( (xub_StrLen)nNewLen );
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ pStr, nLen,
+ pData->maStr, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcBytes );
+ }
+
+ // String entsprechend der durch das Konvertieren tatsaechlich
+ // entstehenden Bytes anpassen
+ if ( !nDestChars )
+ {
+ rtl_freeMemory( pData );
+ ImplIncRefCount( &aImplEmptyStrData );
+ pData = &aImplEmptyStrData;
+ }
+ else if ( nNewLen > nDestChars+8 )
+ {
+ UniStringData* pTempData = ImplAllocData( (xub_StrLen)nDestChars );
+ memcpy( pTempData->maStr, pData->maStr, nDestChars*sizeof( sal_Unicode ) );
+ rtl_freeMemory( pData );
+ pData = pTempData;
+ }
+ else
+ {
+ pData->mnLen = (xub_StrLen)nDestChars;
+ pData->maStr[nDestChars] = '\0';
+ }
+ rtl_destroyTextToUnicodeConverter( hConverter );
+ return pData;
+}
+
+// =======================================================================
+
+void UniString::InitStringRes( const char* pUTF8Str, xub_StrLen nLen )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+
+ mpData = ImplGetUniStringDataFromString( pUTF8Str, nLen,
+ RTL_TEXTENCODING_UTF8,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
+}
+
+// =======================================================================
+
+UniString::UniString( const ByteString& rByteStr, rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+ DBG_CHKOBJ( &rByteStr, ByteString, DbgCheckByteString );
+
+ mpData = ImplGetUniStringDataFromString( rByteStr.mpData->maStr, rByteStr.mpData->mnLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+UniString::UniString( const ByteString& rByteStr, xub_StrLen nPos, xub_StrLen nLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+ DBG_CHKOBJ( &rByteStr, ByteString, DbgCheckByteString );
+
+ // Stringlaenge ermitteln
+ if ( nPos > rByteStr.mpData->mnLen )
+ nLen = 0;
+ else
+ {
+ // Laenge korrigieren, wenn noetig
+ xub_StrLen nMaxLen = rByteStr.mpData->mnLen-nPos;
+ if ( nLen > nMaxLen )
+ nLen = nMaxLen;
+ }
+
+ mpData = ImplGetUniStringDataFromString( rByteStr.mpData->maStr+nPos, nLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+UniString::UniString( const char* pByteStr,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+ DBG_ASSERT( pByteStr, "UniString::UniString() - pByteStr is NULL" );
+
+ mpData = ImplGetUniStringDataFromString( pByteStr, ImplStringLen( pByteStr ),
+ eTextEncoding, nCvtFlags );
+}
+
+// -----------------------------------------------------------------------
+
+UniString::UniString( const char* pByteStr, xub_StrLen nLen,
+ rtl_TextEncoding eTextEncoding, sal_uInt32 nCvtFlags )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+ DBG_ASSERT( pByteStr, "UniString::UniString() - pByteStr is NULL" );
+
+ if ( nLen == STRING_LEN )
+ nLen = ImplStringLen( pByteStr );
+
+ mpData = ImplGetUniStringDataFromString( pByteStr, nLen,
+ eTextEncoding, nCvtFlags );
+}
+
+// =======================================================================
+
+UniString::UniString( const NAMESPACE_RTL(OUString)& rStr )
+{
+ DBG_CTOR( UniString, DbgCheckUniString );
+
+ mpData = (UniStringData*)rStr.pData;
+ ImplIncRefCount( mpData );
+}
+
+// -----------------------------------------------------------------------
+
+NAMESPACE_RTL(OUString)::OUString( const UniString& rStr )
+{
+ pData = (rtl_uString*)rStr.mpData;
+ rtl_uString_acquire( pData );
+}
+
+// -----------------------------------------------------------------------
+
+UniString& UniString::Assign( const NAMESPACE_RTL(OUString)& rStr )
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+
+ rtl_uString_acquire( rStr.pData );
+ ImplDeleteData( mpData );
+ mpData = (UniStringData*)rStr.pData;
+ return *this;
+}
diff --git a/tools/source/string/tstring.cxx b/tools/source/string/tstring.cxx
new file mode 100644
index 000000000000..9e8cda42b736
--- /dev/null
+++ b/tools/source/string/tstring.cxx
@@ -0,0 +1,304 @@
+/*************************************************************************
+ *
+ * $RCSfile: tstring.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#ifndef _OSL_INTERLCK_H
+#include <osl/interlck.h>
+#endif
+#ifndef _RTL_ALLOC_H
+#include <rtl/alloc.h>
+#endif
+#ifndef _RTL_MEMORY_H
+#include <rtl/memory.h>
+#endif
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+
+#define private public
+#include <string.hxx>
+#undef private
+#include <impstrg.hxx>
+
+// For shared byte convert tables
+#ifndef _TOOLS_TOOLSIN_HXX
+#include <toolsin.hxx>
+#endif
+
+#include <debug.hxx>
+
+// =======================================================================
+
+DBG_NAME( ByteString );
+DBG_NAMEEX( UniString );
+
+// -----------------------------------------------------------------------
+
+#define STRCODE sal_Char
+#define STRING ByteString
+#define STRINGDATA ByteStringData
+#define DBGCHECKSTRING DbgCheckByteString
+
+// -----------------------------------------------------------------------
+
+xub_StrLen ImplStringLen( const sal_Char* pStr )
+{
+ const sal_Char* pTempStr = pStr;
+ while( *pTempStr )
+ pTempStr++;
+ return (xub_StrLen)(pTempStr-pStr);
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen ImplStringLen( const sal_Unicode* pStr )
+{
+ const sal_Unicode* pTempStr = pStr;
+ while( *pTempStr )
+ pTempStr++;
+ return (xub_StrLen)(pTempStr-pStr);
+}
+
+// -----------------------------------------------------------------------
+
+#include <strimp.cxx>
+#include <strcvt.cxx>
+
+#ifndef NOOLDSTRING
+#include <strold.cxx>
+#endif
+
+// -----------------------------------------------------------------------
+
+ByteString ByteString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFINT32];
+ return ByteString( aBuf, rtl_str_valueOfInt32( aBuf, n, nRadix ) );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString ByteString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFINT64];
+ return ByteString( aBuf, rtl_str_valueOfInt64( aBuf, n, nRadix ) );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString ByteString::CreateFromFloat( float f )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFFLOAT];
+ return ByteString( aBuf, rtl_str_valueOfFloat( aBuf, f ) );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString ByteString::CreateFromDouble( double d )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFDOUBLE];
+ return ByteString( aBuf, rtl_str_valueOfDouble( aBuf, d ) );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int32 ByteString::ToInt32() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ return atoi( mpData->maStr );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 ByteString::ToInt64() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ return atoi( mpData->maStr );
+}
+
+// -----------------------------------------------------------------------
+
+float ByteString::ToFloat() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+double ByteString::ToDouble() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::IsLowerAscii() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ const sal_Char* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ if ( (*pStr >= 65) && (*pStr <= 90) )
+ return FALSE;
+
+ pStr++;
+ nIndex++;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::IsUpperAscii() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ const sal_Char* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ if ( (*pStr >= 97) && (*pStr <= 122) )
+ return FALSE;
+
+ pStr++;
+ nIndex++;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::IsAlphaAscii() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ const sal_Char* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
+ ((*pStr >= 65) && (*pStr <= 90))) )
+ return FALSE;
+
+ pStr++;
+ nIndex++;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::IsNumericAscii() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ const sal_Char* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ if ( !((*pStr >= 48) && (*pStr <= 57)) )
+ return FALSE;
+
+ pStr++;
+ nIndex++;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ByteString::IsAlphaNumericAscii() const
+{
+ DBG_CHKTHIS( ByteString, DbgCheckByteString );
+
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = mpData->mnLen;
+ const sal_Char* pStr = mpData->maStr;
+ while ( nIndex < nLen )
+ {
+ if ( !(((*pStr >= 97) && (*pStr <= 122)) ||
+ ((*pStr >= 65) && (*pStr <= 90)) ||
+ ((*pStr >= 48) && (*pStr <= 57))) )
+ return FALSE;
+
+ pStr++;
+ nIndex++;
+ }
+
+ return TRUE;
+}
diff --git a/tools/source/string/tustring.cxx b/tools/source/string/tustring.cxx
new file mode 100644
index 000000000000..22c894063441
--- /dev/null
+++ b/tools/source/string/tustring.cxx
@@ -0,0 +1,173 @@
+/*************************************************************************
+ *
+ * $RCSfile: tustring.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:09 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#ifndef _OSL_INTERLCK_H
+#include <osl/interlck.h>
+#endif
+#ifndef _RTL_ALLOC_H
+#include <rtl/alloc.h>
+#endif
+#ifndef _RTL_MEMORY_H
+#include <rtl/memory.h>
+#endif
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+
+#define private public
+#include <string.hxx>
+#undef private
+#include <impstrg.hxx>
+
+#include <debug.hxx>
+
+// =======================================================================
+
+DBG_NAME( UniString );
+DBG_NAMEEX( ByteString );
+
+// -----------------------------------------------------------------------
+
+#define STRCODE sal_Unicode
+#define STRING UniString
+#define STRINGDATA UniStringData
+#define DBGCHECKSTRING DbgCheckUniString
+
+// -----------------------------------------------------------------------
+
+#include <strimp.cxx>
+#include <strucvt.cxx>
+#include <strascii.cxx>
+
+#ifndef NOOLDSTRING
+#include <struold.cxx>
+#endif
+
+// -----------------------------------------------------------------------
+
+UniString UniString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
+{
+ sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT32];
+ return UniString( aBuf, rtl_ustr_valueOfInt32( aBuf, n, nRadix ) );
+}
+
+// -----------------------------------------------------------------------
+
+UniString UniString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
+{
+ sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT64];
+ return UniString( aBuf, rtl_ustr_valueOfInt64( aBuf, n, nRadix ) );
+}
+
+// -----------------------------------------------------------------------
+
+UniString UniString::CreateFromFloat( float f )
+{
+ sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFFLOAT];
+ return UniString( aBuf, rtl_ustr_valueOfFloat( aBuf, f ) );
+}
+
+// -----------------------------------------------------------------------
+
+UniString UniString::CreateFromDouble( double d )
+{
+ sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFDOUBLE];
+ return UniString( aBuf, rtl_ustr_valueOfDouble( aBuf, d ) );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int32 UniString::ToInt32() const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+
+ return rtl_ustr_toInt32( mpData->maStr, 10 );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 UniString::ToInt64() const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+
+ return rtl_ustr_toInt64( mpData->maStr, 10 );
+}
+
+// -----------------------------------------------------------------------
+
+float UniString::ToFloat() const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+
+ return rtl_ustr_toFloat( mpData->maStr );
+}
+
+// -----------------------------------------------------------------------
+
+double UniString::ToDouble() const
+{
+ DBG_CHKTHIS( UniString, DbgCheckUniString );
+
+ return rtl_ustr_toDouble( mpData->maStr );
+}
+
diff --git a/tools/source/zcodec/makefile.mk b/tools/source/zcodec/makefile.mk
new file mode 100644
index 000000000000..f7f3fcdf21e3
--- /dev/null
+++ b/tools/source/zcodec/makefile.mk
@@ -0,0 +1,80 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:10 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=zcodec
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/zcodec.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/zcodec/zcodec.cxx b/tools/source/zcodec/zcodec.cxx
new file mode 100644
index 000000000000..86230b275004
--- /dev/null
+++ b/tools/source/zcodec/zcodec.cxx
@@ -0,0 +1,524 @@
+/*************************************************************************
+ *
+ * $RCSfile: zcodec.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:10 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _STREAM_HXX
+#include "stream.hxx"
+#endif
+#ifndef _ZLIB_H
+#include "zlib/zlib.h"
+#endif
+#ifndef _ZCODEC_HXX
+#include "zcodec.hxx"
+#endif
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define PZSTREAM ((z_stream*) mpsC_Stream)
+
+/* gzip flag byte */
+#define GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define GZ_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define GZ_COMMENT 0x10 /* bit 4 set: file comment present */
+#define GZ_RESERVED 0xE0 /* bits 5..7: reserved */
+
+static int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
+
+
+// ----------
+// - ZCodec -
+// ----------
+
+ZCodec::ZCodec( ULONG nInBufSize, ULONG nOutBufSize, ULONG nMemUsage )
+{
+ mnMemUsage = nMemUsage;
+ mnInBufSize = nInBufSize;
+ mnOutBufSize = nOutBufSize;
+ mpsC_Stream = new z_stream;
+}
+
+ZCodec::ZCodec( void )
+{
+ mnMemUsage = MAX_MEM_USAGE;
+ mnInBufSize = DEFAULT_IN_BUFSIZE;
+ mnOutBufSize = DEFAULT_OUT_BUFSIZE;
+ mpsC_Stream = new z_stream;
+}
+
+// ------------------------------------------------------------------------
+
+ZCodec::~ZCodec()
+{
+ delete (z_stream*) mpsC_Stream;
+}
+
+// ------------------------------------------------------------------------
+
+void ZCodec::BeginCompression( ULONG nCompressMethod )
+{
+ mbInit = 0;
+ mbStatus = TRUE;
+ mbFinish = FALSE;
+ mpIStm = mpOStm = NULL;
+ mnInToRead = 0xffffffff;
+ mpInBuf = mpOutBuf = NULL;
+ PZSTREAM->total_out = PZSTREAM->total_in = 0;
+ mnCompressMethod = nCompressMethod;
+ PZSTREAM->zalloc = ( alloc_func )0;
+ PZSTREAM->zfree = ( free_func )0;
+ PZSTREAM->opaque = ( voidpf )0;
+ PZSTREAM->avail_out = PZSTREAM->avail_in = 0;
+}
+
+// ------------------------------------------------------------------------
+
+long ZCodec::EndCompression()
+{
+ long retvalue;
+
+ if ( mbInit != 0 )
+ {
+ if ( mbInit & 2 ) // 1->decompress, 3->compress
+ {
+ do
+ {
+ ImplWriteBack();
+ }
+ while ( deflate( PZSTREAM, Z_FINISH ) != Z_STREAM_END );
+
+ ImplWriteBack();
+
+ retvalue = PZSTREAM->total_in;
+ deflateEnd( PZSTREAM );
+ }
+ else
+ {
+ retvalue = PZSTREAM->total_out;
+ inflateEnd( PZSTREAM );
+ }
+ delete[] mpOutBuf;
+ delete[] mpInBuf;
+ }
+ return ( mbStatus ) ? retvalue : -1;
+}
+
+
+// ------------------------------------------------------------------------
+
+long ZCodec::Compress( SvStream& rIStm, SvStream& rOStm )
+{
+ char err;
+ long nOldTotal_In = PZSTREAM->total_in;
+
+ if ( mbInit == 0 )
+ {
+ mpIStm = &rIStm;
+ mpOStm = &rOStm;
+ ImplInitBuf( FALSE );
+ mpInBuf = new BYTE[ mnInBufSize ];
+ }
+ while (( PZSTREAM->avail_in = mpIStm->Read( PZSTREAM->next_in = mpInBuf, mnInBufSize )) != 0 )
+ {
+ if ( PZSTREAM->avail_out == 0 )
+ ImplWriteBack();
+ err = deflate( PZSTREAM, Z_NO_FLUSH );
+ if ( err < 0 )
+ {
+ mbStatus = FALSE;
+ break;
+ }
+ };
+ return ( mbStatus ) ? PZSTREAM->total_in - nOldTotal_In : -1;
+}
+
+// ------------------------------------------------------------------------
+
+long ZCodec::Decompress( SvStream& rIStm, SvStream& rOStm )
+{
+ char err;
+ ULONG nInToRead;
+ long nOldTotal_Out = PZSTREAM->total_out;
+
+ if ( mbFinish )
+ return PZSTREAM->total_out - nOldTotal_Out;
+
+ if ( mbInit == 0 )
+ {
+ mpIStm = &rIStm;
+ mpOStm = &rOStm;
+ ImplInitBuf( TRUE );
+ PZSTREAM->next_out = mpOutBuf = new BYTE[ PZSTREAM->avail_out = mnOutBufSize ];
+ }
+ do
+ {
+ if ( PZSTREAM->avail_out == 0 ) ImplWriteBack();
+ if ( PZSTREAM->avail_in == 0 && mnInToRead )
+ {
+ nInToRead = ( mnInBufSize > mnInToRead ) ? mnInToRead : mnInBufSize;
+ PZSTREAM->avail_in = mpIStm->Read( PZSTREAM->next_in = mpInBuf, nInToRead );
+ mnInToRead -= nInToRead;
+
+ if ( mnCompressMethod & ZCODEC_UPDATE_CRC )
+ mnCRC = UpdateCRC( mnCRC, mpInBuf, nInToRead );
+
+ }
+ err = inflate( PZSTREAM, Z_NO_FLUSH );
+ if ( err < 0 )
+ {
+ mbStatus = FALSE;
+ break;
+ }
+
+ }
+ while ( ( err != Z_STREAM_END) && ( PZSTREAM->avail_in || mnInToRead ) );
+ ImplWriteBack();
+
+ if ( err == Z_STREAM_END )
+ mbFinish = TRUE;
+ return ( mbStatus ) ? PZSTREAM->total_out - nOldTotal_Out : -1;
+}
+
+// ------------------------------------------------------------------------
+
+long ZCodec::Write( SvStream& rOStm, const BYTE* pData, ULONG nSize )
+{
+ if ( mbInit == 0 )
+ {
+ mpOStm = &rOStm;
+ ImplInitBuf( FALSE );
+ }
+
+ PZSTREAM->avail_in = nSize;
+ PZSTREAM->next_in = (unsigned char*)pData;
+
+ while ( PZSTREAM->avail_in || ( PZSTREAM->avail_out == 0 ) )
+ {
+ if ( PZSTREAM->avail_out == 0 )
+ ImplWriteBack();
+
+ if ( deflate( PZSTREAM, Z_NO_FLUSH ) < 0 )
+ {
+ mbStatus = FALSE;
+ break;
+ }
+ }
+ return ( mbStatus ) ? nSize : -1;
+}
+
+// ------------------------------------------------------------------------
+
+long ZCodec::Read( SvStream& rIStm, BYTE* pData, ULONG nSize )
+{
+ char err;
+ ULONG nInToRead;
+
+ if ( mbFinish )
+ return 0; // PZSTREAM->total_out;
+
+ mpIStm = &rIStm;
+ if ( mbInit == 0 )
+ {
+ ImplInitBuf( TRUE );
+ }
+ PZSTREAM->avail_out = nSize;
+ PZSTREAM->next_out = pData;
+ do
+ {
+ if ( PZSTREAM->avail_in == 0 && mnInToRead )
+ {
+ nInToRead = (mnInBufSize > mnInToRead) ? mnInToRead : mnInBufSize;
+ PZSTREAM->avail_in = mpIStm->Read (
+ PZSTREAM->next_in = mpInBuf, nInToRead);
+ mnInToRead -= nInToRead;
+
+ if ( mnCompressMethod & ZCODEC_UPDATE_CRC )
+ mnCRC = UpdateCRC( mnCRC, mpInBuf, nInToRead );
+
+ }
+ err = inflate( PZSTREAM, Z_NO_FLUSH );
+ if ( err < 0 )
+ {
+ // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
+ mbStatus = (err == Z_BUF_ERROR);
+ break;
+ }
+ }
+ while ( (err != Z_STREAM_END) &&
+ (PZSTREAM->avail_out != 0) &&
+ (PZSTREAM->avail_in || mnInToRead) );
+ if ( err == Z_STREAM_END )
+ mbFinish = TRUE;
+
+ return (mbStatus ? nSize - PZSTREAM->avail_out : -1);
+}
+
+// ------------------------------------------------------------------------
+
+#pragma optimize ("",off)
+
+long ZCodec::ReadAsynchron( SvStream& rIStm, BYTE* pData, ULONG nSize )
+{
+ char err;
+ ULONG nInToRead;
+
+ if ( mbFinish )
+ return 0; // PZSTREAM->total_out;
+
+ if ( mbInit == 0 )
+ {
+ mpIStm = &rIStm;
+ ImplInitBuf( TRUE );
+ }
+ PZSTREAM->avail_out = nSize;
+ PZSTREAM->next_out = pData;
+ do
+ {
+ if ( PZSTREAM->avail_in == 0 && mnInToRead )
+ {
+ nInToRead = (mnInBufSize > mnInToRead) ? mnInToRead : mnInBufSize;
+
+ ULONG nStreamPos = rIStm.Tell();
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ ULONG nMaxPos = rIStm.Tell();
+ rIStm.Seek( nStreamPos );
+ if ( ( nMaxPos - nStreamPos ) < nInToRead )
+ {
+ rIStm.SetError( ERRCODE_IO_PENDING );
+ break;
+ }
+
+ PZSTREAM->avail_in = mpIStm->Read (
+ PZSTREAM->next_in = mpInBuf, nInToRead);
+ mnInToRead -= nInToRead;
+
+ if ( mnCompressMethod & ZCODEC_UPDATE_CRC )
+ mnCRC = UpdateCRC( mnCRC, mpInBuf, nInToRead );
+
+ }
+ err = inflate( PZSTREAM, Z_NO_FLUSH );
+ if ( err < 0 )
+ {
+ // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
+ mbStatus = (err == Z_BUF_ERROR);
+ break;
+ }
+ }
+ while ( (err != Z_STREAM_END) &&
+ (PZSTREAM->avail_out != 0) &&
+ (PZSTREAM->avail_in || mnInToRead) );
+ if ( err == Z_STREAM_END )
+ mbFinish = TRUE;
+
+ return (mbStatus ? nSize - PZSTREAM->avail_out : -1);
+}
+
+#pragma optimize ("",on)
+
+// ------------------------------------------------------------------------
+
+void ZCodec::ImplWriteBack()
+{
+ ULONG nAvail = mnOutBufSize - PZSTREAM->avail_out;
+
+ if ( nAvail )
+ {
+ if ( mbInit & 2 && ( mnCompressMethod & ZCODEC_UPDATE_CRC ) )
+ mnCRC = UpdateCRC( mnCRC, mpOutBuf, nAvail );
+ mpOStm->Write( PZSTREAM->next_out = mpOutBuf, nAvail );
+ PZSTREAM->avail_out = mnOutBufSize;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ZCodec::SetBreak( ULONG nInToRead )
+{
+ mnInToRead = nInToRead;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ZCodec::GetBreak( void )
+{
+ return ( mnInToRead + PZSTREAM->avail_in );
+}
+
+// ------------------------------------------------------------------------
+
+void ZCodec::SetCRC( ULONG nCRC )
+{
+ mnCRC = nCRC;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ZCodec::GetCRC()
+{
+ return mnCRC;
+}
+
+// ------------------------------------------------------------------------
+
+void ZCodec::ImplInitBuf ( BOOL nIOFlag )
+{
+ if ( mbInit == 0 )
+ {
+ if ( nIOFlag )
+ {
+ mbInit = 1;
+ if ( mbStatus && ( mnCompressMethod & ZCODEC_GZ_LIB ) )
+ {
+ BYTE n1, n2, j, nMethod, nFlags;
+ for ( int i = 0; i < 2; i++ ) // gz - magic number
+ {
+ *mpIStm >> j;
+ if ( j != gz_magic[ i ] )
+ mbStatus = FALSE;
+ }
+ *mpIStm >> nMethod;
+ *mpIStm >> nFlags;
+ if ( nMethod != Z_DEFLATED )
+ mbStatus = FALSE;
+ if ( ( nFlags & GZ_RESERVED ) != 0 )
+ mbStatus = FALSE;
+ /* Discard time, xflags and OS code: */
+ mpIStm->SeekRel( 6 );
+ /* skip the extra field */
+ if ( nFlags & GZ_EXTRA_FIELD )
+ {
+ *mpIStm >> n1 >> n2;
+ mpIStm->SeekRel( n1 + ( n2 << 8 ) );
+ }
+ /* skip the original file name */
+ if ( nFlags & GZ_ORIG_NAME)
+ {
+ do
+ {
+ *mpIStm >> j;
+ }
+ while ( j && !mpIStm->IsEof() );
+ }
+ /* skip the .gz file comment */
+ if ( nFlags & GZ_COMMENT )
+ {
+ do
+ {
+ *mpIStm >> j;
+ }
+ while ( j && !mpIStm->IsEof() );
+ }
+ /* skip the header crc */
+ if ( nFlags & GZ_HEAD_CRC )
+ mpIStm->SeekRel( 2 );
+ if ( mbStatus )
+ mbStatus = ( inflateInit2( PZSTREAM, -MAX_WBITS) != Z_OK ) ? FALSE : TRUE;
+ }
+ else
+ {
+ mbStatus = ( inflateInit( PZSTREAM ) >= 0 );
+ }
+ mpInBuf = new BYTE[ mnInBufSize ];
+ }
+ else
+ {
+ mbInit = 3;
+
+ mbStatus = ( deflateInit2_( PZSTREAM, mnCompressMethod & 0xff, Z_DEFLATED,
+ MAX_WBITS, mnMemUsage, ( mnCompressMethod >> 8 ) & 0xff,
+ ZLIB_VERSION, sizeof( z_stream ) ) >= 0 );
+
+ PZSTREAM->next_out = mpOutBuf = new BYTE[ PZSTREAM->avail_out = mnOutBufSize ];
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ZCodec::UpdateCRC ( ULONG nLatestCRC, ULONG nNumber )
+{
+
+#ifdef __LITTLEENDIAN
+ nNumber = SWAPLONG( nNumber );
+#endif
+ return rtl_crc32( nLatestCRC, &nNumber, 4 );
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ZCodec::UpdateCRC ( ULONG nLatestCRC, BYTE* pSource, long nDatSize)
+{
+ return rtl_crc32( nLatestCRC, pSource, nDatSize );
+}
+
+// ------------------------------------------------------------------------
+
+void GZCodec::BeginCompression( ULONG nCompressMethod )
+{
+ ZCodec::BeginCompression( nCompressMethod | ZCODEC_GZ_LIB );
+};
+
+