diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2014-12-12 16:39:46 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-03-16 07:20:05 +0100 |
commit | c310c7d875c8aa871180de130e820ed19a2489f5 (patch) | |
tree | a42eacf47ba714c99af5ec04ff2ce1b4e9f87765 /src/spawn.cpp | |
parent | eee4f1ae84bcbb18a9ac0f5f450510533014dd40 (diff) | |
download | sciteco-c310c7d875c8aa871180de130e820ed19a2489f5.tar.gz |
implemented automatic EOL translation support
* activated via bit 4 of the ED flag (enabled by default)
* automatic EOL guessing on file loading and translation to LFs.
* works with files that have inconsistent EOL sequences.
* automatic translation to original EOL sequences on file saving
* works with inconsistent EOL sequences in the buffer.
This should usually not happen if the file was read in with
automatic EOL translation enabled.
* also works with the EC and EG commands
* performance is OK, depending on the file being translated.
When reading files with UNIX EOLs, the overhead is minimal
typically-sized files. For DOS EOLs the overhead is larger
but still acceptable.
* Return (line feed) is now an immediate editing command.
This centralizes EOL sequence insertion.
Later, other features like auto-indent could be added to
the editing command.
* get_eol() has been moved to main.cpp (now called
get_eol_seq()
* Warn if file ownership could not be preserved when
saving files.
* IOView has been almost completely rewritten based
on GIOChannels. The EOL translation code is also in IOView.
Diffstat (limited to 'src/spawn.cpp')
-rw-r--r-- | src/spawn.cpp | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/src/spawn.cpp b/src/spawn.cpp index 259f708..af42a95 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -26,6 +26,7 @@ #include "undo.h" #include "expressions.h" #include "qregisters.h" +#include "ioview.h" #include "ring.h" #include "parser.h" #include "error.h" @@ -308,6 +309,12 @@ StateExecuteCommand::done(const gchar *str) GIOChannel *stdin_chan, *stdout_chan; ctx.text_added = false; + /* opaque state for IOView::save() */ + ctx.stdin_state = 0; + /* opaque state for IOView::channel_read_with_eol() */ + ctx.stdout_state = 0; + /* eol style guessed from the stdout stream */ + ctx.eol_style = -1; ctx.error = NULL; argv = parse_shell_command_line(str, &ctx.error); @@ -341,7 +348,11 @@ StateExecuteCommand::done(const gchar *str) g_io_channel_set_buffered(stdin_chan, FALSE); g_io_channel_set_flags(stdout_chan, G_IO_FLAG_NONBLOCK, NULL); g_io_channel_set_encoding(stdout_chan, NULL, NULL); - g_io_channel_set_buffered(stdout_chan, FALSE); + /* + * IOView::save() expects the channel to be buffered + * for performance reasons + */ + g_io_channel_set_buffered(stdout_chan, TRUE); ctx.stdin_src = g_io_create_watch(stdin_chan, (GIOCondition)(G_IO_OUT | G_IO_ERR | G_IO_HUP)); @@ -368,8 +379,12 @@ StateExecuteCommand::done(const gchar *str) interface.ssm(SCI_DELETERANGE, ctx.from, ctx.to - ctx.from); interface.ssm(SCI_ENDUNDOACTION); - if (!register_argument && - (ctx.from != ctx.to || ctx.text_added)) { + if (register_argument) { + if (ctx.eol_style >= 0) { + register_argument->undo_set_eol_mode(); + register_argument->set_eol_mode(ctx.eol_style); + } + } else if (ctx.from != ctx.to || ctx.text_added) { /* undo action is only effective if it changed anything */ if (current_doc_must_undo()) interface.undo_ssm(SCI_UNDO); @@ -478,16 +493,17 @@ stdin_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer data) StateExecuteCommand::Context &ctx = *(StateExecuteCommand::Context *)data; - const gchar *buffer; - gsize bytes_written; + /* we always read from the current view */ + IOView *view = (IOView *)interface.get_current_view(); - buffer = (const gchar *)interface.ssm(SCI_GETRANGEPOINTER, - ctx.from, - ctx.to - ctx.start); + gsize bytes_written; - switch (g_io_channel_write_chars(chan, buffer, ctx.to - ctx.start, - &bytes_written, - ctx.error ? NULL : &ctx.error)) { + /* + * IOView::save() cares about automatic EOL conversion + */ + switch (view->save(chan, ctx.from, ctx.to - ctx.start, + &bytes_written, ctx.stdin_state, + ctx.error ? NULL : &ctx.error)) { case G_IO_STATUS_ERROR: /* do not yet quit -- we still have to reap the child */ goto remove; @@ -526,38 +542,54 @@ stdout_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer data) StateExecuteCommand::Context &ctx = *(StateExecuteCommand::Context *)data; - gchar buffer[1024]; - gsize bytes_read; + GIOStatus status; - switch (g_io_channel_read_chars(chan, buffer, sizeof(buffer)-1, - &bytes_read, - ctx.error ? NULL : &ctx.error)) { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_ERROR: - case G_IO_STATUS_EOF: - if (g_source_is_destroyed(ctx.child_src)) - g_main_loop_quit(ctx.mainloop); - return G_SOURCE_REMOVE; - case G_IO_STATUS_AGAIN: - return G_SOURCE_CONTINUE; - } - - if (register_argument) { - buffer[bytes_read] = '\0'; + gchar buffer[1024]; + gsize read_len = 0; + guint offset = 0; + gsize block_len = 0; + /* we're not really interested in that: */ + gboolean eol_style_inconsistent = FALSE; + + for (;;) { + status = IOView::channel_read_with_eol( + chan, buffer, sizeof(buffer), + read_len, offset, block_len, + ctx.stdout_state, ctx.eol_style, + eol_style_inconsistent, + ctx.error ? NULL : &ctx.error + ); + + switch (status) { + case G_IO_STATUS_NORMAL: + break; + case G_IO_STATUS_ERROR: + case G_IO_STATUS_EOF: + if (g_source_is_destroyed(ctx.child_src)) + g_main_loop_quit(ctx.mainloop); + return G_SOURCE_REMOVE; + case G_IO_STATUS_AGAIN: + return G_SOURCE_CONTINUE; + } - if (ctx.text_added) { - register_argument->undo_append_string(); - register_argument->append_string(buffer); + if (!block_len) + continue; + + if (register_argument) { + if (ctx.text_added) { + register_argument->undo_append_string(); + register_argument->append_string(buffer+offset, block_len); + } else { + register_argument->undo_set_string(); + register_argument->set_string(buffer+offset, block_len); + } } else { - register_argument->undo_set_string(); - register_argument->set_string(buffer); + interface.ssm(SCI_ADDTEXT, block_len, (sptr_t)(buffer+offset)); } - } else { - interface.ssm(SCI_ADDTEXT, bytes_read, (sptr_t)buffer); + ctx.text_added = true; } - ctx.text_added = true; + /* not reached */ return G_SOURCE_CONTINUE; } |