/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SVDIO_HXX
#define _SVDIO_HXX

#include <bf_svtools/bf_solar.h>

#include <tools/stream.hxx>
class SvStream;
namespace binfilter {

////////////////////////////////////////////////////////////////////////////////////////////////////

const char SdrIOMagic [2]={'D','r'};
const char SdrIOModlID[2]={'M','d'}; // Model
const char SdrIOItPlID[2]={'I','P'}; // ItemPool
const char SdrIOLayrID[2]={'L','y'}; // Layer
const char SdrIOLSetID[2]={'L','S'}; // Layerset
const char SdrIOPageID[2]={'P','g'}; // Page
const char SdrIOMaPgID[2]={'M','P'}; // MasterPage (Stammseite)
const char SdrIOMPgDID[2]={'M','D'}; // MasterPageDescriptor
const char SdrIOMPDLID[2]={'M','L'}; // MasterPageDescriptorList
const char SdrIOHlpLID[2]={'H','l'}; // HelpLine
const char SdrIOHLstID[2]={'H','L'}; // HelpLineList
const char SdrIODObjID[2]={'O','b'}; // Object
const char SdrIOConnID[2]={'C','n'}; // ObjConnection (EdgeObj)
const char SdrIOViewID[2]={'V','w'}; // View
const char SdrIOPgVwID[2]={'P','V'}; // PageView
const char SdrIOEndeID[2]={'X','X'}; // Ende
const char SdrIOJoeMagic[4]={'J','o','e','M'}; // Um meine eigenen SubRecords zu erkennen

const int nAktSdrFileMajorVersion =  0;

// #84529# increase fileversion to be able to correct gradient rotation for 5.2 and earlierl
const int nAktSdrFileMinorVersion = 17; // = 16;

const int nAktSdrFileVersion = (nAktSdrFileMajorVersion <<8) + (nAktSdrFileMinorVersion);
const int nSdrFileVersion31 = 12; // Fileversion des Office 3.1
const int nSdrFileVersion40 = 13; // Fileversion des Office 4.0
const int nSdrFileVersion50 = 14; // Fileversion des Office 5.0
const int nSdrFileVersion51 = 15; // Fileversion des Office 5.1

// Fileversionen:
//  0= ??-04-1995  Initialversion.
//     24-04-1995  Offizielles Office 3.0 Beta I Shipping
//  1= 25-04-1995  Zus. Flag fuer Layer: Standardlayer (JOE)
//     26-04-1995  AttrObj: Beim Stylesheet-Namen wird zusaetzlich der CharSet gemerkt (SB)
//     28-04-1995  Neu: MasterPageDescriptoren (VisibleLayers f. Masterpages) (JOE)
//  2= 18-05-1995  Drehwinkel und Shearwinkel am Gruppenobjekt (JOE)
//     20-05-1995  EdgeObj nun von TextObj statt von PathObj abgeleitet (JOE)
//  3= 23-05-1995  Textrahmen werden nun durch RectObj dargestellt (JOE)
//  4= 31-05-1995  Weiteres persistentes Flag am Zeichenobjekt bNotVisibleAsMaster (JOE)
//     12-06-1995  Offizielles Office 3.0 Beta II Shipping
//     13-06-1996  bTextToContour raus und durch Item ersetzt (JOE)
//     14-06-1996  SdrItemPool muss nun ohne RefCounts geladen werden (JOE)
//  5= 14-06-1995  SdrOutlinerSetItem als neuer Member im SdrAttrObj (JOE)
//  6= 28-06-1995  Neue Items: pMiscAttr; -> Eckenradius-Member entfaellt am RectObj (JOE)
//  6= 30-06-1995  Neuer Member am SdrGrafObj: aCropRect (JOE)
//  6= 07-07-1995  Neue Items fuer Fontwork am XOutDev (ESO)
//     10-07-1995  Office 3.0 Beta III Shipping an IBM
//  7= 18-07-1995  PolyObj raus, Import am PathObj
//  8= 25-07-1995  GrafObj: zus. Member: aFileName fuer FileLinks
//  9= 02-08-1995  GrafObj: zus. Member: aFilterName fuer FileLinks
//     14-10-1995  Office 3.0 PreRelease fuer Systems Muenchen
//     21-10-1995  Final Office 3.0 Shipping
// 10= 25-10-1995  *pFormTextBoundRect wird gestreamt; Neue Attribute: TextVAdjust, Textabstaende
//     09-11-1995  entgueltiges Format V10 durch erneute Poolumstellung (ExtraPool raus)
// 11= 10-11-1995  - Nicht rueckwaertskompatibel!
//                 - Einfuehrung von Major/MinorVers.
//                 - Aufraeumer: Datensack am Obj f. Konnektoren,...
//                 - bMirrored und aName fuer GrafikObjekt
//                 - DownCompat fuer Grosses, Komplexes und Unbekanntes:
//                   - SdrObject:
//                     - Konnektoren (Flag davor)
//                     - UserDataList (Flag davor)
//                       - UserData
//                   - SdrTextObj:
//                     - OutlinerParaObject (Flag war schon davor)
//                   - SdrPathObj:
//                     - PathPolygon
//                   - SdrEdgeObj:
//                     - EdgeTrack
//                     - Connections haben nun einen eigenen IOHeader
//                   - SdrGrafObj:
//                     - Graphic (Flag davor)
//                     - zus. Flag fuer HasGraphicLink
//                   - SdrOle2Obj:
//                     - Graphic (Flag war schon da)
//                   - SdrModel:
//                     - DocInfo
//                     - DocStatistic (Platz reserviert)
//                     - Misc eingepackt
//                   - SdrPage:
//                     - Misc eingepackt
//                 - Kennung fuer SubRecord meines Model und meiner Page (JoeMagic)
//                 - SvdAttrObj: CharSet fuer StyleSheet entfaellt
//                 - CharSet weg bei SdrModel und SdrAttrObj
//                 - WhichId's weg bei SdrAttrObj und SdrCaptionObj
// 12= 05-12-1995  Neues Item: SdrTextHorzAdjustItem. Textverankerung an Textrahmen und
//                 Grafikobjekten. Beim Import von <V12 werden Grafikobjekte hart attributiert.
//     12-02-1996  UIScale und UIUnit wird vom Model nun rausgeschrieben
//     16-02-1996  Shipping des Office 3.00.2 (SV304a)
//     29-02-1996  Pool V3: 17 neue Items im XOut von KA fuer Bitmapfuellungen
//     13-03-1996  Version fuer CeBit 96
//  ca 15-04-1996  Shipping Version 3.1
//     10-08-1996  Pool Version 4; eigene Items am Verbinder
//     28-08-1996  CeBIT Home
//     21-01-1997  EdgeObj: EdgeInfo und Attribute
// 13= 05-02-1997  Fuer Franz's Dateiformatsumstellungen an der 3D-Engine
// 14= 13-03-1998  Fuer FmFormPage (FormLayer)
// 15= 19-01-1999  Fuer StarDraw-Preview
// 16= 25-08-1999  SdrPage background object


class SdrIOHeader
{
protected:
    // 10 Bytes persistent:
    char                        cMagic[2];
    char                        cHdrID[2];

