Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <ctype.h>
31 : : #include <stdlib.h>
32 : : #include <stdio.h>
33 : : #include <limits.h>
34 : : #include <rtl/ustrbuf.hxx>
35 : : #include <vcl/svapp.hxx>
36 : : #include <svtools/htmltokn.h>
37 : : #include <comphelper/string.hxx>
38 : : #include "css1kywd.hxx"
39 : : #include "parcss1.hxx"
40 : :
41 : :
42 : : // Loop-Check: Um Endlos-Schleifen zu vermeiden, wird in jeder
43 : : // Schalife geprueft, ob ein Fortschritt in der Eingabe-Position
44 : : // stattgefunden hat
45 : : #define LOOP_CHECK
46 : :
47 : : #ifdef LOOP_CHECK
48 : :
49 : : #define LOOP_CHECK_DECL \
50 : : xub_StrLen nOldInPos = STRING_MAXLEN;
51 : : #define LOOP_CHECK_RESTART \
52 : : nOldInPos = STRING_MAXLEN;
53 : : #define LOOP_CHECK_CHECK( where ) \
54 : : OSL_ENSURE( nOldInPos!=nInPos || cNextCh==(sal_Unicode)EOF, where ); \
55 : : if( nOldInPos==nInPos && cNextCh!=(sal_Unicode)EOF ) \
56 : : break; \
57 : : else \
58 : : nOldInPos = nInPos;
59 : :
60 : : #else
61 : :
62 : : #define LOOP_CHECK_DECL
63 : : #define LOOP_CHECK_RESTART
64 : : #define LOOP_CHECK_CHECK( where )
65 : :
66 : : #endif
67 : :
68 : :
69 : : const sal_Int32 MAX_LEN = 1024;
70 : :
71 : :
72 : 0 : void CSS1Parser::InitRead( const String& rIn )
73 : : {
74 : 0 : nlLineNr = 0;
75 : 0 : nlLinePos = 0;
76 : :
77 : 0 : bWhiteSpace = sal_True; // Wenn noch nichts gelesen wurde ist das wie WS
78 : 0 : bEOF = sal_False;
79 : 0 : eState = CSS1_PAR_WORKING;
80 : 0 : nValue = 0.;
81 : :
82 : 0 : aIn = rIn;
83 : 0 : nInPos = 0;
84 : 0 : cNextCh = GetNextChar();
85 : 0 : nToken = GetNextToken();
86 : 0 : }
87 : :
88 : 0 : sal_Unicode CSS1Parser::GetNextChar()
89 : : {
90 [ # # ]: 0 : if( nInPos >= aIn.Len() )
91 : : {
92 : 0 : bEOF = sal_True;
93 : 0 : return (sal_Unicode)EOF;
94 : : }
95 : :
96 : 0 : sal_Unicode c = aIn.GetChar( nInPos );
97 : 0 : nInPos++;
98 : :
99 [ # # ]: 0 : if( c == '\n' )
100 : : {
101 : 0 : IncLineNr();
102 : 0 : SetLinePos( 1L );
103 : : }
104 : : else
105 : 0 : IncLinePos();
106 : :
107 : 0 : return c;
108 : : }
109 : :
110 : : // Diese Funktion realisiert den in
111 : : //
112 : : // http://www.w3.orh/pub/WWW/TR/WD-css1.html
113 : : // bzw. http://www.w3.orh/pub/WWW/TR/WD-css1-960220.html
114 : : //
115 : : // beschriebenen Scanner fuer CSS1. Es handelt sich um eine direkte
116 : : // Umsetzung der dort beschriebenen Lex-Grammatik
117 : : //
118 : 0 : CSS1Token CSS1Parser::GetNextToken()
119 : : {
120 : 0 : CSS1Token nRet = CSS1_NULL;
121 : 0 : aToken.Erase();
122 : :
123 [ # # # # ]: 0 : do {
[ # # ]
124 : : // Merken, ob davor White-Space gelesen wurde
125 : 0 : sal_Bool bPrevWhiteSpace = bWhiteSpace;
126 : 0 : bWhiteSpace = sal_False;
127 : :
128 : 0 : sal_Bool bNextCh = sal_True;
129 [ # # # # : 0 : switch( cNextCh )
# # # # #
# # # # #
# # # ]
130 : : {
131 : : case '/': // COMMENT | '/'
132 : : {
133 : 0 : cNextCh = GetNextChar();
134 [ # # ]: 0 : if( '*' == cNextCh )
135 : : {
136 : : // COMMENT
137 : 0 : cNextCh = GetNextChar();
138 : :
139 : 0 : sal_Bool bAsterix = sal_False;
140 [ # # ][ # # ]: 0 : while( !(bAsterix && '/'==cNextCh) && !IsEOF() )
[ # # ][ # # ]
141 : : {
142 : 0 : bAsterix = ('*'==cNextCh);
143 : 0 : cNextCh = GetNextChar();
144 : : }
145 : : }
146 : : else
147 : : {
148 : : // '/'
149 : 0 : bNextCh = sal_False;
150 : 0 : nRet = CSS1_SLASH;
151 : : }
152 : : }
153 : 0 : break;
154 : :
155 : : case '@': // '@import' | '@XXX'
156 : : {
157 : 0 : cNextCh = GetNextChar();
158 [ # # ]: 0 : if (comphelper::string::isalphaAscii(cNextCh))
159 : : {
160 : : // den naechsten Identifer scannen
161 : 0 : ::rtl::OUStringBuffer sTmpBuffer( 32L );
162 [ # # ]: 0 : do {
[ # # # # ]
[ # # ]
163 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
164 : 0 : cNextCh = GetNextChar();
165 [ # # ]: 0 : } while( (comphelper::string::isalnumAscii(cNextCh) ||
166 : 0 : '-' == cNextCh) && !IsEOF() );
167 : :
168 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
169 : :
170 : : // und schauen, ob wir ihn kennen
171 [ # # # ]: 0 : switch( aToken.GetChar(0) )
172 : : {
173 : : case 'i':
174 : : case 'I':
175 [ # # ][ # # ]: 0 : if( aToken.EqualsIgnoreCaseAscii(sCSS1_import) )
176 : 0 : nRet = CSS1_IMPORT_SYM;
177 : 0 : break;
178 : : // /Feature: PrintExt
179 : : case 'p':
180 : : case 'P':
181 [ # # ][ # # ]: 0 : if( aToken.EqualsIgnoreCaseAscii(sCSS1_page) )
182 : 0 : nRet = CSS1_PAGE_SYM;
183 : 0 : break;
184 : : // /Feature: PrintExt
185 : : }
186 : :
187 : : // Fehlerbehandlung: '@ident' und alles bis
188 : : // zu einem Semikolon der dem Ende des folgenden
189 : : // Blocks ignorieren
190 [ # # ]: 0 : if( CSS1_NULL==nRet )
191 : : {
192 [ # # ]: 0 : aToken.Erase();
193 : 0 : sal_uInt16 nBlockLvl = 0;
194 : 0 : sal_Unicode cQuoteCh = 0;
195 : 0 : sal_Bool bDone = sal_False, bEscape = sal_False;
196 [ # # ][ # # ]: 0 : while( !bDone && !IsEOF() )
[ # # ]
197 : : {
198 : 0 : sal_Bool bOldEscape = bEscape;
199 : 0 : bEscape = sal_False;
200 [ # # # # : 0 : switch( cNextCh )
# # ]
201 : : {
202 : : case '{':
203 [ # # ][ # # ]: 0 : if( !cQuoteCh && !bOldEscape )
204 : 0 : nBlockLvl++;
205 : 0 : break;
206 : : case ';':
207 [ # # ][ # # ]: 0 : if( !cQuoteCh && !bOldEscape )
208 : 0 : bDone = nBlockLvl==0;
209 : 0 : break;
210 : : case '}':
211 [ # # ][ # # ]: 0 : if( !cQuoteCh && !bOldEscape )
212 : 0 : bDone = --nBlockLvl==0;
213 : 0 : break;
214 : : case '\"':
215 : : case '\'':
216 [ # # ]: 0 : if( !bOldEscape )
217 : : {
218 [ # # ]: 0 : if( cQuoteCh )
219 : : {
220 [ # # ]: 0 : if( cQuoteCh == cNextCh )
221 : 0 : cQuoteCh = 0;
222 : : }
223 : : else
224 : : {
225 : 0 : cQuoteCh = cNextCh;
226 : : }
227 : : }
228 : 0 : break;
229 : : case '\\':
230 [ # # ]: 0 : if( !bOldEscape )
231 : 0 : bEscape = sal_True;
232 : 0 : break;
233 : : }
234 : 0 : cNextCh = GetNextChar();
235 : : }
236 : : }
237 : :
238 : 0 : bNextCh = sal_False;
239 : : }
240 : : }
241 : 0 : break;
242 : :
243 : : case '!': // '!' 'legal' | '!' 'important' | syntax error
244 : : {
245 : : // White Space ueberlesen
246 : 0 : cNextCh = GetNextChar();
247 [ # # ][ # # ]: 0 : while( ( ' ' == cNextCh ||
[ # # # # ]
[ # # ]
248 : 0 : (cNextCh >= 0x09 && cNextCh <= 0x0d) ) && !IsEOF() )
249 : : {
250 : 0 : bWhiteSpace = sal_True;
251 : 0 : cNextCh = GetNextChar();
252 : : }
253 : :
254 [ # # ][ # # ]: 0 : if( 'i'==cNextCh || 'I'==cNextCh)
255 : : {
256 : : // den naechsten Identifer scannen
257 : 0 : ::rtl::OUStringBuffer sTmpBuffer( 32L );
258 [ # # ]: 0 : do {
[ # # # # ]
[ # # ]
259 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
260 : 0 : cNextCh = GetNextChar();
261 [ # # ]: 0 : } while( (comphelper::string::isalnumAscii(cNextCh) ||
262 : 0 : '-' == cNextCh) && !IsEOF() );
263 : :
264 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
265 : :
266 [ # # ][ # # ]: 0 : if( ('i'==aToken.GetChar(0) || 'I'==aToken.GetChar(0)) &&
[ # # ][ # # ]
267 [ # # ]: 0 : aToken.EqualsIgnoreCaseAscii(sCSS1_important) )
268 : : {
269 : : // '!' 'important'
270 : 0 : nRet = CSS1_IMPORTANT_SYM;
271 : : }
272 : : else
273 : : {
274 : : // Fehlerbehandlung: '!' ignorieren, IDENT nicht
275 : 0 : nRet = CSS1_IDENT;
276 : : }
277 : :
278 : 0 : bWhiteSpace = sal_False;
279 : 0 : bNextCh = sal_False;
280 : : }
281 : : else
282 : : {
283 : : // Fehlerbehandlung: '!' ignorieren
284 : 0 : bNextCh = sal_False;
285 : : }
286 : : }
287 : 0 : break;
288 : :
289 : : case '\"':
290 : : case '\'': // STRING
291 : : {
292 : : // \... geht noch nicht!!!
293 : 0 : sal_Unicode cQuoteChar = cNextCh;
294 : 0 : cNextCh = GetNextChar();
295 : :
296 : 0 : ::rtl::OUStringBuffer sTmpBuffer( MAX_LEN );
297 [ # # ]: 0 : do {
[ # # # # ]
298 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
299 : 0 : cNextCh = GetNextChar();
300 : 0 : } while( cQuoteChar != cNextCh && !IsEOF() );
301 : :
302 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
303 : :
304 : 0 : nRet = CSS1_STRING;
305 : : }
306 : 0 : break;
307 : :
308 : : case '0':
309 : : case '1':
310 : : case '2':
311 : : case '3':
312 : : case '4':
313 : : case '5':
314 : : case '6':
315 : : case '7':
316 : : case '8':
317 : : case '9': // NUMBER | PERCENTAGE | LENGTH
318 : : {
319 : : // die aktuelle Position retten
320 : 0 : xub_StrLen nInPosSave = nInPos;
321 : 0 : sal_Unicode cNextChSave = cNextCh;
322 : 0 : sal_uInt32 nlLineNrSave = nlLineNr;
323 : 0 : sal_uInt32 nlLinePosSave = nlLinePos;
324 : 0 : sal_Bool bEOFSave = bEOF;
325 : :
326 : : // erstmal versuchen eine Hex-Zahl zu scannen
327 : 0 : ::rtl::OUStringBuffer sTmpBuffer( 16 );
328 [ # # ][ # # ]: 0 : do {
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
329 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
330 : 0 : cNextCh = GetNextChar();
331 : 0 : } while( sTmpBuffer.getLength() < 7 &&
332 : : ( ('0'<=cNextCh && '9'>=cNextCh) ||
333 : : ('A'<=cNextCh && 'F'>=cNextCh) ||
334 : : ('a'<=cNextCh && 'f'>=cNextCh) ) &&
335 : 0 : !IsEOF() );
336 : :
337 [ # # ]: 0 : if( sTmpBuffer.getLength()==6 )
338 : : {
339 : : // wir haben eine hexadezimale Farbe gefunden
340 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
341 : 0 : nRet = CSS1_HEXCOLOR;
342 : 0 : bNextCh = sal_False;
343 : :
344 : : break;
345 : : }
346 : :
347 : : // sonst versuchen wir es mit einer Zahl
348 : 0 : nInPos = nInPosSave;
349 : 0 : cNextCh = cNextChSave;
350 : 0 : nlLineNr = nlLineNrSave;
351 : 0 : nlLinePos = nlLinePosSave;
352 : 0 : bEOF = bEOFSave;
353 : :
354 : : // erstmal die Zahl scannen
355 [ # # ]: 0 : sTmpBuffer.setLength( 0L );
356 [ # # ]: 0 : do {
[ # # # # ]
[ # # ][ # # ]
357 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
358 : 0 : cNextCh = GetNextChar();
359 : : } while( (('0'<=cNextCh && '9'>=cNextCh) || '.'==cNextCh) &&
360 : 0 : !IsEOF() );
361 : :
362 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
363 [ # # ]: 0 : nValue = rtl::OUString(aToken).toDouble();
364 : :
365 : : // White Space ueberlesen
366 [ # # ][ # # ]: 0 : while( ( ' ' == cNextCh ||
[ # # # # ]
[ # # ]
367 : 0 : (cNextCh >= 0x09 && cNextCh <= 0x0d) ) && !IsEOF() )
368 : : {
369 : 0 : bWhiteSpace = sal_True;
370 : 0 : cNextCh = GetNextChar();
371 : : }
372 : :
373 : : // und nun Schauen, ob es eine Einheit gibt
374 [ # # # ]: 0 : switch( cNextCh )
375 : : {
376 : : case '%': // PERCENTAGE
377 : 0 : bWhiteSpace = sal_False;
378 : 0 : nRet = CSS1_PERCENTAGE;
379 : 0 : break;
380 : :
381 : : case 'c':
382 : : case 'C': // LENGTH cm | LENGTH IDENT
383 : : case 'e':
384 : : case 'E': // LENGTH (em | ex) | LENGTH IDENT
385 : : case 'i':
386 : : case 'I': // LENGTH inch | LENGTH IDENT
387 : : case 'p':
388 : : case 'P': // LENGTH (pt | px | pc) | LENGTH IDENT
389 : : case 'm':
390 : : case 'M': // LENGTH mm | LENGTH IDENT
391 : : {
392 : : // die aktuelle Position retten
393 : 0 : xub_StrLen nInPosOld = nInPos;
394 : 0 : sal_Unicode cNextChOld = cNextCh;
395 : 0 : sal_uLong nlLineNrOld = nlLineNr;
396 : 0 : sal_uLong nlLinePosOld = nlLinePos;
397 : 0 : sal_Bool bEOFOld = bEOF;
398 : :
399 : : // den naechsten Identifer scannen
400 [ # # ]: 0 : String aIdent;
401 : 0 : ::rtl::OUStringBuffer sTmpBuffer2( 64L );
402 [ # # ]: 0 : do {
[ # # # # ]
[ # # ]
403 [ # # ]: 0 : sTmpBuffer2.append( cNextCh );
404 : 0 : cNextCh = GetNextChar();
405 [ # # ]: 0 : } while( (comphelper::string::isalnumAscii(cNextCh) ||
406 : 0 : '-' == cNextCh) && !IsEOF() );
407 : :
408 [ # # ][ # # ]: 0 : aIdent += String(sTmpBuffer2.makeStringAndClear());
[ # # ][ # # ]
409 : :
410 : : // Ist es eine Einheit?
411 : 0 : const sal_Char *pCmp1 = 0, *pCmp2 = 0, *pCmp3 = 0;
412 : 0 : double nScale1 = 1., nScale2 = 1.;
413 : 0 : CSS1Token nToken1 = CSS1_LENGTH,
414 : 0 : nToken2 = CSS1_LENGTH,
415 : 0 : nToken3 = CSS1_LENGTH;
416 [ # # # # : 0 : switch( aIdent.GetChar(0) )
# # ]
417 : : {
418 : : case 'c':
419 : : case 'C':
420 : 0 : pCmp1 = sCSS1_UNIT_cm;
421 : 0 : nScale1 = (72.*20.)/2.54; // twip
422 : 0 : break;
423 : : case 'e':
424 : : case 'E':
425 : 0 : pCmp1 = sCSS1_UNIT_em;
426 : 0 : nToken1 = CSS1_EMS;
427 : :
428 : 0 : pCmp2 = sCSS1_UNIT_ex;
429 : 0 : nToken2 = CSS1_EMX;
430 : 0 : break;
431 : : case 'i':
432 : : case 'I':
433 : 0 : pCmp1 = sCSS1_UNIT_inch;
434 : 0 : nScale1 = 72.*20.; // twip
435 : 0 : break;
436 : : case 'm':
437 : : case 'M':
438 : 0 : pCmp1 = sCSS1_UNIT_mm;
439 : 0 : nScale1 = (72.*20.)/25.4; // twip
440 : 0 : break;
441 : : case 'p':
442 : : case 'P':
443 : 0 : pCmp1 = sCSS1_UNIT_pt;
444 : 0 : nScale1 = 20.; // twip
445 : :
446 : 0 : pCmp2 = sCSS1_UNIT_pc;
447 : 0 : nScale2 = 12.*20.; // twip
448 : :
449 : 0 : pCmp3 = sCSS1_UNIT_px;
450 : 0 : nToken3 = CSS1_PIXLENGTH;
451 : 0 : break;
452 : : }
453 : :
454 : 0 : double nScale = 0.0;
455 : : OSL_ENSURE( pCmp1, "Wo kommt das erste Zeichen her?" );
456 [ # # ][ # # ]: 0 : if( aIdent.EqualsIgnoreCaseAscii(pCmp1) )
457 : : {
458 : 0 : nScale = nScale1;
459 : 0 : nRet = nToken1;
460 : : }
461 [ # # ][ # # ]: 0 : else if( pCmp2 &&
[ # # ]
462 [ # # ]: 0 : aIdent.EqualsIgnoreCaseAscii(pCmp2) )
463 : : {
464 : 0 : nScale = nScale2;
465 : 0 : nRet = nToken2;
466 : : }
467 [ # # ][ # # ]: 0 : else if( pCmp3 &&
[ # # ]
468 [ # # ]: 0 : aIdent.EqualsIgnoreCaseAscii(pCmp3) )
469 : : {
470 : 0 : nScale = 1.; // nScale3
471 : 0 : nRet = nToken3;
472 : : }
473 : : else
474 : : {
475 : 0 : nRet = CSS1_NUMBER;
476 : : }
477 : :
478 [ # # ][ # # ]: 0 : if( CSS1_LENGTH==nRet && nScale!=1.0 )
479 : 0 : nValue *= nScale;
480 : :
481 [ # # ]: 0 : if( nRet == CSS1_NUMBER )
482 : : {
483 : 0 : nInPos = nInPosOld;
484 : 0 : cNextCh = cNextChOld;
485 : 0 : nlLineNr = nlLineNrOld;
486 : 0 : nlLinePos = nlLinePosOld;
487 : 0 : bEOF = bEOFOld;
488 : : }
489 : : else
490 : : {
491 : 0 : bWhiteSpace = sal_False;
492 : : }
493 [ # # ]: 0 : bNextCh = sal_False;
494 : : }
495 : 0 : break;
496 : : default: // NUMBER IDENT
497 : 0 : bNextCh = sal_False;
498 : 0 : nRet = CSS1_NUMBER;
499 : 0 : break;
500 [ # # ]: 0 : }
501 : : }
502 : 0 : break;
503 : :
504 : : case ':': // ':'
505 : : // link/visited/active abfangen !!!
506 : 0 : nRet = CSS1_COLON;
507 : 0 : break;
508 : :
509 : : case '.': // DOT_W_WS | DOT_WO_WS
510 [ # # ]: 0 : nRet = bPrevWhiteSpace ? CSS1_DOT_W_WS : CSS1_DOT_WO_WS;
511 : 0 : break;
512 : :
513 : : case '+': // '+'
514 : 0 : nRet = CSS1_PLUS;
515 : 0 : break;
516 : :
517 : : case '-': // '-'
518 : 0 : nRet = CSS1_MINUS;
519 : 0 : break;
520 : :
521 : : case '{': // '{'
522 : 0 : nRet = CSS1_OBRACE;
523 : 0 : break;
524 : :
525 : : case '}': // '}'
526 : 0 : nRet = CSS1_CBRACE;
527 : 0 : break;
528 : :
529 : : case ';': // ';'
530 : 0 : nRet = CSS1_SEMICOLON;
531 : 0 : break;
532 : :
533 : : case ',': // ','
534 : 0 : nRet = CSS1_COMMA;
535 : 0 : break;
536 : :
537 : : case '#': // '#'
538 : 0 : cNextCh = GetNextChar();
539 [ # # ][ # # ]: 0 : if( ('0'<=cNextCh && '9'>=cNextCh) ||
[ # # ][ # # ]
[ # # ][ # # ]
540 : : ('a'<=cNextCh && 'f'>=cNextCh) ||
541 : : ('A'<=cNextCh && 'F'>=cNextCh) )
542 : : {
543 : : // die aktuelle Position retten
544 : 0 : xub_StrLen nInPosSave = nInPos;
545 : 0 : sal_Unicode cNextChSave = cNextCh;
546 : 0 : sal_uLong nlLineNrSave = nlLineNr;
547 : 0 : sal_uLong nlLinePosSave = nlLinePos;
548 : 0 : sal_Bool bEOFSave = bEOF;
549 : :
550 : : // erstmal versuchen eine Hex-Zahl zu scannen
551 : 0 : ::rtl::OUStringBuffer sTmpBuffer( 6L );
552 [ # # ][ # # ]: 0 : do {
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
553 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
554 : 0 : cNextCh = GetNextChar();
555 : 0 : } while( sTmpBuffer.getLength() < 7 &&
556 : : ( ('0'<=cNextCh && '9'>=cNextCh) ||
557 : : ('A'<=cNextCh && 'F'>=cNextCh) ||
558 : : ('a'<=cNextCh && 'f'>=cNextCh) ) &&
559 : 0 : !IsEOF() );
560 : :
561 [ # # ][ # # ]: 0 : if( sTmpBuffer.getLength()==6 || sTmpBuffer.getLength()==3 )
[ # # ]
562 : : {
563 : : // wir haben eine hexadezimale Farbe gefunden
564 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
565 : 0 : nRet = CSS1_HEXCOLOR;
566 : 0 : bNextCh = sal_False;
567 : :
568 : : break;
569 : : }
570 : :
571 : : // sonst versuchen wir es mit einer Zahl
572 : 0 : nInPos = nInPosSave;
573 : 0 : cNextCh = cNextChSave;
574 : 0 : nlLineNr = nlLineNrSave;
575 : 0 : nlLinePos = nlLinePosSave;
576 [ # # ]: 0 : bEOF = bEOFSave;
577 : : }
578 : :
579 : 0 : nRet = CSS1_HASH;
580 : 0 : bNextCh = sal_False;
581 : 0 : break;
582 : :
583 : : case ' ':
584 : : case '\t':
585 : : case '\r':
586 : : case '\n': // White-Space
587 : 0 : bWhiteSpace = sal_True;
588 : 0 : break;
589 : :
590 : : case (sal_Unicode)EOF:
591 [ # # ]: 0 : if( IsEOF() )
592 : : {
593 : 0 : eState = CSS1_PAR_ACCEPTED;
594 : 0 : bNextCh = sal_False;
595 : 0 : break;
596 : : }
597 : : // kein break;
598 : :
599 : : default: // IDENT | syntax error
600 [ # # ]: 0 : if (comphelper::string::isalphaAscii(cNextCh))
601 : : {
602 : : // IDENT
603 : :
604 : 0 : sal_Bool bHexColor = sal_True;
605 : :
606 : : // den naechsten Identifer scannen
607 : 0 : ::rtl::OUStringBuffer sTmpBuffer( 64L );
608 [ # # ]: 0 : do {
[ # # # # ]
[ # # ]
609 [ # # ]: 0 : sTmpBuffer.append( cNextCh );
610 [ # # ]: 0 : if( bHexColor )
611 : : {
612 : 0 : bHexColor = sTmpBuffer.getLength()<7 &&
613 : : ( ('0'<=cNextCh && '9'>=cNextCh) ||
614 : : ('A'<=cNextCh && 'F'>=cNextCh) ||
615 [ # # ][ # # ]: 0 : ('a'<=cNextCh && 'f'>=cNextCh) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
616 : : }
617 : 0 : cNextCh = GetNextChar();
618 [ # # ]: 0 : } while( (comphelper::string::isalnumAscii(cNextCh) ||
619 : 0 : '-' == cNextCh) && !IsEOF() );
620 : :
621 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
622 : :
623 [ # # ][ # # ]: 0 : if( bHexColor && sTmpBuffer.getLength()==6 )
[ # # ]
624 : : {
625 : 0 : bNextCh = sal_False;
626 : 0 : nRet = CSS1_HEXCOLOR;
627 : :
628 : : break;
629 : : }
630 [ # # # # : 0 : if( '('==cNextCh &&
# # ][ # #
# # # # ]
[ # # ][ # # ]
631 : 0 : ( (('u'==aToken.GetChar(0) || 'U'==aToken.GetChar(0)) &&
632 [ # # ]: 0 : aToken.EqualsIgnoreCaseAscii(sCSS1_url)) ||
633 : 0 : (('r'==aToken.GetChar(0) || 'R'==aToken.GetChar(0)) &&
634 [ # # ]: 0 : aToken.EqualsIgnoreCaseAscii(sCSS1_rgb)) ) )
635 : : {
636 : 0 : sal_uInt16 nNestCnt = 0;
637 : 0 : ::rtl::OUStringBuffer sTmpBuffer2( 64L );
638 [ # # # # ]: 0 : do {
[ # # ][ # # ]
639 [ # # ]: 0 : sTmpBuffer2.append( cNextCh );
640 [ # # # ]: 0 : switch( cNextCh )
641 : : {
642 : 0 : case '(': nNestCnt++; break;
643 : 0 : case ')': nNestCnt--; break;
644 : : }
645 : 0 : cNextCh = GetNextChar();
646 : 0 : } while( (nNestCnt>1 || ')'!=cNextCh) && !IsEOF() );
647 [ # # ]: 0 : sTmpBuffer2.append( cNextCh );
648 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer2.makeStringAndClear());
[ # # ][ # # ]
649 : 0 : bNextCh = sal_True;
650 : 0 : nRet = 'u'==aToken.GetChar(0) || 'U'==aToken.GetChar(0)
651 : : ? CSS1_URL
652 [ # # # # ]: 0 : : CSS1_RGB;
653 : : }
654 : : else
655 : : {
656 : 0 : bNextCh = sal_False;
657 : 0 : nRet = CSS1_IDENT;
658 [ # # ]: 0 : }
659 : : }
660 : : // Fehlerbehandlung: Zeichen ignorieren
661 : 0 : break;
662 : : }
663 [ # # ]: 0 : if( bNextCh )
664 : 0 : cNextCh = GetNextChar();
665 : :
666 : 0 : } while( CSS1_NULL==nRet && IsParserWorking() );
667 : :
668 : 0 : return nRet;
669 : : }
670 : :
671 : :
672 : : // Dies folegenden Funktionen realisieren den in
673 : : //
674 : : // http://www.w3.orh/pub/WWW/TR/WD-css1.html
675 : : // bzw. http://www.w3.orh/pub/WWW/TR/WD-css1-960220.html
676 : : //
677 : : // beschriebenen Parser fuer CSS1. Es handelt sich um eine direkte
678 : : // Umsetzung der dort beschriebenen Grammatik
679 : :
680 : : // stylesheet
681 : : // : import* rule*
682 : : //
683 : : // import
684 : : // : IMPORT_SYM url
685 : : //
686 : : // url
687 : : // : STRING
688 : : //
689 : 0 : void CSS1Parser::ParseStyleSheet()
690 : : {
691 : 0 : LOOP_CHECK_DECL
692 : :
693 : : // import*
694 : 0 : sal_Bool bDone = sal_False;
695 [ # # ][ # # ]: 0 : while( !bDone && IsParserWorking() )
[ # # ]
696 : : {
697 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseStyleSheet()/import *" )
698 : :
699 [ # # # ]: 0 : switch( nToken )
700 : : {
701 : : case CSS1_IMPORT_SYM:
702 : : // IMPORT_SYM url
703 : : // url ueberspringen wir ungeprueft
704 : 0 : nToken = GetNextToken();
705 : 0 : break;
706 : : case CSS1_IDENT: // Look-Aheads
707 : : case CSS1_DOT_W_WS:
708 : : case CSS1_HASH:
709 : : // /Feature: PrintExt
710 : : case CSS1_PAGE_SYM:
711 : : // /Feature: PrintExt
712 : : // rule
713 : 0 : bDone = sal_True;
714 : 0 : break;
715 : : default:
716 : : // Fehlerbehandlung: ueberlesen
717 : 0 : break;
718 : : }
719 : :
720 [ # # ]: 0 : if( !bDone )
721 : 0 : nToken = GetNextToken();
722 : : }
723 : :
724 : 0 : LOOP_CHECK_RESTART
725 : :
726 : : // rule *
727 [ # # ]: 0 : while( IsParserWorking() )
728 : : {
729 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseStyleSheet()/rule *" )
730 : :
731 [ # # ]: 0 : switch( nToken )
732 : : {
733 : : case CSS1_IDENT: // Look-Aheads
734 : : case CSS1_DOT_W_WS:
735 : : case CSS1_HASH:
736 : : // /Feature: PrintExt
737 : : case CSS1_PAGE_SYM:
738 : : // /Feature: PrintExt
739 : : // rule
740 : 0 : ParseRule();
741 : 0 : break;
742 : : default:
743 : : // Fehlerbehandlung: ueberlesen
744 : 0 : nToken = GetNextToken();
745 : 0 : break;
746 : : }
747 : : }
748 : 0 : }
749 : :
750 : : // rule
751 : : // : selector [ ',' selector ]*
752 : : // '{' declaration [ ';' declaration ]* '}'
753 : : //
754 : 0 : void CSS1Parser::ParseRule()
755 : : {
756 : : // selector
757 [ # # ]: 0 : CSS1Selector *pSelector = ParseSelector();
758 [ # # ]: 0 : if( !pSelector )
759 : : return;
760 : :
761 : : // Selektor verarbeiten
762 [ # # ][ # # ]: 0 : if( SelectorParsed( pSelector, sal_True ) )
763 [ # # ][ # # ]: 0 : delete pSelector;
764 : :
765 : 0 : LOOP_CHECK_DECL
766 : :
767 : : // [ ',' selector ]*
768 [ # # ][ # # ]: 0 : while( CSS1_COMMA==nToken && IsParserWorking() )
[ # # ]
769 : : {
770 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseRule()/selector *" )
771 : :
772 : : // ',' ueberelesen
773 [ # # ]: 0 : nToken = GetNextToken();
774 : :
775 : : // selector
776 [ # # ]: 0 : pSelector = ParseSelector();
777 [ # # ]: 0 : if( !pSelector )
778 : : return;
779 : :
780 : : // Selektor verarbeiten
781 [ # # ][ # # ]: 0 : if( SelectorParsed( pSelector, sal_False ) )
782 [ # # ][ # # ]: 0 : delete pSelector;
783 : : }
784 : :
785 : : // '{'
786 [ # # ]: 0 : if( CSS1_OBRACE != nToken )
787 : : return;
788 [ # # ]: 0 : nToken = GetNextToken();
789 : :
790 : : // declaration
791 [ # # ]: 0 : String aProperty;
792 [ # # ]: 0 : CSS1Expression *pExpr = ParseDeclaration( aProperty );
793 [ # # ]: 0 : if( !pExpr )
794 : : return;
795 : :
796 : : // expression verarbeiten
797 [ # # ][ # # ]: 0 : if( DeclarationParsed( aProperty, pExpr ) )
798 [ # # ][ # # ]: 0 : delete pExpr;
799 : :
800 : 0 : LOOP_CHECK_RESTART
801 : :
802 : : // [ ';' declaration ]*
803 [ # # ][ # # ]: 0 : while( CSS1_SEMICOLON==nToken && IsParserWorking() )
[ # # ]
804 : : {
805 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseRule()/declaration *" )
806 : :
807 : : // ';'
808 [ # # ]: 0 : nToken = GetNextToken();
809 : :
810 : : // declaration
811 [ # # ]: 0 : if( CSS1_IDENT == nToken )
812 : : {
813 [ # # ]: 0 : CSS1Expression *pExp = ParseDeclaration( aProperty );
814 [ # # ]: 0 : if( pExp )
815 : : {
816 : : // expression verarbeiten
817 [ # # ][ # # ]: 0 : if( DeclarationParsed( aProperty, pExp ) )
818 [ # # ][ # # ]: 0 : delete pExp;
819 : : }
820 : : }
821 : : }
822 : :
823 : : // '}'
824 [ # # ]: 0 : if( CSS1_CBRACE == nToken )
825 [ # # ][ # # ]: 0 : nToken = GetNextToken();
[ # # ]
826 : : }
827 : :
828 : : // selector
829 : : // : simple_selector+ [ ':' pseudo_element ]?
830 : : //
831 : : // simple_selector
832 : : // : element_name [ DOT_WO_WS class ]?
833 : : // | DOT_W_WS class
834 : : // | id_selector
835 : : //
836 : : // element_name
837 : : // : IDENT
838 : : //
839 : : // class
840 : : // : IDENT
841 : : //
842 : : // id_selector
843 : : // : '#' IDENT
844 : : //
845 : : // pseude_element
846 : : // : IDENT
847 : : //
848 : 0 : CSS1Selector *CSS1Parser::ParseSelector()
849 : : {
850 : 0 : CSS1Selector *pRoot = 0, *pLast = 0;
851 : :
852 : 0 : sal_Bool bDone = sal_False;
853 : 0 : CSS1Selector *pNew = 0;
854 : :
855 : 0 : LOOP_CHECK_DECL
856 : :
857 : : // simple_selector+
858 [ # # ][ # # ]: 0 : while( !bDone && IsParserWorking() )
[ # # ]
859 : : {
860 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseSelector()" )
861 : :
862 : 0 : sal_Bool bNextToken = sal_True;
863 : :
864 [ # # # # : 0 : switch( nToken )
# ]
865 : : {
866 : : case CSS1_IDENT:
867 : : {
868 : : // element_name [ DOT_WO_WS class ]?
869 : :
870 : : // element_name
871 [ # # ]: 0 : String aElement = aToken;
872 : 0 : CSS1SelectorType eType = CSS1_SELTYPE_ELEMENT;
873 [ # # ]: 0 : nToken = GetNextToken();
874 : :
875 [ # # ]: 0 : if( CSS1_DOT_WO_WS == nToken )
876 : : {
877 : : // DOT_WO_WS
878 [ # # ]: 0 : nToken = GetNextToken();
879 : :
880 : : // class
881 [ # # ]: 0 : if( CSS1_IDENT == nToken )
882 : : {
883 [ # # ][ # # ]: 0 : (aElement += '.') += aToken;
884 : 0 : eType = CSS1_SELTYPE_ELEM_CLASS;
885 : : }
886 : : else
887 : : {
888 : : // class fehlt
889 : 0 : return pRoot;
890 : : }
891 : : }
892 : : else
893 : : {
894 : : // das war jetzt ein Look-Ahead
895 : 0 : bNextToken = sal_False;
896 : : }
897 [ # # ][ # # ]: 0 : pNew = new CSS1Selector( eType, aElement );
[ # # ][ # # ]
898 : : }
899 : 0 : break;
900 : : case CSS1_DOT_W_WS:
901 : : // DOT_W_WS class
902 : :
903 : : // DOT_W_WS
904 : 0 : nToken = GetNextToken();
905 : :
906 [ # # ]: 0 : if( CSS1_IDENT==nToken )
907 : : {
908 : : // class
909 [ # # ]: 0 : pNew = new CSS1Selector( CSS1_SELTYPE_CLASS, aToken );
910 : : }
911 : : else
912 : : {
913 : : // class fehlt
914 : 0 : return pRoot;
915 : : }
916 : 0 : break;
917 : : case CSS1_HASH:
918 : : // '#' id_selector
919 : :
920 : : // '#'
921 : 0 : nToken = GetNextToken();
922 : :
923 [ # # ]: 0 : if( CSS1_IDENT==nToken )
924 : : {
925 : : // id_selector
926 [ # # ]: 0 : pNew = new CSS1Selector( CSS1_SELTYPE_ID, aToken );
927 : : }
928 : : else
929 : : {
930 : : // id_selector fehlt
931 : 0 : return pRoot;
932 : : }
933 : 0 : break;
934 : :
935 : : // /Feature: PrintExt
936 : : case CSS1_PAGE_SYM:
937 : : {
938 : : // @page
939 [ # # ]: 0 : pNew = new CSS1Selector( CSS1_SELTYPE_PAGE, aToken );
940 : : }
941 : 0 : break;
942 : : // /Feature: PrintExt
943 : :
944 : : default:
945 : : // wir wissen nicht was kommt, also aufhoehren
946 : 0 : bDone = sal_True;
947 : 0 : break;
948 : : }
949 : :
950 : : // falls ein Selektor angelegt wurd, ihn speichern
951 [ # # ]: 0 : if( pNew )
952 : : {
953 : : OSL_ENSURE( (pRoot!=0) == (pLast!=0),
954 : : "Root-Selektor, aber kein Last" );
955 [ # # ]: 0 : if( pLast )
956 : 0 : pLast->SetNext( pNew );
957 : : else
958 : 0 : pRoot = pNew;
959 : :
960 : 0 : pLast = pNew;
961 : 0 : pNew = 0;
962 : : }
963 : :
964 [ # # ][ # # ]: 0 : if( bNextToken && !bDone )
965 : 0 : nToken = GetNextToken();
966 : : }
967 : :
968 [ # # ]: 0 : if( !pRoot )
969 : : {
970 : : // simple_selector fehlt
971 : 0 : return pRoot;
972 : : }
973 : :
974 : : // [ ':' pseudo_element ]?
975 [ # # ][ # # ]: 0 : if( CSS1_COLON==nToken && IsParserWorking() )
[ # # ]
976 : : {
977 : : // ':' pseudo element
978 : 0 : nToken = GetNextToken();
979 [ # # ]: 0 : if( CSS1_IDENT==nToken )
980 : : {
981 [ # # ]: 0 : pLast->SetNext( new CSS1Selector(CSS1_SELTYPE_PSEUDO,aToken) );
982 : 0 : nToken = GetNextToken();
983 : : }
984 : : else
985 : : {
986 : : // pseudo_element fehlt
987 : 0 : return pRoot;
988 : : }
989 : : }
990 : :
991 : 0 : return pRoot;
992 : : }
993 : :
994 : : // declaration
995 : : // : property ':' expr prio?
996 : : // | /* empty */
997 : : //
998 : : // expression
999 : : // : term [ operator term ]*
1000 : : //
1001 : : // term
1002 : : // : unary_operator?
1003 : : // [ NUMBER | STRING | PERCENTAGE | LENGTH | EMS | EXS | IDENT |
1004 : : // HEXCOLOR | URL | RGB ]
1005 : : //
1006 : : // operator
1007 : : // : '/' | ',' | /* empty */
1008 : : //
1009 : : // unary_operator
1010 : : // : '-' | '+'
1011 : : //
1012 : : // property
1013 : : // : ident
1014 : : //
1015 : : // das Vorzeichen wird nur fuer numerische Werte (ausser PERCENTAGE)
1016 : : // beruecksichtigt und wird auf nValue angewendet!
1017 : 0 : CSS1Expression *CSS1Parser::ParseDeclaration( String& rProperty )
1018 : : {
1019 : 0 : CSS1Expression *pRoot = 0, *pLast = 0;
1020 : :
1021 : : // property
1022 [ # # ]: 0 : if( CSS1_IDENT != nToken )
1023 : : {
1024 : : // property fehlt
1025 : 0 : return pRoot;
1026 : : }
1027 : 0 : rProperty = aToken;
1028 : :
1029 : 0 : nToken = GetNextToken();
1030 : :
1031 : :
1032 : : // ':'
1033 [ # # ]: 0 : if( CSS1_COLON != nToken )
1034 : : {
1035 : : // ':' fehlt
1036 : 0 : return pRoot;
1037 : : }
1038 : 0 : nToken = GetNextToken();
1039 : :
1040 : : // term [operator term]*
1041 : : // hier sind wir sehr lax, was die Syntax angeht, sollte aber kein
1042 : : // Problem sein
1043 : 0 : sal_Bool bDone = sal_False;
1044 : 0 : sal_Unicode cSign = 0, cOp = 0;
1045 : 0 : CSS1Expression *pNew = 0;
1046 : :
1047 : 0 : LOOP_CHECK_DECL
1048 : :
1049 [ # # ][ # # ]: 0 : while( !bDone && IsParserWorking() )
[ # # ]
1050 : : {
1051 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseDeclaration()" )
1052 : :
1053 [ # # # # : 0 : switch( nToken )
# # # ]
1054 : : {
1055 : : case CSS1_MINUS:
1056 : 0 : cSign = '-';
1057 : 0 : break;
1058 : :
1059 : : case CSS1_PLUS:
1060 : 0 : cSign = '+';
1061 : 0 : break;
1062 : :
1063 : : case CSS1_NUMBER:
1064 : : case CSS1_LENGTH:
1065 : : case CSS1_PIXLENGTH:
1066 : : case CSS1_EMS:
1067 : : case CSS1_EMX:
1068 [ # # ]: 0 : if( '-'==cSign )
1069 : 0 : nValue = -nValue;
1070 : : case CSS1_STRING:
1071 : : case CSS1_PERCENTAGE:
1072 : : case CSS1_IDENT:
1073 : : case CSS1_URL:
1074 : : case CSS1_RGB:
1075 : : case CSS1_HEXCOLOR:
1076 [ # # ]: 0 : pNew = new CSS1Expression( nToken, aToken, nValue, cOp );
1077 : 0 : nValue = 0; // sonst landet das auch im naechsten Ident
1078 : 0 : cSign = 0;
1079 : 0 : cOp = 0;
1080 : 0 : break;
1081 : :
1082 : : case CSS1_SLASH:
1083 : 0 : cOp = '/';
1084 : 0 : cSign = 0;
1085 : 0 : break;
1086 : :
1087 : : case CSS1_COMMA:
1088 : 0 : cOp = ',';
1089 : 0 : cSign = 0;
1090 : 0 : break;
1091 : :
1092 : : default:
1093 : 0 : bDone = sal_True;
1094 : 0 : break;
1095 : : }
1096 : :
1097 : : // falls ein Expression angelegt wurde, diesen speichern
1098 [ # # ]: 0 : if( pNew )
1099 : : {
1100 : : OSL_ENSURE( (pRoot!=0) == (pLast!=0),
1101 : : "Root-Selektor, aber kein Last" );
1102 [ # # ]: 0 : if( pLast )
1103 : 0 : pLast->SetNext( pNew );
1104 : : else
1105 : 0 : pRoot = pNew;
1106 : :
1107 : 0 : pLast = pNew;
1108 : 0 : pNew = 0;
1109 : : }
1110 : :
1111 [ # # ]: 0 : if( !bDone )
1112 : 0 : nToken = GetNextToken();
1113 : : }
1114 : :
1115 [ # # ]: 0 : if( !pRoot )
1116 : : {
1117 : : // term fehlt
1118 : 0 : return pRoot;
1119 : : }
1120 : :
1121 : : // prio?
1122 [ # # ]: 0 : if( CSS1_IMPORTANT_SYM==nToken )
1123 : : {
1124 : : // IMPORTANT_SYM
1125 : 0 : nToken = GetNextToken();
1126 : : }
1127 : :
1128 : 0 : return pRoot;
1129 : : }
1130 : :
1131 : :
1132 : 2 : CSS1Parser::CSS1Parser()
1133 : : : nValue(0)
1134 : : , eState(CSS1_PAR_ACCEPTED)
1135 [ + - ]: 2 : , nToken(CSS1_NULL)
1136 : : {
1137 : 2 : }
1138 : :
1139 [ + - ]: 2 : CSS1Parser::~CSS1Parser()
1140 : : {
1141 [ - + ]: 2 : }
1142 : :
1143 : :
1144 : 0 : sal_Bool CSS1Parser::ParseStyleSheet( const String& rIn )
1145 : : {
1146 [ # # ]: 0 : String aTmp( rIn );
1147 : :
1148 : : sal_Unicode c;
1149 [ # # ][ # # ]: 0 : while( aTmp.Len() &&
[ # # ][ # # ]
[ # # ][ # # ]
1150 : : ( ' '==(c=aTmp.GetChar(0)) || '\t'==c || '\r'==c || '\n'==c ) )
1151 [ # # ]: 0 : aTmp.Erase( 0, 1 );
1152 : :
1153 [ # # ][ # # ]: 0 : while( aTmp.Len() && ( ' '==(c=aTmp.GetChar( aTmp.Len()-1))
[ # # ][ # # ]
[ # # ][ # # ]
1154 : : || '\t'==c || '\r'==c || '\n'==c ) )
1155 [ # # ]: 0 : aTmp.Erase( aTmp.Len()-1 );
1156 : :
1157 : : // SGML-Kommentare entfernen
1158 [ # # ][ # # ]: 0 : if( aTmp.Len() >= 4 &&
[ # # ]
1159 [ # # ]: 0 : aTmp.CompareToAscii("<!--",4) == COMPARE_EQUAL )
1160 [ # # ]: 0 : aTmp.Erase( 0, 4 );
1161 : :
1162 [ # # ][ # # ]: 0 : if( aTmp.Len() >=3 &&
[ # # ]
1163 [ # # ][ # # ]: 0 : aTmp.Copy(aTmp.Len()-3).CompareToAscii("-->") == COMPARE_EQUAL )
[ # # ][ # # ]
[ # # ]
1164 [ # # ]: 0 : aTmp.Erase( aTmp.Len()-3 );
1165 : :
1166 [ # # ]: 0 : if( !aTmp.Len() )
1167 : 0 : return sal_True;
1168 : :
1169 [ # # ]: 0 : InitRead( aTmp );
1170 : :
1171 [ # # ]: 0 : ParseStyleSheet();
1172 : :
1173 [ # # ]: 0 : return sal_True;
1174 : : }
1175 : :
1176 : :
1177 : 0 : sal_Bool CSS1Parser::ParseStyleOption( const String& rIn )
1178 : : {
1179 [ # # ]: 0 : if( !rIn.Len() )
1180 : 0 : return sal_True;
1181 : :
1182 [ # # ]: 0 : InitRead( rIn );
1183 : :
1184 : : // fdo#41796: skip over spurious semicolons
1185 [ # # ]: 0 : while (CSS1_SEMICOLON == nToken)
1186 : : {
1187 [ # # ]: 0 : nToken = GetNextToken();
1188 : : }
1189 : :
1190 [ # # ]: 0 : String aProperty;
1191 [ # # ]: 0 : CSS1Expression *pExpr = ParseDeclaration( aProperty );
1192 [ # # ]: 0 : if( !pExpr )
1193 : : {
1194 : 0 : return sal_False;
1195 : : }
1196 : :
1197 : : // expression verarbeiten
1198 [ # # ][ # # ]: 0 : if( DeclarationParsed( aProperty, pExpr ) )
1199 [ # # ][ # # ]: 0 : delete pExpr;
1200 : :
1201 : 0 : LOOP_CHECK_DECL
1202 : :
1203 : : // [ ';' declaration ]*
1204 [ # # ][ # # ]: 0 : while( CSS1_SEMICOLON==nToken && IsParserWorking() )
[ # # ]
1205 : : {
1206 [ # # ][ # # ]: 0 : LOOP_CHECK_CHECK( "Endlos-Schleife in ParseStyleOption()" )
1207 : :
1208 [ # # ]: 0 : nToken = GetNextToken();
1209 [ # # ]: 0 : if( CSS1_IDENT==nToken )
1210 : : {
1211 [ # # ]: 0 : CSS1Expression *pExp = ParseDeclaration( aProperty );
1212 [ # # ]: 0 : if( pExp )
1213 : : {
1214 : : // expression verarbeiten
1215 [ # # ][ # # ]: 0 : if( DeclarationParsed( aProperty, pExp ) )
1216 [ # # ][ # # ]: 0 : delete pExp;
1217 : : }
1218 : : }
1219 : : }
1220 : :
1221 [ # # ]: 0 : return sal_True;
1222 : : }
1223 : :
1224 : 0 : bool CSS1Parser::SelectorParsed( CSS1Selector* /* pSelector */, bool /*bFirst*/ )
1225 : : {
1226 : : // Selektor loeschen
1227 : 0 : return true;
1228 : : }
1229 : :
1230 : 0 : sal_Bool CSS1Parser::DeclarationParsed( const String& /*rProperty*/,
1231 : : const CSS1Expression * /* pExpr */ )
1232 : : {
1233 : : // Deklaration loeschen
1234 : 0 : return sal_True;
1235 : : }
1236 : :
1237 : :
1238 : 0 : CSS1Selector::~CSS1Selector()
1239 : : {
1240 [ # # ][ # # ]: 0 : delete pNext;
1241 : 0 : }
1242 : :
1243 : 0 : CSS1Expression::~CSS1Expression()
1244 : : {
1245 [ # # ][ # # ]: 0 : delete pNext;
1246 : 0 : }
1247 : :
1248 : 0 : sal_Bool CSS1Expression::GetURL( String& rURL ) const
1249 : : {
1250 : : OSL_ENSURE( CSS1_URL==eType, "CSS1-Ausruck ist keine Farbe URL" );
1251 : :
1252 : : OSL_ENSURE( aValue.CompareIgnoreCaseToAscii( sCSS1_url, 3 ) ==
1253 : : COMPARE_EQUAL &&
1254 : : aValue.Len() > 5 &&
1255 : : '(' == aValue.GetChar(3) &&
1256 : : ')' == aValue.GetChar(aValue.Len()-1),
1257 : : "keine gueltiges URL(...)" );
1258 : :
1259 : 0 : sal_Bool bRet = sal_False;
1260 : :
1261 [ # # ]: 0 : if( aValue.Len() > 5 )
1262 : : {
1263 [ # # ]: 0 : rURL = aValue.Copy( 4, aValue.Len()-5 );
1264 [ # # ][ # # ]: 0 : rURL = comphelper::string::strip(rURL, ' ');
1265 : 0 : bRet = sal_True;
1266 : : }
1267 : :
1268 : 0 : return bRet;
1269 : : }
1270 : :
1271 : 0 : sal_Bool CSS1Expression::GetColor( Color &rColor ) const
1272 : : {
1273 : : OSL_ENSURE( CSS1_IDENT==eType || CSS1_RGB==eType ||
1274 : : CSS1_HEXCOLOR==eType || CSS1_STRING==eType,
1275 : : "CSS1-Ausruck kann keine Farbe sein" );
1276 : :
1277 : 0 : sal_Bool bRet = sal_False;
1278 : 0 : sal_uInt32 nColor = SAL_MAX_UINT32;
1279 : :
1280 [ # # # # ]: 0 : switch( eType )
1281 : : {
1282 : : case CSS1_RGB:
1283 : : {
1284 : 0 : sal_uInt8 aColors[3] = { 0, 0, 0 };
1285 : :
1286 : : OSL_ENSURE( aValue.CompareIgnoreCaseToAscii( sCSS1_rgb, 3 )
1287 : : == COMPARE_EQUAL &&
1288 : : aValue.Len() > 5 &&
1289 : : '(' == aValue.GetChar( 3 ) &&
1290 : : ')' == aValue.GetChar( aValue.Len()-1),
1291 : : "keine gueltiges RGB(...)" );
1292 : :
1293 [ # # ]: 0 : String aColorStr( aValue.Copy( 4, aValue.Len()-1 ) );
1294 : :
1295 : 0 : xub_StrLen nPos = 0;
1296 : 0 : sal_uInt16 nCol = 0;
1297 : :
1298 [ # # ][ # # ]: 0 : while( nCol < 3 && nPos < aColorStr.Len() )
[ # # ]
1299 : : {
1300 : : sal_Unicode c;
1301 [ # # ][ # # ]: 0 : while( nPos < aColorStr.Len() &&
[ # # ][ # # ]
[ # # ][ # # ]
1302 : 0 : ((c=aColorStr.GetChar(nPos)) == ' ' || c == '\t' ||
1303 : : c == '\n' || c== '\r' ) )
1304 : 0 : nPos++;
1305 : :
1306 [ # # ]: 0 : xub_StrLen nEnd = aColorStr.Search( ',', nPos );
1307 [ # # ]: 0 : String aNumber;
1308 [ # # ]: 0 : if( STRING_NOTFOUND==nEnd )
1309 : : {
1310 [ # # ][ # # ]: 0 : aNumber = aColorStr.Copy(nPos);
[ # # ]
1311 : 0 : nPos = aColorStr.Len();
1312 : : }
1313 : : else
1314 : : {
1315 [ # # ][ # # ]: 0 : aNumber = aColorStr.Copy( nPos, nEnd-nPos );
[ # # ]
1316 : 0 : nPos = nEnd+1;
1317 : : }
1318 : :
1319 [ # # ]: 0 : sal_uInt16 nNumber = (sal_uInt16)aNumber.ToInt32();
1320 [ # # ][ # # ]: 0 : if( aNumber.Search('%') != STRING_NOTFOUND )
1321 : : {
1322 [ # # ]: 0 : if( nNumber > 100 )
1323 : 0 : nNumber = 100;
1324 : 0 : nNumber *= 255;
1325 : 0 : nNumber /= 100;
1326 : : }
1327 [ # # ]: 0 : else if( nNumber > 255 )
1328 : 0 : nNumber = 255;
1329 : :
1330 : 0 : aColors[nCol] = (sal_uInt8)nNumber;
1331 : 0 : nCol ++;
1332 [ # # ]: 0 : }
1333 : :
1334 [ # # ]: 0 : rColor.SetRed( aColors[0] );
1335 [ # # ]: 0 : rColor.SetGreen( aColors[1] );
1336 [ # # ]: 0 : rColor.SetBlue( aColors[2] );
1337 : :
1338 [ # # ]: 0 : bRet = sal_True; // etwas anderes als eine Farbe kann es nicht sein
1339 : : }
1340 : 0 : break;
1341 : :
1342 : : case CSS1_IDENT:
1343 : : case CSS1_STRING:
1344 : : {
1345 [ # # ]: 0 : String aTmp( aValue );
1346 [ # # ]: 0 : aTmp.ToUpperAscii();
1347 [ # # ]: 0 : nColor = GetHTMLColor( aTmp );
1348 [ # # ]: 0 : bRet = nColor != SAL_MAX_UINT32;
1349 : : }
1350 [ # # ][ # # ]: 0 : if( bRet || CSS1_STRING != eType || !aValue.Len() ||
[ # # # # ]
[ # # ]
1351 : 0 : aValue.GetChar( 0 )!='#' )
1352 : 0 : break;
1353 : :
1354 : : case CSS1_HEXCOLOR:
1355 : : {
1356 : : // HACK fuer MS-IE: DIe Farbe kann auch in einem String stehen
1357 [ # # ]: 0 : xub_StrLen nOffset = CSS1_STRING==eType ? 1 : 0;
1358 : 0 : sal_Bool bDouble = aValue.Len()-nOffset == 3;
1359 [ # # ]: 0 : xub_StrLen i = nOffset, nEnd = (bDouble ? 3 : 6) + nOffset;
1360 : :
1361 : 0 : nColor = 0;
1362 [ # # ]: 0 : for( ; i<nEnd; i++ )
1363 : : {
1364 : 0 : sal_Unicode c = (i<aValue.Len() ? aValue.GetChar(i)
1365 [ # # ]: 0 : : '0' );
1366 [ # # ][ # # ]: 0 : if( c >= '0' && c <= '9' )
1367 : 0 : c -= 48;
1368 [ # # ][ # # ]: 0 : else if( c >= 'A' && c <= 'F' )
1369 : 0 : c -= 55;
1370 [ # # ][ # # ]: 0 : else if( c >= 'a' && c <= 'f' )
1371 : 0 : c -= 87;
1372 : : else
1373 : 0 : c = 16;
1374 : :
1375 : 0 : nColor *= 16;
1376 [ # # ]: 0 : if( c<16 )
1377 : 0 : nColor += c;
1378 [ # # ]: 0 : if( bDouble )
1379 : : {
1380 : 0 : nColor *= 16;
1381 [ # # ]: 0 : if( c<16 )
1382 : 0 : nColor += c;
1383 : : }
1384 : : }
1385 : 0 : bRet = sal_True;
1386 : : }
1387 : 0 : break;
1388 : : default:
1389 : : ;
1390 : : }
1391 : :
1392 : :
1393 [ # # ][ # # ]: 0 : if( bRet && nColor!=SAL_MAX_UINT32 )
1394 : : {
1395 : 0 : rColor.SetRed( (sal_uInt8)((nColor & 0x00ff0000UL) >> 16) );
1396 : 0 : rColor.SetGreen( (sal_uInt8)((nColor & 0x0000ff00UL) >> 8) );
1397 : 0 : rColor.SetBlue( (sal_uInt8)(nColor & 0x000000ffUL) );
1398 : : }
1399 : :
1400 : 0 : return bRet;
1401 : : }
1402 : :
1403 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|