/src/ftk_text_buffer.c

http://ftk.googlecode.com/ · C · 242 lines · 172 code · 41 blank · 29 comment · 50 complexity · 3435300a117c2c8ca91a89917bc3d632 MD5 · raw file

  1. /*
  2. * File: ftk_text_buffer.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: text buffer
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-11-06 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_util.h"
  31. #include "ftk_text_buffer.h"
  32. FtkTextBuffer* ftk_text_buffer_create(size_t init_buffer_length)
  33. {
  34. FtkTextBuffer* thiz = (FtkTextBuffer*)FTK_ALLOC(sizeof(FtkTextBuffer));
  35. if(thiz != NULL)
  36. {
  37. thiz->length = 0;
  38. thiz->buffer = (char*)FTK_ALLOC(init_buffer_length);
  39. thiz->buffer_length = init_buffer_length;
  40. thiz->buffer[thiz->length] = '\0';
  41. }
  42. return thiz;
  43. }
  44. static Ret ftk_text_buffer_extend(FtkTextBuffer* thiz, size_t length)
  45. {
  46. char* buffer = NULL;
  47. size_t buffer_length = 0;
  48. if((thiz->length + length) < thiz->buffer_length)
  49. {
  50. return RET_OK;
  51. }
  52. buffer_length = (thiz->buffer_length + length + 10);
  53. buffer_length = buffer_length + (buffer_length>>1);
  54. if((buffer = (char*)FTK_REALLOC(thiz->buffer, buffer_length)) != NULL)
  55. {
  56. thiz->buffer = buffer;
  57. thiz->buffer_length = buffer_length;
  58. thiz->buffer[thiz->length] = '\0';
  59. return RET_OK;
  60. }
  61. return RET_FAIL;
  62. }
  63. Ret ftk_text_buffer_insert(FtkTextBuffer* thiz, size_t offset, const char* text, int len)
  64. {
  65. int str_len = len;
  66. size_t length = 0;
  67. char* dst = NULL;
  68. const char* src = NULL;
  69. return_val_if_fail(thiz != NULL && thiz->buffer != NULL && text != NULL, RET_FAIL);
  70. str_len = len < 0 ? (int)strlen(text) : len;
  71. return_val_if_fail(ftk_text_buffer_extend(thiz, str_len + 1) == RET_OK, RET_FAIL);
  72. return_val_if_fail(offset <= thiz->length, RET_FAIL);
  73. if(offset < thiz->length)
  74. {
  75. length = thiz->length - offset;
  76. dst = thiz->buffer + thiz->length + str_len - 1;
  77. src = thiz->buffer + thiz->length - 1;
  78. for(; length != 0; length--, dst--, src--)
  79. {
  80. *dst = *src;
  81. }
  82. }
  83. dst = thiz->buffer + offset;
  84. src = text;
  85. length = str_len;
  86. for(;length != 0; length--, dst++, src++)
  87. {
  88. *dst = *src;
  89. }
  90. thiz->length += str_len;
  91. thiz->buffer[thiz->length] = '\0';
  92. return RET_OK;
  93. }
  94. Ret ftk_text_buffer_delete(FtkTextBuffer* thiz, size_t offset, size_t length)
  95. {
  96. size_t i = 0;
  97. char* dst = NULL;
  98. char* src = NULL;
  99. return_val_if_fail(thiz != NULL && thiz->buffer != NULL, RET_FAIL);
  100. if(offset >= thiz->length) return RET_OK;
  101. length = (offset + length) < thiz->length ? length : (thiz->length - offset);
  102. dst = thiz->buffer + offset;
  103. src = thiz->buffer + offset + length;
  104. i = thiz->length - length - offset;
  105. for(; i != 0; i--, dst++, src++)
  106. {
  107. *dst = *src;
  108. }
  109. thiz->length -= length;
  110. thiz->buffer[thiz->length] = '\0';
  111. return RET_OK;
  112. }
  113. Ret ftk_text_buffer_delete_chars(FtkTextBuffer* thiz, int offset, int count)
  114. {
  115. int length = 0;
  116. return_val_if_fail(thiz != NULL && thiz->buffer != NULL, RET_FAIL);
  117. return_val_if_fail(offset <= (int)thiz->length && offset >= 0, RET_FAIL);
  118. if(!((offset + count) <= (int)thiz->length && (offset + count) >= 0))
  119. {
  120. return RET_FAIL;
  121. }
  122. length = ftk_text_buffer_chars_bytes(thiz, offset, count);
  123. if(length == 0)
  124. {
  125. return RET_FAIL;
  126. }
  127. if(length < 0)
  128. {
  129. return ftk_text_buffer_delete(thiz, offset+length, -length);
  130. }
  131. else
  132. {
  133. return ftk_text_buffer_delete(thiz, offset, length);
  134. }
  135. }
  136. int ftk_text_buffer_char_bytes(FtkTextBuffer* thiz, size_t offset, int backward)
  137. {
  138. return ftk_text_buffer_chars_bytes(thiz, offset, backward ? -1 : 1);
  139. }
  140. int ftk_text_buffer_chars_bytes(FtkTextBuffer* thiz, int offset, int count)
  141. {
  142. const char* iter = NULL;
  143. const char* offset_p = NULL;
  144. return_val_if_fail(thiz != NULL && thiz->buffer != NULL, 0);
  145. return_val_if_fail(offset <= (int)thiz->length && offset >= 0, 0);
  146. if((offset + count) > (int)thiz->length || (offset + count) <0)
  147. {
  148. return 0;
  149. }
  150. offset_p = thiz->buffer + offset;
  151. iter = offset_p;
  152. if(count > 0)
  153. {
  154. for(; count > 0; count--)
  155. {
  156. if(utf8_get_char(iter, &iter) == 0)
  157. {
  158. break;
  159. }
  160. }
  161. }
  162. else
  163. {
  164. for(; count < 0; count++)
  165. {
  166. utf8_get_prev_char(iter, &iter);
  167. if(iter <= thiz->buffer)
  168. {
  169. break;
  170. }
  171. }
  172. }
  173. return iter - offset_p;
  174. }
  175. Ret ftk_text_buffer_reset(FtkTextBuffer* thiz)
  176. {
  177. return_val_if_fail(thiz != NULL, RET_FAIL);
  178. thiz->length = 0;
  179. return RET_OK;
  180. }
  181. char* ftk_text_buffer_append_string(FtkTextBuffer* thiz, const char* str)
  182. {
  183. size_t str_len = 0;
  184. char* start = NULL;
  185. return_val_if_fail(thiz != NULL && str != NULL, NULL);
  186. str_len = strlen(str) + 1;
  187. return_val_if_fail(ftk_text_buffer_extend(thiz, str_len) == RET_OK, NULL);
  188. start = thiz->buffer + thiz->length;
  189. ftk_strncpy(start, str, str_len);
  190. thiz->length += str_len;
  191. return start;
  192. }
  193. void ftk_text_buffer_destroy(FtkTextBuffer* thiz)
  194. {
  195. if(thiz != NULL)
  196. {
  197. FTK_FREE(thiz->buffer);
  198. FTK_ZFREE(thiz, sizeof(*thiz));
  199. }
  200. return;
  201. }