Fix for text editor un-indent undo

Same issue as T44381, re-use logic for indent.
This commit is contained in:
Campbell Barton 2015-09-16 03:30:02 +10:00
parent 860e25fe29
commit b8a8059e21
1 changed files with 103 additions and 131 deletions

View File

@ -1914,9 +1914,13 @@ struct LinkInt {
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)
/**
* 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_unprefix_op(
Text *text, char undo_op,
const ListBase *line_index_mask, const int line_index_mask_len)
{
struct LinkInt *idata;
@ -1929,7 +1933,7 @@ static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask
/* Opening buffer sequence with OP */
text->undo_pos++;
text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
text->undo_buf[text->undo_pos] = undo_op;
text->undo_pos++;
/* Adding number of line numbers to read */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
@ -1944,7 +1948,7 @@ static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask
/* Adding current selection */
txt_undo_store_cursors(text);
/* Closing with OP (same as above) */
text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
text->undo_buf[text->undo_pos] = undo_op;
/* Marking as last undo operation */
text->undo_buf[text->undo_pos + 1] = 0;
}
@ -2244,7 +2248,6 @@ void txt_do_undo(Text *text)
break;
case UNDO_INDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
@ -2259,9 +2262,6 @@ void txt_do_undo(Text *text)
else if (op == UNDO_COMMENT) {
txt_uncomment(text);
}
else if (op == UNDO_UNCOMMENT) {
txt_comment(text);
}
else if (op == UNDO_DUPLICATE) {
txt_delete_line(text, text->curl->next);
}
@ -2275,7 +2275,10 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
case UNDO_UNINDENT:
case UNDO_UNCOMMENT:
{
void (*txt_prefix_fn)(Text *);
void (*txt_unprefix_fn)(Text *);
int count;
int i;
/* Get and restore the cursors */
@ -2284,7 +2287,16 @@ void txt_do_undo(Text *text)
txt_move_to(text, selln, selc, 1);
/* Un-unindent */
txt_indent(text);
if (op == UNDO_UNINDENT) {
txt_prefix_fn = txt_indent;
txt_unprefix_fn = txt_unindent;
}
else {
txt_prefix_fn = txt_comment;
txt_unprefix_fn = txt_uncomment;
}
txt_prefix_fn(text);
/* Get the count */
count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
@ -2293,8 +2305,8 @@ void txt_do_undo(Text *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);
/* Un-un-unindent/comment */
txt_unprefix_fn(text);
}
/* Restore selection */
txt_move_to(text, curln, curc, 0);
@ -2823,26 +2835,19 @@ bool txt_replace_char(Text *text, unsigned int add)
return true;
}
void txt_indent(Text *text)
/**
* Generic prefix operation, use for comment & indent.
*
* \note caller must handle undo.
*/
static void txt_select_prefix(Text *text, const char *add)
{
int len, num, curc_old;
char *tmp;
const char *add = "\t";
int indentlen = 1;
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
const int indentlen = strlen(add);
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
/* insert spaces rather than tabs */
if (text->flags & TXT_TABSTOSPACES) {
add = tab_to_spaces;
indentlen = spaceslen;
}
BLI_assert(!ELEM(NULL, text->curl, text->sell));
curc_old = text->curc;
@ -2886,36 +2891,31 @@ void txt_indent(Text *text)
num--;
}
if (!undoing) {
txt_undo_add_op(text, UNDO_INDENT);
}
/* caller must handle undo */
}
void txt_unindent(Text *text)
/**
* Generic un-prefix operation, use for comment & indent.
*
* \param r_line_index_mask: List of lines that are already at indent level 0,
* to store them later into the undo buffer.
*
* \note caller must handle undo.
*/
static void txt_select_unprefix(
Text *text, const char *remove,
ListBase *r_line_index_mask, int *r_line_index_mask_len)
{
int num = 0;
const char *remove = "\t";
int indentlen = 1;
const int indentlen = strlen(remove);
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;
BLI_assert(!ELEM(NULL, text->curl, text->sell));
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
/* insert spaces rather than tabs */
if (text->flags & TXT_TABSTOSPACES) {
remove = tab_to_spaces;
indentlen = spaceslen;
}
BLI_listbase_clear(r_line_index_mask);
*r_line_index_mask_len = 0;
if (!undoing) {
curl_span_init = txt_get_span(text->lines.first, text->curl);
@ -2936,8 +2936,8 @@ void txt_unindent(Text *text)
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;
BLI_addtail(r_line_index_mask, idata);
(*r_line_index_mask_len) += 1;
}
}
@ -2964,57 +2964,20 @@ void txt_unindent(Text *text)
text->curl = text->curl->prev;
num--;
}
if (!undoing) {
txt_undo_add_unindent_op(text, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
/* caller must handle undo */
}
void txt_comment(Text *text)
{
int len, num;
char *tmp;
char add = '#';
const char *prefix = "#";
if (!text->curl) return;
if (!text->sell) return; // Need to change this need to check if only one line is selected to more than one
num = 0;
while (true) {
tmp = MEM_mallocN(text->curl->len + 2, "textline_string");
text->curc = 0;
if (text->curc) memcpy(tmp, text->curl->line, text->curc);
tmp[text->curc] = add;
len = text->curl->len - text->curc;
if (len > 0) memcpy(tmp + text->curc + 1, text->curl->line + text->curc, len);
tmp[text->curl->len + 1] = 0;
make_new_line(text->curl, tmp);
text->curc++;
txt_make_dirty(text);
txt_clean_text(text);
if (text->curl == text->sell) {
text->selc = text->sell->len;
break;
}
else {
text->curl = text->curl->next;
num++;
}
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
text->curc = 0;
while (num > 0) {
text->curl = text->curl->prev;
num--;
}
txt_select_prefix(text, prefix);
if (!undoing) {
txt_undo_add_op(text, UNDO_COMMENT);
}
@ -3022,46 +2985,55 @@ void txt_comment(Text *text)
void txt_uncomment(Text *text)
{
int num = 0;
char remove = '#';
const char *prefix = "#";
ListBase line_index_mask;
int line_index_mask_len;
if (!text->curl) return;
if (!text->sell) return;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
while (true) {
int i = 0;
if (text->curl->line[i] == remove) {
while (i < text->curl->len) {
text->curl->line[i] = text->curl->line[i + 1];
i++;
}
text->curl->len--;
}
txt_make_dirty(text);
txt_clean_text(text);
if (text->curl == text->sell) {
text->selc = text->sell->len;
break;
}
else {
text->curl = text->curl->next;
num++;
}
}
text->curc = 0;
while (num > 0) {
text->curl = text->curl->prev;
num--;
}
if (!undoing) {
txt_undo_add_op(text, UNDO_UNCOMMENT);
txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
void txt_indent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
txt_select_prefix(text, prefix);
if (!undoing) {
txt_undo_add_op(text, UNDO_INDENT);
}
}
void txt_unindent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
ListBase line_index_mask;
int line_index_mask_len;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
if (!undoing) {
txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
void txt_move_lines(struct Text *text, const int direction)