    // Versionsnummer des Blocks
    UINT16                      nVersion;

    // Gesamtgroesse des Blocks inkl. Header und verschachtelten Bloecken
    UINT32                      nBlkSize;

    // ab hier Verwaltungsinformationen:
    SvStream&                   rStream;
    UINT32                      nFilePos;
    UINT16                      nMode;
    BOOL                        bOpen;
    BOOL                        bClosed;
    // Header wird nur zum nachschauen verwendet.
    BOOL                        bLookAhead;

    virtual void Write();
    virtual void Read();

public:
    SdrIOHeader(SvStream& rNewStream, UINT16 nNewMode, const char cID[2]=SdrIOEndeID, BOOL bAutoOpen=TRUE);
    virtual ~SdrIOHeader();

    BOOL IsMagic() const { return cMagic[0] == SdrIOMagic[0] && cMagic[1] == SdrIOMagic[1];  }
    void SetMagic() { cMagic[0] = SdrIOMagic[0]; cMagic[1] = SdrIOMagic[1]; }
    BOOL IsEnde() const { return cHdrID[0] == SdrIOEndeID[0] && cHdrID[1] == SdrIOEndeID[1]; }
    void SetEnde() { cHdrID[0] = SdrIOEndeID[0]; cHdrID[1] = SdrIOEndeID[1]; nBlkSize = 0; SetMagic(); }
    BOOL IsID(const char cID[2]) const { return cHdrID[0] == cID[0] && cHdrID[1] == cID[1]; }
    void SetID(const char cID[2]) { cHdrID[0] = cID[0]; cHdrID[1] = cID[1]; SetMagic(); }
    UINT16 GetVersion() const { return nVersion; }
    UINT16 GetMinorVersion() const { return nVersion | 0xFF; }
    UINT16 GetMajorVersion() const { return nVersion >>8; }
    UINT32 GetFilePos() const { return nFilePos; }
    UINT32 GetBlockSize() const { return nBlkSize; }
    void OpenRecord();
    void CloseRecord();
    UINT32 GetBytesLeft() const;
};

class SdrIOHeaderLookAhead: public SdrIOHeader
{
public:
    SdrIOHeaderLookAhead(SvStream& rNewStream, BOOL bAutoOpen = TRUE);
    void SkipRecord() const { rStream.Seek(nFilePos+nBlkSize); }
};

/*
I/O-Format (12+n Bytes)
 4 Inventor
 2 Version
 2 Identifier
 4 Menge der nachfolgenden Daten in Bytes
-------
 2 Layer
16 Allumschliessendes Rechteck
 n>=18 Objektspezifische Daten
*/
//const SdrObjIOHeaderSize=6;

class SdrObject;

class SdrObjIOHeader: public SdrIOHeader
{
public:
    // ab hier persistente Daten
    UINT32                      nInventor;
    UINT16                      nIdentifier;

