soc-2008-mxcurioni: foundations for Freestyle as a render layer - new UI buttons...
[blender.git] / source / blender / src / drawtext.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #ifndef _WIN32
40 #include <unistd.h>
41 #else
42 #include <io.h>
43 #include "BLI_winstuff.h"
44 #endif   
45 #include "MEM_guardedalloc.h"
46 #include "PIL_time.h"
47
48 #include "BMF_Api.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52
53 #include "DNA_text_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_userdef_types.h"
57
58 #include "BKE_utildefines.h"
59 #include "BKE_text.h"
60 #include "BKE_global.h"
61 #include "BKE_main.h"
62 #include "BKE_node.h"
63
64 #include "BIF_gl.h"
65 #include "BIF_glutil.h"
66 #include "BIF_keyval.h"
67 #include "BIF_interface.h"
68 #include "BIF_drawtext.h"
69 #include "BIF_editfont.h"
70 #include "BIF_spacetypes.h"
71 #include "BIF_usiblender.h"
72 #include "BIF_screen.h"
73 #include "BIF_toolbox.h"
74 #include "BIF_space.h"
75 #include "BIF_mywindow.h"
76 #include "BIF_resources.h"
77
78 #include "BSE_filesel.h"
79
80 #include "BPY_extern.h"
81
82 #include "mydevice.h"
83 #include "blendef.h" 
84 #include "winlay.h"
85
86 #define TEXTXLOC        38
87
88 /* forward declarations */
89
90 void drawtextspace(ScrArea *sa, void *spacedata);
91 void winqreadtextspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt);
92 void txt_copy_selectbuffer (Text *text);
93 void do_brackets();
94
95 void get_selection_buffer(Text *text);
96 int check_bracket(char *string);
97 static int check_delim(char *string);
98 static int check_numbers(char *string);
99 static int check_builtinfuncs(char *string);
100 static int check_specialvars(char *string);
101
102 static void *last_txt_find_string= NULL;
103
104 static BMF_Font *spacetext_get_font(SpaceText *st) {
105         static BMF_Font *scr12= NULL;
106         static BMF_Font *scr15= NULL;
107         
108         switch (st->font_id) {
109         default:
110         case 0:
111                 if (!scr12)
112                         scr12= BMF_GetFont(BMF_kScreen12);
113                 return scr12;
114         case 1:
115                 if (!scr15)
116                         scr15= BMF_GetFont(BMF_kScreen15);
117                 return scr15;
118         }
119 }
120
121 static int spacetext_get_fontwidth(SpaceText *st) {
122         return BMF_GetCharacterWidth(spacetext_get_font(st), ' ');
123 }
124
125 static char *temp_char_buf= NULL;
126 static int *temp_char_accum= NULL;
127 static int temp_char_len= 0;
128 static int temp_char_pos= 0;
129
130 static void temp_char_write(char c, int accum) {
131         if (temp_char_len==0 || temp_char_pos>=temp_char_len) {
132                 char *nbuf; int *naccum;
133                 int olen= temp_char_len;
134                 
135                 if (olen) temp_char_len*= 2;
136                 else temp_char_len= 256;
137                 
138                 nbuf= MEM_mallocN(sizeof(*temp_char_buf)*temp_char_len, "temp_char_buf");
139                 naccum= MEM_mallocN(sizeof(*temp_char_accum)*temp_char_len, "temp_char_accum");
140                 
141                 if (olen) {
142                         memcpy(nbuf, temp_char_buf, olen);
143                         memcpy(naccum, temp_char_accum, olen);
144                         
145                         MEM_freeN(temp_char_buf);
146                         MEM_freeN(temp_char_accum);
147                 }
148                 
149                 temp_char_buf= nbuf;
150                 temp_char_accum= naccum;
151         }
152         
153         temp_char_buf[temp_char_pos]= c;        
154         temp_char_accum[temp_char_pos]= accum;
155         
156         if (c==0) temp_char_pos= 0;
157         else temp_char_pos++;
158 }
159
160 void free_txt_data(void) {
161         txt_free_cut_buffer();
162         
163         if (last_txt_find_string) MEM_freeN(last_txt_find_string);
164         if (temp_char_buf) MEM_freeN(temp_char_buf);
165         if (temp_char_accum) MEM_freeN(temp_char_accum);        
166 }
167
168 static int render_string (SpaceText *st, char *in) {
169         int r = 0, i = 0;
170         
171         while(*in) {
172                 if (*in=='\t') {
173                         if (temp_char_pos && *(in-1)=='\t') i= st->tabnumber;
174                         else if (st->tabnumber > 0) i= st->tabnumber - (temp_char_pos%st->tabnumber);
175                         while(i--) temp_char_write(' ', r);
176                 } else temp_char_write(*in, r);
177
178                 r++;
179                 in++;
180         }
181         r= temp_char_pos;
182         temp_char_write(0, 0);
183                 
184         return r;
185 }
186
187 void get_format_string(SpaceText *st) 
188 {
189         Text *text = st->text;
190         TextLine *tmp;
191         char *in_line;
192         char format[2000], check[200], other[2];
193         unsigned char c;
194         int spot, letter, tabs, mem_amount;
195         size_t a, b, len;
196         
197         if(!text) return;
198         tmp = text->lines.first;
199         
200         while(tmp) {
201                 in_line = tmp->line;
202                 
203                 len = strlen(in_line);
204                 /* weak code... but we dont want crashes (ton) */
205                 if(len>2000-1) {
206                         if (tmp->format) MEM_freeN(tmp->format);
207                         tmp->format= NULL;
208                 }
209                 else {
210                         
211                         spot = 0;
212                         tabs = 0;
213                         //see how many tabs we have
214                         for(a = 0; a <len; a++) {
215                                 c = (unsigned char) in_line[a];
216                                 if(c == '\t') {
217                                         tabs++;
218                                 }
219                         }
220                         //calculate the amount of MEM_mallocN we neen
221                         mem_amount = (((tabs*st->tabnumber)-tabs)+2)+len; // +2 for good measure
222                         if (tmp->format) MEM_freeN(tmp->format);
223                         tmp->format = MEM_mallocN(mem_amount, "Syntax_format");
224                         
225                         for (a = 0; a < len; a++) {
226                                 c = (unsigned char) in_line[a];
227
228                                 check[0] = c;
229                                 check[1] = '\0';
230
231                                 if (check_delim(check))
232                                 {
233                                         switch (c) {
234                                                 case '\"':
235                                                         if(in_line[a] == '\"' && in_line[a+1] == '\"' && in_line[a+2] == '\"') { 
236                                                                 format[spot] = format[spot+1] = format[spot+2] = 'l';
237                                                                 spot +=3;
238                                                                 a += 3;
239                                                                 while(in_line[a] != '\"' || in_line[a-1] != '\"' || in_line[a-2] != '\"') {
240                                                                         c = (unsigned char) in_line[a];
241                                                                         if(a >= len) {
242                                                                                 format[spot] = '\0';
243                                                                                 memcpy(tmp->format, format, strlen(format));
244                                                                                 if(!(tmp= tmp->next)) {
245                                                                                         return;
246                                                                                 } else {
247                                                                                         in_line = tmp->line;
248                                                                                         len = strlen(in_line);
249                                                                                         tabs = 0;
250                                                                                         for(b = 0; b <len; b++) {
251                                                                                                 c = (unsigned char) in_line[b];
252                                                                                                 if(c == '\t') {
253                                                                                                         tabs++;
254                                                                                                 }
255                                                                                         }
256                                                                                         mem_amount = (((tabs*st->tabnumber)-tabs)+2)+len;
257                                                                                         if (tmp->format) MEM_freeN(tmp->format);
258                                                                                         tmp->format = MEM_mallocN(mem_amount, "Syntax_format");
259                                                                                         a = 0; spot = 0;
260                                                                                 }
261                                                                         } else {
262                                                                                 if(c == '\t' || c == ' ') {
263                                                                                         if(c == '\t') {
264                                                                                                 for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
265                                                                                                         format[spot] = ' ';
266                                                                                                         spot++;
267                                                                                                 }
268                                                                                                 a++;
269                                                                                         } else {
270                                                                                                 format[spot] = ' ';
271                                                                                                 a++; spot++;
272                                                                                 }
273                                                                                 } else {
274                                                                                         format[spot] = 'l';
275                                                                                         a++; spot++;
276                                                                                 }
277                                                                         }
278                                                                 }
279                                                                 format[spot] = 'l';
280                                                                 spot++;
281                                                         } else {
282                                                                 format[spot] = 'l';
283                                                                 a++; spot++;
284                                                                 while(in_line[a] != '\"') {
285                                                                         c = (unsigned char) in_line[a];
286                                                                         if(a >= len) {
287                                                                                 format[spot] = '\0';
288                                                                                 memcpy(tmp->format, format, strlen(format));
289                                                                                 if(!(tmp= tmp->next)) {
290                                                                                         return;
291                                                                                 } else {
292                                                                                         in_line = tmp->line;
293                                                                                         len = strlen(in_line);
294                                                                                         for(b = 0; b <len; b++) {
295                                                                                                 c = (unsigned char) in_line[b];
296                                                                                                 if(c == '\t') {
297                                                                                                         tabs++;
298                                                                                                 }
299                                                                                         }
300                                                                                         //calculate the amount of MEM_mallocN we neen
301                                                                                         mem_amount = (((tabs*st->tabnumber)-tabs)+2)+len;
302                                                                                         if (tmp->format) MEM_freeN(tmp->format);
303                                                                                         tmp->format = MEM_mallocN(mem_amount, "Syntax_format");
304                                                                                         a = 0; spot = 0;
305                                                                                 }
306                                                                         }
307                                                                         if(c == '\t' || c == ' ') {
308                                                                                 if(c == '\t') {
309                                                                                         for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
310                                                                                                 format[spot] = ' ';
311                                                                                                 spot++;
312                                                                                         }
313                                                                                         a++;
314                                                                                 } else {
315                                                                                         format[spot] = ' ';
316                                                                                         a++; spot++;
317                                                                                 }
318                                                                         } else {
319                                                                                 format[spot] = 'l';
320                                                                                 a++; spot++;
321                                                                         }
322                                                                 }
323                                                                 format[spot] = 'l';
324                                                                 spot++;
325                                                         }
326                                                         break;
327                                                 case '\'':
328                                                         if(in_line[a] == '\'' && in_line[a+1] == '\'' && in_line[a+2] == '\'') { 
329                                                                 format[spot] = format[spot+1] = format[spot+2] = 'l';
330                                                                 spot +=3;
331                                                                 a += 3;
332                                                                 while(in_line[a] != '\'' || in_line[a-1] != '\'' || in_line[a-2] != '\'') {
333                                                                         c = (unsigned char) in_line[a];
334                                                                         if(a >= len) {
335                                                                                 format[spot] = '\0';
336                                                                                 memcpy(tmp->format, format, strlen(format));
337                                                                                 if(!(tmp= tmp->next)) {
338                                                                                         return;
339                                                                                 } else {
340                                                                                         in_line = tmp->line;
341                                                                                         len = strlen(in_line);
342                                                                                         tabs = 0;
343                                                                                         for(b = 0; b <len; b++) {
344                                                                                                 c = (unsigned char) in_line[b];
345                                                                                                 if(c == '\t') {
346                                                                                                         tabs++;
347                                                                                                 }
348                                                                                         }
349                                                                                         mem_amount = (((tabs*st->tabnumber)-tabs)+2)+len;
350                                                                                         if (tmp->format) MEM_freeN(tmp->format);
351                                                                                         tmp->format = MEM_mallocN(mem_amount, "Syntax_format");
352                                                                                         a = 0; spot = 0;
353                                                                                 }
354                                                                         } else {
355                                                                                 if(c == '\t' || c == ' ') {
356                                                                                         if(c == '\t') {
357                                                                                                 for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
358                                                                                                         format[spot] = ' ';
359                                                                                                         spot++;
360                                                                                                 }
361                                                                                                 a++;
362                                                                                         } else {
363                                                                                                 format[spot] = ' ';
364                                                                                                 a++; spot++;
365                                                                                         }
366                                                                                 } else {
367                                                                                         format[spot] = 'l';
368                                                                                         a++; spot++;
369                                                                                 }
370                                                                         }
371                                                                 }
372                                                                 format[spot] = 'l';
373                                                                 spot++;
374                                                         } else {
375                                                                 format[spot] = 'l';
376                                                                 a++; spot++;
377                                                                 while(in_line[a] != '\'') {
378                                                                         c = (unsigned char) in_line[a];
379                                                                         if(a >= len) {
380                                                                                 format[spot] = '\0';
381                                                                                 memcpy(tmp->format, format, strlen(format));
382                                                                                 if(!(tmp= tmp->next)) {
383                                                                                         return;
384                                                                                 } else {
385                                                                                         in_line = tmp->line;
386                                                                                         len = strlen(in_line);
387                                                                                         for(b = 0; b <len; b++) {
388                                                                                                 c = (unsigned char) in_line[b];
389                                                                                                 if(c == '\t') {
390                                                                                                         tabs++;
391                                                                                                 }
392                                                                                         }
393                                                                                         //calculate the amount of MEM_mallocN we neen
394                                                                                         mem_amount = (((tabs*st->tabnumber)-tabs)+2)+len;
395                                                                                         if (tmp->format) MEM_freeN(tmp->format);
396                                                                                         tmp->format = MEM_mallocN(mem_amount, "Syntax_format");
397                                                                                         a = 0; spot = 0;
398                                                                                 }
399                                                                         }
400                                                                         if(c == '\t' || c == ' ') {
401                                                                                 if(c == '\t') {
402                                                                                         for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
403                                                                                                 format[spot] = ' ';
404                                                                                                 spot++;
405                                                                                         }
406                                                                                         a++;
407                                                                                 } else {
408                                                                                         format[spot] = ' ';
409                                                                                         a++; spot++;
410                                                                                 }
411                                                                         } else {
412                                                                                 format[spot] = 'l';
413                                                                                 a++; spot++;
414                                                                         }
415                                                                 }
416                                                                 format[spot] = 'l';
417                                                                 spot++;
418                                                         }
419                                                         break;
420                                                 case '#':
421                                                         while(a<len) {
422                                                                 c = (unsigned char) in_line[a];
423                                                                 if(c == '\t' || c == ' ') {
424                                                                         if(c == '\t') {
425                                                                                 for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
426                                                                                         format[spot] = '#';
427                                                                                         spot++;
428                                                                                 }
429                                                                                 a++;
430                                                                         } else {
431                                                                                 format[spot] = '#';
432                                                                                 a++; spot++;
433                                                                         }
434                                                                 } else {
435                                                                         format[spot] = '#';
436                                                                         a++; spot++;
437                                                                 }
438                                                         }
439                                                         break;
440                                                 case ' ':
441                                                         format[spot] = ' ';
442                                                         spot++;
443                                                         break;
444                                                 case '\t':
445                                                         for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) {
446                                                                 format[spot] = ' ';
447                                                                 spot++;
448                                                         }
449                                                         break;
450                                                 default:
451                                                         format[spot] = 'q';
452                                                         spot++;
453                                                          
454                                                         break;
455                                         }
456                                 } else if (check_numbers(check)) {
457                                         while (a < len) {
458                                                 c = (unsigned char) in_line[a];
459                                                 other[0] = c;
460                                                 other[1] = '\0';
461                                                 if (check_delim(other) && c != '.') {
462                                                         a--; break;
463                                                 } else {
464                                                         format[spot] = 'n';
465                                                         a++; spot++;
466                                                 }
467                                         }
468                                 } else {
469                                         letter = 0;
470                                         while (a < len) {
471                                                 c = (unsigned char) in_line[a];
472                                                 other[0] = c;
473                                                 other[1] = '\0';
474                                                 if (check_delim(other)) {
475                                                         a--; 
476                                                         break;
477                                                 } else {
478                                                         check[letter] = (unsigned char) in_line[a];
479                                                         letter++; 
480                                                         a++;
481                                                 }
482                                         }
483                                         check[letter] = '\0';
484                                         if (check_builtinfuncs(check)) {
485                                                 for (b = 0; b < strlen(check); b++) {
486                                                         format[spot] = 'b'; 
487                                                         spot++;
488                                                 }
489                                         } else if (check_specialvars(check)) { /*If TRUE then color and color next word*/
490                                                 for (b = 0; b < strlen(check); b++) {
491                                                         format[spot] = 'b';
492                                                         spot++;
493                                                 }
494                                                 a++;
495                                                 format[spot] = 'q';
496                                                 spot++; a++;
497                                                 letter = 0;
498                                                 while (a < len) {
499                                                         c = (unsigned char) in_line[a];
500                                                         other[0] = c;
501                                                         other[1] = '\0';
502                                                         if (check_delim(other)) {
503                                                                 a--; 
504                                                                 break;
505                                                         } else {
506                                                                 check[letter] = (unsigned char) in_line[a];
507                                                                 letter++; 
508                                                                 a++;
509                                                         }
510                                                 }
511                                                 check[letter] = '\0';
512                                                 for (b = 0; b < strlen(check); b++) {
513                                                         format[spot] = 'v';
514                                                         spot++;
515                                                 }
516                                         }else {
517                                                 for (b = 0; b < strlen(check); b++) {
518                                                         format[spot] = 'q';
519                                                         spot++;
520                                                 }
521                                         }
522                                 }
523                         }
524                         format[spot] = '\0';
525                         memcpy(tmp->format, format, strlen(format));
526                 }
527                 
528                 tmp = tmp->next;
529         }
530 }
531
532 static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) {
533         int r=0, w= 0;
534         char *in;
535         int *acc;
536
537         w= render_string(st, str);
538         if(w<cshift ) return 0; /* String is shorter than shift */
539         
540         in= temp_char_buf+cshift;
541         acc= temp_char_accum+cshift;
542         w= w-cshift;
543
544         if (draw) {
545                 if(st->showsyntax && format) {
546                         int amount, a;
547                         char out[2];
548                         format = format+cshift;
549                 
550                         amount = strlen(in);
551                         
552                         for(a = 0; a < amount; a++) {
553                                 out[0] = (unsigned char) in[a]; 
554                                 out[1] = '\0';
555                                 switch (format[a]) {
556                                         case 'l':
557                                                 BIF_ThemeColor(TH_SYNTAX_L);
558                                                 break;
559                                         case 'b':
560                                                 BIF_ThemeColor(TH_SYNTAX_B);
561                                                 break;
562                                         case '#':
563                                                 BIF_ThemeColor(TH_SYNTAX_C);
564                                                 break;
565                                         case 'v': 
566                                                 BIF_ThemeColor(TH_SYNTAX_V);
567                                                 break;
568                                         case 'n':
569                                                 BIF_ThemeColor(TH_SYNTAX_N);
570                                                 break;
571                                         case 'q':
572                                                 BIF_ThemeColor(TH_TEXT);
573                                                 break;
574                                         default:
575                                                 BIF_ThemeColor(TH_TEXT);
576                                                 break;
577                                 }
578                                 glRasterPos2i(x, y);
579                                 BMF_DrawString(spacetext_get_font(st), out);
580                                 x = x+BMF_GetStringWidth(spacetext_get_font(st), out);
581                         }
582                 } else {
583                         glRasterPos2i(x, y);
584                         BMF_DrawString(spacetext_get_font(st), in);
585                 }
586         } else {
587                 while (w-- && *acc++ < maxwidth) {
588                         r+= spacetext_get_fontwidth(st);
589                 }
590         }
591
592         if (cshift && r==0) return 0;
593         else if (st->showlinenrs)
594                 return r+TXT_OFFSET+TEXTXLOC;
595         else
596                 return r+TXT_OFFSET;
597 }
598
599 static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) 
600 {
601         Text *text;
602         TextLine **linep;
603         int *charp;
604         int w;
605         
606         text= st->text;
607
608         if(sel) { linep= &text->sell; charp= &text->selc; } 
609         else { linep= &text->curl; charp= &text->curc; }
610         
611         y= (curarea->winy - y)/st->lheight;
612         
613         y-= txt_get_span(text->lines.first, *linep) - st->top;
614         
615         if (y>0) {
616                 while (y-- != 0) if((*linep)->next) *linep= (*linep)->next;
617         } else if (y<0) {
618                 while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev;
619         }
620
621         if(st->showlinenrs)
622                 x-= TXT_OFFSET+TEXTXLOC;
623         else
624                 x-= TXT_OFFSET;
625
626         if (x<0) x= 0;
627         x = (x/spacetext_get_fontwidth(st)) + st->left;
628         
629         w= render_string(st, (*linep)->line);
630         if(x<w) *charp= temp_char_accum[x];
631         else *charp= (*linep)->len;
632         
633         if(!sel) txt_pop_sel(text);
634 }
635
636 static void draw_cursor(SpaceText *st) {
637         int h, x, i;
638         Text *text= st->text;
639         TextLine *linef, *linel;
640         int charf, charl;
641         
642         if (text->curl==text->sell && text->curc==text->selc) {
643                 x= text_draw(st, text->curl->line, st->left, text->curc, 0, 0, 0, NULL);
644
645                 if (x) {
646                         h= txt_get_span(text->lines.first, text->curl) - st->top;
647
648                         BIF_ThemeColor(TH_HILITE);
649                         
650                         glRecti(x-1, curarea->winy-st->lheight*(h)-2, x+1, curarea->winy-st->lheight*(h+1)-2);
651                 }
652         } else {
653                 int span= txt_get_span(text->curl, text->sell);
654                 
655                 if (span<0) {
656                         linef= text->sell;
657                         charf= text->selc;
658                         
659                         linel= text->curl;
660                         charl= text->curc;
661                 } else if (span>0) {
662                         linef= text->curl;
663                         charf= text->curc;
664         
665                         linel= text->sell;              
666                         charl= text->selc;
667                 } else {
668                         linef= linel= text->curl;
669                         
670                         if (text->curc<text->selc) {
671                                 charf= text->curc;
672                                 charl= text->selc;
673                         } else {
674                                 charf= text->selc;
675                                 charl= text->curc;
676                         }
677                 }
678         
679                         /* Walk to the beginning of visible text */
680                 h= txt_get_span(text->lines.first, linef) - st->top;
681                 while (h++<-1 && linef!=linel) linef= linef->next;
682         
683                 x= text_draw(st, linef->line, st->left, charf, 0, 0, 0, NULL);
684
685                 BIF_ThemeColor(TH_SHADE2);
686
687                 if(st->showlinenrs) {
688                         if (!x) x= TXT_OFFSET + TEXTXLOC -4;
689                 } else {
690                         if (!x) x= TXT_OFFSET - 4;
691                 }
692                 
693                 while (linef && linef != linel) {
694                         h= txt_get_span(text->lines.first, linef) - st->top;
695                         if (h>st->viewlines) break;
696                         
697                         glRecti(x, curarea->winy-st->lheight*(h)-2, curarea->winx, curarea->winy-st->lheight*(h+1)-2);
698                         if(st->showlinenrs)
699                                 glRecti(TXT_OFFSET+TEXTXLOC-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET+TEXTXLOC, curarea->winy-st->lheight*(h+2)-2);
700                         else
701                                 glRecti(TXT_OFFSET-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET, curarea->winy-st->lheight*(h+2)-2);
702
703                         if(st->showlinenrs)
704                                 x= TXT_OFFSET + TEXTXLOC;
705                         else
706                                 x= TXT_OFFSET;
707                         
708                         linef= linef->next;
709                 }
710                 
711                 h= txt_get_span(text->lines.first, linef) - st->top;
712
713                 i= text_draw(st, linel->line, st->left, charl, 0, 0, 0, NULL);
714                 if(i) glRecti(x, curarea->winy-st->lheight*(h)-2, i, curarea->winy-st->lheight*(h+1)-2);
715
716         }
717
718         do_brackets();
719         BIF_ThemeColor(TH_TEXT);
720 }
721
722 static void calc_text_rcts(SpaceText *st)
723 {
724         int lhlstart, lhlend, ltexth;
725         short barheight, barstart, hlstart, hlend, blank_lines;
726         short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff;
727
728         pix_top_margin = 8;
729         pix_bottom_margin = 4;
730         pix_available = curarea->winy - pix_top_margin - pix_bottom_margin;
731         ltexth= txt_get_span(st->text->lines.first, st->text->lines.last);
732         blank_lines = st->viewlines / 2;
733         
734         /* when resizing a vieport with the bar at the bottom to a greater height more blank lines will be added */
735         if (ltexth + blank_lines < st->top + st->viewlines) {
736                 blank_lines = st->top + st->viewlines - ltexth;
737         }
738         
739         ltexth += blank_lines;
740
741         barheight = (ltexth > 0)? (st->viewlines*pix_available)/ltexth: 0;
742         pix_bardiff = 0;
743         if (barheight < 20) {
744                 pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */      
745                 barheight = 20;
746         }
747         barstart = (ltexth > 0)? ((pix_available - pix_bardiff) * st->top)/ltexth: 0;
748
749         st->txtbar.xmin = 5;
750         st->txtbar.xmax = 17;
751         st->txtbar.ymax = curarea->winy - pix_top_margin - barstart;
752         st->txtbar.ymin = st->txtbar.ymax - barheight;
753
754         CLAMP(st->txtbar.ymin, pix_bottom_margin, curarea->winy - pix_top_margin);
755         CLAMP(st->txtbar.ymax, pix_bottom_margin, curarea->winy - pix_top_margin);
756
757         st->pix_per_line= (pix_available > 0)? (float) ltexth/pix_available: 0;
758         if (st->pix_per_line<.1) st->pix_per_line=.1f;
759
760         lhlstart = MIN2(txt_get_span(st->text->lines.first, st->text->curl), 
761                                 txt_get_span(st->text->lines.first, st->text->sell));
762         lhlend = MAX2(txt_get_span(st->text->lines.first, st->text->curl), 
763                                 txt_get_span(st->text->lines.first, st->text->sell));
764
765         if(ltexth > 0) {
766                 hlstart = (lhlstart * pix_available)/ltexth;
767                 hlend = (lhlend * pix_available)/ltexth;
768
769                 /* the scrollbar is non-linear sized */
770                 if (pix_bardiff > 0) {
771                         /* the start of the highlight is in the current viewport */
772                         if (ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) { 
773                                 /* speed the progresion of the start of the highlight through the scrollbar */
774                                 hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines);       
775                         }
776                         else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) {
777                                 /* push hl start down */
778                                 hlstart = barstart + barheight;
779                         }
780                         else if (lhlend > st->top  && lhlstart < st->top && hlstart > barstart) {
781                                 /*fill out start */
782                                 hlstart = barstart;
783                         }
784
785                         if (hlend <= hlstart) { 
786                                 hlend = hlstart + 2;
787                         }
788
789                         /* the end of the highlight is in the current viewport */
790                         if (ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) { 
791                                 /* speed the progresion of the end of the highlight through the scrollbar */
792                                 hlend = (((pix_available - pix_bardiff )*lhlend)/ltexth) + (pix_bardiff * (lhlend - st->top)/st->viewlines);    
793                         }
794                         else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
795                                 /* push hl end up */
796                                 hlend = barstart;
797                         }                                       
798                         else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) {
799                                 /* fill out end */
800                                 hlend = barstart + barheight;
801                         }
802
803                         if (hlend <= hlstart) { 
804                                 hlstart = hlend - 2;
805                         }       
806                 }       
807         }
808         else {
809                 hlstart = 0;
810                 hlend = 0;
811         }
812
813         if (hlend - hlstart < 2) { 
814                 hlend = hlstart + 2;
815         }
816         
817         st->txtscroll.xmin= 5;
818         st->txtscroll.xmax= 17;
819         st->txtscroll.ymax= curarea->winy - pix_top_margin - hlstart;
820         st->txtscroll.ymin= curarea->winy - pix_top_margin - hlend;
821
822         CLAMP(st->txtscroll.ymin, pix_bottom_margin, curarea->winy - pix_top_margin);
823         CLAMP(st->txtscroll.ymax, pix_bottom_margin, curarea->winy - pix_top_margin);
824 }
825
826 static void draw_textscroll(SpaceText *st)
827 {
828         if (!st->text) return;
829
830         calc_text_rcts(st);
831         
832         BIF_ThemeColorShade(TH_SHADE1, -20);
833         glRecti(2, 2, 20, curarea->winy-6);
834         uiEmboss(2, 2, 20, curarea->winy-6, 1);
835
836         BIF_ThemeColor(TH_SHADE1);
837         glRecti(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax);
838
839         BIF_ThemeColor(TH_SHADE2);
840         glRecti(st->txtscroll.xmin, st->txtscroll.ymin, st->txtscroll.xmax, st->txtscroll.ymax);
841
842         uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
843 }
844
845 static void screen_skip(SpaceText *st, int lines)
846 {
847         int last;
848         
849         if (!st) return;
850         if (st->spacetype != SPACE_TEXT) return;
851         if (!st->text) return;
852
853         st->top += lines;
854
855         last= txt_get_span(st->text->lines.first, st->text->lines.last);
856         last= last - (st->viewlines/2);
857         
858         if (st->top>last) st->top= last;
859         if (st->top<0) st->top= 0;
860 }
861
862 /* 
863  * mode 1 == view scroll
864  * mode 2 == scrollbar
865  */
866 static void do_textscroll(SpaceText *st, int mode)
867 {
868         short delta[2]= {0, 0};
869         short mval[2], hold[2], old[2];
870         
871         if (!st->text) return;
872         
873         calc_text_rcts(st);
874
875         st->flags|= ST_SCROLL_SELECT;
876
877         glDrawBuffer(GL_FRONT);
878         uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
879         bglFlush();
880         glDrawBuffer(GL_BACK);
881
882         getmouseco_areawin(mval);
883         old[0]= hold[0]= mval[0];
884         old[1]= hold[1]= mval[1];
885
886         while(get_mbut()&(L_MOUSE|M_MOUSE)) {
887                 getmouseco_areawin(mval);
888
889                 if(old[0]!=mval[0] || old[1]!=mval[1]) {
890                         if (mode==1) {
891                                 delta[0]= (hold[0]-mval[0])/spacetext_get_fontwidth(st);
892                                 delta[1]= (mval[1]-hold[1])/st->lheight;
893                         }
894                         else delta[1]= (hold[1]-mval[1])*st->pix_per_line;
895                         
896                         if (delta[0] || delta[1]) {
897                                 screen_skip(st, delta[1]);
898                                 st->left+= delta[0];
899                                 if (st->left<0) st->left= 0;
900                                 
901                                 scrarea_do_windraw(curarea);
902                                 screen_swapbuffers();
903                                 
904                                 hold[0]=mval[0];
905                                 hold[1]=mval[1];
906                         }
907                         old[0]=mval[0];
908                         old[1]=mval[1];
909                 } else {
910                         BIF_wait_for_statechange();
911                 }
912         }
913         st->flags^= ST_SCROLL_SELECT;
914
915         glDrawBuffer(GL_FRONT);
916         uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT);
917         bglFlush();
918         glDrawBuffer(GL_BACK);
919 }
920
921 static void do_selection(SpaceText *st, int selecting)
922 {
923         short mval[2], old[2];
924         int sell, selc;
925         int linep2, charp2;
926         int first= 1;
927
928         getmouseco_areawin(mval);
929         old[0]= mval[0];
930         old[1]= mval[1];
931
932         if (!selecting) {
933                 int curl= txt_get_span(st->text->lines.first, st->text->curl);
934                 int curc= st->text->curc;                       
935                 int linep2, charp2;
936                                         
937                 set_cursor_to_pos(st, mval[0], mval[1], 0);
938
939                 linep2= txt_get_span(st->text->lines.first, st->text->curl);
940                 charp2= st->text->selc;
941                                 
942                 if (curl!=linep2 || curc!=charp2)
943                         txt_undo_add_toop(st->text, UNDO_CTO, curl, curc, linep2, charp2);
944         }
945
946         sell= txt_get_span(st->text->lines.first, st->text->sell);
947         selc= st->text->selc;
948
949         while(get_mbut()&L_MOUSE) {
950                 getmouseco_areawin(mval);
951
952                 if (mval[1]<0 || mval[1]>curarea->winy) {
953                         int d= (old[1]-mval[1])*st->pix_per_line;
954                         if (d) screen_skip(st, d);
955
956                         set_cursor_to_pos(st, mval[0], mval[1]<0?0:curarea->winy, 1);
957
958                         scrarea_do_windraw(curarea);
959                         screen_swapbuffers();
960                 } else if (mval[0]<0 || mval[0]>curarea->winx) {
961                         if (mval[0]>curarea->winx) st->left++;
962                         else if (mval[0]<0 && st->left>0) st->left--;
963                         
964                         set_cursor_to_pos(st, mval[0], mval[1], 1);
965                         
966                         scrarea_do_windraw(curarea);
967                         screen_swapbuffers();
968                         
969                         PIL_sleep_ms(10);
970                 } else if (first || old[0]!=mval[0] || old[1]!=mval[1]) {
971                         set_cursor_to_pos(st, mval[0], mval[1], 1);
972
973                         scrarea_do_windraw(curarea);
974                         screen_swapbuffers();
975
976                         old[0]= mval[0];
977                         old[1]= mval[1];
978                         first= 1;
979                 } else {
980                         BIF_wait_for_statechange();
981                 }
982         }
983
984         linep2= txt_get_span(st->text->lines.first, st->text->sell);
985         charp2= st->text->selc;
986                 
987         if (sell!=linep2 || selc!=charp2)
988                 txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2);
989 }
990
991 void drawtextspace(ScrArea *sa, void *spacedata)
992 {
993         SpaceText *st= curarea->spacedata.first;
994         Text *text;
995         int i;
996         TextLine *tmp;
997         char linenr[12];
998         float col[3];
999         int linecount = 0;
1000
1001         if (st==NULL || st->spacetype != SPACE_TEXT) return;
1002         
1003         BIF_GetThemeColor3fv(TH_BACK, col);
1004         glClearColor(col[0], col[1], col[2], 0.0);
1005         glClear(GL_COLOR_BUFFER_BIT);
1006         myortho2(-0.375, (float)(sa->winx)-0.375, -0.375, (float)(sa->winy)-0.375);
1007
1008         draw_area_emboss(sa);
1009
1010         text= st->text;
1011         if(!text) return;
1012         
1013         /* Make sure all the positional pointers exist */
1014         if (!text->curl || !text->sell || !text->lines.first || !text->lines.last)
1015                 txt_clean_text(text);
1016         
1017         if(st->lheight) st->viewlines= (int) curarea->winy/st->lheight;
1018         else st->viewlines= 0;
1019         
1020         if(st->showlinenrs) {
1021                 cpack(0x8c787c);
1022                 glRecti(23,  0, (st->lheight==15)?63:59,  curarea->winy - 2);
1023         }
1024
1025         BIF_ThemeColor(TH_TEXT);
1026
1027         draw_cursor(st);
1028
1029         tmp= text->lines.first;
1030         for (i= 0; i<st->top && tmp; i++) {
1031                 tmp= tmp->next;
1032                 linecount++;
1033         }
1034         
1035         if(st->showsyntax) {
1036                 if (tmp && !tmp->format) {
1037                         get_format_string(st);
1038                 }
1039         }
1040         
1041         for (i=0; i<st->viewlines && tmp; i++, tmp= tmp->next) {
1042                 if(st->showlinenrs) {
1043                         /*Change the color of the current line the cursor is on*/
1044                         if(tmp == text->curl) { 
1045                                 BIF_ThemeColor(TH_HILITE);
1046                         } else {
1047                                 BIF_ThemeColor(TH_TEXT);
1048                         }
1049                         if(((float)(i + linecount + 1)/10000.0) < 1.0) {
1050                                 sprintf(linenr, "%4d", i + linecount + 1);
1051                                 glRasterPos2i(TXT_OFFSET - 7, curarea->winy-st->lheight*(i+1));
1052                         } else {
1053                                 sprintf(linenr, "%5d", i + linecount + 1);
1054                                 glRasterPos2i(TXT_OFFSET - 11, curarea->winy-st->lheight*(i+1));
1055                         }
1056                         BIF_ThemeColor(TH_TEXT);
1057                         BMF_DrawString(spacetext_get_font(st), linenr);
1058                         text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET + TEXTXLOC, curarea->winy-st->lheight*(i+1), tmp->format);
1059                 } else
1060                         text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET, curarea->winy-st->lheight*(i+1), tmp->format);
1061         }
1062
1063         draw_textscroll(st);
1064
1065         curarea->win_swap= WIN_BACK_OK;
1066 }
1067
1068 /* Moves the view to the cursor location,
1069   also used to make sure the view isnt outside the file */
1070 void pop_space_text (SpaceText *st)
1071 {
1072         int i, x;
1073
1074         if(!st) return;
1075         if(!st->text) return;
1076         if(!st->text->curl) return;
1077                 
1078         i= txt_get_span(st->text->lines.first, st->text->curl);
1079         if (st->top+st->viewlines <= i || st->top > i) {
1080                 st->top= i - st->viewlines/2;
1081         }
1082         
1083         x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0, NULL);
1084
1085         if (x==0 || x>curarea->winx) {
1086                 st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st);
1087         }
1088
1089         if (st->top < 0) st->top= 0;
1090         if (st->left <0) st->left= 0;
1091 }
1092
1093 void add_text_fs(char *file) /* bad but cant pass an as arg here */
1094 {
1095         SpaceText *st= curarea->spacedata.first;
1096         Text *text;
1097
1098         if (st==NULL || st->spacetype != SPACE_TEXT) return;
1099
1100         text= add_text(file);
1101
1102         st->text= text;
1103
1104         st->top= 0;
1105
1106         if (st->showsyntax) get_format_string(st);
1107         allqueue(REDRAWTEXT, 0);
1108         allqueue(REDRAWHEADERS, 0);     
1109 }
1110
1111 void free_textspace(SpaceText *st)
1112 {
1113         if (!st) return;
1114
1115         st->text= NULL;
1116 }
1117
1118 static void save_mem_text(char *str)
1119 {
1120         SpaceText *st= curarea->spacedata.first;
1121         Text *text;
1122         
1123         if (!str) return;
1124         
1125         if (!st) return;
1126         if (st->spacetype != SPACE_TEXT) return;
1127
1128         text= st->text;
1129         if(!text) return;
1130         
1131         if (text->name) MEM_freeN(text->name);
1132         text->name= MEM_mallocN(strlen(str)+1, "textname");
1133         strcpy(text->name, str);
1134
1135         text->flags ^= TXT_ISMEM;
1136                 
1137         txt_write_file(text);
1138 }
1139
1140 void txt_write_file(Text *text) 
1141 {
1142         FILE *fp;
1143         TextLine *tmp;
1144         
1145         /* Do we need to get a filename? */
1146         if (text->flags & TXT_ISMEM) {
1147                 if (text->name)
1148                         activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->name, save_mem_text);
1149                 else
1150                         activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->id.name+2, save_mem_text);
1151                 return; 
1152         }
1153         
1154         /* Should we ask to save over? */
1155         if (text->flags & TXT_ISTMP) {
1156                 if (BLI_exists(text->name)) {
1157                         if (!okee("Save over")) return;
1158                 } else if (!okee("Create new file")) return;
1159
1160                 text->flags ^= TXT_ISTMP;
1161         }
1162                 
1163         fp= fopen(text->name, "w");
1164         if (fp==NULL) {
1165                 error("Unable to save file");
1166                 return;
1167         }
1168
1169         tmp= text->lines.first;
1170         while (tmp) {
1171                 if (tmp->next) fprintf(fp, "%s\n", tmp->line);
1172                 else fprintf(fp, "%s", tmp->line);
1173                 
1174                 tmp= tmp->next;
1175         }
1176         
1177         fclose (fp);
1178         
1179         if (text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY;
1180 }
1181
1182 void unlink_text(Text *text)
1183 {
1184         bScreen *scr;
1185         ScrArea *area;
1186         SpaceLink *sl;
1187         
1188         /* check if this text was used as script link:
1189          * this check function unsets the pointers and returns how many
1190          * script links used this Text */
1191         if (BPY_check_all_scriptlinks (text)) {
1192                 allqueue(REDRAWBUTSSCRIPT, 0);
1193         }
1194         /* equivalently for pynodes: */
1195         if (nodeDynamicUnlinkText ((ID*)text)) {
1196                 allqueue(REDRAWNODE, 0);
1197         }
1198
1199         for (scr= G.main->screen.first; scr; scr= scr->id.next) {
1200                 for (area= scr->areabase.first; area; area= area->next) {
1201                         for (sl= area->spacedata.first; sl; sl= sl->next) {
1202                                 if (sl->spacetype==SPACE_TEXT) {
1203                                         SpaceText *st= (SpaceText*) sl;
1204                                         
1205                                         if (st->text==text) {
1206                                                 st->text= NULL;
1207                                                 st->top= 0;
1208                                                 
1209                                                 if (st==area->spacedata.first) {
1210                                                         scrarea_queue_redraw(area);
1211                                                 }
1212                                         }
1213                                 }
1214                         }
1215                 }
1216         }
1217 }
1218
1219 int jumptoline_interactive(SpaceText *st) {
1220         short nlines= txt_get_span(st->text->lines.first, st->text->lines.last)+1;
1221         short tmp= txt_get_span(st->text->lines.first, st->text->curl)+1;
1222
1223         if (button(&tmp, 1, nlines, "Jump to line:")) {
1224                 txt_move_toline(st->text, tmp-1, 0);
1225                 pop_space_text(st);
1226                 return 1;
1227         } else {
1228                 return 0;
1229         }
1230 }
1231
1232
1233 int bufferlength;
1234 static char *copybuffer = NULL;
1235
1236 void txt_copy_selectbuffer (Text *text)
1237 {
1238         int length=0;
1239         TextLine *tmp, *linef, *linel;
1240         int charf, charl;
1241         
1242         if (!text) return;
1243         if (!text->curl) return;
1244         if (!text->sell) return;
1245
1246         if (!txt_has_sel(text)) return;
1247         
1248         if (copybuffer) {
1249                 MEM_freeN(copybuffer);
1250                 copybuffer= NULL;
1251         }
1252
1253         if (text->curl==text->sell) {
1254                 linef= linel= text->curl;
1255                 
1256                 if (text->curc < text->selc) {
1257                         charf= text->curc;
1258                         charl= text->selc;
1259                 } else{
1260                         charf= text->selc;
1261                         charl= text->curc;
1262                 }
1263         } else if (txt_get_span(text->curl, text->sell)<0) {
1264                 linef= text->sell;
1265                 linel= text->curl;
1266
1267                 charf= text->selc;              
1268                 charl= text->curc;
1269         } else {
1270                 linef= text->curl;
1271                 linel= text->sell;
1272                 
1273                 charf= text->curc;
1274                 charl= text->selc;
1275         }
1276
1277         if (linef == linel) {
1278                 length= charl-charf;
1279
1280                 copybuffer= MEM_mallocN(length+1, "cut buffera");
1281                 
1282                 BLI_strncpy(copybuffer, linef->line + charf, length+1);
1283         } else {
1284                 length+= linef->len - charf;
1285                 length+= charl;
1286                 length++; /* For the '\n' */
1287                 
1288                 tmp= linef->next;
1289                 while (tmp && tmp!= linel) {
1290                         length+= tmp->len+1;
1291                         tmp= tmp->next;
1292                 }
1293                 
1294                 copybuffer= MEM_mallocN(length+1, "cut bufferb");
1295                 
1296                 strncpy(copybuffer, linef->line+ charf, linef->len-charf);
1297                 length= linef->len-charf;
1298                 
1299                 copybuffer[length++]='\n';
1300                 
1301                 tmp= linef->next;
1302                 while (tmp && tmp!=linel) {
1303                         strncpy(copybuffer+length, tmp->line, tmp->len);
1304                         length+= tmp->len;
1305                         
1306                         copybuffer[length++]='\n';                      
1307                         
1308                         tmp= tmp->next;
1309                 }
1310                 strncpy(copybuffer+length, linel->line, charl);
1311                 length+= charl;
1312                 
1313                 copybuffer[length]=0;
1314         }
1315
1316         bufferlength = length;
1317 }
1318
1319 static char *unixNewLine(char *buffer)
1320 {
1321         char *p, *p2, *output;
1322         
1323         /* we can afford the few extra bytes */
1324         output= MEM_callocN(strlen(buffer)+1, "unixnewline");
1325         for (p= buffer, p2= output; *p; p++)
1326                 if (*p != '\r') *(p2++)= *p;
1327         
1328         *p2= 0;
1329         return(output);
1330 }
1331
1332 static char *winNewLine(char *buffer)
1333 {
1334         char *p, *p2, *output;
1335         int add= 0;
1336         
1337         for (p= buffer; *p; p++)
1338                 if (*p == '\n') add++;
1339                 
1340         bufferlength= p-buffer+add+1;
1341         output= MEM_callocN(bufferlength, "winnewline");
1342         for (p= buffer, p2= output; *p; p++, p2++) {
1343                 if (*p == '\n') { 
1344                         *(p2++)= '\r'; *p2= '\n';
1345                 } else *p2= *p;
1346         }
1347         *p2= 0;
1348         
1349         return(output);
1350 }
1351
1352 void txt_paste_clipboard(Text *text) {
1353
1354         char * buff;
1355         char *temp_buff;
1356         
1357         buff = (char*)getClipboard(0);
1358         if(buff) {
1359                 temp_buff = unixNewLine(buff);
1360                 
1361                 txt_insert_buf(text, temp_buff);
1362                 if(buff){free((void*)buff);}
1363                 if(temp_buff){MEM_freeN(temp_buff);}
1364         }
1365 }
1366
1367 void get_selection_buffer(Text *text)
1368 {
1369         char *buff = getClipboard(1);
1370         txt_insert_buf(text, buff);
1371 }
1372
1373 void txt_copy_clipboard(Text *text) {
1374         char *temp;
1375
1376         txt_copy_selectbuffer(text);
1377
1378         if (copybuffer) {
1379                 copybuffer[bufferlength] = '\0';
1380                 temp = winNewLine(copybuffer);
1381                 
1382                 putClipboard(temp, 0);
1383                 MEM_freeN(temp);
1384                 MEM_freeN(copybuffer);
1385                 copybuffer= NULL;
1386         }
1387 }
1388
1389 /*
1390  * again==0 show find panel or find
1391  * again==1 find text again */
1392 void txt_find_panel(SpaceText *st, int again)
1393 {
1394         Text *text=st->text;
1395         char *findstr= last_txt_find_string;
1396                         
1397         if (again==0) {
1398                 findstr= txt_sel_to_buf(text);
1399         } else if (again==1) {
1400                 char buf[256];
1401
1402         if (findstr && strlen(findstr)<(sizeof(buf)-1))
1403                 strcpy(buf, findstr);
1404         else
1405                 buf[0]= 0;
1406                 
1407         if (sbutton(buf, 0, sizeof(buf)-1, "Find: ") && buf[0])
1408                 findstr= BLI_strdup(buf);
1409         else
1410                 findstr= NULL;
1411         }
1412
1413         if (findstr!=last_txt_find_string) {
1414                 if (last_txt_find_string)
1415                         MEM_freeN(last_txt_find_string);
1416                 last_txt_find_string= findstr;
1417         }
1418                                 
1419         if (findstr) {
1420                 if (txt_find_string(text, findstr))
1421                         pop_space_text(st);
1422                 else
1423                         error("Not found: %s", findstr);
1424         }
1425 }
1426
1427 void run_python_script(SpaceText *st)
1428 {
1429         char *py_filename;
1430         Text *text=st->text;
1431
1432         if (!BPY_txt_do_python_Text(text)) {
1433                 int lineno = BPY_Err_getLinenumber();
1434                 // jump to error if happened in current text:
1435                 py_filename = (char*) BPY_Err_getFilename();
1436
1437                 /* st->text can become NULL: user called Blender.Load(blendfile)
1438                  * before the end of the script. */
1439                 if (!st->text) return;
1440
1441                 if (!strcmp(py_filename, st->text->id.name+2)) {
1442                         error_pyscript(  );
1443                         if (lineno >= 0) {
1444                                 txt_move_toline(text, lineno-1, 0);
1445                                 txt_sel_line(text);
1446                                 pop_space_text(st);
1447                         }       
1448                 } else {
1449                         error("Error in other (possibly external) file, "\
1450                                 "check console");
1451                 }       
1452         }
1453 }
1454
1455 static void set_tabs(Text *text)
1456 {
1457         SpaceText *st = curarea->spacedata.first;
1458         st->currtab_set = setcurr_tab(text);
1459 }
1460
1461 void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
1462 {
1463         unsigned short event= evt->event;
1464         short val= evt->val;
1465         char ascii= evt->ascii;
1466         SpaceText *st= curarea->spacedata.first;
1467         Text *text;
1468         int do_draw=0, p;
1469         
1470         if (st==NULL || st->spacetype != SPACE_TEXT) return;
1471         
1472         /* smartass code to prevent the CTRL/ALT events below from not working! */
1473         if(G.qual & (LR_ALTKEY|LR_CTRLKEY))
1474                 if(!ispunct(ascii)) 
1475                         ascii= 0;
1476
1477         text= st->text;
1478         
1479         if (!text) {
1480                 if (event==RIGHTMOUSE) {
1481                         switch (pupmenu("File %t|New %x0|Open... %x1")) {
1482                         case 0:
1483                                 st->text= add_empty_text("Text");
1484                                 st->top= 0;
1485                         
1486                                 allqueue(REDRAWTEXT, 0);
1487                                 allqueue(REDRAWHEADERS, 0);
1488                                 break;
1489                         case 1:
1490                                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1491                                 break;
1492                         }
1493                 }
1494                 if (val && !ELEM(G.qual, 0, LR_SHIFTKEY)) {
1495                         if (event==FKEY && G.qual == (LR_ALTKEY|LR_SHIFTKEY)) {
1496                                 switch (pupmenu("File %t|New %x0|Open... %x1")) {
1497                                 case 0:
1498                                         st->text= add_empty_text("Text");
1499                                         st->top= 0;
1500                                 
1501                                         allqueue(REDRAWTEXT, 0);
1502                                         allqueue(REDRAWHEADERS, 0);
1503                                         break;
1504                                 case 1:
1505                                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1506                                         break;
1507                                 }
1508                         } 
1509                         else if (event==QKEY) {
1510                                 if (G.qual & LR_CTRLKEY) {
1511                                         if(okee("Quit Blender")) exit_usiblender();
1512                                 }
1513                         }
1514                         else if (event==NKEY) {
1515                                 if (G.qual & LR_ALTKEY) {
1516                                         st->text= add_empty_text("Text");
1517                                         st->top= 0;
1518                                 
1519                                         allqueue(REDRAWTEXT, 0);
1520                                         allqueue(REDRAWHEADERS, 0);
1521                                 }
1522                         }
1523                         else if (event==OKEY) {
1524                                 if (G.qual & LR_ALTKEY) {
1525                                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1526                                 }
1527                         }
1528                 }
1529                 return;
1530         }
1531         
1532         if (event==LEFTMOUSE) {
1533                 if (val) {
1534                         short mval[2];
1535                         char *buffer;
1536                         set_tabs(text);
1537                         getmouseco_areawin(mval);
1538                         
1539                         if (mval[0]>2 && mval[0]<20 && mval[1]>2 && mval[1]<curarea->winy-2) {
1540                                 do_textscroll(st, 2);
1541                         } else {
1542                                 do_selection(st, G.qual&LR_SHIFTKEY);
1543                                 if (txt_has_sel(text)) {
1544                                         buffer = txt_sel_to_buf(text);
1545                                         putClipboard(buffer, 1);
1546                                         MEM_freeN(buffer);
1547                                 }
1548                                 do_draw= 1;
1549                         }
1550                 }
1551         } else if (event==MIDDLEMOUSE) {
1552                 if (val) {
1553                         if (U.uiflag & USER_MMB_PASTE)
1554                         {
1555                                 do_selection(st, G.qual&LR_SHIFTKEY);
1556                                 get_selection_buffer(text);
1557                                 do_draw= 1;
1558                         }
1559                         else
1560                         {
1561                                 do_textscroll(st, 1);
1562                         }
1563                 }
1564         } else if (event==RIGHTMOUSE) {
1565                 if (val) {
1566                         p= pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4");
1567
1568                         switch(p) {
1569                                 case 0:
1570                                         st->text= add_empty_text("Text");
1571                                         st->top= 0;
1572                                         
1573                                         allqueue(REDRAWTEXT, 0);
1574                                         allqueue(REDRAWHEADERS, 0);
1575                                         break;
1576
1577                                 case 1:
1578                                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1579                                         break;
1580                                         
1581                                 case 3:
1582                                         text->flags |= TXT_ISMEM;
1583                                         
1584                                 case 2:
1585                                         txt_write_file(text);
1586                                         do_draw= 1;
1587                                         break;
1588                                 case 4:
1589                                         run_python_script(st);
1590                                         do_draw= 1;
1591                                         break;
1592                                 default:
1593                                         break;
1594                         }
1595                 }
1596         } else if (ascii) {
1597                 if (txt_add_char(text, ascii)) {
1598                         if (st->showsyntax) get_format_string(st);
1599                         pop_space_text(st);
1600                         do_draw= 1;
1601                 }
1602         } else if (val) {
1603                 switch (event) {
1604                 case AKEY:
1605                         if (G.qual & LR_ALTKEY) {
1606                                 txt_move_bol(text, G.qual & LR_SHIFTKEY);
1607                                 do_draw= 1;
1608                                 pop_space_text(st);
1609                         } else if (G.qual & LR_CTRLKEY) {
1610                                 txt_sel_all(text);
1611                                 do_draw= 1;
1612                         }
1613                         break; /* BREAK A */
1614                 case CKEY:
1615                         if (G.qual & LR_ALTKEY || G.qual & LR_CTRLKEY) {
1616                                 if(G.qual & LR_SHIFTKEY)
1617                                         txt_copy_clipboard(text);
1618                                 else
1619                                         txt_copy_clipboard(text);
1620
1621                                 do_draw= 1;     
1622                         }
1623                         break; /* BREAK C */
1624                 case DKEY:
1625                         if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) {
1626                                 //uncommenting
1627                                 txt_order_cursors(text);
1628                                 uncomment(text);
1629                                 do_draw = 1;
1630                                 if (st->showsyntax) get_format_string(st);
1631                                 break;
1632                         } else if (G.qual == LR_CTRLKEY) {
1633                                 txt_delete_char(text);
1634                                 if (st->showsyntax) get_format_string(st);
1635                                 do_draw= 1;
1636                                 pop_space_text(st);
1637                         }
1638                         break; /* BREAK D */
1639                 case EKEY:
1640                         if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) {
1641                                 switch(pupmenu("Edit %t|Cut %x0|Copy %x1|Paste %x2|Print Cut Buffer %x3")) {
1642                                 case 0:
1643                                         txt_copy_clipboard(text); //First copy to clipboard
1644                                         txt_cut_sel(text);
1645                                         do_draw= 1;
1646                                         break;
1647                                 case 1:
1648                                         txt_copy_clipboard(text);
1649                                         //txt_copy_sel(text);
1650                                         do_draw= 1;
1651                                         break;
1652                                 case 2:
1653                                         //txt_paste(text);
1654                                         txt_paste_clipboard(text);
1655                                         if (st->showsyntax) get_format_string(st);
1656                                         do_draw= 1;
1657                                         break;
1658                                 case 3:
1659                                         txt_print_cutbuffer();
1660                                         break;
1661                                 }
1662                         }
1663                         else if (G.qual == LR_CTRLKEY || G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) {
1664                                 txt_move_eol(text, G.qual & LR_SHIFTKEY);
1665                                 do_draw= 1;
1666                                 pop_space_text(st);
1667                         }
1668                         break; /* BREAK E */
1669                 case FKEY:
1670                         if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) {
1671                                 switch(pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3")) {
1672                                 case 0:
1673                                         st->text= add_empty_text("Text");
1674                                         st->top= 0;
1675                                         
1676                                         allqueue(REDRAWTEXT, 0);
1677                                         allqueue(REDRAWHEADERS, 0);
1678                                         break;
1679                                 case 1:
1680                                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1681                                         break;
1682                                 case 3:
1683                                         text->flags |= TXT_ISMEM;
1684                                 case 2:
1685                                         txt_write_file(text);
1686                                         do_draw= 1;
1687                                         break;
1688                                 }
1689                         }
1690                         else if (G.qual == LR_ALTKEY) {
1691                                 if (txt_has_sel(text)) {
1692                                         txt_find_panel(st,0);
1693                                         do_draw= 1;
1694                                 }
1695                         }
1696                         else if (G.qual == (LR_ALTKEY|LR_CTRLKEY)) {    /* always search button */
1697                                 txt_find_panel(st,1);
1698                                 do_draw= 1;
1699                         }
1700                         break; /* BREAK F */
1701                 case JKEY:
1702                         if (G.qual == LR_ALTKEY) {
1703                                 do_draw= jumptoline_interactive(st);
1704                         }
1705                         break; /* BREAK J */
1706                 case MKEY:
1707                         if (G.qual == LR_ALTKEY) {
1708                                 txt_export_to_object(text);
1709                                 do_draw= 1;     
1710                         }
1711                         break; /* BREAK M */
1712                 case NKEY:
1713                         if (G.qual == LR_ALTKEY) {
1714                                 st->text= add_empty_text("Text");
1715                                 st->top= 0;
1716                         
1717                                 allqueue(REDRAWTEXT, 0);
1718                                 allqueue(REDRAWHEADERS, 0);
1719
1720                         }
1721                         break; /* BREAK N */
1722                 case OKEY:
1723                         if (G.qual == LR_ALTKEY) {
1724                                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
1725                         }
1726                         break; /* BREAK O */
1727                 case PKEY:
1728                         if (G.qual == LR_ALTKEY) {
1729                                 run_python_script(st);
1730                                 do_draw= 1;
1731                         }
1732                         break; /* BREAK P */
1733                 case QKEY:
1734                         if(okee("Quit Blender")) exit_usiblender();
1735                         break; /* BREAK Q */
1736                 case RKEY:
1737                         if (G.qual == LR_ALTKEY) {
1738                             if (text->compiled) BPY_free_compiled_text(text);
1739                                 text->compiled = NULL;
1740                                 if (okee("Reopen text")) {
1741                                         if (!reopen_text(text))
1742                                                 error("Could not reopen file");
1743                                 if (st->showsyntax) get_format_string(st);
1744                                 }
1745                                 do_draw= 1;     
1746                         }
1747                         break; /* BREAK R */
1748                 case SKEY:
1749                         if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) {
1750                                 p= pupmenu("Select %t|"
1751                                                         "Select All %x0|"
1752                                                         "Select Line %x1|"
1753                                                         "Jump to Line %x3");
1754                                 switch(p) {
1755                                 case 0:
1756                                         txt_sel_all(text);
1757                                         do_draw= 1;
1758                                         break;
1759                                         
1760                                 case 1:
1761                                         txt_sel_line(text);
1762                                         do_draw= 1;
1763                                         break;
1764                                                                                 
1765                                 case 3:
1766                                         do_draw= jumptoline_interactive(st);
1767                                         break;
1768                                 }
1769                         }
1770                         else if (G.qual & LR_ALTKEY) {
1771                                 /* Event treatment CANNOT enter this if
1772                                 if (G.qual & LR_SHIFTKEY) 
1773                                         if (text) text->flags |= TXT_ISMEM;
1774                                 */
1775                                 txt_write_file(text);
1776                                 do_draw= 1;
1777                         }
1778                         break; /* BREAK S */
1779                 case UKEY:
1780                         //txt_print_undo(text); //debug buffer in console
1781                         if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) {
1782                                 txt_do_redo(text);
1783                                 do_draw= 1;
1784                         }
1785                         if (G.qual == LR_ALTKEY) {
1786                                 txt_do_undo(text);
1787                                 if (st->showsyntax) get_format_string(st);
1788                                 do_draw= 1;
1789                         }
1790                         break; /* BREAK U */
1791                 case VKEY:
1792                         if (G.qual == (LR_ALTKEY| LR_SHIFTKEY)) {
1793                                 switch(pupmenu("View %t|Top of File %x0|Bottom of File %x1|Page Up %x2|Page Down %x3")) {
1794                                 case 0:
1795                                         txt_move_bof(text, 0);
1796                                         do_draw= 1;
1797                                         pop_space_text(st);
1798                                         break;
1799                                 case 1:
1800                                         txt_move_eof(text, 0);
1801                                         do_draw= 1;
1802                                         pop_space_text(st);
1803                                         break;
1804                                 case 2:
1805                                         screen_skip(st, -st->viewlines);
1806                                         do_draw= 1;
1807                                         break;
1808                                 case 3:
1809                                         screen_skip(st, st->viewlines);
1810                                         do_draw= 1;
1811                                         break;
1812                                 }
1813                         }
1814                         /* Support for both Alt-V and Ctrl-V for Paste, for backward compatibility reasons */
1815                         else if (G.qual & LR_ALTKEY || G.qual & LR_CTRLKEY) {
1816                                 /* Throwing in the Shift modifier Paste from the OS clipboard */
1817                                 if (G.qual & LR_SHIFTKEY)
1818                                         txt_paste_clipboard(text);
1819                                 else
1820                                         txt_paste_clipboard(text);
1821                                 if (st->showsyntax) get_format_string(st);
1822                                 do_draw= 1;     
1823                                 pop_space_text(st);
1824                         }
1825                         break; /* BREAK V */
1826                 case XKEY:
1827                         if (G.qual == LR_ALTKEY || G.qual == LR_CTRLKEY) {
1828                                 txt_cut_sel(text);
1829                                 if (st->showsyntax) get_format_string(st);
1830                                 do_draw= 1;     
1831                                 pop_space_text(st);
1832                         }
1833                         break;
1834                 case ZKEY:
1835                         if (G.qual & (LR_ALTKEY|LR_CTRLKEY|LR_COMMANDKEY)) {
1836                                 if (G.qual & LR_SHIFTKEY) {
1837                                         txt_do_redo(text);
1838                                 } else {
1839                                         txt_do_undo(text);
1840                                 }
1841                                 if (st->showsyntax) get_format_string(st);
1842                                 do_draw= 1;
1843                         }
1844                         break;
1845                 case TABKEY:
1846                         if (G.qual & LR_SHIFTKEY) {
1847                                 if (txt_has_sel(text)) {
1848                                         txt_order_cursors(text);
1849                                         unindent(text);
1850                                         
1851                                 }
1852                         } else {
1853                                 if ( txt_has_sel(text)) {
1854                                         txt_order_cursors(text);
1855                                         indent(text);
1856                                 } else {
1857                                         txt_add_char(text, '\t');
1858                                 }
1859                         }
1860                         if (st->showsyntax) get_format_string(st);
1861                         pop_space_text(st);
1862                         do_draw= 1;
1863                         st->currtab_set = setcurr_tab(text);
1864                         break;
1865                 case RETKEY:
1866                         //double check tabs before splitting the line
1867                         st->currtab_set = setcurr_tab(text);
1868                         txt_split_curline(text);
1869                         {
1870                                 int a = 0;
1871                                 if (a < st->currtab_set)
1872                                 {
1873                                         while ( a < st->currtab_set) {
1874                                                 txt_add_char(text, '\t');
1875                                                 a++;
1876                                         }
1877                                 }
1878                         }
1879                         if (st->showsyntax) get_format_string(st);
1880                         do_draw= 1;
1881                         pop_space_text(st);
1882                         break;
1883                 case BACKSPACEKEY:
1884                         txt_backspace_char(text);
1885                         set_tabs(text);
1886                         if (st->showsyntax) get_format_string(st);
1887                         do_draw= 1;
1888                         pop_space_text(st);
1889                         break;
1890                 case DELKEY:
1891                         txt_delete_char(text);
1892                         if (st->showsyntax) get_format_string(st);
1893                         do_draw= 1;
1894                         pop_space_text(st);
1895                         st->currtab_set = setcurr_tab(text);
1896                         break;
1897                 case DOWNARROWKEY:
1898                         txt_move_down(text, G.qual & LR_SHIFTKEY);
1899                         set_tabs(text);
1900                         do_draw= 1;
1901                         pop_space_text(st);
1902                         break;
1903                 case LEFTARROWKEY:
1904                         if (G.qual & LR_COMMANDKEY)
1905                                 txt_move_bol(text, G.qual & LR_SHIFTKEY);
1906                         else
1907                                 txt_move_left(text, G.qual & LR_SHIFTKEY);
1908                         set_tabs(text);
1909                         do_draw= 1;
1910                         pop_space_text(st);
1911                         break;
1912                 case RIGHTARROWKEY:
1913                         if (G.qual & LR_COMMANDKEY)
1914                                 txt_move_eol(text, G.qual & LR_SHIFTKEY);
1915                         else
1916                                 txt_move_right(text, G.qual & LR_SHIFTKEY);
1917                         set_tabs(text);
1918                         do_draw= 1;
1919                         pop_space_text(st);
1920                         break;
1921                 case UPARROWKEY:
1922                         txt_move_up(text, G.qual & LR_SHIFTKEY);
1923                         set_tabs(text);
1924                         do_draw= 1;
1925                         pop_space_text(st);
1926                         break;
1927                 case PAGEDOWNKEY:
1928                         screen_skip(st, st->viewlines);
1929                         do_draw= 1;
1930                         break;
1931                 case PAGEUPKEY:
1932                         screen_skip(st, -st->viewlines);
1933                         do_draw= 1;
1934                         break;
1935                 case HOMEKEY:
1936                         txt_move_bol(text, G.qual & LR_SHIFTKEY);
1937                         do_draw= 1;
1938                         pop_space_text(st);
1939                         break;
1940                 case ENDKEY:
1941                         txt_move_eol(text, G.qual & LR_SHIFTKEY);
1942                         do_draw= 1;
1943                         pop_space_text(st);
1944                         break;
1945                 case WHEELUPMOUSE:
1946                         screen_skip(st, -U.wheellinescroll);
1947                         do_draw= 1;
1948                         break;
1949                 case WHEELDOWNMOUSE:
1950                         screen_skip(st, U.wheellinescroll);
1951                         do_draw= 1;
1952                         break;
1953                 }
1954         }
1955
1956         if (do_draw) {
1957                 ScrArea *sa;
1958                 
1959                 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1960                         SpaceText *st= sa->spacedata.first;
1961                         
1962                         if (st && st->spacetype==SPACE_TEXT) {
1963                                 scrarea_queue_redraw(sa);
1964                         }
1965                 }
1966         }
1967 }
1968
1969 void do_brackets(void) 
1970 {
1971         SpaceText *st = curarea->spacedata.first;
1972         Text *text = st->text;
1973         TextLine *tmp, *start;
1974         char test[2];
1975         int d, pos, open, x, y, x2, y2, h=0;
1976         
1977         if(!text) return;
1978         
1979         tmp = text->curl;
1980         start = text->curl;
1981
1982         test[0] = (unsigned char) tmp->line[text->curc];
1983         test[1] = '\0';
1984         
1985         d = check_bracket(test);
1986         if (!d) /*  If not pri char */
1987         {
1988                 test[0] = (unsigned char) tmp->line[text->curc-1];
1989                 test[1] = '\0';
1990                 d = check_bracket(test);
1991                 if(!d) {
1992                         return; /*If the current char or prev is not a bracket then return*/
1993                 } else { /* current char */
1994                         h= txt_get_span(text->lines.first, start) - st->top;
1995                         x = text_draw(st, start->line, st->left, text->curc-1, 0, 0, 0, NULL);
1996                         y = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL);
1997                         if (d < 4) {
1998                                 pos = text->curc;
1999                         } else {
2000                                 pos = text->curc-2;
2001                         }
2002                 }
2003         } else { /* is pri char */
2004                 h= txt_get_span(text->lines.first, start) - st->top;
2005                 x = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL);
2006                 y = text_draw(st, start->line, st->left, text->curc+1, 0, 0, 0, NULL);
2007                 if (d < 4) {
2008                         pos = text->curc+1;
2009                 } else {
2010                         pos = text->curc-1;
2011                 }
2012         }
2013         
2014         if (d < 4) /*reading forward*/
2015         {
2016                 open = 1; 
2017                 while ( tmp ) {
2018                         while (pos <= tmp->len) {
2019                                 test[0] = (unsigned char) tmp->line[pos];
2020                                 test[1] = '\0';
2021                                 if(check_bracket(test) == d) {
2022                                         open++;
2023                                 } else if (check_bracket(test) == d+3) {
2024                                         open--;
2025                                         if (open == 0) {
2026                                                 BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5);
2027                                                 glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2);
2028
2029                                                 h= txt_get_span(text->lines.first, tmp) - st->top;
2030                                                 x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL);
2031                                                 y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL);
2032                                                 glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2);
2033                                                 BIF_ThemeColor(TH_TEXT);
2034                                                 return;
2035                                         }
2036                                 }
2037                                 pos++;
2038                         }
2039                         tmp = tmp->next;
2040                         pos = 0;
2041                 }
2042         } else { /*  reading back */
2043                 open = 1; 
2044                 while ( tmp ) {
2045                         while (pos >= 0) {
2046                                 test[0] = (unsigned char) tmp->line[pos];
2047                                 test[1] = '\0';
2048                                 if(check_bracket(test) == d) {
2049                                         open++;
2050                                 } else if (check_bracket(test) == d-3) {
2051                                         open--;
2052                                         if (open == 0) {
2053                                                 BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5);
2054                                                 glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2);
2055
2056                                                 h= txt_get_span(text->lines.first, tmp) - st->top;
2057                                                 x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL);
2058                                                 y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL);
2059                                                 glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2);
2060                                                 BIF_ThemeColor(TH_TEXT);
2061                                                 return;
2062                                         }
2063                                 }
2064                                 pos--;
2065                         }
2066                         tmp = tmp->prev;
2067                         if (tmp) {
2068                                 pos = tmp->len;
2069                         }
2070                 }
2071         }
2072         
2073 }
2074
2075 int check_bracket(char *string)
2076 {
2077         int number, a = 0;
2078         char other[][3] = {"(", "[", "{", ")", "]", "}"};
2079         
2080         number = 6;
2081         
2082         while(a < number) {
2083                 if(strcmp(other[a], string) == 0)
2084                 {
2085                         return a+1;
2086                 }
2087                 a++;
2088         }
2089         return 0;
2090 }
2091
2092 static int check_builtinfuncs(char *string) 
2093 {
2094         int number = 30, a = 0;
2095         
2096         char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def",
2097                                                                 "del", "elif", "else", "except", "exec", "finally",
2098                                                                 "for", "from", "global", "if", "import", "in",
2099                                                                 "is", "lambda", "not", "or", "pass", "print",
2100                                                                 "raise", "return", "try", "while", "yield"};
2101
2102         for( a = 0; a < number; a++) {
2103                 if(!strcmp(builtinfuncs[a], string))
2104                         return 1;
2105         }
2106         return 0;
2107 }
2108
2109 static int check_specialvars(char *string) 
2110 {
2111         int number = 2, a = 0;
2112         char specialvars[][7] = {"def", "class"};
2113         
2114         for( a = 0; a < number; a++) {
2115                 if(!strcmp(specialvars[a], string))
2116                         return a+1;
2117         }
2118         return 0;
2119 }
2120
2121 static int check_delim(char *string) 
2122 {
2123         int number = 28, a = 0;
2124         char other[][3] = {"(", ")", ":", "\"", "\'", " ", "~", "!", "%", "^", "&", "*", "-", "+", "=", "[", "]", "{", "}", ";", "/", "<", ">", "|", ".", "#", "\t", ","};
2125         
2126         for( a = 0; a < number; a++) {
2127                 if(!strcmp(other[a], string))
2128                         return 1;
2129         }
2130         return 0;
2131 }
2132
2133 static int check_numbers(char *string)
2134 {
2135         int number = 10, a = 0;
2136         char other[][2] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2137         
2138         for( a = 0; a < number; a++) {
2139                 if(!strcmp(other[a], string))
2140                         return 1;
2141         }
2142         return 0;
2143 }
2144
2145 void convert_tabs (struct SpaceText *st, int tab)
2146 {
2147         Text *text = st->text;
2148         TextLine *tmp;
2149         char *check_line, *new_line, *format;
2150         int extra, number; //unknown for now
2151         size_t a, j;
2152         
2153         if (!text) return;
2154         
2155         tmp = text->lines.first;
2156         
2157         //first convert to all space, this make it alot easier to convert to tabs because there is no mixtures of ' ' && '\t'
2158         while(tmp) {
2159                 check_line = tmp->line;
2160                 new_line = MEM_mallocN(render_string(st, check_line)+1, "Converted_Line");
2161                 format = MEM_mallocN(render_string(st, check_line)+1, "Converted_Syntax_format");
2162                 j = 0;
2163                 for (a=0; a < strlen(check_line); a++) { //foreach char in line
2164                         if(check_line[a] == '\t') { //checking for tabs
2165                                 //get the number of spaces this tabs is showing
2166                                 //i dont like doing it this way but will look into it later
2167                                 new_line[j] = '\0';
2168                                 number = render_string(st, new_line);
2169                                 new_line[j] = '\t';
2170                                 new_line[j+1] = '\0';
2171                                 number = render_string(st, new_line)-number;
2172                                 for(extra = 0; extra < number; extra++) {
2173                                         new_line[j] = ' ';
2174                                         j++;
2175                                 }
2176                         } else {
2177                                 new_line[j] = check_line[a];
2178                                 ++j;
2179                         }
2180                 }
2181                 new_line[j] = '\0';
2182                 // put new_line in the tmp->line spot still need to try and set the curc correctly
2183                 if (tmp->line) MEM_freeN(tmp->line);
2184                 if(tmp->format) MEM_freeN(tmp->format);
2185                 
2186                 tmp->line = new_line;
2187                 tmp->len = strlen(new_line);
2188                 tmp->format = format;
2189                 tmp = tmp->next;
2190         }
2191         
2192         if (tab) // Converting to tabs
2193         {       //start over from the begining
2194                 tmp = text->lines.first;
2195                 
2196                 while(tmp) {
2197                         check_line = tmp->line;
2198                         extra = 0;
2199                         for (a = 0; a < strlen(check_line); a++) {
2200                                 number = 0;
2201                                 for (j = 0; j < (size_t)st->tabnumber; j++) {
2202                                         if ((a+j) <= strlen(check_line)) { //check to make sure we are not pass the end of the line
2203                                                 if(check_line[a+j] != ' ') {
2204                                                         number = 1;
2205                                                 }
2206                                         }
2207                                 }
2208                                 if (!number) { //found all number of space to equal a tab
2209                                         a = a+(st->tabnumber-1);
2210                                         extra = extra+1;
2211                                 }
2212                         }
2213                         
2214                         if ( extra > 0 ) { //got tabs make malloc and do what you have to do
2215                                 new_line = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Line");
2216                                 format = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Syntax_format");
2217                                 extra = 0; //reuse vars
2218                                 for (a = 0; a < strlen(check_line); a++) {
2219                                         number = 0;
2220                                         for (j = 0; j < (size_t)st->tabnumber; j++) {
2221                                                 if ((a+j) <= strlen(check_line)) { //check to make sure we are not pass the end of the line
2222                                                         if(check_line[a+j] != ' ') {
2223                                                                 number = 1;
2224                                                         }
2225                                                 }
2226                                         }
2227                                         if (!number) { //found all number of space to equal a tab
2228                                                 new_line[extra] = '\t';
2229                                                 a = a+(st->tabnumber-1);
2230                                                 ++extra;
2231                                                 
2232                                         } else { //not adding a tab
2233                                                 new_line[extra] = check_line[a];
2234                                                 ++extra;
2235                                         }
2236                                 }
2237                                 new_line[extra] = '\0';
2238                                 // put new_line in the tmp->line spot still need to try and set the curc correctly
2239                                 if (tmp->line) MEM_freeN(tmp->line);
2240                                 if(tmp->format) MEM_freeN(tmp->format);
2241                                 
2242                                 tmp->line = new_line;
2243                                 tmp->len = strlen(new_line);
2244                                 tmp->format = format;
2245                         }
2246                         tmp = tmp->next;
2247                 }
2248         }
2249 }