Link with C++ linker
[oweals/cde.git] / cde / programs / nsgmls / LinkProcess.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: LinkProcess.C /main/1 1996/07/29 16:55:45 cde-hp $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30 #include "splib.h"
31 #include "LinkProcess.h"
32 // ParserState is used for access to parser messages
33 #include "ParserState.h"
34 #include "MessageArg.h"
35 #include "ParserMessages.h"
36
37 #ifdef SP_NAMESPACE
38 namespace SP_NAMESPACE {
39 #endif
40
41 LinkProcess::LinkProcess()
42 {
43 }
44
45 void LinkProcess::init(const ConstPtr<ComplexLpd> &lpd)
46 {
47   lpd_ = lpd;
48   open_.clear();
49   open_.insert(new LinkProcessOpenElement(lpd_->initialLinkSet()));
50 }
51
52 Boolean LinkProcess::startElement(const ElementType *element,
53                                   const AttributeList &attributes,
54                                   const Location &location,
55                                   Messenger &mgr,
56                                   const AttributeList *&linkAttributes,
57                                   const ResultElementSpec *&resultElementSpec)
58 {
59   if (lpd_.isNull()) {
60     linkAttributes = 0;
61     resultElementSpec = 0;
62     return 1;
63   }
64   const StringC *id = attributes.getId();
65   if (id) {
66     const IdLinkRuleGroup *p = lpd_->lookupIdLink(*id);
67     if (p) {
68       size_t selected;
69       if (p->nLinkRules() > 1) {
70         linkAttributes_.resize(p->nLinkRules());
71         for (size_t i = 0; i < linkAttributes_.size(); i++)
72           linkAttributes_[i] = &p->linkRule(i).attributes();
73         if (!selectLinkRule(linkAttributes_,
74                             location,
75                             selected))
76           return 0;
77       }
78       else
79         selected = 0;
80       const IdLinkRule &rule = p->linkRule(selected);
81       open_.insert(new LinkProcessOpenElement(open_.head()->current,
82                                               rule));
83       linkAttributes = &rule.attributes();
84       resultElementSpec = &rule.resultElementSpec();
85       if (!rule.isAssociatedWith(element)) {
86         mgr.setNextLocation(location);
87         mgr.message(ParserMessages::idlinkElementType,
88                     StringMessageArg(element->name()),
89                     StringMessageArg(*id));
90       }
91       return 1;
92     }
93   }
94   const LinkSet *currentLinkSet = open_.head()->current;
95   size_t nRules = currentLinkSet->nLinkRules(element);
96   if (nRules > 0) {
97     size_t selected;
98     if (nRules > 1) {
99       linkAttributes_.resize(nRules);
100       for (size_t i = 0; i < nRules; i++)
101         linkAttributes_[i]
102           = &currentLinkSet->linkRule(element, i).attributes();
103       if (!selectLinkRule(linkAttributes_,
104                           location,
105                           selected))
106         return 0;
107     }
108     else
109       selected = 0;
110     const SourceLinkRule &rule = currentLinkSet->linkRule(element, selected);
111     open_.insert(new LinkProcessOpenElement(open_.head()->current,
112                                             rule));
113     linkAttributes = &rule.attributes();
114     resultElementSpec = &rule.resultElementSpec();
115     return 1;
116   }
117   // FIXME construct attributes from attribute definition list
118   linkAttributes = 0;
119   resultElementSpec = 0;
120   open_.insert(new LinkProcessOpenElement(open_.head()->current));
121   return 1;
122 }
123
124
125 void LinkProcess::endElement()
126 {
127   if (lpd_.isNull())
128     return;
129   LinkProcessOpenElement *top = open_.get();
130   if (top->post)
131     open_.head()->current = top->post;
132   else if (top->postRestore)
133     open_.head()->current = open_.head()->restore;
134   delete top;
135 }
136
137 void LinkProcess::uselink(const LinkSet *linkSet,
138                           Boolean restore,
139                           const Lpd *lpd)
140 {
141   if (lpd_.isNull())
142     return;
143   if (lpd != lpd_.pointer())
144     return;
145   if (restore)
146     open_.head()->current = open_.head()->restore;
147   else if (linkSet)
148     open_.head()->current = linkSet;
149 }
150
151 size_t LinkProcess::nImpliedLinkRules() const
152 {
153   if (!open_.head())
154     return 0;
155   return open_.head()->current->nImpliedLinkRules();
156 }
157
158 const ResultElementSpec &LinkProcess::impliedLinkRule(size_t i) const
159 {
160   return open_.head()->current->impliedLinkRule(i);
161 }
162
163 // Usually redefined by application.
164
165 Boolean LinkProcess::selectLinkRule(const Vector<const AttributeList *> &,
166                                     const Location &,
167                                     size_t &selected)
168 {
169   selected = 0;
170   return 1;
171 }
172
173 void LinkProcess::clear()
174 {
175   open_.clear();
176   lpd_.clear();
177   linkAttributes_.clear();
178 }
179
180 void LinkProcess::swap(LinkProcess &to)
181 {
182   open_.swap(to.open_);
183   lpd_.swap(to.lpd_);
184   linkAttributes_.swap(to.linkAttributes_);
185 }
186
187 LinkProcessOpenElement::LinkProcessOpenElement(const LinkSet *cur,
188                                                const SourceLinkRule &rule)
189 {
190   current = rule.uselink();
191   if (!current)
192     current = cur;
193   restore = cur;
194   post = rule.postlink();
195   postRestore = rule.postlinkRestore();
196 }
197
198 LinkProcessOpenElement::LinkProcessOpenElement(const LinkSet *cur)
199 {
200   restore = current = cur;
201   post = 0;
202   postRestore = 0;
203 }
204
205
206 #ifdef SP_NAMESPACE
207 }
208 #endif