resolve some compiler warnings with intel c/c++ compiler
[blender.git] / source / blender / blenkernel / intern / suggestions.c
index ae0c7baa1467dcc20bdbf9c946e74a8cf55b4bed..6530909336ccb50042f01b775e46fb515cc57a80 100644 (file)
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): none yet.
+ * 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 "BKE_text.h"
 #include "BKE_suggestions.h"
 
-static SuggList suggestions= {NULL, NULL, NULL, NULL};
-static Text *suggText = NULL;
+/**********************/
+/* Static definitions */
+/**********************/
 
-void free_suggestions() {
+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;
@@ -48,10 +65,47 @@ void free_suggestions() {
        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;
 }
 
-void suggest_add(const char *name, char type) {
-       SuggItem *newitem;
+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) {
@@ -60,23 +114,48 @@ void suggest_add(const char *name, char type) {
        }
 
        newitem->name = (char *) (newitem + 1);
-       strcpy(newitem->name, name);
+       len = strlen(name);
+       strncpy(newitem->name, name, len);
+       newitem->name[len] = '\0';
        newitem->type = type;
        newitem->prev = newitem->next = NULL;
 
-       if (!suggestions.first) {
+       /* Perform simple linear search for ordered storage */
+       if (!suggestions.first || !suggestions.last) {
                suggestions.first = suggestions.last = newitem;
-               suggestions.selected = newitem;
        } else {
-               newitem->prev = suggestions.last;
-               suggestions.last->next = newitem;
-               suggestions.last = newitem;
+               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 suggest_prefix(const char *prefix) {
+void texttool_suggest_prefix(const char *prefix) {
        SuggItem *match, *first, *last;
-       int cmp, len = strlen(prefix);
+       int cmp, len = strlen(prefix), top = 0;
 
        if (!suggestions.first) return;
        if (len==0) {
@@ -87,51 +166,89 @@ void suggest_prefix(const char *prefix) {
        
        first = last = NULL;
        for (match=suggestions.first; match; match=match->next) {
-               cmp = strncmp(prefix, match->name, len);
+               cmp = txttl_cmp(prefix, match->name, len);
                if (cmp==0) {
-                       if (!first)
+                       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.selected = suggestions.firstmatch = first;
+               suggestions.firstmatch = first;
                suggestions.lastmatch = last;
+               suggestions.selected = first;
        } else {
-               suggestions.selected = suggestions.firstmatch = suggestions.lastmatch = NULL;
+               suggestions.firstmatch = NULL;
+               suggestions.lastmatch = NULL;
+               suggestions.selected = NULL;
+               suggestions.top = 0;
        }
 }
 
-SuggItem *suggest_first() {
+void texttool_suggest_clear() {
+       txttl_free_suggest();
+}
+
+SuggItem *texttool_suggest_first() {
        return suggestions.firstmatch;
 }
 
-SuggItem *suggest_last() {
+SuggItem *texttool_suggest_last() {
        return suggestions.lastmatch;
 }
 
-void suggest_set_text(Text *text) {
-       suggText = text;
+void texttool_suggest_select(SuggItem *sel) {
+       suggestions.selected = sel;
 }
 
-void suggest_clear_text() {
-       free_suggestions();
-       suggText = NULL;
+SuggItem *texttool_suggest_selected() {
+       return suggestions.selected;
 }
 
-short suggest_is_active(Text *text) {
-       return suggText==text ? 1 : 0;
+int *texttool_suggest_top() {
+       return &suggestions.top;
 }
 
-void suggest_set_selected(SuggItem *sel) {
-       suggestions.selected = sel;
+/*************************/
+/* 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';
 }
 
-SuggItem *suggest_get_selected() {
-       return suggestions.selected;
+char *texttool_docs_get() {
+       return documentation;
+}
+
+void texttool_docs_clear() {
+       txttl_free_docs();
 }