1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: $
10  * $Revision: $
11  *
12  * This file is part of OpenOffice.org.
13  *
14  * OpenOffice.org is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License version 3
16  * only, as published by the Free Software Foundation.
17  *
18  * OpenOffice.org is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU Lesser General Public License version 3 for more details
22  * (a copy is included in the LICENSE file that accompanied this code).
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * version 3 along with OpenOffice.org.  If not, see
26  * <http://www.openoffice.org/license.html>
27  * for a copy of the LGPLv3 License.
28  *
29  ************************************************************************/
30 
31 #include "precompiled_sw.hxx"
32 
33 #include <parachangetrackinginfo.hxx>
34 
35 #include <errhdl.hxx>
36 #include <wrong.hxx>
37 #include <com/sun/star/text/TextMarkupType.hpp>
38 
39 #include <txtfrm.hxx>
40 #include <ndtxt.hxx>
41 #include <IDocumentRedlineAccess.hxx>
42 #include <docary.hxx>
43 #include <redline.hxx>
44 
45 namespace css = com::sun::star;
46 
47 namespace {
48     void initChangeTrackTextMarkupLists( const SwTxtFrm& rTxtFrm,
49                                          SwWrongList*& opChangeTrackInsertionTextMarkupList,
50                                          SwWrongList*& opChangeTrackDeletionTextMarkupList,
51                                          SwWrongList*& opChangeTrackFormatChangeTextMarkupList )
52     {
53         opChangeTrackInsertionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
54         opChangeTrackDeletionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
55         opChangeTrackFormatChangeTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
56 
57         if ( !rTxtFrm.GetTxtNode() )
58         {
59             ASSERT( false,
60                     "<initChangeTrackTextMarkupLists(..) - missing <SwTxtNode> instance!" );
61             return;
62         }
63         const SwTxtNode& rTxtNode( *(rTxtFrm.GetTxtNode()) );
64 
65         const IDocumentRedlineAccess* pIDocChangeTrack( rTxtNode.getIDocumentRedlineAccess() );
66         if ( !pIDocChangeTrack )
67         {
68             ASSERT( false,
69                     "<initChangeTrackTextMarkupLists(..) - missing <IDocumentRedlineAccess> instance!" );
70             return;
71         }
72 
73         if ( !IDocumentRedlineAccess::IsShowChanges( pIDocChangeTrack->GetRedlineMode() ) ||
74              pIDocChangeTrack->GetRedlineTbl().Count() == 0 )
75         {
76             // nothing to do --> empty change track text markup lists.
77             return;
78         }
79 
80         const sal_uInt16 nIdxOfFirstRedlineForTxtNode =
81                     pIDocChangeTrack->GetRedlinePos( rTxtNode, USHRT_MAX );
82         if ( nIdxOfFirstRedlineForTxtNode == USHRT_MAX )
83         {
84             // nothing to do --> empty change track text markup lists.
85             return;
86         }
87 
88         const xub_StrLen nTxtFrmTextStartPos = rTxtFrm.IsFollow()
89                                                ? rTxtFrm.GetOfst()
90                                                : 0;
91         const xub_StrLen nTxtFrmTextEndPos = rTxtFrm.HasFollow()
92                                              ? rTxtFrm.GetFollow()->GetOfst()
93                                              : rTxtFrm.GetTxt().Len();
94 
95         // iteration over the redlines which overlap with the text node.
96         const SwRedlineTbl& rRedlineTbl = pIDocChangeTrack->GetRedlineTbl();
97         const sal_uInt16 nRedlineCount( rRedlineTbl.Count() );
98         for ( sal_uInt16 nActRedline = nIdxOfFirstRedlineForTxtNode;
99               nActRedline < nRedlineCount;
100               ++nActRedline)
101         {
102             const SwRedline* pActRedline = rRedlineTbl[ nActRedline ];
103             if ( pActRedline->Start()->nNode > rTxtNode.GetIndex() )
104             {
105                 break;
106             }
107 
108             xub_StrLen nTxtNodeChangeTrackStart( STRING_LEN );
109             xub_StrLen nTxtNodeChangeTrackEnd( STRING_LEN );
110             pActRedline->CalcStartEnd( rTxtNode.GetIndex(),
111                                        nTxtNodeChangeTrackStart,
112                                        nTxtNodeChangeTrackEnd );
113             if ( nTxtNodeChangeTrackStart > nTxtFrmTextEndPos ||
114                  nTxtNodeChangeTrackEnd < nTxtFrmTextStartPos )
115             {
116                 // Consider only redlines which overlap with the text frame's text.
117                 continue;
118             }
119 
120             SwWrongList* pMarkupList( 0 );
121             switch ( pActRedline->GetType() )
122             {
123                 case nsRedlineType_t::REDLINE_INSERT:
124                 {
125                     pMarkupList = opChangeTrackInsertionTextMarkupList;
126                 }
127                 break;
128                 case nsRedlineType_t::REDLINE_DELETE:
129                 {
130                     pMarkupList = opChangeTrackDeletionTextMarkupList;
131                 }
132                 break;
133                 case nsRedlineType_t::REDLINE_FORMAT:
134                 {
135                     pMarkupList = opChangeTrackFormatChangeTextMarkupList;
136                 }
137                 break;
138                 default:
139                 {
140                     // other types are not considered
141                 }
142             }
143             if ( pMarkupList )
144             {
145                 const xub_StrLen nTxtFrmChangeTrackStart =
146                                     nTxtNodeChangeTrackStart <= nTxtFrmTextStartPos
147                                     ? nTxtFrmTextStartPos
148                                     : nTxtNodeChangeTrackStart;
149 
150                 const xub_StrLen nTxtFrmChangeTrackEnd =
151                                     nTxtNodeChangeTrackEnd >= nTxtFrmTextEndPos
152                                     ? nTxtFrmTextEndPos
153                                     : nTxtNodeChangeTrackEnd;
154 
155                 pMarkupList->Insert( rtl::OUString(), 0,
156                                      nTxtFrmChangeTrackStart,
157                                      nTxtFrmChangeTrackEnd - nTxtFrmChangeTrackStart,
158                                      pMarkupList->Count() );
159             }
160         } // eof iteration over the redlines which overlap with the text node
161     }
162 } // eof anonymous namespace
163 
164 SwParaChangeTrackingInfo::SwParaChangeTrackingInfo( const SwTxtFrm& rTxtFrm )
165     : mrTxtFrm( rTxtFrm )
166     , mpChangeTrackInsertionTextMarkupList( 0 )
167     , mpChangeTrackDeletionTextMarkupList( 0 )
168     , mpChangeTrackFormatChangeTextMarkupList( 0 )
169 {
170 }
171 
172 
173 SwParaChangeTrackingInfo::~SwParaChangeTrackingInfo()
174 {
175     reset();
176 }
177 
178 void SwParaChangeTrackingInfo::reset()
179 {
180     delete mpChangeTrackInsertionTextMarkupList;
181     mpChangeTrackInsertionTextMarkupList = 0;
182 
183     delete mpChangeTrackDeletionTextMarkupList;
184     mpChangeTrackDeletionTextMarkupList = 0;
185 
186     delete mpChangeTrackFormatChangeTextMarkupList;
187     mpChangeTrackFormatChangeTextMarkupList = 0;
188 }
189 
190 const SwWrongList* SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList( const sal_Int32 nTextMarkupType )
191 {
192     SwWrongList* pChangeTrackingTextMarkupList = 0;
193 
194     if ( mpChangeTrackInsertionTextMarkupList == 0 )
195     {
196         ASSERT( mpChangeTrackDeletionTextMarkupList == 0,
197                 "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackDeletionTextMarkupList> expected to be NULL." );
198         ASSERT( mpChangeTrackFormatChangeTextMarkupList == 0,
199                 "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackFormatChangeTextMarkupList> expected to be NULL." );
200         initChangeTrackTextMarkupLists( mrTxtFrm,
201                                         mpChangeTrackInsertionTextMarkupList,
202                                         mpChangeTrackDeletionTextMarkupList,
203                                         mpChangeTrackFormatChangeTextMarkupList );
204     }
205 
206     switch ( nTextMarkupType )
207     {
208         case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
209         {
210             pChangeTrackingTextMarkupList = mpChangeTrackInsertionTextMarkupList;
211         }
212         break;
213         case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
214         {
215             pChangeTrackingTextMarkupList = mpChangeTrackDeletionTextMarkupList;
216         }
217         break;
218         case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
219         {
220             pChangeTrackingTextMarkupList = mpChangeTrackFormatChangeTextMarkupList;
221         }
222         break;
223         default:
224         {
225             ASSERT( false,
226                     "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..)> - misusage - unexpected text markup type for change tracking." );
227         }
228     }
229 
230     return pChangeTrackingTextMarkupList;
231 }
232