Files
test/source/blender/blenkernel/intern/suggestions.c
Andre Susano Pinto 656ee61718 Merge from trunk
(The last time there was some files missing due to failed connection to svn server while merging.. thats why this stuff of reverting last merge and redoing it)

svn merge -r 16231:16608 https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-09-19 14:15:36 +00:00

255 lines
5.8 KiB
C

/**
* $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();
}