diff options
Diffstat (limited to 'source/blender/blenkernel/intern/suggestions.c')
-rw-r--r-- | source/blender/blenkernel/intern/suggestions.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c new file mode 100644 index 00000000000..6530909336c --- /dev/null +++ b/source/blender/blenkernel/intern/suggestions.c @@ -0,0 +1,254 @@ +/** + * $Id: $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * The Original Code is Copyright (C) 2008, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Ian Thompson. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "DNA_text_types.h" +#include "BKE_text.h" +#include "BKE_suggestions.h" + +/**********************/ +/* Static definitions */ +/**********************/ + +static Text *activeToolText = NULL; +static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; +static char *documentation = NULL; +//static int doc_lines = 0; + +static int txttl_cmp(const char *first, const char *second, int len) { + int cmp, i; + for (cmp=0, i=0; i<len; i++) { + if ( (cmp= toupper(first[i])-toupper(second[i])) ) { + break; + } + } + return cmp; +} + +static void txttl_free_suggest() { + SuggItem *item, *prev; + for (item = suggestions.last; item; item=prev) { + prev = item->prev; + MEM_freeN(item); + } + suggestions.first = suggestions.last = NULL; + suggestions.firstmatch = suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; +} + +static void txttl_free_docs() { + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } +} + +/**************************/ +/* General tool functions */ +/**************************/ + +void free_texttools() { + txttl_free_suggest(); + txttl_free_docs(); +} + +void texttool_text_set_active(Text *text) { + if (activeToolText == text) return; + texttool_text_clear(); + activeToolText = text; +} + +void texttool_text_clear() { + free_texttools(); + activeToolText = NULL; +} + +short texttool_text_is_active(Text *text) { + return activeToolText==text ? 1 : 0; +} + +/***************************/ +/* Suggestion list methods */ +/***************************/ + +void texttool_suggest_add(const char *name, char type) { + SuggItem *newitem, *item; + int len, cmp; + + newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + if (!newitem) { + printf("Failed to allocate memory for suggestion.\n"); + return; + } + + newitem->name = (char *) (newitem + 1); + len = strlen(name); + strncpy(newitem->name, name, len); + newitem->name[len] = '\0'; + newitem->type = type; + newitem->prev = newitem->next = NULL; + + /* Perform simple linear search for ordered storage */ + if (!suggestions.first || !suggestions.last) { + suggestions.first = suggestions.last = newitem; + } else { + cmp = -1; + for (item=suggestions.last; item; item=item->prev) { + cmp = txttl_cmp(name, item->name, len); + + /* Newitem comes after this item, insert here */ + if (cmp >= 0) { + newitem->prev = item; + if (item->next) + item->next->prev = newitem; + newitem->next = item->next; + item->next = newitem; + + /* At last item, set last pointer here */ + if (item == suggestions.last) + suggestions.last = newitem; + break; + } + } + /* Reached beginning of list, insert before first */ + if (cmp < 0) { + newitem->next = suggestions.first; + suggestions.first->prev = newitem; + suggestions.first = newitem; + } + } + suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL; + suggestions.top= 0; +} + +void texttool_suggest_prefix(const char *prefix) { + SuggItem *match, *first, *last; + int cmp, len = strlen(prefix), top = 0; + + if (!suggestions.first) return; + if (len==0) { + suggestions.selected = suggestions.firstmatch = suggestions.first; + suggestions.lastmatch = suggestions.last; + return; + } + + first = last = NULL; + for (match=suggestions.first; match; match=match->next) { + cmp = txttl_cmp(prefix, match->name, len); + if (cmp==0) { + if (!first) { + first = match; + suggestions.top = top; + } + } else if (cmp<0) { + if (!last) { + last = match->prev; + break; + } + } + top++; + } + if (first) { + if (!last) last = suggestions.last; + suggestions.firstmatch = first; + suggestions.lastmatch = last; + suggestions.selected = first; + } else { + suggestions.firstmatch = NULL; + suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; + } +} + +void texttool_suggest_clear() { + txttl_free_suggest(); +} + +SuggItem *texttool_suggest_first() { + return suggestions.firstmatch; +} + +SuggItem *texttool_suggest_last() { + return suggestions.lastmatch; +} + +void texttool_suggest_select(SuggItem *sel) { + suggestions.selected = sel; +} + +SuggItem *texttool_suggest_selected() { + return suggestions.selected; +} + +int *texttool_suggest_top() { + return &suggestions.top; +} + +/*************************/ +/* Documentation methods */ +/*************************/ + +void texttool_docs_show(const char *docs) { + int len; + + if (!docs) return; + + len = strlen(docs); + + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } + + /* Ensure documentation ends with a '\n' */ + if (docs[len-1] != '\n') { + documentation = MEM_mallocN(len+2, "Documentation"); + strncpy(documentation, docs, len); + documentation[len++] = '\n'; + } else { + documentation = MEM_mallocN(len+1, "Documentation"); + strncpy(documentation, docs, len); + } + documentation[len] = '\0'; +} + +char *texttool_docs_get() { + return documentation; +} + +void texttool_docs_clear() { + txttl_free_docs(); +} |