diff options
Diffstat (limited to 'source/blender/blenkernel/intern/text.c')
-rw-r--r-- | source/blender/blenkernel/intern/text.c | 172 |
1 files changed, 146 insertions, 26 deletions
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 9f441b45db9..89456763b95 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -330,7 +330,7 @@ static void text_from_buf(Text *text, const unsigned char *buffer, const int len text->curc = text->selc = 0; } -int BKE_text_reload(Text *text) +bool BKE_text_reload(Text *text) { FILE *fp; int len; @@ -339,13 +339,24 @@ int BKE_text_reload(Text *text) char str[FILE_MAX]; BLI_stat_t st; - if (!text->name) return 0; - + if (!text->name) { + return false; + } + BLI_strncpy(str, text->name, FILE_MAX); BLI_path_abs(str, G.main->name); fp = BLI_fopen(str, "r"); - if (fp == NULL) return 0; + if (fp == NULL) { + return false; + } + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + fseek(fp, 0L, SEEK_SET); + if (UNLIKELY(len == -1)) { + fclose(fp); + return false; + } /* free memory: */ @@ -363,11 +374,6 @@ int BKE_text_reload(Text *text) MEM_freeN(text->undo_buf); init_undo_text(text); - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - fseek(fp, 0L, SEEK_SET); - - buffer = MEM_mallocN(len, "text_buffer"); /* under windows fread can return less than len bytes because * of CR stripping */ @@ -385,7 +391,7 @@ int BKE_text_reload(Text *text) text_from_buf(text, buffer, len); MEM_freeN(buffer); - return 1; + return true; } Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal) @@ -402,8 +408,18 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const BLI_path_abs(str, relpath); fp = BLI_fopen(str, "r"); - if (fp == NULL) return NULL; - + if (fp == NULL) { + return NULL; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + fseek(fp, 0L, SEEK_SET); + if (UNLIKELY(len == -1)) { + fclose(fp); + return NULL; + } + ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(str)); ta->id.us = 1; @@ -423,10 +439,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const /* clear undo buffer */ init_undo_text(ta); - - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - fseek(fp, 0L, SEEK_SET); buffer = MEM_mallocN(len, "text_buffer"); /* under windows fread can return less than len bytes because @@ -473,6 +485,7 @@ Text *BKE_text_copy(Main *bmain, Text *ta) BLI_listbase_clear(&tan->lines); tan->curl = tan->sell = NULL; + tan->compiled = NULL; tan->nlines = ta->nlines; @@ -651,7 +664,7 @@ void BKE_text_unlink(Main *bmain, Text *text) } } - /* Freestyle (while looping oer the scene) */ + /* Freestyle (while looping over the scene) */ for (srl = sce->r.layers.first; srl; srl = srl->next) { for (module = srl->freestyleConfig.modules.first; module; module = module->next) { if (module->script == text) @@ -1895,6 +1908,47 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos + 1] = 0; } +/* extends Link */ +struct LinkInt { + struct LinkInt *next, *prev; + int value; +}; + +/* unindentLines points to a ListBase composed of LinkInt elements, listing the numbers + * of the lines that should not be indented back. */ +static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask, const int line_index_mask_len) +{ + struct LinkInt *idata; + + BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len); + + /* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */ + if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) { + return; + } + + /* Opening buffer sequence with OP */ + text->undo_pos++; + text->undo_buf[text->undo_pos] = UNDO_UNINDENT; + text->undo_pos++; + /* Adding number of line numbers to read */ + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len); + + /* Adding linenumbers of lines that shall not be indented if undoing */ + for (idata = line_index_mask->first; idata; idata = idata->next) { + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value); + } + + /* Adding number of line numbers to read again */ + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len); + /* Adding current selection */ + txt_undo_store_cursors(text); + /* Closing with OP (same as above) */ + text->undo_buf[text->undo_pos] = UNDO_UNINDENT; + /* Marking as last undo operation */ + text->undo_buf[text->undo_pos + 1] = 0; +} + static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos) { unsigned short val; @@ -2189,7 +2243,6 @@ void txt_do_undo(Text *text) text->undo_pos--; break; case UNDO_INDENT: - case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: case UNDO_DUPLICATE: @@ -2203,9 +2256,6 @@ void txt_do_undo(Text *text) if (op == UNDO_INDENT) { txt_unindent(text); } - else if (op == UNDO_UNINDENT) { - txt_indent(text); - } else if (op == UNDO_COMMENT) { txt_uncomment(text); } @@ -2224,6 +2274,37 @@ void txt_do_undo(Text *text) text->undo_pos--; break; + case UNDO_UNINDENT: + { + int count; + int i; + /* Get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* Un-unindent */ + txt_indent(text); + + /* Get the count */ + count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); + /* Iterate! */ + txt_pop_sel(text); + + for (i = 0; i < count; i++) { + txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0); + /* Un-un-unindent */ + txt_unindent(text); + } + /* Restore selection */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + /* Jumo over count */ + txt_undo_read_uint32(text->undo_buf, &text->undo_pos); + /* Jump over closing OP byte */ + text->undo_pos--; + break; + } default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; @@ -2353,7 +2434,6 @@ void txt_do_redo(Text *text) break; case UNDO_INDENT: - case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: case UNDO_DUPLICATE: @@ -2369,9 +2449,6 @@ void txt_do_redo(Text *text) if (op == UNDO_INDENT) { txt_indent(text); } - else if (op == UNDO_UNINDENT) { - txt_unindent(text); - } else if (op == UNDO_COMMENT) { txt_comment(text); } @@ -2401,6 +2478,26 @@ void txt_do_redo(Text *text) txt_move_to(text, selln, selc, 1); break; + case UNDO_UNINDENT: + { + int count; + int i; + + text->undo_pos++; + /* Scan all the stuff described in txt_undo_add_unindent_op */ + count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + for (i = 0; i < count; i++) { + txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + } + /* Count again */ + txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + /* Get the selection and re-unindent */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + txt_unindent(text); + break; + } default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; @@ -2801,6 +2898,12 @@ void txt_unindent(Text *text) int indentlen = 1; bool unindented_first = false; + /* List of lines that are already at indent level 0, to store them later into the undo buffer */ + ListBase line_index_mask = {NULL, NULL}; + int line_index_mask_len = 0; + int curl_span_init = 0; + + /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; @@ -2814,6 +2917,10 @@ void txt_unindent(Text *text) indentlen = spaceslen; } + if (!undoing) { + curl_span_init = txt_get_span(text->lines.first, text->curl); + } + while (true) { bool changed = false; if (STREQLEN(text->curl->line, remove, indentlen)) { @@ -2823,6 +2930,16 @@ void txt_unindent(Text *text) memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1); changed = true; } + else { + if (!undoing) { + /* Create list element for 0 indent line */ + struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__); + idata->value = curl_span_init + num; + BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl)); + BLI_addtail(&line_index_mask, idata); + line_index_mask_len += 1; + } + } txt_make_dirty(text); txt_clean_text(text); @@ -2835,6 +2952,7 @@ void txt_unindent(Text *text) else { text->curl = text->curl->next; num++; + } } @@ -2848,8 +2966,10 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_op(text, UNDO_UNINDENT); + txt_undo_add_unindent_op(text, &line_index_mask, line_index_mask_len); } + + BLI_freelistN(&line_index_mask); } void txt_comment(Text *text) |