Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Thompson <quornian@googlemail.com>2008-08-05 03:01:47 +0400
committerIan Thompson <quornian@googlemail.com>2008-08-05 03:01:47 +0400
commit53e535dfcf9637e3aa3327dd3bf2793a67756868 (patch)
treeedc307efe53008580feeffab327056779b8ab6b0 /source/blender/blenkernel
parented5002458b810974277b7a6bd5d9c3c29d052d53 (diff)
Text Markers: multiple, coloured selections within a Text object with group relationships. They allow portions of text to be edited as one and enable quick jumping between and editing of different areas.
Flags control the behaviour and grouping of markers. At present, Ctrl+M places a marker with TMARK_EDITALL set for testing purposes. I have also split the text area event handler into separate methods for marker handling and the existing text tools. This makes the events system much easier to follow as it was getting a little hairy.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_text.h13
-rw-r--r--source/blender/blenkernel/intern/text.c275
2 files changed, 270 insertions, 18 deletions
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index abdf32c8ea5..de54b6413ae 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -100,6 +100,15 @@ int setcurr_tab (struct Text *text);
void convert_tabs (struct SpaceText *st, int tab);
void txt_copy_clipboard (struct Text *text);
void txt_paste_clipboard (struct Text *text);
+
+void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char clr[4], int flags);
+void txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int flags);
+void txt_clear_markers (struct Text *text, int flags);
+struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int flags);
+struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int flags);
+struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker);
+struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker);
+
/* Undo opcodes */
/* Simple main cursor movement */
@@ -146,6 +155,10 @@ void txt_paste_clipboard (struct Text *text);
#define TXT_FIND_ALLTEXTS 0x02
#define TXT_FIND_WRAP 0x04
+/* Marker flags */
+#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */
+#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 67beb4e4397..611eed3999e 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -148,6 +148,7 @@ void free_text(Text *text)
}
BLI_freelistN(&text->lines);
+ BLI_freelistN(&text->markers);
if(text->name) MEM_freeN(text->name);
MEM_freeN(text->undo_buf);
@@ -172,6 +173,7 @@ Text *add_empty_text(char *name)
ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
ta->lines.first= ta->lines.last= NULL;
+ ta->markers.first= ta->markers.last= NULL;
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(1, "textline_string");
@@ -334,6 +336,7 @@ Text *add_text(char *file)
ta->id.us= 1;
ta->lines.first= ta->lines.last= NULL;
+ ta->markers.first= ta->markers.last= NULL;
ta->curl= ta->sell= NULL;
/* ta->flags= TXT_ISTMP | TXT_ISEXT; */
@@ -421,6 +424,7 @@ Text *copy_text(Text *ta)
tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
tan->lines.first= tan->lines.last= NULL;
+ tan->markers.first= tan->markers.last= NULL;
tan->curl= tan->sell= NULL;
tan->nlines= ta->nlines;
@@ -948,7 +952,9 @@ int txt_has_sel(Text *text)
static void txt_delete_sel (Text *text)
{
TextLine *tmpl;
+ TextMarker *mrk;
char *buf;
+ int move, lineno;
if (!text) return;
if (!text->curl) return;
@@ -966,6 +972,23 @@ static void txt_delete_sel (Text *text)
buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
+ if (text->curl != text->sell) {
+ txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0);
+ move= txt_get_span(text->curl, text->sell);
+ } else
+ move= 0;
+
+ mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ mrk->lineno -= move;
+ if (mrk->start > text->curc) mrk->start -= text->selc - text->curc;
+ mrk->end -= text->selc - text->curc;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+
strncpy(buf, text->curl->line, text->curc);
strcpy(buf+text->curc, text->sell->line + text->selc);
buf[text->curc+(text->sell->len - text->selc)]=0;
@@ -2050,12 +2073,29 @@ void txt_do_redo(Text *text)
void txt_split_curline (Text *text)
{
TextLine *ins;
+ TextMarker *mrk;
char *left, *right;
+ int lineno= -1;
if (!text) return;
if (!text->curl) return;
- txt_delete_sel(text);
+ txt_delete_sel(text);
+
+ /* Move markers */
+
+ lineno= txt_get_span(text->lines.first, text->curl);
+ mrk= text->markers.first;
+ while (mrk) {
+ if (mrk->lineno==lineno && mrk->start>text->curc) {
+ mrk->lineno++;
+ mrk->start -= text->curc;
+ mrk->end -= text->curc;
+ } else if (mrk->lineno > lineno) {
+ mrk->lineno++;
+ }
+ mrk= mrk->next;
+ }
/* Make the two half strings */
@@ -2094,9 +2134,23 @@ void txt_split_curline (Text *text)
static void txt_delete_line (Text *text, TextLine *line)
{
+ TextMarker *mrk=NULL, *nxt;
+ int lineno= -1;
+
if (!text) return;
if (!text->curl) return;
+ lineno= txt_get_span(text->lines.first, line);
+ mrk= text->markers.first;
+ while (mrk) {
+ nxt= mrk->next;
+ if (mrk->lineno==lineno)
+ BLI_freelinkN(&text->markers, mrk);
+ else if (mrk->lineno > lineno)
+ mrk->lineno--;
+ mrk= nxt;
+ }
+
BLI_remlink (&text->lines, line);
if (line->line) MEM_freeN(line->line);
@@ -2111,10 +2165,25 @@ static void txt_delete_line (Text *text, TextLine *line)
static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
{
char *tmp;
+ TextMarker *mrk= NULL;
+ int lineno=-1;
if (!text) return;
if(!linea || !lineb) return;
+
+ mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ mrk->lineno--;
+ mrk->start += linea->len;
+ mrk->end += linea->len;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+ if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb);
+ if (!mrk) mrk= text->markers.first;
tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
@@ -2123,7 +2192,7 @@ static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
make_new_line(linea, tmp);
- txt_delete_line(text, lineb);
+ txt_delete_line(text, lineb);
txt_make_dirty(text);
txt_clean_text(text);
@@ -2137,8 +2206,8 @@ void txt_delete_char (Text *text)
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
- return;
+ txt_delete_sel(text);
+ return;
}
else if (text->curc== text->curl->len) { /* Appending two lines */
if (text->curl->next) {
@@ -2147,6 +2216,25 @@ void txt_delete_char (Text *text)
}
} else { /* Just deleting a char */
int i= text->curc;
+
+ TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0);
+ if (mrk) {
+ int lineno= mrk->lineno;
+ if (mrk->end==i) {
+ if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
+ txt_clear_markers(text, mrk->flags);
+ } else {
+ TextMarker *nxt= mrk->next;
+ BLI_freelinkN(&text->markers, mrk);
+ }
+ return;
+ }
+ do {
+ if (mrk->start>i) mrk->start--;
+ mrk->end--;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
c= text->curl->line[i];
while(i< text->curl->len) {
@@ -2178,8 +2266,8 @@ void txt_backspace_char (Text *text)
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
- return;
+ txt_delete_sel(text);
+ return;
}
else if (text->curc==0) { /* Appending two lines */
if (!text->curl->prev) return;
@@ -2189,19 +2277,38 @@ void txt_backspace_char (Text *text)
txt_combine_lines(text, text->curl, text->curl->next);
txt_pop_sel(text);
- }
+ }
else { /* Just backspacing a char */
- int i= text->curc-1;
-
- c= text->curl->line[i];
- while(i< text->curl->len) {
- text->curl->line[i]= text->curl->line[i+1];
- i++;
- }
- text->curl->len--;
- text->curc--;
+ int i= text->curc-1;
+
+ TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0);
+ if (mrk) {
+ int lineno= mrk->lineno;
+ if (mrk->start==i+1) {
+ if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
+ txt_clear_markers(text, mrk->flags);
+ } else {
+ TextMarker *nxt= mrk->next;
+ BLI_freelinkN(&text->markers, mrk);
+ }
+ return;
+ }
+ do {
+ if (mrk->start>i) mrk->start--;
+ mrk->end--;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
- txt_pop_sel(text);
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+ text->curc--;
+
+ txt_pop_sel(text);
}
txt_make_dirty(text);
@@ -2218,8 +2325,9 @@ void txt_backspace_word (Text *text)
int txt_add_char (Text *text, char add)
{
- int len;
+ int len, lineno;
char *tmp;
+ TextMarker *mrk;
if (!text) return 0;
if (!text->curl) return 0;
@@ -2231,6 +2339,16 @@ int txt_add_char (Text *text, char add)
txt_delete_sel(text);
+ mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ if (mrk->start>text->curc) mrk->start++;
+ mrk->end++;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+
tmp= MEM_mallocN(text->curl->len+2, "textline_string");
if(text->curc) memcpy(tmp, text->curl->line, text->curc);
@@ -2535,3 +2653,124 @@ int setcurr_tab (Text *text)
return i;
}
+/*********************************/
+/* Text marker utility functions */
+/*********************************/
+
+/* Creates and adds a marker to the list maintaining sorted order */
+void txt_add_marker(Text *text, TextLine *line, int start, int end, char clr[4], int flags) {
+ TextMarker *tmp, *marker;
+
+ marker= MEM_mallocN(sizeof(TextMarker), "text_marker");
+
+ marker->lineno= txt_get_span(text->lines.first, line);
+ marker->start= MIN2(start, end);
+ marker->end= MAX2(start, end);
+ marker->flags= flags;
+
+ marker->clr[0]= clr[0];
+ marker->clr[1]= clr[1];
+ marker->clr[2]= clr[2];
+ marker->clr[3]= clr[3];
+
+ for (tmp=text->markers.last; tmp; tmp=tmp->prev)
+ if (tmp->lineno < marker->lineno || (tmp->lineno==marker->lineno && tmp->start < marker->start))
+ break;
+
+ if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker);
+ else BLI_addhead(&text->markers, marker);
+}
+
+/* Returns the first matching marker on the specified line between two points
+ If flags is zero, all markers will be searched */
+TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int flags) {
+ TextMarker *marker, *next;
+ int lineno= txt_get_span(text->lines.first, line);
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if (flags && marker->flags != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if ((marker->start==marker->end && start<=marker->start && marker->start<=end) ||
+ (marker->start<end && marker->end>start))
+ return marker;
+ }
+ return NULL;
+}
+
+/* Clears all matching markers on the specified line between two points
+ If flags is zero, all markers will be cleared */
+void txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int flags) {
+ TextMarker *marker, *next;
+ int lineno= txt_get_span(text->lines.first, line);
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if (flags && marker->flags != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if ((marker->start==marker->end && start<=marker->start && marker->start<=end) ||
+ (marker->start<end && marker->end>start))
+ BLI_freelinkN(&text->markers, marker);
+ }
+}
+
+/* Clears all markers with matching flags (useful for clearing temporary markers) */
+void txt_clear_markers(Text *text, int flags) {
+ TextMarker *marker, *next;
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if (marker->flags == flags)
+ BLI_freelinkN(&text->markers, marker);
+ }
+}
+
+/* Finds the marker at the specified line and cursor position with matching flags.
+ If flags is zero, all markers will be searched */
+TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int flags) {
+ TextMarker *marker;
+ int lineno= txt_get_span(text->lines.first, line);
+
+ for (marker=text->markers.first; marker; marker=marker->next) {
+ if (flags && marker->flags != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if (marker->start <= curs && curs <= marker->end)
+ return marker;
+ }
+ return NULL;
+}
+
+/* Finds the previous marker with matching flags. If no other marker is found, the
+ same one will be returned */
+TextMarker *txt_prev_marker(Text *text, TextMarker *marker) {
+ TextMarker *tmp= marker;
+ while (tmp) {
+ if (tmp->prev) tmp= tmp->prev;
+ else tmp= text->markers.last;
+ if (tmp->flags == marker->flags)
+ return tmp;
+ }
+ return NULL; /* Only if marker==NULL */
+}
+
+/* Finds the next marker with matching flags. If no other marker is found, the
+ same one will be returned */
+TextMarker *txt_next_marker(Text *text, TextMarker *marker) {
+ TextMarker *tmp= marker;
+ while (tmp) {
+ if (tmp->next) tmp= tmp->next;
+ else tmp= text->markers.first;
+ if (tmp->flags == marker->flags)
+ return tmp;
+ }
+ return NULL; /* Only if marker==NULL */
+} \ No newline at end of file