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