Index: src/text.c =================================================================== --- src/text.c (revision 5095) +++ src/text.c (working copy) @@ -367,7 +367,97 @@ * mark is on, tabsize columns. */ void do_unindent(void) { - do_indent(-tabsize); + bool modified = FALSE; + size_t line_len, i, m, last_indent, indent_len, tmp_indent, indent_diff; + filestruct *top, *bot, *f, *oldcur; + size_t top_x, bot_x, oldx; + + assert(openfile->current != NULL && openfile->current->data != NULL); + + /* If the mark is on, use all lines covered by the mark. */ + if (openfile->mark_set) { + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, NULL); + /* Otherwise, use the current line. */ + } else { + top = openfile->current; + bot = top; + } + + /* Go through each line of the text. */ + for (f = top; f != bot->next; f = f->next) { + + /* Measure the indentation of the line. */ + line_len = strlen(f->data); + m = 0; + indent_len = 0; + last_indent = 0; + tmp_indent = 0; + for (i = 0; i < line_len; i++) { + if (f->data[i] == '\t') { + last_indent = tmp_indent; + tmp_indent = i + 1; + m = 0; + indent_len++; + } else if (f->data[i] == ' ') { + m++; + indent_len++; + if(m == tabsize) { + last_indent = tmp_indent; + tmp_indent = i + 1; + m = 0; + } + } else { + /* The end of the indentation. */ + break; + } + } + + /* If there's no indentation on the line. Continue to + * the next line. */ + if (indent_len == 0) + continue; + + if (!modified) { + modified = TRUE; + add_undo(SPLIT_BEGIN); + oldcur = openfile->current; + } + + /* Trick do_deletion to work on our current line instead of + * the open file's current line. */ + openfile->current = f; + + /* Move the cursor and start deleting. */ + oldx = openfile->current_x; + openfile->current_x = indent_len; + indent_diff = indent_len - last_indent; + for (i = 0; i < indent_diff; i++) { + do_left(); + do_deletion(BACK); + } + + openfile->current_x = oldx; + if (openfile->current_x > last_indent && + openfile->current_x > indent_diff) { + openfile->current_x -= indent_diff; + } + + } + + if (modified) { + + add_undo(SPLIT_END); + + /* Restore our current line. */ + openfile->current = oldcur; + + /* Mark the file as modified. */ + set_modified(); + + /* Update the screen. */ + edit_refresh_needed = TRUE; + } } #define redo_paste undo_cut