    // ab hier Verwaltungsinformationen
    const SdrObject*            pObj;

protected:
    virtual void Write();
    virtual void Read();

public:
    SdrObjIOHeader(SvStream& rNewStream, UINT16 nNewMode, const SdrObject* pNewObj = NULL, BOOL bAutoOpen = TRUE);

    // DTor ueberladen, den in Dtor von SdrIOHeader lebt der SdrObjIOJHeader nicht mehr.
    virtual ~SdrObjIOHeader();
};

class SdrObjIOHeaderLookAhead: public SdrObjIOHeader
{
public:
    SdrObjIOHeaderLookAhead(SvStream& rNewStream, BOOL bAutoOpen = TRUE);
    void SkipRecord() const { rStream.Seek(nFilePos+nBlkSize); }
};

// Klasse fuer Abwaertskompatibilitaet (Lesen neuer Daten mit altem Code)
// In der Regel reicht es aus, diese Klasse am Anfang des Lese/Schreibfokus
// auf dem Stack mit bAutoOpen=TRUE (default) zu instanziieren. Der Rest
// geschieht von selbst. Will man am Ende des Lesens wissen, ob noch weitere
// Daten im Sub-Record enthalten sind, ruft man GetBytesLeft().
// Den SubRecord schliesst man entweder mit CloseSubRecord() oder man laesst
// ihn vom Destruktor automatisch schliessen.
// Dieses Konzept setzt jedoch eine feste Reihenfolge und Anzahl der SubRecords
// voraus.
class SdrDownCompat
{
protected:
    SvStream&                   rStream;
    UINT32                      nSubRecSiz;
    UINT32                      nSubRecPos;
    UINT16                      nMode;
    BOOL                        bOpen;
    BOOL                        bClosed;

    // nur fuer Debug
    const char*                 pRecId;

protected:
    virtual void Read();
    virtual void Write();

public:
    // Als Modus muss STREAM_READ oder STREAM_WRITE angegeben werden.
    SdrDownCompat(SvStream& rNewStream, UINT16 nNewMode, BOOL bAutoOpen = TRUE);
    ~SdrDownCompat();

#ifdef DBG_UTIL
    // fuer etwas aussagekraeftigere Assertions
    void SetID(const char* pId) { pRecId=pId; }
#endif

    // Mit GetBytesLeft() kann man abfragen, ob und wieviele Bytes noch
    // im SubRecord stehen. Nur gueltig bei STREAM_READ, sonst 0.
    // Nach CloseRecord() liefert diese Methode auch im Modus STREAM_READ 0.
    // (Denn dann sind die restlichen Bytes bereits uebersprungen.)
    UINT32 GetBytesLeft() const;
    BOOL IsOpen() const { return bOpen; }

