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
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"
47 #include "BKE_library.h"
48 #include "BKE_global.h"
51 #include "BPY_extern.h"
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
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
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
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.
93 Undo/Redo works by storing
94 events in a queue, and a pointer
95 to the current position in the
98 Events are stored using an
99 arbitrary op-code system
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
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
);
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
)
135 int txt_get_undostate(void)
140 void free_text(Text
*text
)
144 for (tmp
= text
->lines
.first
; tmp
; tmp
= tmp
->next
) {
145 MEM_freeN(tmp
->line
);
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
)
162 ta
= alloc_libblock(&G
.main
->text
, ID_TXT
, name
);
168 ta
->undo_len
= TXT_INIT_UNDO
;
169 ta
->undo_buf
= MEM_mallocN(ta
->undo_len
, "undo buf");
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");
186 BLI_addhead(&ta
->lines
, tmp
);
188 ta
->curl
= ta
->lines
.first
;
190 ta
->sell
= ta
->lines
.first
;
196 // this function removes any control characters from
199 static void cleanup_textline(TextLine
* tl
)
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
);
212 int reopen_text(Text
*text
)
216 unsigned char *buffer
;
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
);
229 if(fp
==NULL
) return 0;
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
);
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
);
253 fseek(fp
, 0L, SEEK_SET
);
257 buffer
= MEM_mallocN(len
, "text_buffer");
258 // under windows fread can return less then len bytes because
260 len
= fread(buffer
, 1, len
, fp
);
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
);
277 cleanup_textline(tmp
);
279 BLI_addtail(&text
->lines
, tmp
);
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
);
298 cleanup_textline(tmp
);
300 BLI_addtail(&text
->lines
, tmp
);
304 text
->curl
= text
->sell
= text
->lines
.first
;
305 text
->curc
= text
->selc
= 0;
311 Text
*add_text(char *file
)
315 unsigned char *buffer
;
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
);
328 if(fp
==NULL
) return NULL
;
330 ta
= alloc_libblock(&G
.main
->text
, ID_TXT
, sfile
);
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
);
341 fseek(fp
, 0L, SEEK_SET
);
343 ta
->name
= MEM_mallocN(strlen(file
)+1, "text_name");
344 strcpy(ta
->name
, file
);
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
353 len
= fread(buffer
, 1, len
, fp
);
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
);
370 cleanup_textline(tmp
);
372 BLI_addtail(&ta
->lines
, tmp
);
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
);
391 cleanup_textline(tmp
);
393 BLI_addtail(&ta
->lines
, tmp
);
397 ta
->curl
= ta
->sell
= ta
->lines
.first
;
398 ta
->curc
= ta
->selc
= 0;
405 Text
*copy_text(Text
*ta
)
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 */
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
);
433 BLI_addtail(&tan
->lines
, tmp
);
438 tan
->curl
= tan
->sell
= tan
->lines
.first
;
439 tan
->curc
= tan
->selc
= 0;
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
);
454 line
->len
= strlen(newline
);
455 line
->format
= newformat
;
458 static TextLine
*txt_new_line(char *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
;
476 static TextLine
*txt_new_linen(char *str
, int n
)
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
;
494 void txt_clean_text (Text
*text
)
496 TextLine
**top
, **bot
;
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
;
514 if(text
->sell
) text
->curl
= text
->sell
;
515 else text
->curl
= text
->lines
.first
;
520 text
->sell
= text
->curl
;
525 int txt_get_span (TextLine
*from
, TextLine
*to
)
530 if (!to
|| !from
) return 0;
531 if (from
==to
) return 0;
535 if (tmp
== to
) return ret
;
545 if (tmp
== to
) break;
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
) {
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
)) {
590 /****************************/
591 /* Cursor movement functions */
592 /****************************/
594 void txt_move_up(Text
*text
, short sel
)
600 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
601 else { txt_pop_first(text
); txt_curs_cur(text
, &linep
, &charp
); }
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
);
611 if(!undoing
) txt_undo_add_op(text
, sel
?UNDO_SUP
:UNDO_CUP
);
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
)
627 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
628 else { txt_pop_last(text
); txt_curs_cur(text
, &linep
, &charp
); }
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
);
638 if(!undoing
) txt_undo_add_op(text
, sel
?UNDO_SDOWN
:UNDO_CDOWN
);
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
)
650 int *charp
, oundoing
= undoing
;
653 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
654 else { txt_pop_first(text
); txt_curs_cur(text
, &linep
, &charp
); }
659 if ((*linep
)->prev
) {
660 txt_move_up(text
, sel
);
661 *charp
= (*linep
)->len
;
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
)
675 int *charp
, oundoing
= undoing
;
678 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
679 else { txt_pop_last(text
); txt_curs_cur(text
, &linep
, &charp
); }
683 if (*charp
== (*linep
)->len
) {
684 if ((*linep
)->next
) {
685 txt_move_down(text
, sel
);
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
)
703 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
704 else txt_curs_cur(text
, &linep
, &charp
);
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
)
720 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
721 else txt_curs_cur(text
, &linep
, &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
)
737 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
738 else txt_curs_cur(text
, &linep
, &charp
);
742 *linep
= text
->lines
.first
;
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
)
755 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
756 else txt_curs_cur(text
, &linep
, &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
;
774 if(sel
) txt_curs_sel(text
, &linep
, &charp
);
775 else txt_curs_cur(text
, &linep
, &charp
);
780 *linep
= text
->lines
.first
;
781 for (i
=0; i
<line
; i
++) {
782 if ((*linep
)->next
) *linep
= (*linep
)->next
;
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
)
801 text
->curl
= text
->sell
;
805 text
->curc
= text
->selc
;
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
)) {
819 if(!undoing
) txt_undo_add_toop(text
, UNDO_STO
,
820 txt_get_span(text
->lines
.first
, text
->sell
),
822 txt_get_span(text
->lines
.first
, text
->curl
),
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
)) {
835 if(!undoing
) txt_undo_add_toop(text
, UNDO_STO
,
836 txt_get_span(text
->lines
.first
, text
->sell
),
838 txt_get_span(text
->lines
.first
, text
->curl
),
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
)
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
))
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
)
876 if (!text
->curl
) return;
877 if (!text
->sell
) return;
879 if (!txt_has_sel(text
)) return;
881 txt_order_cursors(text
);
884 buf
= txt_sel_to_buf(text
);
885 txt_undo_add_block(text
, UNDO_DBLOCK
, 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
);
899 while (tmpl
!= text
->curl
) {
903 txt_delete_line(text
, tmpl
->next
);
906 text
->sell
= text
->curl
;
907 text
->selc
= text
->curc
;
910 void txt_sel_all (Text
*text
)
914 text
->curl
= text
->lines
.first
;
917 text
->sell
= text
->lines
.last
;
918 text
->selc
= text
->sell
->len
;
921 void txt_sel_line (Text
*text
)
924 if (!text
->curl
) return;
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
)
943 TextLine
*tmp
, *linef
, *linel
;
947 if (!text
) return NULL
;
948 if (!text
->curl
) return NULL
;
949 if (!text
->sell
) return NULL
;
951 linef
= text
->lines
.first
;
954 linel
= text
->lines
.last
;
957 if (linef
== text
->lines
.last
) {
960 buf
= MEM_mallocN(length
+2, "text buffer");
962 BLI_strncpy(buf
, linef
->line
+ charf
, length
+1);
965 length
= linef
->len
- charf
;
967 length
+= 2; /* For the 2 '\n' */
970 while (tmp
&& tmp
!= linel
) {
975 buf
= MEM_mallocN(length
+1, "cut buffer");
977 strncpy(buf
, linef
->line
+ charf
, linef
->len
-charf
);
978 length
= linef
->len
- charf
;
983 while (tmp
&& tmp
!=linel
) {
984 strncpy(buf
+length
, tmp
->line
, tmp
->len
);
991 strncpy(buf
+length
, linel
->line
, charl
);
994 /* python compiler wants an empty end line */
1002 int txt_find_string(Text
*text
, char *findstr
)
1004 TextLine
*tl
, *startl
;
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
);
1017 tl
= text
->lines
.first
;
1019 s
= strstr(tl
->line
, findstr
);
1025 text
->curl
= text
->sell
= tl
;
1026 text
->curc
= (int) (s
-tl
->line
);
1027 text
->selc
= text
->curc
+ strlen(findstr
);
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
)
1046 TextLine
*tmp
, *linef
, *linel
;
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
) {
1063 } else if (txt_get_span(text
->curl
, text
->sell
)<0) {
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);
1084 length
+= linef
->len
- charf
;
1086 length
++; /* For the '\n' */
1089 while (tmp
&& tmp
!= linel
) {
1090 length
+= tmp
->len
+1;
1094 buf
= MEM_mallocN(length
+1, "sel buffer");
1096 strncpy(buf
, linef
->line
+ charf
, linef
->len
-charf
);
1097 length
= linef
->len
-charf
;
1102 while (tmp
&& tmp
!=linel
) {
1103 strncpy(buf
+length
, tmp
->line
, tmp
->len
);
1110 strncpy(buf
+length
, linel
->line
, charl
);
1119 void txt_copy_sel (Text
*text
)
1122 TextLine
*tmp
, *linef
, *linel
;
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
) {
1144 } else if (txt_get_span(text
->curl
, text
->sell
)<0) {
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);
1165 length
+= linef
->len
- charf
;
1167 length
++; /* For the '\n' */
1170 while (tmp
&& tmp
!= linel
) {
1171 length
+= tmp
->len
+1;
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';
1183 while (tmp
&& tmp
!=linel
) {
1184 strncpy(txt_cut_buffer
+length
, tmp
->line
, tmp
->len
);
1187 txt_cut_buffer
[length
++]='\n';
1191 strncpy(txt_cut_buffer
+length
, linel
->line
, 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
;
1204 if (!in_buffer
) return;
1206 txt_delete_sel(text
);
1208 if(!undoing
) txt_undo_add_block (text
, UNDO_IBLOCK
, in_buffer
);
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
]);
1219 if (in_buffer
[i
]=='\n') txt_split_curline(text
);
1220 else { undoing
= u
; return; }
1223 /* Read as many full lines as we can */
1224 len
= strlen(in_buffer
);
1229 while (in_buffer
[i
] && in_buffer
[i
]!='\n') {
1233 if(in_buffer
[i
]=='\n') {
1234 add
= txt_new_linen(in_buffer
+(i
-l
), l
);
1235 BLI_insertlinkbefore(&text
->lines
, text
->curl
, add
);
1238 for (j
= i
-l
; j
<i
&& j
<(int)strlen(in_buffer
); j
++) {
1239 txt_add_char(text
, in_buffer
[j
]);
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; \
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; \
1280 static void dump_buffer(Text
*text
)
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
)
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
) {
1305 } else if (op
==UNDO_CRIGHT
) {
1306 ops
= "Cursor right";
1307 } else if (op
==UNDO_CUP
) {
1309 } else if (op
==UNDO_CDOWN
) {
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
) {
1321 } else if (op
==UNDO_CTO
) {
1323 } else if (op
==UNDO_INSERT
) {
1325 } else if (op
==UNDO_BS
) {
1327 } else if (op
==UNDO_DEL
) {
1329 } else if (op
==UNDO_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
) {
1337 } else if (op
==UNDO_UNINDENT
) {
1339 } else if (op
==UNDO_COMMENT
) {
1341 } else if (op
==UNDO_UNCOMMENT
) {
1347 printf ("Op (%o) at %d = %s", op
, i
, ops
);
1348 if (op
==UNDO_INSERT
|| op
==UNDO_BS
|| op
==UNDO_DEL
) {
1350 printf (" - Char is %c", text
->undo_buf
[i
]);
1352 } else if (op
==UNDO_STO
|| op
==UNDO_CTO
) {
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
) {
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
);
1385 putchar(text
->undo_buf
[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
) {
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
);
1423 static void txt_undo_add_op(Text
*text
, int op
)
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
)
1436 length
= strlen(buf
);
1438 MAX_UNDO_TEST(length
+11);
1441 text
->undo_buf
[text
->undo_pos
]= op
;
1444 text
->undo_buf
[text
->undo_pos
]= (length
)&0xff;
1446 text
->undo_buf
[text
->undo_pos
]= (length
>>8)&0xff;
1448 text
->undo_buf
[text
->undo_pos
]= (length
>>16)&0xff;
1450 text
->undo_buf
[text
->undo_pos
]= (length
>>24)&0xff;
1453 strncpy(text
->undo_buf
+text
->undo_pos
, buf
, length
);
1454 text
->undo_pos
+=length
;
1456 text
->undo_buf
[text
->undo_pos
]= (length
)&0xff;
1458 text
->undo_buf
[text
->undo_pos
]= (length
>>8)&0xff;
1460 text
->undo_buf
[text
->undo_pos
]= (length
>>16)&0xff;
1462 text
->undo_buf
[text
->undo_pos
]= (length
>>24)&0xff;
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
)
1474 if (froml
==tol
&& fromc
==toc
) return;
1477 text
->undo_buf
[text
->undo_pos
]= op
;
1480 text
->undo_buf
[text
->undo_pos
]= (fromc
)&0xff;
1482 text
->undo_buf
[text
->undo_pos
]= (fromc
>>8)&0xff;
1485 text
->undo_buf
[text
->undo_pos
]= (froml
)&0xff;
1487 text
->undo_buf
[text
->undo_pos
]= (froml
>>8)&0xff;
1489 text
->undo_buf
[text
->undo_pos
]= (froml
>>16)&0xff;
1491 text
->undo_buf
[text
->undo_pos
]= (froml
>>24)&0xff;
1494 text
->undo_buf
[text
->undo_pos
]= (toc
)&0xff;
1496 text
->undo_buf
[text
->undo_pos
]= (toc
>>8)&0xff;
1499 text
->undo_buf
[text
->undo_pos
]= (tol
)&0xff;
1501 text
->undo_buf
[text
->undo_pos
]= (tol
>>8)&0xff;
1503 text
->undo_buf
[text
->undo_pos
]= (tol
>>16)&0xff;
1505 text
->undo_buf
[text
->undo_pos
]= (tol
>>24)&0xff;
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
)
1518 text
->undo_buf
[text
->undo_pos
]= op
;
1520 text
->undo_buf
[text
->undo_pos
]= c
;
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
;
1535 if (text
->undo_pos
<0) {
1545 txt_move_right(text
, 0);
1549 txt_move_left(text
, 0);
1553 txt_move_down(text
, 0);
1557 txt_move_up(text
, 0);
1561 txt_move_right(text
, 1);
1565 txt_move_left(text
, 1);
1569 txt_move_down(text
, 1);
1573 txt_move_up(text
, 1);
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
--;
1595 txt_move_toline(text
, linep
, 0);
1599 txt_move_toline(text
, linep
, 1);
1607 txt_backspace_char(text
);
1613 txt_add_char(text
, text
->undo_buf
[text
->undo_pos
]);
1619 txt_add_char(text
, text
->undo_buf
[text
->undo_pos
]);
1620 txt_move_left(text
, 0);
1626 txt_curs_swap(text
);
1627 txt_do_undo(text
); /* swaps should appear transparent */
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
];
1643 txt_curs_first(text
, &holdl
, &holdc
);
1644 holdln
= txt_get_span(text
->lines
.first
, holdl
);
1646 txt_insert_buf(text
, buf
);
1649 text
->curl
= text
->lines
.first
;
1651 if(text
->curl
->next
)
1652 text
->curl
= text
->curl
->next
;
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
--;
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
);
1675 txt_backspace_char(text
);
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
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
1718 text
->curl
= text
->lines
.first
;
1719 for (i
= 0; i
< linep
; i
++) {
1720 text
->curl
= text
->curl
->next
;
1724 if (op
==UNDO_INDENT
) {
1726 } else if (op
== UNDO_UNINDENT
) {
1728 } else if (op
== UNDO_COMMENT
) {
1730 } else if (op
== UNDO_UNCOMMENT
) {
1737 error("Undo buffer error - resetting");
1746 void txt_do_redo(Text
*text
)
1749 unsigned int linep
, i
;
1750 unsigned short charp
;
1754 op
= text
->undo_buf
[text
->undo_pos
];
1765 txt_move_left(text
, 0);
1769 txt_move_right(text
, 0);
1773 txt_move_up(text
, 0);
1777 txt_move_down(text
, 0);
1781 txt_move_left(text
, 1);
1785 txt_move_right(text
, 1);
1789 txt_move_up(text
, 1);
1793 txt_move_down(text
, 1);
1798 txt_add_char(text
, text
->undo_buf
[text
->undo_pos
]);
1804 txt_backspace_char(text
);
1810 txt_delete_char(text
);
1815 txt_curs_swap(text
);
1816 txt_do_undo(text
); /* swaps should appear transparent a*/
1831 charp
= text
->undo_buf
[text
->undo_pos
];
1833 charp
= charp
+(text
->undo_buf
[text
->undo_pos
]<<8);
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
++;
1842 txt_move_toline(text
, linep
, 0);
1846 txt_move_toline(text
, linep
, 1);
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
;
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
;
1881 txt_insert_buf(text
, 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
++;
1893 case UNDO_UNCOMMENT
:
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
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
1921 text
->sell
= text
->lines
.first
;
1922 for (i
= 0; i
< linep
; i
++) {
1923 text
->sell
= text
->sell
->next
;
1926 if (op
==UNDO_INDENT
) {
1928 } else if (op
== UNDO_UNINDENT
) {
1930 } else if (op
== UNDO_COMMENT
) {
1932 } else if (op
== UNDO_UNCOMMENT
) {
1937 error("Undo buffer error - resetting");
1946 /**************************/
1947 /* Line editing functions */
1948 /**************************/
1950 void txt_split_curline (Text
*text
)
1953 char *left
, *right
, *fleft
, *fright
;
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
);
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");
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
);
1990 txt_make_dirty(text
);
1991 txt_clean_text(text
);
1994 if(!undoing
) txt_undo_add_charop(text
, UNDO_INSERT
, '\n');
1997 static void txt_delete_line (Text
*text
, TextLine
*line
)
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
);
2009 txt_make_dirty(text
);
2010 txt_clean_text(text
);
2013 static void txt_combine_lines (Text
*text
, TextLine
*linea
, TextLine
*lineb
)
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
)
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
);
2050 } else { /* Just deleting a char */
2053 c
= text
->curl
->line
[i
];
2054 while(i
< text
->curl
->len
) {
2055 text
->curl
->line
[i
]= text
->curl
->line
[i
+1];
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
)
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
);
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];
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
)
2113 if (!text
) return 0;
2114 if (!text
->curl
) return 0;
2117 txt_split_curline(text
);
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
);
2138 txt_make_dirty(text
);
2139 txt_clean_text(text
);
2141 if(!undoing
) txt_undo_add_charop(text
, UNDO_INSERT
, add
);
2145 void indent(Text
*text
)
2152 if (!text
->curl
) return;
2153 if (!text
->sell
) return;
2158 tmp
= MEM_mallocN(text
->curl
->len
+2, "textline_string");
2159 format
= MEM_mallocN(text
->curl
->len
+3, "Syntax_format");
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
);
2173 txt_make_dirty(text
);
2174 txt_clean_text(text
);
2176 if(text
->curl
== text
->sell
)
2178 text
->selc
= text
->sell
->len
;
2181 text
->curl
= text
->curl
->next
;
2188 text
->curl
= text
->curl
->prev
;
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
)
2204 if (!text
->curl
) return;
2205 if (!text
->sell
) return;
2211 if (text
->curl
->line
[i
] == remove
)
2213 while(i
< text
->curl
->len
) {
2214 text
->curl
->line
[i
]= text
->curl
->line
[i
+1];
2221 txt_make_dirty(text
);
2222 txt_clean_text(text
);
2224 if(text
->curl
== text
->sell
)
2226 text
->selc
= text
->sell
->len
;
2229 text
->curl
= text
->curl
->next
;
2237 text
->curl
= text
->curl
->prev
;
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
)
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
2260 tmp
= MEM_mallocN(text
->curl
->len
+2, "textline_string");
2261 format
= MEM_mallocN(text
->curl
->len
+3, "Syntax_format");
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
);
2275 txt_make_dirty(text
);
2276 txt_clean_text(text
);
2278 if(text
->curl
== text
->sell
)
2280 text
->selc
= text
->sell
->len
;
2283 text
->curl
= text
->curl
->next
;
2290 text
->curl
= text
->curl
->prev
;
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
)
2306 if (!text
->curl
) return;
2307 if (!text
->sell
) return;
2313 if (text
->curl
->line
[i
] == remove
)
2315 while(i
< text
->curl
->len
) {
2316 text
->curl
->line
[i
]= text
->curl
->line
[i
+1];
2323 txt_make_dirty(text
);
2324 txt_clean_text(text
);
2326 if(text
->curl
== text
->sell
)
2328 text
->selc
= text
->sell
->len
;
2331 text
->curl
= text
->curl
->next
;
2339 text
->curl
= text
->curl
->prev
;
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
)
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
)
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
))
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
))