(root)/
gettext-0.22.4/
libtextstyle/
lib/
libcroco/
cr-simple-sel.c
       1  /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
       2  
       3  /* libcroco - Library for parsing and applying CSS
       4   * Copyright (C) 2006-2019 Free Software Foundation, Inc.
       5   *
       6   * This file is not part of the GNU gettext program, but is used with
       7   * GNU gettext.
       8   *
       9   * The original copyright notice is as follows:
      10   */
      11  
      12  /*
      13   * This file is part of The Croco Library
      14   *
      15   * Copyright (C) 2003-2004 Dodji Seketeli.  All Rights Reserved.
      16   *
      17   * This program is free software; you can redistribute it and/or
      18   * modify it under the terms of version 2.1 of the GNU Lesser General Public
      19   * License as published by the Free Software Foundation.
      20   *
      21   * This program is distributed in the hope that it will be useful,
      22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24   * GNU General Public License for more details.
      25   *
      26   * You should have received a copy of the GNU Lesser General Public License
      27   * along with this program; if not, write to the Free Software
      28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      29   * USA
      30   *
      31   * Author: Dodji Seketeli
      32   */
      33  
      34  #include <config.h>
      35  #include <string.h>
      36  #include <glib.h>
      37  #include "cr-simple-sel.h"
      38  
      39  /**
      40   * cr_simple_sel_new:
      41   *
      42   *The constructor of #CRSimpleSel.
      43   *
      44   *Returns the new instance of #CRSimpleSel.
      45   */
      46  CRSimpleSel *
      47  cr_simple_sel_new (void)
      48  {
      49          CRSimpleSel *result = NULL;
      50  
      51          result = g_try_malloc (sizeof (CRSimpleSel));
      52          if (!result) {
      53                  cr_utils_trace_info ("Out of memory");
      54                  return NULL;
      55          }
      56          memset (result, 0, sizeof (CRSimpleSel));
      57  
      58          return result;
      59  }
      60  
      61  /**
      62   * cr_simple_sel_append_simple_sel:
      63   *
      64   *Appends a simpe selector to the current list of simple selector.
      65   *
      66   *@a_this: the this pointer of the current instance of #CRSimpleSel.
      67   *@a_sel: the simple selector to append.
      68   *
      69   *Returns: the new list upon successfull completion, an error code otherwise.
      70   */
      71  CRSimpleSel *
      72  cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
      73  {
      74          CRSimpleSel *cur = NULL;
      75  
      76          g_return_val_if_fail (a_sel, NULL);
      77  
      78          if (a_this == NULL)
      79                  return a_sel;
      80  
      81          for (cur = a_this; cur->next; cur = cur->next) ;
      82  
      83          cur->next = a_sel;
      84          a_sel->prev = cur;
      85  
      86          return a_this;
      87  }
      88  
      89  /**
      90   * cr_simple_sel_prepend_simple_sel:
      91   *
      92   *@a_this: the this pointer of the current instance of #CRSimpleSel.
      93   *@a_sel: the simple selector to prepend.
      94   *
      95   *Prepends a simple selector to the current list of simple selectors.
      96   *
      97   *Returns the new list upon successfull completion, an error code otherwise.
      98   */
      99  CRSimpleSel *
     100  cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
     101  {
     102          g_return_val_if_fail (a_sel, NULL);
     103  
     104          if (a_this == NULL)
     105                  return a_sel;
     106  
     107          a_sel->next = a_this;
     108          a_this->prev = a_sel;
     109  
     110          return a_sel;
     111  }
     112  
     113  guchar *
     114  cr_simple_sel_to_string (CRSimpleSel const * a_this)
     115  {
     116          GString *str_buf = NULL;
     117          guchar *result = NULL;
     118  
     119          CRSimpleSel const *cur = NULL;
     120  
     121          g_return_val_if_fail (a_this, NULL);
     122  
     123          str_buf = g_string_new (NULL);
     124          for (cur = a_this; cur; cur = cur->next) {
     125                  if (cur->name) {
     126                          guchar *str = (guchar *) g_strndup (cur->name->stryng->str,
     127                                                   cur->name->stryng->len);
     128  
     129                          if (str) {
     130                                  switch (cur->combinator) {
     131                                  case COMB_WS:
     132                                          g_string_append (str_buf, " ");
     133                                          break;
     134  
     135                                  case COMB_PLUS:
     136                                          g_string_append (str_buf, "+");
     137                                          break;
     138  
     139                                  case COMB_GT:
     140                                          g_string_append (str_buf, ">");
     141                                          break;
     142  
     143                                  default:
     144                                          break;
     145                                  }
     146  
     147                                  g_string_append (str_buf, (const gchar *) str);
     148                                  g_free (str);
     149                                  str = NULL;
     150                          }
     151                  }
     152  
     153                  if (cur->add_sel) {
     154                          guchar *tmp_str = NULL;
     155  
     156                          tmp_str = cr_additional_sel_to_string (cur->add_sel);
     157                          if (tmp_str) {
     158                                  g_string_append (str_buf, (const gchar *) tmp_str);
     159                                  g_free (tmp_str);
     160                                  tmp_str = NULL;
     161                          }
     162                  }
     163          }
     164  
     165          if (str_buf) {
     166                  result = (guchar *) str_buf->str;
     167                  g_string_free (str_buf, FALSE);
     168                  str_buf = NULL;
     169          }
     170  
     171          return result;
     172  }
     173  
     174  
     175  guchar *
     176  cr_simple_sel_one_to_string (CRSimpleSel const * a_this)
     177  {
     178          GString *str_buf = NULL;
     179          guchar *result = NULL;
     180  
     181          g_return_val_if_fail (a_this, NULL);
     182  
     183          str_buf = g_string_new (NULL);
     184          if (a_this->name) {
     185                  guchar *str = (guchar *) g_strndup (a_this->name->stryng->str,
     186                                           a_this->name->stryng->len);
     187  
     188                  if (str) {
     189                          g_string_append_printf (str_buf, "%s", str);
     190                          g_free (str);
     191                          str = NULL;
     192                  }
     193          }
     194  
     195          if (a_this->add_sel) {
     196                  guchar *tmp_str = NULL;
     197  
     198                  tmp_str = cr_additional_sel_to_string (a_this->add_sel);
     199                  if (tmp_str) {
     200                          g_string_append_printf
     201                                  (str_buf, "%s", tmp_str);
     202                          g_free (tmp_str);
     203                          tmp_str = NULL;
     204                  }
     205          }
     206  
     207          if (str_buf) {
     208                  result = (guchar *) str_buf->str;
     209                  g_string_free (str_buf, FALSE);
     210                  str_buf = NULL;
     211          }
     212  
     213          return result;
     214  }
     215  
     216  /**
     217   * cr_simple_sel_dump:
     218   *@a_this: the current instance of #CRSimpleSel.
     219   *@a_fp: the destination file pointer.
     220   *
     221   *Dumps the selector to a file.
     222   *TODO: add the support of unicode in the dump.
     223   *
     224   *Returns CR_OK upon successfull completion, an error code
     225   *otherwise.
     226   */
     227  enum CRStatus
     228  cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp)
     229  {
     230          guchar *tmp_str = NULL;
     231  
     232          g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
     233  
     234          if (a_this) {
     235                  tmp_str = cr_simple_sel_to_string (a_this);
     236                  if (tmp_str) {
     237                          fprintf (a_fp, "%s", tmp_str);
     238                          g_free (tmp_str);
     239                          tmp_str = NULL;
     240                  }
     241          }
     242  
     243          return CR_OK;
     244  }
     245  
     246  /**
     247   * cr_simple_sel_compute_specificity:
     248   *
     249   *@a_this: the current instance of #CRSimpleSel
     250   *
     251   *Computes the selector (combinator separated list of simple selectors)
     252   *as defined in the css2 spec in chapter 6.4.3
     253   *
     254   *Returns CR_OK upon successfull completion, an error code otherwise.
     255   */
     256  enum CRStatus
     257  cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
     258  {
     259          CRAdditionalSel const *cur_add_sel = NULL;
     260          CRSimpleSel const *cur_sel = NULL;
     261          gulong a = 0,
     262                  b = 0,
     263                  c = 0;
     264  
     265          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
     266  
     267          for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
     268                  if (cur_sel->type_mask & TYPE_SELECTOR) {
     269                          c++;    /*hmmh, is this a new language ? */
     270                  } else if (!cur_sel->name 
     271                             || !cur_sel->name->stryng
     272                             || !cur_sel->name->stryng->str) {
     273                          if (cur_sel->add_sel->type ==
     274                              PSEUDO_CLASS_ADD_SELECTOR) {
     275                                  /*
     276                                   *this is a pseudo element, and
     277                                   *the spec says, "ignore pseudo elements".
     278                                   */
     279                                  continue;
     280                          }
     281                  }
     282  
     283                  for (cur_add_sel = cur_sel->add_sel;
     284                       cur_add_sel; cur_add_sel = cur_add_sel->next) {
     285                          switch (cur_add_sel->type) {
     286                          case ID_ADD_SELECTOR:
     287                                  a++;
     288                                  break;
     289  
     290                          case NO_ADD_SELECTOR:
     291                                  continue;
     292  
     293                          default:
     294                                  b++;
     295                                  break;
     296                          }
     297                  }
     298          }
     299  
     300          /*we suppose a, b and c have 1 to 3 digits */
     301          a_this->specificity = a * 1000000 + b * 1000 + c;
     302  
     303          return CR_OK;
     304  }
     305  
     306  /**
     307   * cr_simple_sel_destroy:
     308   *
     309   *@a_this: the this pointer of the current instance of #CRSimpleSel.
     310   *
     311   *The destructor of the current instance of
     312   *#CRSimpleSel.
     313   */
     314  void
     315  cr_simple_sel_destroy (CRSimpleSel * a_this)
     316  {
     317          g_return_if_fail (a_this);
     318  
     319          if (a_this->name) {
     320                  cr_string_destroy (a_this->name);
     321                  a_this->name = NULL;
     322          }
     323  
     324          if (a_this->add_sel) {
     325                  cr_additional_sel_destroy (a_this->add_sel);
     326                  a_this->add_sel = NULL;
     327          }
     328  
     329          if (a_this->next) {
     330                  cr_simple_sel_destroy (a_this->next);
     331          }
     332  
     333          if (a_this) {
     334                  g_free (a_this);
     335          }
     336  }