1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <precomp.h>
29 #include "hfi_typetext.hxx"
30 
31 
32 // NOT FULLY DEFINED SERVICES
33 #include <string.h>
34 #include <ary/idl/i_type.hxx>
35 #include <ary/idl/i_ce.hxx>
36 #include <ary/idl/i_module.hxx>
37 #include <ary/idl/i_module.hxx>
38 #include <ary/idl/ik_ce.hxx>
39 #include <adc_cl.hxx>
40 #include <adc_msg.hxx>
41 #include "hi_linkhelper.hxx"
42 
43 
44 
45 
46 
47 
48 inline const ary::idl::Module *
49 HF_IdlTypeText::referingModule() const
50 {
51     if (pReferingCe == 0)
52         return Env().Linker().Search_CurModule();
53     else
54         return &Env().Data().Find_Module(pReferingCe->NameRoom());
55 }
56 
57 inline const HF_IdlTypeText::client *
58 HF_IdlTypeText::referingCe() const
59 {
60     return pReferingCe;
61 }
62 
63 
64 HF_IdlTypeText::HF_IdlTypeText( Environment &       io_rEnv,
65                                 Xml::Element &      o_rOut,
66                                 bool                i_bWithLink,
67                                 const client *      i_pScopeGivingCe )
68     :   HtmlFactory_Idl(io_rEnv, &o_rOut),
69         pReferingCe( i_pScopeGivingCe ),
70         bWithLink(i_bWithLink)
71 {
72 }
73 
74 HF_IdlTypeText::HF_IdlTypeText( Environment &       io_rEnv,
75                                 E_Index             )
76     :   HtmlFactory_Idl(io_rEnv, 0),
77         pReferingCe( 0 ),
78         bWithLink(true)
79 {
80 }
81 
82 HF_IdlTypeText::~HF_IdlTypeText()
83 {
84 }
85 
86 void
87 HF_IdlTypeText::Produce_byData(ary::idl::Type_id i_idType) const
88 {
89     StringVector        aModule_;
90     String              sName;
91     ce_id               nCe;
92 	int                 nSequenceCount = 0;
93     csv::erase_container(aModule_);
94 
95     const ary::idl::Type &
96         rType = Env().Data().Find_Type(i_idType);
97     Env().Data().Get_TypeText(aModule_, sName, nCe, nSequenceCount, rType);
98 
99     if ( Env().Data().IsBuiltInOrRelated(rType) )
100     {
101         produce_BuiltIn(sName,nSequenceCount);
102     }
103     else
104     {
105         produce_FromStd( aModule_,
106                          sName,
107                          String::Null_(),
108                          nSequenceCount,
109                          (nCe.IsValid() ? exists_yes : exists_no),
110                          rType.FirstEnclosedNonSequenceType(Env().Gate()).TemplateParameters() );
111     }
112 }
113 
114 void
115 HF_IdlTypeText::Produce_byData( ary::idl::Ce_id i_idCe ) const
116 {
117     StringVector        aModule_;
118     String              sCe;
119     String              sMember;
120     csv::erase_container(aModule_);
121 
122     const ary::idl::CodeEntity &
123         rCe = Env().Data().Find_Ce(i_idCe);
124     Env().Data().Get_CeText(aModule_, sCe, sMember, rCe);
125     produce_FromStd(aModule_, sCe, sMember, 0, exists_yes);
126 }
127 
128 void
129 HF_IdlTypeText::Produce_byData( const String & i_sFullName ) const
130 {
131     if ( strncmp(i_sFullName,"http://", 7) == 0 )
132     {
133         CurOut()
134             >> *new Html::Link(i_sFullName)
135                 << i_sFullName;
136         return;
137     }
138 
139     StringVector        aModule_;
140     String              sCe,
141 		                sMember;
142     int                 nSequence = 0;
143     String              sTypeText;
144     csv::erase_container(aModule_);
145 
146     const ary::idl::Module *
147         pScopeModule = referingModule();
148     if (pScopeModule == 0)
149     {
150         // SYNTAX_ERR, but rather logical error: Missing module.
151         CurOut() << i_sFullName;
152         // KORR_FUTURE
153         // How to put a message about this?
154         // errorOut_UnresolvedLink(i_sFullName);
155         return;
156     }
157 
158     const char * sTypeStart = strrchr(i_sFullName,'<');
159     if ( sTypeStart != 0 )
160     {
161         const char * sTypeEnd = strchr(i_sFullName,'>');
162         if (sTypeEnd == 0)
163         {   // SYNTAX_ERR
164             CurOut() << i_sFullName;
165             // KORR_FUTURE
166             // How to put a message about this?
167             // errorOut_UnresolvedLink(i_sFullName);
168             return;
169         }
170 
171         nSequence = count_Sequences(i_sFullName);
172         sTypeStart++;
173         sTypeText.assign(sTypeStart, sTypeEnd-sTypeStart);
174     }
175     else
176     {
177         sTypeText = i_sFullName;
178     }
179 
180     csv::erase_container(aModule_);
181     bool bFound =   // KORR : Check the semantics of this, see if ce really exists, if it is a member?
182         Env().Data().Search_Ce( aModule_,
183                                 sCe,sMember,
184                                 sTypeText,
185                                 *pScopeModule );
186     if (NOT bFound)
187     {
188         if ( strchr(sTypeText,':') == 0
189              AND
190              *sTypeText.c_str() != 'X' )    // This is a HACK, make this correct!
191         {
192             Produce_LocalLinkInDocu(sTypeText);
193             return;
194         }
195         CurOut() << i_sFullName;
196         // KORR
197         // How to put a message about this?
198         // errorOut_UnresolvedLink(i_sFullName);
199         return;
200     }
201 
202     produce_FromStd(aModule_, sCe, sMember, nSequence, exists_yes);
203 }
204 
205 void
206 HF_IdlTypeText::Produce_LinkInDocu( const String &      i_scope,
207 	                                const String &      i_name,
208 	                                const String &      i_member ) const
209 {
210     StringVector        aModule_;
211     String              sName;
212     csv::erase_container(aModule_);
213 
214     const ary::idl::Module *
215         pScopeModule = referingModule();
216     if (pScopeModule == 0)
217     {
218         // SYNTAX_ERR, but rather logical error: Missing module.
219         CurOut() << i_scope << "::" << i_name;
220         if (NOT i_member.empty())
221             CurOut() << "::" << i_member;
222         return;
223     }
224 
225     bool
226         bFound = Env().Data().Search_CesModule( aModule_,
227                                                 i_scope,
228                                                 i_name,
229                                                 *pScopeModule );
230     if (NOT bFound)
231     {
232         CurOut() << i_scope << "::" << i_name;
233         if (NOT i_member.empty())
234             CurOut() << "::" << i_member;
235         return;
236     }
237     produce_FromStd(aModule_, i_name, i_member, 0, exists_yes);
238 }
239 
240 void
241 HF_IdlTypeText::Produce_LocalLinkInDocu( const String & i_member ) const
242 {
243     StringVector        aModule_;
244     String              sName;
245     csv::erase_container(aModule_);
246 
247     csv_assert(referingCe() != 0);
248     if ( referingModule() == Env().Linker().Search_CurModule() )
249     {
250         StreamLock slLink(200);
251         if (referingCe()->SightLevel() == ary::idl::sl_Member)
252         {
253             slLink() << "#" << i_member;
254         }
255         else
256         {
257             slLink() << referingCe()->LocalName()
258                      << ".html#"
259                      << i_member;
260         }
261         CurOut()
262             >> *new Html::Link(slLink().c_str())
263                << i_member;
264         return;
265     }
266 
267     String sDummyMember;
268     Env().Data().Get_CeText(aModule_, sName, sDummyMember, *referingCe());
269     produce_FromStd(aModule_, sName, i_member, 0, exists_yes);
270 }
271 
272 void
273 HF_IdlTypeText::Produce_IndexLink( Xml::Element &   o_out,
274                                    const client &   i_ce ) const
275 {
276     StringVector        aModule_;
277     String              sCe;
278     String              sMember;
279     csv::erase_container(aModule_);
280 
281     Out().Enter(o_out);
282 
283     Env().Data().Get_CeText(aModule_, sCe, sMember, i_ce);
284     produce_IndexLink(aModule_, sCe, sMember, false);
285 
286     Out().Leave();
287 }
288 
289 void
290 HF_IdlTypeText::Produce_IndexOwnerLink( Xml::Element &  o_out,
291                                         const client &  i_owner ) const
292 {
293     StringVector        aModule_;
294     String              sCe;
295     String              sMember;
296     csv::erase_container(aModule_);
297 
298     Out().Enter(o_out);
299 
300     if (i_owner.Owner().IsValid())
301     {
302         Env().Data().Get_CeText(aModule_, sCe, sMember, i_owner);
303         produce_IndexLink(aModule_, sCe, sMember, true);
304     }
305     else
306     {   // global namespace:
307 
308         CurOut()
309             << "."
310             >> *new Html::Link("../module-ix.html")
311                << "global namespace";
312     }
313 
314 
315     Out().Leave();
316 }
317 
318 void
319 HF_IdlTypeText::Produce_IndexSecondEntryLink( Xml::Element &      o_out,
320                                               const client &      i_ce ) const
321 {
322     StringVector        aModule_;
323     String              sCe;
324     String              sMember;
325     csv::erase_container(aModule_);
326 
327     Out().Enter(o_out);
328 
329     Env().Data().Get_CeText(aModule_, sCe, sMember, i_ce);
330     produce_IndexLink(aModule_, sCe, sMember, true);
331     Out().Leave();
332 }
333 
334 
335 void
336 HF_IdlTypeText::produce_FromStd( const StringVector & i_module,
337                                  const String &       i_ce,
338                                  const String &       i_member,
339                                  int                  i_sequenceCount,
340                                  E_Existence          i_ceExists,
341                                  const std::vector<ary::idl::Type_id> *
342                                                       i_templateParameters ) const
343 {
344     if (i_ceExists == exists_no)
345     {
346         if ( is_ExternLink(i_module) )
347         {
348             produce_ExternLink(i_module,i_ce,i_member,i_sequenceCount,i_templateParameters);
349             return;
350         }
351         errorOut_UnresolvedLink(i_module, i_ce, i_member);
352     }
353 
354     output::Node &
355         rCeNode = Env().OutputTree().Provide_Node(i_module);
356     output::Position
357         aTargetPos(rCeNode);
358     bool
359         bShowModule = rCeNode != Env().CurPosition().RelatedNode()
360                             ?   i_module.size() > 0
361                             :   false;
362     bool
363         bUseMember = NOT i_member.empty();
364     bool
365         bLink2Module = i_ceExists == exists_yes;
366     bool
367         bLink2Ce = i_ceExists == exists_yes;
368     bool
369         bLink2Member = NOT Env().Is_MemberExistenceCheckRequired()
370                        AND i_ceExists == exists_yes;
371     bool
372         bHasCeOrName = NOT i_ce.empty();
373 
374     if (i_sequenceCount > 0)
375         start_Sequence(i_sequenceCount);
376 
377     StreamLock  aLink(300);
378     StreamStr & rLink = aLink();
379 
380     // Produce output: module
381     if (bShowModule)
382     {
383         int nMax = i_module.size() - 1;
384         int nCount = 0;
385         StringVector::const_iterator
386             itm = i_module.begin();
387         for ( ;
388               nCount < nMax;
389               ++itm, ++nCount )
390         {
391             CurOut() << "::" << *itm;
392         }
393 
394         CurOut() << "::";
395         if (bLink2Module)
396         {
397             aTargetPos.Set_File(output::ModuleFileName());
398             Env().Linker().Get_Link2Position(rLink, aTargetPos);
399             CurOut()
400                 >> *new Html::Link( rLink.c_str() )
401                     << *itm;
402             rLink.reset();
403         }
404         else
405         {
406             CurOut() << *itm;
407         }
408 
409         if (bHasCeOrName)
410             CurOut() << "::";
411     }   // end if (bShowModule)
412 
413     // CodeEntity and member:
414     aTargetPos.Set_File( rLink << i_ce << ".html" << c_str );
415     rLink.reset();
416 
417     if (bHasCeOrName)
418     {
419         if (bLink2Ce)
420         {
421             Env().Linker().Get_Link2Position(rLink, aTargetPos);
422             CurOut()
423                 >> *new Html::Link(rLink.c_str())
424                     << i_ce;
425             rLink.reset();
426         }
427         else
428         {
429             CurOut() << i_ce;
430         }
431 
432         if (i_templateParameters != 0)
433             write_TemplateParameterList(*i_templateParameters);
434 
435         if (bUseMember)
436         {
437             CurOut() << "::";
438 
439             if (bLink2Member)
440             {
441     			bool bFunction = strstr(i_member,"()") != 0;
442 			    String sMember( i_member );
443 			    if (bFunction)
444 				    sMember.assign(i_member.c_str(), sMember.length()-2);
445 
446                 Env().Linker().Get_Link2Member(rLink, aTargetPos, sMember);
447                 CurOut()
448                     >> *new Html::Link(rLink.c_str())
449                         << i_member;
450                 rLink.reset();
451             }
452             else
453             {
454                 CurOut()
455                     << i_member;
456             }
457         }   // endif (bUseMember)
458     }   // endif (bHasCeOrName)
459 
460     if (i_sequenceCount > 0)
461         finish_Sequence(i_sequenceCount);
462 }
463 
464 void
465 HF_IdlTypeText::produce_BuiltIn( const String &      i_type,
466                                  int                 i_sequenceCount ) const
467 {
468     if (i_sequenceCount > 0)
469         start_Sequence(i_sequenceCount);
470     CurOut() << i_type;
471     if (i_sequenceCount > 0)
472         finish_Sequence(i_sequenceCount);
473 }
474 
475 void
476 HF_IdlTypeText::produce_IndexLink( const StringVector & i_module,
477                                    const String &       i_ce,
478                                    const String &       i_member,
479                                    bool                 i_bIsOwner ) const
480 {
481     output::Node &
482         rCeNode = Env().OutputTree().Provide_Node(i_module);
483     output::Position
484         aTargetPos(rCeNode);
485     bool
486         bShowModule = i_bIsOwner OR (i_module.size() > 0 AND i_ce.empty());
487     bool
488         bShowNonModule = NOT bShowModule OR (i_bIsOwner AND NOT i_ce.empty());
489     bool
490         bUseMember = NOT i_member.empty();
491 
492     StreamLock  aLink(300);
493     StreamStr & rLink = aLink();
494 
495     // Produce output: module
496     if (bShowModule)
497     {
498         if (i_bIsOwner)
499         {
500             int nMax = bShowNonModule ? i_module.size() : i_module.size() - 1;
501             int nCount = 0;
502             for ( StringVector::const_iterator itm = i_module.begin();
503                   nCount < nMax;
504                   ++itm, ++nCount )
505             {
506                 CurOut() << "::" << *itm;
507             }
508             CurOut() << ":: .";
509         }
510 
511         if (NOT bShowNonModule)
512         {
513             aTargetPos.Set_File(output::ModuleFileName());
514             Env().Linker().Get_Link2Position(rLink, aTargetPos);
515             CurOut()
516                 >> *new Html::Link( rLink.c_str() )
517                     >> *new Html::Bold
518                         << i_module.back();
519             rLink.reset();
520         }
521     }   // end if (bShowModule)
522 
523 	if (bShowNonModule)
524     {
525         aTargetPos.Set_File( rLink << i_ce << ".html" << c_str );
526         rLink.reset();
527 
528         if (bUseMember)
529         {
530 			bool bFunction = strstr(i_member,"()") != 0;
531 			String sMember( i_member );
532 			if (bFunction)
533 				sMember.assign(i_member.c_str(), sMember.length()-2);
534             Env().Linker().Get_Link2Member(rLink, aTargetPos, sMember);
535             CurOut()
536                 >> *new Html::Link(rLink.c_str())
537                     >> *new Html::Bold
538                         << i_member;
539             rLink.reset();
540         }
541         else
542         {
543             Env().Linker().Get_Link2Position(rLink, aTargetPos);
544             if (i_bIsOwner)
545             {
546                 CurOut()
547                     >> *new Html::Link(rLink.c_str())
548                        << i_ce;
549             }
550             else
551             {
552                 CurOut()
553                     >> *new Html::Link(rLink.c_str())
554    	                    >> *new Html::Bold
555                             << i_ce;
556             }
557             rLink.reset();
558         }
559     }   // endif (bHasCeOrName)
560 }
561 
562 int
563 HF_IdlTypeText::count_Sequences( const char * i_sFullType ) const
564 {
565     int ret = 0;
566 
567     for ( const char * pCount = i_sFullType;
568           *pCount != 0;
569            )
570     {
571         pCount = strstr(pCount,"sequence");
572         if (pCount != 0)
573         {
574             pCount += sizeof("sequence");   // = strlen(sequence) + 1 for '<'.
575             if ( *(pCount-1) == '\0' )
576             {
577                 // SYNTAX_ERR
578                 return 0;
579             }
580             ++ret;
581         }
582     }   // end for
583 
584     return ret;
585 }
586 
587 void
588 HF_IdlTypeText::start_Sequence( int i_count ) const
589 {
590     csv_assert( i_count > 0 );
591     for (int i = 0; i < i_count; ++i )
592     {
593         CurOut() << "sequence< ";
594     }
595 }
596 
597 void
598 HF_IdlTypeText::finish_Sequence( int i_count ) const
599 {
600     csv_assert( i_count > 0 );
601     for (int i = 0; i < i_count; ++i )
602     {
603         CurOut() << " >";
604     }
605 }
606 
607 void
608 HF_IdlTypeText::errorOut_UnresolvedLink( const char *        i_name ) const
609 {
610     StreamLock slFile(1000);
611 
612     // KORR
613     // Handle links in cited documentation from other entities.
614     slFile() << Env().CurPageCe_AsText();
615     slFile().pop_back(5);
616     slFile() << ".idl";
617 
618     // KORR
619     // Retrieve, correct line number.
620     TheMessages().Out_UnresolvedLink( i_name,
621                                       slFile().c_str(),
622                                       0 );
623 }
624 
625 void
626 HF_IdlTypeText::errorOut_UnresolvedLink( const StringVector & i_module,
627                                          const String &       i_ce,
628                                          const String &       i_member ) const
629 {
630     StreamLock slName(500);
631 
632     if (i_module.size() > 0)
633     {
634         slName().operator_join(i_module.begin(), i_module.end(), "::");
635      	if (NOT i_ce.empty())
636             slName() << "::";
637     }
638     if (NOT i_ce.empty())
639     {
640         slName() << i_ce;
641         if (NOT i_member.empty())
642             slName() << "::" << i_member;
643     }
644     errorOut_UnresolvedLink(slName().c_str());
645 }
646 
647 bool
648 HF_IdlTypeText::is_ExternLink( const StringVector & i_module ) const
649 {
650     const autodoc::CommandLine &
651         rCmdLine = autodoc::CommandLine::Get_();
652     uintt nExtNspLength = rCmdLine.ExternNamespace().length();
653     if (nExtNspLength == 0)
654         return false;
655 
656     StreamStr s(1000);
657     s << "::";
658     s.operator_join( i_module.begin(),
659                      i_module.end(),
660                      "::" );
661 
662     if (s.length() < nExtNspLength)
663         return false;
664     return ( strncmp( rCmdLine.ExternNamespace().c_str(),
665                       s.c_str(),
666                       nExtNspLength ) == 0 );
667 }
668 
669 void
670 HF_IdlTypeText::produce_ExternLink( const StringVector & i_module,
671                                     const String &       i_ce,
672                                     const String &       i_member,
673                                     int                  i_sequenceCount,
674                                     const std::vector<ary::idl::Type_id> *
675                                                          i_templateParameters ) const
676 {
677     // KORR
678     // Look again at this code and take some time.
679 
680     StreamLock  aLink(1000);
681     StreamStr & rLink = aLink();
682 
683     rLink << autodoc::CommandLine::Get_().ExternRoot();
684     rLink.operator_join( i_module.begin(),
685                          i_module.end(),
686                          "/" );
687     rLink << '/'
688           << i_ce
689           << ".html";
690     if (i_member.length() > 0)
691         rLink << "/#" << i_member;
692 
693     if (i_sequenceCount > 0)
694         start_Sequence(i_sequenceCount);
695 
696     // module
697     int nMax = i_module.size();
698     int nCount = 0;
699     StringVector::const_iterator
700         itm = i_module.begin();
701     for ( ;
702           nCount < nMax;
703           ++itm, ++nCount )
704     {
705         CurOut() << "::" << *itm;
706     }
707     CurOut() << "::";
708 
709 
710     // CodeEntity
711     if (i_member.length() == 0)
712     {
713         CurOut()
714            >> *new Html::Link(rLink.c_str())
715               << i_ce;
716     }
717     else
718     {
719         CurOut()
720             << i_ce;
721     }
722 
723     if (i_templateParameters != 0)
724         write_TemplateParameterList(*i_templateParameters);
725 
726     // Member
727     if (i_member.length() > 0)
728     {
729         CurOut()
730             >> *new Html::Link(rLink.c_str())
731                 << i_member;
732     }
733 
734     if (i_sequenceCount > 0)
735         finish_Sequence(i_sequenceCount);
736 }
737 
738 void
739 HF_IdlTypeText::write_TemplateParameterList(
740                     const std::vector<ary::idl::Type_id> & i_templateParameters ) const
741 {
742     if (i_templateParameters.size() == 0)
743         return;
744 
745     HF_IdlTypeText
746         aTemplateParamWriter(Env(), CurOut(), true, pReferingCe);
747     CurOut() << "< ";
748     std::vector<ary::idl::Type_id>::const_iterator
749         it = i_templateParameters.begin();
750     aTemplateParamWriter.Produce_byData(*it);
751     for ( ++it; it != i_templateParameters.end(); ++it )
752     {
753         CurOut() << ", ";
754         aTemplateParamWriter.Produce_byData(*it);
755     }
756     CurOut() << " >";
757 }
758