(root)/
gettext-0.22.4/
libtextstyle/
lib/
libcroco/
cr-selector.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  
      32  #include <config.h>
      33  #include <string.h>
      34  #include "cr-selector.h"
      35  #include "cr-parser.h"
      36  
      37  /**
      38   * cr_selector_new:
      39   *
      40   *@a_simple_sel: the initial simple selector list
      41   *of the current instance of #CRSelector.
      42   *
      43   *Creates a new instance of #CRSelector.
      44   *
      45   *Returns the newly built instance of #CRSelector, or
      46   *NULL in case of failure.
      47   */
      48  CRSelector *
      49  cr_selector_new (CRSimpleSel * a_simple_sel)
      50  {
      51          CRSelector *result = NULL;
      52  
      53          result = g_try_malloc (sizeof (CRSelector));
      54          if (!result) {
      55                  cr_utils_trace_info ("Out of memory");
      56                  return NULL;
      57          }
      58          memset (result, 0, sizeof (CRSelector));
      59          result->simple_sel = a_simple_sel;
      60          return result;
      61  }
      62  
      63  CRSelector *
      64  cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
      65  {
      66          CRParser *parser = NULL;
      67  
      68          g_return_val_if_fail (a_char_buf, NULL);
      69  
      70          parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen ((const char *) a_char_buf),
      71                                           a_enc, FALSE);
      72          g_return_val_if_fail (parser, NULL);
      73  
      74          return NULL;
      75  }
      76  
      77  /**
      78   * cr_selector_append:
      79   *
      80   *@a_this: the current instance of #CRSelector.
      81   *@a_new: the instance of #CRSelector to be appended.
      82   *
      83   *Appends a new instance of #CRSelector to the current selector list.
      84   *
      85   *Returns the new list.
      86   */
      87  CRSelector *
      88  cr_selector_append (CRSelector * a_this, CRSelector * a_new)
      89  {
      90          CRSelector *cur = NULL;
      91  
      92          if (!a_this) {
      93                  return a_new;
      94          }
      95  
      96          /*walk forward the list headed by a_this to get the list tail */
      97          for (cur = a_this; cur && cur->next; cur = cur->next) ;
      98  
      99          cur->next = a_new;
     100          a_new->prev = cur;
     101  
     102          return a_this;
     103  }
     104  
     105  /**
     106   * cr_selector_prepend:
     107   *
     108   *@a_this: the current instance of #CRSelector list.
     109   *@a_new: the instance of #CRSelector.
     110   *
     111   *Prepends an element to the #CRSelector list.
     112   * 
     113   *Returns the new list.
     114   */
     115  CRSelector *
     116  cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
     117  {
     118          CRSelector *cur = NULL;
     119  
     120          a_new->next = a_this;
     121          a_this->prev = a_new;
     122  
     123          for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
     124  
     125          return cur;
     126  }
     127  
     128  /**
     129   * cr_selector_append_simple_sel:
     130   *
     131   *@a_this: the current instance of #CRSelector.
     132   *@a_simple_sel: the simple selector to append.
     133   *
     134   *append a simple selector to the current #CRSelector list.
     135   *
     136   *Returns the new list or NULL in case of failure.
     137   */
     138  CRSelector *
     139  cr_selector_append_simple_sel (CRSelector * a_this,
     140                                 CRSimpleSel * a_simple_sel)
     141  {
     142          CRSelector *selector = NULL;
     143  
     144          selector = cr_selector_new (a_simple_sel);
     145          g_return_val_if_fail (selector, NULL);
     146  
     147          return cr_selector_append (a_this, selector);
     148  }
     149  
     150  guchar *
     151  cr_selector_to_string (CRSelector const * a_this)
     152  {
     153          guchar *result = NULL;
     154          GString *str_buf = NULL;
     155  
     156          str_buf = g_string_new (NULL);
     157          g_return_val_if_fail (str_buf, NULL);
     158  
     159          if (a_this) {
     160                  CRSelector const *cur = NULL;
     161  
     162                  for (cur = a_this; cur; cur = cur->next) {
     163                          if (cur->simple_sel) {
     164                                  guchar *tmp_str = NULL;
     165  
     166                                  tmp_str = cr_simple_sel_to_string
     167                                          (cur->simple_sel);
     168  
     169                                  if (tmp_str) {
     170                                          if (cur->prev)
     171                                                  g_string_append (str_buf, 
     172  								 ", ");
     173  
     174                                          g_string_append (str_buf, (const gchar *) tmp_str);
     175  
     176                                          g_free (tmp_str);
     177                                          tmp_str = NULL;
     178                                  }
     179                          }
     180                  }
     181          }
     182  
     183          if (str_buf) {
     184                  result = (guchar *) str_buf->str;
     185                  g_string_free (str_buf, FALSE);
     186                  str_buf = NULL;
     187          }
     188  
     189          return result;
     190  }
     191  
     192  /**
     193   * cr_selector_dump:
     194   *
     195   *@a_this: the current instance of #CRSelector.
     196   *@a_fp: the destination file.
     197   *
     198   *Serializes the current instance of #CRSelector to a file.
     199   */
     200  void
     201  cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
     202  {
     203          guchar *tmp_buf = NULL;
     204  
     205          if (a_this) {
     206                  tmp_buf = cr_selector_to_string (a_this);
     207                  if (tmp_buf) {
     208                          fprintf (a_fp, "%s", tmp_buf);
     209                          g_free (tmp_buf);
     210                          tmp_buf = NULL;
     211                  }
     212          }
     213  }
     214  
     215  /**
     216   * cr_selector_ref:
     217   *
     218   *@a_this: the current instance of #CRSelector.
     219   *
     220   *Increments the ref count of the current instance
     221   *of #CRSelector.
     222   */
     223  void
     224  cr_selector_ref (CRSelector * a_this)
     225  {
     226          g_return_if_fail (a_this);
     227  
     228          a_this->ref_count++;
     229  }
     230  
     231  /**
     232   * cr_selector_unref:
     233   *
     234   *@a_this: the current instance of #CRSelector.
     235   *
     236   *Decrements the ref count of the current instance of
     237   *#CRSelector.
     238   *If the ref count reaches zero, the current instance of
     239   *#CRSelector is destroyed.
     240   *
     241   *Returns TRUE if this function destroyed the current instance
     242   *of #CRSelector, FALSE otherwise.
     243   */
     244  gboolean
     245  cr_selector_unref (CRSelector * a_this)
     246  {
     247          g_return_val_if_fail (a_this, FALSE);
     248  
     249          if (a_this->ref_count) {
     250                  a_this->ref_count--;
     251          }
     252  
     253          if (a_this->ref_count == 0) {
     254                  cr_selector_destroy (a_this);
     255                  return TRUE;
     256          }
     257  
     258          return FALSE;
     259  }
     260  
     261  /**
     262   * cr_selector_destroy:
     263   *
     264   *@a_this: the current instance of #CRSelector.
     265   *
     266   *Destroys the selector list.
     267   */
     268  void
     269  cr_selector_destroy (CRSelector * a_this)
     270  {
     271          CRSelector *cur = NULL;
     272  
     273          g_return_if_fail (a_this);
     274  
     275          /*
     276           *go and get the list tail. In the same time, free
     277           *all the simple selectors contained in the list.
     278           */
     279          for (cur = a_this; cur && cur->next; cur = cur->next) {
     280                  if (cur->simple_sel) {
     281                          cr_simple_sel_destroy (cur->simple_sel);
     282                          cur->simple_sel = NULL;
     283                  }
     284          }
     285  
     286          if (cur) {
     287                  if (cur->simple_sel) {
     288                          cr_simple_sel_destroy (cur->simple_sel);
     289                          cur->simple_sel = NULL;
     290                  }
     291          }
     292  
     293          /*in case the list has only one element */
     294          if (cur && !cur->prev) {
     295                  g_free (cur);
     296                  return;
     297          }
     298  
     299          /*walk backward the list and free each "next element" */
     300          for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
     301                  if (cur->next) {
     302                          g_free (cur->next);
     303                          cur->next = NULL;
     304                  }
     305          }
     306  
     307          if (!cur)
     308                  return;
     309  
     310          if (cur->next) {
     311                  g_free (cur->next);
     312                  cur->next = NULL;
     313          }
     314  
     315          g_free (cur);
     316  }