diff options
Diffstat (limited to 'source/blender/blenkernel/intern/text.c')
-rw-r--r-- | source/blender/blenkernel/intern/text.c | 275 |
1 files changed, 257 insertions, 18 deletions
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 |