##// END OF EJS Templates
Merged r1492 to r1498 from trunk....
Jean-Philippe Lang -
r1515:3f62305e91c4
parent child
Show More
@@ -298,7 +298,7 module ApplicationHelper
298 # source:some/file#L120 -> Link to line 120 of the file
298 # source:some/file#L120 -> Link to line 120 of the file
299 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
299 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
300 # export:some/file -> Force the download of the file
300 # export:some/file -> Force the download of the file
301 text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
301 text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
302 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
302 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
303 link = nil
303 link = nil
304 if esc.nil?
304 if esc.nil?
@@ -45,7 +45,7
45
45
46 <p class="other-formats">
46 <p class="other-formats">
47 <%= l(:label_export_to) %>
47 <%= l(:label_export_to) %>
48 <span><%= link_to 'Atom', {:format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
48 <span><%= link_to 'Atom', {:query_id => @query, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
49 <span><%= link_to 'CSV', {:format => 'csv'}, :class => 'csv' %></span>
49 <span><%= link_to 'CSV', {:format => 'csv'}, :class => 'csv' %></span>
50 <span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span>
50 <span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span>
51 </p>
51 </p>
@@ -17,6 +17,7
17 </div>
17 </div>
18 <br />
18 <br />
19
19
20 <% unless @replies.empty? %>
20 <h3 class="icon22 icon22-comment"><%= l(:label_reply_plural) %></h3>
21 <h3 class="icon22 icon22-comment"><%= l(:label_reply_plural) %></h3>
21 <% @replies.each do |message| %>
22 <% @replies.each do |message| %>
22 <a name="<%= "message-#{message.id}" %>"></a>
23 <a name="<%= "message-#{message.id}" %>"></a>
@@ -30,6 +31,7
30 <%= link_to_attachments message.attachments, :no_author => true %>
31 <%= link_to_attachments message.attachments, :no_author => true %>
31 </div>
32 </div>
32 <% end %>
33 <% end %>
34 <% end %>
33
35
34 <% if !@topic.locked? && authorize_for('messages', 'reply') %>
36 <% if !@topic.locked? && authorize_for('messages', 'reply') %>
35 <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
37 <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
@@ -620,3 +620,7 default_activity_development: Fejlesztés
620 enumeration_issue_priorities: Feladat prioritások
620 enumeration_issue_priorities: Feladat prioritások
621 enumeration_doc_categories: Dokumentum kategóriák
621 enumeration_doc_categories: Dokumentum kategóriák
622 enumeration_activities: Tevékenységek (idő rögzítés)
622 enumeration_activities: Tevékenységek (idő rögzítés)
623 mail_body_reminder: "%d neked kiosztott feladat határidős az elkövetkező %d napban:"
624 mail_subject_reminder: "%d feladat határidős az elkövetkező napokban"
625 text_user_wrote: '%s írta:'
626 label_duplicated_by: duplikálta
@@ -91,6 +91,8 mail_body_account_information_external: Du kan bruke din "%s"-konto for å logge
91 mail_body_account_information: Informasjon om din konto
91 mail_body_account_information: Informasjon om din konto
92 mail_subject_account_activation_request: %s kontoaktivering
92 mail_subject_account_activation_request: %s kontoaktivering
93 mail_body_account_activation_request: 'En ny bruker (%s) er registrert, og avventer din godkjenning:'
93 mail_body_account_activation_request: 'En ny bruker (%s) er registrert, og avventer din godkjenning:'
94 mail_subject_reminder: "%d sak(er) har frist de kommende dagene"
95 mail_body_reminder: "%d sak(er) som er tildelt deg har frist de kommende %d dager:"
94
96
95 gui_validation_error: 1 feil
97 gui_validation_error: 1 feil
96 gui_validation_error_plural: %d feil
98 gui_validation_error_plural: %d feil
@@ -445,7 +447,8 label_loading: Laster...
445 label_relation_new: Ny relasjon
447 label_relation_new: Ny relasjon
446 label_relation_delete: Slett relasjon
448 label_relation_delete: Slett relasjon
447 label_relates_to: relatert til
449 label_relates_to: relatert til
448 label_duplicates: duplikater
450 label_duplicates: dupliserer
451 label_duplicated_by: duplisert av
449 label_blocks: blokkerer
452 label_blocks: blokkerer
450 label_blocked_by: blokkert av
453 label_blocked_by: blokkert av
451 label_precedes: kommer før
454 label_precedes: kommer før
@@ -594,6 +597,7 text_destroy_time_entries_question: %.02f timer er ført på sakene du er i ferd
594 text_destroy_time_entries: Slett førte timer
597 text_destroy_time_entries: Slett førte timer
595 text_assign_time_entries_to_project: Overfør førte timer til prosjektet
598 text_assign_time_entries_to_project: Overfør førte timer til prosjektet
596 text_reassign_time_entries: 'Overfør førte timer til denne saken:'
599 text_reassign_time_entries: 'Overfør førte timer til denne saken:'
600 text_user_wrote: '%s skrev:'
597
601
598 default_role_manager: Leder
602 default_role_manager: Leder
599 default_role_developper: Utvikler
603 default_role_developper: Utvikler
@@ -332,7 +332,7 label_internal: Внутренний
332 label_last_changes: менее %d изменений
332 label_last_changes: менее %d изменений
333 label_change_view_all: Просмотреть все изменения
333 label_change_view_all: Просмотреть все изменения
334 label_personalize_page: Персонализировать данную страницу
334 label_personalize_page: Персонализировать данную страницу
335 label_comment: Комментировать
335 label_comment: комментарий
336 label_comment_plural: Комментарии
336 label_comment_plural: Комментарии
337 label_comment_add: Оставить комментарий
337 label_comment_add: Оставить комментарий
338 label_comment_added: Добавленный комментарий
338 label_comment_added: Добавленный комментарий
@@ -621,4 +621,9 label_overall_activity: Сводная активность
621 setting_default_projects_public: Новые проекты являются публичными
621 setting_default_projects_public: Новые проекты являются публичными
622 error_scm_annotate: "Данные отсутствуют или не могут быть подписаны."
622 error_scm_annotate: "Данные отсутствуют или не могут быть подписаны."
623 label_planning: Планирование
623 label_planning: Планирование
624 text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
624 text_subprojects_destroy_warning: 'Подпроекты: %s также будут удалены.'
625 label_and_its_subprojects: %s и все подпроекты
626 mail_body_reminder: "%d назначенных на вас задач на следующие %d дней:"
627 mail_subject_reminder: "%d назначенных на вас задач в ближайшие дни"
628 text_user_wrote: '%s написал:'
629 label_duplicated_by: duplicated by
@@ -91,6 +91,8 mail_body_account_information_external: 您可以使用 "%s" 帳號登入 Redmin
91 mail_body_account_information: 您的 Redmine 帳號資訊
91 mail_body_account_information: 您的 Redmine 帳號資訊
92 mail_subject_account_activation_request: Redmine 帳號啟用需求通知
92 mail_subject_account_activation_request: Redmine 帳號啟用需求通知
93 mail_body_account_activation_request: '有位新用戶 (%s) 已經完成註冊,正等候您的審核:'
93 mail_body_account_activation_request: '有位新用戶 (%s) 已經完成註冊,正等候您的審核:'
94 mail_subject_reminder: "您有 %d 個項目即將到期"
95 mail_body_reminder: "%d 個指派給您的項目,將於 %d 天之內到期:"
94
96
95 gui_validation_error: 1 個錯誤
97 gui_validation_error: 1 個錯誤
96 gui_validation_error_plural: %d 個錯誤
98 gui_validation_error_plural: %d 個錯誤
@@ -446,6 +448,7 label_relation_new: 建立新關聯
446 label_relation_delete: 刪除關聯
448 label_relation_delete: 刪除關聯
447 label_relates_to: 關聯至
449 label_relates_to: 關聯至
448 label_duplicates: 已重複
450 label_duplicates: 已重複
451 label_duplicated_by: 與後面所列項目重複
449 label_blocks: 阻擋
452 label_blocks: 阻擋
450 label_blocked_by: 被阻擋
453 label_blocked_by: 被阻擋
451 label_precedes: 優先於
454 label_precedes: 優先於
@@ -594,6 +597,7 text_destroy_time_entries_question: 您即將刪除的項目已報工 %.02f 小
594 text_destroy_time_entries: 刪除已報工的時數
597 text_destroy_time_entries: 刪除已報工的時數
595 text_assign_time_entries_to_project: 指定已報工的時數至專案中
598 text_assign_time_entries_to_project: 指定已報工的時數至專案中
596 text_reassign_time_entries: '重新指定已報工的時數至此項目:'
599 text_reassign_time_entries: '重新指定已報工的時數至此項目:'
600 text_user_wrote: '%s 先前提到:'
597
601
598 default_role_manager: 管理人員
602 default_role_manager: 管理人員
599 default_role_developper: 開發人員
603 default_role_developper: 開發人員
@@ -91,6 +91,8 mail_body_account_information_external: 您可以使用您的 "%s" 帐号来登
91 mail_body_account_information: 您的帐号信息
91 mail_body_account_information: 您的帐号信息
92 mail_subject_account_activation_request: %s帐号激活请求
92 mail_subject_account_activation_request: %s帐号激活请求
93 mail_body_account_activation_request: '新用户(%s)已完成注册,正在等候您的审核:'
93 mail_body_account_activation_request: '新用户(%s)已完成注册,正在等候您的审核:'
94 mail_subject_reminder: "%d 个问题需要尽快解决"
95 mail_body_reminder: "指派给您的 %d 个问题需要在 %d 天内完成:"
94
96
95 gui_validation_error: 1 个错误
97 gui_validation_error: 1 个错误
96 gui_validation_error_plural: %d 个错误
98 gui_validation_error_plural: %d 个错误
@@ -594,6 +596,7 text_destroy_time_entries_question: 您要删除的问题已经上报了 %.02f
594 text_destroy_time_entries: 删除上报的工作量
596 text_destroy_time_entries: 删除上报的工作量
595 text_assign_time_entries_to_project: 将已上报的工作量提交到项目中
597 text_assign_time_entries_to_project: 将已上报的工作量提交到项目中
596 text_reassign_time_entries: '将已上报的工作量指定到此问题:'
598 text_reassign_time_entries: '将已上报的工作量指定到此问题:'
599 text_user_wrote: '%s 写到:'
597
600
598 default_role_manager: 管理人员
601 default_role_manager: 管理人员
599 default_role_developper: 开发人员
602 default_role_developper: 开发人员
@@ -620,5 +623,4 default_activity_development: 开发
620 enumeration_issue_priorities: 问题优先级
623 enumeration_issue_priorities: 问题优先级
621 enumeration_doc_categories: 文档类别
624 enumeration_doc_categories: 文档类别
622 enumeration_activities: 活动(时间跟踪)
625 enumeration_activities: 活动(时间跟踪)
623 mail_subject_reminder: "%d issue(s) due in the next days"
626 label_duplicated_by: duplicated by
624 mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
@@ -118,7 +118,7 module Redmine
118 def logger
118 def logger
119 RAILS_DEFAULT_LOGGER
119 RAILS_DEFAULT_LOGGER
120 end
120 end
121
121
122 def shellout(cmd, &block)
122 def shellout(cmd, &block)
123 logger.debug "Shelling out: #{cmd}" if logger && logger.debug?
123 logger.debug "Shelling out: #{cmd}" if logger && logger.debug?
124 begin
124 begin
@@ -127,11 +127,22 module Redmine
127 block.call(io) if block_given?
127 block.call(io) if block_given?
128 end
128 end
129 rescue Errno::ENOENT => e
129 rescue Errno::ENOENT => e
130 msg = strip_credential(e.message)
130 # The command failed, log it and re-raise
131 # The command failed, log it and re-raise
131 logger.error("SCM command failed: #{cmd}\n with: #{e.message}")
132 logger.error("SCM command failed: #{strip_credential(cmd)}\n with: #{msg}")
132 raise CommandFailed.new(e.message)
133 raise CommandFailed.new(msg)
133 end
134 end
134 end
135 end
136
137 # Hides username/password in a given command
138 def self.hide_credential(cmd)
139 q = (RUBY_PLATFORM =~ /mswin/ ? '"' : "'")
140 cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
141 end
142
143 def strip_credential(cmd)
144 self.class.hide_credential(cmd)
145 end
135 end
146 end
136
147
137 class Entries < Array
148 class Entries < Array
@@ -237,7 +237,8 namespace :redmine do
237 text = text.gsub(/\[\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
237 text = text.gsub(/\[\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
238 text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
238 text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
239 text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
239 text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
240 text = text.gsub(/\[wiki:([^\s\]]+).*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
240 text = text.gsub(/\[wiki:([^\s\]]+)\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
241 text = text.gsub(/\[wiki:([^\s\]]+)\s(.*)\]/) {|s| "[[#{$1.delete(',./?;|:')}|#{$2.delete(',./?;|:')}]]"}
241
242
242 # Links to pages UsingJustWikiCaps
243 # Links to pages UsingJustWikiCaps
243 text = text.gsub(/([^!]|^)(^| )([A-Z][a-z]+[A-Z][a-zA-Z]+)/, '\\1\\2[[\3]]')
244 text = text.gsub(/([^!]|^)(^| )([A-Z][a-z]+[A-Z][a-zA-Z]+)/, '\\1\\2[[\3]]')
@@ -84,13 +84,13 Calendar._TT["INFO"] = "關於 calendar";
84 Calendar._TT["ABOUT"] =
84 Calendar._TT["ABOUT"] =
85 "DHTML 日期/時間 選擇器\n" +
85 "DHTML 日期/時間 選擇器\n" +
86 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
86 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
87 "最For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
87 "最新版本取得位址: http://www.dynarch.com/projects/calendar/\n" +
88 "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." +
88 "使用 GNU LGPL 發行. 參考 http://gnu.org/licenses/lgpl.html 以取得更多關於 LGPL 之細節。" +
89 "\n\n" +
89 "\n\n" +
90 "Date selection:\n" +
90 "日期選擇方式:\n" +
91 "- Use the \xab, \xbb buttons to select year\n" +
91 "- 使用滑鼠點擊 \xab 、 \xbb 按鈕選擇年份\n" +
92 "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
92 "- 使用滑鼠點擊 " + String.fromCharCode(0x2039) + " " + String.fromCharCode(0x203a) + " 按鈕選擇月份\n" +
93 "- Hold mouse button on any of the above buttons for faster selection.";
93 "- 使用滑鼠點擊上述按鈕並按住不放,可開啟快速選單。";
94 Calendar._TT["ABOUT_TIME"] = "\n\n" +
94 Calendar._TT["ABOUT_TIME"] = "\n\n" +
95 "時間選擇方式:\n" +
95 "時間選擇方式:\n" +
96 "- 「單擊」時分秒為遞增\n" +
96 "- 「單擊」時分秒為遞增\n" +
@@ -82,33 +82,33 Calendar._TT = {};
82 Calendar._TT["INFO"] = "关于日历";
82 Calendar._TT["INFO"] = "关于日历";
83
83
84 Calendar._TT["ABOUT"] =
84 Calendar._TT["ABOUT"] =
85 "DHTML Date/Time Selector\n" +
85 "DHTML 日期/时间 选择器\n" +
86 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
86 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
87 "For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
87 "最新版本请访问: http://www.dynarch.com/projects/calendar/\n" +
88 "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." +
88 "遵循 GNU LGPL 发布。详情请查阅 http://gnu.org/licenses/lgpl.html " +
89 "\n\n" +
89 "\n\n" +
90 "Date selection:\n" +
90 "日期选择:\n" +
91 "- Use the \xab, \xbb buttons to select year\n" +
91 "- 使用 \xab,\xbb 按钮选择年\n" +
92 "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
92 "- 使用 " + String.fromCharCode(0x2039) + "" + String.fromCharCode(0x203a) + " 按钮选择月\n" +
93 "- Hold mouse button on any of the above buttons for faster selection.";
93 "- 在上述按钮上按住不放可以快速选择";
94 Calendar._TT["ABOUT_TIME"] = "\n\n" +
94 Calendar._TT["ABOUT_TIME"] = "\n\n" +
95 "Time selection:\n" +
95 "时间选择:\n" +
96 "- Click on any of the time parts to increase it\n" +
96 "- 点击时间的任意部分来增加\n" +
97 "- or Shift-click to decrease it\n" +
97 "- Shift加点击来减少\n" +
98 "- or click and drag for faster selection.";
98 "- 点击后拖动进行快速选择";
99
99
100 Calendar._TT["PREV_YEAR"] = "上年 (hold for menu)";
100 Calendar._TT["PREV_YEAR"] = "上年(按住不放显示菜单)";
101 Calendar._TT["PREV_MONTH"] = "上月 (hold for menu)";
101 Calendar._TT["PREV_MONTH"] = "上月(按住不放显示菜单)";
102 Calendar._TT["GO_TODAY"] = "回到今天";
102 Calendar._TT["GO_TODAY"] = "回到今天";
103 Calendar._TT["NEXT_MONTH"] = "下月 (hold for menu)";
103 Calendar._TT["NEXT_MONTH"] = "下月(按住不放显示菜单)";
104 Calendar._TT["NEXT_YEAR"] = "下年 (hold for menu)";
104 Calendar._TT["NEXT_YEAR"] = "下年(按住不放显示菜单)";
105 Calendar._TT["SEL_DATE"] = "选择日期";
105 Calendar._TT["SEL_DATE"] = "选择日期";
106 Calendar._TT["DRAG_TO_MOVE"] = "拖动";
106 Calendar._TT["DRAG_TO_MOVE"] = "拖动";
107 Calendar._TT["PART_TODAY"] = " (今日)";
107 Calendar._TT["PART_TODAY"] = " (今日)";
108
108
109 // the following is to inform that "%s" is to be the first day of week
109 // the following is to inform that "%s" is to be the first day of week
110 // %s will be replaced with the day name.
110 // %s will be replaced with the day name.
111 Calendar._TT["DAY_FIRST"] = "Display %s first";
111 Calendar._TT["DAY_FIRST"] = "一周开始于 %s";
112
112
113 // This may be locale-dependent. It specifies the week-end days, as an array
113 // This may be locale-dependent. It specifies the week-end days, as an array
114 // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1
114 // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1
@@ -117,11 +117,11 Calendar._TT["WEEKEND"] = "0,6";
117
117
118 Calendar._TT["CLOSE"] = "关闭";
118 Calendar._TT["CLOSE"] = "关闭";
119 Calendar._TT["TODAY"] = "今天";
119 Calendar._TT["TODAY"] = "今天";
120 Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value";
120 Calendar._TT["TIME_PART"] = "Shift加点击或者拖动来变更";
121
121
122 // date formats
122 // date formats
123 Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
123 Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
124 Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
124 Calendar._TT["TT_DATE_FORMAT"] = "星期%a %b%e";
125
125
126 Calendar._TT["WK"] = "wk";
126 Calendar._TT["WK"] = "";
127 Calendar._TT["TIME"] = "Time:";
127 Calendar._TT["TIME"] = "时间:";
@@ -9,6 +9,8 jsToolBar.strings['Heading 2'] = '標題 2';
9 jsToolBar.strings['Heading 3'] = '標題 3';
9 jsToolBar.strings['Heading 3'] = '標題 3';
10 jsToolBar.strings['Unordered list'] = '項目清單';
10 jsToolBar.strings['Unordered list'] = '項目清單';
11 jsToolBar.strings['Ordered list'] = '編號清單';
11 jsToolBar.strings['Ordered list'] = '編號清單';
12 jsToolBar.strings['Preformatted text'] = '格式化文字';
12 jsToolBar.strings['Quote'] = '引文';
13 jsToolBar.strings['Unquote'] = '取消引文';
14 jsToolBar.strings['Preformatted text'] = '已格式文字';
13 jsToolBar.strings['Wiki link'] = '連結至 Wiki 頁面';
15 jsToolBar.strings['Wiki link'] = '連結至 Wiki 頁面';
14 jsToolBar.strings['Image'] = '圖片';
16 jsToolBar.strings['Image'] = '圖片';
@@ -1,14 +1,16
1 jsToolBar.strings = {};
1 jsToolBar.strings = {};
2 jsToolBar.strings['Strong'] = 'Strong';
2 jsToolBar.strings['Strong'] = '粗体';
3 jsToolBar.strings['Italic'] = 'Italic';
3 jsToolBar.strings['Italic'] = '斜体';
4 jsToolBar.strings['Underline'] = 'Underline';
4 jsToolBar.strings['Underline'] = '下划线';
5 jsToolBar.strings['Deleted'] = 'Deleted';
5 jsToolBar.strings['Deleted'] = '删除线';
6 jsToolBar.strings['Code'] = 'Inline Code';
6 jsToolBar.strings['Code'] = '程序代码';
7 jsToolBar.strings['Heading 1'] = 'Heading 1';
7 jsToolBar.strings['Heading 1'] = '标题 1';
8 jsToolBar.strings['Heading 2'] = 'Heading 2';
8 jsToolBar.strings['Heading 2'] = '标题 2';
9 jsToolBar.strings['Heading 3'] = 'Heading 3';
9 jsToolBar.strings['Heading 3'] = '标题 3';
10 jsToolBar.strings['Unordered list'] = 'Unordered list';
10 jsToolBar.strings['Unordered list'] = '无序列表';
11 jsToolBar.strings['Ordered list'] = 'Ordered list';
11 jsToolBar.strings['Ordered list'] = '排序列表';
12 jsToolBar.strings['Preformatted text'] = 'Preformatted text';
12 jsToolBar.strings['Quote'] = '引用';
13 jsToolBar.strings['Wiki link'] = 'Link to a Wiki page';
13 jsToolBar.strings['Unquote'] = '删除引用';
14 jsToolBar.strings['Image'] = 'Image';
14 jsToolBar.strings['Preformatted text'] = '格式化文本';
15 jsToolBar.strings['Wiki link'] = '连接到 Wiki 页面';
16 jsToolBar.strings['Image'] = '图片';
@@ -108,7 +108,9 class ApplicationHelperTest < HelperTestCase
108 '!version:"1.0"' => 'version:"1.0"',
108 '!version:"1.0"' => 'version:"1.0"',
109 '!source:/some/file' => 'source:/some/file',
109 '!source:/some/file' => 'source:/some/file',
110 # invalid expressions
110 # invalid expressions
111 'source:' => 'source:'
111 'source:' => 'source:',
112 # url hash
113 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
112 }
114 }
113 @project = Project.find(1)
115 @project = Project.find(1)
114 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
116 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
This diff has been collapsed as it changes many lines, (946 lines changed) Show them Hide them
@@ -1,473 +1,473
1 # Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>
1 # Copyright (c) 2006 4ssoM LLC <www.4ssoM.com>
2 # 1.12 contributed by Ed Moss.
2 # 1.12 contributed by Ed Moss.
3 #
3 #
4 # The MIT License
4 # The MIT License
5 #
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
11 # furnished to do so, subject to the following conditions:
12 #
12 #
13 # The above copyright notice and this permission notice shall be included in
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
14 # all copies or substantial portions of the Software.
15 #
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
22 # THE SOFTWARE.
23 #
23 #
24 # This is direct port of chinese.php
24 # This is direct port of chinese.php
25 #
25 #
26 # Chinese PDF support.
26 # Chinese PDF support.
27 #
27 #
28 # Usage is as follows:
28 # Usage is as follows:
29 #
29 #
30 # require 'fpdf'
30 # require 'fpdf'
31 # require 'chinese'
31 # require 'chinese'
32 # pdf = FPDF.new
32 # pdf = FPDF.new
33 # pdf.extend(PDF_Chinese)
33 # pdf.extend(PDF_Chinese)
34 #
34 #
35 # This allows it to be combined with other extensions, such as the bookmark
35 # This allows it to be combined with other extensions, such as the bookmark
36 # module.
36 # module.
37
37
38 module PDF_Chinese
38 module PDF_Chinese
39
39
40 Big5_widths={' '=>250,'!'=>250,'"'=>408,'#'=>668,''=>490,'%'=>875,'&'=>698,'\''=>250,
40 Big5_widths={' '=>250,'!'=>250,'"'=>408,'#'=>668,''=>490,'%'=>875,'&'=>698,'\''=>250,
41 '('=>240,')'=>240,'*'=>417,'+'=>667,','=>250,'-'=>313,'.'=>250,'/'=>520,'0'=>500,'1'=>500,
41 '('=>240,')'=>240,'*'=>417,'+'=>667,','=>250,'-'=>313,'.'=>250,'/'=>520,'0'=>500,'1'=>500,
42 '2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>250,''=>250,
42 '2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>250,''=>250,
43 '<'=>667,'='=>667,'>'=>667,'?'=>396,'@'=>921,'A'=>677,'B'=>615,'C'=>719,'D'=>760,'E'=>625,
43 '<'=>667,'='=>667,'>'=>667,'?'=>396,'@'=>921,'A'=>677,'B'=>615,'C'=>719,'D'=>760,'E'=>625,
44 'F'=>552,'G'=>771,'H'=>802,'I'=>354,'J'=>354,'K'=>781,'L'=>604,'M'=>927,'N'=>750,'O'=>823,
44 'F'=>552,'G'=>771,'H'=>802,'I'=>354,'J'=>354,'K'=>781,'L'=>604,'M'=>927,'N'=>750,'O'=>823,
45 'P'=>563,'Q'=>823,'R'=>729,'S'=>542,'T'=>698,'U'=>771,'V'=>729,'W'=>948,'X'=>771,'Y'=>677,
45 'P'=>563,'Q'=>823,'R'=>729,'S'=>542,'T'=>698,'U'=>771,'V'=>729,'W'=>948,'X'=>771,'Y'=>677,
46 'Z'=>635,'['=>344,'\\'=>520,']'=>344,'^'=>469,'_'=>500,'`'=>250,'a'=>469,'b'=>521,'c'=>427,
46 'Z'=>635,'['=>344,'\\'=>520,']'=>344,'^'=>469,'_'=>500,'`'=>250,'a'=>469,'b'=>521,'c'=>427,
47 'd'=>521,'e'=>438,'f'=>271,'g'=>469,'h'=>531,'i'=>250,'j'=>250,'k'=>458,'l'=>240,'m'=>802,
47 'd'=>521,'e'=>438,'f'=>271,'g'=>469,'h'=>531,'i'=>250,'j'=>250,'k'=>458,'l'=>240,'m'=>802,
48 'n'=>531,'o'=>500,'p'=>521,'q'=>521,'r'=>365,'s'=>333,'t'=>292,'u'=>521,'v'=>458,'w'=>677,
48 'n'=>531,'o'=>500,'p'=>521,'q'=>521,'r'=>365,'s'=>333,'t'=>292,'u'=>521,'v'=>458,'w'=>677,
49 'x'=>479,'y'=>458,'z'=>427,'{'=>480,'|'=>496,'end'=>480,'~'=>667}
49 'x'=>479,'y'=>458,'z'=>427,'{'=>480,'|'=>496,'end'=>480,'~'=>667}
50
50
51 GB_widths={' '=>207,'!'=>270,'"'=>342,'#'=>467,''=>462,'%'=>797,'&'=>710,'\''=>239,
51 GB_widths={' '=>207,'!'=>270,'"'=>342,'#'=>467,''=>462,'%'=>797,'&'=>710,'\''=>239,
52 '('=>374,')'=>374,'*'=>423,'+'=>605,','=>238,'-'=>375,'.'=>238,'/'=>334,'0'=>462,'1'=>462,
52 '('=>374,')'=>374,'*'=>423,'+'=>605,','=>238,'-'=>375,'.'=>238,'/'=>334,'0'=>462,'1'=>462,
53 '2'=>462,'3'=>462,'4'=>462,'5'=>462,'6'=>462,'7'=>462,'8'=>462,'9'=>462,':'=>238,''=>238,
53 '2'=>462,'3'=>462,'4'=>462,'5'=>462,'6'=>462,'7'=>462,'8'=>462,'9'=>462,':'=>238,''=>238,
54 '<'=>605,'='=>605,'>'=>605,'?'=>344,'@'=>748,'A'=>684,'B'=>560,'C'=>695,'D'=>739,'E'=>563,
54 '<'=>605,'='=>605,'>'=>605,'?'=>344,'@'=>748,'A'=>684,'B'=>560,'C'=>695,'D'=>739,'E'=>563,
55 'F'=>511,'G'=>729,'H'=>793,'I'=>318,'J'=>312,'K'=>666,'L'=>526,'M'=>896,'N'=>758,'O'=>772,
55 'F'=>511,'G'=>729,'H'=>793,'I'=>318,'J'=>312,'K'=>666,'L'=>526,'M'=>896,'N'=>758,'O'=>772,
56 'P'=>544,'Q'=>772,'R'=>628,'S'=>465,'T'=>607,'U'=>753,'V'=>711,'W'=>972,'X'=>647,'Y'=>620,
56 'P'=>544,'Q'=>772,'R'=>628,'S'=>465,'T'=>607,'U'=>753,'V'=>711,'W'=>972,'X'=>647,'Y'=>620,
57 'Z'=>607,'['=>374,'\\'=>333,']'=>374,'^'=>606,'_'=>500,'`'=>239,'a'=>417,'b'=>503,'c'=>427,
57 'Z'=>607,'['=>374,'\\'=>333,']'=>374,'^'=>606,'_'=>500,'`'=>239,'a'=>417,'b'=>503,'c'=>427,
58 'd'=>529,'e'=>415,'f'=>264,'g'=>444,'h'=>518,'i'=>241,'j'=>230,'k'=>495,'l'=>228,'m'=>793,
58 'd'=>529,'e'=>415,'f'=>264,'g'=>444,'h'=>518,'i'=>241,'j'=>230,'k'=>495,'l'=>228,'m'=>793,
59 'n'=>527,'o'=>524,'p'=>524,'q'=>504,'r'=>338,'s'=>336,'t'=>277,'u'=>517,'v'=>450,'w'=>652,
59 'n'=>527,'o'=>524,'p'=>524,'q'=>504,'r'=>338,'s'=>336,'t'=>277,'u'=>517,'v'=>450,'w'=>652,
60 'x'=>466,'y'=>452,'z'=>407,'{'=>370,'|'=>258,'end'=>370,'~'=>605}
60 'x'=>466,'y'=>452,'z'=>407,'{'=>370,'|'=>258,'end'=>370,'~'=>605}
61
61
62 def AddCIDFont(family,style,name,cw,cMap,registry)
62 def AddCIDFont(family,style,name,cw,cMap,registry)
63 #ActionController::Base::logger.debug registry.to_a.join(":").to_s
63 #ActionController::Base::logger.debug registry.to_a.join(":").to_s
64 fontkey=family.downcase+style.upcase
64 fontkey=family.downcase+style.upcase
65 unless @fonts[fontkey].nil?
65 unless @fonts[fontkey].nil?
66 Error("Font already added: family style")
66 Error("Font already added: family style")
67 end
67 end
68 i=@fonts.length+1
68 i=@fonts.length+1
69 name=name.gsub(' ','')
69 name=name.gsub(' ','')
70 @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, 'CMap'=>cMap,'registry'=>registry}
70 @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, 'CMap'=>cMap,'registry'=>registry}
71 end
71 end
72
72
73 def AddCIDFonts(family,name,cw,cMap,registry)
73 def AddCIDFonts(family,name,cw,cMap,registry)
74 AddCIDFont(family,'',name,cw,cMap,registry)
74 AddCIDFont(family,'',name,cw,cMap,registry)
75 AddCIDFont(family,'B',name+',Bold',cw,cMap,registry)
75 AddCIDFont(family,'B',name+',Bold',cw,cMap,registry)
76 AddCIDFont(family,'I',name+',Italic',cw,cMap,registry)
76 AddCIDFont(family,'I',name+',Italic',cw,cMap,registry)
77 AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry)
77 AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry)
78 end
78 end
79
79
80 def AddBig5Font(family='Big5',name='MSungStd-Light-Acro')
80 def AddBig5Font(family='Big5',name='MSungStd-Light-Acro')
81 #Add Big5 font with proportional Latin
81 #Add Big5 font with proportional Latin
82 cw=Big5_widths
82 cw=Big5_widths
83 cMap='ETenms-B5-H'
83 cMap='ETenms-B5-H'
84 registry={'ordering'=>'CNS1','supplement'=>0}
84 registry={'ordering'=>'CNS1','supplement'=>0}
85 #ActionController::Base::logger.debug registry.to_a.join(":").to_s
85 #ActionController::Base::logger.debug registry.to_a.join(":").to_s
86 AddCIDFonts(family,name,cw,cMap,registry)
86 AddCIDFonts(family,name,cw,cMap,registry)
87 end
87 end
88
88
89 def AddBig5hwFont(family='Big5-hw',name='MSungStd-Light-Acro')
89 def AddBig5hwFont(family='Big5-hw',name='MSungStd-Light-Acro')
90 #Add Big5 font with half-witdh Latin
90 #Add Big5 font with half-witdh Latin
91 cw = {}
91 cw = {}
92 32.upto(126) do |i|
92 32.upto(126) do |i|
93 cw[i.chr]=500
93 cw[i.chr]=500
94 end
94 end
95 cMap='ETen-B5-H'
95 cMap='ETen-B5-H'
96 registry={'ordering'=>'CNS1','supplement'=>0}
96 registry={'ordering'=>'CNS1','supplement'=>0}
97 AddCIDFonts(family,name,cw,cMap,registry)
97 AddCIDFonts(family,name,cw,cMap,registry)
98 end
98 end
99
99
100 def AddGBFont(family='GB',name='STSongStd-Light-Acro')
100 def AddGBFont(family='GB',name='STSongStd-Light-Acro')
101 #Add GB font with proportional Latin
101 #Add GB font with proportional Latin
102 cw=GB_widths
102 cw=GB_widths
103 cMap='GBKp-EUC-H'
103 cMap='GBKp-EUC-H'
104 registry={'ordering'=>'GB1','supplement'=>2}
104 registry={'ordering'=>'GB1','supplement'=>2}
105 AddCIDFonts(family,name,cw,cMap,registry)
105 AddCIDFonts(family,name,cw,cMap,registry)
106 end
106 end
107
107
108 def AddGBhwFont(family='GB-hw',name='STSongStd-Light-Acro')
108 def AddGBhwFont(family='GB-hw',name='STSongStd-Light-Acro')
109 #Add GB font with half-width Latin
109 #Add GB font with half-width Latin
110 32.upto(126) do |i|
110 32.upto(126) do |i|
111 cw[i.chr]=500
111 cw[i.chr]=500
112 end
112 end
113 cMap='GBK-EUC-H'
113 cMap='GBK-EUC-H'
114 registry={'ordering'=>'GB1','supplement'=>2}
114 registry={'ordering'=>'GB1','supplement'=>2}
115 AddCIDFonts(family,name,cw,cMap,registry)
115 AddCIDFonts(family,name,cw,cMap,registry)
116 end
116 end
117
117
118 def GetStringWidth(s)
118 def GetStringWidth(s)
119 if(@CurrentFont['type']=='Type0')
119 if(@CurrentFont['type']=='Type0')
120 return GetMBStringWidth(s)
120 return GetMBStringWidth(s)
121 else
121 else
122 return super(s)
122 return super(s)
123 end
123 end
124 end
124 end
125
125
126 def GetMBStringWidth(s)
126 def GetMBStringWidth(s)
127 #Multi-byte version of GetStringWidth()
127 #Multi-byte version of GetStringWidth()
128 l=0
128 l=0
129 cw=@CurrentFont['cw']
129 cw=@CurrentFont['cw']
130 nb=s.length
130 nb=s.length
131 i=0
131 i=0
132 while(i<nb)
132 while(i<nb)
133 c=s[i]
133 c=s[i]
134 if(c<128)
134 if(c<128)
135 l+=cw[c.chr] if cw[c.chr]
135 l+=cw[c.chr] if cw[c.chr]
136 i+=1
136 i+=1
137 else
137 else
138 l+=1000
138 l+=1000
139 i+=2
139 i+=2
140 end
140 end
141 end
141 end
142 return l*@FontSize/1000
142 return l*@FontSize/1000
143 end
143 end
144
144
145 def MultiCell(w,h,txt,border=0,align='L',fill=0)
145 def MultiCell(w,h,txt,border=0,align='L',fill=0)
146 if(@CurrentFont['type']=='Type0')
146 if(@CurrentFont['type']=='Type0')
147 MBMultiCell(w,h,txt,border,align,fill)
147 MBMultiCell(w,h,txt,border,align,fill)
148 else
148 else
149 super(w,h,txt,border,align,fill)
149 super(w,h,txt,border,align,fill)
150 end
150 end
151 end
151 end
152
152
153 def MBMultiCell(w,h,txt,border=0,align='L',fill=0)
153 def MBMultiCell(w,h,txt,border=0,align='L',fill=0)
154 #Multi-byte version of MultiCell()
154 #Multi-byte version of MultiCell()
155 cw=@CurrentFont['cw']
155 cw=@CurrentFont['cw']
156 if(w==0)
156 if(w==0)
157 w=@w-@rMargin-@x
157 w=@w-@rMargin-@x
158 end
158 end
159 wmax=(w-2*@cMargin)*1000/@FontSize
159 wmax=(w-2*@cMargin)*1000/@FontSize
160 s=txt.gsub("\r",'')
160 s=txt.gsub("\r",'')
161 nb=s.length
161 nb=s.length
162 if(nb>0 and s[nb-1]=="\n")
162 if(nb>0 and s[nb-1]=="\n")
163 nb-=1
163 nb-=1
164 end
164 end
165 b=0
165 b=0
166 if(border)
166 if(border)
167 if(border==1)
167 if(border==1)
168 border='LTRB'
168 border='LTRB'
169 b='LRT'
169 b='LRT'
170 b2='LR'
170 b2='LR'
171 else
171 else
172 b2=''
172 b2=''
173 if(border.to_s.index('L'))
173 if(border.to_s.index('L'))
174 b2+='L'
174 b2+='L'
175 end
175 end
176 if(border.to_s.index('R'))
176 if(border.to_s.index('R'))
177 b2+='R'
177 b2+='R'
178 end
178 end
179 b=border.to_s.index('T') ? b2+'T' : b2
179 b=border.to_s.index('T') ? b2+'T' : b2
180 end
180 end
181 end
181 end
182 sep=-1
182 sep=-1
183 i=0
183 i=0
184 j=0
184 j=0
185 l=0
185 l=0
186 nl=1
186 nl=1
187 while(i<nb)
187 while(i<nb)
188 #Get next character
188 #Get next character
189 c=s[i]
189 c=s[i]
190 #Check if ASCII or MB
190 #Check if ASCII or MB
191 ascii=(c<128)
191 ascii=(c<128)
192 if(c=="\n")
192 if(c.chr=="\n")
193 #Explicit line break
193 #Explicit line break
194 Cell(w,h,s[j,i-j],b,2,align,fill)
194 Cell(w,h,s[j,i-j],b,2,align,fill)
195 i+=1
195 i+=1
196 sep=-1
196 sep=-1
197 j=i
197 j=i
198 l=0
198 l=0
199 nl+=1
199 nl+=1
200 if(border and nl==2)
200 if(border and nl==2)
201 b=b2
201 b=b2
202 end
202 end
203 next
203 next
204 end
204 end
205 if(!ascii)
205 if(!ascii)
206 sep=i
206 sep=i
207 ls=l
207 ls=l
208 elsif(c==' ')
208 elsif(c==' ')
209 sep=i
209 sep=i
210 ls=l
210 ls=l
211 end
211 end
212 l+=ascii ? (cw[c.chr] || 0) : 1000
212 l+=ascii ? (cw[c.chr] || 0) : 1100
213 if(l>wmax)
213 if(l>wmax)
214 #Automatic line break
214 #Automatic line break
215 if(sep==-1 or i==j)
215 if(sep==-1 or i==j)
216 if(i==j)
216 if(i==j)
217 i+=ascii ? 1 : 2
217 i+=ascii ? 1 : 3
218 end
218 end
219 Cell(w,h,s[j,i-j],b,2,align,fill)
219 Cell(w,h,s[j,i-j],b,2,align,fill)
220 else
220 else
221 Cell(w,h,s[j,sep-j],b,2,align,fill)
221 Cell(w,h,s[j,sep-j],b,2,align,fill)
222 i=(s[sep]==' ') ? sep+1 : sep
222 i=(s[sep]==' ') ? sep+1 : sep
223 end
223 end
224 sep=-1
224 sep=-1
225 j=i
225 j=i
226 l=0
226 l=0
227 # nl+=1
227 # nl+=1
228 if(border and nl==2)
228 if(border and nl==2)
229 b=b2
229 b=b2
230 end
230 end
231 else
231 else
232 i+=ascii ? 1 : 2
232 i+=ascii ? 1 : 3
233 end
233 end
234 end
234 end
235 #Last chunk
235 #Last chunk
236 if(border and not border.to_s.index('B').nil?)
236 if(border and not border.to_s.index('B').nil?)
237 b+='B'
237 b+='B'
238 end
238 end
239 Cell(w,h,s[j,i-j],b,2,align,fill)
239 Cell(w,h,s[j,i-j],b,2,align,fill)
240 @x=@lMargin
240 @x=@lMargin
241 end
241 end
242
242
243 def Write(h,txt,link='')
243 def Write(h,txt,link='')
244 if(@CurrentFont['type']=='Type0')
244 if(@CurrentFont['type']=='Type0')
245 MBWrite(h,txt,link)
245 MBWrite(h,txt,link)
246 else
246 else
247 super(h,txt,link)
247 super(h,txt,link)
248 end
248 end
249 end
249 end
250
250
251 def MBWrite(h,txt,link)
251 def MBWrite(h,txt,link)
252 #Multi-byte version of Write()
252 #Multi-byte version of Write()
253 cw=@CurrentFont['cw']
253 cw=@CurrentFont['cw']
254 w=@w-@rMargin-@x
254 w=@w-@rMargin-@x
255 wmax=(w-2*@cMargin)*1000/@FontSize
255 wmax=(w-2*@cMargin)*1000/@FontSize
256 s=txt.gsub("\r",'')
256 s=txt.gsub("\r",'')
257 nb=s.length
257 nb=s.length
258 sep=-1
258 sep=-1
259 i=0
259 i=0
260 j=0
260 j=0
261 l=0
261 l=0
262 nl=1
262 nl=1
263 while(i<nb)
263 while(i<nb)
264 #Get next character
264 #Get next character
265 c=s[i]
265 c=s[i]
266 #Check if ASCII or MB
266 #Check if ASCII or MB
267 ascii=(c<128)
267 ascii=(c<128)
268 if(c=="\n")
268 if(c.chr=="\n")
269 #Explicit line break
269 #Explicit line break
270 Cell(w,h,s[j,i-j],0,2,'',0,link)
270 Cell(w,h,s[j,i-j],0,2,'',0,link)
271 i+=1
271 i+=1
272 sep=-1
272 sep=-1
273 j=i
273 j=i
274 l=0
274 l=0
275 if(nl==1)
275 if(nl==1)
276 @x=@lMargin
276 @x=@lMargin
277 w=@w-@rMargin-@x
277 w=@w-@rMargin-@x
278 wmax=(w-2*@cMargin)*1000/@FontSize
278 wmax=(w-2*@cMargin)*1000/@FontSize
279 end
279 end
280 nl+=1
280 nl+=1
281 next
281 next
282 end
282 end
283 if(!ascii or c==' ')
283 if(!ascii or c==' ')
284 sep=i
284 sep=i
285 end
285 end
286 l+=ascii ? cw[c.chr] : 1000
286 l+=ascii ? cw[c.chr] : 1100
287 if(l>wmax)
287 if(l>wmax)
288 #Automatic line break
288 #Automatic line break
289 if(sep==-1 or i==j)
289 if(sep==-1 or i==j)
290 if(@x>@lMargin)
290 if(@x>@lMargin)
291 #Move to next line
291 #Move to next line
292 @x=@lMargin
292 @x=@lMargin
293 @y+=h
293 @y+=h
294 w=@w-@rMargin-@x
294 w=@w-@rMargin-@x
295 wmax=(w-2*@cMargin)*1000/@FontSize
295 wmax=(w-2*@cMargin)*1000/@FontSize
296 i+=1
296 i+=1
297 nl+=1
297 nl+=1
298 next
298 next
299 end
299 end
300 if(i==j)
300 if(i==j)
301 i+=ascii ? 1 : 2
301 i+=ascii ? 1 : 3
302 end
302 end
303 Cell(w,h,s[j,i-j],0,2,'',0,link)
303 Cell(w,h,s[j,i-j],0,2,'',0,link)
304 else
304 else
305 Cell(w,h,s[j,sep-j],0,2,'',0,link)
305 Cell(w,h,s[j,sep-j],0,2,'',0,link)
306 i=(s[sep]==' ') ? sep+1 : sep
306 i=(s[sep]==' ') ? sep+1 : sep
307 end
307 end
308 sep=-1
308 sep=-1
309 j=i
309 j=i
310 l=0
310 l=0
311 if(nl==1)
311 if(nl==1)
312 @x=@lMargin
312 @x=@lMargin
313 w=@w-@rMargin-@x
313 w=@w-@rMargin-@x
314 wmax=(w-2*@cMargin)*1000/@FontSize
314 wmax=(w-2*@cMargin)*1000/@FontSize
315 end
315 end
316 nl+=1
316 nl+=1
317 else
317 else
318 i+=ascii ? 1 : 2
318 i+=ascii ? 1 : 3
319 end
319 end
320 end
320 end
321 #Last chunk
321 #Last chunk
322 if(i!=j)
322 if(i!=j)
323 Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link)
323 Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link)
324 end
324 end
325 end
325 end
326
326
327 private
327 private
328
328
329 def putfonts()
329 def putfonts()
330 nf=@n
330 nf=@n
331 @diffs.each do |diff|
331 @diffs.each do |diff|
332 #Encodings
332 #Encodings
333 newobj()
333 newobj()
334 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')
334 out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['+diff+']>>')
335 out('endobj')
335 out('endobj')
336 end
336 end
337 # mqr=get_magic_quotes_runtime()
337 # mqr=get_magic_quotes_runtime()
338 # set_magic_quotes_runtime(0)
338 # set_magic_quotes_runtime(0)
339 @FontFiles.each_pair do |file, info|
339 @FontFiles.each_pair do |file, info|
340 #Font file embedding
340 #Font file embedding
341 newobj()
341 newobj()
342 @FontFiles[file]['n']=@n
342 @FontFiles[file]['n']=@n
343 if(defined('FPDF_FONTPATH'))
343 if(defined('FPDF_FONTPATH'))
344 file=FPDF_FONTPATH+file
344 file=FPDF_FONTPATH+file
345 end
345 end
346 size=filesize(file)
346 size=filesize(file)
347 if(!size)
347 if(!size)
348 Error('Font file not found')
348 Error('Font file not found')
349 end
349 end
350 out('<</Length '+size)
350 out('<</Length '+size)
351 if(file[-2]=='.z')
351 if(file[-2]=='.z')
352 out('/Filter /FlateDecode')
352 out('/Filter /FlateDecode')
353 end
353 end
354 out('/Length1 '+info['length1'])
354 out('/Length1 '+info['length1'])
355 unless info['length2'].nil?
355 unless info['length2'].nil?
356 out('/Length2 '+info['length2']+' /Length3 0')
356 out('/Length2 '+info['length2']+' /Length3 0')
357 end
357 end
358 out('>>')
358 out('>>')
359 f=fopen(file,'rb')
359 f=fopen(file,'rb')
360 putstream(fread(f,size))
360 putstream(fread(f,size))
361 fclose(f)
361 fclose(f)
362 out('endobj')
362 out('endobj')
363 end
363 end
364 #
364 #
365 # set_magic_quotes_runtime(mqr)
365 # set_magic_quotes_runtime(mqr)
366 #
366 #
367 @fonts.each_pair do |k, font|
367 @fonts.each_pair do |k, font|
368 #Font objects
368 #Font objects
369 newobj()
369 newobj()
370 @fonts[k]['n']=@n
370 @fonts[k]['n']=@n
371 out('<</Type /Font')
371 out('<</Type /Font')
372 if(font['type']=='Type0')
372 if(font['type']=='Type0')
373 putType0(font)
373 putType0(font)
374 else
374 else
375 name=font['name']
375 name=font['name']
376 out('/BaseFont /'+name)
376 out('/BaseFont /'+name)
377 if(font['type']=='core')
377 if(font['type']=='core')
378 #Standard font
378 #Standard font
379 out('/Subtype /Type1')
379 out('/Subtype /Type1')
380 if(name!='Symbol' and name!='ZapfDingbats')
380 if(name!='Symbol' and name!='ZapfDingbats')
381 out('/Encoding /WinAnsiEncoding')
381 out('/Encoding /WinAnsiEncoding')
382 end
382 end
383 else
383 else
384 #Additional font
384 #Additional font
385 out('/Subtype /'+font['type'])
385 out('/Subtype /'+font['type'])
386 out('/FirstChar 32')
386 out('/FirstChar 32')
387 out('/LastChar 255')
387 out('/LastChar 255')
388 out('/Widths '+(@n+1)+' 0 R')
388 out('/Widths '+(@n+1)+' 0 R')
389 out('/FontDescriptor '+(@n+2)+' 0 R')
389 out('/FontDescriptor '+(@n+2)+' 0 R')
390 if(font['enc'])
390 if(font['enc'])
391 if !font['diff'].nil?
391 if !font['diff'].nil?
392 out('/Encoding '+(nf+font['diff'])+' 0 R')
392 out('/Encoding '+(nf+font['diff'])+' 0 R')
393 else
393 else
394 out('/Encoding /WinAnsiEncoding')
394 out('/Encoding /WinAnsiEncoding')
395 end
395 end
396 end
396 end
397 end
397 end
398 out('>>')
398 out('>>')
399 out('endobj')
399 out('endobj')
400 if(font['type']!='core')
400 if(font['type']!='core')
401 #Widths
401 #Widths
402 newobj()
402 newobj()
403 cw=font['cw']
403 cw=font['cw']
404 s='['
404 s='['
405 32.upto(255) do |i|
405 32.upto(255) do |i|
406 s+=cw[i.chr]+' '
406 s+=cw[i.chr]+' '
407 end
407 end
408 out(s+']')
408 out(s+']')
409 out('endobj')
409 out('endobj')
410 #Descriptor
410 #Descriptor
411 newobj()
411 newobj()
412 s='<</Type /FontDescriptor /FontName /'+name
412 s='<</Type /FontDescriptor /FontName /'+name
413 font['desc'].each_pair do |k, v|
413 font['desc'].each_pair do |k, v|
414 s+=' /'+k+' '+v
414 s+=' /'+k+' '+v
415 end
415 end
416 file=font['file']
416 file=font['file']
417 if(file)
417 if(file)
418 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@FontFiles[file]['n']+' 0 R'
418 s+=' /FontFile'+(font['type']=='Type1' ? '' : '2')+' '+@FontFiles[file]['n']+' 0 R'
419 end
419 end
420 out(s+'>>')
420 out(s+'>>')
421 out('endobj')
421 out('endobj')
422 end
422 end
423 end
423 end
424 end
424 end
425 end
425 end
426
426
427 def putType0(font)
427 def putType0(font)
428 #Type0
428 #Type0
429 out('/Subtype /Type0')
429 out('/Subtype /Type0')
430 out('/BaseFont /'+font['name']+'-'+font['CMap'])
430 out('/BaseFont /'+font['name']+'-'+font['CMap'])
431 out('/Encoding /'+font['CMap'])
431 out('/Encoding /'+font['CMap'])
432 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
432 out('/DescendantFonts ['+(@n+1).to_s+' 0 R]')
433 out('>>')
433 out('>>')
434 out('endobj')
434 out('endobj')
435 #CIDFont
435 #CIDFont
436 newobj()
436 newobj()
437 out('<</Type /Font')
437 out('<</Type /Font')
438 out('/Subtype /CIDFontType0')
438 out('/Subtype /CIDFontType0')
439 out('/BaseFont /'+font['name'])
439 out('/BaseFont /'+font['name'])
440 out('/CIDSystemInfo <</Registry '+textstring('Adobe')+' /Ordering '+textstring(font['registry']['ordering'])+' /Supplement '+font['registry']['supplement'].to_s+'>>')
440 out('/CIDSystemInfo <</Registry '+textstring('Adobe')+' /Ordering '+textstring(font['registry']['ordering'])+' /Supplement '+font['registry']['supplement'].to_s+'>>')
441 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
441 out('/FontDescriptor '+(@n+1).to_s+' 0 R')
442 if(font['CMap']=='ETen-B5-H')
442 if(font['CMap']=='ETen-B5-H')
443 w='13648 13742 500'
443 w='13648 13742 500'
444 elsif(font['CMap']=='GBK-EUC-H')
444 elsif(font['CMap']=='GBK-EUC-H')
445 w='814 907 500 7716 [500]'
445 w='814 907 500 7716 [500]'
446 else
446 else
447 # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s
447 # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s
448 # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s
448 # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s
449 w='1 ['
449 w='1 ['
450 font['cw'].keys.sort.each {|key|
450 font['cw'].keys.sort.each {|key|
451 w+=font['cw'][key].to_s + " "
451 w+=font['cw'][key].to_s + " "
452 # ActionController::Base::logger.debug key.to_s
452 # ActionController::Base::logger.debug key.to_s
453 # ActionController::Base::logger.debug font['cw'][key].to_s
453 # ActionController::Base::logger.debug font['cw'][key].to_s
454 }
454 }
455 w +=']'
455 w +=']'
456 end
456 end
457 out('/W ['+w+']>>')
457 out('/W ['+w+']>>')
458 out('endobj')
458 out('endobj')
459 #Font descriptor
459 #Font descriptor
460 newobj()
460 newobj()
461 out('<</Type /FontDescriptor')
461 out('<</Type /FontDescriptor')
462 out('/FontName /'+font['name'])
462 out('/FontName /'+font['name'])
463 out('/Flags 6')
463 out('/Flags 6')
464 out('/FontBBox [0 -200 1000 900]')
464 out('/FontBBox [0 -200 1000 900]')
465 out('/ItalicAngle 0')
465 out('/ItalicAngle 0')
466 out('/Ascent 800')
466 out('/Ascent 800')
467 out('/Descent -200')
467 out('/Descent -200')
468 out('/CapHeight 800')
468 out('/CapHeight 800')
469 out('/StemV 50')
469 out('/StemV 50')
470 out('>>')
470 out('>>')
471 out('endobj')
471 out('endobj')
472 end
472 end
473 end
473 end
General Comments 0
You need to be logged in to leave comments. Login now