]> git.cworth.org Git - sup/commitdiff
Merge branch 'utf8-fixes' into next
authorWilliam Morgan <wmorgan-sup@masanjin.net>
Wed, 20 May 2009 01:06:07 +0000 (18:06 -0700)
committerWilliam Morgan <wmorgan-sup@masanjin.net>
Wed, 20 May 2009 01:06:07 +0000 (18:06 -0700)
lib/sup/mode.rb
lib/sup/modes/edit-message-mode.rb
lib/sup/modes/scroll-mode.rb
lib/sup/modes/thread-index-mode.rb
lib/sup/modes/thread-view-mode.rb
lib/sup/util.rb

index bea46d92d425835142f2ae3b94eca035b0a64148..6433492c4d50acb187c1ae426620fde6a13b36be 100644 (file)
@@ -58,7 +58,7 @@ class Mode
       title = "Keybindings from #{Mode.make_name klass.name}"
       s = <<EOS
 #{title}
-#{'-' * title.length}
+#{'-' * title.display_length}
 
 #{km.help_text used_keys}
 EOS
index c91827938bbbbe0ef104d48cf02ff924af9e10f2..d7bd41c692f55a7fe7f23f0ebb608e506f938f06 100644 (file)
@@ -2,6 +2,7 @@ require 'tempfile'
 require 'socket' # just for gethostname!
 require 'pathname'
 require 'rmail'
+require 'jcode' # for RE_UTF8
 
 module Redwood
 
@@ -170,6 +171,29 @@ EOS
 
 protected
 
+  def mime_encode string
+    string = [string].pack('M') # basic quoted-printable
+    string.gsub!(/=\n/,'')      # .. remove trailing newline
+    string.gsub!(/_/,'=96')     # .. encode underscores
+    string.gsub!(/\?/,'=3F')    # .. encode question marks
+    string.gsub!(/ /,'_')       # .. translate space to underscores
+    "=?utf-8?q?#{string}?="
+  end
+
+  def mime_encode_subject string
+    return string unless string.match(String::RE_UTF8)
+    mime_encode string
+  end
+
+  RE_ADDRESS = /(.+)( <.*@.*>)/
+
+  # Encode "bælammet mitt <user@example.com>" into
+  # "=?utf-8?q?b=C3=A6lammet_mitt?= <user@example.com>
+  def mime_encode_address string
+    return string unless string.match(String::RE_UTF8)
+    string.sub(RE_ADDRESS) { |match| mime_encode($1) + $2 }
+  end
+
   def move_cursor_left
     if curpos < @selectors.length
       @selectors[curpos].roll_left
@@ -259,7 +283,7 @@ protected
           if i == 0
             header + " " + name
           else
-            (" " * (header.length + 1)) + name
+            (" " * (header.display_length + 1)) + name
           end + (i == things.length - 1 ? "" : ",")
         end
       end
@@ -335,14 +359,16 @@ protected
       m.header[k] = 
         case v
         when String
-          v
+          k.match(/subject/i) ? mime_encode_subject(v) : mime_encode_address(v)
         when Array
-          v.join ", "
+          v.map { |v| mime_encode_address v }.join ", "
         end
     end
+
     m.header["Date"] = date.rfc2822
     m.header["Message-Id"] = @message_id
     m.header["User-Agent"] = "Sup/#{Redwood::VERSION}"
+    m.header["Content-Transfer-Encoding"] = '8bit'
     m
   end
 
index 66c098be06b43d343ac7b0e120589d71b3ea20f7..05fe201c224d8cd9d423c1b704cc5f95a790b8c7 100644 (file)
@@ -73,7 +73,7 @@ class ScrollMode < Mode
     end
     if line
       @search_line = line + 1
-      search_goto_pos line, col, col + @search_query.length
+      search_goto_pos line, col, col + @search_query.display_length
       buffer.mark_dirty
     else
       BufferManager.flash "Not found!"
