Camera tracking: libmv distortion API now also uses camera intrinsics
[blender.git] / source / blender / blenkernel / intern / suggestions.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008, Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Ian Thompson.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/suggestions.c
29  *  \ingroup bke
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 #include "MEM_guardedalloc.h"
38 #include "DNA_text_types.h"
39 #include "BKE_suggestions.h"
40
41 /**********************/
42 /* Static definitions */
43 /**********************/
44
45 static Text *activeToolText = NULL;
46 static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL};
47 static char *documentation = NULL;
48 //static int doc_lines = 0;
49
50 /* TODO, replace with  BLI_strncasecmp() */
51 static int txttl_cmp(const char *first, const char *second, int len)
52 {
53         int cmp, i;
54         for (cmp = 0, i = 0; i < len; i++) {
55                 if ( (cmp = toupper(first[i]) - toupper(second[i])) ) {
56                         break;
57                 }
58         }
59         return cmp;
60 }
61
62 static void txttl_free_suggest(void)
63 {
64         SuggItem *item, *prev;
65         for (item = suggestions.last; item; item = prev) {
66                 prev = item->prev;
67                 MEM_freeN(item);
68         }
69         suggestions.first = suggestions.last = NULL;
70         suggestions.firstmatch = suggestions.lastmatch = NULL;
71         suggestions.selected = NULL;
72         suggestions.top = 0;
73 }
74
75 static void txttl_free_docs(void)
76 {
77         if (documentation) {
78                 MEM_freeN(documentation);
79                 documentation = NULL;
80         }
81 }
82
83 /**************************/
84 /* General tool functions */
85 /**************************/
86
87 void free_texttools(void)
88 {
89         txttl_free_suggest();
90         txttl_free_docs();
91 }
92
93 void texttool_text_set_active(Text *text)
94 {
95         if (activeToolText == text) return;
96         texttool_text_clear();
97         activeToolText = text;
98 }
99
100 void texttool_text_clear(void)
101 {
102         free_texttools();
103         activeToolText = NULL;
104 }
105
106 short texttool_text_is_active(Text *text)
107 {
108         return activeToolText == text ? 1 : 0;
109 }
110
111 /***************************/
112 /* Suggestion list methods */
113 /***************************/
114
115 void texttool_suggest_add(const char *name, char type)
116 {
117         const int len = strlen(name);
118         int cmp;
119         SuggItem *newitem, *item;
120
121         newitem = MEM_mallocN(sizeof(SuggItem) + len + 1, "SuggItem");
122         if (!newitem) {
123                 printf("Failed to allocate memory for suggestion.\n");
124                 return;
125         }
126
127         newitem->name = (char *) (newitem + 1);
128         memcpy(newitem->name, name, len + 1);
129         newitem->type = type;
130         newitem->prev = newitem->next = NULL;
131
132         /* Perform simple linear search for ordered storage */
133         if (!suggestions.first || !suggestions.last) {
134                 suggestions.first = suggestions.last = newitem;
135         }
136         else {
137                 cmp = -1;
138                 for (item = suggestions.last; item; item = item->prev) {
139                         cmp = txttl_cmp(name, item->name, len);
140
141                         /* Newitem comes after this item, insert here */
142                         if (cmp >= 0) {
143                                 newitem->prev = item;
144                                 if (item->next)
145                                         item->next->prev = newitem;
146                                 newitem->next = item->next;
147                                 item->next = newitem;
148
149                                 /* At last item, set last pointer here */
150                                 if (item == suggestions.last)
151                                         suggestions.last = newitem;
152                                 break;
153                         }
154                 }
155                 /* Reached beginning of list, insert before first */
156                 if (cmp < 0) {
157                         newitem->next = suggestions.first;
158                         suggestions.first->prev = newitem;
159                         suggestions.first = newitem;
160                 }
161         }
162         suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL;
163         suggestions.top = 0;
164 }
165
166 void texttool_suggest_prefix(const char *prefix, const int prefix_len)
167 {
168         SuggItem *match, *first, *last;
169         int cmp, top = 0;
170
171         if (!suggestions.first) return;
172         if (prefix_len == 0) {
173                 suggestions.selected = suggestions.firstmatch = suggestions.first;
174                 suggestions.lastmatch = suggestions.last;
175                 return;
176         }
177         
178         first = last = NULL;
179         for (match = suggestions.first; match; match = match->next) {
180                 cmp = txttl_cmp(prefix, match->name, prefix_len);
181                 if (cmp == 0) {
182                         if (!first) {
183                                 first = match;
184                                 suggestions.top = top;
185                         }
186                 }
187                 else if (cmp < 0) {
188                         if (!last) {
189                                 last = match->prev;
190                                 break;
191                         }
192                 }
193                 top++;
194         }
195         if (first) {
196                 if (!last) last = suggestions.last;
197                 suggestions.firstmatch = first;
198                 suggestions.lastmatch = last;
199                 suggestions.selected = first;
200         }
201         else {
202                 suggestions.firstmatch = NULL;
203                 suggestions.lastmatch = NULL;
204                 suggestions.selected = NULL;
205                 suggestions.top = 0;
206         }
207 }
208
209 void texttool_suggest_clear(void)
210 {
211         txttl_free_suggest();
212 }
213
214 SuggItem *texttool_suggest_first(void)
215 {
216         return suggestions.firstmatch;
217 }
218
219 SuggItem *texttool_suggest_last(void)
220 {
221         return suggestions.lastmatch;
222 }
223
224 void texttool_suggest_select(SuggItem *sel)
225 {
226         suggestions.selected = sel;
227 }
228
229 SuggItem *texttool_suggest_selected(void)
230 {
231         return suggestions.selected;
232 }
233
234 int *texttool_suggest_top(void)
235 {
236         return &suggestions.top;
237 }
238
239 /*************************/
240 /* Documentation methods */
241 /*************************/
242
243 void texttool_docs_show(const char *docs)
244 {
245         int len;
246
247         if (!docs) return;
248
249         len = strlen(docs);
250
251         if (documentation) {
252                 MEM_freeN(documentation);
253                 documentation = NULL;
254         }
255
256         /* Ensure documentation ends with a '\n' */
257         if (docs[len - 1] != '\n') {
258                 documentation = MEM_mallocN(len + 2, "Documentation");
259                 strncpy(documentation, docs, len);
260                 documentation[len++] = '\n';
261         }
262         else {
263                 documentation = MEM_mallocN(len + 1, "Documentation");
264                 strncpy(documentation, docs, len);
265         }
266         documentation[len] = '\0';
267 }
268
269 char *texttool_docs_get(void)
270 {
271         return documentation;
272 }
273
274 void texttool_docs_clear(void)
275 {
276         txttl_free_docs();
277 }