Blender V2.61 - r43446
|
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 }