@@ -164,7 +164,7 @@ protected
           if match
             return [i, offset + match]
           else
-            offset += string.length
+            offset += string.display_length
           end
         end
       end
@@ -222,20 +222,20 @@ protected
     a.each do |color, text|
       raise "nil text for color '#{color}'" if text.nil? # good for debugging
       
-      if xpos + text.length < @leftcol
+      if xpos + text.display_length < @leftcol
         buffer.write ln - @topline, 0, "", :color => color,
                      :highlight => opts[:highlight]
-        xpos += text.length
+        xpos += text.display_length
       elsif xpos < @leftcol
         ## partial
         buffer.write ln - @topline, 0, text[(@leftcol - xpos) .. -1],
                      :color => color,
                      :highlight => opts[:highlight]
-        xpos += text.length
+        xpos += text.display_length
       else
         buffer.write ln - @topline, xpos - @leftcol, text,
                      :color => color, :highlight => opts[:highlight]
-        xpos += text.length
+        xpos += text.display_length
       end
     end
   end
index 055484e838059a8117ef8d0b4b3b79bc9e4f30a4..f65d241f93d674c5ff3a43f32db9c74413335dd1 100644 (file)
@@ -222,7 +222,7 @@ EOS
       ## let's see you do THIS in python
       @threads = @ts.threads.select { |t| !@hidden_threads[t] }.sort_by { |t| [t.date, t.first.id] }.reverse
       @size_widgets = @threads.map { |t| size_widget_for_thread t }
-      @size_widget_width = @size_widgets.max_of { |w| w.length }
+      @size_widget_width = @size_widgets.max_of { |w| w.display_length }
     end
 
     regen_text
@@ -794,9 +794,9 @@ protected
       last = i == ann.length - 1
 
       abbrev =
-        if cur_width + name.length > from_width
+        if cur_width + name.display_length > from_width
           name[0 ... (from_width - cur_width - 1)] + "."
-        elsif cur_width + name.length == from_width
+        elsif cur_width + name.display_length == from_width
           name[0 ... (from_width - cur_width)]
         else
           if last
@@ -806,7 +806,7 @@ protected
           end
         end
 
-      cur_width += abbrev.length
+      cur_width += abbrev.display_length
 
       if last && from_width > cur_width
         abbrev += " " * (from_width - cur_width)
index f27f00d81ec28bb7563dac53e2ccfd406ae93e2f..e6bd1597a236422e38de46e01241882eab284a00 100644 (file)
@@ -540,7 +540,7 @@ private
       (0 ... text.length).each do |i|
         @chunk_lines[@text.length + i] = m
         @message_lines[@text.length + i] = m
-        lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.length }.sum
+        lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.display_length }.sum
       end
 
       @text += text
@@ -561,7 +561,7 @@ private
           (0 ... text.length).each do |i|
             @chunk_lines[@text.length + i] = c
             @message_lines[@text.length + i] = m
-            lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.length }.sum - (depth * INDENT_SPACES)
+            lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.display_length }.sum - (depth * INDENT_SPACES)
             l.width = lw if lw > l.width
           end
           @text += text
@@ -635,7 +635,7 @@ private
 
   def format_person_list prefix, people
     ptext = people.map { |p| format_person p }
-    pad = " " * prefix.length
+    pad = "." * prefix.display_length
     [prefix + ptext.first + (ptext.length > 1 ? "," : "")] + 
       ptext[1 .. -1].map_with_index do |e, i|
         pad + e + (i == ptext.length - 1 ? "" : ",")
index c54a2c0db2b47efdc547000cc0ed9f8974536960..02575c0fdd0403e727f829692c7c1d9ffadbcde4 100644 (file)
@@ -172,6 +172,8 @@ class Object
 end
 
 class String
+  def display_length; scan(/./u).size end
+
   def camel_to_hyphy
     self.gsub(/([a-z])([A-Z0-9])/, '\1-\2').downcase
   end