id ||= @minibuf_stack.length
@minibuf_stack[id] = s
unless @freeze
- draw_minibuf
+ draw_screen
Ncurses.refresh
end
id
def flash s
@flash = s
unless @freeze
- draw_minibuf
+ draw_screen
Ncurses.refresh
end
end
end
end
unless @freeze
- draw_minibuf
+ draw_screen
Ncurses.refresh
end
end
end
end
- ## load the full header text
- def load_header_text offset
+ def raw_header offset
ret = ""
File.open fn_for_offset(offset) do |f|
until f.eof? || (l = f.gets) =~ /^$/
ret
end
+ def raw_full_message offset
+ ret = ""
+ File.open fn_for_offset(offset) do |f|
+ ret += l until f.eof?
+ end
+ ret
+ end
+
def each
while File.exists?(fn = File.join(@dir, @end_offset.to_s))
yield @end_offset, [:draft, :inbox]
end).compact
end
- def reset!; @end_offset = 0; @dirty = true; end
+ def seek_to! offset
+ @end_offset = [offset, File.size(@f) - 1].min;
+ @dirty = true
+ end
+ def reset!; seek_to! 0; end
def == o; o.is_a?(Loader) && o.filename == filename; end
def to_s; "mbox://#{@filename}"; end
end
end
- ## load the full header text
- def load_header_text offset
+ def raw_header offset
ret = ""
@mutex.synchronize do
@f.seek offset
ret
end
+ def raw_full_message offset
+ ret = ""
+ @mutex.synchronize do
+ @f.seek offset
+ @f.gets # skip mbox header
+ until @f.eof? || (l = @f.gets) =~ BREAK_RE
+ ret += l
+ end
+ end
+ ret
+ end
+
def next
return nil if done?
@dirty = true
end
class Attachment
- attr_reader :content_type, :desc
+ attr_reader :content_type, :desc, :filename
def initialize content_type, desc, part
@content_type = content_type
@desc = desc
@part = part
@file = nil
+ desc =~ /filename="(.*?)"/ && @filename = $1
end
def view!
unless @file
@file = Tempfile.new "redwood.attachment"
- @file.print @part.decode
+ @file.print self
@file.close
end
## TODO: handle unknown mime-types
system "/usr/bin/run-mailcap --action=view #{@content_type}:#{@file.path}"
end
+
+ def to_s; @part.decode; end
end
class Text
message_to_chunks m
end
- def header_text
- @source.load_header_text @source_info
+ def raw_header
+ @source.raw_header @source_info
+ end
+
+ def raw_full_message
+ @source.raw_full_message @source_info
end
def content
k.add :collapse_non_new_messages, "Collapse all but new messages", 'N'
k.add :reply, "Reply to a message", 'r'
k.add :forward, "Forward a message", 'f'
+ k.add :save_to_disk, "Save message/attachment to disk", 's'
end
def initialize thread, hidden_labels=[]
def show_header
return unless(m = @message_lines[curpos])
BufferManager.spawn_unless_exists("Full header") do
- TextMode.new m.header_text
+ TextMode.new m.raw_header
end
end
update
end
+ def save fn
+ if File.exists? fn
+ return unless BufferManager.ask_yes_or_no "File exists. Overwrite?"
+ end
+ begin
+ File.open(fn, "w") { |f| yield f }
+ BufferManager.flash "Successfully wrote #{fn}."
+ rescue SystemCallError => e
+ BufferManager.flash "Error writing to file: #{e.message}"
+ end
+ end
+ private :save
+
+ def save_to_disk
+ return unless(chunk = @chunk_lines[curpos])
+ case chunk
+ when Message::Attachment
+ fn = BufferManager.ask :filename, "save attachment to file: ", chunk.filename
+ save(fn) { |f| f.print chunk } if fn
+ else
+ m = @message_lines[curpos]
+ fn = BufferManager.ask :filename, "save message to file: "
+ save(fn) { |f| f.print m.raw_full_message } if fn
+ end
+ end
+
def edit_message
return unless(m = @message_lines[curpos])
if m.is_draft?
else
## to disable subject grouping, use the next line instead
## (and the same for below)
+ Redwood::log "[1] normalized subject for #{id} is #{Message.normalize_subj(root.subj)}"
thread = (@subj_thread[Message.normalize_subj(root.subj)] ||= Thread.new)
#thread = (@subj_thread[root.id] ||= Thread.new)
else
## to disable subject grouping, use the next line instead
## (and the same above)
+ Redwood::log "[2] normalized subject for #{id} is #{Message.normalize_subj(root.subj)}"
thread = (@subj_thread[Message.normalize_subj(root.subj)] ||= Thread.new)
#thread = (@subj_thread[root.id] ||= Thread.new)