Holiday coding log :)
[blender.git] / source / blender / editors / space_text / text_python.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  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_text/text_python.c
28  *  \ingroup sptext
29  */
30
31
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "DNA_screen_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_text_types.h"
39 #include "DNA_userdef_types.h"
40
41 #include "BKE_blender.h"
42 #include "BKE_suggestions.h"
43 #include "BKE_text.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_utildefines.h"
47
48 #include "WM_types.h"
49
50 #include "text_intern.h"
51
52 int text_do_suggest_select(SpaceText *st, ARegion *ar)
53 {
54         SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
55         TextLine *tmp;
56         int l, x, y, w, h, i;
57         int tgti, *top;
58         int mval[2] = {0, 0};
59         
60         if (!st || !st->text) return 0;
61         if (!texttool_text_is_active(st->text)) return 0;
62
63         first = texttool_suggest_first();
64         last = texttool_suggest_last();
65         /* sel = texttool_suggest_selected(); */ /* UNUSED */
66         top = texttool_suggest_top();
67
68         if (!last || !first)
69                 return 0;
70
71         /* Count the visible lines to the cursor */
72         for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
73         if (l < 0) return 0;
74
75         text_update_character_width(st);
76         
77         if (st->showlinenrs) {
78                 x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
79         }
80         else {
81                 x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
82         }
83         y = ar->winy - st->lheight_dpi * l - 2;
84
85         w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
86         h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
87
88         // XXX getmouseco_areawin(mval);
89
90         if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
91                 return 0;
92
93         /* Work out which of the items is at the top of the visible list */
94         for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
95
96         /* Work out the target item index in the visible list */
97         tgti = (y - mval[1] - 4) / st->lheight_dpi;
98         if (tgti < 0 || tgti > SUGG_LIST_SIZE)
99                 return 1;
100
101         for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
102         if (item)
103                 texttool_suggest_select(item);
104         return 1;
105 }
106
107 void text_pop_suggest_list(void)
108 {
109         SuggItem *item, *sel;
110         int *top, i;
111
112         item = texttool_suggest_first();
113         sel = texttool_suggest_selected();
114         top = texttool_suggest_top();
115
116         i = 0;
117         while (item && item != sel) {
118                 item = item->next;
119                 i++;
120         }
121         if (i > *top + SUGG_LIST_SIZE - 1)
122                 *top = i - SUGG_LIST_SIZE + 1;
123         else if (i < *top)
124                 *top = i;
125 }
126
127 static void get_suggest_prefix(Text *text, int offset)
128 {
129         int i, len;
130         char *line, tmp[256];
131
132         if (!text) return;
133         if (!texttool_text_is_active(text)) return;
134
135         line = text->curl->line;
136         for (i = text->curc - 1 + offset; i >= 0; i--)
137                 if (!text_check_identifier(line[i]))
138                         break;
139         i++;
140         len = text->curc - i + offset;
141         if (len > 255) {
142                 printf("Suggestion prefix too long\n");
143                 len = 255;
144         }
145         BLI_strncpy(tmp, line + i, len);
146         tmp[len] = '\0';
147         texttool_suggest_prefix(tmp);
148 }
149
150 static void confirm_suggestion(Text *text, int skipleft)
151 {
152         SuggItem *sel;
153         int i, over = 0;
154         char *line;
155
156         if (!text) return;
157         if (!texttool_text_is_active(text)) return;
158
159         sel = texttool_suggest_selected();
160         if (!sel) return;
161
162         line = text->curl->line;
163         i = text->curc - skipleft - 1;
164         while (i >= 0) {
165                 if (!text_check_identifier(line[i]))
166                         break;
167                 over++;
168                 i--;
169         }
170
171         for (i = 0; i < skipleft; i++)
172                 txt_move_left(text, 0);
173         for (i = 0; i < over; i++)
174                 txt_move_left(text, 1);
175
176         txt_insert_buf(text, sel->name);
177         
178         for (i = 0; i < skipleft; i++)
179                 txt_move_right(text, 0);
180
181         texttool_text_clear();
182 }
183
184 // XXX
185 #define LR_SHIFTKEY 0
186 #define LR_ALTKEY 0
187 #define LR_CTRLKEY 0
188
189 // XXX
190 static int doc_scroll = 0;
191
192 static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
193 {
194         ARegion *ar = NULL; // XXX
195         int qual = 0; // XXX
196         int draw = 0, tools = 0, swallow = 0, scroll = 1;
197         if (!texttool_text_is_active(st->text)) return 0;
198         if (!st->text || st->text->id.lib) return 0;
199
200         if (st->doplugins && texttool_text_is_active(st->text)) {
201                 if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
202                 if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
203         }
204
205         if (ascii) {
206                 if (tools & TOOL_SUGG_LIST) {
207                         if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
208                                 confirm_suggestion(st->text, 0);
209                                 text_update_line_edited(st->text->curl);
210                         }
211                         else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
212                                 get_suggest_prefix(st->text, 0);
213                                 text_pop_suggest_list();
214                                 swallow = 1;
215                                 draw = 1;
216                         }
217                 }
218                 if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
219
220         }
221         else if (val == 1 && evnt) {
222                 switch (evnt) {
223                         case LEFTMOUSE:
224                                 if (text_do_suggest_select(st, ar))
225                                         swallow = 1;
226                                 else {
227                                         if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
228                                         if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
229                                 }
230                                 draw = 1;
231                                 break;
232                         case MIDDLEMOUSE:
233                                 if (text_do_suggest_select(st, ar)) {
234                                         confirm_suggestion(st->text, 0);
235                                         text_update_line_edited(st->text->curl);
236                                         swallow = 1;
237                                 }
238                                 else {
239                                         if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
240                                         if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
241                                 }
242                                 draw = 1;
243                                 break;
244                         case ESCKEY:
245                                 draw = swallow = 1;
246                                 if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
247                                 else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
248                                 else draw = swallow = 0;
249                                 break;
250                         case RETKEY:
251                                 if (tools & TOOL_SUGG_LIST) {
252                                         confirm_suggestion(st->text, 0);
253                                         text_update_line_edited(st->text->curl);
254                                         swallow = 1;
255                                         draw = 1;
256                                 }
257                                 if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
258                                 break;
259                         case LEFTARROWKEY:
260                         case BACKSPACEKEY:
261                                 if (tools & TOOL_SUGG_LIST) {
262                                         if (qual)
263                                                 texttool_suggest_clear();
264                                         else {
265                                                 /* Work out which char we are about to delete/pass */
266                                                 if (st->text->curl && st->text->curc > 0) {
267                                                         char ch = st->text->curl->line[st->text->curc - 1];
268                                                         if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
269                                                                 get_suggest_prefix(st->text, -1);
270                                                                 text_pop_suggest_list();
271                                                         }
272                                                         else
273                                                                 texttool_suggest_clear();
274                                                 }
275                                                 else
276                                                         texttool_suggest_clear();
277                                         }
278                                 }
279                                 if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
280                                 break;
281                         case RIGHTARROWKEY:
282                                 if (tools & TOOL_SUGG_LIST) {
283                                         if (qual)
284                                                 texttool_suggest_clear();
285                                         else {
286                                                 /* Work out which char we are about to pass */
287                                                 if (st->text->curl && st->text->curc < st->text->curl->len) {
288                                                         char ch = st->text->curl->line[st->text->curc + 1];
289                                                         if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
290                                                                 get_suggest_prefix(st->text, 1);
291                                                                 text_pop_suggest_list();
292                                                         }
293                                                         else
294                                                                 texttool_suggest_clear();
295                                                 }
296                                                 else
297                                                         texttool_suggest_clear();
298                                         }
299                                 }
300                                 if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
301                                 break;
302                         case PAGEDOWNKEY:
303                                 scroll = SUGG_LIST_SIZE - 1;
304                         case WHEELDOWNMOUSE:
305                         case DOWNARROWKEY:
306                                 if (tools & TOOL_DOCUMENT) {
307                                         doc_scroll++;
308                                         swallow = 1;
309                                         draw = 1;
310                                         break;
311                                 }
312                                 else if (tools & TOOL_SUGG_LIST) {
313                                         SuggItem *sel = texttool_suggest_selected();
314                                         if (!sel) {
315                                                 texttool_suggest_select(texttool_suggest_first());
316                                         }
317                                         else {
318                                                 while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
319                                                         texttool_suggest_select(sel->next);
320                                                         sel = sel->next;
321                                                 }
322                                         }
323                                         text_pop_suggest_list();
324                                         swallow = 1;
325                                         draw = 1;
326                                         break;
327                                 }
328                         case PAGEUPKEY:
329                                 scroll = SUGG_LIST_SIZE - 1;
330                         case WHEELUPMOUSE:
331                         case UPARROWKEY:
332                                 if (tools & TOOL_DOCUMENT) {
333                                         if (doc_scroll > 0) doc_scroll--;
334                                         swallow = 1;
335                                         draw = 1;
336                                         break;
337                                 }
338                                 else if (tools & TOOL_SUGG_LIST) {
339                                         SuggItem *sel = texttool_suggest_selected();
340                                         while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
341                                                 texttool_suggest_select(sel->prev);
342                                                 sel = sel->prev;
343                                         }
344                                         text_pop_suggest_list();
345                                         swallow = 1;
346                                         draw = 1;
347                                         break;
348                                 }
349                         case RIGHTSHIFTKEY:
350                         case LEFTSHIFTKEY:
351                                 break;
352                         default:
353                                 if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
354                                 if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
355                 }
356         }
357
358         if (draw) {
359                 // XXX redraw_alltext();
360         }
361
362         return swallow;
363 }