xref: /aoo4110/main/l10ntools/source/tagtest.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_l10ntools.hxx"
26*b1cdbd2cSJim Jagielski #include <tools/string.hxx>
27*b1cdbd2cSJim Jagielski #include "tagtest.hxx"
28*b1cdbd2cSJim Jagielski 
29*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
30*b1cdbd2cSJim Jagielski #include <stdio.h>
31*b1cdbd2cSJim Jagielski #endif
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski #include "gsicheck.hxx"
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski #define HAS_FLAG( nFlags, nFlag )		( ( nFlags & nFlag ) != 0 )
36*b1cdbd2cSJim Jagielski #define SET_FLAG( nFlags, nFlag )		( nFlags |= nFlag )
37*b1cdbd2cSJim Jagielski #define RESET_FLAG( nFlags, nFlag )		( nFlags &= ~nFlag )	// ~ = Bitweises NOT
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski 
TokenInfo(TokenId pnId,sal_uInt16 nP,String paStr,ParserMessageList & rErrorList)41*b1cdbd2cSJim Jagielski TokenInfo::TokenInfo( TokenId pnId, sal_uInt16 nP, String paStr, ParserMessageList &rErrorList )
42*b1cdbd2cSJim Jagielski : bClosed(sal_False)
43*b1cdbd2cSJim Jagielski , bCloseTag(sal_False)
44*b1cdbd2cSJim Jagielski , bIsBroken(sal_False)
45*b1cdbd2cSJim Jagielski , bHasBeenFixed(sal_False)
46*b1cdbd2cSJim Jagielski , bDone(sal_False)
47*b1cdbd2cSJim Jagielski , aTokenString( paStr )
48*b1cdbd2cSJim Jagielski , nId( pnId )
49*b1cdbd2cSJim Jagielski , nPos(nP)
50*b1cdbd2cSJim Jagielski {
51*b1cdbd2cSJim Jagielski     if ( nId == TAG_COMMONSTART || nId == TAG_COMMONEND )
52*b1cdbd2cSJim Jagielski         SplitTag( rErrorList );
53*b1cdbd2cSJim Jagielski }
54*b1cdbd2cSJim Jagielski 
55*b1cdbd2cSJim Jagielski enum tagcheck { TC_START, TC_HAS_TAG_NAME, TC_HAS_PROP_NAME_EQ, TC_HAS_PROP_NAME_EQ_SP, TC_HAS_PROP_NAME_SP, TC_INSIDE_STRING, TC_PROP_FINISHED, TC_CLOSED, TC_CLOSED_SPACE, TC_CLOSETAG, TC_CLOSETAG_HAS_TAG_NAME, TC_FINISHED, TC_ERROR };
56*b1cdbd2cSJim Jagielski 
57*b1cdbd2cSJim Jagielski /*
58*b1cdbd2cSJim Jagielski                                                       \<  link  href  =  \"text\"  name  =  \"C\"  \>
59*b1cdbd2cSJim Jagielski START               ' ' ->  HAS_TAG_NAME
60*b1cdbd2cSJim Jagielski START               '/' ->  CLOSED
61*b1cdbd2cSJim Jagielski START               '/' ->  CLOSETAG    - no Portion (starting with /)
62*b1cdbd2cSJim Jagielski START               '>' ->  FINISHED
63*b1cdbd2cSJim Jagielski HAS_TAG_NAME        '=' ->  HAS_PROP_NAME_EQ
64*b1cdbd2cSJim Jagielski HAS_TAG_NAME        ' ' ->  HAS_PROP_NAME_SP
65*b1cdbd2cSJim Jagielski HAS_TAG_NAME        '/' ->  CLOSED
66*b1cdbd2cSJim Jagielski HAS_TAG_NAME        '>' ->  FINISHED
67*b1cdbd2cSJim Jagielski HAS_PROP_NAME_SP    '=' ->  HAS_PROP_NAME_EQ
68*b1cdbd2cSJim Jagielski HAS_PROP_NAME_EQ    ' ' ->  HAS_PROP_NAME_EQ_SP
69*b1cdbd2cSJim Jagielski HAS_PROP_NAME_EQ    '"' ->  INSIDE_STRING
70*b1cdbd2cSJim Jagielski HAS_PROP_NAME_EQ_SP '"' ->  INSIDE_STRING
71*b1cdbd2cSJim Jagielski INSIDE_STRING       ' ' ->  INSIDE_STRING
72*b1cdbd2cSJim Jagielski INSIDE_STRING       '=' ->  INSIDE_STRING
73*b1cdbd2cSJim Jagielski INSIDE_STRING       '>' ->  INSIDE_STRING
74*b1cdbd2cSJim Jagielski INSIDE_STRING       '"' ->  PROP_FINISHED
75*b1cdbd2cSJim Jagielski PROP_FINISHED       ' ' ->  HAS_TAG_NAME
76*b1cdbd2cSJim Jagielski PROP_FINISHED       '/' ->  CLOSED
77*b1cdbd2cSJim Jagielski PROP_FINISHED       '>' ->  FINISHED
78*b1cdbd2cSJim Jagielski CLOSED              ' ' ->  CLOSED_SPACE
79*b1cdbd2cSJim Jagielski CLOSED              '>' ->  FINISHED
80*b1cdbd2cSJim Jagielski CLOSED_SPACE        '>' ->  FINISHED
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski CLOSETAG            ' ' ->  CLOSETAG_HAS_TAG_NAME
83*b1cdbd2cSJim Jagielski CLOSETAG            '>' ->  FINISHED
84*b1cdbd2cSJim Jagielski CLOSETAG_HAS_TAG_NAME  '>' ->  FINISHED
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski */
SplitTag(ParserMessageList & rErrorList)87*b1cdbd2cSJim Jagielski void TokenInfo::SplitTag( ParserMessageList &rErrorList )
88*b1cdbd2cSJim Jagielski {
89*b1cdbd2cSJim Jagielski     sal_uInt16 nLastPos = 2;    // skip initial  \<
90*b1cdbd2cSJim Jagielski     sal_uInt16 nCheckPos = nLastPos;
91*b1cdbd2cSJim Jagielski     String aDelims( String::CreateFromAscii( " \\=>/" ) );
92*b1cdbd2cSJim Jagielski     String aPortion;
93*b1cdbd2cSJim Jagielski     String aValue;      // store the value of a property
94*b1cdbd2cSJim Jagielski     ByteString aName;   // store the name of a property/tag
95*b1cdbd2cSJim Jagielski     sal_Bool bCheckName = sal_False;
96*b1cdbd2cSJim Jagielski     sal_Bool bCheckEmpty = sal_False;
97*b1cdbd2cSJim Jagielski     sal_Unicode cDelim;
98*b1cdbd2cSJim Jagielski     tagcheck aState = TC_START;
99*b1cdbd2cSJim Jagielski 
100*b1cdbd2cSJim Jagielski     // skip blanks
101*b1cdbd2cSJim Jagielski     while ( nLastPos < aTokenString.Len() && aTokenString.GetChar( nLastPos ) == ' ')
102*b1cdbd2cSJim Jagielski         nLastPos++;
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski     nCheckPos = aTokenString.SearchChar( aDelims.GetBuffer(), nLastPos );
105*b1cdbd2cSJim Jagielski     while ( nCheckPos != STRING_NOTFOUND && !( aState == TC_FINISHED || aState == TC_ERROR ) )
106*b1cdbd2cSJim Jagielski     {
107*b1cdbd2cSJim Jagielski         aPortion = aTokenString.Copy( nLastPos, nCheckPos-nLastPos );
108*b1cdbd2cSJim Jagielski 
109*b1cdbd2cSJim Jagielski         if ( aTokenString.GetChar( nCheckPos ) == '\\' )
110*b1cdbd2cSJim Jagielski             nCheckPos++;
111*b1cdbd2cSJim Jagielski 
112*b1cdbd2cSJim Jagielski         cDelim = aTokenString.GetChar( nCheckPos );
113*b1cdbd2cSJim Jagielski         nCheckPos++;
114*b1cdbd2cSJim Jagielski 
115*b1cdbd2cSJim Jagielski         switch ( aState )
116*b1cdbd2cSJim Jagielski         {
117*b1cdbd2cSJim Jagielski //            START           ' ' ->  HAS_TAG_NAME
118*b1cdbd2cSJim Jagielski //            START           '/' ->  CLOSED
119*b1cdbd2cSJim Jagielski //            START           '>' ->  FINISHED
120*b1cdbd2cSJim Jagielski             case TC_START:
121*b1cdbd2cSJim Jagielski                 aTagName = aPortion;
122*b1cdbd2cSJim Jagielski                 switch ( cDelim )
123*b1cdbd2cSJim Jagielski                 {
124*b1cdbd2cSJim Jagielski                     case ' ':  aState = TC_HAS_TAG_NAME;
125*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
126*b1cdbd2cSJim Jagielski                                break;
127*b1cdbd2cSJim Jagielski                     case '/':
128*b1cdbd2cSJim Jagielski                         {
129*b1cdbd2cSJim Jagielski                             if ( aPortion.Len() == 0 )
130*b1cdbd2cSJim Jagielski                             {
131*b1cdbd2cSJim Jagielski                                 aState = TC_CLOSETAG;
132*b1cdbd2cSJim Jagielski                             }
133*b1cdbd2cSJim Jagielski                             else
134*b1cdbd2cSJim Jagielski                             {
135*b1cdbd2cSJim Jagielski                                 aState = TC_CLOSED;
136*b1cdbd2cSJim Jagielski                                 bCheckName = sal_True;
137*b1cdbd2cSJim Jagielski                             }
138*b1cdbd2cSJim Jagielski                         }
139*b1cdbd2cSJim Jagielski                         break;
140*b1cdbd2cSJim Jagielski                     case '>':  aState = TC_FINISHED;
141*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
142*b1cdbd2cSJim Jagielski                                break;
143*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
144*b1cdbd2cSJim Jagielski                 }
145*b1cdbd2cSJim Jagielski                 break;
146*b1cdbd2cSJim Jagielski 
147*b1cdbd2cSJim Jagielski //            HAS_TAG_NAME    '=' ->  HAS_PROP_NAME_EQ
148*b1cdbd2cSJim Jagielski //            HAS_TAG_NAME    ' ' ->  HAS_PROP_NAME_SP
149*b1cdbd2cSJim Jagielski //            HAS_TAG_NAME    '/' ->  CLOSED
150*b1cdbd2cSJim Jagielski //            HAS_TAG_NAME    '>' ->  FINISHED
151*b1cdbd2cSJim Jagielski             case TC_HAS_TAG_NAME:
152*b1cdbd2cSJim Jagielski                 switch ( cDelim )
153*b1cdbd2cSJim Jagielski                 {
154*b1cdbd2cSJim Jagielski                     case '=':  aState = TC_HAS_PROP_NAME_EQ;
155*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
156*b1cdbd2cSJim Jagielski                                break;
157*b1cdbd2cSJim Jagielski                     case ' ':  aState = TC_HAS_PROP_NAME_SP;
158*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
159*b1cdbd2cSJim Jagielski                                break;
160*b1cdbd2cSJim Jagielski                     case '/':  aState = TC_CLOSED;
161*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
162*b1cdbd2cSJim Jagielski                                break;
163*b1cdbd2cSJim Jagielski                     case '>':  aState = TC_FINISHED;
164*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
165*b1cdbd2cSJim Jagielski                                break;
166*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
167*b1cdbd2cSJim Jagielski                 }
168*b1cdbd2cSJim Jagielski                 break;
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski //            HAS_PROP_NAME_SP    '=' ->  HAS_PROP_NAME_EQ
171*b1cdbd2cSJim Jagielski             case TC_HAS_PROP_NAME_SP:
172*b1cdbd2cSJim Jagielski                 switch ( cDelim )
173*b1cdbd2cSJim Jagielski                 {
174*b1cdbd2cSJim Jagielski                     case '=':  aState = TC_HAS_PROP_NAME_EQ;
175*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
176*b1cdbd2cSJim Jagielski                                break;
177*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
178*b1cdbd2cSJim Jagielski                 }
179*b1cdbd2cSJim Jagielski                 break;
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski //            HAS_PROP_NAME_EQ    ' ' ->  HAS_PROP_NAME_EQ_SP
182*b1cdbd2cSJim Jagielski //            HAS_PROP_NAME_EQ    '"' ->  INSIDE_STRING
183*b1cdbd2cSJim Jagielski             case TC_HAS_PROP_NAME_EQ:
184*b1cdbd2cSJim Jagielski                 switch ( cDelim )
185*b1cdbd2cSJim Jagielski                 {
186*b1cdbd2cSJim Jagielski                     case ' ':  aState = TC_HAS_PROP_NAME_EQ_SP;
187*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
188*b1cdbd2cSJim Jagielski                                break;
189*b1cdbd2cSJim Jagielski                     case '\"': aState = TC_INSIDE_STRING;
190*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
191*b1cdbd2cSJim Jagielski                                aValue.Erase();
192*b1cdbd2cSJim Jagielski                                break;
193*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
194*b1cdbd2cSJim Jagielski                 }
195*b1cdbd2cSJim Jagielski                 break;
196*b1cdbd2cSJim Jagielski 
197*b1cdbd2cSJim Jagielski //            HAS_PROP_NAME_EQ_SP '"' ->  INSIDE_STRING
198*b1cdbd2cSJim Jagielski             case TC_HAS_PROP_NAME_EQ_SP:
199*b1cdbd2cSJim Jagielski                 switch ( cDelim )
200*b1cdbd2cSJim Jagielski                 {
201*b1cdbd2cSJim Jagielski                     case '\"': aState = TC_INSIDE_STRING;
202*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
203*b1cdbd2cSJim Jagielski                                aValue.Erase();
204*b1cdbd2cSJim Jagielski                                break;
205*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
206*b1cdbd2cSJim Jagielski                 }
207*b1cdbd2cSJim Jagielski                 break;
208*b1cdbd2cSJim Jagielski 
209*b1cdbd2cSJim Jagielski //            INSIDE_STRING    *  ->  INSIDE_STRING
210*b1cdbd2cSJim Jagielski //            INSIDE_STRING   '"' ->  PROP_FINISHED
211*b1cdbd2cSJim Jagielski             case TC_INSIDE_STRING:
212*b1cdbd2cSJim Jagielski                 switch ( cDelim )
213*b1cdbd2cSJim Jagielski                 {
214*b1cdbd2cSJim Jagielski                     case '\"':
215*b1cdbd2cSJim Jagielski                         {
216*b1cdbd2cSJim Jagielski                             aState = TC_PROP_FINISHED;
217*b1cdbd2cSJim Jagielski                             aValue += aPortion;
218*b1cdbd2cSJim Jagielski                             if ( aProperties.find( aName ) == aProperties.end() )
219*b1cdbd2cSJim Jagielski                             {
220*b1cdbd2cSJim Jagielski                                 if ( !IsPropertyValueValid( aName, aValue ) )
221*b1cdbd2cSJim Jagielski                                 {
222*b1cdbd2cSJim Jagielski                                     rErrorList.AddError( 25, ByteString("Property '").Append(aName).Append("' has invalid value '").Append(ByteString( aValue, RTL_TEXTENCODING_UTF8 )).Append("' "), *this );
223*b1cdbd2cSJim Jagielski                                     bIsBroken = sal_True;
224*b1cdbd2cSJim Jagielski                                 }
225*b1cdbd2cSJim Jagielski                                 aProperties[ aName ] = aValue;
226*b1cdbd2cSJim Jagielski                             }
227*b1cdbd2cSJim Jagielski                             else
228*b1cdbd2cSJim Jagielski                             {
229*b1cdbd2cSJim Jagielski                                 rErrorList.AddError( 25, ByteString("Property '").Append(aName).Append("' defined twice "), *this );
230*b1cdbd2cSJim Jagielski                                 bIsBroken = sal_True;
231*b1cdbd2cSJim Jagielski                             }
232*b1cdbd2cSJim Jagielski                         }
233*b1cdbd2cSJim Jagielski                                break;
234*b1cdbd2cSJim Jagielski                     default:
235*b1cdbd2cSJim Jagielski                         {
236*b1cdbd2cSJim Jagielski                             aState = TC_INSIDE_STRING;
237*b1cdbd2cSJim Jagielski                             aValue += aPortion;
238*b1cdbd2cSJim Jagielski                             aValue += cDelim;
239*b1cdbd2cSJim Jagielski                         }
240*b1cdbd2cSJim Jagielski                 }
241*b1cdbd2cSJim Jagielski                 break;
242*b1cdbd2cSJim Jagielski 
243*b1cdbd2cSJim Jagielski //            PROP_FINISHED   ' ' ->  HAS_TAG_NAME
244*b1cdbd2cSJim Jagielski //            PROP_FINISHED   '/' ->  CLOSED
245*b1cdbd2cSJim Jagielski //            PROP_FINISHED   '>' ->  FINISHED
246*b1cdbd2cSJim Jagielski             case TC_PROP_FINISHED:
247*b1cdbd2cSJim Jagielski                 switch ( cDelim )
248*b1cdbd2cSJim Jagielski                 {
249*b1cdbd2cSJim Jagielski                     case ' ': aState = TC_HAS_TAG_NAME;
250*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
251*b1cdbd2cSJim Jagielski                                break;
252*b1cdbd2cSJim Jagielski                     case '/': aState = TC_CLOSED;
253*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
254*b1cdbd2cSJim Jagielski                                break;
255*b1cdbd2cSJim Jagielski                     case '>': aState = TC_FINISHED;
256*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
257*b1cdbd2cSJim Jagielski                                break;
258*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
259*b1cdbd2cSJim Jagielski                 }
260*b1cdbd2cSJim Jagielski                 break;
261*b1cdbd2cSJim Jagielski 
262*b1cdbd2cSJim Jagielski //            CLOSED          ' ' ->  CLOSED_SPACE
263*b1cdbd2cSJim Jagielski //            CLOSED          '>' ->  FINISHED
264*b1cdbd2cSJim Jagielski             case TC_CLOSED:
265*b1cdbd2cSJim Jagielski                 switch ( cDelim )
266*b1cdbd2cSJim Jagielski                 {
267*b1cdbd2cSJim Jagielski                     case ' ': aState = TC_CLOSED_SPACE;
268*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
269*b1cdbd2cSJim Jagielski                                bClosed = sal_True;
270*b1cdbd2cSJim Jagielski                                break;
271*b1cdbd2cSJim Jagielski                     case '>': aState = TC_FINISHED;
272*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
273*b1cdbd2cSJim Jagielski                                break;
274*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
275*b1cdbd2cSJim Jagielski                 }
276*b1cdbd2cSJim Jagielski                 break;
277*b1cdbd2cSJim Jagielski 
278*b1cdbd2cSJim Jagielski //            CLOSED_SPACE    '>' ->  FINISHED
279*b1cdbd2cSJim Jagielski             case TC_CLOSED_SPACE:
280*b1cdbd2cSJim Jagielski                 switch ( cDelim )
281*b1cdbd2cSJim Jagielski                 {
282*b1cdbd2cSJim Jagielski                     case '>': aState = TC_FINISHED;
283*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
284*b1cdbd2cSJim Jagielski                                break;
285*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
286*b1cdbd2cSJim Jagielski                 }
287*b1cdbd2cSJim Jagielski                 break;
288*b1cdbd2cSJim Jagielski 
289*b1cdbd2cSJim Jagielski // CLOSETAG            ' ' ->  CLOSETAG_HAS_TAG_NAME
290*b1cdbd2cSJim Jagielski // CLOSETAG            '>' ->  FINISHED
291*b1cdbd2cSJim Jagielski             case TC_CLOSETAG:
292*b1cdbd2cSJim Jagielski                 bCloseTag = sal_True;
293*b1cdbd2cSJim Jagielski                 switch ( cDelim )
294*b1cdbd2cSJim Jagielski                 {
295*b1cdbd2cSJim Jagielski                     case ' ': aState = TC_CLOSETAG_HAS_TAG_NAME;
296*b1cdbd2cSJim Jagielski                                aTagName = aPortion;
297*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
298*b1cdbd2cSJim Jagielski                                break;
299*b1cdbd2cSJim Jagielski                     case '>': aState = TC_FINISHED;
300*b1cdbd2cSJim Jagielski                                aTagName = aPortion;
301*b1cdbd2cSJim Jagielski                                bCheckName = sal_True;
302*b1cdbd2cSJim Jagielski                                break;
303*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
304*b1cdbd2cSJim Jagielski                 }
305*b1cdbd2cSJim Jagielski                 break;
306*b1cdbd2cSJim Jagielski 
307*b1cdbd2cSJim Jagielski // CLOSETAG_HAS_TAG_NAME       '>' ->  FINISHED
308*b1cdbd2cSJim Jagielski             case TC_CLOSETAG_HAS_TAG_NAME:
309*b1cdbd2cSJim Jagielski                 switch ( cDelim )
310*b1cdbd2cSJim Jagielski                 {
311*b1cdbd2cSJim Jagielski                     case '>': aState = TC_FINISHED;
312*b1cdbd2cSJim Jagielski                                bCheckEmpty = sal_True;
313*b1cdbd2cSJim Jagielski                                break;
314*b1cdbd2cSJim Jagielski                     default:   aState = TC_ERROR;
315*b1cdbd2cSJim Jagielski                 }
316*b1cdbd2cSJim Jagielski                 break;
317*b1cdbd2cSJim Jagielski 
318*b1cdbd2cSJim Jagielski 
319*b1cdbd2cSJim Jagielski             default: rErrorList.AddError( 99, "Internal error Parsing Tag ", *this );
320*b1cdbd2cSJim Jagielski                      bIsBroken = sal_True;
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski         }
323*b1cdbd2cSJim Jagielski 
324*b1cdbd2cSJim Jagielski         if ( bCheckName )
325*b1cdbd2cSJim Jagielski         {
326*b1cdbd2cSJim Jagielski             if ( aPortion.Len() == 0 )
327*b1cdbd2cSJim Jagielski             {
328*b1cdbd2cSJim Jagielski                 rErrorList.AddError( 25, "Tag/Property name missing ", *this );
329*b1cdbd2cSJim Jagielski                 bIsBroken = sal_True;
330*b1cdbd2cSJim Jagielski             }
331*b1cdbd2cSJim Jagielski             else
332*b1cdbd2cSJim Jagielski             {
333*b1cdbd2cSJim Jagielski                 aName = ByteString( aPortion, RTL_TEXTENCODING_UTF8 );
334*b1cdbd2cSJim Jagielski                 // "a-zA-Z_-.0-9"
335*b1cdbd2cSJim Jagielski                 xub_StrLen nCount;
336*b1cdbd2cSJim Jagielski                 sal_Bool bBroken = sal_False;
337*b1cdbd2cSJim Jagielski                 const sal_Char* aBuf = aName.GetBuffer();
338*b1cdbd2cSJim Jagielski                 for ( nCount = 0 ; !bBroken && nCount < aName.Len() ; nCount++ )
339*b1cdbd2cSJim Jagielski                 {
340*b1cdbd2cSJim Jagielski                     bBroken = ! (   ( aBuf[nCount] >= 'a' && aBuf[nCount] <= 'z' )
341*b1cdbd2cSJim Jagielski                                 ||( aBuf[nCount] >= 'A' && aBuf[nCount] <= 'Z' )
342*b1cdbd2cSJim Jagielski                                 ||( aBuf[nCount] >= '0' && aBuf[nCount] <= '9' )
343*b1cdbd2cSJim Jagielski                                 ||( aBuf[nCount] == '_' )
344*b1cdbd2cSJim Jagielski                                 ||( aBuf[nCount] == '-' )
345*b1cdbd2cSJim Jagielski                                 ||( aBuf[nCount] == '.' )
346*b1cdbd2cSJim Jagielski                                 );
347*b1cdbd2cSJim Jagielski                 }
348*b1cdbd2cSJim Jagielski 
349*b1cdbd2cSJim Jagielski                 if ( bBroken )
350*b1cdbd2cSJim Jagielski                 {
351*b1cdbd2cSJim Jagielski                     rErrorList.AddError( 25, "Found illegal character in Tag/Property name ", *this );
352*b1cdbd2cSJim Jagielski                     bIsBroken = sal_True;
353*b1cdbd2cSJim Jagielski                 }
354*b1cdbd2cSJim Jagielski             }
355*b1cdbd2cSJim Jagielski 
356*b1cdbd2cSJim Jagielski             bCheckName = sal_False;
357*b1cdbd2cSJim Jagielski         }
358*b1cdbd2cSJim Jagielski 
359*b1cdbd2cSJim Jagielski         if ( bCheckEmpty )
360*b1cdbd2cSJim Jagielski         {
361*b1cdbd2cSJim Jagielski             if ( aPortion.Len() )
362*b1cdbd2cSJim Jagielski             {
363*b1cdbd2cSJim Jagielski                 rErrorList.AddError( 25, ByteString("Found displaced characters '").Append(ByteString( aPortion, RTL_TEXTENCODING_UTF8 )).Append("' in Tag "), *this );
364*b1cdbd2cSJim Jagielski                 bIsBroken = sal_True;
365*b1cdbd2cSJim Jagielski             }
366*b1cdbd2cSJim Jagielski             bCheckEmpty = sal_False;
367*b1cdbd2cSJim Jagielski         }
368*b1cdbd2cSJim Jagielski 
369*b1cdbd2cSJim Jagielski 
370*b1cdbd2cSJim Jagielski         nLastPos = nCheckPos;
371*b1cdbd2cSJim Jagielski 
372*b1cdbd2cSJim Jagielski         // skip further blanks
373*b1cdbd2cSJim Jagielski         if ( cDelim == ' ' && aState != TC_INSIDE_STRING )
374*b1cdbd2cSJim Jagielski             while ( nLastPos < aTokenString.Len() && aTokenString.GetChar( nLastPos ) == ' ')
375*b1cdbd2cSJim Jagielski                 nLastPos++;
376*b1cdbd2cSJim Jagielski 
377*b1cdbd2cSJim Jagielski         nCheckPos = aTokenString.SearchChar( aDelims.GetBuffer(), nLastPos );
378*b1cdbd2cSJim Jagielski     }
379*b1cdbd2cSJim Jagielski     if ( aState != TC_FINISHED )
380*b1cdbd2cSJim Jagielski     {
381*b1cdbd2cSJim Jagielski         rErrorList.AddError( 25, "Parsing error in Tag ", *this );
382*b1cdbd2cSJim Jagielski         bIsBroken = sal_True;
383*b1cdbd2cSJim Jagielski     }
384*b1cdbd2cSJim Jagielski }
385*b1cdbd2cSJim Jagielski 
IsPropertyRelevant(const ByteString & aName,const String & aValue) const386*b1cdbd2cSJim Jagielski sal_Bool TokenInfo::IsPropertyRelevant( const ByteString &aName, const String &aValue ) const
387*b1cdbd2cSJim Jagielski {
388*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "alt" ) && aName.Equals( "xml-lang" ) )
389*b1cdbd2cSJim Jagielski         return sal_False;
390*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "ahelp" ) && aName.Equals( "visibility" ) && aValue.EqualsAscii("visible") )
391*b1cdbd2cSJim Jagielski         return sal_False;
392*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "image" ) && (aName.Equals( "width" ) || aName.Equals( "height" )) )
393*b1cdbd2cSJim Jagielski         return sal_False;
394*b1cdbd2cSJim Jagielski 
395*b1cdbd2cSJim Jagielski     return sal_True;
396*b1cdbd2cSJim Jagielski }
397*b1cdbd2cSJim Jagielski 
IsPropertyValueValid(const ByteString & aName,const String & aValue) const398*b1cdbd2cSJim Jagielski sal_Bool TokenInfo::IsPropertyValueValid( const ByteString &aName, const String &aValue ) const
399*b1cdbd2cSJim Jagielski {
400*b1cdbd2cSJim Jagielski /*  removed due to i56740
401*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "switchinline" ) && aName.Equals( "select" ) )
402*b1cdbd2cSJim Jagielski     {
403*b1cdbd2cSJim Jagielski         return aValue.EqualsAscii("sys") ||
404*b1cdbd2cSJim Jagielski                aValue.EqualsAscii("appl") ||
405*b1cdbd2cSJim Jagielski                aValue.EqualsAscii("distrib");
406*b1cdbd2cSJim Jagielski     } */
407*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "caseinline" ) && aName.Equals( "select" ) )
408*b1cdbd2cSJim Jagielski     {
409*b1cdbd2cSJim Jagielski         return /*!aValue.EqualsAscii("OS2") &&  removed due to i56740 */
410*b1cdbd2cSJim Jagielski                !aValue.EqualsAscii("");
411*b1cdbd2cSJim Jagielski     }
412*b1cdbd2cSJim Jagielski 
413*b1cdbd2cSJim Jagielski     // we don't know any better so we assume it to be OK
414*b1cdbd2cSJim Jagielski     return sal_True;
415*b1cdbd2cSJim Jagielski }
416*b1cdbd2cSJim Jagielski 
IsPropertyInvariant(const ByteString & aName,const String & aValue) const417*b1cdbd2cSJim Jagielski sal_Bool TokenInfo::IsPropertyInvariant( const ByteString &aName, const String &aValue ) const
418*b1cdbd2cSJim Jagielski {
419*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "link" ) && aName.Equals( "name" ) )
420*b1cdbd2cSJim Jagielski         return sal_False;
421*b1cdbd2cSJim Jagielski     if ( aTagName.EqualsAscii( "link" ) && aName.Equals( "href" ) )
422*b1cdbd2cSJim Jagielski     {   // check for external reference
423*b1cdbd2cSJim Jagielski         if (  aValue.Copy( 0, 5 ).EqualsIgnoreCaseAscii( "http:" )
424*b1cdbd2cSJim Jagielski            || aValue.Copy( 0, 6 ).EqualsIgnoreCaseAscii( "https:" )
425*b1cdbd2cSJim Jagielski            || aValue.Copy( 0, 4 ).EqualsIgnoreCaseAscii( "ftp:" ) )
426*b1cdbd2cSJim Jagielski             return sal_False;
427*b1cdbd2cSJim Jagielski         else
428*b1cdbd2cSJim Jagielski             return sal_True;
429*b1cdbd2cSJim Jagielski     }
430*b1cdbd2cSJim Jagielski     return sal_True;
431*b1cdbd2cSJim Jagielski }
432*b1cdbd2cSJim Jagielski 
IsPropertyFixable(const ByteString & aName) const433*b1cdbd2cSJim Jagielski sal_Bool TokenInfo::IsPropertyFixable( const ByteString &aName ) const
434*b1cdbd2cSJim Jagielski {
435*b1cdbd2cSJim Jagielski     // name everything that is allowed to be fixed automatically here
436*b1cdbd2cSJim Jagielski     if ( (aTagName.EqualsAscii( "ahelp" ) && aName.Equals( "hid" ))
437*b1cdbd2cSJim Jagielski       || (aTagName.EqualsAscii( "link" ) && aName.Equals( "href" ))
438*b1cdbd2cSJim Jagielski       || (aTagName.EqualsAscii( "alt" ) && aName.Equals( "id" ))
439*b1cdbd2cSJim Jagielski       || (aTagName.EqualsAscii( "variable" ) && aName.Equals( "id" ))
440*b1cdbd2cSJim Jagielski       || (aTagName.EqualsAscii( "image" ) && aName.Equals( "src" ))
441*b1cdbd2cSJim Jagielski       || (aTagName.EqualsAscii( "image" ) && aName.Equals( "id" ) ))
442*b1cdbd2cSJim Jagielski         return sal_True;
443*b1cdbd2cSJim Jagielski     return sal_False;
444*b1cdbd2cSJim Jagielski }
445*b1cdbd2cSJim Jagielski 
MatchesTranslation(TokenInfo & rInfo,sal_Bool bGenErrors,ParserMessageList & rErrorList,sal_Bool bFixTags) const446*b1cdbd2cSJim Jagielski sal_Bool TokenInfo::MatchesTranslation( TokenInfo& rInfo, sal_Bool bGenErrors, ParserMessageList &rErrorList, sal_Bool bFixTags ) const
447*b1cdbd2cSJim Jagielski {
448*b1cdbd2cSJim Jagielski     // check if tags are equal
449*b1cdbd2cSJim Jagielski     // check if all existing properties are in the translation as well and
450*b1cdbd2cSJim Jagielski     // wether they have a matching content (the same in most cases)
451*b1cdbd2cSJim Jagielski 
452*b1cdbd2cSJim Jagielski     if ( nId != rInfo.nId )
453*b1cdbd2cSJim Jagielski         return sal_False;
454*b1cdbd2cSJim Jagielski 
455*b1cdbd2cSJim Jagielski     if ( !aTagName.Equals( rInfo.aTagName ) )
456*b1cdbd2cSJim Jagielski         return sal_False;
457*b1cdbd2cSJim Jagielski 
458*b1cdbd2cSJim Jagielski     // If one of the tags has formating errors already it does make no sense to check here, so return right away
459*b1cdbd2cSJim Jagielski     if ( bGenErrors && ( bIsBroken || rInfo.bIsBroken ) )
460*b1cdbd2cSJim Jagielski         return sal_True;
461*b1cdbd2cSJim Jagielski 
462*b1cdbd2cSJim Jagielski 	StringHashMap::const_iterator iProp;
463*b1cdbd2cSJim Jagielski 	for( iProp = aProperties.begin() ; iProp != aProperties.end(); ++iProp )
464*b1cdbd2cSJim Jagielski     {
465*b1cdbd2cSJim Jagielski         if ( rInfo.aProperties.find( iProp->first ) != rInfo.aProperties.end() )
466*b1cdbd2cSJim Jagielski         {
467*b1cdbd2cSJim Jagielski             if ( IsPropertyRelevant( iProp->first, iProp->second ) || IsPropertyRelevant( iProp->first, rInfo.aProperties.find( iProp->first )->second ) )
468*b1cdbd2cSJim Jagielski             {
469*b1cdbd2cSJim Jagielski                 if ( IsPropertyInvariant( iProp->first, iProp->second ) )
470*b1cdbd2cSJim Jagielski                 {
471*b1cdbd2cSJim Jagielski                     if ( !rInfo.aProperties.find( iProp->first )->second.Equals( iProp->second ) )
472*b1cdbd2cSJim Jagielski                     {
473*b1cdbd2cSJim Jagielski                         if ( bGenErrors )
474*b1cdbd2cSJim Jagielski                         {
475*b1cdbd2cSJim Jagielski                             if ( bFixTags && IsPropertyFixable( iProp->first ) )
476*b1cdbd2cSJim Jagielski                             {
477*b1cdbd2cSJim Jagielski                                 rInfo.aProperties.find( iProp->first )->second = iProp->second;
478*b1cdbd2cSJim Jagielski                                 rInfo.SetHasBeenFixed();
479*b1cdbd2cSJim Jagielski                                 rErrorList.AddWarning( 25, ByteString("Property '").Append(iProp->first).Append("': FIXED different value in Translation "), *this );
480*b1cdbd2cSJim Jagielski                             }
481*b1cdbd2cSJim Jagielski                             else
482*b1cdbd2cSJim Jagielski                                 rErrorList.AddError( 25, ByteString("Property '").Append(iProp->first).Append("': value different in Translation "), *this );
483*b1cdbd2cSJim Jagielski                         }
484*b1cdbd2cSJim Jagielski                         else return sal_False;
485*b1cdbd2cSJim Jagielski                     }
486*b1cdbd2cSJim Jagielski                 }
487*b1cdbd2cSJim Jagielski             }
488*b1cdbd2cSJim Jagielski         }
489*b1cdbd2cSJim Jagielski         else
490*b1cdbd2cSJim Jagielski         {
491*b1cdbd2cSJim Jagielski             if ( IsPropertyRelevant( iProp->first, iProp->second ) )
492*b1cdbd2cSJim Jagielski             {
493*b1cdbd2cSJim Jagielski                 if ( bGenErrors )
494*b1cdbd2cSJim Jagielski                     rErrorList.AddError( 25, ByteString("Property '").Append(iProp->first).Append("' missing in Translation "), *this );
495*b1cdbd2cSJim Jagielski                 else return sal_False;
496*b1cdbd2cSJim Jagielski             }
497*b1cdbd2cSJim Jagielski         }
498*b1cdbd2cSJim Jagielski 	}
499*b1cdbd2cSJim Jagielski 	for( iProp = rInfo.aProperties.begin() ; iProp != rInfo.aProperties.end(); ++iProp )
500*b1cdbd2cSJim Jagielski     {
501*b1cdbd2cSJim Jagielski         if ( aProperties.find( iProp->first ) == aProperties.end() )
502*b1cdbd2cSJim Jagielski         {
503*b1cdbd2cSJim Jagielski             if ( IsPropertyRelevant( iProp->first, iProp->second ) )
504*b1cdbd2cSJim Jagielski             {
505*b1cdbd2cSJim Jagielski                 if ( bGenErrors )
506*b1cdbd2cSJim Jagielski                     rErrorList.AddError( 25, ByteString("Extra Property '").Append(iProp->first).Append("' in Translation "), rInfo );
507*b1cdbd2cSJim Jagielski                 else return sal_False;
508*b1cdbd2cSJim Jagielski             }
509*b1cdbd2cSJim Jagielski         }
510*b1cdbd2cSJim Jagielski 	}
511*b1cdbd2cSJim Jagielski 
512*b1cdbd2cSJim Jagielski     // if we reach here eather
513*b1cdbd2cSJim Jagielski     //   the tags match completely or
514*b1cdbd2cSJim Jagielski     //   the tags match but not the properties and we generated errors for that
515*b1cdbd2cSJim Jagielski     return sal_True;
516*b1cdbd2cSJim Jagielski }
517*b1cdbd2cSJim Jagielski 
GetTagName() const518*b1cdbd2cSJim Jagielski String TokenInfo::GetTagName() const
519*b1cdbd2cSJim Jagielski {
520*b1cdbd2cSJim Jagielski     return aTagName;
521*b1cdbd2cSJim Jagielski }
522*b1cdbd2cSJim Jagielski 
MakeTag() const523*b1cdbd2cSJim Jagielski String TokenInfo::MakeTag() const
524*b1cdbd2cSJim Jagielski {
525*b1cdbd2cSJim Jagielski     String aRet;
526*b1cdbd2cSJim Jagielski     aRet.AppendAscii("\\<");
527*b1cdbd2cSJim Jagielski     if ( bCloseTag )
528*b1cdbd2cSJim Jagielski         aRet.AppendAscii("/");
529*b1cdbd2cSJim Jagielski     aRet.Append( GetTagName() );
530*b1cdbd2cSJim Jagielski 	StringHashMap::const_iterator iProp;
531*b1cdbd2cSJim Jagielski 
532*b1cdbd2cSJim Jagielski 	for( iProp = aProperties.begin() ; iProp != aProperties.end(); ++iProp )
533*b1cdbd2cSJim Jagielski     {
534*b1cdbd2cSJim Jagielski         aRet.AppendAscii(" ");
535*b1cdbd2cSJim Jagielski         aRet.Append( String( iProp->first, RTL_TEXTENCODING_UTF8 ) );
536*b1cdbd2cSJim Jagielski         aRet.AppendAscii("=\\\"");
537*b1cdbd2cSJim Jagielski         aRet.Append( iProp->second );
538*b1cdbd2cSJim Jagielski         aRet.AppendAscii("\\\"");
539*b1cdbd2cSJim Jagielski     }
540*b1cdbd2cSJim Jagielski     if ( bClosed )
541*b1cdbd2cSJim Jagielski         aRet.AppendAscii("/");
542*b1cdbd2cSJim Jagielski     aRet.AppendAscii("\\>");
543*b1cdbd2cSJim Jagielski     return aRet;
544*b1cdbd2cSJim Jagielski }
545*b1cdbd2cSJim Jagielski 
546*b1cdbd2cSJim Jagielski 
AddError(sal_uInt16 nErrorNr,ByteString aErrorText,const TokenInfo & rTag)547*b1cdbd2cSJim Jagielski void ParserMessageList::AddError( sal_uInt16 nErrorNr, ByteString aErrorText, const TokenInfo &rTag )
548*b1cdbd2cSJim Jagielski {
549*b1cdbd2cSJim Jagielski     Insert( new ParserError( nErrorNr, aErrorText, rTag ), LIST_APPEND );
550*b1cdbd2cSJim Jagielski }
551*b1cdbd2cSJim Jagielski 
AddWarning(sal_uInt16 nErrorNr,ByteString aErrorText,const TokenInfo & rTag)552*b1cdbd2cSJim Jagielski void ParserMessageList::AddWarning( sal_uInt16 nErrorNr, ByteString aErrorText, const TokenInfo &rTag )
553*b1cdbd2cSJim Jagielski {
554*b1cdbd2cSJim Jagielski     Insert( new ParserWarning( nErrorNr, aErrorText, rTag ), LIST_APPEND );
555*b1cdbd2cSJim Jagielski }
556*b1cdbd2cSJim Jagielski 
HasErrors()557*b1cdbd2cSJim Jagielski sal_Bool ParserMessageList::HasErrors()
558*b1cdbd2cSJim Jagielski {
559*b1cdbd2cSJim Jagielski     sal_uInt16 i;
560*b1cdbd2cSJim Jagielski     for ( i=0 ; i < Count() ; i++ )
561*b1cdbd2cSJim Jagielski         if ( GetObject( i )->IsError() )
562*b1cdbd2cSJim Jagielski             return sal_True;
563*b1cdbd2cSJim Jagielski     return sal_False;
564*b1cdbd2cSJim Jagielski }
565*b1cdbd2cSJim Jagielski 
566*b1cdbd2cSJim Jagielski struct Tag
567*b1cdbd2cSJim Jagielski {
GetNameTag568*b1cdbd2cSJim Jagielski     String GetName() const { return String::CreateFromAscii( pName ); };
569*b1cdbd2cSJim Jagielski 	const char* pName;
570*b1cdbd2cSJim Jagielski 	TokenId nTag;
571*b1cdbd2cSJim Jagielski };
572*b1cdbd2cSJim Jagielski 
573*b1cdbd2cSJim Jagielski 
574*b1cdbd2cSJim Jagielski static const Tag aKnownTags[] =
575*b1cdbd2cSJim Jagielski {
576*b1cdbd2cSJim Jagielski /*  commenting oldstyle tags
577*b1cdbd2cSJim Jagielski //	{ "<#GROUP_FORMAT>", TAG_GROUP_FORMAT },
578*b1cdbd2cSJim Jagielski 	{ "<#BOLD>", TAG_BOLDON },
579*b1cdbd2cSJim Jagielski 	{ "<#/BOLD>", TAG_BOLDOFF },
580*b1cdbd2cSJim Jagielski 	{ "<#ITALIC>", TAG_ITALICON },
581*b1cdbd2cSJim Jagielski 	{ "<#/ITALIC>", TAG_ITALICOFF },
582*b1cdbd2cSJim Jagielski 	{ "<#UNDER>", TAG_UNDERLINEON },
583*b1cdbd2cSJim Jagielski 	{ "<#/UNDER>", TAG_UNDERLINEOFF },
584*b1cdbd2cSJim Jagielski 
585*b1cdbd2cSJim Jagielski //	{ "<#GROUP_NOTALLOWED>", TAG_GROUP_NOTALLOWED },
586*b1cdbd2cSJim Jagielski 	{ "<#HELPID>", TAG_HELPID },
587*b1cdbd2cSJim Jagielski 	{ "<#MODIFY>", TAG_MODIFY },
588*b1cdbd2cSJim Jagielski 	{ "<#REFNR>", TAG_REFNR },
589*b1cdbd2cSJim Jagielski 
590*b1cdbd2cSJim Jagielski //	{ "<#GROUP_STRUCTURE>", TAG_GROUP_STRUCTURE },
591*b1cdbd2cSJim Jagielski 	{ "<#NAME>", TAG_NAME },
592*b1cdbd2cSJim Jagielski 	{ "<#HREF>", TAG_HREF },
593*b1cdbd2cSJim Jagielski 	{ "<#AVIS>", TAG_AVIS },
594*b1cdbd2cSJim Jagielski 	{ "<#AHID>", TAG_AHID },
595*b1cdbd2cSJim Jagielski 	{ "<#AEND>", TAG_AEND },
596*b1cdbd2cSJim Jagielski 
597*b1cdbd2cSJim Jagielski 	{ "<#TITEL>", TAG_TITEL },
598*b1cdbd2cSJim Jagielski 	{ "<#KEY>", TAG_KEY },
599*b1cdbd2cSJim Jagielski 	{ "<#INDEX>", TAG_INDEX },
600*b1cdbd2cSJim Jagielski 
601*b1cdbd2cSJim Jagielski 	{ "<#REFSTART>", TAG_REFSTART },
602*b1cdbd2cSJim Jagielski 
603*b1cdbd2cSJim Jagielski 	{ "<#GRAPHIC>", TAG_GRAPHIC },
604*b1cdbd2cSJim Jagielski 	{ "<#NEXTVERSION>", TAG_NEXTVERSION },
605*b1cdbd2cSJim Jagielski 
606*b1cdbd2cSJim Jagielski     //	{ "<#GROUP_SYSSWITCH>", TAG_GROUP_SYSSWITCH },
607*b1cdbd2cSJim Jagielski 	{ "<#WIN>", TAG_WIN },
608*b1cdbd2cSJim Jagielski 	{ "<#UNIX>", TAG_UNIX },
609*b1cdbd2cSJim Jagielski 	{ "<#MAC>", TAG_MAC },
610*b1cdbd2cSJim Jagielski 	{ "<#OS2>", TAG_OS2 },
611*b1cdbd2cSJim Jagielski 
612*b1cdbd2cSJim Jagielski //	{ "<#GROUP_PROGSWITCH>", TAG_GROUP_PROGSWITCH },
613*b1cdbd2cSJim Jagielski 	{ "<#WRITER>", TAG_WRITER },
614*b1cdbd2cSJim Jagielski 	{ "<#CALC>", TAG_CALC },
615*b1cdbd2cSJim Jagielski 	{ "<#DRAW>", TAG_DRAW },
616*b1cdbd2cSJim Jagielski 	{ "<#IMPRESS>", TAG_IMPRESS },
617*b1cdbd2cSJim Jagielski 	{ "<#SCHEDULE>", TAG_SCHEDULE },
618*b1cdbd2cSJim Jagielski 	{ "<#IMAGE>", TAG_IMAGE },
619*b1cdbd2cSJim Jagielski 	{ "<#MATH>", TAG_MATH },
620*b1cdbd2cSJim Jagielski 	{ "<#CHART>", TAG_CHART },
621*b1cdbd2cSJim Jagielski 	{ "<#OFFICE>", TAG_OFFICE },
622*b1cdbd2cSJim Jagielski   */
623*b1cdbd2cSJim Jagielski //	{ "<#TAG_GROUP_META>", TAG_GROUP_META },
624*b1cdbd2cSJim Jagielski 	{ "$[officefullname]", TAG_OFFICEFULLNAME },
625*b1cdbd2cSJim Jagielski 	{ "$[officename]", TAG_OFFICENAME },
626*b1cdbd2cSJim Jagielski 	{ "$[officepath]", TAG_OFFICEPATH },
627*b1cdbd2cSJim Jagielski 	{ "$[officeversion]", TAG_OFFICEVERSION },
628*b1cdbd2cSJim Jagielski 	{ "$[portalname]", TAG_PORTALNAME },
629*b1cdbd2cSJim Jagielski 	{ "$[portalfullname]", TAG_PORTALFULLNAME },
630*b1cdbd2cSJim Jagielski 	{ "$[portalpath]", TAG_PORTALPATH },
631*b1cdbd2cSJim Jagielski 	{ "$[portalversion]", TAG_PORTALVERSION },
632*b1cdbd2cSJim Jagielski 	{ "$[portalshortname]", TAG_PORTALSHORTNAME },
633*b1cdbd2cSJim Jagielski /*  commenting oldstyle tags
634*b1cdbd2cSJim Jagielski //	{ "<#TAG_GROUP_SINGLE>", TAG_GROUP_SINGLE },
635*b1cdbd2cSJim Jagielski 	{ "<#REFINSERT>", TAG_REFINSERT },
636*b1cdbd2cSJim Jagielski 
637*b1cdbd2cSJim Jagielski //	{ "<#GROUP_MULTI>", TAG_GROUP_MULTI },
638*b1cdbd2cSJim Jagielski 	{ "<#END>", TAG_END },
639*b1cdbd2cSJim Jagielski 	{ "<#ELSE>", TAG_ELSE },
640*b1cdbd2cSJim Jagielski 	{ "<#VERSIONEND>", TAG_VERSIONEND },
641*b1cdbd2cSJim Jagielski 	{ "<#ENDGRAPHIC>", TAG_ENDGRAPHIC },*/
642*b1cdbd2cSJim Jagielski 	{ "<Common Tag>", TAG_COMMONSTART },
643*b1cdbd2cSJim Jagielski 	{ "</Common Tag>", TAG_COMMONEND },
644*b1cdbd2cSJim Jagielski 
645*b1cdbd2cSJim Jagielski     { "<no more tags>", TAG_NOMORETAGS },
646*b1cdbd2cSJim Jagielski 	{ "", TAG_UNKNOWN_TAG },
647*b1cdbd2cSJim Jagielski };
648*b1cdbd2cSJim Jagielski 
649*b1cdbd2cSJim Jagielski 
SimpleParser()650*b1cdbd2cSJim Jagielski SimpleParser::SimpleParser()
651*b1cdbd2cSJim Jagielski : nPos( 0 )
652*b1cdbd2cSJim Jagielski , aNextTag( TAG_NOMORETAGS, TOK_INVALIDPOS )
653*b1cdbd2cSJim Jagielski {
654*b1cdbd2cSJim Jagielski }
655*b1cdbd2cSJim Jagielski 
Parse(String PaSource)656*b1cdbd2cSJim Jagielski void SimpleParser::Parse( String PaSource )
657*b1cdbd2cSJim Jagielski {
658*b1cdbd2cSJim Jagielski     aSource = PaSource;
659*b1cdbd2cSJim Jagielski 	nPos = 0;
660*b1cdbd2cSJim Jagielski 	aLastToken.Erase();
661*b1cdbd2cSJim Jagielski     aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
662*b1cdbd2cSJim Jagielski 	aTokenList.Clear();
663*b1cdbd2cSJim Jagielski };
664*b1cdbd2cSJim Jagielski 
GetNextToken(ParserMessageList & rErrorList)665*b1cdbd2cSJim Jagielski TokenInfo SimpleParser::GetNextToken( ParserMessageList &rErrorList )
666*b1cdbd2cSJim Jagielski {
667*b1cdbd2cSJim Jagielski     TokenInfo aResult;
668*b1cdbd2cSJim Jagielski     sal_uInt16 nTokenStartPos = 0;
669*b1cdbd2cSJim Jagielski     if ( aNextTag.nId != TAG_NOMORETAGS )
670*b1cdbd2cSJim Jagielski     {
671*b1cdbd2cSJim Jagielski         aResult = aNextTag;
672*b1cdbd2cSJim Jagielski         aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
673*b1cdbd2cSJim Jagielski     }
674*b1cdbd2cSJim Jagielski     else
675*b1cdbd2cSJim Jagielski     {
676*b1cdbd2cSJim Jagielski 	    aLastToken = GetNextTokenString( rErrorList, nTokenStartPos );
677*b1cdbd2cSJim Jagielski 	    if ( aLastToken.Len() == 0 )
678*b1cdbd2cSJim Jagielski 		    return TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
679*b1cdbd2cSJim Jagielski 
680*b1cdbd2cSJim Jagielski         // do we have a \< ... \> style tag?
681*b1cdbd2cSJim Jagielski         if ( aLastToken.Copy(0,2).EqualsAscii( "\\<" ) )
682*b1cdbd2cSJim Jagielski         {
683*b1cdbd2cSJim Jagielski             // check for paired \" \"
684*b1cdbd2cSJim Jagielski             bool bEven = true;
685*b1cdbd2cSJim Jagielski             sal_uInt16 nQuotePos = 0;
686*b1cdbd2cSJim Jagielski     	    sal_uInt16 nQuotedQuotesPos = aLastToken.SearchAscii( "\\\"" );
687*b1cdbd2cSJim Jagielski     	    sal_uInt16 nQuotedBackPos = aLastToken.SearchAscii( "\\\\" );    // this is only to kick out quoted backslashes
688*b1cdbd2cSJim Jagielski             while ( nQuotedQuotesPos != STRING_NOTFOUND )
689*b1cdbd2cSJim Jagielski             {
690*b1cdbd2cSJim Jagielski                 if ( nQuotedBackPos <= nQuotedQuotesPos )
691*b1cdbd2cSJim Jagielski                     nQuotePos = nQuotedBackPos+2;
692*b1cdbd2cSJim Jagielski                 else
693*b1cdbd2cSJim Jagielski                 {
694*b1cdbd2cSJim Jagielski                     nQuotePos = nQuotedQuotesPos+2;
695*b1cdbd2cSJim Jagielski                     bEven = !bEven;
696*b1cdbd2cSJim Jagielski                 }
697*b1cdbd2cSJim Jagielski 		        nQuotedQuotesPos = aLastToken.SearchAscii( "\\\"", nQuotePos );
698*b1cdbd2cSJim Jagielski     	        nQuotedBackPos = aLastToken.SearchAscii( "\\\\", nQuotePos );    // this is only to kick out quoted backslashes
699*b1cdbd2cSJim Jagielski             }
700*b1cdbd2cSJim Jagielski             if ( !bEven )
701*b1cdbd2cSJim Jagielski             {
702*b1cdbd2cSJim Jagielski         		rErrorList.AddError( 24, "Missing quotes ( \\\" ) in Tag", TokenInfo( TAG_UNKNOWN_TAG, nTokenStartPos, aLastToken ) );
703*b1cdbd2cSJim Jagielski             }
704*b1cdbd2cSJim Jagielski 
705*b1cdbd2cSJim Jagielski             // check if we have an end-tag or a start-tag
706*b1cdbd2cSJim Jagielski             sal_uInt16 nNonBlankStartPos,nNonBlankEndPos;
707*b1cdbd2cSJim Jagielski             nNonBlankStartPos = 2;
708*b1cdbd2cSJim Jagielski             while ( aLastToken.GetChar(nNonBlankStartPos) == ' ' )
709*b1cdbd2cSJim Jagielski                 nNonBlankStartPos++;
710*b1cdbd2cSJim Jagielski             if ( aLastToken.GetChar(nNonBlankStartPos) == '/' )
711*b1cdbd2cSJim Jagielski                 aResult = TokenInfo( TAG_COMMONEND, nTokenStartPos, aLastToken, rErrorList );
712*b1cdbd2cSJim Jagielski             else
713*b1cdbd2cSJim Jagielski             {
714*b1cdbd2cSJim Jagielski                 aResult = TokenInfo( TAG_COMMONSTART, nTokenStartPos, aLastToken, rErrorList );
715*b1cdbd2cSJim Jagielski                 nNonBlankEndPos = aLastToken.Len() -3;
716*b1cdbd2cSJim Jagielski                 while ( aLastToken.GetChar(nNonBlankEndPos) == ' ' )
717*b1cdbd2cSJim Jagielski                     nNonBlankEndPos--;
718*b1cdbd2cSJim Jagielski                 if ( aLastToken.GetChar( nNonBlankEndPos ) == '/' )
719*b1cdbd2cSJim Jagielski                     aNextTag = TokenInfo( TAG_COMMONEND, nTokenStartPos, String::CreateFromAscii("\\</").Append(aResult.GetTagName()).AppendAscii("\\>"), rErrorList );
720*b1cdbd2cSJim Jagielski             }
721*b1cdbd2cSJim Jagielski         }
722*b1cdbd2cSJim Jagielski         else
723*b1cdbd2cSJim Jagielski         {
724*b1cdbd2cSJim Jagielski 	        sal_uInt16 i = 0;
725*b1cdbd2cSJim Jagielski 	        while ( aKnownTags[i].nTag != TAG_UNKNOWN_TAG &&
726*b1cdbd2cSJim Jagielski 		        aLastToken != aKnownTags[i].GetName() )
727*b1cdbd2cSJim Jagielski 		        i++;
728*b1cdbd2cSJim Jagielski             aResult = TokenInfo( aKnownTags[i].nTag, nTokenStartPos );
729*b1cdbd2cSJim Jagielski         }
730*b1cdbd2cSJim Jagielski     }
731*b1cdbd2cSJim Jagielski 
732*b1cdbd2cSJim Jagielski     if ( aResult.nId == TAG_UNKNOWN_TAG )
733*b1cdbd2cSJim Jagielski         aResult = TokenInfo( TAG_UNKNOWN_TAG, nTokenStartPos, aLastToken );
734*b1cdbd2cSJim Jagielski 	aTokenList.Insert( aResult, LIST_APPEND );
735*b1cdbd2cSJim Jagielski 	return aResult;
736*b1cdbd2cSJim Jagielski }
737*b1cdbd2cSJim Jagielski 
GetNextTokenString(ParserMessageList & rErrorList,sal_uInt16 & rTagStartPos)738*b1cdbd2cSJim Jagielski String SimpleParser::GetNextTokenString( ParserMessageList &rErrorList, sal_uInt16 &rTagStartPos )
739*b1cdbd2cSJim Jagielski {
740*b1cdbd2cSJim Jagielski //	sal_uInt16 nStyle1StartPos = aSource.SearchAscii( "<#", nPos );
741*b1cdbd2cSJim Jagielski 	sal_uInt16 nStyle2StartPos = aSource.SearchAscii( "$[", nPos );
742*b1cdbd2cSJim Jagielski 	sal_uInt16 nStyle3StartPos = aSource.SearchAscii( "\\<", nPos );
743*b1cdbd2cSJim Jagielski 	sal_uInt16 nStyle4StartPos = aSource.SearchAscii( "\\\\", nPos );    // this is only to kick out quoted backslashes
744*b1cdbd2cSJim Jagielski 
745*b1cdbd2cSJim Jagielski     rTagStartPos = 0;
746*b1cdbd2cSJim Jagielski 
747*b1cdbd2cSJim Jagielski /* removing since a \<... is not likely
748*b1cdbd2cSJim Jagielski     // check if the tag starts with a letter to avoid things like <> <= ... >
749*b1cdbd2cSJim Jagielski     while ( STRING_NOTFOUND != nStyle3StartPos && !( aSource.Copy( nStyle3StartPos+2, 1 ).IsAlphaAscii() || aSource.GetChar( nStyle3StartPos+2 ) == '/' ) )
750*b1cdbd2cSJim Jagielski     	nStyle3StartPos = aSource.SearchAscii( "\\<", nStyle3StartPos+1 );
751*b1cdbd2cSJim Jagielski */
752*b1cdbd2cSJim Jagielski     if ( STRING_NOTFOUND == nStyle2StartPos && STRING_NOTFOUND == nStyle3StartPos )
753*b1cdbd2cSJim Jagielski         return String();  // no more tokens
754*b1cdbd2cSJim Jagielski 
755*b1cdbd2cSJim Jagielski 	if ( nStyle4StartPos < nStyle2StartPos && nStyle4StartPos <= nStyle3StartPos )  // <= to make sure \\ is always handled first
756*b1cdbd2cSJim Jagielski     {   // Skip quoted Backslash
757*b1cdbd2cSJim Jagielski         nPos = nStyle4StartPos +2;
758*b1cdbd2cSJim Jagielski         return GetNextTokenString( rErrorList, rTagStartPos );
759*b1cdbd2cSJim Jagielski     }
760*b1cdbd2cSJim Jagielski 
761*b1cdbd2cSJim Jagielski /*	if ( nStyle1StartPos < nStyle2StartPos && nStyle1StartPos <= nStyle3StartPos )  // <= to make sure our spechial tags are recognized before all others
762*b1cdbd2cSJim Jagielski     {	// test for <# ... > style tokens
763*b1cdbd2cSJim Jagielski 	    sal_uInt16 nEndPos = aSource.SearchAscii( ">", nStyle1StartPos );
764*b1cdbd2cSJim Jagielski         if ( nEndPos == STRING_NOTFOUND )
765*b1cdbd2cSJim Jagielski         {   // Token is incomplete. Skip start and search for better ones
766*b1cdbd2cSJim Jagielski             nPos = nStyle1StartPos +2;
767*b1cdbd2cSJim Jagielski             return GetNextTokenString( rErrorList, rTagStartPos );
768*b1cdbd2cSJim Jagielski         }
769*b1cdbd2cSJim Jagielski 	    nPos = nEndPos;
770*b1cdbd2cSJim Jagielski         rTagStartPos = nStyle1StartPos;
771*b1cdbd2cSJim Jagielski 	    return aSource.Copy( nStyle1StartPos, nEndPos-nStyle1StartPos +1 ).ToUpperAscii();
772*b1cdbd2cSJim Jagielski     }
773*b1cdbd2cSJim Jagielski     else*/ if ( nStyle2StartPos < nStyle3StartPos )
774*b1cdbd2cSJim Jagielski 	{	// test for $[ ... ] style tokens
775*b1cdbd2cSJim Jagielski 		sal_uInt16 nEndPos = aSource.SearchAscii( "]", nStyle2StartPos);
776*b1cdbd2cSJim Jagielski         if ( nEndPos == STRING_NOTFOUND )
777*b1cdbd2cSJim Jagielski         {   // Token is incomplete. Skip start and search for better ones
778*b1cdbd2cSJim Jagielski             nPos = nStyle2StartPos +2;
779*b1cdbd2cSJim Jagielski             return GetNextTokenString( rErrorList, rTagStartPos );
780*b1cdbd2cSJim Jagielski         }
781*b1cdbd2cSJim Jagielski 		nPos = nEndPos;
782*b1cdbd2cSJim Jagielski         rTagStartPos = nStyle2StartPos;
783*b1cdbd2cSJim Jagielski 		return aSource.Copy( nStyle2StartPos, nEndPos-nStyle2StartPos +1 );
784*b1cdbd2cSJim Jagielski 	}
785*b1cdbd2cSJim Jagielski     else
786*b1cdbd2cSJim Jagielski 	{	// test for \< ... \> style tokens
787*b1cdbd2cSJim Jagielski     	sal_uInt16 nEndPos = aSource.SearchAscii( "\\>", nStyle3StartPos);
788*b1cdbd2cSJim Jagielski     	sal_uInt16 nQuotedBackPos = aSource.SearchAscii( "\\\\", nStyle3StartPos );    // this is only to kick out quoted backslashes
789*b1cdbd2cSJim Jagielski         while ( nQuotedBackPos <= nEndPos && nQuotedBackPos != STRING_NOTFOUND )
790*b1cdbd2cSJim Jagielski         {
791*b1cdbd2cSJim Jagielski 		    nEndPos = aSource.SearchAscii( "\\>", nQuotedBackPos +2);
792*b1cdbd2cSJim Jagielski     	    nQuotedBackPos = aSource.SearchAscii( "\\\\", nQuotedBackPos +2 );    // this is only to kick out quoted backslashes
793*b1cdbd2cSJim Jagielski         }
794*b1cdbd2cSJim Jagielski         if ( nEndPos == STRING_NOTFOUND )
795*b1cdbd2cSJim Jagielski         {   // Token is incomplete. Skip start and search for better ones
796*b1cdbd2cSJim Jagielski             nPos = nStyle3StartPos +2;
797*b1cdbd2cSJim Jagielski 		    ByteString sTmp( "Tag Start '\\<' without Tag End '\\>': " );
798*b1cdbd2cSJim Jagielski         	rErrorList.AddError( 24, "Tag Start '\\<' without Tag End '\\>'", TokenInfo( TAG_UNKNOWN_TAG, nStyle3StartPos, aSource.Copy( nStyle3StartPos-10, 20 ) ) );
799*b1cdbd2cSJim Jagielski             return GetNextTokenString( rErrorList, rTagStartPos );
800*b1cdbd2cSJim Jagielski         }
801*b1cdbd2cSJim Jagielski         // check for paired quoted "    -->   \"sometext\"
802*b1cdbd2cSJim Jagielski 
803*b1cdbd2cSJim Jagielski         nPos = nEndPos;
804*b1cdbd2cSJim Jagielski         rTagStartPos = nStyle3StartPos;
805*b1cdbd2cSJim Jagielski 		return aSource.Copy( nStyle3StartPos, nEndPos-nStyle3StartPos +2 );
806*b1cdbd2cSJim Jagielski 	}
807*b1cdbd2cSJim Jagielski }
808*b1cdbd2cSJim Jagielski 
GetLexem(TokenInfo const & aToken)809*b1cdbd2cSJim Jagielski String SimpleParser::GetLexem( TokenInfo const &aToken )
810*b1cdbd2cSJim Jagielski {
811*b1cdbd2cSJim Jagielski     if ( aToken.aTokenString.Len() )
812*b1cdbd2cSJim Jagielski         return aToken.aTokenString;
813*b1cdbd2cSJim Jagielski     else
814*b1cdbd2cSJim Jagielski     {
815*b1cdbd2cSJim Jagielski         sal_uInt16 i = 0;
816*b1cdbd2cSJim Jagielski 	    while ( aKnownTags[i].nTag != TAG_UNKNOWN_TAG &&
817*b1cdbd2cSJim Jagielski 		    aKnownTags[i].nTag != aToken.nId )
818*b1cdbd2cSJim Jagielski 		    i++;
819*b1cdbd2cSJim Jagielski 
820*b1cdbd2cSJim Jagielski         return aKnownTags[i].GetName();
821*b1cdbd2cSJim Jagielski     }
822*b1cdbd2cSJim Jagielski }
823*b1cdbd2cSJim Jagielski 
TokenParser()824*b1cdbd2cSJim Jagielski TokenParser::TokenParser()
825*b1cdbd2cSJim Jagielski : pErrorList( NULL )
826*b1cdbd2cSJim Jagielski {}
827*b1cdbd2cSJim Jagielski 
Parse(const String & aCode,ParserMessageList * pList)828*b1cdbd2cSJim Jagielski void TokenParser::Parse( const String &aCode, ParserMessageList* pList )
829*b1cdbd2cSJim Jagielski {
830*b1cdbd2cSJim Jagielski     pErrorList = pList;
831*b1cdbd2cSJim Jagielski 
832*b1cdbd2cSJim Jagielski 	//Scanner initialisieren
833*b1cdbd2cSJim Jagielski 	aParser.Parse( aCode );
834*b1cdbd2cSJim Jagielski 
835*b1cdbd2cSJim Jagielski 	//erstes Symbol holen
836*b1cdbd2cSJim Jagielski 	aTag = aParser.GetNextToken( *pErrorList );
837*b1cdbd2cSJim Jagielski 
838*b1cdbd2cSJim Jagielski 	nPfCaseOptions = 0;
839*b1cdbd2cSJim Jagielski 	nAppCaseOptions = 0;
840*b1cdbd2cSJim Jagielski 	bPfCaseActive = sal_False;
841*b1cdbd2cSJim Jagielski 	bAppCaseActive = sal_False;
842*b1cdbd2cSJim Jagielski 
843*b1cdbd2cSJim Jagielski 	nActiveRefTypes = 0;
844*b1cdbd2cSJim Jagielski 
845*b1cdbd2cSJim Jagielski     //Ausfuehren der Start-Produktion
846*b1cdbd2cSJim Jagielski 	Paragraph();
847*b1cdbd2cSJim Jagielski 
848*b1cdbd2cSJim Jagielski 	//Es wurde nicht die ganze Kette abgearbeitet, bisher ist aber
849*b1cdbd2cSJim Jagielski 	//kein Fehler aufgetreten
850*b1cdbd2cSJim Jagielski 	//=> es wurde ein einleitendes Tag vergessen
851*b1cdbd2cSJim Jagielski 	if ( aTag.nId != TAG_NOMORETAGS )
852*b1cdbd2cSJim Jagielski 	{
853*b1cdbd2cSJim Jagielski 		switch ( aTag.nId )
854*b1cdbd2cSJim Jagielski 		{
855*b1cdbd2cSJim Jagielski 			case TAG_END:
856*b1cdbd2cSJim Jagielski 				{
857*b1cdbd2cSJim Jagielski 					ParseError( 3, "Extra Tag <#END>. Switch or <#HREF> expected.", aTag );
858*b1cdbd2cSJim Jagielski 				}
859*b1cdbd2cSJim Jagielski 				break;
860*b1cdbd2cSJim Jagielski 			case TAG_BOLDOFF:
861*b1cdbd2cSJim Jagielski 				{
862*b1cdbd2cSJim Jagielski 					ParseError( 4, "<#BOLD> expected before <#/BOLD>.", aTag );
863*b1cdbd2cSJim Jagielski 				}
864*b1cdbd2cSJim Jagielski 				break;
865*b1cdbd2cSJim Jagielski 			case TAG_ITALICOFF:
866*b1cdbd2cSJim Jagielski 				{
867*b1cdbd2cSJim Jagielski 					ParseError( 5, "<#ITALIC> expected before <#/ITALIC>.", aTag );
868*b1cdbd2cSJim Jagielski 				}
869*b1cdbd2cSJim Jagielski 				break;
870*b1cdbd2cSJim Jagielski 			case TAG_UNDERLINEOFF:
871*b1cdbd2cSJim Jagielski 				{
872*b1cdbd2cSJim Jagielski 					ParseError( 17, "<#UNDER> expected before <#/UNDER>.", aTag );
873*b1cdbd2cSJim Jagielski 				}
874*b1cdbd2cSJim Jagielski 				break;
875*b1cdbd2cSJim Jagielski /*			case TAG_MISSPARENTHESIS:
876*b1cdbd2cSJim Jagielski 				{
877*b1cdbd2cSJim Jagielski 					ParseError( 14, "missing closing parenthesis '>'", aTag );
878*b1cdbd2cSJim Jagielski 				}
879*b1cdbd2cSJim Jagielski 				break;*/
880*b1cdbd2cSJim Jagielski 			case TAG_AEND:
881*b1cdbd2cSJim Jagielski 				{
882*b1cdbd2cSJim Jagielski 					ParseError( 5, "Extra Tag <#AEND>. <#AVIS> or <#AHID> expected.", aTag );
883*b1cdbd2cSJim Jagielski 				}
884*b1cdbd2cSJim Jagielski 				break;
885*b1cdbd2cSJim Jagielski 			case TAG_ELSE:
886*b1cdbd2cSJim Jagielski 				{
887*b1cdbd2cSJim Jagielski 					ParseError( 16, "Application-tag or platform-tag expected before <#ELSE>.", aTag );
888*b1cdbd2cSJim Jagielski 				}
889*b1cdbd2cSJim Jagielski 				break;
890*b1cdbd2cSJim Jagielski 			case TAG_UNKNOWN_TAG:
891*b1cdbd2cSJim Jagielski 				{
892*b1cdbd2cSJim Jagielski 					ParseError( 6, "unknown Tag", aTag );
893*b1cdbd2cSJim Jagielski 				}
894*b1cdbd2cSJim Jagielski 				break;
895*b1cdbd2cSJim Jagielski 			default:
896*b1cdbd2cSJim Jagielski 				{
897*b1cdbd2cSJim Jagielski 					ParseError( 6, "unexpected Tag", aTag );
898*b1cdbd2cSJim Jagielski 				}
899*b1cdbd2cSJim Jagielski 		}
900*b1cdbd2cSJim Jagielski 	}
901*b1cdbd2cSJim Jagielski     pErrorList = NULL;
902*b1cdbd2cSJim Jagielski }
903*b1cdbd2cSJim Jagielski 
Paragraph()904*b1cdbd2cSJim Jagielski void TokenParser::Paragraph()
905*b1cdbd2cSJim Jagielski {
906*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
907*b1cdbd2cSJim Jagielski 	{
908*b1cdbd2cSJim Jagielski 		case TAG_GRAPHIC:
909*b1cdbd2cSJim Jagielski 		case TAG_NEXTVERSION:
910*b1cdbd2cSJim Jagielski 			{
911*b1cdbd2cSJim Jagielski 				TagRef();
912*b1cdbd2cSJim Jagielski 				Paragraph();
913*b1cdbd2cSJim Jagielski 			}
914*b1cdbd2cSJim Jagielski 			break;
915*b1cdbd2cSJim Jagielski 		case TAG_AVIS:
916*b1cdbd2cSJim Jagielski 		case TAG_AHID:
917*b1cdbd2cSJim Jagielski 			{
918*b1cdbd2cSJim Jagielski 				TagRef();
919*b1cdbd2cSJim Jagielski 				Paragraph();
920*b1cdbd2cSJim Jagielski 			}
921*b1cdbd2cSJim Jagielski 			break;
922*b1cdbd2cSJim Jagielski 		case TAG_HELPID:
923*b1cdbd2cSJim Jagielski 			{
924*b1cdbd2cSJim Jagielski 				SimpleTag();
925*b1cdbd2cSJim Jagielski 				Paragraph();
926*b1cdbd2cSJim Jagielski 			}
927*b1cdbd2cSJim Jagielski 			break;
928*b1cdbd2cSJim Jagielski 		case TAG_OFFICEFULLNAME:
929*b1cdbd2cSJim Jagielski 		case TAG_OFFICENAME:
930*b1cdbd2cSJim Jagielski 		case TAG_OFFICEPATH:
931*b1cdbd2cSJim Jagielski 		case TAG_OFFICEVERSION:
932*b1cdbd2cSJim Jagielski 		case TAG_PORTALNAME:
933*b1cdbd2cSJim Jagielski 		case TAG_PORTALFULLNAME:
934*b1cdbd2cSJim Jagielski 		case TAG_PORTALPATH:
935*b1cdbd2cSJim Jagielski 		case TAG_PORTALVERSION:
936*b1cdbd2cSJim Jagielski 		case TAG_PORTALSHORTNAME:
937*b1cdbd2cSJim Jagielski 			{
938*b1cdbd2cSJim Jagielski 				SimpleTag();
939*b1cdbd2cSJim Jagielski 				Paragraph();
940*b1cdbd2cSJim Jagielski 			}
941*b1cdbd2cSJim Jagielski 			break;
942*b1cdbd2cSJim Jagielski 		case TAG_REFINSERT:
943*b1cdbd2cSJim Jagielski 			{
944*b1cdbd2cSJim Jagielski 				SimpleTag();
945*b1cdbd2cSJim Jagielski 				Paragraph();
946*b1cdbd2cSJim Jagielski 			}
947*b1cdbd2cSJim Jagielski 			break;
948*b1cdbd2cSJim Jagielski 		case TAG_BOLDON:
949*b1cdbd2cSJim Jagielski 		case TAG_ITALICON:
950*b1cdbd2cSJim Jagielski 		case TAG_UNDERLINEON:
951*b1cdbd2cSJim Jagielski 		case TAG_COMMONSTART:
952*b1cdbd2cSJim Jagielski 			{
953*b1cdbd2cSJim Jagielski 				TagPair();
954*b1cdbd2cSJim Jagielski 				Paragraph();
955*b1cdbd2cSJim Jagielski 			}
956*b1cdbd2cSJim Jagielski 			break;
957*b1cdbd2cSJim Jagielski 		case TAG_HREF:
958*b1cdbd2cSJim Jagielski 		case TAG_NAME:
959*b1cdbd2cSJim Jagielski 		case TAG_KEY:
960*b1cdbd2cSJim Jagielski 		case TAG_INDEX:
961*b1cdbd2cSJim Jagielski         case TAG_TITEL:
962*b1cdbd2cSJim Jagielski         case TAG_REFSTART:
963*b1cdbd2cSJim Jagielski             {
964*b1cdbd2cSJim Jagielski 				TagRef();
965*b1cdbd2cSJim Jagielski 				Paragraph();
966*b1cdbd2cSJim Jagielski 			}
967*b1cdbd2cSJim Jagielski 			break;
968*b1cdbd2cSJim Jagielski 		case TAG_OS2:
969*b1cdbd2cSJim Jagielski 		case TAG_WIN:
970*b1cdbd2cSJim Jagielski 		case TAG_UNIX:
971*b1cdbd2cSJim Jagielski 		case TAG_MAC: //...
972*b1cdbd2cSJim Jagielski 			{
973*b1cdbd2cSJim Jagielski 				if ( ! bPfCaseActive )
974*b1cdbd2cSJim Jagielski 				{
975*b1cdbd2cSJim Jagielski                     //PfCases duerfen nicht verschachtelt sein:
976*b1cdbd2cSJim Jagielski 					bPfCaseActive = sal_True;
977*b1cdbd2cSJim Jagielski 					PfCase();
978*b1cdbd2cSJim Jagielski 
979*b1cdbd2cSJim Jagielski 					//So jetzt kann wieder ein PfCase kommen:
980*b1cdbd2cSJim Jagielski 					bPfCaseActive = sal_False;
981*b1cdbd2cSJim Jagielski 					Paragraph();
982*b1cdbd2cSJim Jagielski 				}
983*b1cdbd2cSJim Jagielski 			}
984*b1cdbd2cSJim Jagielski 			break;
985*b1cdbd2cSJim Jagielski 		case TAG_WRITER:
986*b1cdbd2cSJim Jagielski 		case TAG_CALC:
987*b1cdbd2cSJim Jagielski 		case TAG_DRAW:
988*b1cdbd2cSJim Jagielski 		case TAG_IMPRESS:
989*b1cdbd2cSJim Jagielski 		case TAG_SCHEDULE:
990*b1cdbd2cSJim Jagielski 		case TAG_IMAGE:
991*b1cdbd2cSJim Jagielski 		case TAG_MATH:
992*b1cdbd2cSJim Jagielski 		case TAG_CHART:
993*b1cdbd2cSJim Jagielski 		case TAG_OFFICE:
994*b1cdbd2cSJim Jagielski 			{
995*b1cdbd2cSJim Jagielski 				if ( !bAppCaseActive )
996*b1cdbd2cSJim Jagielski 				{
997*b1cdbd2cSJim Jagielski                     //AppCases duerfen nicht verschachtelt sein:
998*b1cdbd2cSJim Jagielski 					bAppCaseActive = sal_True;
999*b1cdbd2cSJim Jagielski 					AppCase();
1000*b1cdbd2cSJim Jagielski 
1001*b1cdbd2cSJim Jagielski                     //jetzt koennen wieder AppCases kommen:
1002*b1cdbd2cSJim Jagielski 					bAppCaseActive = sal_False;
1003*b1cdbd2cSJim Jagielski 					Paragraph();
1004*b1cdbd2cSJim Jagielski 				}
1005*b1cdbd2cSJim Jagielski 			}
1006*b1cdbd2cSJim Jagielski 			break;
1007*b1cdbd2cSJim Jagielski 
1008*b1cdbd2cSJim Jagielski 		//Case TAG_BOLDOFF, TAG_ITALICOFF, TAG_BUNDERLINE, TAG_END
1009*b1cdbd2cSJim Jagielski 			//nichts tun wg. epsilon-Prod.
1010*b1cdbd2cSJim Jagielski 	}
1011*b1cdbd2cSJim Jagielski }
1012*b1cdbd2cSJim Jagielski 
PfCase()1013*b1cdbd2cSJim Jagielski void TokenParser::PfCase()
1014*b1cdbd2cSJim Jagielski {
1015*b1cdbd2cSJim Jagielski 
1016*b1cdbd2cSJim Jagielski 	//Produktion:
1017*b1cdbd2cSJim Jagielski 	//PfCase -> PfCaseBegin Paragraph (PfCase | PfCaseEnd)
1018*b1cdbd2cSJim Jagielski 
1019*b1cdbd2cSJim Jagielski 	PfCaseBegin();
1020*b1cdbd2cSJim Jagielski 
1021*b1cdbd2cSJim Jagielski 	//Jetzt ist eine PfCase-Produktion aktiv:
1022*b1cdbd2cSJim Jagielski 	Paragraph();
1023*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1024*b1cdbd2cSJim Jagielski 	{
1025*b1cdbd2cSJim Jagielski 		case TAG_ELSE:
1026*b1cdbd2cSJim Jagielski 		case TAG_END:
1027*b1cdbd2cSJim Jagielski 			{
1028*b1cdbd2cSJim Jagielski 				CaseEnd();
1029*b1cdbd2cSJim Jagielski 			}
1030*b1cdbd2cSJim Jagielski 			break;
1031*b1cdbd2cSJim Jagielski 		case TAG_OS2:
1032*b1cdbd2cSJim Jagielski 		case TAG_WIN:
1033*b1cdbd2cSJim Jagielski 		case TAG_UNIX:
1034*b1cdbd2cSJim Jagielski 		case TAG_MAC: //First (PfBegin)
1035*b1cdbd2cSJim Jagielski 			{
1036*b1cdbd2cSJim Jagielski 				PfCase();
1037*b1cdbd2cSJim Jagielski 			}
1038*b1cdbd2cSJim Jagielski 			break;
1039*b1cdbd2cSJim Jagielski 		default:
1040*b1cdbd2cSJim Jagielski 			ParseError( 8, "<#ELSE> or <#END> or platform-tag expected.", aTag );
1041*b1cdbd2cSJim Jagielski 	}
1042*b1cdbd2cSJim Jagielski     //Die gemerkten Tags wieder loeschen fuer naechstes PfCase:
1043*b1cdbd2cSJim Jagielski 	nPfCaseOptions = 0;
1044*b1cdbd2cSJim Jagielski }
1045*b1cdbd2cSJim Jagielski 
PfCaseBegin()1046*b1cdbd2cSJim Jagielski void TokenParser::PfCaseBegin()
1047*b1cdbd2cSJim Jagielski {
1048*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1049*b1cdbd2cSJim Jagielski 	{
1050*b1cdbd2cSJim Jagielski 		case TAG_OS2:
1051*b1cdbd2cSJim Jagielski 		case TAG_WIN:
1052*b1cdbd2cSJim Jagielski 		case TAG_UNIX:
1053*b1cdbd2cSJim Jagielski 		case TAG_MAC:
1054*b1cdbd2cSJim Jagielski 			{
1055*b1cdbd2cSJim Jagielski 				//Token darf noch nicht vorgekommen sein im
1056*b1cdbd2cSJim Jagielski 				//aktuellen Plattform-Case:
1057*b1cdbd2cSJim Jagielski 				if ( !HAS_FLAG( nPfCaseOptions, TAG_NOGROUP( aTag.nId ) ) )
1058*b1cdbd2cSJim Jagielski 				{
1059*b1cdbd2cSJim Jagielski 					SET_FLAG( nPfCaseOptions, TAG_NOGROUP( aTag.nId ) );
1060*b1cdbd2cSJim Jagielski 					match( aTag, aTag );
1061*b1cdbd2cSJim Jagielski 				}
1062*b1cdbd2cSJim Jagielski 				else {
1063*b1cdbd2cSJim Jagielski 					ParseError( 9, "Tag defined twice in the same platform-case", aTag );
1064*b1cdbd2cSJim Jagielski 				}
1065*b1cdbd2cSJim Jagielski 			}
1066*b1cdbd2cSJim Jagielski 	}
1067*b1cdbd2cSJim Jagielski }
1068*b1cdbd2cSJim Jagielski 
AppCase()1069*b1cdbd2cSJim Jagielski void TokenParser::AppCase()
1070*b1cdbd2cSJim Jagielski {
1071*b1cdbd2cSJim Jagielski 
1072*b1cdbd2cSJim Jagielski 	//Produktion:
1073*b1cdbd2cSJim Jagielski 	//AppCase -> AppCaseBegin Paragraph (AppCase | AppCaseEnd)
1074*b1cdbd2cSJim Jagielski 
1075*b1cdbd2cSJim Jagielski 
1076*b1cdbd2cSJim Jagielski 	AppCaseBegin();
1077*b1cdbd2cSJim Jagielski 
1078*b1cdbd2cSJim Jagielski 	Paragraph();
1079*b1cdbd2cSJim Jagielski 
1080*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1081*b1cdbd2cSJim Jagielski 	{
1082*b1cdbd2cSJim Jagielski 		case TAG_ELSE:
1083*b1cdbd2cSJim Jagielski 		case TAG_END:
1084*b1cdbd2cSJim Jagielski 			{
1085*b1cdbd2cSJim Jagielski 				CaseEnd();
1086*b1cdbd2cSJim Jagielski 			}
1087*b1cdbd2cSJim Jagielski 			break;
1088*b1cdbd2cSJim Jagielski 		case TAG_WRITER:
1089*b1cdbd2cSJim Jagielski 		case TAG_DRAW:
1090*b1cdbd2cSJim Jagielski 		case TAG_CALC:
1091*b1cdbd2cSJim Jagielski 		case TAG_IMAGE:
1092*b1cdbd2cSJim Jagielski 		case TAG_MATH:
1093*b1cdbd2cSJim Jagielski 		case TAG_CHART:
1094*b1cdbd2cSJim Jagielski 		case TAG_OFFICE:
1095*b1cdbd2cSJim Jagielski 		case TAG_IMPRESS:
1096*b1cdbd2cSJim Jagielski 		case TAG_SCHEDULE: //First (AppBegin)
1097*b1cdbd2cSJim Jagielski 			{
1098*b1cdbd2cSJim Jagielski 				AppCase();
1099*b1cdbd2cSJim Jagielski 			}
1100*b1cdbd2cSJim Jagielski 			break;
1101*b1cdbd2cSJim Jagielski 		default:
1102*b1cdbd2cSJim Jagielski 			ParseError( 1, "<#ELSE> or <#END> or application-case-tag expected.", aTag );
1103*b1cdbd2cSJim Jagielski 		}
1104*b1cdbd2cSJim Jagielski 
1105*b1cdbd2cSJim Jagielski     //Die gemerkten Tags wieder loeschen fuer naechstes AppCase:
1106*b1cdbd2cSJim Jagielski 	nAppCaseOptions = 0;
1107*b1cdbd2cSJim Jagielski }
1108*b1cdbd2cSJim Jagielski 
AppCaseBegin()1109*b1cdbd2cSJim Jagielski void TokenParser::AppCaseBegin()
1110*b1cdbd2cSJim Jagielski {
1111*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1112*b1cdbd2cSJim Jagielski 	{
1113*b1cdbd2cSJim Jagielski 		case TAG_WRITER:
1114*b1cdbd2cSJim Jagielski 		case TAG_DRAW:
1115*b1cdbd2cSJim Jagielski 		case TAG_CALC:
1116*b1cdbd2cSJim Jagielski 		case TAG_IMAGE:
1117*b1cdbd2cSJim Jagielski 		case TAG_MATH:
1118*b1cdbd2cSJim Jagielski 		case TAG_CHART:
1119*b1cdbd2cSJim Jagielski 		case TAG_OFFICE:
1120*b1cdbd2cSJim Jagielski 		case TAG_IMPRESS:
1121*b1cdbd2cSJim Jagielski 		case TAG_SCHEDULE:
1122*b1cdbd2cSJim Jagielski 			{
1123*b1cdbd2cSJim Jagielski 				//Token darf noch nicht vorgekommen sein im
1124*b1cdbd2cSJim Jagielski 				//aktuellen Plattform-Case:
1125*b1cdbd2cSJim Jagielski 				if ( !HAS_FLAG( nAppCaseOptions, TAG_NOGROUP( aTag.nId ) ) )
1126*b1cdbd2cSJim Jagielski 				{
1127*b1cdbd2cSJim Jagielski 					SET_FLAG( nAppCaseOptions, TAG_NOGROUP( aTag.nId ) );
1128*b1cdbd2cSJim Jagielski 					match( aTag, aTag );
1129*b1cdbd2cSJim Jagielski 				}
1130*b1cdbd2cSJim Jagielski 				else {
1131*b1cdbd2cSJim Jagielski 					ParseError( 13, "Tag defined twice in the same application-case.", aTag );
1132*b1cdbd2cSJim Jagielski 				}
1133*b1cdbd2cSJim Jagielski 			}
1134*b1cdbd2cSJim Jagielski 	}
1135*b1cdbd2cSJim Jagielski }
1136*b1cdbd2cSJim Jagielski 
CaseEnd()1137*b1cdbd2cSJim Jagielski void TokenParser::CaseEnd()
1138*b1cdbd2cSJim Jagielski {
1139*b1cdbd2cSJim Jagielski 	//Produktion:
1140*b1cdbd2cSJim Jagielski 	//CaseEnd -> <#ELSE> Paragraph <#END> | <#END>
1141*b1cdbd2cSJim Jagielski 
1142*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1143*b1cdbd2cSJim Jagielski 	{
1144*b1cdbd2cSJim Jagielski 		case TAG_ELSE:
1145*b1cdbd2cSJim Jagielski 		{
1146*b1cdbd2cSJim Jagielski 			match( aTag, TAG_ELSE );
1147*b1cdbd2cSJim Jagielski 			Paragraph();
1148*b1cdbd2cSJim Jagielski 			match( aTag, TAG_END );
1149*b1cdbd2cSJim Jagielski 		}
1150*b1cdbd2cSJim Jagielski 		break;
1151*b1cdbd2cSJim Jagielski 		case TAG_END:
1152*b1cdbd2cSJim Jagielski 		{
1153*b1cdbd2cSJim Jagielski 			match( aTag, TAG_END );
1154*b1cdbd2cSJim Jagielski 		}
1155*b1cdbd2cSJim Jagielski 		break;
1156*b1cdbd2cSJim Jagielski 		default:
1157*b1cdbd2cSJim Jagielski 			ParseError( 2, "<#ELSE> or <#END> expected.", aTag );
1158*b1cdbd2cSJim Jagielski 	}
1159*b1cdbd2cSJim Jagielski }
1160*b1cdbd2cSJim Jagielski 
SimpleTag()1161*b1cdbd2cSJim Jagielski void TokenParser::SimpleTag()
1162*b1cdbd2cSJim Jagielski {
1163*b1cdbd2cSJim Jagielski 
1164*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1165*b1cdbd2cSJim Jagielski 	{
1166*b1cdbd2cSJim Jagielski 		case TAG_HELPID:
1167*b1cdbd2cSJim Jagielski 			{
1168*b1cdbd2cSJim Jagielski 				match( aTag, TAG_HELPID );
1169*b1cdbd2cSJim Jagielski     		}
1170*b1cdbd2cSJim Jagielski 			break;
1171*b1cdbd2cSJim Jagielski 		case TAG_OFFICEFULLNAME:
1172*b1cdbd2cSJim Jagielski 		case TAG_OFFICENAME:
1173*b1cdbd2cSJim Jagielski 		case TAG_OFFICEPATH:
1174*b1cdbd2cSJim Jagielski 		case TAG_OFFICEVERSION:
1175*b1cdbd2cSJim Jagielski 		case TAG_PORTALNAME:
1176*b1cdbd2cSJim Jagielski 		case TAG_PORTALFULLNAME:
1177*b1cdbd2cSJim Jagielski 		case TAG_PORTALPATH:
1178*b1cdbd2cSJim Jagielski 		case TAG_PORTALVERSION:
1179*b1cdbd2cSJim Jagielski 		case TAG_PORTALSHORTNAME:
1180*b1cdbd2cSJim Jagielski 
1181*b1cdbd2cSJim Jagielski         case TAG_REFINSERT:
1182*b1cdbd2cSJim Jagielski 			{
1183*b1cdbd2cSJim Jagielski 				match( aTag, aTag );
1184*b1cdbd2cSJim Jagielski     		}
1185*b1cdbd2cSJim Jagielski 			break;
1186*b1cdbd2cSJim Jagielski 		default:
1187*b1cdbd2cSJim Jagielski 			ParseError( 15, "[<#SimpleTag>] expected.", aTag );
1188*b1cdbd2cSJim Jagielski 	}
1189*b1cdbd2cSJim Jagielski }
1190*b1cdbd2cSJim Jagielski 
TagPair()1191*b1cdbd2cSJim Jagielski void TokenParser::TagPair()
1192*b1cdbd2cSJim Jagielski {
1193*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1194*b1cdbd2cSJim Jagielski 	{
1195*b1cdbd2cSJim Jagielski 		case TAG_BOLDON:
1196*b1cdbd2cSJim Jagielski 			{
1197*b1cdbd2cSJim Jagielski 				match( aTag, TAG_BOLDON );
1198*b1cdbd2cSJim Jagielski 				Paragraph();
1199*b1cdbd2cSJim Jagielski 				match( aTag, TAG_BOLDOFF );
1200*b1cdbd2cSJim Jagielski 			}
1201*b1cdbd2cSJim Jagielski 			break;
1202*b1cdbd2cSJim Jagielski 		case TAG_ITALICON:
1203*b1cdbd2cSJim Jagielski 			{
1204*b1cdbd2cSJim Jagielski 				match( aTag, TAG_ITALICON );
1205*b1cdbd2cSJim Jagielski 				Paragraph();
1206*b1cdbd2cSJim Jagielski 				match( aTag, TAG_ITALICOFF );
1207*b1cdbd2cSJim Jagielski 			}
1208*b1cdbd2cSJim Jagielski 			break;
1209*b1cdbd2cSJim Jagielski 		case TAG_UNDERLINEON:
1210*b1cdbd2cSJim Jagielski 			{
1211*b1cdbd2cSJim Jagielski 				match( aTag, TAG_UNDERLINEON );
1212*b1cdbd2cSJim Jagielski 				Paragraph();
1213*b1cdbd2cSJim Jagielski 				match( aTag, TAG_UNDERLINEOFF );
1214*b1cdbd2cSJim Jagielski 			}
1215*b1cdbd2cSJim Jagielski 			break;
1216*b1cdbd2cSJim Jagielski 		case TAG_COMMONSTART:
1217*b1cdbd2cSJim Jagielski 			{
1218*b1cdbd2cSJim Jagielski                 //remember tag so we can give the original tag in case of an error
1219*b1cdbd2cSJim Jagielski                 TokenInfo aEndTag( aTag );
1220*b1cdbd2cSJim Jagielski                 aEndTag.nId = TAG_COMMONEND;
1221*b1cdbd2cSJim Jagielski 				match( aTag, TAG_COMMONSTART );
1222*b1cdbd2cSJim Jagielski 				Paragraph();
1223*b1cdbd2cSJim Jagielski 				match( aTag, aEndTag );
1224*b1cdbd2cSJim Jagielski 			}
1225*b1cdbd2cSJim Jagielski 			break;
1226*b1cdbd2cSJim Jagielski 		default:
1227*b1cdbd2cSJim Jagielski 			ParseError( 10, "<#BOLD>, <#ITALIC>, <#UNDER> expected.", aTag );
1228*b1cdbd2cSJim Jagielski 	}
1229*b1cdbd2cSJim Jagielski }
1230*b1cdbd2cSJim Jagielski 
1231*b1cdbd2cSJim Jagielski 
TagRef()1232*b1cdbd2cSJim Jagielski void TokenParser::TagRef()
1233*b1cdbd2cSJim Jagielski {
1234*b1cdbd2cSJim Jagielski 	switch ( aTag.nId )
1235*b1cdbd2cSJim Jagielski 	{
1236*b1cdbd2cSJim Jagielski 		case TAG_GRAPHIC:
1237*b1cdbd2cSJim Jagielski 		case TAG_NEXTVERSION:
1238*b1cdbd2cSJim Jagielski             {
1239*b1cdbd2cSJim Jagielski 				if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
1240*b1cdbd2cSJim Jagielski 				{
1241*b1cdbd2cSJim Jagielski 					TokenId aThisToken = aTag.nId;
1242*b1cdbd2cSJim Jagielski 					SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1243*b1cdbd2cSJim Jagielski 					match( aTag, aTag );
1244*b1cdbd2cSJim Jagielski 					Paragraph();
1245*b1cdbd2cSJim Jagielski                     if ( aThisToken == TAG_GRAPHIC )
1246*b1cdbd2cSJim Jagielski     					match( aTag, TAG_ENDGRAPHIC );
1247*b1cdbd2cSJim Jagielski                     else
1248*b1cdbd2cSJim Jagielski     					match( aTag, TAG_VERSIONEND );
1249*b1cdbd2cSJim Jagielski                     // don't reset since alowed only once per paragraph
1250*b1cdbd2cSJim Jagielski 					// RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1251*b1cdbd2cSJim Jagielski 				}
1252*b1cdbd2cSJim Jagielski 				else
1253*b1cdbd2cSJim Jagielski 				{
1254*b1cdbd2cSJim Jagielski 					ParseError( 11, "Tags <#GRAPHIC>,<#NEXTVERSION> allowed only once per paragraph at", aTag );
1255*b1cdbd2cSJim Jagielski 				}
1256*b1cdbd2cSJim Jagielski             }
1257*b1cdbd2cSJim Jagielski 			break;
1258*b1cdbd2cSJim Jagielski 		case TAG_AVIS:
1259*b1cdbd2cSJim Jagielski 		case TAG_AHID:
1260*b1cdbd2cSJim Jagielski 			{
1261*b1cdbd2cSJim Jagielski 				if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
1262*b1cdbd2cSJim Jagielski 				{
1263*b1cdbd2cSJim Jagielski 					TokenId aThisToken = aTag.nId;
1264*b1cdbd2cSJim Jagielski 					SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1265*b1cdbd2cSJim Jagielski 					match( aTag, aTag );
1266*b1cdbd2cSJim Jagielski 					Paragraph();
1267*b1cdbd2cSJim Jagielski 					match( aTag, TAG_AEND );
1268*b1cdbd2cSJim Jagielski 					RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1269*b1cdbd2cSJim Jagielski 				}
1270*b1cdbd2cSJim Jagielski 				else
1271*b1cdbd2cSJim Jagielski 				{
1272*b1cdbd2cSJim Jagielski 					ParseError( 11, "Nested <#AHID>,<#AVIS> not allowed.", aTag );
1273*b1cdbd2cSJim Jagielski 				}
1274*b1cdbd2cSJim Jagielski 			}
1275*b1cdbd2cSJim Jagielski 			break;
1276*b1cdbd2cSJim Jagielski 		case TAG_HREF:
1277*b1cdbd2cSJim Jagielski 		case TAG_NAME:
1278*b1cdbd2cSJim Jagielski 			{
1279*b1cdbd2cSJim Jagielski 
1280*b1cdbd2cSJim Jagielski 			}
1281*b1cdbd2cSJim Jagielski 			// NOBREAK
1282*b1cdbd2cSJim Jagielski 		case TAG_KEY:
1283*b1cdbd2cSJim Jagielski 		case TAG_INDEX:
1284*b1cdbd2cSJim Jagielski 		case TAG_TITEL:
1285*b1cdbd2cSJim Jagielski         case TAG_REFSTART:
1286*b1cdbd2cSJim Jagielski 			{
1287*b1cdbd2cSJim Jagielski 				if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
1288*b1cdbd2cSJim Jagielski 				{
1289*b1cdbd2cSJim Jagielski 					TokenId aThisToken = aTag.nId;
1290*b1cdbd2cSJim Jagielski 					match( aTag, aTag );
1291*b1cdbd2cSJim Jagielski 					if ( aThisToken != TAG_NAME )
1292*b1cdbd2cSJim Jagielski 					{	// TAG_NAME has no TAG_END
1293*b1cdbd2cSJim Jagielski 						SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1294*b1cdbd2cSJim Jagielski 						Paragraph();
1295*b1cdbd2cSJim Jagielski 						match( aTag, TAG_END );
1296*b1cdbd2cSJim Jagielski 						RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
1297*b1cdbd2cSJim Jagielski 					}
1298*b1cdbd2cSJim Jagielski 				}
1299*b1cdbd2cSJim Jagielski 				else
1300*b1cdbd2cSJim Jagielski 				{
1301*b1cdbd2cSJim Jagielski 					ParseError( 11, "Nested <#HREF>,<#NAME> or <#KEY> not allowed.", aTag );
1302*b1cdbd2cSJim Jagielski 				}
1303*b1cdbd2cSJim Jagielski 			}
1304*b1cdbd2cSJim Jagielski 			break;
1305*b1cdbd2cSJim Jagielski 		default:
1306*b1cdbd2cSJim Jagielski 			ParseError( 12, "<#HREF>,<#NAME> or <#KEY> expected.", aTag );
1307*b1cdbd2cSJim Jagielski 	}
1308*b1cdbd2cSJim Jagielski }
1309*b1cdbd2cSJim Jagielski 
match(const TokenInfo & aCurrentToken,const TokenId & aExpectedToken)1310*b1cdbd2cSJim Jagielski sal_Bool TokenParser::match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken )
1311*b1cdbd2cSJim Jagielski {
1312*b1cdbd2cSJim Jagielski     return match( aCurrentToken, TokenInfo( aExpectedToken, TOK_INVALIDPOS ) );
1313*b1cdbd2cSJim Jagielski }
1314*b1cdbd2cSJim Jagielski 
match(const TokenInfo & aCurrentToken,const TokenInfo & rExpectedToken)1315*b1cdbd2cSJim Jagielski sal_Bool TokenParser::match( const TokenInfo &aCurrentToken, const TokenInfo &rExpectedToken )
1316*b1cdbd2cSJim Jagielski {
1317*b1cdbd2cSJim Jagielski     TokenInfo aExpectedToken( rExpectedToken );
1318*b1cdbd2cSJim Jagielski 	if ( aCurrentToken.nId == aExpectedToken.nId )
1319*b1cdbd2cSJim Jagielski 	{
1320*b1cdbd2cSJim Jagielski         if ( ( aCurrentToken.nId == TAG_COMMONEND
1321*b1cdbd2cSJim Jagielski                && aCurrentToken.GetTagName().Equals( aExpectedToken.GetTagName() ) )
1322*b1cdbd2cSJim Jagielski              || aCurrentToken.nId != TAG_COMMONEND )
1323*b1cdbd2cSJim Jagielski         {
1324*b1cdbd2cSJim Jagielski 		    aTag = aParser.GetNextToken( *pErrorList );
1325*b1cdbd2cSJim Jagielski 		    return sal_True;
1326*b1cdbd2cSJim Jagielski         }
1327*b1cdbd2cSJim Jagielski 	}
1328*b1cdbd2cSJim Jagielski 
1329*b1cdbd2cSJim Jagielski     if ( aExpectedToken.nId == TAG_COMMONEND )
1330*b1cdbd2cSJim Jagielski     {
1331*b1cdbd2cSJim Jagielski         aExpectedToken.aTokenString.Insert( String::CreateFromAscii( "Close tag for " ), 0 );
1332*b1cdbd2cSJim Jagielski     }
1333*b1cdbd2cSJim Jagielski 
1334*b1cdbd2cSJim Jagielski     ByteString sTmp( "Expected Symbol" );
1335*b1cdbd2cSJim Jagielski     if ( aCurrentToken.nId == TAG_NOMORETAGS )
1336*b1cdbd2cSJim Jagielski     {
1337*b1cdbd2cSJim Jagielski 		ParseError( 7, sTmp, aExpectedToken );
1338*b1cdbd2cSJim Jagielski     }
1339*b1cdbd2cSJim Jagielski     else
1340*b1cdbd2cSJim Jagielski     {
1341*b1cdbd2cSJim Jagielski 		sTmp += ": ";
1342*b1cdbd2cSJim Jagielski 		sTmp += ByteString( aParser.GetLexem( aExpectedToken ), RTL_TEXTENCODING_UTF8 );
1343*b1cdbd2cSJim Jagielski 		sTmp += " near ";
1344*b1cdbd2cSJim Jagielski 		ParseError( 7, sTmp, aCurrentToken );
1345*b1cdbd2cSJim Jagielski     }
1346*b1cdbd2cSJim Jagielski 	return sal_False;
1347*b1cdbd2cSJim Jagielski }
1348*b1cdbd2cSJim Jagielski 
ParseError(sal_uInt16 nErrNr,ByteString aErrMsg,const TokenInfo & rTag)1349*b1cdbd2cSJim Jagielski void TokenParser::ParseError( sal_uInt16 nErrNr, ByteString aErrMsg, const TokenInfo &rTag )
1350*b1cdbd2cSJim Jagielski {
1351*b1cdbd2cSJim Jagielski 	pErrorList->AddError( nErrNr, aErrMsg, rTag);
1352*b1cdbd2cSJim Jagielski 
1353*b1cdbd2cSJim Jagielski     // Das Fehlerhafte Tag ueberspringen
1354*b1cdbd2cSJim Jagielski 	aTag = aParser.GetNextToken( *pErrorList );
1355*b1cdbd2cSJim Jagielski }
1356*b1cdbd2cSJim Jagielski 
1357*b1cdbd2cSJim Jagielski 
ParserMessage(sal_uInt16 PnErrorNr,ByteString PaErrorText,const TokenInfo & rTag)1358*b1cdbd2cSJim Jagielski ParserMessage::ParserMessage( sal_uInt16 PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag )
1359*b1cdbd2cSJim Jagielski 		: nErrorNr( PnErrorNr )
1360*b1cdbd2cSJim Jagielski 		, aErrorText( PaErrorText )
1361*b1cdbd2cSJim Jagielski 		, nTagBegin( 0 )
1362*b1cdbd2cSJim Jagielski 		, nTagLength( 0 )
1363*b1cdbd2cSJim Jagielski {
1364*b1cdbd2cSJim Jagielski     String aLexem( SimpleParser::GetLexem( rTag ) );
1365*b1cdbd2cSJim Jagielski     aErrorText.Append(": ");
1366*b1cdbd2cSJim Jagielski 	aErrorText += ByteString( aLexem, RTL_TEXTENCODING_UTF8 );
1367*b1cdbd2cSJim Jagielski     if ( rTag.nId == TAG_NOMORETAGS )
1368*b1cdbd2cSJim Jagielski         aErrorText.Append(" at end of line ");
1369*b1cdbd2cSJim Jagielski     else if ( rTag.nPos != TOK_INVALIDPOS )
1370*b1cdbd2cSJim Jagielski     {
1371*b1cdbd2cSJim Jagielski         aErrorText.Append(" at Position ");
1372*b1cdbd2cSJim Jagielski         aErrorText.Append( ByteString::CreateFromInt32( rTag.nPos ) );
1373*b1cdbd2cSJim Jagielski     }
1374*b1cdbd2cSJim Jagielski     nTagBegin = rTag.nPos;
1375*b1cdbd2cSJim Jagielski 	nTagLength = aLexem.Len();
1376*b1cdbd2cSJim Jagielski }
1377*b1cdbd2cSJim Jagielski 
ParserError(sal_uInt16 ErrorNr,ByteString ErrorText,const TokenInfo & rTag)1378*b1cdbd2cSJim Jagielski ParserError::ParserError( sal_uInt16 ErrorNr, ByteString ErrorText, const TokenInfo &rTag )
1379*b1cdbd2cSJim Jagielski : ParserMessage( ErrorNr, ErrorText, rTag )
1380*b1cdbd2cSJim Jagielski {}
1381*b1cdbd2cSJim Jagielski 
ParserWarning(sal_uInt16 ErrorNr,ByteString ErrorText,const TokenInfo & rTag)1382*b1cdbd2cSJim Jagielski ParserWarning::ParserWarning( sal_uInt16 ErrorNr, ByteString ErrorText, const TokenInfo &rTag )
1383*b1cdbd2cSJim Jagielski : ParserMessage( ErrorNr, ErrorText, rTag )
1384*b1cdbd2cSJim Jagielski {}
1385*b1cdbd2cSJim Jagielski 
IsTagMandatory(TokenInfo const & aToken,TokenId & aMetaTokens)1386*b1cdbd2cSJim Jagielski sal_Bool LingTest::IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens )
1387*b1cdbd2cSJim Jagielski {
1388*b1cdbd2cSJim Jagielski 	TokenId aTokenId = aToken.nId;
1389*b1cdbd2cSJim Jagielski 	TokenId aTokenGroup = TAG_GROUP( aTokenId );
1390*b1cdbd2cSJim Jagielski 	if ( TAG_GROUP_PROGSWITCH == aTokenGroup
1391*b1cdbd2cSJim Jagielski 		|| TAG_REFINSERT == aTokenId
1392*b1cdbd2cSJim Jagielski 		|| TAG_REFSTART == aTokenId
1393*b1cdbd2cSJim Jagielski 		|| TAG_NAME == aTokenId
1394*b1cdbd2cSJim Jagielski 		|| TAG_HREF == aTokenId
1395*b1cdbd2cSJim Jagielski 		|| TAG_AVIS == aTokenId
1396*b1cdbd2cSJim Jagielski 		|| TAG_AHID == aTokenId
1397*b1cdbd2cSJim Jagielski 		|| TAG_GRAPHIC == aTokenId
1398*b1cdbd2cSJim Jagielski 		|| TAG_NEXTVERSION == aTokenId
1399*b1cdbd2cSJim Jagielski         || ( TAG_GROUP_META == aTokenGroup && (aMetaTokens & aTokenId) == aTokenId ) )
1400*b1cdbd2cSJim Jagielski     {
1401*b1cdbd2cSJim Jagielski         if ( TAG_GROUP_META == aTokenGroup )
1402*b1cdbd2cSJim Jagielski             aMetaTokens |= aTokenId;
1403*b1cdbd2cSJim Jagielski         return sal_True;
1404*b1cdbd2cSJim Jagielski     }
1405*b1cdbd2cSJim Jagielski     else if (   TAG_COMMONSTART == aTokenId
1406*b1cdbd2cSJim Jagielski 		     || TAG_COMMONEND == aTokenId )
1407*b1cdbd2cSJim Jagielski     {
1408*b1cdbd2cSJim Jagielski         String aTagName = aToken.GetTagName();
1409*b1cdbd2cSJim Jagielski         return !(aTagName.EqualsIgnoreCaseAscii( "comment" )
1410*b1cdbd2cSJim Jagielski               || aTagName.EqualsIgnoreCaseAscii( "bookmark_value" )
1411*b1cdbd2cSJim Jagielski               || aTagName.EqualsIgnoreCaseAscii( "emph" )
1412*b1cdbd2cSJim Jagielski               || aTagName.EqualsIgnoreCaseAscii( "item" )
1413*b1cdbd2cSJim Jagielski               || aTagName.EqualsIgnoreCaseAscii( "br" ) );
1414*b1cdbd2cSJim Jagielski     }
1415*b1cdbd2cSJim Jagielski     return sal_False;
1416*b1cdbd2cSJim Jagielski }
1417*b1cdbd2cSJim Jagielski 
CheckTags(TokenList & aReference,TokenList & aTestee,sal_Bool bFixTags)1418*b1cdbd2cSJim Jagielski void LingTest::CheckTags( TokenList &aReference, TokenList &aTestee, sal_Bool bFixTags )
1419*b1cdbd2cSJim Jagielski {
1420*b1cdbd2cSJim Jagielski 	sal_uLong i=0,j=0;
1421*b1cdbd2cSJim Jagielski 	// Clean old Warnings
1422*b1cdbd2cSJim Jagielski 	while ( aCompareWarningList.Count() )
1423*b1cdbd2cSJim Jagielski 	{
1424*b1cdbd2cSJim Jagielski 		delete aCompareWarningList.GetCurObject();
1425*b1cdbd2cSJim Jagielski 		aCompareWarningList.Remove();
1426*b1cdbd2cSJim Jagielski 	}
1427*b1cdbd2cSJim Jagielski 
1428*b1cdbd2cSJim Jagielski     /* in xml tags, do not require the following tags
1429*b1cdbd2cSJim Jagielski         comment
1430*b1cdbd2cSJim Jagielski         bookmark_value
1431*b1cdbd2cSJim Jagielski         emph
1432*b1cdbd2cSJim Jagielski         item
1433*b1cdbd2cSJim Jagielski         br
1434*b1cdbd2cSJim Jagielski     */
1435*b1cdbd2cSJim Jagielski 
1436*b1cdbd2cSJim Jagielski     // filter uninteresting Tags
1437*b1cdbd2cSJim Jagielski     TokenId aMetaTokens = 0;
1438*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aReference.Count() ; i++ )
1439*b1cdbd2cSJim Jagielski 	{
1440*b1cdbd2cSJim Jagielski 		if ( !IsTagMandatory( aReference.GetObject( i ), aMetaTokens ) )
1441*b1cdbd2cSJim Jagielski 			aReference.GetObject( i ).SetDone();
1442*b1cdbd2cSJim Jagielski 	}
1443*b1cdbd2cSJim Jagielski 
1444*b1cdbd2cSJim Jagielski     aMetaTokens = 0;
1445*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aTestee.Count() ; i++ )
1446*b1cdbd2cSJim Jagielski 	{
1447*b1cdbd2cSJim Jagielski 		if ( !IsTagMandatory( aTestee.GetObject( i ), aMetaTokens ) )
1448*b1cdbd2cSJim Jagielski 			aTestee.GetObject( i ).SetDone();
1449*b1cdbd2cSJim Jagielski 	}
1450*b1cdbd2cSJim Jagielski 
1451*b1cdbd2cSJim Jagielski     // remove all matching tags
1452*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aReference.Count() ; i++ )
1453*b1cdbd2cSJim Jagielski     {
1454*b1cdbd2cSJim Jagielski         if ( aReference.GetObject( i ).IsDone() )
1455*b1cdbd2cSJim Jagielski             continue;
1456*b1cdbd2cSJim Jagielski 
1457*b1cdbd2cSJim Jagielski     	sal_Bool bTagFound = sal_False;
1458*b1cdbd2cSJim Jagielski     	for ( j=0 ; j < aTestee.Count() && !bTagFound ; j++ )
1459*b1cdbd2cSJim Jagielski         {
1460*b1cdbd2cSJim Jagielski             if ( aTestee.GetObject( j ).IsDone() )
1461*b1cdbd2cSJim Jagielski                 continue;
1462*b1cdbd2cSJim Jagielski 
1463*b1cdbd2cSJim Jagielski 		    if ( aReference.GetObject( i ).MatchesTranslation( aTestee.GetObject( j ), sal_False, aCompareWarningList ) )
1464*b1cdbd2cSJim Jagielski             {
1465*b1cdbd2cSJim Jagielski 			    aReference.GetObject( i ).SetDone();
1466*b1cdbd2cSJim Jagielski 			    aTestee.GetObject( j ).SetDone();
1467*b1cdbd2cSJim Jagielski                 bTagFound = sal_True;
1468*b1cdbd2cSJim Jagielski             }
1469*b1cdbd2cSJim Jagielski         }
1470*b1cdbd2cSJim Jagielski     }
1471*b1cdbd2cSJim Jagielski 
1472*b1cdbd2cSJim Jagielski     sal_Bool bCanFix = sal_True;
1473*b1cdbd2cSJim Jagielski 
1474*b1cdbd2cSJim Jagielski     if ( bFixTags )
1475*b1cdbd2cSJim Jagielski     {
1476*b1cdbd2cSJim Jagielski         // we fix only if its a really simple case
1477*b1cdbd2cSJim Jagielski         sal_uInt16 nTagCount = 0;
1478*b1cdbd2cSJim Jagielski 	    for ( i=0 ; i < aReference.Count() ; i++ )
1479*b1cdbd2cSJim Jagielski             if ( !aReference.GetObject( i ).IsDone() )
1480*b1cdbd2cSJim Jagielski                 nTagCount++;
1481*b1cdbd2cSJim Jagielski         if ( nTagCount > 1 )
1482*b1cdbd2cSJim Jagielski             bCanFix = sal_False;
1483*b1cdbd2cSJim Jagielski 
1484*b1cdbd2cSJim Jagielski         nTagCount = 0;
1485*b1cdbd2cSJim Jagielski 	    for ( i=0 ; i < aTestee.Count() ; i++ )
1486*b1cdbd2cSJim Jagielski             if ( !aTestee.GetObject( i ).IsDone() )
1487*b1cdbd2cSJim Jagielski                 nTagCount++;
1488*b1cdbd2cSJim Jagielski         if ( nTagCount > 1 )
1489*b1cdbd2cSJim Jagielski             bCanFix = sal_False;
1490*b1cdbd2cSJim Jagielski     }
1491*b1cdbd2cSJim Jagielski 
1492*b1cdbd2cSJim Jagielski     // generate errors for tags that have differing attributes
1493*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aReference.Count() ; i++ )
1494*b1cdbd2cSJim Jagielski     {
1495*b1cdbd2cSJim Jagielski         if ( aReference.GetObject( i ).IsDone() )
1496*b1cdbd2cSJim Jagielski             continue;
1497*b1cdbd2cSJim Jagielski 
1498*b1cdbd2cSJim Jagielski     	sal_Bool bTagFound = sal_False;
1499*b1cdbd2cSJim Jagielski     	for ( j=0 ; j < aTestee.Count() && !bTagFound ; j++ )
1500*b1cdbd2cSJim Jagielski         {
1501*b1cdbd2cSJim Jagielski             if ( aTestee.GetObject( j ).IsDone() )
1502*b1cdbd2cSJim Jagielski                 continue;
1503*b1cdbd2cSJim Jagielski 
1504*b1cdbd2cSJim Jagielski 		    if ( aReference.GetObject( i ).MatchesTranslation( aTestee.GetObject( j ), sal_True, aCompareWarningList, bCanFix && bFixTags ) )
1505*b1cdbd2cSJim Jagielski             {
1506*b1cdbd2cSJim Jagielski 			    aReference.GetObject( i ).SetDone();
1507*b1cdbd2cSJim Jagielski 			    aTestee.GetObject( j ).SetDone();
1508*b1cdbd2cSJim Jagielski                 bTagFound = sal_True;
1509*b1cdbd2cSJim Jagielski             }
1510*b1cdbd2cSJim Jagielski         }
1511*b1cdbd2cSJim Jagielski     }
1512*b1cdbd2cSJim Jagielski 
1513*b1cdbd2cSJim Jagielski     // list remaining tags as errors
1514*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aReference.Count() ; i++ )
1515*b1cdbd2cSJim Jagielski     {
1516*b1cdbd2cSJim Jagielski         if ( aReference.GetObject( i ).IsDone() )
1517*b1cdbd2cSJim Jagielski             continue;
1518*b1cdbd2cSJim Jagielski 
1519*b1cdbd2cSJim Jagielski         aCompareWarningList.AddError( 20, "Missing Tag in Translation", aReference.GetObject( i ) );
1520*b1cdbd2cSJim Jagielski     }
1521*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aTestee.Count() ; i++ )
1522*b1cdbd2cSJim Jagielski     {
1523*b1cdbd2cSJim Jagielski         if ( aTestee.GetObject( i ).IsDone() )
1524*b1cdbd2cSJim Jagielski             continue;
1525*b1cdbd2cSJim Jagielski 
1526*b1cdbd2cSJim Jagielski 		aCompareWarningList.AddError( 21, "Extra Tag in Translation", aTestee.GetObject( i ) );
1527*b1cdbd2cSJim Jagielski     }
1528*b1cdbd2cSJim Jagielski 
1529*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aReference.Count() ; i++ )
1530*b1cdbd2cSJim Jagielski         aReference.GetObject( i ).SetDone( sal_False );
1531*b1cdbd2cSJim Jagielski 
1532*b1cdbd2cSJim Jagielski 	for ( i=0 ; i < aTestee.Count() ; i++ )
1533*b1cdbd2cSJim Jagielski         aTestee.GetObject( i ).SetDone( sal_False );
1534*b1cdbd2cSJim Jagielski }
1535*b1cdbd2cSJim Jagielski 
CheckReference(GSILine * aReference)1536*b1cdbd2cSJim Jagielski void LingTest::CheckReference( GSILine *aReference )
1537*b1cdbd2cSJim Jagielski {
1538*b1cdbd2cSJim Jagielski 	aReferenceParser.Parse( aReference->GetUText(), aReference->GetMessageList() );
1539*b1cdbd2cSJim Jagielski }
1540*b1cdbd2cSJim Jagielski 
CheckTestee(GSILine * aTestee,sal_Bool bHasSourceLine,sal_Bool bFixTags)1541*b1cdbd2cSJim Jagielski void LingTest::CheckTestee( GSILine *aTestee, sal_Bool bHasSourceLine, sal_Bool bFixTags )
1542*b1cdbd2cSJim Jagielski {
1543*b1cdbd2cSJim Jagielski     aFixedTestee = aTestee->GetUText();
1544*b1cdbd2cSJim Jagielski 	aTesteeParser.Parse( aFixedTestee, aTestee->GetMessageList() );
1545*b1cdbd2cSJim Jagielski 
1546*b1cdbd2cSJim Jagielski     if ( bHasSourceLine )
1547*b1cdbd2cSJim Jagielski 	    CheckTags( aReferenceParser.GetTokenList(), aTesteeParser.GetTokenList(), bFixTags );
1548*b1cdbd2cSJim Jagielski 
1549*b1cdbd2cSJim Jagielski     if ( bFixTags )
1550*b1cdbd2cSJim Jagielski     {
1551*b1cdbd2cSJim Jagielski         TokenList& aTesteeTokens = aTesteeParser.GetTokenList();
1552*b1cdbd2cSJim Jagielski         sal_Bool bFixesDone = sal_False;
1553*b1cdbd2cSJim Jagielski         // count backwards to allow replacing from right to left
1554*b1cdbd2cSJim Jagielski         int i;
1555*b1cdbd2cSJim Jagielski 	    for ( i=aTesteeTokens.Count()-1 ; i>=0 ; i-- )
1556*b1cdbd2cSJim Jagielski         {
1557*b1cdbd2cSJim Jagielski             if ( aTesteeTokens.GetObject( i ).HasBeenFixed() )
1558*b1cdbd2cSJim Jagielski             {
1559*b1cdbd2cSJim Jagielski                 bFixesDone = sal_True;
1560*b1cdbd2cSJim Jagielski                 aFixedTestee.Replace( aTesteeTokens.GetObject( i ).nPos, aTesteeTokens.GetObject( i ).aTokenString.Len(), aTesteeTokens.GetObject( i ).MakeTag() );
1561*b1cdbd2cSJim Jagielski             }
1562*b1cdbd2cSJim Jagielski         }
1563*b1cdbd2cSJim Jagielski         if ( bFixesDone )
1564*b1cdbd2cSJim Jagielski         {
1565*b1cdbd2cSJim Jagielski             aTestee->SetUText( aFixedTestee );
1566*b1cdbd2cSJim Jagielski             aTestee->SetFixed();
1567*b1cdbd2cSJim Jagielski         }
1568*b1cdbd2cSJim Jagielski     }
1569*b1cdbd2cSJim Jagielski }
1570*b1cdbd2cSJim Jagielski 
1571