rich_text.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. Copyright (C) 2014 Olivier Marty <olivier.marty.m at gmail.com>
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include "rich_text.h"
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. char *strnstr(const char *s, const char *find, size_t slen)
  20. {
  21. char c, sc;
  22. size_t len;
  23. if ((c = *find++) != '\0') {
  24. len = strlen(find);
  25. do {
  26. do {
  27. if ((sc = *s++) == '\0' || slen-- < 1)
  28. return (NULL);
  29. } while (sc != c);
  30. if (len > slen)
  31. return (NULL);
  32. } while (strncmp(s, find, len) != 0);
  33. s--;
  34. }
  35. return ((char *)s);
  36. }
  37. /*char *strnstr(const char *s, const char *find, size_t slen)
  38. {
  39. return (char*)memmem((void*)s, slen, (void*)find, strlen(find));
  40. }*/
  41. struct richText* newRt(struct richText *left, struct richText *right,
  42. char* pos, int size, enum t_type type)
  43. {
  44. struct richText *rt = malloc(sizeof(struct richText));
  45. if(rt == NULL)
  46. {
  47. perror("malloc()");
  48. exit(1);
  49. }
  50. rt->left = left;
  51. rt->right = right;
  52. rt->pos = pos;
  53. rt->size = size;
  54. rt->type = type;
  55. return rt;
  56. }
  57. // rt must be of type data (pos and size)
  58. // inflate rt
  59. void parseAux(struct richText *rt) {
  60. char *text = rt->pos;
  61. int size = rt->size;
  62. char *i = strnstr(text, "<i>", size),
  63. *b = strnstr(text, "<b>", size);
  64. char *end, *begin = NULL;
  65. if(i == text || b == text) // text start with <i> or <b>
  66. {
  67. enum t_type type = rt->type;
  68. if(i == text)
  69. {
  70. type |= T_ITALIC;
  71. end = strnstr(text, "</i>", size); // TODO reverse for nested tags
  72. }
  73. else
  74. {
  75. type |= T_BOLD;
  76. end = strnstr(text, "</b>", size);
  77. }
  78. if(end != NULL)
  79. {
  80. if(end == text + size - 4) // text end with end tag
  81. {
  82. // we do not create a node
  83. rt->pos = text+3;
  84. rt->size = end-text-3;
  85. rt->type = type;
  86. parseAux(rt);
  87. }
  88. else
  89. {
  90. rt->left = newRt(NULL, NULL, text+3, end-text-3, type);
  91. rt->right = newRt(NULL, NULL, end+4, text+size-end-4, rt->type);
  92. parseAux(rt->left);
  93. parseAux(rt->right);
  94. }
  95. }
  96. else // tags do not match
  97. {
  98. rt->left = newRt(NULL, NULL, text, 3, rt->type);
  99. rt->right = newRt(NULL, NULL, text+3, size-3, rt->type);
  100. // rt->left is not inflated
  101. parseAux(rt->right);
  102. }
  103. }
  104. else if(i != NULL || b != NULL) // there is a tag in the text
  105. {
  106. char *pos = i;
  107. if(i == NULL || (b != NULL && b < i))
  108. pos = b;
  109. // pos : first tag
  110. rt->left = newRt(NULL, NULL, text, pos-text, rt->type);
  111. rt->right = newRt(NULL, NULL, pos, text+size-pos, rt->type);
  112. parseAux(rt->right);
  113. }
  114. }
  115. struct richText* richTextParse(char* data) {
  116. struct richText *rt = newRt(NULL, NULL, data, strlen(data), T_REGULAR);
  117. parseAux(rt);
  118. rt->raw = data;
  119. return rt;
  120. }
  121. void richTextFree(struct richText *rt) {
  122. if(rt->left != NULL)
  123. richTextFree(rt->left);
  124. if(rt->right != NULL)
  125. richTextFree(rt->right);
  126. free(rt);
  127. }