« RTFDをWindowsで開けるように変換[概要] | トップページ | El Capitan各種検証結果 »

2014年11月26日 (水)

RTFDをWindows対応に変換するApple Scriptを作ってみた

先日の [概要] の結果を踏まえて、RTFD変換Apple Scriptを作ってみた。

画像が貼り付けられている Mac OS X 独自形式の RTFD を、Windows でも画像が表示される RTF に変換するスクリプトである。

ついでに、ヒラギノなどの日本語のフォントをMS Pゴシックなどの Windows 用フォントに変換することも行っている。

なお、RTF を変換対象にした場合は、単にフォントの変更だけを行う。

テストは Yosemite 上でしか行っていない。他のバージョンの OS X 上での動作は確認していない。

使用方法は、以下に掲載するスクリプトをスクリプトエディターにコピー&ペーストして実行する。頻繁に使用するならメニューバーにスクリプトメニューを表示させてそこに登録するとか、コンパイルしてアプリ化すれば良いだろう(筆者はメニューバーに表示している)。

なお、当スクリプトは無保証である。当スクリプトを使用して生じた損害に対し、作者はいかなる責任も取らないので悪しからずご了承願いたい。

-- スクリプト次行から --

 (*
 RTFD ファイルを Windows に対応した 画像付き RTF にコンバートするスクリプト。
 Yosemite 上でしかテストしていない。
 フォント変換は一部の日本語フォントのみ。
 
 既知の問題:変換後、ごく稀に中央寄せが反映されなくなることがある。
 *)
 
 tell application "Finder"
   activate
   set added_items to selection
   if (length of added_items < 1) then
     display alert "Finder 上で何も選択されていません。選択してください。" buttons {"了解"} default button 1
   else
     set check_flag to 0
     repeat with i in added_items
       if (i as string) ends with ".rtfd" then
       else if (i as string) ends with ".rtf" then
       else
         set check_flag to check_flag + 1
       end if
     end repeat
     if check_flag > 0 then
       display alert "RTF / RTFD 以外のファイルが選択されています。RTF / RTFD だけを選択してください。" buttons {"了解"} default button 1
     else
       display dialog "Finder 上で選択されている RTF / RTFD ファイルをすべて Windows 対応型 RTF に変換します。\n\n※但し、RTFD に貼り付けられている画像形式が JPEG、PNG、TIFF、GIF、PSD、BMP の場合にのみ対応します。それ以外の画像は表示されなくなります。\n\n(ペーストした画像は TIFF 形式なので対応しています)\n\nフォントも Windows に合わせたフォントに変換されます。\n\nRTF の場合はフォントの変換のみです。" buttons {"キャンセル", "続行"} default button 2
       set bReturned to button returned of result
       if bReturned is "続行" then
         
         set export_folder to choose folder with prompt "コンバートされる RTFD ファイルの書き出しフォルダー作成場所を決めてください。"
         set exfolder_items to list folder export_folder
         set new_folder to "RTFコンバート"
         repeat --作成するフォルダの名前の重複チェック
           set nf_tmp to new_folder
           set repeat_flag to 0
           repeat with ei in exfolder_items
             if ((ei as text) = nf_tmp) then
               set new_folder to new_folder & "_"
               set repeat_flag to repeat_flag + 1
             end if
           end repeat
           if repeat_flag < 1 then exit repeat
         end repeat
         make new folder at export_folder with properties {name:new_folder}
         set new_path to POSIX path of ((folder new_folder of export_folder) as text)
         
         repeat with i in added_items
           if (i as string) ends with ".rtfd" then
             
             --変換後のファイル名を決めて保存する
             set extension hidden of i to true
             set displayed_name to displayed name of i
             set extension hidden of i to false
             set new_file_name to (displayed_name & ".rtf")
             
             set array_folder_items to list folder (i as text)
             set image_count to 0
             repeat with folder_item in array_folder_items
               set array_extensions to {".jpg", ".jpeg", "png", ".tiff", ".tif", ".gif", ".bmp", ".psd"}
               repeat with exte in array_extensions
                 if (folder_item as string) ends with exte then
                   set image_count to image_count + 1
                 end if
               end repeat
             end repeat
             
             duplicate file "TXT.rtf" of i to folder new_folder of export_folder
             
             if image_count < 1 then
               display dialog "「" & (name of i) & "」\n\nには変換可能な画像が含まれていません。" buttons {"了解して続行"} default button 1
               set name of file "TXT.rtf" of folder new_folder of export_folder to "TXT_RTFcon.rtf"
             else
               
               set i_path to POSIX path of (i as text)
               
               repeat with folder_item in array_folder_items
                 if ((folder_item as string) ends with ".tiff") or ((folder_item as string) ends with ".tif") then
                   set image_mode to "tiff"
                 else if (folder_item as string) ends with ".gif" then
                   set image_mode to "gif"
                 else if (folder_item as string) ends with ".psd" then
                   set image_mode to "gif"
                 else if (folder_item as string) ends with ".bmp" then
                   set image_mode to "bmp"
                 else if (folder_item as string) ends with ".png" then
                   set image_mode to "png"
                 else if ((folder_item as string) ends with ".jpg") or ((folder_item as string) ends with ".jpeg") then
                   set image_mode to "jpeg"
                 else
                   set image_mode to ""
                 end if
                 
                 if image_mode is not "" then
                   my replace_image(i_path, image_mode, folder_item, new_path)
                 end if
               end repeat
               
               (* 当スクリプトが対応していないタイプの画像が貼り付けられている場合、不要な画像タグを全て除去する *)
               try
                 do shell script "perl -e '$_=join \"\",<>; s/{{\\\\NeXTGraphic .+?}.}//sg; print;' < " & quoted form of (new_path & "TXT.rtf") & " > " & quoted form of (new_path & "TXT_RTFcon.rtf")
               on error
                 my error_exit("画像タグの除去に失敗")
               end try
             end if
           else
             duplicate i to folder new_folder of export_folder
             set new_file_name to name of i
             set name of file new_file_name of folder new_folder of export_folder to "TXT_RTFcon.rtf"
           end if
           
           (* 改行を変換。画像の前後で改行が反映されないことがあるので *)
           try
             do shell script "sed -e \"s/\\\\\\uc0\\\\\\u8232 /\\\\\\line /g\" " & quoted form of (new_path & "TXT_RTFcon.rtf") & " > " & quoted form of (new_path & "TXT.rtf")
           on error
             my error_exit("改行タグの変換に失敗")
           end try
           
           (* フォントを変換 *)
           --MS Pゴシック
           set ms_p_gothic to "\\\\\\'82\\\\\\'6c\\\\\\'82\\\\\\'72 \\\\\\'82\\\\\\'6f\\\\\\'83\\\\\\'53\\\\\\'83\\\\\\'56\\\\\\'83\\\\\\'62\\\\\\'83\\\\\\'4e"
           try
             do shell script "sed -e \"s/HiraKaku.\\{3,4\\}-W[0-9]/" & ms_p_gothic & "/g\" " & quoted form of (new_path & "TXT.rtf") & " > " & quoted form of (new_path & "TXT_RTFcon.rtf")
           on error
             my error_exit("ヒラギノ角ゴシックのMS Pゴシックへの変換に失敗")
           end try
           try
             do shell script "sed -e \"s/Osaka/" & ms_p_gothic & "/g\" " & quoted form of (new_path & "TXT_RTFcon.rtf") & " > " & quoted form of (new_path & "TXT.rtf")
           on error
             my error_exit("Osaka のMS Pゴシックへの変換に失敗")
           end try
           --MS P明朝
           set ms_p_mincho to "\\\\\\'82\\\\\\'6c\\\\\\'82\\\\\\'72 \\\\\\'82\\\\\\'6f\\\\\\'96\\\\\\'be\\\\\\'92\\\\\\'a9"
           try
             do shell script "sed -e \"s/HiraMinPro.*-W[0-9]/" & ms_p_mincho & "/g\" " & quoted form of (new_path & "TXT.rtf") & " > " & quoted form of (new_path & "TXT_RTFcon.rtf")
           on error
             my error_exit("MS P明朝への変換に失敗")
           end try
           --メイリオ
           set meiryo to "\\\\\\'83\\\\\\'81\\\\\\'83\\\\\\'43\\\\\\'83\\\\\\'8a\\\\\\'83\\\\\\'49"
           try
             do shell script "sed -e \"s/HiraMaruPro.*-W[0-9]/" & meiryo & "/g\" " & quoted form of (new_path & "TXT_RTFcon.rtf") & " > " & quoted form of (new_path & "TXT.rtf")
           on error
             my error_exit("メイリオへの変換に失敗")
           end try
           (* フォントを変換 ここまで *)
           
           set name of file "TXT.rtf" of (folder new_folder of export_folder) to new_file_name
           
           try
             do shell script "rm -f " & quoted form of new_path & "TXT_RTFcon.rtf"
           on error
             my error_exit(new_path & "TXT_RTFcon.rtf の削除に失敗しました")
           end try
         end repeat
         
         set temp_exist to get exists of file "temp.png" of (folder new_folder of export_folder)
         if temp_exist is true then
           try
             do shell script "rm -f " & quoted form of (POSIX path of ((file "temp.png" of (folder new_folder of export_folder)) as text))
           on error
             my error_exit(((file "temp.png" of (folder new_folder of export_folder)) as text) & "の削除に失敗しました")
           end try
         end if
         open folder new_folder of export_folder
         display dialog "終了しました。\n\n変換された RTF ファイルは Windows 上では画像が表示されます。Mac 上でも LibreOffice で開けば表示されます。" buttons {"終了"} default button 1
       end if
     end if
   end if
 end tell
 
 on replace_image(i_path, image_mode, folder_item, new_path)
   set tmp_folder_item to folder_item --後のエスケープのために先に別変数に入れる
   set folder_item to my replace_text(folder_item, "/", ":") --ファイル名に含まれる /  Unix 的には : らしい
   if (image_mode is "jpeg") or (image_mode is "png") then
     set image_path to (i_path & "/" & folder_item)
   else
     try
       do shell script "sips -s format png " & quoted form of (i_path & "/" & folder_item) & " --out " & quoted form of new_path & "temp.png"
     on error
       my error_exit((i_path & "/" & folder_item) & " の画像フォーマット変更に失敗")
     end try
     set image_mode to "png"
     set image_path to new_path & "temp.png"
   end if
   
   try
     set decoded_image to do shell script "hexdump -e '39/1 \"%02x\" \"\\n\"' " & quoted form of image_path & " | sed -e 's/ //g'" without altering line endings
   on error
     my error_exit((i_path & "/" & folder_item) & " を16進数化することに失敗")
   end try
   
   (* perl でのマッチングに備えて folder_item をエスケープする *)
   set tmp_folder_item to my replace_text(tmp_folder_item, "\\", "\\\\\\\\")
   set tmp_folder_item to my replace_text(tmp_folder_item, ".", "\\.")
   set tmp_folder_item to my replace_text(tmp_folder_item, "/", ":") --ファイル名に / が含まれる場合、内部的には : に変換処理されているらしい
   set tmp_folder_item to my replace_text(tmp_folder_item, "^", "\\^")
   set tmp_folder_item to my replace_text(tmp_folder_item, "$", "\\$")
   set tmp_folder_item to my replace_text(tmp_folder_item, "!", "\\!")
   set tmp_folder_item to my replace_text(tmp_folder_item, "?", "\\?")
   set tmp_folder_item to my replace_text(tmp_folder_item, ":", "\\:")
   set tmp_folder_item to my replace_text(tmp_folder_item, "(", "\\(")
   set tmp_folder_item to my replace_text(tmp_folder_item, ")", "\\)")
   set tmp_folder_item to my replace_text(tmp_folder_item, "[", "\\[")
   set tmp_folder_item to my replace_text(tmp_folder_item, "]", "\\]")
   set tmp_folder_item to my replace_text(tmp_folder_item, "{", "\\{")
   set tmp_folder_item to my replace_text(tmp_folder_item, "}", "\\}")
   set tmp_folder_item to my replace_text(tmp_folder_item, "-", "\\-")
   set tmp_folder_item to my replace_text(tmp_folder_item, "=", "\\=")
   set tmp_folder_item to my replace_text(tmp_folder_item, "+", "\\+")
   set tmp_folder_item to my replace_text(tmp_folder_item, "¥", "\\¥")
   
   (* 画像幅の抽出 *)
   try
     set image_width to do shell script "perl -e '$_=join \"\",<>; s/^.*?{{\\\\NeXTGraphic " & tmp_folder_item & " \\\\width(\\d{1,20}) \\\\height\\d{1,20}.+?}.}.*?$/$1/sg; print;' < " & quoted form of (new_path & "TXT.rtf") without altering line endings
   on error
     my error_exit(folder_item & "の画像幅の抽出に失敗")
   end try
   --正しく数字が取り出せているかどうか検証
   try
     set width_boolean to do shell script "perl -e '$_=join \"\",<>; if (" & quoted form of image_width & " =~ /^\\d{1,20}$/){print \"true\";}'" without altering line endings
   on error
     my error_exit(folder_item & "の画像幅が数字かどうかの検証に失敗")
   end try
   --数字を調整
   if width_boolean is "true" then
     set image_width to (image_width / 4 * 3) as integer
   else
     my error_exit(folder_item & "の画像幅値の調整に失敗")
   end if
   
   (* 画像高さの抽出 *)
   try
     set image_height to do shell script "perl -e '$_=join \"\",<>; s/^.*?{{\\\\NeXTGraphic " & tmp_folder_item & " \\\\width\\d{1,20} \\\\height(\\d{1,20}).+?}.}.*?$/$1/sg; print;' < " & quoted form of (new_path & "TXT.rtf") without altering line endings
   on error
     my error_exit(folder_item & "の画像高さの抽出に失敗")
   end try
   --正しく数字が取り出せているかどうか検証
   try
     set height_boolean to do shell script "perl -e '$_=join \"\",<>; if (" & quoted form of image_height & " =~ /^\\d{1,20}$/){print \"true\";}'" without altering line endings
   on error
     my error_exit(folder_item & "の画像高さが数字かどうかの検証に失敗")
   end try
   --数字を調整
   if height_boolean is "true" then
     set image_height to (image_height / 4 * 3) as integer
   else
     my error_exit(folder_item & "の画像高さ値の調整に失敗")
   end if
   
   (* 置換 *)
   try
     do shell script "perl -e '$_=join \"\",<>; s/{{\\\\NeXTGraphic " & tmp_folder_item & " \\\\width\\d{1,20} \\\\height\\d{1,20}.+?}.}/{\\\\pict\\\\" & image_mode & "blip\\\\picwgoal" & image_width & "\\\\pichgoal" & image_height & " \\n" & decoded_image & "}/sg; print;' < " & quoted form of (new_path & "TXT.rtf") & " > " & quoted form of (new_path & "TXT_RTFcon.rtf")
   on error
     my error_exit(folder_item & "の画像タグの置換に失敗")
   end try
   set decoded_image to ""
   
   try
     do shell script "mv " & quoted form of (new_path & "/TXT_RTFcon.rtf") & " " & quoted form of (new_path & "/TXT.rtf")
   on error
     my error_exit(folder_item & " 置換の後に TXT_RTFcon.rtf を TXT.rtf に書き込むことに失敗")
   end try
 end replace_image
 
 on error_exit(error_message)
   tell application "Finder" to display alert error_message & "。スクリプトを終了します。"
   error number -128
 end error_exit
 
 on replace_text(obj_text, search_str, replace_str)
   set astid_tmp to AppleScript's text item delimiters
   set AppleScript's text item delimiters to search_str
   set astid_texts to every text item of obj_text
   set AppleScript's text item delimiters to replace_str
   set obj_text to astid_texts as string
   set AppleScript's text item delimiters to astid_tmp
   return obj_text
 end replace_text

-- スクリプト前行まで --

« RTFDをWindowsで開けるように変換[概要] | トップページ | El Capitan各種検証結果 »

コメント

コメントを書く

(ウェブ上には掲載しません)

« RTFDをWindowsで開けるように変換[概要] | トップページ | El Capitan各種検証結果 »