X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Ffe-text%2Ftextbuffer.c;fp=apps%2Firssi%2Fsrc%2Ffe-text%2Ftextbuffer.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=930e55ad6d205365adc909c808232f313243c5ef;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/irssi/src/fe-text/textbuffer.c b/apps/irssi/src/fe-text/textbuffer.c deleted file mode 100644 index 930e55ad..00000000 --- a/apps/irssi/src/fe-text/textbuffer.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - textbuffer.c : Text buffer handling - - Copyright (C) 1999-2001 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#define G_LOG_DOMAIN "TextBuffer" - -#include "module.h" -#include "misc.h" -#include "formats.h" - -#include "textbuffer.h" - -#ifdef HAVE_REGEX_H -# include -#endif - -#define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*)) - -static GMemChunk *buffer_chunk, *line_chunk, *text_chunk; - -TEXT_BUFFER_REC *textbuffer_create(void) -{ - TEXT_BUFFER_REC *buffer; - - buffer = g_mem_chunk_alloc0(buffer_chunk); - buffer->last_eol = TRUE; - return buffer; -} - -void textbuffer_destroy(TEXT_BUFFER_REC *buffer) -{ - g_return_if_fail(buffer != NULL); - - textbuffer_remove_all_lines(buffer); - g_mem_chunk_free(buffer_chunk, buffer); -} - -static TEXT_CHUNK_REC *text_chunk_find(TEXT_BUFFER_REC *buffer, - const unsigned char *data) -{ - GSList *tmp; - - for (tmp = buffer->text_chunks; tmp != NULL; tmp = tmp->next) { - TEXT_CHUNK_REC *rec = tmp->data; - - if (data >= rec->buffer && - data < rec->buffer+sizeof(rec->buffer)) - return rec; - } - - return NULL; -} - -#define mark_temp_eol(chunk) G_STMT_START { \ - (chunk)->buffer[(chunk)->pos] = 0; \ - (chunk)->buffer[(chunk)->pos+1] = LINE_CMD_EOL; \ - } G_STMT_END - -static TEXT_CHUNK_REC *text_chunk_create(TEXT_BUFFER_REC *buffer) -{ - TEXT_CHUNK_REC *rec; - unsigned char *buf, *ptr, **pptr; - - rec = g_mem_chunk_alloc(text_chunk); - rec->pos = 0; - rec->refcount = 0; - - if (buffer->cur_line != NULL && buffer->cur_line->text != NULL) { - /* create a link to new block from the old block */ - buf = buffer->cur_text->buffer + buffer->cur_text->pos; - *buf++ = 0; *buf++ = (char) LINE_CMD_CONTINUE; - - /* we want to store pointer to beginning of the new text - block to char* buffer. this probably isn't ANSI-C - compatible, and trying this without the pptr variable - breaks at least NetBSD/Alpha, so don't go "optimize" - it :) */ - ptr = rec->buffer; pptr = &ptr; - memcpy(buf, pptr, sizeof(unsigned char *)); - } else { - /* just to be safe */ - mark_temp_eol(rec); - } - - buffer->cur_text = rec; - buffer->text_chunks = g_slist_append(buffer->text_chunks, rec); - return rec; -} - -static void text_chunk_destroy(TEXT_BUFFER_REC *buffer, TEXT_CHUNK_REC *chunk) -{ - buffer->text_chunks = g_slist_remove(buffer->text_chunks, chunk); - g_mem_chunk_free(text_chunk, chunk); -} - -static void text_chunk_line_free(TEXT_BUFFER_REC *buffer, LINE_REC *line) -{ - TEXT_CHUNK_REC *chunk; - const unsigned char *text; - unsigned char cmd, *tmp = NULL; - - for (text = line->text;; text++) { - if (*text != '\0') - continue; - - text++; - cmd = *text; - if (cmd == LINE_CMD_CONTINUE || cmd == LINE_CMD_EOL) { - if (cmd == LINE_CMD_CONTINUE) - memcpy(&tmp, text+1, sizeof(char *)); - - /* free the previous block */ - chunk = text_chunk_find(buffer, text); - if (--chunk->refcount == 0) { - if (buffer->cur_text == chunk) - chunk->pos = 0; - else - text_chunk_destroy(buffer, chunk); - } - - if (cmd == LINE_CMD_EOL) - break; - - text = tmp-1; - } else if (cmd == LINE_CMD_INDENT_FUNC) { - text += sizeof(int (*) ()); - } - } -} - -static void text_chunk_append(TEXT_BUFFER_REC *buffer, - const unsigned char *data, int len) -{ - TEXT_CHUNK_REC *chunk; - int left; - - if (len == 0) - return; - - chunk = buffer->cur_text; - while (chunk->pos + len >= TEXT_CHUNK_USABLE_SIZE) { - left = TEXT_CHUNK_USABLE_SIZE - chunk->pos; - if (left > 0 && data[left-1] == 0) - left--; /* don't split the commands */ - - memcpy(chunk->buffer + chunk->pos, data, left); - chunk->pos += left; - - chunk = text_chunk_create(buffer); - chunk->refcount++; - len -= left; data += left; - } - - memcpy(chunk->buffer + chunk->pos, data, len); - chunk->pos += len; - - mark_temp_eol(chunk); -} - -static LINE_REC *textbuffer_line_create(TEXT_BUFFER_REC *buffer) -{ - LINE_REC *rec; - - if (buffer->cur_text == NULL) - text_chunk_create(buffer); - - rec = g_mem_chunk_alloc(line_chunk); - rec->refcount = 1; - rec->text = buffer->cur_text->buffer + buffer->cur_text->pos; - - buffer->cur_text->refcount++; - return rec; -} - -static LINE_REC *textbuffer_line_insert(TEXT_BUFFER_REC *buffer, - LINE_REC *prev) -{ - LINE_REC *line; - - line = textbuffer_line_create(buffer); - line->prev = prev; - if (prev == NULL) { - line->next = buffer->first_line; - if (buffer->first_line != NULL) - buffer->first_line->prev = line; - buffer->first_line = line; - } else { - line->next = prev->next; - if (line->next != NULL) - line->next->prev = line; - prev->next = line; - } - - if (prev == buffer->cur_line) - buffer->cur_line = line; - buffer->lines_count++; - - return line; -} - -void textbuffer_line_ref(LINE_REC *line) -{ - g_return_if_fail(line != NULL); - - if (++line->refcount == 255) - g_error("line reference counter wrapped - shouldn't happen"); -} - -void textbuffer_line_unref(TEXT_BUFFER_REC *buffer, LINE_REC *line) -{ - g_return_if_fail(buffer != NULL); - g_return_if_fail(line != NULL); - - if (--line->refcount == 0) { - text_chunk_line_free(buffer, line); - g_mem_chunk_free(line_chunk, line); - } -} - -void textbuffer_line_unref_list(TEXT_BUFFER_REC *buffer, GList *list) -{ - g_return_if_fail(buffer != NULL); - - while (list != NULL) { - if (list->data != NULL) - textbuffer_line_unref(buffer, list->data); - list = list->next; - } -} - -LINE_REC *textbuffer_line_last(TEXT_BUFFER_REC *buffer) -{ - LINE_REC *line; - - line = buffer->cur_line; - if (line != NULL) { - while (line->next != NULL) - line = line->next; - } - return line; -} - -int textbuffer_line_exists_after(LINE_REC *line, LINE_REC *search) -{ - while (line != NULL) { - if (line == search) - return TRUE; - line = line->next; - } - return FALSE; -} - -LINE_REC *textbuffer_append(TEXT_BUFFER_REC *buffer, - const unsigned char *data, int len, - LINE_INFO_REC *info) -{ - return textbuffer_insert(buffer, buffer->cur_line, data, len, info); -} - -LINE_REC *textbuffer_insert(TEXT_BUFFER_REC *buffer, LINE_REC *insert_after, - const unsigned char *data, int len, - LINE_INFO_REC *info) -{ - LINE_REC *line; - - g_return_val_if_fail(buffer != NULL, NULL); - g_return_val_if_fail(data != NULL, NULL); - - if (len == 0) - return insert_after; - - line = !buffer->last_eol ? insert_after : - textbuffer_line_insert(buffer, insert_after); - - if (info != NULL) - memcpy(&line->info, info, sizeof(line->info)); - - text_chunk_append(buffer, data, len); - - buffer->last_eol = len >= 2 && - data[len-2] == 0 && data[len-1] == LINE_CMD_EOL; - - return line; -} - -void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line) -{ - g_return_if_fail(buffer != NULL); - g_return_if_fail(line != NULL); - - if (buffer->first_line == line) - buffer->first_line = line->next; - if (line->prev != NULL) - line->prev->next = line->next; - if (line->next != NULL) - line->next->prev = line->prev; - - if (buffer->cur_line == line) { - buffer->cur_line = line->next != NULL ? - line->next : line->prev; - } - - line->prev = line->next = NULL; - - buffer->lines_count--; - textbuffer_line_unref(buffer, line); -} - -/* Removes all lines from buffer, ignoring reference counters */ -void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer) -{ - GSList *tmp; - LINE_REC *line; - - g_return_if_fail(buffer != NULL); - - for (tmp = buffer->text_chunks; tmp != NULL; tmp = tmp->next) - g_mem_chunk_free(text_chunk, tmp->data); - g_slist_free(buffer->text_chunks); - buffer->text_chunks = NULL; - - while (buffer->first_line != NULL) { - line = buffer->first_line->next; - g_mem_chunk_free(line_chunk, buffer->first_line); - buffer->first_line = line; - } - buffer->lines_count = 0; - - buffer->cur_line = NULL; - buffer->cur_text = NULL; - - buffer->last_eol = TRUE; -} - -static void set_color(GString *str, int cmd, int *last_fg, int *last_bg) -{ - if (cmd & LINE_COLOR_DEFAULT) { - g_string_sprintfa(str, "\004%c", FORMAT_STYLE_DEFAULTS); - - /* need to reset the fg/bg color */ - if (cmd & LINE_COLOR_BG) { - *last_bg = -1; - if (*last_fg != -1) { - g_string_sprintfa(str, "\004%c%c", - *last_fg, - FORMAT_COLOR_NOCHANGE); - } - } else { - *last_fg = -1; - if (*last_bg != -1) { - g_string_sprintfa(str, "\004%c%c", - FORMAT_COLOR_NOCHANGE, - *last_bg); - } - } - return; - } - - if ((cmd & LINE_COLOR_BG) == 0) { - /* change foreground color */ - *last_fg = (cmd & 0x0f)+'0'; - g_string_sprintfa(str, "\004%c%c", *last_fg, - FORMAT_COLOR_NOCHANGE); - } else { - /* change background color */ - *last_bg = (cmd & 0x0f)+'0'; - g_string_sprintfa(str, "\004%c%c", - FORMAT_COLOR_NOCHANGE, *last_bg); - } -} - -void textbuffer_line2text(LINE_REC *line, int coloring, GString *str) -{ - unsigned char cmd, *ptr, *tmp; - int last_fg, last_bg; - - g_return_if_fail(line != NULL); - g_return_if_fail(str != NULL); - - g_string_truncate(str, 0); - - last_fg = last_bg = -1; - for (ptr = line->text;;) { - if (*ptr != 0) { - g_string_append_c(str, (char) *ptr); - ptr++; - continue; - } - - ptr++; - cmd = *ptr; - ptr++; - - if (cmd == LINE_CMD_EOL || cmd == LINE_CMD_FORMAT) { - /* end of line */ - break; - } - - if (cmd == LINE_CMD_CONTINUE) { - /* line continues in another address.. */ - memcpy(&tmp, ptr, sizeof(unsigned char *)); - ptr = tmp; - continue; - } - - if (!coloring) { - /* no colors, skip coloring commands */ - continue; - } - - if ((cmd & 0x80) == 0) { - /* set color */ - set_color(str, cmd, &last_fg, &last_bg); - } else switch (cmd) { - case LINE_CMD_UNDERLINE: - g_string_append_c(str, 31); - break; - case LINE_CMD_REVERSE: - g_string_append_c(str, 22); - break; - case LINE_CMD_COLOR0: - g_string_sprintfa(str, "\004%c%c", - '0', FORMAT_COLOR_NOCHANGE); - break; - case LINE_CMD_INDENT: - break; - case LINE_CMD_INDENT_FUNC: - ptr += sizeof(void *); - break; - } - } -} - -GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, - int level, int nolevel, const char *text, - int before, int after, - int regexp, int fullword, int case_sensitive) -{ -#ifdef HAVE_REGEX_H - regex_t preg; -#endif - LINE_REC *line, *pre_line; - GList *matches; - GString *str; - int i, match_after, line_matched; - - g_return_val_if_fail(buffer != NULL, NULL); - g_return_val_if_fail(text != NULL, NULL); - - if (regexp) { -#ifdef HAVE_REGEX_H - int flags = REG_EXTENDED | REG_NOSUB | - (case_sensitive ? 0 : REG_ICASE); - if (regcomp(&preg, text, flags) != 0) - return NULL; -#else - return NULL; -#endif - } - - matches = NULL; match_after = 0; - str = g_string_new(NULL); - - line = startline != NULL ? startline : buffer->first_line; - - for (; line != NULL; line = line->next) { - if ((line->info.level & level) == 0 || - (line->info.level & nolevel) != 0) - continue; - - if (*text == '\0') { - /* no search word, everything matches */ - textbuffer_line_ref(line); - matches = g_list_append(matches, line); - continue; - } - - textbuffer_line2text(line, FALSE, str); - - line_matched = -#ifdef HAVE_REGEX_H - regexp ? regexec(&preg, str->str, 0, NULL, 0) == 0 : -#endif - fullword ? strstr_full_case(str->str, text, !case_sensitive) != NULL : - case_sensitive ? strstr(str->str, text) != NULL : - stristr(str->str, text) != NULL; - if (line_matched) { - /* add the -before lines */ - pre_line = line; - for (i = 0; i < before; i++) { - if (pre_line->prev == NULL || - g_list_find(matches, pre_line->prev) != NULL) - break; - pre_line = pre_line->prev; - } - - for (; pre_line != line; pre_line = pre_line->next) { - textbuffer_line_ref(pre_line); - matches = g_list_append(matches, pre_line); - } - - match_after = after; - } - - if (line_matched || match_after > 0) { - /* matched */ - textbuffer_line_ref(line); - matches = g_list_append(matches, line); - - if ((!line_matched && --match_after == 0) || - (line_matched && match_after == 0 && before > 0)) - matches = g_list_append(matches, NULL); - } - } -#ifdef HAVE_REGEX_H - if (regexp) regfree(&preg); -#endif - g_string_free(str, TRUE); - return matches; -} - -void textbuffer_init(void) -{ - buffer_chunk = g_mem_chunk_new("text buffer chunk", - sizeof(TEXT_BUFFER_REC), - sizeof(TEXT_BUFFER_REC)*32, G_ALLOC_AND_FREE); - line_chunk = g_mem_chunk_new("line chunk", sizeof(LINE_REC), - sizeof(LINE_REC)*1024, G_ALLOC_AND_FREE); - text_chunk = g_mem_chunk_new("text chunk", sizeof(TEXT_CHUNK_REC), - sizeof(TEXT_CHUNK_REC)*32, G_ALLOC_AND_FREE); -} - -void textbuffer_deinit(void) -{ - g_mem_chunk_destroy(buffer_chunk); - g_mem_chunk_destroy(line_chunk); - g_mem_chunk_destroy(text_chunk); -}