Fix compiling error.
[plumiferos.git] / source / blender / blenkernel / intern / text.c
blob82555335ceff88911c781bd47a9d0d5f074518f5
1 /* text.c
4 * $Id: text.c 10247 2007-03-12 06:21:58Z campbellbarton $
6 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version. The Blender
12 * Foundation also sells licenses for use in proprietary software under
13 * the Blender License. See http://www.blender.org/BL/ for information
14 * about this.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26 * All rights reserved.
28 * The Original Code is: all of this file.
30 * Contributor(s): none yet.
32 * ***** END GPL/BL DUAL LICENSE BLOCK *****
35 #include <string.h> /* strstr */
37 #include "MEM_guardedalloc.h"
39 #include "BLI_blenlib.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_text_types.h"
44 #include "BKE_bad_level_calls.h"
45 #include "BKE_utildefines.h"
46 #include "BKE_text.h"
47 #include "BKE_library.h"
48 #include "BKE_global.h"
49 #include "BKE_main.h"
51 #include "BPY_extern.h"
53 #ifdef HAVE_CONFIG_H
54 #include <config.h>
55 #endif
57 /***************/ /*
59 How Texts should work
61 A text should relate to a file as follows -
62 (Text *)->name should be the place where the
63 file will or has been saved.
65 (Text *)->flags has the following bits
66 TXT_ISDIRTY - should always be set if the file in mem. differs from
67 the file on disk, or if there is no file on disk.
68 TXT_ISTMP - should always be set if the (Text *)->name file has not
69 been written before, and attempts to save should result
70 in "Save over?"
71 TXT_ISMEM - should always be set if the Text has not been mapped to
72 a file, in which case (Text *)->name may be NULL or garbage.
73 TXT_ISEXT - should always be set if the Text is not to be written into
74 the .blend
75 TXT_ISSCRIPT - should be set if the user has designated the text
76 as a script. (NEW: this was unused, but now it is needed by
77 space handler script links (see header_view3d.c, for example)
79 ->>> see also: /makesdna/DNA_text_types.h
81 Display
83 The st->top determines at what line the top of the text is displayed.
84 If the user moves the cursor the st containing that cursor should
85 be popped ... other st's retain their own top location.
87 */ /***************/
90 /****************/ /*
91 Undo
93 Undo/Redo works by storing
94 events in a queue, and a pointer
95 to the current position in the
96 queue...
98 Events are stored using an
99 arbitrary op-code system
100 to keep track of
101 a) the two cursors (normal and selected)
102 b) input (visible and control (ie backspace))
104 input data is stored as its
105 ASCII value, the opcodes are
106 then selected to not conflict.
108 opcodes with data in between are
109 written at the beginning and end
110 of the data to allow undo and redo
111 to simply check the code at the current
112 undo position
114 */ /***************/
116 /***/
118 static void txt_pop_first(Text *text);
119 static void txt_pop_last(Text *text);
120 static void txt_undo_add_op(Text *text, int op);
121 static void txt_undo_add_block(Text *text, int op, char *buf);
122 static void txt_delete_line(Text *text, TextLine *line);
124 /***/
126 static char *txt_cut_buffer= NULL;
127 static unsigned char undoing;
129 /* allow to switch off undoing externally */
130 void txt_set_undostate(int u)
132 undoing = u;
135 int txt_get_undostate(void)
137 return undoing;
140 void free_text(Text *text)
142 TextLine *tmp;
144 for (tmp= text->lines.first; tmp; tmp= tmp->next) {
145 MEM_freeN(tmp->line);
146 if (tmp->format)
147 MEM_freeN(tmp->format);
150 BLI_freelistN(&text->lines);
152 if(text->name) MEM_freeN(text->name);
153 MEM_freeN(text->undo_buf);
154 if (text->compiled) BPY_free_compiled_text(text);
157 Text *add_empty_text(char *name)
159 Text *ta;
160 TextLine *tmp;
162 ta= alloc_libblock(&G.main->text, ID_TXT, name);
163 ta->id.us= 1;
165 ta->name= NULL;
167 ta->undo_pos= -1;
168 ta->undo_len= TXT_INIT_UNDO;
169 ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
171 ta->nlines=1;
172 ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
174 ta->lines.first= ta->lines.last= NULL;
176 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
177 tmp->line= (char*) MEM_mallocN(1, "textline_string");
178 tmp->format= (char*) MEM_mallocN(2, "Syntax_format");
180 tmp->line[0]=0;
181 tmp->len= 0;
183 tmp->next= NULL;
184 tmp->prev= NULL;
186 BLI_addhead(&ta->lines, tmp);
188 ta->curl= ta->lines.first;
189 ta->curc= 0;
190 ta->sell= ta->lines.first;
191 ta->selc= 0;
193 return ta;
196 // this function removes any control characters from
197 // a textline
199 static void cleanup_textline(TextLine * tl)
201 int i;
203 for (i = 0; i < tl->len; i++ ) {
204 if (tl->line[i] < ' ' && tl->line[i] != '\t') {
205 memmove(tl->line + i, tl->line + i + 1, tl->len - i);
206 tl->len--;
207 i--;
212 int reopen_text(Text *text)
214 FILE *fp;
215 int i, llen, len;
216 unsigned char *buffer;
217 TextLine *tmp;
218 char sdir[FILE_MAXDIR];
219 char sfile[FILE_MAXFILE];
220 char str[FILE_MAXDIR+FILE_MAXFILE];
222 if (!text || !text->name) return 0;
224 BLI_strncpy(str, text->name, FILE_MAXDIR+FILE_MAXFILE);
225 BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
226 BLI_split_dirfile(str, sdir, sfile);
228 fp= fopen(str, "r");
229 if(fp==NULL) return 0;
231 /* free memory: */
233 for (tmp= text->lines.first; tmp; tmp= tmp->next) {
234 MEM_freeN(tmp->line);
235 if (tmp->format) MEM_freeN(tmp->format);
238 BLI_freelistN(&text->lines);
240 text->lines.first= text->lines.last= NULL;
241 text->curl= text->sell= NULL;
243 /* clear undo buffer */
244 MEM_freeN(text->undo_buf);
245 text->undo_pos= -1;
246 text->undo_len= TXT_INIT_UNDO;
247 text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
249 text->flags= TXT_ISDIRTY | TXT_ISTMP;
251 fseek(fp, 0L, SEEK_END);
252 len= ftell(fp);
253 fseek(fp, 0L, SEEK_SET);
255 text->undo_pos= -1;
257 buffer= MEM_mallocN(len, "text_buffer");
258 // under windows fread can return less then len bytes because
259 // of CR stripping
260 len = fread(buffer, 1, len, fp);
262 fclose(fp);
264 text->nlines=0;
265 i=0;
266 llen=0;
267 for(i=0; i<len; i++) {
268 if (buffer[i]=='\n') {
269 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
270 tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
271 tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
273 if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
274 tmp->line[llen]=0;
275 tmp->len= llen;
277 cleanup_textline(tmp);
279 BLI_addtail(&text->lines, tmp);
280 text->nlines++;
282 llen=0;
283 continue;
285 llen++;
288 if (llen!=0 || text->nlines==0) {
289 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
290 tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
291 tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
293 if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
295 tmp->line[llen]=0;
296 tmp->len= llen;
298 cleanup_textline(tmp);
300 BLI_addtail(&text->lines, tmp);
301 text->nlines++;
304 text->curl= text->sell= text->lines.first;
305 text->curc= text->selc= 0;
307 MEM_freeN(buffer);
308 return 1;
311 Text *add_text(char *file)
313 FILE *fp;
314 int i, llen, len;
315 unsigned char *buffer;
316 TextLine *tmp;
317 Text *ta;
318 char sdir[FILE_MAXDIR];
319 char sfile[FILE_MAXFILE];
320 char str[FILE_MAXDIR+FILE_MAXFILE];
322 BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE);
323 if (G.scene) /* can be NULL (bg mode) */
324 BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
325 BLI_split_dirfile(str, sdir, sfile);
327 fp= fopen(str, "r");
328 if(fp==NULL) return NULL;
330 ta= alloc_libblock(&G.main->text, ID_TXT, sfile);
331 ta->id.us= 1;
333 ta->lines.first= ta->lines.last= NULL;
334 ta->curl= ta->sell= NULL;
336 /* ta->flags= TXT_ISTMP | TXT_ISEXT; */
337 ta->flags= TXT_ISTMP;
339 fseek(fp, 0L, SEEK_END);
340 len= ftell(fp);
341 fseek(fp, 0L, SEEK_SET);
343 ta->name= MEM_mallocN(strlen(file)+1, "text_name");
344 strcpy(ta->name, file);
346 ta->undo_pos= -1;
347 ta->undo_len= TXT_INIT_UNDO;
348 ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf");
350 buffer= MEM_mallocN(len, "text_buffer");
351 // under windows fread can return less then len bytes because
352 // of CR stripping
353 len = fread(buffer, 1, len, fp);
355 fclose(fp);
357 ta->nlines=0;
358 i=0;
359 llen=0;
360 for(i=0; i<len; i++) {
361 if (buffer[i]=='\n') {
362 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
363 tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
364 tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
366 if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
367 tmp->line[llen]=0;
368 tmp->len= llen;
370 cleanup_textline(tmp);
372 BLI_addtail(&ta->lines, tmp);
373 ta->nlines++;
375 llen=0;
376 continue;
378 llen++;
381 if (llen!=0 || ta->nlines==0) {
382 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
383 tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
384 tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
386 if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
388 tmp->line[llen]=0;
389 tmp->len= llen;
391 cleanup_textline(tmp);
393 BLI_addtail(&ta->lines, tmp);
394 ta->nlines++;
397 ta->curl= ta->sell= ta->lines.first;
398 ta->curc= ta->selc= 0;
400 MEM_freeN(buffer);
402 return ta;
405 Text *copy_text(Text *ta)
407 Text *tan;
408 TextLine *line, *tmp;
410 tan= copy_libblock(ta);
412 tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name");
413 strcpy(tan->name, ta->name);
415 tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
417 tan->lines.first= tan->lines.last= NULL;
418 tan->curl= tan->sell= NULL;
420 tan->nlines= ta->nlines;
422 line= ta->lines.first;
423 /* Walk down, reconstructing */
424 while (line) {
425 tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
426 tmp->line= MEM_mallocN(line->len+1, "textline_string");
427 tmp->format= MEM_mallocN(line->len+2, "Syntax_format");
429 strcpy(tmp->line, line->line);
431 tmp->len= line->len;
433 BLI_addtail(&tan->lines, tmp);
435 line= line->next;
438 tan->curl= tan->sell= tan->lines.first;
439 tan->curc= tan->selc= 0;
441 return tan;
444 /*****************************/
445 /* Editing utility functions */
446 /*****************************/
448 static void make_new_line (TextLine *line, char *newline, char *newformat)
450 if (line->line) MEM_freeN(line->line);
451 if (line->format) MEM_freeN(line->format);
453 line->line= newline;
454 line->len= strlen(newline);
455 line->format= newformat;
458 static TextLine *txt_new_line(char *str)
460 TextLine *tmp;
462 if(!str) str= "";
464 tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
465 tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
466 tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format");
468 strcpy(tmp->line, str);
470 tmp->len= strlen(str);
471 tmp->next= tmp->prev= NULL;
473 return tmp;
476 static TextLine *txt_new_linen(char *str, int n)
478 TextLine *tmp;
480 if(!str) str= "";
482 tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
483 tmp->line= MEM_mallocN(n+1, "textline_string");
484 tmp->format= MEM_mallocN(n+2, "Syntax_format");
486 BLI_strncpy(tmp->line, str, n+1);
488 tmp->len= strlen(tmp->line);
489 tmp->next= tmp->prev= NULL;
491 return tmp;
494 void txt_clean_text (Text *text)
496 TextLine **top, **bot;
498 if (!text) return;
500 if (!text->lines.first) {
501 if (text->lines.last) text->lines.first= text->lines.last;
502 else text->lines.first= text->lines.last= txt_new_line(NULL);
505 if (!text->lines.last) text->lines.last= text->lines.first;
507 top= (TextLine **) &text->lines.first;
508 bot= (TextLine **) &text->lines.last;
510 while ((*top)->prev) *top= (*top)->prev;
511 while ((*bot)->next) *bot= (*bot)->next;
513 if(!text->curl) {
514 if(text->sell) text->curl= text->sell;
515 else text->curl= text->lines.first;
516 text->curc= 0;
519 if(!text->sell) {
520 text->sell= text->curl;
521 text->selc= 0;
525 int txt_get_span (TextLine *from, TextLine *to)
527 int ret=0;
528 TextLine *tmp= from;
530 if (!to || !from) return 0;
531 if (from==to) return 0;
533 /* Look forwards */
534 while (tmp) {
535 if (tmp == to) return ret;
536 ret++;
537 tmp= tmp->next;
540 /* Look backwards */
541 if (!tmp) {
542 tmp= from;
543 ret=0;
544 while(tmp) {
545 if (tmp == to) break;
546 ret--;
547 tmp= tmp->prev;
549 if(!tmp) ret=0;
552 return ret;
555 static void txt_make_dirty (Text *text)
557 text->flags |= TXT_ISDIRTY;
558 if (text->compiled) BPY_free_compiled_text(text);
561 /****************************/
562 /* Cursor utility functions */
563 /****************************/
565 static void txt_curs_cur (Text *text, TextLine ***linep, int **charp)
567 *linep= &text->curl; *charp= &text->curc;
570 static void txt_curs_sel (Text *text, TextLine ***linep, int **charp)
572 *linep= &text->sell; *charp= &text->selc;
575 static void txt_curs_first (Text *text, TextLine **linep, int *charp)
577 if (text->curl==text->sell) {
578 *linep= text->curl;
579 if (text->curc<text->selc) *charp= text->curc;
580 else *charp= text->selc;
581 } else if (txt_get_span(text->lines.first, text->curl)<txt_get_span(text->lines.first, text->sell)) {
582 *linep= text->curl;
583 *charp= text->curc;
584 } else {
585 *linep= text->sell;
586 *charp= text->selc;
590 /****************************/
591 /* Cursor movement functions */
592 /****************************/
594 void txt_move_up(Text *text, short sel)
596 TextLine **linep;
597 int *charp, old;
599 if (!text) return;
600 if(sel) txt_curs_sel(text, &linep, &charp);
601 else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
602 if (!*linep) return;
603 old= *charp;
605 if((*linep)->prev) {
606 *linep= (*linep)->prev;
607 if (*charp > (*linep)->len) {
608 *charp= (*linep)->len;
609 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp);
610 } else {
611 if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
613 } else {
614 *charp= 0;
615 if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
618 if(!sel) txt_pop_sel(text);
621 void txt_move_down(Text *text, short sel)
623 TextLine **linep;
624 int *charp, old;
626 if (!text) return;
627 if(sel) txt_curs_sel(text, &linep, &charp);
628 else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
629 if (!*linep) return;
630 old= *charp;
632 if((*linep)->next) {
633 *linep= (*linep)->next;
634 if (*charp > (*linep)->len) {
635 *charp= (*linep)->len;
636 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
637 } else
638 if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
639 } else {
640 *charp= (*linep)->len;
641 if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
644 if(!sel) txt_pop_sel(text);
647 void txt_move_left(Text *text, short sel)
649 TextLine **linep;
650 int *charp, oundoing= undoing;
652 if (!text) return;
653 if(sel) txt_curs_sel(text, &linep, &charp);
654 else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
655 if (!*linep) return;
657 undoing= 1;
658 if (*charp== 0) {
659 if ((*linep)->prev) {
660 txt_move_up(text, sel);
661 *charp= (*linep)->len;
663 } else {
664 (*charp)--;
666 undoing= oundoing;
667 if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT);
669 if(!sel) txt_pop_sel(text);
672 void txt_move_right(Text *text, short sel)
674 TextLine **linep;
675 int *charp, oundoing= undoing;
677 if (!text) return;
678 if(sel) txt_curs_sel(text, &linep, &charp);
679 else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
680 if (!*linep) return;
682 undoing= 1;
683 if (*charp== (*linep)->len) {
684 if ((*linep)->next) {
685 txt_move_down(text, sel);
686 *charp= 0;
688 } else {
689 (*charp)++;
691 undoing= oundoing;
692 if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT);
694 if(!sel) txt_pop_sel(text);
697 void txt_move_bol (Text *text, short sel)
699 TextLine **linep;
700 int *charp, old;
702 if (!text) return;
703 if(sel) txt_curs_sel(text, &linep, &charp);
704 else txt_curs_cur(text, &linep, &charp);
705 if (!*linep) return;
706 old= *charp;
708 *charp= 0;
710 if(!sel) txt_pop_sel(text);
711 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
714 void txt_move_eol (Text *text, short sel)
716 TextLine **linep;
717 int *charp, old;
719 if (!text) return;
720 if(sel) txt_curs_sel(text, &linep, &charp);
721 else txt_curs_cur(text, &linep, &charp);
722 if (!*linep) return;
723 old= *charp;
725 *charp= (*linep)->len;
727 if(!sel) txt_pop_sel(text);
728 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
731 void txt_move_bof (Text *text, short sel)
733 TextLine **linep;
734 int *charp, old;
736 if (!text) return;
737 if(sel) txt_curs_sel(text, &linep, &charp);
738 else txt_curs_cur(text, &linep, &charp);
739 if (!*linep) return;
740 old= *charp;
742 *linep= text->lines.first;
743 *charp= 0;
745 if(!sel) txt_pop_sel(text);
746 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
749 void txt_move_eof (Text *text, short sel)
751 TextLine **linep;
752 int *charp, old;
754 if (!text) return;
755 if(sel) txt_curs_sel(text, &linep, &charp);
756 else txt_curs_cur(text, &linep, &charp);
757 if (!*linep) return;
758 old= *charp;
760 *linep= text->lines.last;
761 *charp= (*linep)->len;
763 if(!sel) txt_pop_sel(text);
764 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
767 void txt_move_toline (Text *text, unsigned int line, short sel)
769 TextLine **linep, *oldl;
770 int *charp, oldc;
771 unsigned int i;
773 if (!text) return;
774 if(sel) txt_curs_sel(text, &linep, &charp);
775 else txt_curs_cur(text, &linep, &charp);
776 if (!*linep) return;
777 oldc= *charp;
778 oldl= *linep;
780 *linep= text->lines.first;
781 for (i=0; i<line; i++) {
782 if ((*linep)->next) *linep= (*linep)->next;
783 else break;
785 *charp= 0;
787 if(!sel) txt_pop_sel(text);
788 if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
791 /****************************/
792 /* Text selection functions */
793 /****************************/
795 static void txt_curs_swap (Text *text)
797 TextLine *tmpl;
798 int tmpc;
800 tmpl= text->curl;
801 text->curl= text->sell;
802 text->sell= tmpl;
804 tmpc= text->curc;
805 text->curc= text->selc;
806 text->selc= tmpc;
808 if(!undoing) txt_undo_add_op(text, UNDO_SWAP);
811 static void txt_pop_first (Text *text)
814 if (txt_get_span(text->curl, text->sell)<0 ||
815 (text->curl==text->sell && text->curc>text->selc)) {
816 txt_curs_swap(text);
819 if(!undoing) txt_undo_add_toop(text, UNDO_STO,
820 txt_get_span(text->lines.first, text->sell),
821 text->selc,
822 txt_get_span(text->lines.first, text->curl),
823 text->curc);
825 txt_pop_sel(text);
828 static void txt_pop_last (Text *text)
830 if (txt_get_span(text->curl, text->sell)>0 ||
831 (text->curl==text->sell && text->curc<text->selc)) {
832 txt_curs_swap(text);
835 if(!undoing) txt_undo_add_toop(text, UNDO_STO,
836 txt_get_span(text->lines.first, text->sell),
837 text->selc,
838 txt_get_span(text->lines.first, text->curl),
839 text->curc);
841 txt_pop_sel(text);
844 /* never used: CVS 1.19 */
845 /* static void txt_pop_selr (Text *text) */
847 void txt_pop_sel (Text *text)
849 text->sell= text->curl;
850 text->selc= text->curc;
853 void txt_order_cursors(Text *text)
855 if (!text) return;
856 if (!text->curl) return;
857 if (!text->sell) return;
859 /* Flip so text->curl is before text->sell */
860 if (txt_get_span(text->curl, text->sell)<0 ||
861 (text->curl==text->sell && text->curc>text->selc))
862 txt_curs_swap(text);
865 int txt_has_sel(Text *text)
867 return ((text->curl!=text->sell) || (text->curc!=text->selc));
870 static void txt_delete_sel (Text *text)
872 TextLine *tmpl;
873 char *buf, *format;
875 if (!text) return;
876 if (!text->curl) return;
877 if (!text->sell) return;
879 if (!txt_has_sel(text)) return;
881 txt_order_cursors(text);
883 if(!undoing) {
884 buf= txt_sel_to_buf(text);
885 txt_undo_add_block(text, UNDO_DBLOCK, buf);
886 MEM_freeN(buf);
889 buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
890 format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format");
892 strncpy(buf, text->curl->line, text->curc);
893 strcpy(buf+text->curc, text->sell->line + text->selc);
894 buf[text->curc+(text->sell->len - text->selc)]=0;
896 make_new_line(text->curl, buf, format);
898 tmpl= text->sell;
899 while (tmpl != text->curl) {
900 tmpl= tmpl->prev;
901 if (!tmpl) break;
903 txt_delete_line(text, tmpl->next);
906 text->sell= text->curl;
907 text->selc= text->curc;
910 void txt_sel_all (Text *text)
912 if (!text) return;
914 text->curl= text->lines.first;
915 text->curc= 0;
917 text->sell= text->lines.last;
918 text->selc= text->sell->len;
921 void txt_sel_line (Text *text)
923 if (!text) return;
924 if (!text->curl) return;
926 text->curc= 0;
927 text->sell= text->curl;
928 text->selc= text->sell->len;
931 /***************************/
932 /* Cut and paste functions */
933 /***************************/
935 void txt_print_cutbuffer (void)
937 printf ("Cut buffer\n--\n%s\n--\n", txt_cut_buffer);
940 char *txt_to_buf (Text *text)
942 int length;
943 TextLine *tmp, *linef, *linel;
944 int charf, charl;
945 char *buf;
947 if (!text) return NULL;
948 if (!text->curl) return NULL;
949 if (!text->sell) return NULL;
951 linef= text->lines.first;
952 charf= 0;
954 linel= text->lines.last;
955 charl= linel->len;
957 if (linef == text->lines.last) {
958 length= charl-charf;
960 buf= MEM_mallocN(length+2, "text buffer");
962 BLI_strncpy(buf, linef->line + charf, length+1);
963 buf[length]=0;
964 } else {
965 length= linef->len - charf;
966 length+= charl;
967 length+= 2; /* For the 2 '\n' */
969 tmp= linef->next;
970 while (tmp && tmp!= linel) {
971 length+= tmp->len+1;
972 tmp= tmp->next;
975 buf= MEM_mallocN(length+1, "cut buffer");
977 strncpy(buf, linef->line + charf, linef->len-charf);
978 length= linef->len - charf;
980 buf[length++]='\n';
982 tmp= linef->next;
983 while (tmp && tmp!=linel) {
984 strncpy(buf+length, tmp->line, tmp->len);
985 length+= tmp->len;
987 buf[length++]='\n';
989 tmp= tmp->next;
991 strncpy(buf+length, linel->line, charl);
992 length+= charl;
994 /* python compiler wants an empty end line */
995 buf[length++]='\n';
996 buf[length]=0;
999 return buf;
1002 int txt_find_string(Text *text, char *findstr)
1004 TextLine *tl, *startl;
1005 char *s= NULL;
1007 if (!text || !text->curl || !text->sell) return 0;
1009 txt_order_cursors(text);
1011 tl= startl= text->sell;
1013 s= strstr(&tl->line[text->selc], findstr);
1014 while (!s) {
1015 tl= tl->next;
1016 if (!tl)
1017 tl= text->lines.first;
1019 s= strstr(tl->line, findstr);
1020 if (tl==startl)
1021 break;
1024 if (s) {
1025 text->curl= text->sell= tl;
1026 text->curc= (int) (s-tl->line);
1027 text->selc= text->curc + strlen(findstr);
1029 return 1;
1030 } else
1031 return 0;
1034 void txt_cut_sel (Text *text)
1036 txt_copy_clipboard(text);
1038 txt_delete_sel(text);
1039 txt_make_dirty(text);
1042 char *txt_sel_to_buf (Text *text)
1044 char *buf;
1045 int length=0;
1046 TextLine *tmp, *linef, *linel;
1047 int charf, charl;
1049 if (!text) return NULL;
1050 if (!text->curl) return NULL;
1051 if (!text->sell) return NULL;
1053 if (text->curl==text->sell) {
1054 linef= linel= text->curl;
1056 if (text->curc < text->selc) {
1057 charf= text->curc;
1058 charl= text->selc;
1059 } else{
1060 charf= text->selc;
1061 charl= text->curc;
1063 } else if (txt_get_span(text->curl, text->sell)<0) {
1064 linef= text->sell;
1065 linel= text->curl;
1067 charf= text->selc;
1068 charl= text->curc;
1069 } else {
1070 linef= text->curl;
1071 linel= text->sell;
1073 charf= text->curc;
1074 charl= text->selc;
1077 if (linef == linel) {
1078 length= charl-charf;
1080 buf= MEM_mallocN(length+1, "sel buffer");
1082 BLI_strncpy(buf, linef->line + charf, length+1);
1083 } else {
1084 length+= linef->len - charf;
1085 length+= charl;
1086 length++; /* For the '\n' */
1088 tmp= linef->next;
1089 while (tmp && tmp!= linel) {
1090 length+= tmp->len+1;
1091 tmp= tmp->next;
1094 buf= MEM_mallocN(length+1, "sel buffer");
1096 strncpy(buf, linef->line+ charf, linef->len-charf);
1097 length= linef->len-charf;
1099 buf[length++]='\n';
1101 tmp= linef->next;
1102 while (tmp && tmp!=linel) {
1103 strncpy(buf+length, tmp->line, tmp->len);
1104 length+= tmp->len;
1106 buf[length++]='\n';
1108 tmp= tmp->next;
1110 strncpy(buf+length, linel->line, charl);
1111 length+= charl;
1113 buf[length]=0;
1116 return buf;
1119 void txt_copy_sel (Text *text)
1121 int length=0;
1122 TextLine *tmp, *linef, *linel;
1123 int charf, charl;
1125 if (!text) return;
1126 if (!text->curl) return;
1127 if (!text->sell) return;
1129 if (!txt_has_sel(text)) return;
1131 if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
1132 txt_cut_buffer= NULL;
1134 if (text->curl==text->sell) {
1135 linef= linel= text->curl;
1137 if (text->curc < text->selc) {
1138 charf= text->curc;
1139 charl= text->selc;
1140 } else{
1141 charf= text->selc;
1142 charl= text->curc;
1144 } else if (txt_get_span(text->curl, text->sell)<0) {
1145 linef= text->sell;
1146 linel= text->curl;
1148 charf= text->selc;
1149 charl= text->curc;
1150 } else {
1151 linef= text->curl;
1152 linel= text->sell;
1154 charf= text->curc;
1155 charl= text->selc;
1158 if (linef == linel) {
1159 length= charl-charf;
1161 txt_cut_buffer= MEM_mallocN(length+1, "cut buffera");
1163 BLI_strncpy(txt_cut_buffer, linef->line + charf, length+1);
1164 } else {
1165 length+= linef->len - charf;
1166 length+= charl;
1167 length++; /* For the '\n' */
1169 tmp= linef->next;
1170 while (tmp && tmp!= linel) {
1171 length+= tmp->len+1;
1172 tmp= tmp->next;
1175 txt_cut_buffer= MEM_mallocN(length+1, "cut bufferb");
1177 strncpy(txt_cut_buffer, linef->line+ charf, linef->len-charf);
1178 length= linef->len-charf;
1180 txt_cut_buffer[length++]='\n';
1182 tmp= linef->next;
1183 while (tmp && tmp!=linel) {
1184 strncpy(txt_cut_buffer+length, tmp->line, tmp->len);
1185 length+= tmp->len;
1187 txt_cut_buffer[length++]='\n';
1189 tmp= tmp->next;
1191 strncpy(txt_cut_buffer+length, linel->line, charl);
1192 length+= charl;
1194 txt_cut_buffer[length]=0;
1198 void txt_insert_buf(Text *text, char *in_buffer)
1200 int i=0, l=0, j, u, len;
1201 TextLine *add;
1203 if (!text) return;
1204 if (!in_buffer) return;
1206 txt_delete_sel(text);
1208 if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer);
1210 u= undoing;
1211 undoing= 1;
1213 /* Read the first line (or as close as possible */
1214 while (in_buffer[i] && in_buffer[i]!='\n') {
1215 txt_add_char(text, in_buffer[i]);
1216 i++;
1219 if (in_buffer[i]=='\n') txt_split_curline(text);
1220 else { undoing = u; return; }
1221 i++;
1223 /* Read as many full lines as we can */
1224 len= strlen(in_buffer);
1226 while (i<len) {
1227 l=0;
1229 while (in_buffer[i] && in_buffer[i]!='\n') {
1230 i++; l++;
1233 if(in_buffer[i]=='\n') {
1234 add= txt_new_linen(in_buffer +(i-l), l);
1235 BLI_insertlinkbefore(&text->lines, text->curl, add);
1236 i++;
1237 } else {
1238 for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) {
1239 txt_add_char(text, in_buffer[j]);
1241 break;
1245 undoing= u;
1248 void txt_free_cut_buffer(void)
1250 if (txt_cut_buffer) MEM_freeN(txt_cut_buffer);
1253 void txt_paste(Text *text)
1255 txt_insert_buf(text, txt_cut_buffer);
1258 /******************/
1259 /* Undo functions */
1260 /******************/
1262 #define MAX_UNDO_TEST(x) \
1263 while (text->undo_pos+x >= text->undo_len) { \
1264 if(text->undo_len*2 > TXT_MAX_UNDO) { \
1265 error("Undo limit reached, buffer cleared\n"); \
1266 MEM_freeN(text->undo_buf); \
1267 text->undo_len= TXT_INIT_UNDO; \
1268 text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); \
1269 text->undo_pos=-1; \
1270 return; \
1271 } else { \
1272 void *tmp= text->undo_buf; \
1273 text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); \
1274 memcpy(text->undo_buf, tmp, text->undo_len); \
1275 text->undo_len*=2; \
1276 MEM_freeN(tmp); \
1280 static void dump_buffer(Text *text)
1282 int i= 0;
1284 while (i++<text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
1287 void txt_print_undo(Text *text)
1289 int i= 0;
1290 int op;
1291 char *ops;
1292 int linep, charp;
1294 dump_buffer(text);
1296 printf ("---< Undo Buffer >---\n");
1298 printf ("UndoPosition is %d\n", text->undo_pos);
1300 while (i<=text->undo_pos) {
1301 op= text->undo_buf[i];
1303 if (op==UNDO_CLEFT) {
1304 ops= "Cursor left";
1305 } else if (op==UNDO_CRIGHT) {
1306 ops= "Cursor right";
1307 } else if (op==UNDO_CUP) {
1308 ops= "Cursor up";
1309 } else if (op==UNDO_CDOWN) {
1310 ops= "Cursor down";
1311 } else if (op==UNDO_SLEFT) {
1312 ops= "Selection left";
1313 } else if (op==UNDO_SRIGHT) {
1314 ops= "Selection right";
1315 } else if (op==UNDO_SUP) {
1316 ops= "Selection up";
1317 } else if (op==UNDO_SDOWN) {
1318 ops= "Selection down";
1319 } else if (op==UNDO_STO) {
1320 ops= "Selection ";
1321 } else if (op==UNDO_CTO) {
1322 ops= "Cursor ";
1323 } else if (op==UNDO_INSERT) {
1324 ops= "Insert";
1325 } else if (op==UNDO_BS) {
1326 ops= "Backspace";
1327 } else if (op==UNDO_DEL) {
1328 ops= "Delete";
1329 } else if (op==UNDO_SWAP) {
1330 ops= "Cursor swap";
1331 } else if (op==UNDO_DBLOCK) {
1332 ops= "Delete text block";
1333 } else if (op==UNDO_IBLOCK) {
1334 ops= "Insert text block";
1335 } else if (op==UNDO_INDENT) {
1336 ops= "Indent ";
1337 } else if (op==UNDO_UNINDENT) {
1338 ops= "Unindent ";
1339 } else if (op==UNDO_COMMENT) {
1340 ops= "Comment ";
1341 } else if (op==UNDO_UNCOMMENT) {
1342 ops= "Uncomment ";
1343 } else {
1344 ops= "Unknown";
1347 printf ("Op (%o) at %d = %s", op, i, ops);
1348 if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) {
1349 i++;
1350 printf (" - Char is %c", text->undo_buf[i]);
1351 i++;
1352 } else if (op==UNDO_STO || op==UNDO_CTO) {
1353 i++;
1355 charp= text->undo_buf[i]; i++;
1356 charp= charp+(text->undo_buf[i]<<8); i++;
1358 linep= text->undo_buf[i]; i++;
1359 linep= linep+(text->undo_buf[i]<<8); i++;
1360 linep= linep+(text->undo_buf[i]<<16); i++;
1361 linep= linep+(text->undo_buf[i]<<24); i++;
1363 printf ("to <%d, %d> ", linep, charp);
1365 charp= text->undo_buf[i]; i++;
1366 charp= charp+(text->undo_buf[i]<<8); i++;
1368 linep= text->undo_buf[i]; i++;
1369 linep= linep+(text->undo_buf[i]<<8); i++;
1370 linep= linep+(text->undo_buf[i]<<16); i++;
1371 linep= linep+(text->undo_buf[i]<<24); i++;
1373 printf ("from <%d, %d>", linep, charp);
1374 } else if (op==UNDO_DBLOCK || op==UNDO_IBLOCK) {
1375 i++;
1377 linep= text->undo_buf[i]; i++;
1378 linep= linep+(text->undo_buf[i]<<8); i++;
1379 linep= linep+(text->undo_buf[i]<<16); i++;
1380 linep= linep+(text->undo_buf[i]<<24); i++;
1382 printf (" (length %d) <", linep);
1384 while (linep>0) {
1385 putchar(text->undo_buf[i]);
1386 linep--; i++;
1389 linep= text->undo_buf[i]; i++;
1390 linep= linep+(text->undo_buf[i]<<8); i++;
1391 linep= linep+(text->undo_buf[i]<<16); i++;
1392 linep= linep+(text->undo_buf[i]<<24); i++;
1393 printf ("> (%d)", linep);
1394 } else if (op==UNDO_INDENT || op==UNDO_UNINDENT) {
1395 i++;
1397 charp= text->undo_buf[i]; i++;
1398 charp= charp+(text->undo_buf[i]<<8); i++;
1400 linep= text->undo_buf[i]; i++;
1401 linep= linep+(text->undo_buf[i]<<8); i++;
1402 linep= linep+(text->undo_buf[i]<<16); i++;
1403 linep= linep+(text->undo_buf[i]<<24); i++;
1405 printf ("to <%d, %d> ", linep, charp);
1407 charp= text->undo_buf[i]; i++;
1408 charp= charp+(text->undo_buf[i]<<8); i++;
1410 linep= text->undo_buf[i]; i++;
1411 linep= linep+(text->undo_buf[i]<<8); i++;
1412 linep= linep+(text->undo_buf[i]<<16); i++;
1413 linep= linep+(text->undo_buf[i]<<24); i++;
1415 printf ("from <%d, %d>", linep, charp);
1418 printf (" %d\n", i);
1419 i++;
1423 static void txt_undo_add_op(Text *text, int op)
1425 MAX_UNDO_TEST(2);
1427 text->undo_pos++;
1428 text->undo_buf[text->undo_pos]= op;
1429 text->undo_buf[text->undo_pos+1]= 0;
1432 static void txt_undo_add_block(Text *text, int op, char *buf)
1434 int length;
1436 length= strlen(buf);
1438 MAX_UNDO_TEST(length+11);
1440 text->undo_pos++;
1441 text->undo_buf[text->undo_pos]= op;
1443 text->undo_pos++;
1444 text->undo_buf[text->undo_pos]= (length)&0xff;
1445 text->undo_pos++;
1446 text->undo_buf[text->undo_pos]= (length>>8)&0xff;
1447 text->undo_pos++;
1448 text->undo_buf[text->undo_pos]= (length>>16)&0xff;
1449 text->undo_pos++;
1450 text->undo_buf[text->undo_pos]= (length>>24)&0xff;
1452 text->undo_pos++;
1453 strncpy(text->undo_buf+text->undo_pos, buf, length);
1454 text->undo_pos+=length;
1456 text->undo_buf[text->undo_pos]= (length)&0xff;
1457 text->undo_pos++;
1458 text->undo_buf[text->undo_pos]= (length>>8)&0xff;
1459 text->undo_pos++;
1460 text->undo_buf[text->undo_pos]= (length>>16)&0xff;
1461 text->undo_pos++;
1462 text->undo_buf[text->undo_pos]= (length>>24)&0xff;
1464 text->undo_pos++;
1465 text->undo_buf[text->undo_pos]= op;
1467 text->undo_buf[text->undo_pos+1]= 0;
1470 void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc)
1472 MAX_UNDO_TEST(15);
1474 if (froml==tol && fromc==toc) return;
1476 text->undo_pos++;
1477 text->undo_buf[text->undo_pos]= op;
1479 text->undo_pos++;
1480 text->undo_buf[text->undo_pos]= (fromc)&0xff;
1481 text->undo_pos++;
1482 text->undo_buf[text->undo_pos]= (fromc>>8)&0xff;
1484 text->undo_pos++;
1485 text->undo_buf[text->undo_pos]= (froml)&0xff;
1486 text->undo_pos++;
1487 text->undo_buf[text->undo_pos]= (froml>>8)&0xff;
1488 text->undo_pos++;
1489 text->undo_buf[text->undo_pos]= (froml>>16)&0xff;
1490 text->undo_pos++;
1491 text->undo_buf[text->undo_pos]= (froml>>24)&0xff;
1493 text->undo_pos++;
1494 text->undo_buf[text->undo_pos]= (toc)&0xff;
1495 text->undo_pos++;
1496 text->undo_buf[text->undo_pos]= (toc>>8)&0xff;
1498 text->undo_pos++;
1499 text->undo_buf[text->undo_pos]= (tol)&0xff;
1500 text->undo_pos++;
1501 text->undo_buf[text->undo_pos]= (tol>>8)&0xff;
1502 text->undo_pos++;
1503 text->undo_buf[text->undo_pos]= (tol>>16)&0xff;
1504 text->undo_pos++;
1505 text->undo_buf[text->undo_pos]= (tol>>24)&0xff;
1507 text->undo_pos++;
1508 text->undo_buf[text->undo_pos]= op;
1510 text->undo_buf[text->undo_pos+1]= 0;
1513 static void txt_undo_add_charop(Text *text, int op, char c)
1515 MAX_UNDO_TEST(4);
1517 text->undo_pos++;
1518 text->undo_buf[text->undo_pos]= op;
1519 text->undo_pos++;
1520 text->undo_buf[text->undo_pos]= c;
1521 text->undo_pos++;
1522 text->undo_buf[text->undo_pos]= op;
1523 text->undo_buf[text->undo_pos+1]= 0;
1526 void txt_do_undo(Text *text)
1528 int op= text->undo_buf[text->undo_pos];
1529 unsigned int linep, i;
1530 unsigned short charp;
1531 TextLine *holdl;
1532 int holdc, holdln;
1533 char *buf;
1535 if (text->undo_pos<0) {
1536 return;
1539 text->undo_pos--;
1541 undoing= 1;
1543 switch(op) {
1544 case UNDO_CLEFT:
1545 txt_move_right(text, 0);
1546 break;
1548 case UNDO_CRIGHT:
1549 txt_move_left(text, 0);
1550 break;
1552 case UNDO_CUP:
1553 txt_move_down(text, 0);
1554 break;
1556 case UNDO_CDOWN:
1557 txt_move_up(text, 0);
1558 break;
1560 case UNDO_SLEFT:
1561 txt_move_right(text, 1);
1562 break;
1564 case UNDO_SRIGHT:
1565 txt_move_left(text, 1);
1566 break;
1568 case UNDO_SUP:
1569 txt_move_down(text, 1);
1570 break;
1572 case UNDO_SDOWN:
1573 txt_move_up(text, 1);
1574 break;
1576 case UNDO_CTO:
1577 case UNDO_STO:
1578 text->undo_pos--;
1579 text->undo_pos--;
1580 text->undo_pos--;
1581 text->undo_pos--;
1583 text->undo_pos--;
1584 text->undo_pos--;
1586 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1587 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1588 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1589 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1591 charp= text->undo_buf[text->undo_pos]; text->undo_pos--;
1592 charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1594 if (op==UNDO_CTO) {
1595 txt_move_toline(text, linep, 0);
1596 text->curc= charp;
1597 txt_pop_sel(text);
1598 } else {
1599 txt_move_toline(text, linep, 1);
1600 text->selc= charp;
1603 text->undo_pos--;
1604 break;
1606 case UNDO_INSERT:
1607 txt_backspace_char(text);
1608 text->undo_pos--;
1609 text->undo_pos--;
1610 break;
1612 case UNDO_BS:
1613 txt_add_char(text, text->undo_buf[text->undo_pos]);
1614 text->undo_pos--;
1615 text->undo_pos--;
1616 break;
1618 case UNDO_DEL:
1619 txt_add_char(text, text->undo_buf[text->undo_pos]);
1620 txt_move_left(text, 0);
1621 text->undo_pos--;
1622 text->undo_pos--;
1623 break;
1625 case UNDO_SWAP:
1626 txt_curs_swap(text);
1627 txt_do_undo(text); /* swaps should appear transparent */
1628 break;
1630 case UNDO_DBLOCK:
1631 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1632 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1633 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1634 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1636 buf= MEM_mallocN(linep+1, "dblock buffer");
1637 for (i=0; i < linep; i++){
1638 buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
1639 text->undo_pos--;
1641 buf[i]= 0;
1643 txt_curs_first(text, &holdl, &holdc);
1644 holdln= txt_get_span(text->lines.first, holdl);
1646 txt_insert_buf(text, buf);
1647 MEM_freeN(buf);
1649 text->curl= text->lines.first;
1650 while (holdln>0) {
1651 if(text->curl->next)
1652 text->curl= text->curl->next;
1654 holdln--;
1656 text->curc= holdc;
1658 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1659 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1660 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1661 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1663 text->undo_pos--;
1665 break;
1667 case UNDO_IBLOCK:
1668 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1669 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1670 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1671 linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1673 txt_delete_sel(text);
1674 while (linep>0) {
1675 txt_backspace_char(text);
1676 text->undo_pos--;
1677 linep--;
1680 text->undo_pos--;
1681 text->undo_pos--;
1682 text->undo_pos--;
1683 text->undo_pos--;
1685 text->undo_pos--;
1687 break;
1688 case UNDO_INDENT:
1689 case UNDO_UNINDENT:
1690 case UNDO_COMMENT:
1691 case UNDO_UNCOMMENT:
1692 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1693 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1694 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1695 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1696 //linep is now the end line of the selection
1698 charp = text->undo_buf[text->undo_pos]; text->undo_pos--;
1699 charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1700 //charp is the last char selected or text->line->len
1701 //set the selcetion for this now
1702 text->selc = charp;
1703 text->sell = text->lines.first;
1704 for (i= 0; i < linep; i++) {
1705 text->sell = text->sell->next;
1708 linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
1709 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1710 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1711 linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1712 //first line to be selected
1714 charp = text->undo_buf[text->undo_pos]; text->undo_pos--;
1715 charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
1716 //first postion to be selected
1717 text->curc = charp;
1718 text->curl = text->lines.first;
1719 for (i = 0; i < linep; i++) {
1720 text->curl = text->curl->next;
1724 if (op==UNDO_INDENT) {
1725 unindent(text);
1726 } else if (op== UNDO_UNINDENT) {
1727 indent(text);
1728 } else if (op == UNDO_COMMENT) {
1729 uncomment(text);
1730 } else if (op == UNDO_UNCOMMENT) {
1731 comment(text);
1734 text->undo_pos--;
1735 break;
1736 default:
1737 error("Undo buffer error - resetting");
1738 text->undo_pos= -1;
1740 break;
1743 undoing= 0;
1746 void txt_do_redo(Text *text)
1748 char op;
1749 unsigned int linep, i;
1750 unsigned short charp;
1751 char *buf;
1753 text->undo_pos++;
1754 op= text->undo_buf[text->undo_pos];
1756 if (!op) {
1757 text->undo_pos--;
1758 return;
1761 undoing= 1;
1763 switch(op) {
1764 case UNDO_CLEFT:
1765 txt_move_left(text, 0);
1766 break;
1768 case UNDO_CRIGHT:
1769 txt_move_right(text, 0);
1770 break;
1772 case UNDO_CUP:
1773 txt_move_up(text, 0);
1774 break;
1776 case UNDO_CDOWN:
1777 txt_move_down(text, 0);
1778 break;
1780 case UNDO_SLEFT:
1781 txt_move_left(text, 1);
1782 break;
1784 case UNDO_SRIGHT:
1785 txt_move_right(text, 1);
1786 break;
1788 case UNDO_SUP:
1789 txt_move_up(text, 1);
1790 break;
1792 case UNDO_SDOWN:
1793 txt_move_down(text, 1);
1794 break;
1796 case UNDO_INSERT:
1797 text->undo_pos++;
1798 txt_add_char(text, text->undo_buf[text->undo_pos]);
1799 text->undo_pos++;
1800 break;
1802 case UNDO_BS:
1803 text->undo_pos++;
1804 txt_backspace_char(text);
1805 text->undo_pos++;
1806 break;
1808 case UNDO_DEL:
1809 text->undo_pos++;
1810 txt_delete_char(text);
1811 text->undo_pos++;
1812 break;
1814 case UNDO_SWAP:
1815 txt_curs_swap(text);
1816 txt_do_undo(text); /* swaps should appear transparent a*/
1817 break;
1819 case UNDO_CTO:
1820 case UNDO_STO:
1821 text->undo_pos++;
1822 text->undo_pos++;
1824 text->undo_pos++;
1825 text->undo_pos++;
1826 text->undo_pos++;
1827 text->undo_pos++;
1829 text->undo_pos++;
1831 charp= text->undo_buf[text->undo_pos];
1832 text->undo_pos++;
1833 charp= charp+(text->undo_buf[text->undo_pos]<<8);
1835 text->undo_pos++;
1836 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1837 linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1838 linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1839 linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1841 if (op==UNDO_CTO) {
1842 txt_move_toline(text, linep, 0);
1843 text->curc= charp;
1844 txt_pop_sel(text);
1845 } else {
1846 txt_move_toline(text, linep, 1);
1847 text->selc= charp;
1850 break;
1852 case UNDO_DBLOCK:
1853 text->undo_pos++;
1854 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1855 linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1856 linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1857 linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1859 txt_delete_sel(text);
1860 text->undo_pos+=linep;
1862 text->undo_pos++;
1863 text->undo_pos++;
1864 text->undo_pos++;
1865 text->undo_pos++;
1867 break;
1869 case UNDO_IBLOCK:
1870 text->undo_pos++;
1871 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1872 linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1873 linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1874 linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1876 buf= MEM_mallocN(linep+1, "iblock buffer");
1877 memcpy (buf, &text->undo_buf[text->undo_pos], linep);
1878 text->undo_pos+= linep;
1879 buf[linep]= 0;
1881 txt_insert_buf(text, buf);
1882 MEM_freeN(buf);
1884 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1885 linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1886 linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1887 linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1889 break;
1890 case UNDO_INDENT:
1891 case UNDO_UNINDENT:
1892 case UNDO_COMMENT:
1893 case UNDO_UNCOMMENT:
1894 text->undo_pos++;
1895 charp = text->undo_buf[text->undo_pos]; text->undo_pos++;
1896 charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1897 //charp is the first char selected or 0
1899 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1900 linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1901 linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1902 linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1903 //linep is now the first line of the selection
1904 //set the selcetion for this now
1905 text->curc = charp;
1906 text->curl = text->lines.first;
1907 for (i= 0; i < linep; i++) {
1908 text->curl = text->curl->next;
1911 charp = text->undo_buf[text->undo_pos]; text->undo_pos++;
1912 charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1913 //last postion to be selected
1914 linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
1915 linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
1916 linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
1917 linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
1918 //Last line to be selected
1920 text->selc = charp;
1921 text->sell = text->lines.first;
1922 for (i = 0; i < linep; i++) {
1923 text->sell = text->sell->next;
1926 if (op==UNDO_INDENT) {
1927 indent(text);
1928 } else if (op== UNDO_UNINDENT) {
1929 unindent(text);
1930 } else if (op == UNDO_COMMENT) {
1931 comment(text);
1932 } else if (op == UNDO_UNCOMMENT) {
1933 uncomment(text);
1935 break;
1936 default:
1937 error("Undo buffer error - resetting");
1938 text->undo_pos= -1;
1940 break;
1943 undoing= 0;
1946 /**************************/
1947 /* Line editing functions */
1948 /**************************/
1950 void txt_split_curline (Text *text)
1952 TextLine *ins;
1953 char *left, *right, *fleft, *fright;
1955 if (!text) return;
1956 if (!text->curl) return;
1958 txt_delete_sel(text);
1960 /* Make the two half strings */
1962 left= MEM_mallocN(text->curc+1, "textline_string");
1963 fleft= MEM_mallocN(text->curc+2, "Syntax_format");
1964 if (text->curc) memcpy(left, text->curl->line, text->curc);
1965 left[text->curc]=0;
1967 right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
1968 fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format");
1969 if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
1970 right[text->curl->len - text->curc]=0;
1972 MEM_freeN(text->curl->line);
1973 if (text->curl->format) MEM_freeN(text->curl->format);
1975 /* Make the new TextLine */
1977 ins= MEM_mallocN(sizeof(TextLine), "textline");
1978 ins->line= left;
1979 ins->format= fleft;
1980 ins->len= text->curc;
1982 text->curl->line= right;
1983 text->curl->format= fright;
1984 text->curl->len= text->curl->len - text->curc;
1986 BLI_insertlinkbefore(&text->lines, text->curl, ins);
1988 text->curc=0;
1990 txt_make_dirty(text);
1991 txt_clean_text(text);
1993 txt_pop_sel(text);
1994 if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n');
1997 static void txt_delete_line (Text *text, TextLine *line)
1999 if (!text) return;
2000 if (!text->curl) return;
2002 BLI_remlink (&text->lines, line);
2004 if (line->line) MEM_freeN(line->line);
2005 if (line->format) MEM_freeN(line->format);
2007 MEM_freeN(line);
2009 txt_make_dirty(text);
2010 txt_clean_text(text);
2013 static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
2015 char *tmp, *format;
2017 if (!text) return;
2019 if(!linea || !lineb) return;
2021 tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
2022 format= MEM_mallocN(linea->len+lineb->len+1, "Syntax_format");
2024 strcpy(tmp, linea->line);
2025 strcat(tmp, lineb->line);
2027 make_new_line(linea, tmp, format);
2029 txt_delete_line(text, lineb);
2031 txt_make_dirty(text);
2032 txt_clean_text(text);
2035 void txt_delete_char (Text *text)
2037 char c='\n';
2039 if (!text) return;
2040 if (!text->curl) return;
2042 if (txt_has_sel(text)) { /* deleting a selection */
2043 txt_delete_sel(text);
2045 else if (text->curc== text->curl->len) { /* Appending two lines */
2046 if (text->curl->next) {
2047 txt_combine_lines(text, text->curl, text->curl->next);
2048 txt_pop_sel(text);
2050 } else { /* Just deleting a char */
2051 int i= text->curc;
2053 c= text->curl->line[i];
2054 while(i< text->curl->len) {
2055 text->curl->line[i]= text->curl->line[i+1];
2056 i++;
2058 text->curl->len--;
2060 txt_pop_sel(text);
2063 txt_make_dirty(text);
2064 txt_clean_text(text);
2066 if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c);
2069 void txt_backspace_char (Text *text)
2071 char c='\n';
2073 if (!text) return;
2074 if (!text->curl) return;
2076 if (txt_has_sel(text)) { /* deleting a selection */
2077 txt_delete_sel(text);
2079 else if (text->curc==0) { /* Appending two lines */
2080 if (text->curl->prev) {
2081 text->curl= text->curl->prev;
2082 text->curc= text->curl->len;
2084 txt_combine_lines(text, text->curl, text->curl->next);
2085 txt_pop_sel(text);
2088 else { /* Just backspacing a char */
2089 int i= text->curc-1;
2091 c= text->curl->line[i];
2092 while(i< text->curl->len) {
2093 text->curl->line[i]= text->curl->line[i+1];
2094 i++;
2096 text->curl->len--;
2097 text->curc--;
2099 txt_pop_sel(text);
2102 txt_make_dirty(text);
2103 txt_clean_text(text);
2105 if(!undoing) txt_undo_add_charop(text, UNDO_BS, c);
2108 int txt_add_char (Text *text, char add)
2110 int len;
2111 char *tmp, *format;
2113 if (!text) return 0;
2114 if (!text->curl) return 0;
2116 if (add=='\n') {
2117 txt_split_curline(text);
2118 return 1;
2121 txt_delete_sel(text);
2123 tmp= MEM_mallocN(text->curl->len+2, "textline_string");
2124 format= MEM_mallocN(text->curl->len+4, "Syntax_format");
2126 if(text->curc) memcpy(tmp, text->curl->line, text->curc);
2127 tmp[text->curc]= add;
2129 len= text->curl->len - text->curc;
2130 if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
2131 tmp[text->curl->len+1]=0;
2132 make_new_line(text->curl, tmp, format);
2134 text->curc++;
2136 txt_pop_sel(text);
2138 txt_make_dirty(text);
2139 txt_clean_text(text);
2141 if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add);
2142 return 1;
2145 void indent(Text *text)
2147 int len, num;
2148 char *tmp, *format;
2149 char add = '\t';
2151 if (!text) return;
2152 if (!text->curl) return;
2153 if (!text->sell) return;
2155 num = 0;
2156 while (TRUE)
2158 tmp= MEM_mallocN(text->curl->len+2, "textline_string");
2159 format= MEM_mallocN(text->curl->len+3, "Syntax_format");
2161 text->curc = 0;
2162 if(text->curc) memcpy(tmp, text->curl->line, text->curc);
2163 tmp[text->curc]= add;
2165 len= text->curl->len - text->curc;
2166 if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
2167 tmp[text->curl->len+1]=0;
2169 make_new_line(text->curl, tmp, format);
2171 text->curc++;
2173 txt_make_dirty(text);
2174 txt_clean_text(text);
2176 if(text->curl == text->sell)
2178 text->selc = text->sell->len;
2179 break;
2180 } else {
2181 text->curl = text->curl->next;
2182 num++;
2185 text->curc = 0;
2186 while( num > 0 )
2188 text->curl = text->curl->prev;
2189 num--;
2192 if(!undoing)
2194 txt_undo_add_toop(text, UNDO_INDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc);
2198 void unindent(Text *text)
2200 int num = 0;
2201 char remove = '\t';
2203 if (!text) return;
2204 if (!text->curl) return;
2205 if (!text->sell) return;
2207 while(TRUE)
2209 int i = 0;
2211 if (text->curl->line[i] == remove)
2213 while(i< text->curl->len) {
2214 text->curl->line[i]= text->curl->line[i+1];
2215 i++;
2217 text->curl->len--;
2221 txt_make_dirty(text);
2222 txt_clean_text(text);
2224 if(text->curl == text->sell)
2226 text->selc = text->sell->len;
2227 break;
2228 } else {
2229 text->curl = text->curl->next;
2230 num++;
2234 text->curc = 0;
2235 while( num > 0 )
2237 text->curl = text->curl->prev;
2238 num--;
2241 if(!undoing)
2243 txt_undo_add_toop(text, UNDO_UNINDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc);
2247 void comment(Text *text)
2249 int len, num;
2250 char *tmp, *format;
2251 char add = '#';
2253 if (!text) return;
2254 if (!text->curl) return;
2255 if (!text->sell) return;// Need to change this need to check if only one line is selected ot more then one
2257 num = 0;
2258 while (TRUE)
2260 tmp= MEM_mallocN(text->curl->len+2, "textline_string");
2261 format = MEM_mallocN(text->curl->len+3, "Syntax_format");
2263 text->curc = 0;
2264 if(text->curc) memcpy(tmp, text->curl->line, text->curc);
2265 tmp[text->curc]= add;
2267 len= text->curl->len - text->curc;
2268 if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
2269 tmp[text->curl->len+1]=0;
2271 make_new_line(text->curl, tmp, format);
2273 text->curc++;
2275 txt_make_dirty(text);
2276 txt_clean_text(text);
2278 if(text->curl == text->sell)
2280 text->selc = text->sell->len;
2281 break;
2282 } else {
2283 text->curl = text->curl->next;
2284 num++;
2287 text->curc = 0;
2288 while( num > 0 )
2290 text->curl = text->curl->prev;
2291 num--;
2294 if(!undoing)
2296 txt_undo_add_toop(text, UNDO_COMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc);
2300 void uncomment(Text *text)
2302 int num = 0;
2303 char remove = '#';
2305 if (!text) return;
2306 if (!text->curl) return;
2307 if (!text->sell) return;
2309 while(TRUE)
2311 int i = 0;
2313 if (text->curl->line[i] == remove)
2315 while(i< text->curl->len) {
2316 text->curl->line[i]= text->curl->line[i+1];
2317 i++;
2319 text->curl->len--;
2323 txt_make_dirty(text);
2324 txt_clean_text(text);
2326 if(text->curl == text->sell)
2328 text->selc = text->sell->len;
2329 break;
2330 } else {
2331 text->curl = text->curl->next;
2332 num++;
2336 text->curc = 0;
2337 while( num > 0 )
2339 text->curl = text->curl->prev;
2340 num--;
2343 if(!undoing)
2345 txt_undo_add_toop(text, UNDO_UNCOMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc);
2349 int setcurr_tab (Text *text)
2351 int i = 0;
2352 int test = 0;
2353 char *word = ":";
2354 char *comm = "#";
2355 char back_words[3][7] = {"return", "break", "pass"};
2356 if (!text) return 0;
2357 if (!text->curl) return 0;
2359 while (text->curl->line[i] == '\t')
2361 //we only count thos tabs that are before any text or before the curs;
2362 if (i == text->curc)
2364 return i;
2365 } else {
2366 i++;
2369 if(strstr(text->curl->line, word))
2371 //if we find a : then add a tab but not if it is in a comment
2372 if(strcspn(text->curl->line, word) < strcspn(text->curl->line, comm))
2374 i++;
2379 while(test < 3)
2381 //if there are these 3 key words then remove a tab because we are done with the block
2382 if(strstr(text->curl->line, back_words[test]) && i > 0)
2384 if(strcspn(text->curl->line, back_words[test]) < strcspn(text->curl->line, comm))
2386 i--;
2389 test++;
2391 return i;