From 713e6056862cdfe9e8ec4275ae39d1abf25c36bf Mon Sep 17 00:00:00 2001
From: Ilia Maslakov <il.smind@gmail.com>
Date: Mon, 28 Mar 2011 12:42:53 +0000
Subject: [PATCH 1/2] Ticket #1652 (autodetect line-endings)
* On opening file, detect line-endings used by sampling some initial content.
* If it happen to be CR or CRLF, skip fast load path, and in edit_insert_file() convert such line endings to \n.
* Save detected line ending type for editor.
Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
---
src/editor/edit-impl.h | 2 +-
src/editor/edit.c | 59 +++++++++++++++++++++++++++++++++++++++++++-----
src/editor/editcmd.c | 12 +++++----
src/editor/editdraw.c | 21 ++++++++++++-----
4 files changed, 76 insertions(+), 18 deletions(-)
diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h
index d6bb43a..1b6ac87 100644
a
|
b
|
void edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, in |
290 | 290 | long *start_pos, long *end_pos, int *col1, int *col2); |
291 | 291 | int edit_insert_column_of_text_from_file (WEdit * edit, int file, |
292 | 292 | long *start_pos, long *end_pos, int *col1, int *col2); |
293 | | long edit_insert_file (WEdit * edit, const char *filename); |
| 293 | long edit_insert_file (WEdit * edit, const char *filename, LineBreaks lb_type); |
294 | 294 | int edit_load_back_cmd (WEdit * edit); |
295 | 295 | int edit_load_forward_cmd (WEdit * edit); |
296 | 296 | void edit_block_process_cmd (WEdit * edit, int macro_number); |
diff --git a/src/editor/edit.c b/src/editor/edit.c
index 226151b..0d854f9 100644
a
|
b
|
check_file_access (WEdit * edit, const char *filename, struct stat *st) |
419 | 419 | |
420 | 420 | /* --------------------------------------------------------------------------------------------- */ |
421 | 421 | /** |
| 422 | * detect type of line breaks of loaded file by lead BUF_MEDIUM bytes |
| 423 | * |
| 424 | */ |
| 425 | static LineBreaks |
| 426 | detect_lb_type (char *filename) |
| 427 | { |
| 428 | char buf[BUF_MEDIUM]; |
| 429 | ssize_t file, sz; |
| 430 | |
| 431 | file = mc_open (filename, O_RDONLY | O_BINARY); |
| 432 | if (file == -1) |
| 433 | return LB_ASIS; |
| 434 | |
| 435 | memset (buf, 0, sizeof (buf)); |
| 436 | sz = mc_read (file, buf, sizeof (buf) - 1); |
| 437 | if (sz < 0) |
| 438 | return LB_ASIS; |
| 439 | mc_close (file); |
| 440 | |
| 441 | buf[(size_t) sz] = '\0'; |
| 442 | if (strstr (buf, "\r\n") != NULL) |
| 443 | return LB_WIN; |
| 444 | if (strchr (buf, '\r') != NULL) |
| 445 | return LB_MAC; |
| 446 | return LB_ASIS; |
| 447 | } |
| 448 | |
| 449 | /* --------------------------------------------------------------------------------------------- */ |
| 450 | /** |
422 | 451 | * Open the file and load it into the buffers, either directly or using |
423 | 452 | * a filter. Return 0 on success, 1 on error. |
424 | 453 | * |
… |
… |
static int |
432 | 461 | edit_load_file (WEdit * edit) |
433 | 462 | { |
434 | 463 | int fast_load = 1; |
| 464 | LineBreaks lb_type = LB_ASIS; |
435 | 465 | |
436 | 466 | /* Cannot do fast load if a filter is used */ |
437 | 467 | if (edit_find_filter (edit->filename) >= 0) |
… |
… |
edit_load_file (WEdit * edit) |
454 | 484 | /* If we are dealing with a real file, check that it exists */ |
455 | 485 | if (check_file_access (edit, edit->filename, &edit->stat1)) |
456 | 486 | return 1; |
| 487 | lb_type = detect_lb_type(edit->filename); |
| 488 | |
| 489 | if (lb_type != LB_ASIS && lb_type != LB_UNIX) |
| 490 | fast_load = 0; |
457 | 491 | } |
458 | 492 | else |
459 | 493 | { |
… |
… |
edit_load_file (WEdit * edit) |
476 | 510 | if (*edit->filename) |
477 | 511 | { |
478 | 512 | edit->undo_stack_disable = 1; |
479 | | if (edit_insert_file (edit, edit->filename) == 0) |
| 513 | if (edit_insert_file (edit, edit->filename, lb_type) == 0) |
480 | 514 | { |
481 | 515 | edit_clean (edit); |
482 | 516 | return 1; |
483 | 517 | } |
| 518 | edit_set_markers (edit, 0, 0, 0, 0); |
484 | 519 | edit->undo_stack_disable = 0; |
485 | 520 | } |
486 | 521 | } |
487 | | edit->lb = LB_ASIS; |
| 522 | edit->lb = lb_type; |
488 | 523 | return 0; |
489 | 524 | } |
490 | 525 | |
… |
… |
user_menu (WEdit * edit, const char *menu_file, int selected_entry) |
1665 | 1700 | { |
1666 | 1701 | long ins_len; |
1667 | 1702 | |
1668 | | ins_len = edit_insert_file (edit, block_file); |
| 1703 | ins_len = edit_insert_file (edit, block_file, LB_ASIS); |
1669 | 1704 | if (nomark == 0 && ins_len > 0) |
1670 | 1705 | edit_set_markers (edit, start_mark, start_mark + ins_len, 0, 0); |
1671 | 1706 | } |
… |
… |
edit_write_stream (WEdit * edit, FILE * f) |
1987 | 2022 | /* --------------------------------------------------------------------------------------------- */ |
1988 | 2023 | /** inserts a file at the cursor, returns count of inserted bytes on success */ |
1989 | 2024 | long |
1990 | | edit_insert_file (WEdit * edit, const char *filename) |
| 2025 | edit_insert_file (WEdit * edit, const char *filename, LineBreaks lb_type) |
1991 | 2026 | { |
1992 | 2027 | char *p; |
1993 | 2028 | long ins_len = 0; |
… |
… |
edit_insert_file (WEdit * edit, const char *filename) |
2062 | 2097 | while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) |
2063 | 2098 | { |
2064 | 2099 | for (i = 0; i < blocklen; i++) |
2065 | | edit_insert (edit, buf[i]); |
| 2100 | { |
| 2101 | if (buf[i] == '\r') |
| 2102 | { |
| 2103 | if (lb_type == LB_MAC) |
| 2104 | edit_insert (edit, '\n'); |
| 2105 | else if (lb_type == LB_WIN) |
| 2106 | /* just skip */; |
| 2107 | else |
| 2108 | edit_insert (edit, '\r'); |
| 2109 | } |
| 2110 | else |
| 2111 | edit_insert (edit, buf[i]); |
| 2112 | } |
2066 | 2113 | } |
2067 | 2114 | /* highlight inserted text then not persistent blocks */ |
2068 | 2115 | if (!option_persistent_selections) |
… |
… |
edit_init (WEdit * edit, int lines, int columns, const char *filename, long line |
2157 | 2204 | edit->redo_stack_size = START_STACK_SIZE; |
2158 | 2205 | edit->redo_stack_size_mask = START_STACK_SIZE - 1; |
2159 | 2206 | edit->redo_stack = g_malloc0 ((edit->redo_stack_size + 10) * sizeof (long)); |
2160 | | |
| 2207 | edit->highlight = 0; |
2161 | 2208 | edit->utf8 = 0; |
2162 | 2209 | edit->converter = str_cnv_from_term; |
2163 | 2210 | edit_set_codeset (edit); |
diff --git a/src/editor/editcmd.c b/src/editor/editcmd.c
index fc027e1..15f1b45 100644
a
|
b
|
edit_get_save_file_as (WEdit * edit) |
432 | 432 | { |
433 | 433 | char *fname; |
434 | 434 | |
435 | | edit->lb = cur_lb; |
| 435 | /* Don't change current LB type (possibly autodetected), unless user asked to. */ |
| 436 | if (cur_lb != LB_ASIS) |
| 437 | edit->lb = cur_lb; |
436 | 438 | fname = tilde_expand (filename); |
437 | 439 | g_free (filename); |
438 | 440 | return fname; |
… |
… |
edit_paste_from_X_buf_cmd (WEdit * edit) |
2638 | 2640 | /* try use external clipboard utility */ |
2639 | 2641 | mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_from_ext_clip", NULL); |
2640 | 2642 | tmp = concat_dir_and_file (mc_config_get_cache_path (), EDIT_CLIP_FILE); |
2641 | | edit_insert_file (edit, tmp); |
| 2643 | edit_insert_file (edit, tmp, LB_ASIS); |
2642 | 2644 | g_free (tmp); |
2643 | 2645 | } |
2644 | 2646 | |
… |
… |
edit_insert_file_cmd (WEdit * edit) |
2754 | 2756 | } |
2755 | 2757 | else |
2756 | 2758 | { |
2757 | | if (edit_insert_file (edit, exp) != 0) |
| 2759 | if (edit_insert_file (edit, exp, LB_ASIS) != 0) |
2758 | 2760 | { |
2759 | 2761 | g_free (exp); |
2760 | 2762 | edit->force |= REDRAW_COMPLETELY; |
… |
… |
edit_sort_cmd (WEdit * edit) |
2828 | 2830 | if (edit_block_delete_cmd (edit)) |
2829 | 2831 | return 1; |
2830 | 2832 | tmp = concat_dir_and_file (mc_config_get_cache_path (), EDIT_TEMP_FILE); |
2831 | | edit_insert_file (edit, tmp); |
| 2833 | edit_insert_file (edit, tmp, LB_ASIS); |
2832 | 2834 | g_free (tmp); |
2833 | 2835 | return 0; |
2834 | 2836 | } |
… |
… |
edit_ext_cmd (WEdit * edit) |
2867 | 2869 | |
2868 | 2870 | edit->force |= REDRAW_COMPLETELY; |
2869 | 2871 | tmp = concat_dir_and_file (mc_config_get_cache_path (), EDIT_TEMP_FILE); |
2870 | | edit_insert_file (edit, tmp); |
| 2872 | edit_insert_file (edit, tmp, LB_ASIS); |
2871 | 2873 | g_free (tmp); |
2872 | 2874 | return 0; |
2873 | 2875 | } |
diff --git a/src/editor/editdraw.c b/src/editor/editdraw.c
index 7fbb294..d0368cf 100644
a
|
b
|
status_string (WEdit * edit, char *s, int w) |
102 | 102 | unsigned int cur_utf = 0; |
103 | 103 | int cw = 1; |
104 | 104 | |
| 105 | static const char *lb_names[LB_NAMES] = { |
| 106 | "", |
| 107 | "LF", |
| 108 | "CRLF", |
| 109 | "CR" |
| 110 | }; |
| 111 | |
105 | 112 | /* |
106 | 113 | * If we are at the end of file, print <EOF>, |
107 | 114 | * otherwise print the current character as is (if printable), |
… |
… |
status_string (WEdit * edit, char *s, int w) |
141 | 148 | /* The field lengths just prevent the status line from shortening too much */ |
142 | 149 | if (simple_statusbar) |
143 | 150 | g_snprintf (s, w, |
144 | | "%c%c%c%c %3ld %5ld/%ld %6ld/%ld %s %s", |
| 151 | "%c%c%c%c %3ld %5ld/%ld %6ld/%ld %s %s %s", |
145 | 152 | edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-', |
146 | 153 | edit->modified ? 'M' : '-', |
147 | 154 | macro_index < 0 ? '-' : 'R', |
… |
… |
status_string (WEdit * edit, char *s, int w) |
150 | 157 | edit->curs_line + 1, |
151 | 158 | edit->total_lines + 1, edit->curs1, edit->last_byte, byte_str, |
152 | 159 | #ifdef HAVE_CHARSET |
153 | | mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) : "" |
| 160 | mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) : "", |
154 | 161 | #else |
155 | | "" |
| 162 | "", |
156 | 163 | #endif |
| 164 | lb_names[edit->lb] |
157 | 165 | ); |
158 | 166 | else |
159 | 167 | g_snprintf (s, w, |
160 | | "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb) %s %s", |
| 168 | "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb) %s %s %s", |
161 | 169 | edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-', |
162 | 170 | edit->modified ? 'M' : '-', |
163 | 171 | macro_index < 0 ? '-' : 'R', |
… |
… |
status_string (WEdit * edit, char *s, int w) |
168 | 176 | edit->curs_line + 1, |
169 | 177 | edit->total_lines + 1, edit->curs1, edit->last_byte, byte_str, |
170 | 178 | #ifdef HAVE_CHARSET |
171 | | mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) : "" |
| 179 | mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) : "", |
172 | 180 | #else |
173 | | "" |
| 181 | "", |
174 | 182 | #endif |
| 183 | lb_names[edit->lb] |
175 | 184 | ); |
176 | 185 | } |
177 | 186 | |