diff options
-rw-r--r-- | source/blender/blenkernel/BKE_text.h | 13 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/text.c | 275 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 10 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_text_types.h | 8 | ||||
-rw-r--r-- | source/blender/src/drawtext.c | 546 |
6 files changed, 668 insertions, 185 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 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ad19cde3c9b..29fd314236b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2273,6 +2273,7 @@ static void direct_link_text(FileData *fd, Text *text) */ link_list(fd, &text->lines); + link_list(fd, &text->markers); text->curl= newdataadr(fd, text->curl); text->sell= newdataadr(fd, text->sell); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 3a70438dd13..3af7d3f7c25 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1845,6 +1845,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) { Text *text; TextLine *tmp; + TextMarker *mrk; text= idbase->first; while(text) { @@ -1868,7 +1869,16 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } + + /* write markers */ + mrk= text->markers.first; + while (mrk) { + writestruct(wd, DATA, "TextMarker", 1, mrk); + mrk= mrk->next; + } } + + text= text->id.next; } diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index bec4e0062f9..41ea0b23323 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -42,6 +42,12 @@ typedef struct TextLine { int len, blen; } TextLine; +typedef struct TextMarker { + struct TextMarker *next, *prev; + int lineno, start, end, flags; + char clr[4], pad[4]; +} TextMarker; + typedef struct Text { ID id; @@ -52,12 +58,12 @@ typedef struct Text { ListBase lines; TextLine *curl, *sell; int curc, selc; + ListBase markers; char *undo_buf; int undo_pos, undo_len; void *compiled; - double mtime; } Text; diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 335062cb055..a05133f47bd 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -123,6 +123,9 @@ def wrap(line, view_width, wrap_chars): #define TOOL_SUGG_LIST 0x01 #define TOOL_DOCUMENT 0x02 +#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for flags */ +#define TMARK_GRP_FINDALL 0x00020000 /* Upper 2 bytes used for group */ + /* forward declarations */ void drawtextspace(ScrArea *sa, void *spacedata); @@ -141,7 +144,6 @@ static int check_whitespace(char ch); static int get_wrap_width(SpaceText *st); static int get_wrap_points(SpaceText *st, char *line); - static void get_suggest_prefix(Text *text); static void confirm_suggestion(Text *text, int skipleft); @@ -777,6 +779,77 @@ static int get_char_pos(SpaceText *st, char *line, int cur) { return a; } +static void draw_markers(SpaceText *st) { + Text *text= st->text; + TextMarker *marker, *next; + TextLine *top, *bottom, *line; + int offl, offc, i, cy, x1, x2, y1, y2, x, y; + + for (i=st->top, top= text->lines.first; top->next && i>0; i--) top= top->next; + for (i=st->viewlines-1, bottom=top; bottom->next && i>0; i--) bottom= bottom->next; + + for (marker= text->markers.first; marker; marker= next) { + next= marker->next; + for (cy= 0, line= top; line; cy++, line= line->next) { + if (cy+st->top==marker->lineno) { + /* Remove broken markers */ + if (marker->end>line->len || marker->start>marker->end) { + BLI_freelinkN(&text->markers, marker); + break; + } + + wrap_offset(st, line, marker->start, &offl, &offc); + x1= get_char_pos(st, line->line, marker->start) - st->left + offc; + y1= cy + offl; + wrap_offset(st, line, marker->end, &offl, &offc); + x2= get_char_pos(st, line->line, marker->end) - st->left + offc; + y2= cy + offl; + + glColor3ub(marker->clr[0], marker->clr[1], marker->clr[2]); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy-3; + + if (y1==y2) { + y -= y1*st->lheight; + glBegin(GL_LINE_LOOP); + glVertex2i(x+x2*spacetext_get_fontwidth(st), y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st), y-st->lheight); + glEnd(); + } else { + y -= y1*st->lheight; + glBegin(GL_LINE_STRIP); + glVertex2i(curarea->winx, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-1, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + for (i=y1+1; i<y2; i++) { + glBegin(GL_LINES); + glVertex2i(x, y); + glVertex2i(curarea->winx, y); + glVertex2i(x, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + } + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st), y); + glVertex2i(x+x2*spacetext_get_fontwidth(st), y-st->lheight); + glVertex2i(x, y-st->lheight); + glEnd(); + } + + break; + } + if (line==bottom) break; + } + } +} + static void draw_cursor(SpaceText *st) { Text *text= st->text; int vcurl, vcurc, vsell, vselc, hidden=0; @@ -1410,6 +1483,7 @@ void drawtextspace(ScrArea *sa, void *spacedata) } draw_brackets(st); + draw_markers(st); draw_textscroll(st); draw_documentation(st); @@ -2032,6 +2106,277 @@ static void confirm_suggestion(Text *text, int skipleft) { texttool_text_clear(); } +static short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) { + int draw=0, swallow=0, tools=0, tools_cancel=0, tools_update=0, scroll=1; + if (!texttool_text_is_active(st->text)) return 0; + if (!st->text || st->text->id.lib) return 0; + + if (st->showsyntax && texttool_text_is_active(st->text)) { + if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST; + if (texttool_docs_get()) tools |= TOOL_DOCUMENT; + } + + if (ascii) { + if (tools & TOOL_SUGG_LIST) { + if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || check_whitespace(ascii)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + } else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { + tools_update |= TOOL_SUGG_LIST; + swallow= 1; + draw= 1; + } + } + tools_cancel |= TOOL_DOCUMENT; + + } else if (val) { + switch (evnt) { + case LEFTMOUSE: + if (do_suggest_select(st)) swallow= 1; + else tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; + draw= 1; + break; + case MIDDLEMOUSE: + if (do_suggest_select(st)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + } else + tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; + draw= 1; + break; + case ESCKEY: + swallow= 1; + if (tools & TOOL_SUGG_LIST) + tools_cancel |= TOOL_SUGG_LIST; + else if (tools & TOOL_DOCUMENT) + tools_cancel |= TOOL_DOCUMENT; + else + swallow= 0; + break; + case RETKEY: + if (tools & TOOL_SUGG_LIST) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + draw= 1; + } + tools_cancel |= TOOL_DOCUMENT; + break; + case BACKSPACEKEY: + if (tools & TOOL_SUGG_LIST) { + if (G.qual) tools_cancel |= TOOL_SUGG_LIST; + else { + /* Work out which char we are about to delete */ + if (st->text->curl && st->text->curc > 0) { + char ch= st->text->curl->line[st->text->curc-1]; + if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) + tools_update |= TOOL_SUGG_LIST; + else + tools_cancel |= TOOL_SUGG_LIST; + } + } + } + tools_cancel |= TOOL_DOCUMENT; + break; + case PAGEDOWNKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELDOWNMOUSE: + case DOWNARROWKEY: + if (tools & TOOL_DOCUMENT) { + doc_scroll++; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + if (!sel) { + texttool_suggest_select(texttool_suggest_first()); + } else while (sel && sel!=texttool_suggest_last() && sel->next && scroll--) { + texttool_suggest_select(sel->next); + sel= sel->next; + } + swallow= 1; + draw= 1; + break; + } + case PAGEUPKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELUPMOUSE: + case UPARROWKEY: + if (tools & TOOL_DOCUMENT) { + if (doc_scroll>0) doc_scroll--; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + while (sel && sel!=texttool_suggest_first() && sel->prev && scroll--) { + texttool_suggest_select(sel->prev); + sel= sel->prev; + } + swallow= 1; + draw= 1; + break; + } + default: + if (G.qual!=0 && G.qual!=LR_SHIFTKEY) + tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; + } + } + + if (tools & TOOL_SUGG_LIST) { + if (tools_update & TOOL_SUGG_LIST) { + get_suggest_prefix(st->text); + } else if (tools_cancel & TOOL_SUGG_LIST) { + texttool_suggest_clear(); + } + draw= 1; + } + if (tools & TOOL_DOCUMENT) { + if (tools_cancel & TOOL_DOCUMENT) { + texttool_docs_clear(); + doc_scroll= 0; + } + draw= 1; + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + + return swallow; +} + +static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short val) { + Text *text; + TextMarker *marker, *mrk, *nxt; + int c, s, draw=0, swallow=0; + + text= st->text; + if (!text || text->curl != text->sell) return 0; + + marker= txt_find_marker(text, text->curl, text->curc, 0); + if (!marker || text->id.lib) return 0; + + if (ascii) { + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + if (st->overwrite) { + if (txt_replace_char(text, ascii)) + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } else { + if (txt_add_char(text, ascii)) { + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } + } + + if (mrk==marker) break; + mrk=txt_next_marker(text, mrk); + } + swallow= 1; + draw= 1; + } + } else if (val) { + switch(evnt) { + case BACKSPACEKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_backspace_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case DELKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_delete_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case TABKEY: + marker= (G.qual & LR_SHIFTKEY) ? txt_prev_marker(text, marker) : txt_next_marker(text, marker); + txt_move_to(text, marker->lineno, marker->start, 0); + txt_move_to(text, marker->lineno, marker->end, 1); + pop_space_text(st); + swallow= 1; + draw= 1; + break; + + /* Events that should clear markers */ + case RETKEY: + case ESCKEY: + if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) + txt_clear_markers(text, marker->flags); + else + BLI_freelinkN(&text->markers, marker); + swallow= 1; + draw= 1; + break; + case RIGHTMOUSE: /* Marker context menu? */ + case LEFTMOUSE: + break; + + default: + if (G.qual!=0 && G.qual!=LR_SHIFTKEY) + swallow= 1; /* Swallow all other shortcut events */ + } + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + return swallow; +} + void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { unsigned short event= evt->event; @@ -2040,7 +2385,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) SpaceText *st= curarea->spacedata.first; Text *text; int do_draw=0, p; - int tools=0, tools_cancel=0, tools_update=0; /* Bitmasks for operations */ if (st==NULL || st->spacetype != SPACE_TEXT) return; @@ -2104,10 +2448,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) return; } - if (st->showsyntax && texttool_text_is_active(text)) { - if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST; - if (texttool_docs_get()) tools |= TOOL_DOCUMENT; - } + if (st->showsyntax && do_texttools(st, ascii, event, val)) return; + if (do_markers(st, ascii, event, val)) return; if (event==LEFTMOUSE) { if (val) { @@ -2118,9 +2460,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (mval[0]>2 && mval[0]<20 && mval[1]>2 && mval[1]<curarea->winy-2) { do_textscroll(st, 2); - tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; - } else if (do_suggest_select(st)) { - do_draw= 1; } else { do_selection(st, G.qual&LR_SHIFTKEY); if (txt_has_sel(text)) { @@ -2129,24 +2468,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) MEM_freeN(buffer); } do_draw= 1; - tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; } } } else if (event==MIDDLEMOUSE) { if (val) { - if (do_suggest_select(st)) { - confirm_suggestion(text, 0); + if (U.uiflag & USER_MMB_PASTE) { + do_selection(st, G.qual&LR_SHIFTKEY); + get_selection_buffer(text); do_draw= 1; } else { - if (U.uiflag & USER_MMB_PASTE) { - do_selection(st, G.qual&LR_SHIFTKEY); - get_selection_buffer(text); - do_draw= 1; - tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; - } else { - do_textscroll(st, 1); - tools_cancel |= TOOL_SUGG_LIST; - } + do_textscroll(st, 1); } } } else if (event==RIGHTMOUSE) { @@ -2180,33 +2511,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) default: break; } - tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; } } else if (ascii) { if (text && text->id.lib) { error_libdata(); - } else if ((st->overwrite && txt_replace_char(text, ascii)) || txt_add_char(text, ascii)) { if (st->showsyntax) txt_format_line(st, text->curl, 1); pop_space_text(st); do_draw= 1; - if (tools & TOOL_SUGG_LIST) { - if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || check_whitespace(ascii)) { - confirm_suggestion(text, 1); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } else { - tools_update |= TOOL_SUGG_LIST; - } - } - tools_cancel |= TOOL_DOCUMENT; } } else if (val) { - - /* Cases that require tools not to be cancelled must explicitly say so. - * The default case does this to prevent window/mousemove events - * from cancelling. */ - tools_cancel |= TOOL_SUGG_LIST | TOOL_DOCUMENT; - switch (event) { case AKEY: if (G.qual & LR_ALTKEY) { @@ -2334,6 +2648,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.qual == LR_ALTKEY) { txt_export_to_object(text); do_draw= 1; + } else if ((G.qual & LR_CTRLKEY) && text->sell==text->curl) { + int a= text->curc < text->selc ? text->curc : text->selc; + int b= text->curc < text->selc ? text->selc : text->curc; + + /* Don't allow overlapping markers */ + txt_clear_marker_region(text, text->curl, a, b, TMARK_GRP_CUSTOM); + if (!(G.qual & LR_ALTKEY)) { + txt_add_marker(text, text->curl, a, b, "\xFF\xC0\xFF\xFF", TMARK_GRP_CUSTOM | TMARK_EDITALL); + do_draw= 1; + } } break; /* BREAK M */ case NKEY: @@ -2477,31 +2801,26 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) do_draw= 1; } break; - case ESCKEY: - /* To allow ESC to close one tool at a time we remove all others from the cancel list */ - if (tools & TOOL_DOCUMENT) { - tools_cancel &= ~TOOL_SUGG_LIST; - } - break; case TABKEY: if (text && text->id.lib) { error_libdata(); break; - } - if (G.qual & LR_SHIFTKEY) { - if (txt_has_sel(text)) { - txt_order_cursors(text); - unindent(text); - if (st->showsyntax) txt_format_text(st); - } } else { - if ( txt_has_sel(text)) { - txt_order_cursors(text); - indent(text); - if (st->showsyntax) txt_format_text(st); + if (G.qual & LR_SHIFTKEY) { + if (txt_has_sel(text)) { + txt_order_cursors(text); + unindent(text); + if (st->showsyntax) txt_format_text(st); + } } else { - txt_add_char(text, '\t'); - if (st->showsyntax) txt_format_line(st, text->curl, 1); + if ( txt_has_sel(text)) { + txt_order_cursors(text); + indent(text); + if (st->showsyntax) txt_format_text(st); + } else { + txt_add_char(text, '\t'); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } } } pop_space_text(st); @@ -2513,11 +2832,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) error_libdata(); break; } - if (tools & TOOL_SUGG_LIST) { - confirm_suggestion(text, 0); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - break; - } //double check tabs before splitting the line st->currtab_set = setcurr_tab(text); txt_split_curline(text); @@ -2545,15 +2859,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { txt_backspace_word(text); - tools_cancel |= TOOL_SUGG_LIST; } else { - /* Work out which char we are about to delete */ - if (text && text->curl && text->curc > 0) { - char ch= text->curl->line[text->curc-1]; - if (!ispunct(ch) && !check_whitespace(ch)) { - tools_update |= TOOL_SUGG_LIST; - } - } txt_backspace_char(text); } set_tabs(text); @@ -2579,23 +2885,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case INSERTKEY: st->overwrite= !st->overwrite; do_draw= 1; - tools_cancel = 0; break; case DOWNARROWKEY: - if (tools & TOOL_DOCUMENT) { - doc_scroll++; - tools_cancel &= ~(TOOL_SUGG_LIST | TOOL_DOCUMENT); - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - if (!sel) { - texttool_suggest_select(texttool_suggest_first()); - } else if (sel!=texttool_suggest_last() && sel->next) { - texttool_suggest_select(sel->next); - } - tools_cancel &= ~TOOL_SUGG_LIST; - break; - } txt_move_down(text, G.qual & LR_SHIFTKEY); set_tabs(text); do_draw= 1; @@ -2624,48 +2915,17 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pop_space_text(st); break; case UPARROWKEY: - if (tools & TOOL_DOCUMENT) { - if (doc_scroll) doc_scroll--; - tools_cancel &= ~(TOOL_SUGG_LIST | TOOL_DOCUMENT); - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - if (sel && sel!=texttool_suggest_first() && sel->prev) - texttool_suggest_select(sel->prev); - tools_cancel &= ~TOOL_SUGG_LIST; - break; - } txt_move_up(text, G.qual & LR_SHIFTKEY); set_tabs(text); do_draw= 1; pop_space_text(st); break; case PAGEDOWNKEY: - if (tools & TOOL_SUGG_LIST) { - int i; - SuggItem *sel = texttool_suggest_selected(); - if (!sel) - sel = texttool_suggest_first(); - for (i=0; i<SUGG_LIST_SIZE-1 && sel && sel!=texttool_suggest_last() && sel->next; i++, sel=sel->next) - texttool_suggest_select(sel->next); - tools_cancel &= ~TOOL_SUGG_LIST; - break; - } else { - screen_skip(st, st->viewlines); - } + screen_skip(st, st->viewlines); do_draw= 1; break; case PAGEUPKEY: - if (tools & TOOL_SUGG_LIST) { - int i; - SuggItem *sel = texttool_suggest_selected(); - for (i=0; i<SUGG_LIST_SIZE-1 && sel && sel!=texttool_suggest_first() && sel->prev; i++, sel=sel->prev) - texttool_suggest_select(sel->prev); - tools_cancel &= ~TOOL_SUGG_LIST; - break; - } else { - screen_skip(st, -st->viewlines); - } + screen_skip(st, -st->viewlines); do_draw= 1; break; case HOMEKEY: @@ -2679,43 +2939,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pop_space_text(st); break; case WHEELUPMOUSE: - if (tools & TOOL_DOCUMENT) { - if (doc_scroll) doc_scroll--; - tools_cancel &= ~(TOOL_SUGG_LIST | TOOL_DOCUMENT); - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - if (sel && sel!=texttool_suggest_first() && sel->prev) - texttool_suggest_select(sel->prev); - tools_cancel &= ~TOOL_SUGG_LIST; - } else { - screen_skip(st, -U.wheellinescroll); - tools_cancel &= ~TOOL_DOCUMENT; - } + screen_skip(st, -U.wheellinescroll); do_draw= 1; break; case WHEELDOWNMOUSE: - if (tools & TOOL_DOCUMENT) { - doc_scroll++; - tools_cancel &= ~(TOOL_SUGG_LIST | TOOL_DOCUMENT); - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - if (!sel) { - texttool_suggest_select(texttool_suggest_first()); - } else if (sel && sel!=texttool_suggest_last() && sel->next) { - texttool_suggest_select(sel->next); - } - tools_cancel &= ~TOOL_SUGG_LIST; - } else { - screen_skip(st, U.wheellinescroll); - tools_cancel &= ~TOOL_DOCUMENT; - } + screen_skip(st, U.wheellinescroll); do_draw= 1; break; - default: - /* We don't want all sorts of events closing the suggestions box */ - tools_cancel &= ~TOOL_SUGG_LIST & ~TOOL_DOCUMENT; } } @@ -2779,22 +3009,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } - if (tools & TOOL_SUGG_LIST) { - if (tools_update & TOOL_SUGG_LIST) { - get_suggest_prefix(text); - } else if (tools_cancel & TOOL_SUGG_LIST) { - texttool_suggest_clear(); - } - do_draw= 1; - } - if (tools & TOOL_DOCUMENT) { - if (tools_cancel & TOOL_DOCUMENT) { - texttool_docs_clear(); - doc_scroll= 0; - } - do_draw= 1; - } - if (do_draw) { ScrArea *sa; |