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