1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21
22 #include <algorithm>
23
24 #include <rtl/strbuf.hxx>
25 #include <osl/diagnose.h>
26 #include <sal/log.hxx>
27
28 #include <object.hxx>
29 #include <globals.hxx>
30 #include <database.hxx>
31
32
SvClassElement()33 SvClassElement::SvClassElement()
34 {
35 };
36
SvMetaClass()37 SvMetaClass::SvMetaClass()
38 {
39 }
40
ReadContextSvIdl(SvIdlDataBase & rBase,SvTokenStream & rInStm)41 void SvMetaClass::ReadContextSvIdl( SvIdlDataBase & rBase,
42 SvTokenStream & rInStm )
43 {
44 sal_uInt32 nTokPos = rInStm.Tell();
45 SvToken& rTok = rInStm.GetToken_Next();
46
47 if( rTok.Is( SvHash_import() ) )
48 {
49 SvMetaClass * pClass = rBase.ReadKnownClass( rInStm );
50 if( !pClass )
51 throw SvParseException( rInStm, "unknown imported interface" );
52 SvClassElement aEle;
53 aEle.SetClass( pClass );
54 aClassElementList.push_back( aEle );
55
56 rTok = rInStm.GetToken();
57 if( rTok.IsString() )
58 {
59 aEle.SetPrefix( rTok.GetString() );
60 rInStm.GetToken_Next();
61 }
62 return;
63 }
64 else
65 {
66 rInStm.Seek( nTokPos );
67 SvMetaType * pType = rBase.ReadKnownType( rInStm );
68
69 bool bOk = false;
70 tools::SvRef<SvMetaAttribute> xAttr;
71 if( !pType || pType->IsItem() )
72 {
73 xAttr = new SvMetaSlot( pType );
74 if( xAttr->ReadSvIdl( rBase, rInStm ) )
75 bOk = xAttr->Test( rInStm );
76 }
77 else
78 {
79 xAttr = new SvMetaAttribute( pType );
80 if( xAttr->ReadSvIdl( rBase, rInStm ) )
81 bOk = xAttr->Test( rInStm );
82 }
83
84 if( bOk )
85 bOk = TestAttribute( rBase, rInStm, *xAttr );
86 if( bOk )
87 {
88 if( !xAttr->GetSlotId().IsSet() )
89 {
90 SvIdentifier aI;
91 aI.SetValue( rBase.GetUniqueId() );
92 xAttr->SetSlotId( aI );
93 }
94 aAttrList.push_back( xAttr.get() );
95 return;
96 }
97 }
98 rInStm.Seek( nTokPos );
99 }
100
TestAttribute(SvIdlDataBase & rBase,SvTokenStream & rInStm,SvMetaAttribute & rAttr) const101 bool SvMetaClass::TestAttribute( SvIdlDataBase & rBase, SvTokenStream & rInStm,
102 SvMetaAttribute & rAttr ) const
103 {
104 if ( !rAttr.GetRef() && dynamic_cast<const SvMetaSlot *>(&rAttr) )
105 {
106 SAL_WARN( "idl", "new slot : " << rAttr.GetSlotId().getString() );
107 }
108
109 for( size_t n = 0; n < aAttrList.size(); n++ )
110 {
111 SvMetaAttribute * pS = aAttrList[n];
112 if( pS->GetName() == rAttr.GetName() )
113 {
114 // values have to match
115 if( pS->GetSlotId().GetValue() != rAttr.GetSlotId().GetValue() )
116 {
117 throw SvParseException( rInStm, "Attribute's " + pS->GetName() + " with different id's");
118 }
119 }
120 else
121 {
122 sal_uInt32 nId1 = pS->GetSlotId().GetValue();
123 sal_uInt32 nId2 = rAttr.GetSlotId().GetValue();
124 if( nId1 == nId2 && nId1 != 0 )
125 {
126 OString aStr = "Attribute " + pS->GetName() + " and Attribute " + rAttr.GetName() + " with equal id's";
127 throw SvParseException(rInStm, aStr);
128 }
129 }
130 }
131 SvMetaClass * pSC = aSuperClass.get();
132 if( pSC )
133 return pSC->TestAttribute( rBase, rInStm, rAttr );
134 return true;
135 }
136
WriteSlotParamArray(SvIdlDataBase & rBase,SvSlotElementList & rSlotList,SvStream & rOutStm)137 sal_uInt16 SvMetaClass::WriteSlotParamArray( SvIdlDataBase & rBase,
138 SvSlotElementList & rSlotList,
139 SvStream & rOutStm )
140 {
141 sal_uInt16 nCount = 0;
142 for ( size_t i = 0, n = rSlotList.size(); i < n; ++i )
143 {
144 SvMetaSlot *pAttr = rSlotList[ i ];
145 nCount = nCount + pAttr->WriteSlotParamArray( rBase, rOutStm );
146 }
147
148 return nCount;
149 }
150
WriteSlots(std::string_view rShellName,SvSlotElementList & rSlotList,SvIdlDataBase & rBase,SvStream & rOutStm)151 sal_uInt16 SvMetaClass::WriteSlots( std::string_view rShellName,
152 SvSlotElementList & rSlotList,
153 SvIdlDataBase & rBase,
154 SvStream & rOutStm )
155 {
156 sal_uInt16 nSCount = 0;
157 for ( size_t i = 0, n = rSlotList.size(); i < n; ++i )
158 {
159 SvMetaSlot * pAttr = rSlotList[ i ];
160 nSCount = nSCount + pAttr->WriteSlotMap( rShellName, nSCount,
161 rSlotList, i, rBase,
162 rOutStm );
163 }
164
165 return nSCount;
166 }
167
InsertSlots(SvSlotElementList & rList,std::vector<sal_uLong> & rSuperList,SvMetaClassList & rClassList,const OString & rPrefix,SvIdlDataBase & rBase)168 void SvMetaClass::InsertSlots( SvSlotElementList& rList, std::vector<sal_uLong>& rSuperList,
169 SvMetaClassList &rClassList,
170 const OString& rPrefix, SvIdlDataBase& rBase)
171 {
172 // was this class already written?
173 for ( size_t i = 0, n = rClassList.size(); i < n ; ++i )
174 if ( rClassList[ i ] == this )
175 return;
176
177 rClassList.push_back( this );
178
179 // write all direct attributes
180 sal_uLong n;
181 for( n = 0; n < aAttrList.size(); n++ )
182 {
183 SvMetaAttribute * pAttr = aAttrList[n];
184
185 sal_uLong nId = pAttr->GetSlotId().GetValue();
186
187 std::vector<sal_uLong>::iterator iter = std::find(rSuperList.begin(),
188 rSuperList.end(),nId);
189
190 if( iter == rSuperList.end() )
191 {
192 // Write only if not already written by subclass or
193 // imported interface.
194 rSuperList.push_back(nId);
195 pAttr->Insert(rList);
196 }
197 }
198
199 // All Interfaces already imported by SuperShell should not be
200 // written any more.
201 // It is prohibited that Shell and SuperShell directly import the same
202 // class.
203 if( GetMetaTypeType() == MetaTypeType::Shell && aSuperClass.is() )
204 aSuperClass->FillClasses( rClassList );
205
206 // Write all attributes of the imported classes, as long as they have
207 // not already been imported by the superclass.
208 for( n = 0; n < aClassElementList.size(); n++ )
209 {
210 SvClassElement& rElement = aClassElementList[n];
211 SvMetaClass * pCl = rElement.GetClass();
212 OStringBuffer rPre(rPrefix.getLength() + 1 + rElement.GetPrefix().getLength());
213 rPre.append(rPrefix);
214 if( !rPre.isEmpty() && !rElement.GetPrefix().isEmpty() )
215 rPre.append('.');
216 rPre.append(rElement.GetPrefix());
217
218 // first of all write direct imported interfaces
219 pCl->InsertSlots( rList, rSuperList, rClassList,
220 rPre.makeStringAndClear(), rBase );
221 }
222
223 // only write superclass if no shell and not in the list
224 if( GetMetaTypeType() != MetaTypeType::Shell && aSuperClass.is() )
225 {
226 aSuperClass->InsertSlots( rList, rSuperList, rClassList, rPrefix, rBase );
227 }
228 }
229
FillClasses(SvMetaClassList & rList)230 void SvMetaClass::FillClasses( SvMetaClassList & rList )
231 {
232 // Am I not yet in?
233 for ( size_t i = 0, n = rList.size(); i < n; ++i )
234 if ( rList[ i ] == this )
235 return;
236
237 rList.push_back( this );
238
239 // my imports
240 for( size_t n = 0; n < aClassElementList.size(); n++ )
241 {
242 SvClassElement& rElement = aClassElementList[n];
243 SvMetaClass * pCl = rElement.GetClass();
244 pCl->FillClasses( rList );
245 }
246
247 // my superclass
248 if( aSuperClass.is() )
249 aSuperClass->FillClasses( rList );
250 }
251
252
WriteSlotStubs(std::string_view rShellName,SvSlotElementList & rSlotList,std::vector<OString> & rList,SvStream & rOutStm)253 void SvMetaClass::WriteSlotStubs( std::string_view rShellName,
254 SvSlotElementList & rSlotList,
255 std::vector<OString> & rList,
256 SvStream & rOutStm )
257 {
258 // write all attributes
259 for ( size_t i = 0, n = rSlotList.size(); i < n; ++i )
260 {
261 SvMetaSlot *pAttr = rSlotList[ i ];
262 pAttr->WriteSlotStubs( rShellName, rList, rOutStm );
263 }
264 }
265
WriteSfx(SvIdlDataBase & rBase,SvStream & rOutStm)266 void SvMetaClass::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm )
267 {
268 WriteStars( rOutStm );
269 // define class
270 rOutStm.WriteCharPtr( "#ifdef ShellClass_" ).WriteOString( GetName() ) << endl;
271 rOutStm.WriteCharPtr( "#undef ShellClass" ) << endl;
272 rOutStm.WriteCharPtr( "#undef ShellClass_" ).WriteOString( GetName() ) << endl;
273 rOutStm.WriteCharPtr( "#define ShellClass " ).WriteOString( GetName() ) << endl;
274
275 // no slotmaps get written for interfaces
276 if( GetMetaTypeType() != MetaTypeType::Shell )
277 {
278 rOutStm.WriteCharPtr( "#endif" ) << endl << endl;
279 return;
280 }
281 // write parameter array
282 rOutStm.WriteCharPtr("static SfxFormalArgument a").WriteOString(GetName()).WriteCharPtr("Args_Impl[] =") << endl;
283 rOutStm.WriteChar('{') << endl;
284
285 std::vector<sal_uLong> aSuperList;
286 SvMetaClassList classList;
287 SvSlotElementList aSlotList;
288 InsertSlots(aSlotList, aSuperList, classList, OString(), rBase);
289 for ( size_t i = 0, n = aSlotList.size(); i < n; ++i )
290 {
291 SvMetaSlot *pSlot = aSlotList[ i ];
292 pSlot->SetListPos( i );
293 }
294
295 size_t nSlotCount = aSlotList.size();
296
297 // write all attributes
298 sal_uInt16 nArgCount = WriteSlotParamArray( rBase, aSlotList, rOutStm );
299 if( nArgCount )
300 Back2Delimiter( rOutStm );
301 else
302 {
303 // at least one dummy
304 WriteTab( rOutStm, 1 );
305 rOutStm.WriteCharPtr("{ (const SfxType*) &aSfxVoidItem_Impl, 0, 0 }" ) << endl;
306 }
307 rOutStm << endl;
308 rOutStm.WriteCharPtr( "};" ) << endl << endl;
309
310 std::vector<OString> aStringList;
311 WriteSlotStubs( GetName(), aSlotList, aStringList, rOutStm );
312 aStringList.clear();
313
314 rOutStm << endl;
315
316 // write slotmap
317 rOutStm.WriteCharPtr("static SfxSlot a").WriteOString(GetName()).WriteCharPtr("Slots_Impl[] =") << endl;
318 rOutStm.WriteChar( '{' ) << endl;
319
320 // write all attributes
321 WriteSlots( GetName(), aSlotList, rBase, rOutStm );
322 if( nSlotCount )
323 Back2Delimiter( rOutStm );
324 else
325 {
326 // at least one dummy
327 WriteTab( rOutStm, 1 );
328 rOutStm.WriteCharPtr( "SFX_SLOT_ARG(" ).WriteOString( GetName() )
329 .WriteCharPtr( ", 0, SfxGroupId::NONE, " )
330 .WriteCharPtr( "SFX_STUB_PTR_EXEC_NONE," )
331 .WriteCharPtr( "SFX_STUB_PTR_STATE_NONE," )
332 .WriteCharPtr( "SfxSlotMode::NONE, SfxVoidItem, 0, 0, \"\", SfxSlotMode::NONE )" ) << endl;
333 }
334 rOutStm << endl;
335 rOutStm.WriteCharPtr( "};" ) << endl;
336 rOutStm.WriteCharPtr( "#endif" ) << endl << endl;
337
338 for( size_t i = 0, n = aSlotList.size(); i < n; ++i )
339 {
340 SvMetaSlot* pAttr = aSlotList[ i ];
341 pAttr->ResetSlotPointer();
342 }
343
344 aSlotList.clear();
345 }
346
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
348