Index: src/global.c =================================================================== --- src/global.c (revision 5095) +++ src/global.c (working copy) @@ -544,6 +544,7 @@ N_("Copy the current line and store it in the cutbuffer"); const char *nano_indent_msg = N_("Indent the current line"); const char *nano_unindent_msg = N_("Unindent the current line"); + const char *nano_whitespace_to_tabs_msg = N_("Convert leading whitespace to tabs"); const char *nano_undo_msg = N_("Undo the last operation"); const char *nano_redo_msg = N_("Redo the last undone operation"); #endif @@ -799,7 +800,9 @@ add_to_funcs(do_indent_void, MMAIN, N_("Indent Text"), IFSCHELP(nano_indent_msg), TOGETHER, NOVIEW); add_to_funcs(do_unindent, MMAIN, - N_("Unindent Text"), IFSCHELP(nano_unindent_msg), BLANKAFTER, NOVIEW); + N_("Unindent Text"), IFSCHELP(nano_unindent_msg), TOGETHER, NOVIEW); + add_to_funcs(do_whitespace_to_tabs, MMAIN, + N_("Convert leading whitespace to tabs"), IFSCHELP(nano_whitespace_to_tabs_msg), BLANKAFTER, NOVIEW); add_to_funcs(do_undo, MMAIN, N_("Undo"), IFSCHELP(nano_undo_msg), TOGETHER, NOVIEW); @@ -1035,6 +1038,7 @@ add_to_sclist(MMAIN, "M-6", do_copy_text, 0); add_to_sclist(MMAIN, "M-}", do_indent_void, 0); add_to_sclist(MMAIN, "M-{", do_unindent, 0); + add_to_sclist(MMAIN, "", do_whitespace_to_tabs, 0); add_to_sclist(MMAIN, "M-U", do_undo, 0); add_to_sclist(MMAIN, "M-E", do_redo, 0); #endif @@ -1279,6 +1283,8 @@ else if (!strcasecmp(input, "searchagain") || !strcasecmp(input, "research")) s->scfunc = do_research; + else if (!strcasecmp(input, "whitespace_to_tabs")) + s->scfunc = do_whitespace_to_tabs; #endif else if (!strcasecmp(input, "replace")) s->scfunc = do_replace; Index: src/nano.h =================================================================== --- src/nano.h (revision 5095) +++ src/nano.h (working copy) @@ -191,7 +191,11 @@ #ifndef DISABLE_WRAPPING SPLIT_BEGIN, SPLIT_END, #endif - JOIN, PASTE, INSERT, ENTER, OTHER + JOIN, PASTE, INSERT, ENTER, +#ifndef NANO_TINY + WS_TO_TABS, +#endif + OTHER } undo_type; typedef struct color_pair { Index: src/proto.h =================================================================== --- src/proto.h (revision 5095) +++ src/proto.h (working copy) @@ -641,6 +641,7 @@ #ifndef NANO_TINY void do_indent(ssize_t cols); void do_indent_void(void); +void do_whitespace_to_tabs(void); void do_unindent(void); void do_undo(void); void do_redo(void); Index: src/text.c =================================================================== --- src/text.c (revision 5095) +++ src/text.c (working copy) @@ -370,6 +370,104 @@ do_indent(-tabsize); } +#ifndef NANO_TINY +/* Convert leading whitespace to tabs on the current line or all + * lines covered by the mark if the mark is on. */ +void do_whitespace_to_tabs(void) +{ + filestruct *top, *bot, *f, *orig_fs; + size_t top_x, bot_x, line_len, i, diff_len_ws, + spaces, tabs, tabs_needed, ws_len, new_len; + bool ws_changed = FALSE; + + assert(openfile->current != NULL && openfile->current->data != NULL); + + /* If tabsize is zero, get out. */ + if (tabsize == 0) + return; + + /* 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; + } + + /* Save a reference to the current line so we can restore it later. */ + orig_fs = openfile->current; + + /* Go through each line of the text. */ + for (f = top; f != bot->next; f = f->next) { + + line_len = strlen(f->data); + spaces = 0; + tabs = 0; + + /* Calculate how much space the whitespace is using. */ + for (i = 0; i < line_len; i++) { + if (f->data[i] == ' ') { + spaces++; + } else if (f->data[i] == '\t') { + tabs++; + } else { + break; + } + } + + /* If there's no leading spaces there's nothing to do. */ + if (spaces == 0) + continue; + + /* Set the current line to the line we're editing. */ + openfile->current = f; + + /* Enable undoing since we're modifying this line. */ + add_undo(WS_TO_TABS); + + ws_len = spaces + tabs; + + /* Round up to closest tab width. */ + tabs_needed = ((spaces + tabsize - 1) / tabsize) + tabs; + + new_len = line_len - ws_len + tabs_needed; + /* Fill up the first part with tabs. */ + charset(f->data, '\t', tabs_needed); + if (tabs_needed < ws_len) { + /* Move the line data to it's new position. */ + charmove(f->data + tabs_needed, f->data + ws_len, line_len - ws_len + 1); + } + + openfile->totsize -= line_len - new_len; + + /* Adjust the cursor position. */ + if (openfile->mark_set && f == openfile->mark_begin && + openfile->mark_begin_x >= ws_len) + openfile->mark_begin_x -= line_len - new_len + (spaces / tabsize); + + diff_len_ws = ws_len - tabs_needed; + if (openfile->current_x > 0 && openfile->current_x > diff_len_ws) + openfile->current_x -= diff_len_ws; + + update_undo(WS_TO_TABS); + ws_changed = TRUE; + } + + if (ws_changed) { + /* Restore the current line. */ + openfile->current = orig_fs; + + /* Mark the file as modified. */ + set_modified(); + + /* Update the screen. */ + edit_refresh_needed = TRUE; + } +} +#endif + #define redo_paste undo_cut #define undo_paste redo_cut @@ -552,6 +650,15 @@ u->strdata = f->data; f->data = data; break; +#ifndef NANO_TINY + case WS_TO_TABS: + undidmsg = _("whitespace to tabs"); + goto_line_posx(u->lineno, u->begin); + data = u->strdata; + u->strdata = f->data; + f->data = data; + break; +#endif default: undidmsg = _("Internal error: unknown type. Please save your work."); break; @@ -675,6 +782,15 @@ free_filestruct(u->cutbuffer); u->cutbuffer = NULL; break; +#ifndef NANO_TINY + case WS_TO_TABS: + redidmsg = _("whitespace to tabs"); + data = u->strdata; + u->strdata = f->data; + f->data = data; + goto_line_posx(u->lineno, u->begin); + break; +#endif default: redidmsg = _("Internal error: unknown type. Please save your work."); break; @@ -979,6 +1095,12 @@ break; case ENTER: break; +#ifndef NANO_TINY + case WS_TO_TABS: + data = mallocstrcpy(NULL, fs->current->data); + u->strdata = data; + break; +#endif case OTHER: statusbar(_("Internal error: unknown type. Please save your work.")); break; @@ -1100,6 +1222,12 @@ u->begin = fs->current_x; u->lineno = openfile->current->lineno; break; +#ifndef NANO_TINY + case WS_TO_TABS: + u->begin = fs->current_x; + u->lineno = openfile->current->lineno; + break; +#endif case INSERT: u->mark_begin_lineno = openfile->current->lineno; break;