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