    // Die Pos ist erst gueltig nach Open bzw nach CTor mit bAutoOpen=TRUE.
    UINT32 GetSubRecordPos() const { return nSubRecPos; }

    // Erst gueltig nach Open bzw. nach CTor mit bAutoOpen=TRUE.
    // Beim Modus STREAM_WRITE ist die Size erst nach Close() gueltig.
    UINT32 GetSubRecordSize() const { return nSubRecSiz; }
    void  OpenSubRecord();
    void  CloseSubRecord();
};

// Identifier fuer SdrNamedSubRecord bei Inventor==SdrInventor
enum {SDRIORECNAME_VIEWPAGEVIEWS   =0x0000,  // alle Pageviews, angezeigte und nicht angezeigte
      SDRIORECNAME_VIEWVISIELEM    =0x0001,  // sichtbare Elemente (Seite, Rand, Gitter, Hilfslinien,...)

      SDRIORECNAME_VIEWSNAP        =0x0010,  // Fangeinstellungen
      SDRIORECNAME_VIEWORTHO       =0x0011,  // Einstellungen fuer Ortho

      SDRIORECNAME_VIEWDRAGMODE    =0x0020,  // Move oder Rotate/Slant/..., bEditMode, RefPoints, FramDragSingles, PlusAlways
      SDRIORECNAME_VIEWMARKEDOBJ   =0x0021,  // (ni) markierte Objekte
      SDRIORECNAME_VIEWMARKEDPNT   =0x0022,  // (ni) markierte Punkte
      SDRIORECNAME_VIEWCROOKCENTER =0x0023,  // Kreismittelpunkt des letzten Crook
      SDRIORECNAME_VIEWMARKEDGLUE  =0x0024,  // (ni) markierte Klebepunkte

      SDRIORECNAME_VIEWDRAGSTRIPES =0x0030,  // Animierte Begrenzungslinien waerend des Draeggens
      SDRIORECNAME_VIEWDRAGHIDEHDL =0x0031,  // Handles waerend des Draeggens verstecken
      SDRIORECNAME_VIEWDRAGEDGES   =0x0032,  // (ni) Einstellungen fuer EdgeDragging
      SDRIORECNAME_VIEWOBJHITMOVES =0x0033,  // Bei MarkedHit Move oder DragMode
      SDRIORECNAME_VIEWMIRRDRAGOBJ =0x0034,  // Obj beim schieben der Spiegelachse zeigen

      SDRIORECNAME_VIEWCROBJECT    =0x0040,  // Aktuelles CreateObj
      SDRIORECNAME_VIEWAKTLAYER    =0x0041,  // Layer fuer Create und Paste (nun in der PaintView)
      SDRIORECNAME_VIEWCRATTRIBUTES=0x0042,  // (ni) Attribute fuer Create
      SDRIORECNAME_VIEWCRSTYLESHEET=0x0043,  // (ni) StyleSheet fuer Create
      SDRIORECNAME_VIEWCRFLAGS     =0x0044,  // Misc Flags fuer Create

      SDRIORECNAME_VIEWTEXTEDIT    =0x0050,  // Div. Einstellungen fuer TextEdit
      SDRIORECNAME_VIEWMACRO       =0x0051,  // Div. Einstellungen fuer Macro

      SDRIORECNAME_VIEWCHARSET     =0x0080,  // Hier merkt sich die SdrView den CharSet und setzt diesem beim Read am Stream

      SDRIORECNAME_PAGVIEW         =0x0100,  // Pageview sichtbar, Seitennummer, Position, Ursprung
      SDRIORECNAME_PAGVLAYER       =0x0101,  // angezeigte, gesperrte und druckbare Layer
      SDRIORECNAME_PAGVHELPLINES   =0x0102,  // Hilfslinien und -punkte
      SDRIORECNAME_PAGVAKTGROUP    =0x0103,  // (ni) aktuelle Gruppe

      SDRIORECNAME_MARK            =0x0200,  // (ni)

