Blender  V2.59
suggestions.c
Go to the documentation of this file.
00001 /*
00002  * $Id: suggestions.c 35247 2011-02-27 20:40:57Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2008, Blender Foundation
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): Ian Thompson.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <ctype.h>
00038 
00039 #include "MEM_guardedalloc.h"
00040 #include "DNA_text_types.h"
00041 #include "BKE_suggestions.h"
00042 
00043 /**********************/
00044 /* Static definitions */
00045 /**********************/
00046 
00047 static Text *activeToolText = NULL;
00048 static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL};
00049 static char *documentation = NULL;
00050 //static int doc_lines = 0;
00051 
00052 static int txttl_cmp(const char *first, const char *second, int len) {  
00053         int cmp, i;
00054         for (cmp=0, i=0; i<len; i++) {
00055                 if ( (cmp= toupper(first[i])-toupper(second[i])) ) {
00056                         break;
00057                 }
00058         }
00059         return cmp;
00060 }
00061 
00062 static void txttl_free_suggest(void) {
00063         SuggItem *item, *prev;
00064         for (item = suggestions.last; item; item=prev) {
00065                 prev = item->prev;
00066                 MEM_freeN(item);
00067         }
00068         suggestions.first = suggestions.last = NULL;
00069         suggestions.firstmatch = suggestions.lastmatch = NULL;
00070         suggestions.selected = NULL;
00071         suggestions.top = 0;
00072 }
00073 
00074 static void txttl_free_docs(void) {
00075         if (documentation) {
00076                 MEM_freeN(documentation);
00077                 documentation = NULL;
00078         }
00079 }
00080 
00081 /**************************/
00082 /* General tool functions */
00083 /**************************/
00084 
00085 void free_texttools(void) {
00086         txttl_free_suggest();
00087         txttl_free_docs();
00088 }
00089 
00090 void texttool_text_set_active(Text *text) {
00091         if (activeToolText == text) return;
00092         texttool_text_clear();
00093         activeToolText = text;
00094 }
00095 
00096 void texttool_text_clear(void) {
00097         free_texttools();
00098         activeToolText = NULL;
00099 }
00100 
00101 short texttool_text_is_active(Text *text) {
00102         return activeToolText==text ? 1 : 0;
00103 }
00104 
00105 /***************************/
00106 /* Suggestion list methods */
00107 /***************************/
00108 
00109 void texttool_suggest_add(const char *name, char type) {
00110         SuggItem *newitem, *item;
00111         int len, cmp;
00112 
00113         newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem");
00114         if (!newitem) {
00115                 printf("Failed to allocate memory for suggestion.\n");
00116                 return;
00117         }
00118 
00119         newitem->name = (char *) (newitem + 1);
00120         len = strlen(name);
00121         strncpy(newitem->name, name, len);
00122         newitem->name[len] = '\0';
00123         newitem->type = type;
00124         newitem->prev = newitem->next = NULL;
00125 
00126         /* Perform simple linear search for ordered storage */
00127         if (!suggestions.first || !suggestions.last) {
00128                 suggestions.first = suggestions.last = newitem;
00129         } else {
00130                 cmp = -1;
00131                 for (item=suggestions.last; item; item=item->prev) {
00132                         cmp = txttl_cmp(name, item->name, len);
00133 
00134                         /* Newitem comes after this item, insert here */
00135                         if (cmp >= 0) {
00136                                 newitem->prev = item;
00137                                 if (item->next)
00138                                         item->next->prev = newitem;
00139                                 newitem->next = item->next;
00140                                 item->next = newitem;
00141 
00142                                 /* At last item, set last pointer here */
00143                                 if (item == suggestions.last)
00144                                         suggestions.last = newitem;
00145                                 break;
00146                         }
00147                 }
00148                 /* Reached beginning of list, insert before first */
00149                 if (cmp < 0) {
00150                         newitem->next = suggestions.first;
00151                         suggestions.first->prev = newitem;
00152                         suggestions.first = newitem;
00153                 }
00154         }
00155         suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL;
00156         suggestions.top= 0;
00157 }
00158 
00159 void texttool_suggest_prefix(const char *prefix) {
00160         SuggItem *match, *first, *last;
00161         int cmp, len = strlen(prefix), top = 0;
00162 
00163         if (!suggestions.first) return;
00164         if (len==0) {
00165                 suggestions.selected = suggestions.firstmatch = suggestions.first;
00166                 suggestions.lastmatch = suggestions.last;
00167                 return;
00168         }
00169         
00170         first = last = NULL;
00171         for (match=suggestions.first; match; match=match->next) {
00172                 cmp = txttl_cmp(prefix, match->name, len);
00173                 if (cmp==0) {
00174                         if (!first) {
00175                                 first = match;
00176                                 suggestions.top = top;
00177                         }
00178                 } else if (cmp<0) {
00179                         if (!last) {
00180                                 last = match->prev;
00181                                 break;
00182                         }
00183                 }
00184                 top++;
00185         }
00186         if (first) {
00187                 if (!last) last = suggestions.last;
00188                 suggestions.firstmatch = first;
00189                 suggestions.lastmatch = last;
00190                 suggestions.selected = first;
00191         } else {
00192                 suggestions.firstmatch = NULL;
00193                 suggestions.lastmatch = NULL;
00194                 suggestions.selected = NULL;
00195                 suggestions.top = 0;
00196         }
00197 }
00198 
00199 void texttool_suggest_clear(void) {
00200         txttl_free_suggest();
00201 }
00202 
00203 SuggItem *texttool_suggest_first(void) {
00204         return suggestions.firstmatch;
00205 }
00206 
00207 SuggItem *texttool_suggest_last(void) {
00208         return suggestions.lastmatch;
00209 }
00210 
00211 void texttool_suggest_select(SuggItem *sel) {
00212         suggestions.selected = sel;
00213 }
00214 
00215 SuggItem *texttool_suggest_selected(void) {
00216         return suggestions.selected;
00217 }
00218 
00219 int *texttool_suggest_top(void) {
00220         return &suggestions.top;
00221 }
00222 
00223 /*************************/
00224 /* Documentation methods */
00225 /*************************/
00226 
00227 void texttool_docs_show(const char *docs) {
00228         int len;
00229 
00230         if (!docs) return;
00231 
00232         len = strlen(docs);
00233 
00234         if (documentation) {
00235                 MEM_freeN(documentation);
00236                 documentation = NULL;
00237         }
00238 
00239         /* Ensure documentation ends with a '\n' */
00240         if (docs[len-1] != '\n') {
00241                 documentation = MEM_mallocN(len+2, "Documentation");
00242                 strncpy(documentation, docs, len);
00243                 documentation[len++] = '\n';
00244         } else {
00245                 documentation = MEM_mallocN(len+1, "Documentation");
00246                 strncpy(documentation, docs, len);
00247         }
00248         documentation[len] = '\0';
00249 }
00250 
00251 char *texttool_docs_get(void) {
00252         return documentation;
00253 }
00254 
00255 void texttool_docs_clear(void) {
00256         txttl_free_docs();
00257 }