LCOV - code coverage report
Current view: top level - sw/source/filter/html - parcss1.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 437 607 72.0 %
Date: 2015-06-13 12:38:46 Functions: 14 18 77.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11