PageRenderTime 63ms CodeModel.GetById 30ms app.highlight 15ms RepoModel.GetById 15ms app.codeStats 0ms

/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/*
 26 * History:
 27 * ================================================================
 28 * 2009-11-06 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_util.h"
 33#include "ftk_text_buffer.h"
 34
 35FtkTextBuffer* ftk_text_buffer_create(size_t init_buffer_length)
 36{
 37	FtkTextBuffer* thiz = (FtkTextBuffer*)FTK_ALLOC(sizeof(FtkTextBuffer));
 38	if(thiz != NULL)
 39	{
 40		thiz->length = 0;
 41		thiz->buffer = (char*)FTK_ALLOC(init_buffer_length);
 42		thiz->buffer_length = init_buffer_length;
 43		thiz->buffer[thiz->length] = '\0';
 44	}
 45
 46	return thiz;
 47}
 48
 49static Ret ftk_text_buffer_extend(FtkTextBuffer* thiz, size_t length)
 50{
 51	char* buffer = NULL;
 52	size_t buffer_length = 0;
 53	if((thiz->length + length) < thiz->buffer_length)
 54	{
 55		return RET_OK;
 56	}
 57
 58	buffer_length = (thiz->buffer_length + length + 10);
 59	buffer_length = buffer_length + (buffer_length>>1);
 60
 61	if((buffer = (char*)FTK_REALLOC(thiz->buffer, buffer_length)) != NULL)
 62	{
 63		thiz->buffer = buffer;
 64		thiz->buffer_length = buffer_length;
 65		thiz->buffer[thiz->length] = '\0';
 66
 67		return RET_OK;
 68	}
 69
 70	return RET_FAIL;
 71}
 72
 73Ret  ftk_text_buffer_insert(FtkTextBuffer* thiz, size_t offset, const char* text, int len)
 74{
 75	int str_len = len;
 76	size_t length = 0;
 77	char* dst = NULL;
 78	const char* src = NULL;
 79	return_val_if_fail(thiz != NULL && thiz->buffer != NULL && text != NULL, RET_FAIL);	
 80	str_len = len < 0 ? (int)strlen(text) : len;
 81	return_val_if_fail(ftk_text_buffer_extend(thiz, str_len + 1) == RET_OK, RET_FAIL);
 82	return_val_if_fail(offset <= thiz->length, RET_FAIL);
 83
 84	if(offset < thiz->length)
 85	{
 86		length = thiz->length - offset;
 87		dst = thiz->buffer + thiz->length + str_len - 1;
 88		src = thiz->buffer + thiz->length - 1;
 89		for(; length != 0; length--, dst--, src--)
 90		{
 91			*dst = *src;
 92		}
 93	}
 94	dst = thiz->buffer + offset;
 95	src = text;
 96	length = str_len;
 97	for(;length != 0; length--, dst++, src++)
 98	{
 99		*dst = *src;
100	}
101
102	thiz->length += str_len;
103	thiz->buffer[thiz->length] = '\0';
104
105	return RET_OK;
106}
107
108Ret  ftk_text_buffer_delete(FtkTextBuffer* thiz, size_t offset, size_t length)
109{
110	size_t i = 0;
111	char* dst = NULL;
112	char* src = NULL;
113	return_val_if_fail(thiz != NULL && thiz->buffer != NULL, RET_FAIL);
114
115	if(offset >= thiz->length) return RET_OK;
116
117	length = (offset + length) < thiz->length ? length : (thiz->length - offset);
118	
119	dst = thiz->buffer + offset;
120	src = thiz->buffer + offset + length;
121
122	i = thiz->length - length - offset;
123	for(; i != 0; i--, dst++, src++)
124	{
125		*dst = *src;
126	}
127	thiz->length -= length;
128	thiz->buffer[thiz->length] = '\0';
129
130	return RET_OK;
131}
132
133Ret  ftk_text_buffer_delete_chars(FtkTextBuffer* thiz, int offset, int count)
134{
135	int length = 0;
136	return_val_if_fail(thiz != NULL && thiz->buffer != NULL, RET_FAIL);
137	return_val_if_fail(offset <= (int)thiz->length && offset >= 0, RET_FAIL);
138
139	if(!((offset + count) <= (int)thiz->length && (offset + count) >= 0))
140	{
141		return RET_FAIL;
142	}
143
144	length = ftk_text_buffer_chars_bytes(thiz, offset, count);
145	if(length == 0)
146	{
147		return RET_FAIL;
148	}
149
150	if(length < 0)
151	{
152		return ftk_text_buffer_delete(thiz, offset+length, -length);
153	}
154	else
155	{
156		return ftk_text_buffer_delete(thiz, offset, length);
157	}
158}
159
160int  ftk_text_buffer_char_bytes(FtkTextBuffer* thiz, size_t offset, int backward)
161{
162	return ftk_text_buffer_chars_bytes(thiz, offset, backward ? -1 : 1);
163}
164
165int  ftk_text_buffer_chars_bytes(FtkTextBuffer* thiz, int offset, int count)
166{
167	const char* iter = NULL;
168	const char* offset_p = NULL;
169	return_val_if_fail(thiz != NULL && thiz->buffer != NULL, 0);
170	return_val_if_fail(offset <= (int)thiz->length && offset >= 0, 0);
171	
172	if((offset + count) > (int)thiz->length || (offset + count) <0)
173	{
174		return 0;
175	}
176
177	offset_p = thiz->buffer + offset;
178	iter = offset_p;
179	if(count > 0)
180	{
181		for(; count > 0; count--)
182		{
183			 if(utf8_get_char(iter, &iter) == 0)
184			 {
185			 	break;
186			 }
187		}
188	}
189	else
190	{
191		for(; count < 0; count++)
192		{
193			utf8_get_prev_char(iter, &iter);
194			if(iter <= thiz->buffer)
195			{
196				break;
197			}
198		}
199
200	}
201	
202	return iter - offset_p;
203}
204
205Ret   ftk_text_buffer_reset(FtkTextBuffer* thiz)
206{
207	return_val_if_fail(thiz != NULL, RET_FAIL);
208
209	thiz->length = 0;
210
211	return RET_OK;
212}
213
214char* ftk_text_buffer_append_string(FtkTextBuffer* thiz, const char* str)
215{
216	size_t str_len = 0;
217	char*  start = NULL;
218	return_val_if_fail(thiz != NULL && str != NULL, NULL);
219	
220	str_len = strlen(str) + 1;
221	return_val_if_fail(ftk_text_buffer_extend(thiz, str_len) == RET_OK, NULL);
222
223	start = thiz->buffer + thiz->length;
224	ftk_strncpy(start, str, str_len);
225
226	thiz->length += str_len;
227
228	return start;
229}
230
231void ftk_text_buffer_destroy(FtkTextBuffer* thiz)
232{
233	if(thiz != NULL)
234	{
235		FTK_FREE(thiz->buffer);
236		FTK_ZFREE(thiz, sizeof(*thiz));
237	}
238
239	return;
240}
241
242