PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/cssed-0.4.0/libcroco/parser/cr-simple-sel.c

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