      SDRIORECNAME_USERDEFINEDFIRST=0x7000,
      SDRIORECNAME_USERDEFINEDLAST =0x7FFF};

class SdrNamedSubRecord: public SdrDownCompat
{
    UINT32                      nInventor;
    UINT16                      nIdentifier;

protected:
    virtual void Read();
    virtual void Write();

public:
    SdrNamedSubRecord(SvStream& rNewStream, UINT16 nNewMode,
        UINT32 nNewInventor = 0xFFFF, UINT16 nNewIdentifier = 0xFFFF,
        BOOL bAutoOpen = TRUE);
    UINT32 GetInventor() const { return nInventor; }
    UINT16 GetIdentifier() const { return nIdentifier; }
};

// Zum Speichern einer View habe ich ein etwas anderes Konzept gewaehlt, da
// sich das Dateiformat hier sicherlich haeufiger und aufwendiger aendert.
// Es werden eine Anzahl von SdrNamedSubRecords geschrieben, wobei jeder
// dieser Records bestimmte Teilinformationen enthaelt, z.B. die Menge der
// sichtbaren Layer einer Page oder den Default-Stylesheet fuer neu zu
// erzeugende Objekte, ... . Diese Konzept hat zwar einen groesseren Overhead
// an Verwaltung und Daten zur Folge, bietet dafuer jedoch eine sehr grosse
// Flexibilitaet im Punkte auf-/abwaertskompatibilitaet. Da die Menge der
// persistenten Daten einer View recht gering ist spielt der Overhead an
// Streamdaten kaum eine Rolle.
// Eine abgeleitete View ueberlaed die Methoden ReadRecord() (lesen eines
// einzelnen Records) und WriteRecords() (schreiben aller Records). Ein Muster
// ist in SdrSnpV.CXX zu finden.

// Folgende Methoden schauen nach, ob sich im Stream an der aktuellen Position
// ein SdrModel bzw. eine SdrView befindet. Hat der Stream einen Fehlerstatus
// oder Eof(), so wird FALSE returniert.

}//end of namespace binfilter
#endif //_SVDIO_HXX

/* /////////////////////////////////////////////////////////////////////////////////////////////////

IO-Datenstruktur:

?--------?    ?---?              ?---?
| SdrData | --->�Modl??---->----?>�Ende?-->
?--------?    ?---?  ?---?   ?---?
                       ?-�View?-?
                          ?---?

?-----?        ?------?  ?------? ?-------?               ?---?
| Modl |     --->�ModlHdr?->�ModlDat?>�ItemPool?>?---->----?>�Ende?-->
?-----?        ?------?  ?------? ?-------?   ?---?   ?---?
                                                    ?-�Layr?-?
                                                    |  ?---? |
                                                      ?---? 
                                                    ?-�LSet?-?
                                                    |  ?---? |
                                                      ?---? 
                                                    ?-�Page?-?
                                                       ?---?

?-------?      ?----------?  ?----------?
|ItemPool|   --->�ItemPoolHdr?->�SfxItemPool?-->
?-------?      ?----------?  ?----------?

?-----?        ?------?  ?------?               ?-------?
| Page |     --->�PageHdr?->�PageDat?>?---->----?>�DObjList?-->
?-----?        ?------?  ?------?   ?---?   ?-------?
                                        ?-�Layr?-?
                                        |  ?---? |
                                          ?---? 
                                        ?-�LSet?-?
                                           ?---?

?---------?                    ?---?
| DObjList | --->?----->-----?>�Ende?-->
?---------?      ?-----?   ?---?
                 ?-?DObj ?-?
                    ?-----?

?-----?        ?------?  ?------?
| DObj |     --->�DObjHdr?->�DObjDat?->?----->-------?-->
?-----?        ?------?  ?------?    ?-------? 
                                         ?>�DObjList?>?
                                            ?-------?
?-----?        ?------?  ?------?
| Layr |     --->�LayrHdr?->�LayrDat?-->
?-----?        ?------?  ?------?

?-----?        ?------?  ?------?
| LSet |     --->�LSetHdr?->�LSetDat?-->
?-----?        ?------?  ?------?

?-----?        ?------?  ?------?
| View |     --->�ViewHdr?->�ViewDat?-->
?-----?        ?------?  ?------?

///////////////////////////////////////////////////////////////////////////////////////////////// */

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
