Blender V2.61 - r43446

suggestions.c

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