From 96f83cc8f0f032554f771a59da22303cd473b878 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Tue, 5 Dec 2006 20:45:04 +0000 Subject: trunk moved from /trunk/redmine to /trunk git-svn-id: http://redmine.rubyforge.org/svn/trunk@67 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/gloc-1.1.0/CHANGELOG | 19 + vendor/plugins/gloc-1.1.0/MIT-LICENSE | 19 + vendor/plugins/gloc-1.1.0/README | 208 +++ vendor/plugins/gloc-1.1.0/Rakefile | 15 + .../ActionController/Filters/ClassMethods.html | 230 +++ .../gloc-1.1.0/doc/classes/ActionMailer/Base.html | 140 ++ .../gloc-1.1.0/doc/classes/ActionView/Base.html | 174 ++ .../doc/classes/ActionView/Helpers/DateHelper.html | 348 ++++ .../classes/ActionView/Helpers/InstanceTag.html | 167 ++ .../doc/classes/ActiveRecord/Errors.html | 215 +++ .../ActiveRecord/Validations/ClassMethods.html | 217 +++ vendor/plugins/gloc-1.1.0/doc/classes/GLoc.html | 774 +++++++++ .../gloc-1.1.0/doc/classes/GLoc/ClassMethods.html | 160 ++ .../gloc-1.1.0/doc/classes/GLoc/Helpers.html | 323 ++++ .../doc/classes/GLoc/InstanceMethods.html | 364 ++++ vendor/plugins/gloc-1.1.0/doc/created.rid | 1 + vendor/plugins/gloc-1.1.0/doc/files/CHANGELOG.html | 153 ++ vendor/plugins/gloc-1.1.0/doc/files/README.html | 480 ++++++ .../gloc-1.1.0/doc/files/lib/gloc-helpers_rb.html | 107 ++ .../gloc-1.1.0/doc/files/lib/gloc-internal_rb.html | 115 ++ .../doc/files/lib/gloc-rails-text_rb.html | 114 ++ .../gloc-1.1.0/doc/files/lib/gloc-rails_rb.html | 114 ++ .../gloc-1.1.0/doc/files/lib/gloc-ruby_rb.html | 107 ++ .../gloc-1.1.0/doc/files/lib/gloc-version_rb.html | 101 ++ .../plugins/gloc-1.1.0/doc/files/lib/gloc_rb.html | 116 ++ vendor/plugins/gloc-1.1.0/doc/fr_class_index.html | 37 + vendor/plugins/gloc-1.1.0/doc/fr_file_index.html | 35 + vendor/plugins/gloc-1.1.0/doc/fr_method_index.html | 72 + vendor/plugins/gloc-1.1.0/doc/index.html | 24 + vendor/plugins/gloc-1.1.0/doc/rdoc-style.css | 208 +++ vendor/plugins/gloc-1.1.0/init.rb | 11 + vendor/plugins/gloc-1.1.0/lib/gloc-config.rb | 16 + vendor/plugins/gloc-1.1.0/lib/gloc-dev.rb | 97 ++ vendor/plugins/gloc-1.1.0/lib/gloc-helpers.rb | 20 + vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb | 134 ++ vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb | 137 ++ vendor/plugins/gloc-1.1.0/lib/gloc-rails.rb | 230 +++ vendor/plugins/gloc-1.1.0/lib/gloc-ruby.rb | 7 + vendor/plugins/gloc-1.1.0/lib/gloc-version.rb | 12 + vendor/plugins/gloc-1.1.0/lib/gloc.rb | 294 ++++ vendor/plugins/gloc-1.1.0/tasks/gloc.rake | 30 + vendor/plugins/gloc-1.1.0/test/gloc_rails_test.rb | 118 ++ vendor/plugins/gloc-1.1.0/test/gloc_test.rb | 433 +++++ vendor/plugins/gloc-1.1.0/test/lang/en.yaml | 2 + vendor/plugins/gloc-1.1.0/test/lang/en_AU.yaml | 2 + vendor/plugins/gloc-1.1.0/test/lang/ja.yml | 2 + vendor/plugins/gloc-1.1.0/test/lang2/en.yml | 2 + vendor/plugins/gloc-1.1.0/test/lang2/ja.yaml | 2 + .../gloc-1.1.0/test/lib/rails-string_ext.rb | 23 + .../plugins/gloc-1.1.0/test/lib/rails-time_ext.rb | 76 + vendor/plugins/rfpdf/CHANGELOG | 13 + vendor/plugins/rfpdf/MIT-LICENSE | 20 + vendor/plugins/rfpdf/README | 99 ++ vendor/plugins/rfpdf/init.rb | 3 + vendor/plugins/rfpdf/lib/rfpdf.rb | 31 + vendor/plugins/rfpdf/lib/rfpdf/bookmark.rb | 99 ++ vendor/plugins/rfpdf/lib/rfpdf/chinese.rb | 473 ++++++ vendor/plugins/rfpdf/lib/rfpdf/errors.rb | 4 + vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb | 1550 +++++++++++++++++ vendor/plugins/rfpdf/lib/rfpdf/fpdf_eps.rb | 139 ++ vendor/plugins/rfpdf/lib/rfpdf/japanese.rb | 468 +++++ vendor/plugins/rfpdf/lib/rfpdf/korean.rb | 436 +++++ vendor/plugins/rfpdf/lib/rfpdf/makefont.rb | 1787 ++++++++++++++++++++ vendor/plugins/rfpdf/lib/rfpdf/rfpdf.rb | 346 ++++ vendor/plugins/rfpdf/lib/rfpdf/view.rb | 75 + vendor/plugins/rfpdf/test/test_helper.rb | 1 + 66 files changed, 12349 insertions(+) create mode 100644 vendor/plugins/gloc-1.1.0/CHANGELOG create mode 100644 vendor/plugins/gloc-1.1.0/MIT-LICENSE create mode 100644 vendor/plugins/gloc-1.1.0/README create mode 100644 vendor/plugins/gloc-1.1.0/Rakefile create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActionController/Filters/ClassMethods.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActionMailer/Base.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Base.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/DateHelper.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/InstanceTag.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Errors.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Validations/ClassMethods.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/GLoc.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/GLoc/ClassMethods.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/GLoc/Helpers.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/classes/GLoc/InstanceMethods.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/created.rid create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/CHANGELOG.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/README.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-helpers_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-internal_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails-text_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-ruby_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-version_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/files/lib/gloc_rb.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/fr_class_index.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/fr_file_index.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/fr_method_index.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/index.html create mode 100644 vendor/plugins/gloc-1.1.0/doc/rdoc-style.css create mode 100644 vendor/plugins/gloc-1.1.0/init.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-config.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-dev.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-helpers.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-rails.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-ruby.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc-version.rb create mode 100644 vendor/plugins/gloc-1.1.0/lib/gloc.rb create mode 100644 vendor/plugins/gloc-1.1.0/tasks/gloc.rake create mode 100644 vendor/plugins/gloc-1.1.0/test/gloc_rails_test.rb create mode 100644 vendor/plugins/gloc-1.1.0/test/gloc_test.rb create mode 100644 vendor/plugins/gloc-1.1.0/test/lang/en.yaml create mode 100644 vendor/plugins/gloc-1.1.0/test/lang/en_AU.yaml create mode 100644 vendor/plugins/gloc-1.1.0/test/lang/ja.yml create mode 100644 vendor/plugins/gloc-1.1.0/test/lang2/en.yml create mode 100644 vendor/plugins/gloc-1.1.0/test/lang2/ja.yaml create mode 100644 vendor/plugins/gloc-1.1.0/test/lib/rails-string_ext.rb create mode 100644 vendor/plugins/gloc-1.1.0/test/lib/rails-time_ext.rb create mode 100644 vendor/plugins/rfpdf/CHANGELOG create mode 100644 vendor/plugins/rfpdf/MIT-LICENSE create mode 100644 vendor/plugins/rfpdf/README create mode 100644 vendor/plugins/rfpdf/init.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/bookmark.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/chinese.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/errors.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/fpdf_eps.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/japanese.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/korean.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/makefont.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/rfpdf.rb create mode 100644 vendor/plugins/rfpdf/lib/rfpdf/view.rb create mode 100644 vendor/plugins/rfpdf/test/test_helper.rb (limited to 'vendor') diff --git a/vendor/plugins/gloc-1.1.0/CHANGELOG b/vendor/plugins/gloc-1.1.0/CHANGELOG new file mode 100644 index 000000000..6392d7cbe --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/CHANGELOG @@ -0,0 +1,19 @@ +== Version 1.1 (28 May 2006) + +* The charset for each and/or all languages can now be easily configured. +* Added a ActionController filter that auto-detects the client language. +* The rake task "sort" now merges lines that match 100%, and warns if duplicate keys are found. +* Rule support. Create flexible rules to handle issues such as pluralization. +* Massive speed and stability improvements to development mode. +* Added Russian strings. (Thanks to Evgeny Lineytsev) +* Complete RDoc documentation. +* Improved helpers. +* GLoc now configurable via get_config and set_config +* Added an option to tell GLoc to output various verbose information. +* More useful functions such as set_language_if_valid, similar_language +* GLoc's entire internal state can now be backed up and restored. + + +== Version 1.0 (17 April 2006) + +* Initial public release. diff --git a/vendor/plugins/gloc-1.1.0/MIT-LICENSE b/vendor/plugins/gloc-1.1.0/MIT-LICENSE new file mode 100644 index 000000000..081774a65 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/MIT-LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2005-2006 David Barri + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/README b/vendor/plugins/gloc-1.1.0/README new file mode 100644 index 000000000..66f8e5e9f --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/README @@ -0,0 +1,208 @@ += About + +=== Preface +I originally started designing this on weekends and after work in 2005. We started to become very interested in Rails at work and I wanted to get some experience with ruby with before we started using it full-time. I didn't have very many ideas for anything interesting to create so, because we write a lot of multilingual webapps at my company, I decided to write a localization library. That way if my little hobby project developed into something decent, I could at least put it to good use. +And here we are in 2006, my little hobby project has come a long way and become quite a useful piece of software. Not only do I use it in production sites I write at work, but I also prefer it to other existing alternatives. Therefore I have decided to make it publicly available, and I hope that other developers will find it useful too. + +=== About +GLoc is a localization library. It doesn't aim to do everything l10n-related that you can imagine, but what it does, it does very well. It was originally designed as a Rails plugin, but can also be used for plain ruby projects. Here are a list of its main features: +* Lightweight and efficient. +* Uses file-based string bundles. Strings can also be set directly. +* Intelligent, cascading language configuration. +* Create flexible rules to handle issues such as pluralization. +* Includes a ActionController filter that auto-detects the client language. +* Works perfectly with Rails Engines and allows strings to be overridden just as easily as controllers, models, etc. +* Automatically localizes Rails functions such as distance_in_minutes, select_month etc +* Supports different charsets. You can even specify the encoding to use for each language seperately. +* Special Rails mods/helpers. + +=== What does GLoc mean? +If you're wondering about the name "GLoc", I'm sure you're not alone. +This project was originally just called "Localization" which was a bit too common, so when I decided to release it I decided to call it "Golly's Localization Library" instead (Golly is my nickname), and that was long and boring so I then abbreviated that to "GLoc". What a fun story!! + +=== Localization helpers +This also includes a few helpers for common situations such as displaying localized date, time, "yes" or "no", etc. + +=== Rails Localization +At the moment, unless you manually remove the require 'gloc-rails-text' line from init.rb, this plugin overrides certain Rails functions to provide multilingual versions. This automatically localizes functions such as select_date(), distance_of_time_in_words() and more... +The strings can be found in lang/*.yml. +NOTE: This is not complete. Timezones and countries are not currently localized. + + + + += Usage + +=== Quickstart + +Windows users will need to first install iconv. http://wiki.rubyonrails.com/rails/pages/iconv + +* Create a dir "#{RAILS_ROOT}/lang" +* Create a file "#{RAILS_ROOT}/lang/en.yml" and write your strings. The format is "key: string". Save it as UTF-8. If you save it in a different encoding, add a key called file_charset (eg. "file_charset: iso-2022-jp") +* Put the following in config/environment.rb and change the values as you see fit. The following example is for an app that uses English and Japanese, with Japanese being the default. + GLoc.set_config :default_language => :ja + GLoc.clear_strings_except :en, :ja + GLoc.set_kcode + GLoc.load_localized_strings +* Add 'include GLoc' to all classes that will use localization. This is added to most Rails classes automatically. +* Optionally, you can set the language for models and controllers by simply inserting set_language :en in classes and/or methods. +* To use localized strings, replace text such as "Welcome" with l(:welcome_string_key), and "Hello #{name}." with l(:hello_string_key, name). (Of course the strings will need to exist in your string bundle.) + +There is more functionality provided by this plugin, that is not demonstrated above. Please read the API summary for details. + +=== API summary + +The following methods are added as both class methods and instance methods to modules/classes that include GLoc. They are also available as class methods of GLoc. + current_language # Returns the current language + l(symbol, *arguments) # Returns a localized string + ll(lang, symbol, *arguments) # Returns a localized string in a specific language + ltry(possible_key) # Returns a localized string if passed a Symbol, else returns the same argument passed + lwr(symbol, *arguments) # Uses the default rule to return a localized string. + lwr_(rule, symbol, *arguments) # Uses a specified rule to return a localized string. + l_has_string?(symbol) # Checks if a localized string exists + set_language(language) # Sets the language for the current class or class instance + set_language_if_valid(lang) # Sets the current language if the language passed is a valid language + +The GLoc module also defines the following class methods: + add_localized_strings(lang, symbol_hash, override=true) # Adds a hash of localized strings + backup_state(clear=false) # Creates a backup of GLoc's internal state and optionally clears everything too + clear_strings(*languages) # Removes localized strings from memory + clear_strings_except(*languages) # Removes localized strings from memory except for those of certain specified languages + get_charset(lang) # Returns the charset used to store localized strings in memory + get_config(key) # Returns a GLoc configuration value (see below) + load_localized_strings(dir=nil, override=true) # Loads localized strings from all YML files in a given directory + restore_state(state) # Restores a backup of GLoc's internal state + set_charset(new_charset, *langs) # Sets the charset used to internally store localized strings + set_config(hash) # Sets GLoc configuration values (see below) + set_kcode(charset=nil) # Sets the $KCODE global variable + similar_language(language) # Tries to find a valid language that is similar to the argument passed + valid_languages # Returns an array of (currently) valid languages (ie. languages for which localized data exists) + valid_language?(language) # Checks whether any localized strings are in memory for a given language + +GLoc uses the following configuration items. They can be accessed via get_config and set_config. + :default_cookie_name + :default_language + :default_param_name + :raise_string_not_found_errors + :verbose + +The GLoc module is automatically included in the following classes: + ActionController::Base + ActionMailer::Base + ActionView::Base + ActionView::Helpers::InstanceTag + ActiveRecord::Base + ActiveRecord::Errors + ApplicationHelper + Test::Unit::TestCase + +The GLoc module also defines the following controller filters: + autodetect_language_filter + +GLoc also makes the following change to Rails: +* Views for ActionMailer are now #{view_name}_#{language}.rb rather than just #{view_name}.rb +* All ActiveRecord validation class methods now accept a localized string key (symbol) as a :message value. +* ActiveRecord::Errors.add now accepts symbols as valid message values. At runtime these symbols are converted to localized strings using the current_language of the base record. +* ActiveRecord::Errors.add now accepts arrays as arguments so that printf-style strings can be generated at runtime. This also applies to the validates_* class methods. + Eg. validates_xxxxxx_of :name, :message => ['Your name must be at least %d characters.', MIN_LEN] + Eg. validates_xxxxxx_of :name, :message => [:user_error_validation_name_too_short, MIN_LEN] +* Instances of ActiveView inherit their current_language from the controller (or mailer) creating them. + +This plugin also adds the following rake tasks: + * gloc:sort - Sorts the keys in the lang ymls (also accepts a DIR argument) + +=== Cascading language configuration + +The language can be set at three levels: + 1. The default # GLoc.get_config :default_language + 2. Class level # class A; set_language :de; end + 3. Instance level # b= B.new; b.set_language :zh + +Instance level has the highest priority and the default has the lowest. + +Because GLoc is included at class level too, it becomes easy to associate languages with contexts. +For example: + class Student + set_language :en + def say_hello + puts "We say #{l :hello} but our teachers say #{Teacher.l :hello}" + end + end + +=== Rules + +There are often situations when depending on the value of one or more variables, the surrounding text +changes. The most common case of this is pluralization. Rather than hardcode these rules, they are +completely definable by the user so that the user can eaasily accomodate for more complicated grammatical +rules such as those found in Russian and Polish (or so I hear). To define a rule, simply include a string +in the string bundle whose key begins with "_gloc_rule_" and then write ruby code as the value. The ruby +code will be converted to a Proc when the string bundle is first read, and should return a prefix that will +be appended to the string key at runtime to point to a new string. Make sense? Probably not... Please look +at the following example and I am sure it will all make sense. + +Simple example (string bundle / en.yml) + _gloc_rule_default: ' |n| n==1 ? "_single" : "_plural" ' + man_count_plural: There are %d men. + man_count_single: There is 1 man. + +Simple example (code) + lwr(:man_count, 1) # => There is 1 man. + lwr(:man_count, 8) # => There are 8 men. + +To use rules other than the default simply call lwr_ instead of lwr, and specify the rule. + +Example #2 (string bundle / en.yml) + _gloc_rule_default: ' |n| n==1 ? "_single" : "_plural" ' + _gloc_rule_custom: ' |n| return "_none" if n==0; return "_heaps" if n>100; n==1 ? "_single" : "_plural" ' + man_count_none: There are no men. + man_count_heaps: There are heaps of men!! + man_count_plural: There are %d men. + man_count_single: There is 1 man. + +Example #2 (code) + lwr_(:custom, :man_count, 0) # => There are no men. + lwr_(:custom, :man_count, 1) # => There is 1 man. + lwr_(:custom, :man_count, 8) # => There are 8 men. + lwr_(:custom, :man_count, 150) # => There are heaps of men!! + + +=== Helpers + +GLoc includes the following helpers: + l_age(age) # Returns a localized version of an age. eg "3 years old" + l_date(date) # Returns a date in a localized format + l_datetime(date) # Returns a date+time in a localized format + l_datetime_short(date) # Returns a date+time in a localized short format. + l_lang_name(l,dl=nil) # Returns the name of a language (you must supply your own strings) + l_strftime(date,fmt) # Formats a date/time in a localized format. + l_time(date) # Returns a time in a localized format + l_YesNo(value) # Returns localized string of "Yes" or "No" depending on the arg + l_yesno(value) # Returns localized string of "yes" or "no" depending on the arg + +=== Rails localization + +Not all of Rails is covered but the following functions are: + distance_of_time_in_words + select_day + select_month + select_year + add_options + + + + += FAQ + +==== How do I use it in engines? +Simply put this in your init_engine.rb + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') +That way your engines strings will be loaded when the engine is started. Just simply make sure that you load your application strings after you start your engines to safely override any engine strings. + +==== Why am I getting an Iconv::IllegalSequence error when calling GLoc.set_charset? +By default GLoc loads all of its default strings at startup. For example, calling set_charset 'iso-2022-jp' will cause this error because Russian strings are loaded by default, and the Russian strings use characters that cannot be expressed in the ISO-2022-JP charset. +Before calling set_charset you should call clear_strings_except to remove strings from any languages that you will not be using. +Alternatively, you can simply specify the language(s) as follows, set_charset 'iso-2022-jp', :ja. + +==== How do I make GLoc ignore StringNotFoundErrors? +Disable it as follows: + GLoc.set_config :raise_string_not_found_errors => false diff --git a/vendor/plugins/gloc-1.1.0/Rakefile b/vendor/plugins/gloc-1.1.0/Rakefile new file mode 100644 index 000000000..a5b8fe762 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/Rakefile @@ -0,0 +1,15 @@ +Dir.glob("#{File.dirname(__FILE__)}/tasks/*.rake").each {|f| load f} + +task :default => 'gloc:sort' + +# RDoc task +require 'rake/rdoctask' +Rake::RDocTask.new() { |rdoc| + rdoc.rdoc_dir = 'doc' + rdoc.title = "GLoc Localization Library Documentation" + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README', 'CHANGELOG') + rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.exclude('lib/gloc-dev.rb') + rdoc.rdoc_files.exclude('lib/gloc-config.rb') +} diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActionController/Filters/ClassMethods.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActionController/Filters/ClassMethods.html new file mode 100644 index 000000000..fba33b5b5 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActionController/Filters/ClassMethods.html @@ -0,0 +1,230 @@ + + + + + + Module: ActionController::Filters::ClassMethods + + + + + + + + + + +
+ + + + + + + + + + +
ModuleActionController::Filters::ClassMethods
In: + + lib/gloc-rails.rb + +
+
+
+ + +
+ + + +
+ + + +
+ +
+

Methods

+ + +
+ +
+ + + + +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+This filter attempts to auto-detect the clients desired language. It first +checks the params, then a cookie and then the HTTP_ACCEPT_LANGUAGE request +header. If a language is found to match or be similar to a currently valid +language, then it sets the current_language of the controller. +

+
+  class ExampleController < ApplicationController
+    set_language :en
+    autodetect_language_filter :except => 'monkey', :on_no_lang => :lang_not_autodetected_callback
+    autodetect_language_filter :only => 'monkey', :check_cookie => 'monkey_lang', :check_accept_header => false
+    ...
+    def lang_not_autodetected_callback
+      redirect_to somewhere
+    end
+  end
+
+

+The args for this filter are exactly the same the arguments of +before_filter with the following exceptions: +

+
    +
  • :check_params — If false, then params will not be checked +for a language. If a String, then this will value will be used as the name +of the param. + +
  • +
  • :check_cookie — If false, then the cookie will not be +checked for a language. If a String, then this will value will be used as +the name of the cookie. + +
  • +
  • :check_accept_header — If false, then HTTP_ACCEPT_LANGUAGE +will not be checked for a language. + +
  • +
  • :on_set_lang — You can specify the name of a callback +function to be called when the language is successfully detected and set. +The param must be a Symbol or a String which is the name of the function. +The callback function must accept one argument (the language) and must be +instance level. + +
  • +
  • :on_no_lang — You can specify the name of a callback +function to be called when the language couldn’t be detected +automatically. The param must be a Symbol or a String which is the name of +the function. The callback function must be instance level. + +
  • +
+

+You override the default names of the param or cookie by calling GLoc.set_config :default_param_name +=> ‘new_param_name‘ and GLoc.set_config :default_cookie_name +=> ‘new_cookie_name‘. +

+

[Source]

+
+
+    # File lib/gloc-rails.rb, line 43
+43:       def autodetect_language_filter(*args)
+44:         options= args.last.is_a?(Hash) ? args.last : {}
+45:         x= 'Proc.new { |c| l= nil;'
+46:         # :check_params
+47:         unless (v= options.delete(:check_params)) == false
+48:           name= v ? ":#{v}" : 'GLoc.get_config(:default_param_name)'
+49:           x << "l ||= GLoc.similar_language(c.params[#{name}]);"
+50:         end
+51:         # :check_cookie
+52:         unless (v= options.delete(:check_cookie)) == false
+53:           name= v ? ":#{v}" : 'GLoc.get_config(:default_cookie_name)'
+54:           x << "l ||= GLoc.similar_language(c.send(:cookies)[#{name}]);"
+55:         end
+56:         # :check_accept_header
+57:         unless options.delete(:check_accept_header) == false
+58:           x << %<
+59:               unless l
+60:                 a= c.request.env['HTTP_ACCEPT_LANGUAGE'].split(/,|;/) rescue nil
+61:                 a.each {|x| l ||= GLoc.similar_language(x)} if a
+62:               end; >
+63:         end
+64:         # Set language
+65:         x << 'ret= true;'
+66:         x << 'if l; c.set_language(l); c.headers[\'Content-Language\']= l.to_s; '
+67:         if options.has_key?(:on_set_lang)
+68:           x << "ret= c.#{options.delete(:on_set_lang)}(l);"
+69:         end
+70:         if options.has_key?(:on_no_lang)
+71:           x << "else; ret= c.#{options.delete(:on_no_lang)};"
+72:         end
+73:         x << 'end; ret }'
+74:         
+75:         # Create filter
+76:         block= eval x
+77:         before_filter(*args, &block)
+78:       end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActionMailer/Base.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActionMailer/Base.html new file mode 100644 index 000000000..056b23d85 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActionMailer/Base.html @@ -0,0 +1,140 @@ + + + + + + Class: ActionMailer::Base + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassActionMailer::Base
In: + + lib/gloc-rails.rb + +
+
Parent: + Object +
+
+ + +
+ + + +
+ +
+

+In addition to including GLoc, +render_message is also overridden so that mail templates contain +the current language at the end of the file. Eg. deliver_hello +will render hello_en.rhtml. +

+ +
+ + +
+ + +
+ + + +
+

Included Modules

+ +
+ GLoc +
+
+ +
+ + + +
+

External Aliases

+ +
+ + + + + + +
render_message->render_message_without_gloc
+
+
+ + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Base.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Base.html new file mode 100644 index 000000000..00767055d --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Base.html @@ -0,0 +1,174 @@ + + + + + + Class: ActionView::Base + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassActionView::Base
In: + + lib/gloc-rails.rb + +
+
Parent: + Object +
+
+ + +
+ + + +
+ +
+

+initialize is overridden so that new instances of this class +inherit the current language of the controller. +

+ +
+ + +
+ +
+

Methods

+ +
+ new   +
+
+ +
+ + + +
+

Included Modules

+ +
+ GLoc +
+
+ +
+ + + +
+

External Aliases

+ +
+ + + + + + +
initialize->initialize_without_gloc
+
+
+ + + + + + +
+

Public Class methods

+ +
+ + + + +
+

[Source]

+
+
+     # File lib/gloc-rails.rb, line 109
+109:     def initialize(base_path = nil, assigns_for_first_render = {}, controller = nil)
+110:       initialize_without_gloc(base_path, assigns_for_first_render, controller)
+111:       set_language controller.current_language unless controller.nil?
+112:     end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/DateHelper.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/DateHelper.html new file mode 100644 index 000000000..84ca8fae3 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/DateHelper.html @@ -0,0 +1,348 @@ + + + + + + Module: ActionView::Helpers::DateHelper + + + + + + + + + + +
+ + + + + + + + + + +
ModuleActionView::Helpers::DateHelper
In: + + lib/gloc-rails-text.rb + +
+
+
+ + +
+ + + +
+ + + +
+ +
+

Methods

+ + +
+ +
+ + + + +
+ + +
+

Constants

+ +
+ + + + + + + + + + + + + + + + +
LOCALIZED_HELPERS=true
LOCALIZED_MONTHNAMES={}
LOCALIZED_ABBR_MONTHNAMES={}
+
+
+ + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+This method uses current_language to return a localized string. +

+

[Source]

+
+
+    # File lib/gloc-rails-text.rb, line 16
+16:       def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
+17:         from_time = from_time.to_time if from_time.respond_to?(:to_time)
+18:         to_time = to_time.to_time if to_time.respond_to?(:to_time)
+19:         distance_in_minutes = (((to_time - from_time).abs)/60).round
+20:         distance_in_seconds = ((to_time - from_time).abs).round
+21: 
+22:         case distance_in_minutes
+23:           when 0..1
+24:             return (distance_in_minutes==0) ? l(:actionview_datehelper_time_in_words_minute_less_than) : l(:actionview_datehelper_time_in_words_minute_single) unless include_seconds
+25:             case distance_in_seconds
+26:               when 0..5   then lwr(:actionview_datehelper_time_in_words_second_less_than, 5)
+27:               when 6..10  then lwr(:actionview_datehelper_time_in_words_second_less_than, 10)
+28:               when 11..20 then lwr(:actionview_datehelper_time_in_words_second_less_than, 20)
+29:               when 21..40 then l(:actionview_datehelper_time_in_words_minute_half)
+30:               when 41..59 then l(:actionview_datehelper_time_in_words_minute_less_than)
+31:               else             l(:actionview_datehelper_time_in_words_minute)
+32:             end
+33:                                 
+34:           when 2..45      then lwr(:actionview_datehelper_time_in_words_minute, distance_in_minutes)
+35:           when 46..90     then l(:actionview_datehelper_time_in_words_hour_about_single)
+36:           when 90..1440   then lwr(:actionview_datehelper_time_in_words_hour_about, (distance_in_minutes.to_f / 60.0).round)
+37:           when 1441..2880 then lwr(:actionview_datehelper_time_in_words_day, 1)
+38:           else                 lwr(:actionview_datehelper_time_in_words_day, (distance_in_minutes / 1440).round)
+39:         end
+40:       end
+
+
+
+
+ +
+ + + + +
+

+This method has been modified so that a localized string can be appended to +the day numbers. +

+

[Source]

+
+
+    # File lib/gloc-rails-text.rb, line 43
+43:       def select_day(date, options = {})
+44:         day_options = []
+45:         prefix = l :actionview_datehelper_select_day_prefix
+46: 
+47:         1.upto(31) do |day|
+48:           day_options << ((date && (date.kind_of?(Fixnum) ? date : date.day) == day) ?
+49:             %(<option value="#{day}" selected="selected">#{day}#{prefix}</option>\n) :
+50:             %(<option value="#{day}">#{day}#{prefix}</option>\n)
+51:           )
+52:         end
+53: 
+54:         select_html(options[:field_name] || 'day', day_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled])
+55:       end
+
+
+
+
+ +
+ + + + +
+

+This method has been modified so that +

+
    +
  • the month names are localized. + +
  • +
  • it uses options: :min_date, :max_date, +:start_month, :end_month + +
  • +
  • a localized string can be appended to the month numbers when the +:use_month_numbers option is specified. + +
  • +
+

[Source]

+
+
+    # File lib/gloc-rails-text.rb, line 61
+61:       def select_month(date, options = {})
+62:         unless LOCALIZED_MONTHNAMES.has_key?(current_language)
+63:           LOCALIZED_MONTHNAMES[current_language] = [''] + l(:actionview_datehelper_select_month_names).split(',')
+64:           LOCALIZED_ABBR_MONTHNAMES[current_language] = [''] + l(:actionview_datehelper_select_month_names_abbr).split(',')
+65:         end
+66:         
+67:         month_options = []
+68:         month_names = options[:use_short_month] ? LOCALIZED_ABBR_MONTHNAMES[current_language] : LOCALIZED_MONTHNAMES[current_language]
+69:         
+70:         if options.has_key?(:min_date) && options.has_key?(:max_date)
+71:           if options[:min_date].year == options[:max_date].year
+72:             start_month, end_month = options[:min_date].month, options[:max_date].month
+73:           end
+74:         end
+75:         start_month = (options[:start_month] || 1) unless start_month
+76:         end_month = (options[:end_month] || 12) unless end_month
+77:         prefix = l :actionview_datehelper_select_month_prefix
+78: 
+79:         start_month.upto(end_month) do |month_number|
+80:           month_name = if options[:use_month_numbers]
+81:             "#{month_number}#{prefix}"
+82:           elsif options[:add_month_numbers]
+83:             month_number.to_s + ' - ' + month_names[month_number]
+84:           else
+85:             month_names[month_number]
+86:           end
+87: 
+88:           month_options << ((date && (date.kind_of?(Fixnum) ? date : date.month) == month_number) ?
+89:             %(<option value="#{month_number}" selected="selected">#{month_name}</option>\n) :
+90:             %(<option value="#{month_number}">#{month_name}</option>\n)
+91:           )
+92:         end
+93: 
+94:         select_html(options[:field_name] || 'month', month_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled])
+95:       end
+
+
+
+
+ +
+ + + + +
+

+This method has been modified so that +

+
    +
  • it uses options: :min_date, :max_date + +
  • +
  • a localized string can be appended to the years numbers. + +
  • +
+

[Source]

+
+
+     # File lib/gloc-rails-text.rb, line 100
+100:       def select_year(date, options = {})
+101:         year_options = []
+102:         y = date ? (date.kind_of?(Fixnum) ? (y = (date == 0) ? Date.today.year : date) : date.year) : Date.today.year
+103: 
+104:         start_year = options.has_key?(:min_date) ? options[:min_date].year : (options[:start_year] || y-5)
+105:         end_year = options.has_key?(:max_date) ? options[:max_date].year : (options[:end_year] || y+5)
+106:         step_val = start_year < end_year ? 1 : -1
+107:         prefix = l :actionview_datehelper_select_year_prefix
+108: 
+109:         start_year.step(end_year, step_val) do |year|
+110:           year_options << ((date && (date.kind_of?(Fixnum) ? date : date.year) == year) ?
+111:             %(<option value="#{year}" selected="selected">#{year}#{prefix}</option>\n) :
+112:             %(<option value="#{year}">#{year}#{prefix}</option>\n)
+113:           )
+114:         end
+115: 
+116:         select_html(options[:field_name] || 'year', year_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled])
+117:       end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/InstanceTag.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/InstanceTag.html new file mode 100644 index 000000000..a236e0e5d --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActionView/Helpers/InstanceTag.html @@ -0,0 +1,167 @@ + + + + + + Class: ActionView::Helpers::InstanceTag + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassActionView::Helpers::InstanceTag
In: + + lib/gloc-rails-text.rb + +
+ + lib/gloc-rails.rb + +
+
Parent: + Object +
+
+ + +
+ + + +
+ +
+

+The private method add_options is overridden so that "Please +select" is localized. +

+ +
+ + +
+ +
+

Methods

+ + +
+ +
+ + + +
+

Included Modules

+ +
+ GLoc +
+
+ +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+Inherits the current language from the template object. +

+

[Source]

+
+
+     # File lib/gloc-rails.rb, line 119
+119:       def current_language
+120:         @template_object.current_language
+121:       end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Errors.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Errors.html new file mode 100644 index 000000000..9a16f608b --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Errors.html @@ -0,0 +1,215 @@ + + + + + + Class: ActiveRecord::Errors + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassActiveRecord::Errors
In: + + lib/gloc-rails.rb + +
+
Parent: + Object +
+
+ + +
+ + + +
+ + + +
+ +
+

Methods

+ +
+ add   + current_language   +
+
+ +
+ + + +
+

Included Modules

+ +
+ GLoc +
+
+ +
+ + + +
+

External Aliases

+ +
+ + + + + + +
add->add_without_gloc
+
+
+ + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+The GLoc version of this method provides two +extra features +

+
    +
  • If msg is a string, it will be considered a GLoc string key. + +
  • +
  • If msg is an array, the first element will be considered the +string and the remaining elements will be considered arguments for the +string. Eg. [‘Hi %s.’,’John’] + +
  • +
+

[Source]

+
+
+     # File lib/gloc-rails.rb, line 141
+141:     def add(attribute, msg= @@default_error_messages[:invalid])
+142:       if msg.is_a?(Array)
+143:         args= msg.clone
+144:         msg= args.shift
+145:         args= nil if args.empty?
+146:       end
+147:       msg= ltry(msg)
+148:       msg= msg % args unless args.nil?
+149:       add_without_gloc(attribute, msg)
+150:     end
+
+
+
+
+ +
+ + + + +
+

+Inherits the current language from the base record. +

+

[Source]

+
+
+     # File lib/gloc-rails.rb, line 152
+152:     def current_language
+153:       @base.current_language
+154:     end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Validations/ClassMethods.html b/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Validations/ClassMethods.html new file mode 100644 index 000000000..145a74c2b --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/ActiveRecord/Validations/ClassMethods.html @@ -0,0 +1,217 @@ + + + + + + Module: ActiveRecord::Validations::ClassMethods + + + + + + + + + + +
+ + + + + + + + + + +
ModuleActiveRecord::Validations::ClassMethods
In: + + lib/gloc-rails.rb + +
+
+
+ + +
+ + + +
+ + + +
+ +
+

Methods

+ + +
+ +
+ + + + +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+The default Rails version of this function creates an error message and +then passes it to ActiveRecord.Errors. The GLoc version of this method, sends an array to +ActiveRecord.Errors that will be turned into a +string by ActiveRecord.Errors which in turn +allows for the message of this validation function to be a GLoc string key. +

+

[Source]

+
+
+     # File lib/gloc-rails.rb, line 164
+164:       def validates_length_of(*attrs)
+165:         # Merge given options with defaults.
+166:         options = {
+167:           :too_long     => ActiveRecord::Errors.default_error_messages[:too_long],
+168:           :too_short    => ActiveRecord::Errors.default_error_messages[:too_short],
+169:           :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length]
+170:         }.merge(DEFAULT_VALIDATION_OPTIONS)
+171:         options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash)
+172: 
+173:         # Ensure that one and only one range option is specified.
+174:         range_options = ALL_RANGE_OPTIONS & options.keys
+175:         case range_options.size
+176:           when 0
+177:             raise ArgumentError, 'Range unspecified.  Specify the :within, :maximum, :minimum, or :is option.'
+178:           when 1
+179:             # Valid number of options; do nothing.
+180:           else
+181:             raise ArgumentError, 'Too many range options specified.  Choose only one.'
+182:         end
+183: 
+184:         # Get range option and value.
+185:         option = range_options.first
+186:         option_value = options[range_options.first]
+187: 
+188:         case option
+189:         when :within, :in
+190:           raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
+191: 
+192:           too_short = [options[:too_short] , option_value.begin]
+193:           too_long  = [options[:too_long]  , option_value.end  ]
+194: 
+195:           validates_each(attrs, options) do |record, attr, value|
+196:             if value.nil? or value.split(//).size < option_value.begin
+197:               record.errors.add(attr, too_short)
+198:             elsif value.split(//).size > option_value.end
+199:               record.errors.add(attr, too_long)
+200:             end
+201:           end
+202:         when :is, :minimum, :maximum
+203:           raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0
+204: 
+205:           # Declare different validations per option.
+206:           validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
+207:           message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
+208: 
+209:           message = [(options[:message] || options[message_options[option]]) , option_value]
+210: 
+211:           validates_each(attrs, options) do |record, attr, value|
+212:             if value.kind_of?(String)
+213:               record.errors.add(attr, message) unless !value.nil? and value.split(//).size.method(validity_checks[option])[option_value]
+214:             else
+215:               record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value]
+216:             end
+217:           end
+218:         end
+219:       end
+
+
+
+
+ +
+ + +
+ validates_size_of(*attrs) +
+ +
+

+Alias for validates_length_of +

+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/GLoc.html b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc.html new file mode 100644 index 000000000..8a25c7de8 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc.html @@ -0,0 +1,774 @@ + + + + + + Module: GLoc + + + + + + + + + + +
+ + + + + + + + + + +
ModuleGLoc
In: + + lib/gloc-helpers.rb + +
+ + lib/gloc-internal.rb + +
+ + lib/gloc-version.rb + +
+ + lib/gloc.rb + +
+
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ + +
+ + + +
+ + + +
+

Included Modules

+ + +
+ +
+ +
+

Classes and Modules

+ + Module GLoc::ClassMethods
+Module GLoc::Helpers
+Module GLoc::InstanceMethods
+ +
+ +
+

Constants

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LOCALIZED_STRINGS={}
RULES={}
LOWERCASE_LANGUAGES={}
UTF_8='utf-8'
SHIFT_JIS='sjis'
EUC_JP='euc-jp'
+
+
+ +
+

External Aliases

+ +
+ + + + + + +
clear_strings->_clear_strings
+
+
+ + + + + + +
+

Public Class methods

+ +
+ + + + +
+

+Adds a collection of localized strings to the in-memory string store. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 113
+113:     def add_localized_strings(lang, symbol_hash, override=true, strings_charset=nil)
+114:       _verbose_msg {"Adding #{symbol_hash.size} #{lang} strings."}
+115:       _add_localized_strings(lang, symbol_hash, override, strings_charset)
+116:       _verbose_msg :stats
+117:     end
+
+
+
+
+ +
+ + + + +
+

+Creates a backup of the internal state of GLoc (ie. +strings, langs, rules, config) and optionally clears everything. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 121
+121:     def backup_state(clear=false)
+122:       s= _get_internal_state_vars.map{|o| o.clone}
+123:       _get_internal_state_vars.each{|o| o.clear} if clear
+124:       s
+125:     end
+
+
+
+
+ +
+ + + + +
+

+Removes all localized strings from memory, either of a certain language (or +languages), or entirely. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 129
+129:     def clear_strings(*languages)
+130:       if languages.empty?
+131:         _verbose_msg {"Clearing all strings"}
+132:         LOCALIZED_STRINGS.clear
+133:         LOWERCASE_LANGUAGES.clear
+134:       else
+135:         languages.each {|l|
+136:           _verbose_msg {"Clearing :#{l} strings"}
+137:           l= l.to_sym
+138:           LOCALIZED_STRINGS.delete l
+139:           LOWERCASE_LANGUAGES.each_pair {|k,v| LOWERCASE_LANGUAGES.delete k if v == l}
+140:         }
+141:       end
+142:     end
+
+
+
+
+ +
+ + + + +
+

+Removes all localized strings from memory, except for those of certain +specified languages. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 146
+146:     def clear_strings_except(*languages)
+147:       clear= (LOCALIZED_STRINGS.keys - languages)
+148:       _clear_strings(*clear) unless clear.empty?
+149:     end
+
+
+
+
+ +
+ + + + +
+

+Returns the default language +

+

[Source]

+
+
+     # File lib/gloc.rb, line 108
+108:     def current_language
+109:       GLoc::CONFIG[:default_language]
+110:     end
+
+
+
+
+ +
+ + + + +
+

+Returns the charset used to store localized strings in memory. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 152
+152:     def get_charset(lang)
+153:       CONFIG[:internal_charset_per_lang][lang] || CONFIG[:internal_charset]
+154:     end
+
+
+
+
+ +
+ + + + +
+

+Returns a GLoc configuration value. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 157
+157:     def get_config(key)
+158:       CONFIG[key]
+159:     end
+
+
+
+
+ +
+ + + + +
+

+Loads the localized strings that are included in the GLoc library. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 162
+162:     def load_gloc_default_localized_strings(override=false)
+163:       GLoc.load_localized_strings "#{File.dirname(__FILE__)}/../lang", override
+164:     end
+
+
+
+
+ +
+ + + + +
+

+Loads localized strings from all yml files in the specifed directory. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 167
+167:     def load_localized_strings(dir=nil, override=true)
+168:       _charset_required
+169:       _get_lang_file_list(dir).each {|filename|
+170:         
+171:         # Load file
+172:         raw_hash = YAML::load(File.read(filename))
+173:         raw_hash={} unless raw_hash.kind_of?(Hash)
+174:         filename =~ /([^\/\\]+)\.ya?ml$/
+175:         lang = $1.to_sym
+176:         file_charset = raw_hash['file_charset'] || UTF_8
+177:   
+178:         # Convert string keys to symbols
+179:         dest_charset= get_charset(lang)
+180:         _verbose_msg {"Reading file #{filename} [charset: #{file_charset} --> #{dest_charset}]"}
+181:         symbol_hash = {}
+182:         Iconv.open(dest_charset, file_charset) do |i|
+183:           raw_hash.each {|key, value|
+184:             symbol_hash[key.to_sym] = i.iconv(value)
+185:           }
+186:         end
+187:   
+188:         # Add strings to repos
+189:         _add_localized_strings(lang, symbol_hash, override)
+190:       }
+191:       _verbose_msg :stats
+192:     end
+
+
+
+
+ +
+ + + + +
+

+Restores a backup of GLoc’s internal state +that was made with backup_state. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 195
+195:     def restore_state(state)
+196:       _get_internal_state_vars.each do |o|
+197:         o.clear
+198:         o.send o.respond_to?(:merge!) ? :merge! : :concat, state.shift
+199:       end
+200:     end
+
+
+
+
+ +
+ + + + +
+

+Sets the charset used to internally store localized strings. You can set +the charset to use for a specific language or languages, or if none are +specified the charset for ALL localized strings will be set. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 205
+205:     def set_charset(new_charset, *langs)
+206:       CONFIG[:internal_charset_per_lang] ||= {}
+207:       
+208:       # Convert symbol shortcuts
+209:       if new_charset.is_a?(Symbol)
+210:         new_charset= case new_charset
+211:           when :utf8, :utf_8 then UTF_8
+212:           when :sjis, :shift_jis, :shiftjis then SHIFT_JIS
+213:           when :eucjp, :euc_jp then EUC_JP
+214:           else new_charset.to_s
+215:           end
+216:       end
+217:       
+218:       # Convert existing strings
+219:       (langs.empty? ? LOCALIZED_STRINGS.keys : langs).each do |lang|
+220:         cur_charset= get_charset(lang)
+221:         if cur_charset && new_charset != cur_charset
+222:           _verbose_msg {"Converting :#{lang} strings from #{cur_charset} to #{new_charset}"}
+223:           Iconv.open(new_charset, cur_charset) do |i|
+224:             bundle= LOCALIZED_STRINGS[lang]
+225:             bundle.each_pair {|k,v| bundle[k]= i.iconv(v)}
+226:           end
+227:         end
+228:       end
+229:       
+230:       # Set new charset value
+231:       if langs.empty?
+232:         _verbose_msg {"Setting GLoc charset for all languages to #{new_charset}"}
+233:         CONFIG[:internal_charset]= new_charset
+234:         CONFIG[:internal_charset_per_lang].clear
+235:       else
+236:         langs.each do |lang|
+237:           _verbose_msg {"Setting GLoc charset for :#{lang} strings to #{new_charset}"}
+238:           CONFIG[:internal_charset_per_lang][lang]= new_charset
+239:         end
+240:       end
+241:     end
+
+
+
+
+ +
+ + + + +
+

+Sets GLoc configuration values. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 244
+244:     def set_config(hash)
+245:       CONFIG.merge! hash
+246:     end
+
+
+
+
+ +
+ + + + +
+

+Sets the $KCODE global variable according to a specified charset, or else +the current default charset for the default language. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 250
+250:     def set_kcode(charset=nil)
+251:       _charset_required
+252:       charset ||= get_charset(current_language)
+253:       $KCODE= case charset
+254:         when UTF_8 then 'u'
+255:         when SHIFT_JIS then 's'
+256:         when EUC_JP then 'e'
+257:         else 'n'
+258:         end
+259:       _verbose_msg {"$KCODE set to #{$KCODE}"}
+260:     end
+
+
+
+
+ +
+ + + + +
+

+Tries to find a valid language that is similar to the argument passed. Eg. +:en, :en_au, :EN_US are all similar languages. Returns nil if no +similar languages are found. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 265
+265:     def similar_language(lang)
+266:       return nil if lang.nil?
+267:       return lang.to_sym if valid_language?(lang)
+268:       # Check lowercase without dashes
+269:       lang= lang.to_s.downcase.gsub('-','_')
+270:       return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang)
+271:       # Check without dialect
+272:       if lang.to_s =~ /^([a-z]+?)[^a-z].*/
+273:         lang= $1
+274:         return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang)
+275:       end
+276:       # Check other dialects
+277:       lang= "#{lang}_"
+278:       LOWERCASE_LANGUAGES.keys.each {|k| return LOWERCASE_LANGUAGES[k] if k.starts_with?(lang)}
+279:       # Nothing found
+280:       nil
+281:     end
+
+
+
+
+ +
+ + + + +
+

+Returns true if there are any localized strings for a specified +language. Note that although set_langauge nil is perfectly valid, +nil is not a valid language. +

+

[Source]

+
+
+     # File lib/gloc.rb, line 290
+290:     def valid_language?(language)
+291:       LOCALIZED_STRINGS.has_key? language.to_sym rescue false
+292:     end
+
+
+
+
+ +
+ + + + +
+

+Returns an array of (currently) valid languages (ie. languages for which +localized data exists). +

+

[Source]

+
+
+     # File lib/gloc.rb, line 284
+284:     def valid_languages
+285:       LOCALIZED_STRINGS.keys
+286:     end
+
+
+
+
+ +

Public Instance methods

+ +
+ + + + +
+

+Returns the instance-level current language, or if not set, returns the +class-level current language. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 77
+77:   def current_language
+78:     @gloc_language || self.class.current_language
+79:   end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/ClassMethods.html b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/ClassMethods.html new file mode 100644 index 000000000..ba1a28ad0 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/ClassMethods.html @@ -0,0 +1,160 @@ + + + + + + Module: GLoc::ClassMethods + + + + + + + + + + +
+ + + + + + + + + + +
ModuleGLoc::ClassMethods
In: + + lib/gloc.rb + +
+
+
+ + +
+ + + +
+ +
+

+All classes/modules that include GLoc will also +gain these class methods. Notice that the GLoc::InstanceMethods module is also +included. +

+ +
+ + +
+ +
+

Methods

+ + +
+ +
+ + + +
+

Included Modules

+ + +
+ +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+Returns the current language, or if not set, returns the GLoc current language. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 89
+89:     def current_language
+90:       @gloc_language || GLoc.current_language
+91:     end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/Helpers.html b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/Helpers.html new file mode 100644 index 000000000..f3fdf63e1 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/Helpers.html @@ -0,0 +1,323 @@ + + + + + + Module: GLoc::Helpers + + + + + + + + + + +
+ + + + + + + + + + +
ModuleGLoc::Helpers
In: + + lib/gloc-helpers.rb + +
+
+
+ + +
+ + + +
+ +
+

+These helper methods will be included in the InstanceMethods module. +

+ +
+ + +
+ +
+

Methods

+ +
+ l_YesNo   + l_age   + l_date   + l_datetime   + l_datetime_short   + l_lang_name   + l_strftime   + l_time   + l_yesno   +
+
+ +
+ + + + +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

[Source]

+
+
+    # File lib/gloc-helpers.rb, line 12
+12:     def l_YesNo(value)         l(value ? :general_text_Yes : :general_text_No) end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+   # File lib/gloc-helpers.rb, line 6
+6:     def l_age(age)             lwr :general_fmt_age, age end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+   # File lib/gloc-helpers.rb, line 7
+7:     def l_date(date)           l_strftime date, :general_fmt_date end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+   # File lib/gloc-helpers.rb, line 8
+8:     def l_datetime(date)       l_strftime date, :general_fmt_datetime end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+   # File lib/gloc-helpers.rb, line 9
+9:     def l_datetime_short(date) l_strftime date, :general_fmt_datetime_short end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # File lib/gloc-helpers.rb, line 15
+15:     def l_lang_name(lang, display_lang=nil)
+16:       ll display_lang || current_language, "general_lang_#{lang}"
+17:     end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # File lib/gloc-helpers.rb, line 10
+10:     def l_strftime(date,fmt)   date.strftime l(fmt) end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # File lib/gloc-helpers.rb, line 11
+11:     def l_time(time)           l_strftime time, :general_fmt_time end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # File lib/gloc-helpers.rb, line 13
+13:     def l_yesno(value)         l(value ? :general_text_yes : :general_text_no) end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/InstanceMethods.html b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/InstanceMethods.html new file mode 100644 index 000000000..4e15c9383 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/classes/GLoc/InstanceMethods.html @@ -0,0 +1,364 @@ + + + + + + Module: GLoc::InstanceMethods + + + + + + + + + + +
+ + + + + + + + + + +
ModuleGLoc::InstanceMethods
In: + + lib/gloc.rb + +
+
+
+ + +
+ + + +
+ +
+

+This module will be included in both instances and classes of GLoc includees. It is also included as class +methods in the GLoc module itself. +

+ +
+ + +
+ +
+

Methods

+ +
+ l   + l_has_string?   + ll   + ltry   + lwr   + lwr_   + set_language   + set_language_if_valid   +
+
+ +
+ + + +
+

Included Modules

+ +
+ Helpers +
+
+ +
+ + + + + + + + + +
+

Public Instance methods

+ +
+ + + + +
+

+Returns a localized string. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 18
+18:     def l(symbol, *arguments)
+19:       return GLoc._l(symbol,current_language,*arguments)
+20:     end
+
+
+
+
+ +
+ + + + +
+

+Returns true if a localized string with the specified key exists. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 48
+48:     def l_has_string?(symbol)
+49:       return GLoc._l_has_string?(symbol,current_language)
+50:     end
+
+
+
+
+ +
+ + + + +
+

+Returns a localized string in a specified language. This does not effect +current_language. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 24
+24:     def ll(lang, symbol, *arguments)
+25:       return GLoc._l(symbol,lang.to_sym,*arguments)
+26:     end
+
+
+
+
+ +
+ + + + +
+

+Returns a localized string if the argument is a Symbol, else just returns +the argument. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 29
+29:     def ltry(possible_key)
+30:       possible_key.is_a?(Symbol) ? l(possible_key) : possible_key
+31:     end
+
+
+
+
+ +
+ + + + +
+

+Uses the default GLoc rule to return a localized +string. See lwr_() for more info. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 35
+35:     def lwr(symbol, *arguments)
+36:       lwr_(:default, symbol, *arguments)
+37:     end
+
+
+
+
+ +
+ + + + +
+

+Uses a rule to return a localized string. A rule is a function +that uses specified arguments to return a localization key prefix. The +prefix is appended to the localization key originally specified, to create +a new key which is then used to lookup a localized string. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 43
+43:     def lwr_(rule, symbol, *arguments)
+44:       GLoc._l("#{symbol}#{GLoc::_l_rule(rule,current_language).call(*arguments)}",current_language,*arguments)
+45:     end
+
+
+
+
+ +
+ + + + +
+

+Sets the current language for this instance/class. Setting the language of +a class effects all instances unless the instance has its own language +defined. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 54
+54:     def set_language(language)
+55:       @gloc_language= language.nil? ? nil : language.to_sym
+56:     end
+
+
+
+
+ +
+ + + + +
+

+Sets the current language if the language passed is a valid language. If +the language was valid, this method returns true else it will +return false. Note that nil is not a valid language. See +set_language(language) for more +info. +

+

[Source]

+
+
+    # File lib/gloc.rb, line 62
+62:     def set_language_if_valid(language)
+63:       if GLoc.valid_language?(language)
+64:         set_language(language)
+65:         true
+66:       else
+67:         false
+68:       end
+69:     end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/created.rid b/vendor/plugins/gloc-1.1.0/doc/created.rid new file mode 100644 index 000000000..eba9efa29 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/created.rid @@ -0,0 +1 @@ +Sun May 28 15:21:13 E. Australia Standard Time 2006 diff --git a/vendor/plugins/gloc-1.1.0/doc/files/CHANGELOG.html b/vendor/plugins/gloc-1.1.0/doc/files/CHANGELOG.html new file mode 100644 index 000000000..aec36c5bf --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/CHANGELOG.html @@ -0,0 +1,153 @@ + + + + + + File: CHANGELOG + + + + + + + + + + +
+

CHANGELOG

+ + + + + + + + + +
Path:CHANGELOG +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

Version 1.1 (28 May 2006)

+
    +
  • The charset for each and/or all languages can now be easily configured. + +
  • +
  • Added a ActionController filter that auto-detects the client language. + +
  • +
  • The rake task "sort" now merges lines that match 100%, and warns +if duplicate keys are found. + +
  • +
  • Rule support. Create flexible rules to handle issues such as pluralization. + +
  • +
  • Massive speed and stability improvements to development mode. + +
  • +
  • Added Russian strings. (Thanks to Evgeny Lineytsev) + +
  • +
  • Complete RDoc documentation. + +
  • +
  • Improved helpers. + +
  • +
  • GLoc now configurable via get_config and +set_config + +
  • +
  • Added an option to tell GLoc to output +various verbose information. + +
  • +
  • More useful functions such as set_language_if_valid, similar_language + +
  • +
  • GLoc’s entire internal state can +now be backed up and restored. + +
  • +
+

Version 1.0 (17 April 2006)

+
    +
  • Initial public release. + +
  • +
+ +
+ + +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/README.html b/vendor/plugins/gloc-1.1.0/doc/files/README.html new file mode 100644 index 000000000..d078659d2 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/README.html @@ -0,0 +1,480 @@ + + + + + + File: README + + + + + + + + + + +
+

README

+ + + + + + + + + +
Path:README +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

About

+

Preface

+

+I originally started designing this on weekends and after work in 2005. We +started to become very interested in Rails at work and I wanted to get some +experience with ruby with before we started using it full-time. I +didn’t have very many ideas for anything interesting to create so, +because we write a lot of multilingual webapps at my company, I decided to +write a localization library. That way if my little hobby project developed +into something decent, I could at least put it to good use. And here we are +in 2006, my little hobby project has come a long way and become quite a +useful piece of software. Not only do I use it in production sites I write +at work, but I also prefer it to other existing alternatives. Therefore I +have decided to make it publicly available, and I hope that other +developers will find it useful too. +

+

About

+

+GLoc is a localization library. It +doesn’t aim to do everything l10n-related that you can imagine, but +what it does, it does very well. It was originally designed as a Rails +plugin, but can also be used for plain ruby projects. Here are a list of +its main features: +

+
    +
  • Lightweight and efficient. + +
  • +
  • Uses file-based string bundles. Strings can also be set directly. + +
  • +
  • Intelligent, cascading language configuration. + +
  • +
  • Create flexible rules to handle issues such as pluralization. + +
  • +
  • Includes a ActionController filter that auto-detects the client language. + +
  • +
  • Works perfectly with Rails Engines and allows strings to be overridden just +as easily as controllers, models, etc. + +
  • +
  • Automatically localizes Rails functions such as distance_in_minutes, +select_month etc + +
  • +
  • Supports different charsets. You can even specify the encoding to use for +each language seperately. + +
  • +
  • Special Rails mods/helpers. + +
  • +
+

What does GLoc mean?

+

+If you’re wondering about the name "GLoc", I’m sure you’re not +alone. This project was originally just called "Localization" +which was a bit too common, so when I decided to release it I decided to +call it "Golly’s Localization Library" instead (Golly is my +nickname), and that was long and boring so I then abbreviated that to +"GLoc". What a fun story!! +

+

Localization helpers

+

+This also includes a few helpers for common situations such as displaying +localized date, time, "yes" or "no", etc. +

+

Rails Localization

+

+At the moment, unless you manually remove the require +‘gloc-rails-text’ line from init.rb, this plugin overrides +certain Rails functions to provide multilingual versions. This +automatically localizes functions such as select_date(), +distance_of_time_in_words() and more… The strings can be found in +lang/*.yml. NOTE: This is not complete. Timezones and countries are not +currently localized. +

+

Usage

+

Quickstart

+

+Windows users will need to first install iconv. wiki.rubyonrails.com/rails/pages/iconv +

+
    +
  • Create a dir "#{RAILS_ROOT}/lang" + +
  • +
  • Create a file "#{RAILS_ROOT}/lang/en.yml" and write your strings. +The format is "key: string". Save it as UTF-8. If you save it in +a different encoding, add a key called file_charset (eg. +"file_charset: iso-2022-jp") + +
  • +
  • Put the following in config/environment.rb and change the values as you see +fit. The following example is for an app that uses English and Japanese, +with Japanese being the default. + +
    +  GLoc.set_config :default_language => :ja
    +  GLoc.clear_strings_except :en, :ja
    +  GLoc.set_kcode
    +  GLoc.load_localized_strings
    +
    +
  • +
  • Add ‘include GLoc’ to all +classes that will use localization. This is added to most Rails classes +automatically. + +
  • +
  • Optionally, you can set the language for models and controllers by simply +inserting set_language :en in classes and/or methods. + +
  • +
  • To use localized strings, replace text such as "Welcome" +with l(:welcome_string_key), and "Hello +#{name}." with l(:hello_string_key, name). (Of course +the strings will need to exist in your string bundle.) + +
  • +
+

+There is more functionality provided by this plugin, that is not +demonstrated above. Please read the API summary for details. +

+

API summary

+

+The following methods are added as both class methods and instance methods +to modules/classes that include GLoc. +They are also available as class methods of GLoc. +

+
+  current_language               # Returns the current language
+  l(symbol, *arguments)          # Returns a localized string
+  ll(lang, symbol, *arguments)   # Returns a localized string in a specific language
+  ltry(possible_key)             # Returns a localized string if passed a Symbol, else returns the same argument passed
+  lwr(symbol, *arguments)        # Uses the default rule to return a localized string.
+  lwr_(rule, symbol, *arguments) # Uses a specified rule to return a localized string.
+  l_has_string?(symbol)          # Checks if a localized string exists
+  set_language(language)         # Sets the language for the current class or class instance
+  set_language_if_valid(lang)    # Sets the current language if the language passed is a valid language
+
+

+The GLoc module also defines the +following class methods: +

+
+  add_localized_strings(lang, symbol_hash, override=true) # Adds a hash of localized strings
+  backup_state(clear=false)                               # Creates a backup of GLoc's internal state and optionally clears everything too
+  clear_strings(*languages)                               # Removes localized strings from memory
+  clear_strings_except(*languages)                        # Removes localized strings from memory except for those of certain specified languages
+  get_charset(lang)                                       # Returns the charset used to store localized strings in memory
+  get_config(key)                                         # Returns a GLoc configuration value (see below)
+  load_localized_strings(dir=nil, override=true)          # Loads localized strings from all YML files in a given directory
+  restore_state(state)                                    # Restores a backup of GLoc's internal state
+  set_charset(new_charset, *langs)                        # Sets the charset used to internally store localized strings
+  set_config(hash)                                        # Sets GLoc configuration values (see below)
+  set_kcode(charset=nil)                                  # Sets the $KCODE global variable
+  similar_language(language)                              # Tries to find a valid language that is similar to the argument passed
+  valid_languages                                         # Returns an array of (currently) valid languages (ie. languages for which localized data exists)
+  valid_language?(language)                               # Checks whether any localized strings are in memory for a given language
+
+

+GLoc uses the following configuration +items. They can be accessed via get_config and +set_config. +

+
+  :default_cookie_name
+  :default_language
+  :default_param_name
+  :raise_string_not_found_errors
+  :verbose
+
+

+The GLoc module is automatically +included in the following classes: +

+
+  ActionController::Base
+  ActionMailer::Base
+  ActionView::Base
+  ActionView::Helpers::InstanceTag
+  ActiveRecord::Base
+  ActiveRecord::Errors
+  ApplicationHelper
+  Test::Unit::TestCase
+
+

+The GLoc module also defines the +following controller filters: +

+
+  autodetect_language_filter
+
+

+GLoc also makes the following change to +Rails: +

+
    +
  • Views for ActionMailer are now #{view_name}_#{language}.rb rather than just +#{view_name}.rb + +
  • +
  • All ActiveRecord validation class methods now accept a localized string key +(symbol) as a :message value. + +
  • +
  • ActiveRecord::Errors.add +now accepts symbols as valid message values. At runtime these symbols are +converted to localized strings using the current_language of the base +record. + +
  • +
  • ActiveRecord::Errors.add +now accepts arrays as arguments so that printf-style strings can be +generated at runtime. This also applies to the validates_* class methods. + +
    +  Eg. validates_xxxxxx_of :name, :message => ['Your name must be at least %d characters.', MIN_LEN]
    +  Eg. validates_xxxxxx_of :name, :message => [:user_error_validation_name_too_short, MIN_LEN]
    +
    +
  • +
  • Instances of ActiveView inherit their current_language from the controller +(or mailer) creating them. + +
  • +
+

+This plugin also adds the following rake tasks: +

+
+  * gloc:sort - Sorts the keys in the lang ymls (also accepts a DIR argument)
+
+

Cascading language configuration

+

+The language can be set at three levels: +

+
+  1. The default     # GLoc.get_config :default_language
+  2. Class level     # class A; set_language :de; end
+  3. Instance level  # b= B.new; b.set_language :zh
+
+

+Instance level has the highest priority and the default has the lowest. +

+

+Because GLoc is included at class level +too, it becomes easy to associate languages with contexts. For example: +

+
+  class Student
+    set_language :en
+    def say_hello
+      puts "We say #{l :hello} but our teachers say #{Teacher.l :hello}"
+    end
+  end
+
+

Rules

+

+There are often situations when depending on the value of one or more +variables, the surrounding text changes. The most common case of this is +pluralization. Rather than hardcode these rules, they are completely +definable by the user so that the user can eaasily accomodate for more +complicated grammatical rules such as those found in Russian and Polish (or +so I hear). To define a rule, simply include a string in the string bundle +whose key begins with "gloc_rule" and then write ruby +code as the value. The ruby code will be converted to a Proc when the +string bundle is first read, and should return a prefix that will be +appended to the string key at runtime to point to a new string. Make sense? +Probably not… Please look at the following example and I am sure it +will all make sense. +

+

+Simple example (string bundle / en.yml) +

+
+  _gloc_rule_default: ' |n| n==1 ? "_single" : "_plural" '
+  man_count_plural: There are %d men.
+  man_count_single: There is 1 man.
+
+

+Simple example (code) +

+
+  lwr(:man_count, 1)  # => There is 1 man.
+  lwr(:man_count, 8)  # => There are 8 men.
+
+

+To use rules other than the default simply call lwr_ instead of lwr, and +specify the rule. +

+

+Example 2 (string bundle / en.yml) +

+
+  _gloc_rule_default: ' |n| n==1 ? "_single" : "_plural" '
+  _gloc_rule_custom: ' |n| return "_none" if n==0; return "_heaps" if n>100; n==1 ? "_single" : "_plural" '
+  man_count_none: There are no men.
+  man_count_heaps: There are heaps of men!!
+  man_count_plural: There are %d men.
+  man_count_single: There is 1 man.
+
+

+Example 2 (code) +

+
+  lwr_(:custom, :man_count, 0)    # => There are no men.
+  lwr_(:custom, :man_count, 1)    # => There is 1 man.
+  lwr_(:custom, :man_count, 8)    # => There are 8 men.
+  lwr_(:custom, :man_count, 150)  # => There are heaps of men!!
+
+

Helpers

+

+GLoc includes the following helpers: +

+
+  l_age(age)             # Returns a localized version of an age. eg "3 years old"
+  l_date(date)           # Returns a date in a localized format
+  l_datetime(date)       # Returns a date+time in a localized format
+  l_datetime_short(date) # Returns a date+time in a localized short format.
+  l_lang_name(l,dl=nil)  # Returns the name of a language (you must supply your own strings)
+  l_strftime(date,fmt)   # Formats a date/time in a localized format.
+  l_time(date)           # Returns a time in a localized format
+  l_YesNo(value)         # Returns localized string of "Yes" or "No" depending on the arg
+  l_yesno(value)         # Returns localized string of "yes" or "no" depending on the arg
+
+

Rails localization

+

+Not all of Rails is covered but the following functions are: +

+
+  distance_of_time_in_words
+  select_day
+  select_month
+  select_year
+  add_options
+
+

FAQ

+

How do I use it in engines?

+

+Simply put this in your init_engine.rb +

+
+  GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang')
+
+

+That way your engines strings will be loaded when the engine is started. +Just simply make sure that you load your application strings after you +start your engines to safely override any engine strings. +

+

Why am I getting an Iconv::IllegalSequence error when calling GLoc.set_charset?

+

+By default GLoc loads all of its default +strings at startup. For example, calling set_charset +‘iso-2022-jp’ will cause this error because Russian +strings are loaded by default, and the Russian strings use characters that +cannot be expressed in the ISO-2022-JP charset. Before calling +set_charset you should call clear_strings_except to +remove strings from any languages that you will not be using. +Alternatively, you can simply specify the language(s) as follows, +set_charset ‘iso-2022-jp’, :ja. +

+

How do I make GLoc ignore StringNotFoundErrors?

+

+Disable it as follows: +

+
+  GLoc.set_config :raise_string_not_found_errors => false
+
+ +
+ + +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-helpers_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-helpers_rb.html new file mode 100644 index 000000000..394b79d70 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-helpers_rb.html @@ -0,0 +1,107 @@ + + + + + + File: gloc-helpers.rb + + + + + + + + + + +
+

gloc-helpers.rb

+ + + + + + + + + +
Path:lib/gloc-helpers.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ + +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-internal_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-internal_rb.html new file mode 100644 index 000000000..6d09fec7b --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-internal_rb.html @@ -0,0 +1,115 @@ + + + + + + File: gloc-internal.rb + + + + + + + + + + +
+

gloc-internal.rb

+ + + + + + + + + +
Path:lib/gloc-internal.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ +
+

Required files

+ +
+ iconv   + gloc-version   +
+
+ +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails-text_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails-text_rb.html new file mode 100644 index 000000000..52a387218 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails-text_rb.html @@ -0,0 +1,114 @@ + + + + + + File: gloc-rails-text.rb + + + + + + + + + + +
+

gloc-rails-text.rb

+ + + + + + + + + +
Path:lib/gloc-rails-text.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ +
+

Required files

+ +
+ date   +
+
+ +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails_rb.html new file mode 100644 index 000000000..3ae73b87b --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-rails_rb.html @@ -0,0 +1,114 @@ + + + + + + File: gloc-rails.rb + + + + + + + + + + +
+

gloc-rails.rb

+ + + + + + + + + +
Path:lib/gloc-rails.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ +
+

Required files

+ +
+ gloc   +
+
+ +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-ruby_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-ruby_rb.html new file mode 100644 index 000000000..4b29e9d94 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-ruby_rb.html @@ -0,0 +1,107 @@ + + + + + + File: gloc-ruby.rb + + + + + + + + + + +
+

gloc-ruby.rb

+ + + + + + + + + +
Path:lib/gloc-ruby.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ + +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-version_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-version_rb.html new file mode 100644 index 000000000..17f93aa43 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc-version_rb.html @@ -0,0 +1,101 @@ + + + + + + File: gloc-version.rb + + + + + + + + + + +
+

gloc-version.rb

+ + + + + + + + + +
Path:lib/gloc-version.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ + + +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc_rb.html b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc_rb.html new file mode 100644 index 000000000..9e68a89cd --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/files/lib/gloc_rb.html @@ -0,0 +1,116 @@ + + + + + + File: gloc.rb + + + + + + + + + + +
+

gloc.rb

+ + + + + + + + + +
Path:lib/gloc.rb +
Last Update:Sun May 28 15:19:38 E. Australia Standard Time 2006
+
+ + +
+ + + +
+ +
+

+Copyright © 2005-2006 David Barri +

+ +
+ +
+

Required files

+ +
+ yaml   + gloc-internal   + gloc-helpers   +
+
+ +
+ + +
+ + + + +
+ + + + + + + + + + + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/fr_class_index.html b/vendor/plugins/gloc-1.1.0/doc/fr_class_index.html new file mode 100644 index 000000000..08e0418f3 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/fr_class_index.html @@ -0,0 +1,37 @@ + + + + + + + + Classes + + + + + +
+

Classes

+ +
+ + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/fr_file_index.html b/vendor/plugins/gloc-1.1.0/doc/fr_file_index.html new file mode 100644 index 000000000..839e378d3 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/fr_file_index.html @@ -0,0 +1,35 @@ + + + + + + + + Files + + + + + +
+

Files

+ +
+ + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/fr_method_index.html b/vendor/plugins/gloc-1.1.0/doc/fr_method_index.html new file mode 100644 index 000000000..325ed3589 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/fr_method_index.html @@ -0,0 +1,72 @@ + + + + + + + + Methods + + + + + +
+

Methods

+
+ add (ActiveRecord::Errors)
+ add_localized_strings (GLoc)
+ autodetect_language_filter (ActionController::Filters::ClassMethods)
+ backup_state (GLoc)
+ clear_strings (GLoc)
+ clear_strings_except (GLoc)
+ current_language (GLoc::ClassMethods)
+ current_language (GLoc)
+ current_language (GLoc)
+ current_language (ActionView::Helpers::InstanceTag)
+ current_language (ActiveRecord::Errors)
+ distance_of_time_in_words (ActionView::Helpers::DateHelper)
+ get_charset (GLoc)
+ get_config (GLoc)
+ l (GLoc::InstanceMethods)
+ l_YesNo (GLoc::Helpers)
+ l_age (GLoc::Helpers)
+ l_date (GLoc::Helpers)
+ l_datetime (GLoc::Helpers)
+ l_datetime_short (GLoc::Helpers)
+ l_has_string? (GLoc::InstanceMethods)
+ l_lang_name (GLoc::Helpers)
+ l_strftime (GLoc::Helpers)
+ l_time (GLoc::Helpers)
+ l_yesno (GLoc::Helpers)
+ ll (GLoc::InstanceMethods)
+ load_gloc_default_localized_strings (GLoc)
+ load_localized_strings (GLoc)
+ ltry (GLoc::InstanceMethods)
+ lwr (GLoc::InstanceMethods)
+ lwr_ (GLoc::InstanceMethods)
+ new (ActionView::Base)
+ restore_state (GLoc)
+ select_day (ActionView::Helpers::DateHelper)
+ select_month (ActionView::Helpers::DateHelper)
+ select_year (ActionView::Helpers::DateHelper)
+ set_charset (GLoc)
+ set_config (GLoc)
+ set_kcode (GLoc)
+ set_language (GLoc::InstanceMethods)
+ set_language_if_valid (GLoc::InstanceMethods)
+ similar_language (GLoc)
+ valid_language? (GLoc)
+ valid_languages (GLoc)
+ validates_length_of (ActiveRecord::Validations::ClassMethods)
+ validates_size_of (ActiveRecord::Validations::ClassMethods)
+
+
+ + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/index.html b/vendor/plugins/gloc-1.1.0/doc/index.html new file mode 100644 index 000000000..f29103142 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/index.html @@ -0,0 +1,24 @@ + + + + + + + GLoc Localization Library Documentation + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/doc/rdoc-style.css b/vendor/plugins/gloc-1.1.0/doc/rdoc-style.css new file mode 100644 index 000000000..fbf7326af --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/doc/rdoc-style.css @@ -0,0 +1,208 @@ + +body { + font-family: Verdana,Arial,Helvetica,sans-serif; + font-size: 90%; + margin: 0; + margin-left: 40px; + padding: 0; + background: white; +} + +h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } +h1 { font-size: 150%; } +h2,h3,h4 { margin-top: 1em; } + +a { background: #eef; color: #039; text-decoration: none; } +a:hover { background: #039; color: #eef; } + +/* Override the base stylesheet's Anchor inside a table cell */ +td > a { + background: transparent; + color: #039; + text-decoration: none; +} + +/* and inside a section title */ +.section-title > a { + background: transparent; + color: #eee; + text-decoration: none; +} + +/* === Structural elements =================================== */ + +div#index { + margin: 0; + margin-left: -40px; + padding: 0; + font-size: 90%; +} + + +div#index a { + margin-left: 0.7em; +} + +div#index .section-bar { + margin-left: 0px; + padding-left: 0.7em; + background: #ccc; + font-size: small; +} + + +div#classHeader, div#fileHeader { + width: auto; + color: white; + padding: 0.5em 1.5em 0.5em 1.5em; + margin: 0; + margin-left: -40px; + border-bottom: 3px solid #006; +} + +div#classHeader a, div#fileHeader a { + background: inherit; + color: white; +} + +div#classHeader td, div#fileHeader td { + background: inherit; + color: white; +} + + +div#fileHeader { + background: #057; +} + +div#classHeader { + background: #048; +} + + +.class-name-in-header { + font-size: 180%; + font-weight: bold; +} + + +div#bodyContent { + padding: 0 1.5em 0 1.5em; +} + +div#description { + padding: 0.5em 1.5em; + background: #efefef; + border: 1px dotted #999; +} + +div#description h1,h2,h3,h4,h5,h6 { + color: #125;; + background: transparent; +} + +div#validator-badges { + text-align: center; +} +div#validator-badges img { border: 0; } + +div#copyright { + color: #333; + background: #efefef; + font: 0.75em sans-serif; + margin-top: 5em; + margin-bottom: 0; + padding: 0.5em 2em; +} + + +/* === Classes =================================== */ + +table.header-table { + color: white; + font-size: small; +} + +.type-note { + font-size: small; + color: #DEDEDE; +} + +.xxsection-bar { + background: #eee; + color: #333; + padding: 3px; +} + +.section-bar { + color: #333; + border-bottom: 1px solid #999; + margin-left: -20px; +} + + +.section-title { + background: #79a; + color: #eee; + padding: 3px; + margin-top: 2em; + margin-left: -30px; + border: 1px solid #999; +} + +.top-aligned-row { vertical-align: top } +.bottom-aligned-row { vertical-align: bottom } + +/* --- Context section classes ----------------------- */ + +.context-row { } +.context-item-name { font-family: monospace; font-weight: bold; color: black; } +.context-item-value { font-size: small; color: #448; } +.context-item-desc { color: #333; padding-left: 2em; } + +/* --- Method classes -------------------------- */ +.method-detail { + background: #efefef; + padding: 0; + margin-top: 0.5em; + margin-bottom: 1em; + border: 1px dotted #ccc; +} +.method-heading { + color: black; + background: #ccc; + border-bottom: 1px solid #666; + padding: 0.2em 0.5em 0 0.5em; +} +.method-signature { color: black; background: inherit; } +.method-name { font-weight: bold; } +.method-args { font-style: italic; } +.method-description { padding: 0 0.5em 0 0.5em; } + +/* --- Source code sections -------------------- */ + +a.source-toggle { font-size: 90%; } +div.method-source-code { + background: #262626; + color: #ffdead; + margin: 1em; + padding: 0.5em; + border: 1px dashed #999; + overflow: hidden; +} + +div.method-source-code pre { color: #ffdead; overflow: hidden; } + +/* --- Ruby keyword styles --------------------- */ + +.standalone-code { background: #221111; color: #ffdead; overflow: hidden; } + +.ruby-constant { color: #7fffd4; background: transparent; } +.ruby-keyword { color: #00ffff; background: transparent; } +.ruby-ivar { color: #eedd82; background: transparent; } +.ruby-operator { color: #00ffee; background: transparent; } +.ruby-identifier { color: #ffdead; background: transparent; } +.ruby-node { color: #ffa07a; background: transparent; } +.ruby-comment { color: #b22222; font-weight: bold; background: transparent; } +.ruby-regexp { color: #ffa07a; background: transparent; } +.ruby-value { color: #7fffd4; background: transparent; } \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/init.rb b/vendor/plugins/gloc-1.1.0/init.rb new file mode 100644 index 000000000..9d99acd61 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/init.rb @@ -0,0 +1,11 @@ +# Copyright (c) 2005-2006 David Barri + +require 'gloc' +require 'gloc-ruby' +require 'gloc-rails' +require 'gloc-rails-text' +require 'gloc-config' + +require 'gloc-dev' if ENV['RAILS_ENV'] == 'development' + +GLoc.load_gloc_default_localized_strings diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-config.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-config.rb new file mode 100644 index 000000000..e85b041f5 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-config.rb @@ -0,0 +1,16 @@ +# Copyright (c) 2005-2006 David Barri + +module GLoc + + private + + CONFIG= {} unless const_defined?(:CONFIG) + unless CONFIG.frozen? + CONFIG[:default_language] ||= :en + CONFIG[:default_param_name] ||= 'lang' + CONFIG[:default_cookie_name] ||= 'lang' + CONFIG[:raise_string_not_found_errors]= true unless CONFIG.has_key?(:raise_string_not_found_errors) + CONFIG[:verbose] ||= false + end + +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-dev.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-dev.rb new file mode 100644 index 000000000..cb12b4cb3 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-dev.rb @@ -0,0 +1,97 @@ +# Copyright (c) 2005-2006 David Barri + +puts "GLoc v#{GLoc::VERSION} running in development mode. Strings can be modified at runtime." + +module GLoc + class << self + + alias :actual_add_localized_strings :add_localized_strings + def add_localized_strings(lang, symbol_hash, override=true, strings_charset=nil) + _verbose_msg {"dev::add_localized_strings #{lang}, [#{symbol_hash.size}], #{override}, #{strings_charset ? strings_charset : 'nil'}"} + STATE.push [:hash, lang, {}.merge(symbol_hash), override, strings_charset] + _force_refresh + end + + alias :actual_load_localized_strings :load_localized_strings + def load_localized_strings(dir=nil, override=true) + _verbose_msg {"dev::load_localized_strings #{dir ? dir : 'nil'}, #{override}"} + STATE.push [:dir, dir, override] + _get_lang_file_list(dir).each {|filename| FILES[filename]= nil} + end + + alias :actual_clear_strings :clear_strings + def clear_strings(*languages) + _verbose_msg {"dev::clear_strings #{languages.map{|l|l.to_s}.join(', ')}"} + STATE.push [:clear, languages.clone] + _force_refresh + end + + alias :actual_clear_strings_except :clear_strings_except + def clear_strings_except(*languages) + _verbose_msg {"dev::clear_strings_except #{languages.map{|l|l.to_s}.join(', ')}"} + STATE.push [:clear_except, languages.clone] + _force_refresh + end + + # Replace methods + [:_l, :_l_rule, :_l_has_string?, :similar_language, :valid_languages, :valid_language?].each do |m| + class_eval <<-EOB + alias :actual_#{m} :#{m} + def #{m}(*args) + _assert_gloc_strings_up_to_date + actual_#{m}(*args) + end + EOB + end + + #------------------------------------------------------------------------- + private + + STATE= [] + FILES= {} + + def _assert_gloc_strings_up_to_date + changed= @@force_refresh + + # Check if any lang files have changed + unless changed + FILES.each_pair {|f,mtime| + changed ||= (File.stat(f).mtime != mtime) + } + end + + return unless changed + puts "GLoc reloading strings..." + @@force_refresh= false + + # Update file timestamps + FILES.each_key {|f| + FILES[f]= File.stat(f).mtime + } + + # Reload strings + actual_clear_strings + STATE.each {|s| + case s[0] + when :dir then actual_load_localized_strings s[1], s[2] + when :hash then actual_add_localized_strings s[1], s[2], s[3], s[4] + when :clear then actual_clear_strings(*s[1]) + when :clear_except then actual_clear_strings_except(*s[1]) + else raise "Invalid state id: '#{s[0]}'" + end + } + _verbose_msg :stats + end + + @@force_refresh= false + def _force_refresh + @@force_refresh= true + end + + alias :super_get_internal_state_vars :_get_internal_state_vars + def _get_internal_state_vars + super_get_internal_state_vars + [ STATE, FILES ] + end + + end +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-helpers.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-helpers.rb new file mode 100644 index 000000000..f2ceb8e3d --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-helpers.rb @@ -0,0 +1,20 @@ +# Copyright (c) 2005-2006 David Barri + +module GLoc + # These helper methods will be included in the InstanceMethods module. + module Helpers + def l_age(age) lwr :general_fmt_age, age end + def l_date(date) l_strftime date, :general_fmt_date end + def l_datetime(date) l_strftime date, :general_fmt_datetime end + def l_datetime_short(date) l_strftime date, :general_fmt_datetime_short end + def l_strftime(date,fmt) date.strftime l(fmt) end + def l_time(time) l_strftime time, :general_fmt_time end + def l_YesNo(value) l(value ? :general_text_Yes : :general_text_No) end + def l_yesno(value) l(value ? :general_text_yes : :general_text_no) end + + def l_lang_name(lang, display_lang=nil) + ll display_lang || current_language, "general_lang_#{lang}" + end + + end +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb new file mode 100644 index 000000000..f16e90555 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb @@ -0,0 +1,134 @@ +# Copyright (c) 2005-2006 David Barri + +require 'iconv' +require 'gloc-version' + +module GLoc + class GLocError < StandardError #:nodoc: + end + class InvalidArgumentsError < GLocError #:nodoc: + end + class InvalidKeyError < GLocError #:nodoc: + end + class RuleNotFoundError < GLocError #:nodoc: + end + class StringNotFoundError < GLocError #:nodoc: + end + + class << self + private + + def _add_localized_data(lang, symbol_hash, override, target) #:nodoc: + lang= lang.to_sym + if override + target[lang] ||= {} + target[lang].merge!(symbol_hash) + else + symbol_hash.merge!(target[lang]) if target[lang] + target[lang]= symbol_hash + end + end + + def _add_localized_strings(lang, symbol_hash, override=true, strings_charset=nil) #:nodoc: + _charset_required + + # Convert all incoming strings to the gloc charset + if strings_charset + Iconv.open(get_charset(lang), strings_charset) do |i| + symbol_hash.each_pair {|k,v| symbol_hash[k]= i.iconv(v)} + end + end + + # Convert rules + rules= {} + old_kcode= $KCODE + begin + $KCODE= 'u' + Iconv.open(UTF_8, get_charset(lang)) do |i| + symbol_hash.each {|k,v| + if /^_gloc_rule_(.+)$/ =~ k.to_s + v= i.iconv(v) if v + v= '""' if v.nil? + rules[$1.to_sym]= eval "Proc.new do #{v} end" + end + } + end + ensure + $KCODE= old_kcode + end + rules.keys.each {|k| symbol_hash.delete "_gloc_rule_#{k}".to_sym} + + # Add new localized data + LOWERCASE_LANGUAGES[lang.to_s.downcase]= lang + _add_localized_data(lang, symbol_hash, override, LOCALIZED_STRINGS) + _add_localized_data(lang, rules, override, RULES) + end + + def _charset_required #:nodoc: + set_charset UTF_8 unless CONFIG[:internal_charset] + end + + def _get_internal_state_vars + [ CONFIG, LOCALIZED_STRINGS, RULES, LOWERCASE_LANGUAGES ] + end + + def _get_lang_file_list(dir) #:nodoc: + dir= File.join(RAILS_ROOT,'lang') if dir.nil? + Dir[File.join(dir,'*.{yaml,yml}')] + end + + def _l(symbol, language, *arguments) #:nodoc: + symbol= symbol.to_sym if symbol.is_a?(String) + raise InvalidKeyError.new("Symbol or String expected as key.") unless symbol.kind_of?(Symbol) + + translation= LOCALIZED_STRINGS[language][symbol] rescue nil + if translation.nil? + raise StringNotFoundError.new("There is no key called '#{symbol}' in the #{language} strings.") if CONFIG[:raise_string_not_found_errors] + translation= symbol.to_s + end + + begin + return translation % arguments + rescue => e + raise InvalidArgumentsError.new("Translation value #{translation.inspect} with arguments #{arguments.inspect} caused error '#{e.message}'") + end + end + + def _l_has_string?(symbol,lang) #:nodoc: + symbol= symbol.to_sym if symbol.is_a?(String) + LOCALIZED_STRINGS[lang].has_key?(symbol.to_sym) rescue false + end + + def _l_rule(symbol,lang) #:nodoc: + symbol= symbol.to_sym if symbol.is_a?(String) + raise InvalidKeyError.new("Symbol or String expected as key.") unless symbol.kind_of?(Symbol) + + r= RULES[lang][symbol] rescue nil + raise RuleNotFoundError.new("There is no rule called '#{symbol}' in the #{lang} rules.") if r.nil? + r + end + + def _verbose_msg(type=nil) + return unless CONFIG[:verbose] + x= case type + when :stats + x= valid_languages.map{|l| ":#{l}(#{LOCALIZED_STRINGS[l].size}/#{RULES[l].size})"}.sort.join(', ') + "Current stats -- #{x}" + else + yield + end + puts "[GLoc] #{x}" + end + + public :_l, :_l_has_string?, :_l_rule + end + + private + + unless const_defined?(:LOCALIZED_STRINGS) + LOCALIZED_STRINGS= {} + RULES= {} + LOWERCASE_LANGUAGES= {} + end + +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb new file mode 100644 index 000000000..abbb7a190 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb @@ -0,0 +1,137 @@ +# Copyright (c) 2005-2006 David Barri + +require 'date' + +module ActionView #:nodoc: + module Helpers #:nodoc: + module DateHelper + + unless const_defined?(:LOCALIZED_HELPERS) + LOCALIZED_HELPERS= true + LOCALIZED_MONTHNAMES = {} + LOCALIZED_ABBR_MONTHNAMES = {} + end + + # This method uses current_language to return a localized string. + def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false) + from_time = from_time.to_time if from_time.respond_to?(:to_time) + to_time = to_time.to_time if to_time.respond_to?(:to_time) + distance_in_minutes = (((to_time - from_time).abs)/60).round + distance_in_seconds = ((to_time - from_time).abs).round + + case distance_in_minutes + when 0..1 + return (distance_in_minutes==0) ? l(:actionview_datehelper_time_in_words_minute_less_than) : l(:actionview_datehelper_time_in_words_minute_single) unless include_seconds + case distance_in_seconds + when 0..5 then lwr(:actionview_datehelper_time_in_words_second_less_than, 5) + when 6..10 then lwr(:actionview_datehelper_time_in_words_second_less_than, 10) + when 11..20 then lwr(:actionview_datehelper_time_in_words_second_less_than, 20) + when 21..40 then l(:actionview_datehelper_time_in_words_minute_half) + when 41..59 then l(:actionview_datehelper_time_in_words_minute_less_than) + else l(:actionview_datehelper_time_in_words_minute) + end + + when 2..45 then lwr(:actionview_datehelper_time_in_words_minute, distance_in_minutes) + when 46..90 then l(:actionview_datehelper_time_in_words_hour_about_single) + when 90..1440 then lwr(:actionview_datehelper_time_in_words_hour_about, (distance_in_minutes.to_f / 60.0).round) + when 1441..2880 then lwr(:actionview_datehelper_time_in_words_day, 1) + else lwr(:actionview_datehelper_time_in_words_day, (distance_in_minutes / 1440).round) + end + end + + # This method has been modified so that a localized string can be appended to the day numbers. + def select_day(date, options = {}) + day_options = [] + prefix = l :actionview_datehelper_select_day_prefix + + 1.upto(31) do |day| + day_options << ((date && (date.kind_of?(Fixnum) ? date : date.day) == day) ? + %(\n) : + %(\n) + ) + end + + select_html(options[:field_name] || 'day', day_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # This method has been modified so that + # * the month names are localized. + # * it uses options: :min_date, :max_date, :start_month, :end_month + # * a localized string can be appended to the month numbers when the :use_month_numbers option is specified. + def select_month(date, options = {}) + unless LOCALIZED_MONTHNAMES.has_key?(current_language) + LOCALIZED_MONTHNAMES[current_language] = [''] + l(:actionview_datehelper_select_month_names).split(',') + LOCALIZED_ABBR_MONTHNAMES[current_language] = [''] + l(:actionview_datehelper_select_month_names_abbr).split(',') + end + + month_options = [] + month_names = options[:use_short_month] ? LOCALIZED_ABBR_MONTHNAMES[current_language] : LOCALIZED_MONTHNAMES[current_language] + + if options.has_key?(:min_date) && options.has_key?(:max_date) + if options[:min_date].year == options[:max_date].year + start_month, end_month = options[:min_date].month, options[:max_date].month + end + end + start_month = (options[:start_month] || 1) unless start_month + end_month = (options[:end_month] || 12) unless end_month + prefix = l :actionview_datehelper_select_month_prefix + + start_month.upto(end_month) do |month_number| + month_name = if options[:use_month_numbers] + "#{month_number}#{prefix}" + elsif options[:add_month_numbers] + month_number.to_s + ' - ' + month_names[month_number] + else + month_names[month_number] + end + + month_options << ((date && (date.kind_of?(Fixnum) ? date : date.month) == month_number) ? + %(\n) : + %(\n) + ) + end + + select_html(options[:field_name] || 'month', month_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # This method has been modified so that + # * it uses options: :min_date, :max_date + # * a localized string can be appended to the years numbers. + def select_year(date, options = {}) + year_options = [] + y = date ? (date.kind_of?(Fixnum) ? (y = (date == 0) ? Date.today.year : date) : date.year) : Date.today.year + + start_year = options.has_key?(:min_date) ? options[:min_date].year : (options[:start_year] || y-5) + end_year = options.has_key?(:max_date) ? options[:max_date].year : (options[:end_year] || y+5) + step_val = start_year < end_year ? 1 : -1 + prefix = l :actionview_datehelper_select_year_prefix + + start_year.step(end_year, step_val) do |year| + year_options << ((date && (date.kind_of?(Fixnum) ? date : date.year) == year) ? + %(\n) : + %(\n) + ) + end + + select_html(options[:field_name] || 'year', year_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + end + + # The private method add_options is overridden so that "Please select" is localized. + class InstanceTag + private + + def add_options(option_tags, options, value = nil) + option_tags = "\n" + option_tags if options[:include_blank] + + if value.blank? && options[:prompt] + ("\n") + option_tags + else + option_tags + end + end + + end + end +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-rails.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-rails.rb new file mode 100644 index 000000000..0a35b90ab --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-rails.rb @@ -0,0 +1,230 @@ +# Copyright (c) 2005-2006 David Barri + +require 'gloc' + +module ActionController #:nodoc: + class Base #:nodoc: + include GLoc + end + module Filters #:nodoc: + module ClassMethods + + # This filter attempts to auto-detect the clients desired language. + # It first checks the params, then a cookie and then the HTTP_ACCEPT_LANGUAGE + # request header. If a language is found to match or be similar to a currently + # valid language, then it sets the current_language of the controller. + # + # class ExampleController < ApplicationController + # set_language :en + # autodetect_language_filter :except => 'monkey', :on_no_lang => :lang_not_autodetected_callback + # autodetect_language_filter :only => 'monkey', :check_cookie => 'monkey_lang', :check_accept_header => false + # ... + # def lang_not_autodetected_callback + # redirect_to somewhere + # end + # end + # + # The args for this filter are exactly the same the arguments of + # before_filter with the following exceptions: + # * :check_params -- If false, then params will not be checked for a language. + # If a String, then this will value will be used as the name of the param. + # * :check_cookie -- If false, then the cookie will not be checked for a language. + # If a String, then this will value will be used as the name of the cookie. + # * :check_accept_header -- If false, then HTTP_ACCEPT_LANGUAGE will not be checked for a language. + # * :on_set_lang -- You can specify the name of a callback function to be called when the language + # is successfully detected and set. The param must be a Symbol or a String which is the name of the function. + # The callback function must accept one argument (the language) and must be instance level. + # * :on_no_lang -- You can specify the name of a callback function to be called when the language + # couldn't be detected automatically. The param must be a Symbol or a String which is the name of the function. + # The callback function must be instance level. + # + # You override the default names of the param or cookie by calling GLoc.set_config :default_param_name => 'new_param_name' + # and GLoc.set_config :default_cookie_name => 'new_cookie_name'. + def autodetect_language_filter(*args) + options= args.last.is_a?(Hash) ? args.last : {} + x= 'Proc.new { |c| l= nil;' + # :check_params + unless (v= options.delete(:check_params)) == false + name= v ? ":#{v}" : 'GLoc.get_config(:default_param_name)' + x << "l ||= GLoc.similar_language(c.params[#{name}]);" + end + # :check_cookie + unless (v= options.delete(:check_cookie)) == false + name= v ? ":#{v}" : 'GLoc.get_config(:default_cookie_name)' + x << "l ||= GLoc.similar_language(c.send(:cookies)[#{name}]);" + end + # :check_accept_header + unless options.delete(:check_accept_header) == false + x << %< + unless l + a= c.request.env['HTTP_ACCEPT_LANGUAGE'].split(/,|;/) rescue nil + a.each {|x| l ||= GLoc.similar_language(x)} if a + end; > + end + # Set language + x << 'ret= true;' + x << 'if l; c.set_language(l); c.headers[\'Content-Language\']= l.to_s; ' + if options.has_key?(:on_set_lang) + x << "ret= c.#{options.delete(:on_set_lang)}(l);" + end + if options.has_key?(:on_no_lang) + x << "else; ret= c.#{options.delete(:on_no_lang)};" + end + x << 'end; ret }' + + # Create filter + block= eval x + before_filter(*args, &block) + end + + end + end +end + +# ============================================================================== + +module ActionMailer #:nodoc: + # In addition to including GLoc, render_message is also overridden so + # that mail templates contain the current language at the end of the file. + # Eg. deliver_hello will render hello_en.rhtml. + class Base + include GLoc + private + alias :render_message_without_gloc :render_message + def render_message(method_name, body) + render_message_without_gloc("#{method_name}_#{current_language}", body) + end + end +end + +# ============================================================================== + +module ActionView #:nodoc: + # initialize is overridden so that new instances of this class inherit + # the current language of the controller. + class Base + include GLoc + + alias :initialize_without_gloc :initialize + def initialize(base_path = nil, assigns_for_first_render = {}, controller = nil) + initialize_without_gloc(base_path, assigns_for_first_render, controller) + set_language controller.current_language unless controller.nil? + end + end + + module Helpers #:nodoc: + class InstanceTag + include GLoc + # Inherits the current language from the template object. + def current_language + @template_object.current_language + end + end + end +end + +# ============================================================================== + +module ActiveRecord #:nodoc: + class Base #:nodoc: + include GLoc + end + + class Errors + include GLoc + alias :add_without_gloc :add + # The GLoc version of this method provides two extra features + # * If msg is a string, it will be considered a GLoc string key. + # * If msg is an array, the first element will be considered + # the string and the remaining elements will be considered arguments for the + # string. Eg. ['Hi %s.','John'] + def add(attribute, msg= @@default_error_messages[:invalid]) + if msg.is_a?(Array) + args= msg.clone + msg= args.shift + args= nil if args.empty? + end + msg= ltry(msg) + msg= msg % args unless args.nil? + add_without_gloc(attribute, msg) + end + # Inherits the current language from the base record. + def current_language + @base.current_language + end + end + + module Validations #:nodoc: + module ClassMethods + # The default Rails version of this function creates an error message and then + # passes it to ActiveRecord.Errors. + # The GLoc version of this method, sends an array to ActiveRecord.Errors that will + # be turned into a string by ActiveRecord.Errors which in turn allows for the message + # of this validation function to be a GLoc string key. + def validates_length_of(*attrs) + # Merge given options with defaults. + options = { + :too_long => ActiveRecord::Errors.default_error_messages[:too_long], + :too_short => ActiveRecord::Errors.default_error_messages[:too_short], + :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length] + }.merge(DEFAULT_VALIDATION_OPTIONS) + options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash) + + # Ensure that one and only one range option is specified. + range_options = ALL_RANGE_OPTIONS & options.keys + case range_options.size + when 0 + raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.' + when 1 + # Valid number of options; do nothing. + else + raise ArgumentError, 'Too many range options specified. Choose only one.' + end + + # Get range option and value. + option = range_options.first + option_value = options[range_options.first] + + case option + when :within, :in + raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range) + + too_short = [options[:too_short] , option_value.begin] + too_long = [options[:too_long] , option_value.end ] + + validates_each(attrs, options) do |record, attr, value| + if value.nil? or value.split(//).size < option_value.begin + record.errors.add(attr, too_short) + elsif value.split(//).size > option_value.end + record.errors.add(attr, too_long) + end + end + when :is, :minimum, :maximum + raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0 + + # Declare different validations per option. + validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" } + message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long } + + message = [(options[:message] || options[message_options[option]]) , option_value] + + validates_each(attrs, options) do |record, attr, value| + if value.kind_of?(String) + record.errors.add(attr, message) unless !value.nil? and value.split(//).size.method(validity_checks[option])[option_value] + else + record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value] + end + end + end + end + + alias_method :validates_size_of, :validates_length_of + end + end +end + +# ============================================================================== + +module ApplicationHelper #:nodoc: + include GLoc +end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-ruby.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-ruby.rb new file mode 100644 index 000000000..f96ab6cf9 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-ruby.rb @@ -0,0 +1,7 @@ +# Copyright (c) 2005-2006 David Barri + +module Test # :nodoc: + module Unit # :nodoc: + class TestCase # :nodoc: + include GLoc +end; end; end diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc-version.rb b/vendor/plugins/gloc-1.1.0/lib/gloc-version.rb new file mode 100644 index 000000000..91afcf482 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc-version.rb @@ -0,0 +1,12 @@ +module GLoc + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 1 + TINY = nil + + STRING= [MAJOR, MINOR, TINY].delete_if{|x|x.nil?}.join('.') + def self.to_s; STRING end + end +end + +puts "NOTICE: You are using a dev version of GLoc." if GLoc::VERSION::TINY == 'DEV' \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/lib/gloc.rb b/vendor/plugins/gloc-1.1.0/lib/gloc.rb new file mode 100644 index 000000000..bcad0ed9b --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/lib/gloc.rb @@ -0,0 +1,294 @@ +# Copyright (c) 2005-2006 David Barri + +require 'yaml' +require 'gloc-internal' +require 'gloc-helpers' + +module GLoc + UTF_8= 'utf-8' + SHIFT_JIS= 'sjis' + EUC_JP= 'euc-jp' + + # This module will be included in both instances and classes of GLoc includees. + # It is also included as class methods in the GLoc module itself. + module InstanceMethods + include Helpers + + # Returns a localized string. + def l(symbol, *arguments) + return GLoc._l(symbol,current_language,*arguments) + end + + # Returns a localized string in a specified language. + # This does not effect current_language. + def ll(lang, symbol, *arguments) + return GLoc._l(symbol,lang.to_sym,*arguments) + end + + # Returns a localized string if the argument is a Symbol, else just returns the argument. + def ltry(possible_key) + possible_key.is_a?(Symbol) ? l(possible_key) : possible_key + end + + # Uses the default GLoc rule to return a localized string. + # See lwr_() for more info. + def lwr(symbol, *arguments) + lwr_(:default, symbol, *arguments) + end + + # Uses a rule to return a localized string. + # A rule is a function that uses specified arguments to return a localization key prefix. + # The prefix is appended to the localization key originally specified, to create a new key which + # is then used to lookup a localized string. + def lwr_(rule, symbol, *arguments) + GLoc._l("#{symbol}#{GLoc::_l_rule(rule,current_language).call(*arguments)}",current_language,*arguments) + end + + # Returns true if a localized string with the specified key exists. + def l_has_string?(symbol) + return GLoc._l_has_string?(symbol,current_language) + end + + # Sets the current language for this instance/class. + # Setting the language of a class effects all instances unless the instance has its own language defined. + def set_language(language) + @gloc_language= language.nil? ? nil : language.to_sym + end + + # Sets the current language if the language passed is a valid language. + # If the language was valid, this method returns true else it will return false. + # Note that nil is not a valid language. + # See set_language(language) for more info. + def set_language_if_valid(language) + if GLoc.valid_language?(language) + set_language(language) + true + else + false + end + end + end + + #--------------------------------------------------------------------------- + # Instance + + include ::GLoc::InstanceMethods + # Returns the instance-level current language, or if not set, returns the class-level current language. + def current_language + @gloc_language || self.class.current_language + end + + #--------------------------------------------------------------------------- + # Class + + # All classes/modules that include GLoc will also gain these class methods. + # Notice that the GLoc::InstanceMethods module is also included. + module ClassMethods + include ::GLoc::InstanceMethods + # Returns the current language, or if not set, returns the GLoc current language. + def current_language + @gloc_language || GLoc.current_language + end + end + + def self.included(target) #:nodoc: + super + class << target + include ::GLoc::ClassMethods + end + end + + #--------------------------------------------------------------------------- + # GLoc module + + class << self + include ::GLoc::InstanceMethods + + # Returns the default language + def current_language + GLoc::CONFIG[:default_language] + end + + # Adds a collection of localized strings to the in-memory string store. + def add_localized_strings(lang, symbol_hash, override=true, strings_charset=nil) + _verbose_msg {"Adding #{symbol_hash.size} #{lang} strings."} + _add_localized_strings(lang, symbol_hash, override, strings_charset) + _verbose_msg :stats + end + + # Creates a backup of the internal state of GLoc (ie. strings, langs, rules, config) + # and optionally clears everything. + def backup_state(clear=false) + s= _get_internal_state_vars.map{|o| o.clone} + _get_internal_state_vars.each{|o| o.clear} if clear + s + end + + # Removes all localized strings from memory, either of a certain language (or languages), + # or entirely. + def clear_strings(*languages) + if languages.empty? + _verbose_msg {"Clearing all strings"} + LOCALIZED_STRINGS.clear + LOWERCASE_LANGUAGES.clear + else + languages.each {|l| + _verbose_msg {"Clearing :#{l} strings"} + l= l.to_sym + LOCALIZED_STRINGS.delete l + LOWERCASE_LANGUAGES.each_pair {|k,v| LOWERCASE_LANGUAGES.delete k if v == l} + } + end + end + alias :_clear_strings :clear_strings + + # Removes all localized strings from memory, except for those of certain specified languages. + def clear_strings_except(*languages) + clear= (LOCALIZED_STRINGS.keys - languages) + _clear_strings(*clear) unless clear.empty? + end + + # Returns the charset used to store localized strings in memory. + def get_charset(lang) + CONFIG[:internal_charset_per_lang][lang] || CONFIG[:internal_charset] + end + + # Returns a GLoc configuration value. + def get_config(key) + CONFIG[key] + end + + # Loads the localized strings that are included in the GLoc library. + def load_gloc_default_localized_strings(override=false) + GLoc.load_localized_strings "#{File.dirname(__FILE__)}/../lang", override + end + + # Loads localized strings from all yml files in the specifed directory. + def load_localized_strings(dir=nil, override=true) + _charset_required + _get_lang_file_list(dir).each {|filename| + + # Load file + raw_hash = YAML::load(File.read(filename)) + raw_hash={} unless raw_hash.kind_of?(Hash) + filename =~ /([^\/\\]+)\.ya?ml$/ + lang = $1.to_sym + file_charset = raw_hash['file_charset'] || UTF_8 + + # Convert string keys to symbols + dest_charset= get_charset(lang) + _verbose_msg {"Reading file #{filename} [charset: #{file_charset} --> #{dest_charset}]"} + symbol_hash = {} + Iconv.open(dest_charset, file_charset) do |i| + raw_hash.each {|key, value| + symbol_hash[key.to_sym] = i.iconv(value) + } + end + + # Add strings to repos + _add_localized_strings(lang, symbol_hash, override) + } + _verbose_msg :stats + end + + # Restores a backup of GLoc's internal state that was made with backup_state. + def restore_state(state) + _get_internal_state_vars.each do |o| + o.clear + o.send o.respond_to?(:merge!) ? :merge! : :concat, state.shift + end + end + + # Sets the charset used to internally store localized strings. + # You can set the charset to use for a specific language or languages, + # or if none are specified the charset for ALL localized strings will be set. + def set_charset(new_charset, *langs) + CONFIG[:internal_charset_per_lang] ||= {} + + # Convert symbol shortcuts + if new_charset.is_a?(Symbol) + new_charset= case new_charset + when :utf8, :utf_8 then UTF_8 + when :sjis, :shift_jis, :shiftjis then SHIFT_JIS + when :eucjp, :euc_jp then EUC_JP + else new_charset.to_s + end + end + + # Convert existing strings + (langs.empty? ? LOCALIZED_STRINGS.keys : langs).each do |lang| + cur_charset= get_charset(lang) + if cur_charset && new_charset != cur_charset + _verbose_msg {"Converting :#{lang} strings from #{cur_charset} to #{new_charset}"} + Iconv.open(new_charset, cur_charset) do |i| + bundle= LOCALIZED_STRINGS[lang] + bundle.each_pair {|k,v| bundle[k]= i.iconv(v)} + end + end + end + + # Set new charset value + if langs.empty? + _verbose_msg {"Setting GLoc charset for all languages to #{new_charset}"} + CONFIG[:internal_charset]= new_charset + CONFIG[:internal_charset_per_lang].clear + else + langs.each do |lang| + _verbose_msg {"Setting GLoc charset for :#{lang} strings to #{new_charset}"} + CONFIG[:internal_charset_per_lang][lang]= new_charset + end + end + end + + # Sets GLoc configuration values. + def set_config(hash) + CONFIG.merge! hash + end + + # Sets the $KCODE global variable according to a specified charset, or else the + # current default charset for the default language. + def set_kcode(charset=nil) + _charset_required + charset ||= get_charset(current_language) + $KCODE= case charset + when UTF_8 then 'u' + when SHIFT_JIS then 's' + when EUC_JP then 'e' + else 'n' + end + _verbose_msg {"$KCODE set to #{$KCODE}"} + end + + # Tries to find a valid language that is similar to the argument passed. + # Eg. :en, :en_au, :EN_US are all similar languages. + # Returns nil if no similar languages are found. + def similar_language(lang) + return nil if lang.nil? + return lang.to_sym if valid_language?(lang) + # Check lowercase without dashes + lang= lang.to_s.downcase.gsub('-','_') + return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang) + # Check without dialect + if lang.to_s =~ /^([a-z]+?)[^a-z].*/ + lang= $1 + return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang) + end + # Check other dialects + lang= "#{lang}_" + LOWERCASE_LANGUAGES.keys.each {|k| return LOWERCASE_LANGUAGES[k] if k.starts_with?(lang)} + # Nothing found + nil + end + + # Returns an array of (currently) valid languages (ie. languages for which localized data exists). + def valid_languages + LOCALIZED_STRINGS.keys + end + + # Returns true if there are any localized strings for a specified language. + # Note that although set_langauge nil is perfectly valid, nil is not a valid language. + def valid_language?(language) + LOCALIZED_STRINGS.has_key? language.to_sym rescue false + end + end +end diff --git a/vendor/plugins/gloc-1.1.0/tasks/gloc.rake b/vendor/plugins/gloc-1.1.0/tasks/gloc.rake new file mode 100644 index 000000000..8da73779e --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/tasks/gloc.rake @@ -0,0 +1,30 @@ +namespace :gloc do + desc 'Sorts the keys in the lang ymls' + task :sort do + dir = ENV['DIR'] || '{.,vendor/plugins/*}/lang' + puts "Processing directory #{dir}" + files = Dir.glob(File.join(dir,'*.{yaml,yml}')) + puts 'No files found.' if files.empty? + files.each {|file| + puts "Sorting file: #{file}" + header = [] + content = IO.readlines(file) + content.each {|line| line.gsub!(/[\s\r\n\t]+$/,'')} + content.delete_if {|line| line==''} + tmp= [] + content.each {|x| tmp << x unless tmp.include?(x)} + content= tmp + header << content.shift if !content.empty? && content[0] =~ /^file_charset:/ + content.sort! + filebak = "#{file}.bak" + File.rename file, filebak + File.open(file, 'w') {|fout| fout << header.join("\n") << content.join("\n") << "\n"} + File.delete filebak + # Report duplicates + count= {} + content.map {|x| x.gsub(/:.+$/, '') }.each {|x| count[x] ||= 0; count[x] += 1} + count.delete_if {|k,v|v==1} + puts count.keys.sort.map{|x|" WARNING: Duplicate key '#{x}' (#{count[x]} occurances)"}.join("\n") unless count.empty? + } + end +end \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/gloc_rails_test.rb b/vendor/plugins/gloc-1.1.0/test/gloc_rails_test.rb new file mode 100644 index 000000000..4cb232904 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/gloc_rails_test.rb @@ -0,0 +1,118 @@ +# Copyright (c) 2005-2006 David Barri + +$LOAD_PATH.push File.join(File.dirname(__FILE__),'..','lib') +require "#{File.dirname(__FILE__)}/../../../../test/test_helper" +require "#{File.dirname(__FILE__)}/../init" + +class GLocRailsTestController < ActionController::Base + autodetect_language_filter :only => :auto, :on_set_lang => :called_when_set, :on_no_lang => :called_when_bad + autodetect_language_filter :only => :auto2, :check_accept_header => false, :check_params => 'xx' + autodetect_language_filter :only => :auto3, :check_cookie => false + autodetect_language_filter :only => :auto4, :check_cookie => 'qwe', :check_params => false + def rescue_action(e) raise e end + def auto; render :text => 'auto'; end + def auto2; render :text => 'auto'; end + def auto3; render :text => 'auto'; end + def auto4; render :text => 'auto'; end + attr_accessor :callback_set, :callback_bad + def called_when_set(l) @callback_set ||= 0; @callback_set += 1 end + def called_when_bad; @callback_bad ||= 0; @callback_bad += 1 end +end + +class GLocRailsTest < Test::Unit::TestCase + + def setup + @lstrings = GLoc::LOCALIZED_STRINGS.clone + @old_config= GLoc::CONFIG.clone + begin_new_request + end + + def teardown + GLoc.clear_strings + GLoc::LOCALIZED_STRINGS.merge! @lstrings + GLoc::CONFIG.merge! @old_config + end + + def begin_new_request + @controller = GLocRailsTestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_autodetect_language + GLoc::CONFIG[:default_language]= :def + GLoc::CONFIG[:default_param_name] = 'plang' + GLoc::CONFIG[:default_cookie_name] = 'clang' + GLoc.clear_strings + GLoc.add_localized_strings :en, :a => 'a' + GLoc.add_localized_strings :en_au, :a => 'a' + GLoc.add_localized_strings :en_US, :a => 'a' + GLoc.add_localized_strings :Ja, :a => 'a' + GLoc.add_localized_strings :ZH_HK, :a => 'a' + + # default + subtest_autodetect_language :def, nil, nil, nil + subtest_autodetect_language :def, 'its', 'all', 'bullshit,man;q=zxc' + # simple + subtest_autodetect_language :en_au, 'en_au', nil, nil + subtest_autodetect_language :en_US, nil, 'en_us', nil + subtest_autodetect_language :Ja, nil, nil, 'ja' + # priority + subtest_autodetect_language :Ja, 'ja', 'en_us', 'qwe_ja,zh,monkey_en;q=0.5' + subtest_autodetect_language :en_US, 'why', 'en_us', 'qwe_ja,zh,monkey_en;q=0.5' + subtest_autodetect_language :Ja, nil, nil, 'qwe_en,JA,zh,monkey_en;q=0.5' + # dashes to underscores in accept string + subtest_autodetect_language :en_au, 'monkey', nil, 'de,EN-Au' + # remove dialect + subtest_autodetect_language :en, nil, 'en-bullshit', nil + subtest_autodetect_language :en, 'monkey', nil, 'de,EN-NZ,ja' + # different dialect + subtest_autodetect_language :ZH_HK, 'zh', nil, 'de,EN-NZ,ja' + subtest_autodetect_language :ZH_HK, 'monkey', 'zh', 'de,EN-NZ,ja' + + # Check param/cookie names use defaults + GLoc::CONFIG[:default_param_name] = 'p_lang' + GLoc::CONFIG[:default_cookie_name] = 'c_lang' + # :check_params + subtest_autodetect_language :def, 'en_au', nil, nil + subtest_autodetect_language :en_au, {:p_lang => 'en_au'}, nil, nil + # :check_cookie + subtest_autodetect_language :def, nil, 'en_us', nil + subtest_autodetect_language :en_US, nil, {:c_lang => 'en_us'}, nil + GLoc::CONFIG[:default_param_name] = 'plang' + GLoc::CONFIG[:default_cookie_name] = 'clang' + + # autodetect_language_filter :only => :auto2, :check_accept_header => false, :check_params => 'xx' + subtest_autodetect_language :def, 'ja', nil, 'en_US', :auto2 + subtest_autodetect_language :Ja, {:xx => 'ja'}, nil, 'en_US', :auto2 + subtest_autodetect_language :en_au, 'ja', 'en_au', 'en_US', :auto2 + + # autodetect_language_filter :only => :auto3, :check_cookie => false + subtest_autodetect_language :Ja, 'ja', 'en_us', 'qwe_ja,zh,monkey_en;q=0.5', :auto3 + subtest_autodetect_language :ZH_HK, 'hehe', 'en_us', 'qwe_ja,zh,monkey_en;q=0.5', :auto3 + + # autodetect_language_filter :only => :auto4, :check_cookie => 'qwe', :check_params => false + subtest_autodetect_language :def, 'ja', 'en_us', nil, :auto4 + subtest_autodetect_language :ZH_HK, 'ja', 'en_us', 'qwe_ja,zh,monkey_en;q=0.5', :auto4 + subtest_autodetect_language :en_US, 'ja', {:qwe => 'en_us'}, 'ja', :auto4 + end + + def subtest_autodetect_language(expected,params,cookie,accept, action=:auto) + begin_new_request + params= {'plang' => params} if params.is_a?(String) + params ||= {} + if cookie + cookie={'clang' => cookie} unless cookie.is_a?(Hash) + cookie.each_pair {|k,v| @request.cookies[k.to_s]= CGI::Cookie.new(k.to_s,v)} + end + @request.env['HTTP_ACCEPT_LANGUAGE']= accept + get action, params + assert_equal expected, @controller.current_language + if action == :auto + s,b = expected != :def ? [1,nil] : [nil,1] + assert_equal s, @controller.callback_set + assert_equal b, @controller.callback_bad + end + end + +end \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/gloc_test.rb b/vendor/plugins/gloc-1.1.0/test/gloc_test.rb new file mode 100644 index 000000000..a39d5c41c --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/gloc_test.rb @@ -0,0 +1,433 @@ +# Copyright (c) 2005-2006 David Barri + +$LOAD_PATH.push File.join(File.dirname(__FILE__),'..','lib') +require 'gloc' +require 'gloc-ruby' +require 'gloc-config' +require 'gloc-rails-text' +require File.join(File.dirname(__FILE__),'lib','rails-time_ext') unless 3.respond_to?(:days) +require File.join(File.dirname(__FILE__),'lib','rails-string_ext') unless ''.respond_to?(:starts_with?) +#require 'gloc-dev' + +class LClass; include GLoc; end +class LClass2 < LClass; end +class LClass_en < LClass2; set_language :en; end +class LClass_ja < LClass2; set_language :ja; end +# class LClass_forced_au < LClass; set_language :en; force_language :en_AU; set_language :ja; end + +class GLocTest < Test::Unit::TestCase + include GLoc + include ActionView::Helpers::DateHelper + + def setup + @l1 = LClass.new + @l2 = LClass.new + @l3 = LClass.new + @l1.set_language :ja + @l2.set_language :en + @l3.set_language 'en_AU' + @gloc_state= GLoc.backup_state true + GLoc::CONFIG.merge!({ + :default_param_name => 'lang', + :default_cookie_name => 'lang', + :default_language => :ja, + :raise_string_not_found_errors => true, + :verbose => false, + }) + end + + def teardown + GLoc.restore_state @gloc_state + end + + #--------------------------------------------------------------------------- + + def test_basic + assert_localized_value [nil, @l1, @l2, @l3], nil, :in_both_langs + + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + + assert_localized_value [nil, @l1], 'enにもjaにもある', :in_both_langs + assert_localized_value [nil, @l1], '日本語のみ', :ja_only + assert_localized_value [nil, @l1], nil, :en_only + + assert_localized_value @l2, 'This is in en+ja', :in_both_langs + assert_localized_value @l2, nil, :ja_only + assert_localized_value @l2, 'English only', :en_only + + assert_localized_value @l3, "Thiz in en 'n' ja", :in_both_langs + assert_localized_value @l3, nil, :ja_only + assert_localized_value @l3, 'Aussie English only bro', :en_only + + @l3.set_language :en + assert_localized_value @l3, 'This is in en+ja', :in_both_langs + assert_localized_value @l3, nil, :ja_only + assert_localized_value @l3, 'English only', :en_only + + assert_localized_value nil, 'enにもjaにもある', :in_both_langs + assert_localized_value nil, '日本語のみ', :ja_only + assert_localized_value nil, nil, :en_only + end + + def test_load_twice_with_override + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang2') + + assert_localized_value [nil, @l1], '更新された', :in_both_langs + assert_localized_value [nil, @l1], '日本語のみ', :ja_only + assert_localized_value [nil, @l1], nil, :en_only + assert_localized_value [nil, @l1], nil, :new_en + assert_localized_value [nil, @l1], '新たな日本語ストリング', :new_ja + + assert_localized_value @l2, 'This is in en+ja', :in_both_langs + assert_localized_value @l2, nil, :ja_only + assert_localized_value @l2, 'overriden dude', :en_only + assert_localized_value @l2, 'This is a new English string', :new_en + assert_localized_value @l2, nil, :new_ja + + assert_localized_value @l3, "Thiz in en 'n' ja", :in_both_langs + assert_localized_value @l3, nil, :ja_only + assert_localized_value @l3, 'Aussie English only bro', :en_only + end + + def test_load_twice_without_override + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang2'), false + + assert_localized_value [nil, @l1], 'enにもjaにもある', :in_both_langs + assert_localized_value [nil, @l1], '日本語のみ', :ja_only + assert_localized_value [nil, @l1], nil, :en_only + assert_localized_value [nil, @l1], nil, :new_en + assert_localized_value [nil, @l1], '新たな日本語ストリング', :new_ja + + assert_localized_value @l2, 'This is in en+ja', :in_both_langs + assert_localized_value @l2, nil, :ja_only + assert_localized_value @l2, 'English only', :en_only + assert_localized_value @l2, 'This is a new English string', :new_en + assert_localized_value @l2, nil, :new_ja + + assert_localized_value @l3, "Thiz in en 'n' ja", :in_both_langs + assert_localized_value @l3, nil, :ja_only + assert_localized_value @l3, 'Aussie English only bro', :en_only + end + + def test_add_localized_strings + assert_localized_value nil, nil, :add + assert_localized_value nil, nil, :ja_only + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + assert_localized_value nil, nil, :add + assert_localized_value nil, '日本語のみ', :ja_only + GLoc.add_localized_strings 'en', {:ja_only => 'bullshit'}, true + GLoc.add_localized_strings 'en', {:ja_only => 'bullshit'}, false + assert_localized_value nil, nil, :add + assert_localized_value nil, '日本語のみ', :ja_only + GLoc.add_localized_strings 'ja', {:ja_only => 'bullshit', :add => '123'}, false + assert_localized_value nil, '123', :add + assert_localized_value nil, '日本語のみ', :ja_only + GLoc.add_localized_strings 'ja', {:ja_only => 'bullshit', :add => '234'} + assert_localized_value nil, '234', :add + assert_localized_value nil, 'bullshit', :ja_only + end + + def test_class_set_language + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + + @l1 = LClass_ja.new + @l2 = LClass_en.new + @l3 = LClass_en.new + + assert_localized_value @l1, 'enにもjaにもある', :in_both_langs + assert_localized_value @l2, 'This is in en+ja', :in_both_langs + assert_localized_value @l3, 'This is in en+ja', :in_both_langs + + @l3.set_language 'en_AU' + + assert_localized_value @l1, 'enにもjaにもある', :in_both_langs + assert_localized_value @l2, 'This is in en+ja', :in_both_langs + assert_localized_value @l3, "Thiz in en 'n' ja", :in_both_langs + end + + def test_ll + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + + assert_equal 'enにもjaにもある', ll('ja',:in_both_langs) + assert_equal 'enにもjaにもある', GLoc::ll('ja',:in_both_langs) + assert_equal 'enにもjaにもある', LClass_en.ll('ja',:in_both_langs) + assert_equal 'enにもjaにもある', LClass_ja.ll('ja',:in_both_langs) + + assert_equal 'This is in en+ja', ll('en',:in_both_langs) + assert_equal 'This is in en+ja', GLoc::ll('en',:in_both_langs) + assert_equal 'This is in en+ja', LClass_en.ll('en',:in_both_langs) + assert_equal 'This is in en+ja', LClass_ja.ll('en',:in_both_langs) + end + + def test_lsym + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'lang') + assert_equal 'enにもjaにもある', LClass_ja.ltry(:in_both_langs) + assert_equal 'hello', LClass_ja.ltry('hello') + assert_equal nil, LClass_ja.ltry(nil) + end + +# def test_forced +# assert_equal :en_AU, LClass_forced_au.current_language +# a= LClass_forced_au.new +# a.set_language :ja +# assert_equal :en_AU, a.current_language +# a.force_language :ja +# assert_equal :ja, a.current_language +# assert_equal :en_AU, LClass_forced_au.current_language +# end + + def test_pluralization + GLoc.add_localized_strings :en, :_gloc_rule_default => %[|n| case n; when 0 then '_none'; when 1 then '_single'; else '_many'; end], :a_single => '%d man', :a_many => '%d men', :a_none => 'No men' + GLoc.add_localized_strings :en, :_gloc_rule_asd => %[|n| n<10 ? '_few' : '_heaps'], :a_few => 'a few men (%d)', :a_heaps=> 'soo many men' + set_language :en + + assert_equal 'No men', lwr(:a, 0) + assert_equal '1 man', lwr(:a, 1) + assert_equal '3 men', lwr(:a, 3) + assert_equal '20 men', lwr(:a, 20) + + assert_equal 'a few men (0)', lwr_(:asd, :a, 0) + assert_equal 'a few men (1)', lwr_(:asd, :a, 1) + assert_equal 'a few men (3)', lwr_(:asd, :a, 3) + assert_equal 'soo many men', lwr_(:asd, :a, 12) + assert_equal 'soo many men', lwr_(:asd, :a, 20) + + end + + def test_distance_in_words + load_default_strings + [ + [20.seconds, 'less than a minute', '1分以内', 'меньше минуты'], + [80.seconds, '1 minute', '1分', '1 минуту'], + [3.seconds, 'less than 5 seconds', '5秒以内', 'менее 5 секунд', true], + [9.seconds, 'less than 10 seconds', '10秒以内', 'менее 10 секунд', true], + [16.seconds, 'less than 20 seconds', '20秒以内', 'менее 20 секунд', true], + [35.seconds, 'half a minute', '約30秒', 'полминуты', true], + [50.seconds, 'less than a minute', '1分以内', 'меньше минуты', true], + [1.1.minutes, '1 minute', '1分', '1 минуту'], + [2.1.minutes, '2 minutes', '2分', '2 минуты'], + [4.1.minutes, '4 minutes', '4分', '4 минуты'], + [5.1.minutes, '5 minutes', '5分', '5 минут'], + [1.1.hours, 'about an hour', '約1時間', 'около часа'], + [3.1.hours, 'about 3 hours', '約3時間', 'около 3 часов'], + [9.1.hours, 'about 9 hours', '約9時間', 'около 9 часов'], + [1.1.days, '1 day', '1日間', '1 день'], + [2.1.days, '2 days', '2日間', '2 дня'], + [4.days, '4 days', '4日間', '4 дня'], + [6.days, '6 days', '6日間', '6 дней'], + [11.days, '11 days', '11日間', '11 дней'], + [12.days, '12 days', '12日間', '12 дней'], + [15.days, '15 days', '15日間', '15 дней'], + [20.days, '20 days', '20日間', '20 дней'], + [21.days, '21 days', '21日間', '21 день'], + [22.days, '22 days', '22日間', '22 дня'], + [25.days, '25 days', '25日間', '25 дней'], + ].each do |a| + t, en, ja, ru = a + inc_sec= (a.size == 5) ? a[-1] : false + set_language :en + assert_equal en, distance_of_time_in_words(t,0,inc_sec) + set_language :ja + assert_equal ja, distance_of_time_in_words(t,0,inc_sec) + set_language :ru + assert_equal ru, distance_of_time_in_words(t,0,inc_sec) + end + end + + def test_age + load_default_strings + [ + [1, '1 yr', '1歳', '1 год'], + [22, '22 yrs', '22歳', '22 года'], + [27, '27 yrs', '27歳', '27 лет'], + ].each do |a, en, ja, ru| + set_language :en + assert_equal en, l_age(a) + set_language :ja + assert_equal ja, l_age(a) + set_language :ru + assert_equal ru, l_age(a) + end + end + + def test_yesno + load_default_strings + set_language :en + assert_equal 'yes', l_yesno(true) + assert_equal 'no', l_yesno(false) + assert_equal 'Yes', l_YesNo(true) + assert_equal 'No', l_YesNo(false) + end + + def test_all_languages_have_values_for_helpers + load_default_strings + t= Time.local(2000, 9, 15, 11, 23, 57) + GLoc.valid_languages.each {|l| + set_language l + 0.upto(120) {|n| l_age(n)} + l_date(t) + l_datetime(t) + l_datetime_short(t) + l_time(t) + [true,false].each{|v| l_YesNo(v); l_yesno(v) } + } + end + + def test_similar_languages + GLoc.add_localized_strings :en, :a => 'a' + GLoc.add_localized_strings :en_AU, :a => 'a' + GLoc.add_localized_strings :ja, :a => 'a' + GLoc.add_localized_strings :zh_tw, :a => 'a' + + assert_equal :en, GLoc.similar_language(:en) + assert_equal :en, GLoc.similar_language('en') + assert_equal :ja, GLoc.similar_language(:ja) + assert_equal :ja, GLoc.similar_language('ja') + # lowercase + dashes to underscores + assert_equal :en, GLoc.similar_language('EN') + assert_equal :en, GLoc.similar_language(:EN) + assert_equal :en_AU, GLoc.similar_language(:EN_Au) + assert_equal :en_AU, GLoc.similar_language('eN-Au') + # remove dialect + assert_equal :ja, GLoc.similar_language(:ja_Au) + assert_equal :ja, GLoc.similar_language('JA-ASDF') + assert_equal :ja, GLoc.similar_language('jA_ASD_ZXC') + # different dialect + assert_equal :zh_tw, GLoc.similar_language('ZH') + assert_equal :zh_tw, GLoc.similar_language('ZH_HK') + assert_equal :zh_tw, GLoc.similar_language('ZH-BUL') + # non matching + assert_equal nil, GLoc.similar_language('WW') + assert_equal nil, GLoc.similar_language('WW_AU') + assert_equal nil, GLoc.similar_language('WW-AU') + assert_equal nil, GLoc.similar_language('eZ_en') + assert_equal nil, GLoc.similar_language('AU-ZH') + end + + def test_clear_strings_and_similar_langs + GLoc.add_localized_strings :en, :a => 'a' + GLoc.add_localized_strings :en_AU, :a => 'a' + GLoc.add_localized_strings :ja, :a => 'a' + GLoc.add_localized_strings :zh_tw, :a => 'a' + GLoc.clear_strings :en, :ja + assert_equal nil, GLoc.similar_language('ja') + assert_equal :en_AU, GLoc.similar_language('en') + assert_equal :zh_tw, GLoc.similar_language('ZH_HK') + GLoc.clear_strings + assert_equal nil, GLoc.similar_language('ZH_HK') + end + + def test_lang_name + GLoc.add_localized_strings :en, :general_lang_en => 'English', :general_lang_ja => 'Japanese' + GLoc.add_localized_strings :ja, :general_lang_en => '英語', :general_lang_ja => '日本語' + set_language :en + assert_equal 'Japanese', l_lang_name(:ja) + assert_equal 'English', l_lang_name('en') + set_language :ja + assert_equal '日本語', l_lang_name('ja') + assert_equal '英語', l_lang_name(:en) + end + + def test_charset_change_all + load_default_strings + GLoc.add_localized_strings :ja2, :a => 'a' + GLoc.valid_languages # Force refresh if in dev mode + GLoc.class_eval 'LOCALIZED_STRINGS[:ja2]= LOCALIZED_STRINGS[:ja].clone' + + [:ja, :ja2].each do |l| + set_language l + assert_equal 'はい', l_yesno(true) + assert_equal "E381AFE38184", l_yesno(true).unpack('H*')[0].upcase + end + + GLoc.set_charset 'sjis' + assert_equal 'sjis', GLoc.get_charset(:ja) + assert_equal 'sjis', GLoc.get_charset(:ja2) + + [:ja, :ja2].each do |l| + set_language l + assert_equal "82CD82A2", l_yesno(true).unpack('H*')[0].upcase + end + end + + def test_charset_change_single + load_default_strings + GLoc.add_localized_strings :ja2, :a => 'a' + GLoc.add_localized_strings :ja3, :a => 'a' + GLoc.valid_languages # Force refresh if in dev mode + GLoc.class_eval 'LOCALIZED_STRINGS[:ja2]= LOCALIZED_STRINGS[:ja].clone' + GLoc.class_eval 'LOCALIZED_STRINGS[:ja3]= LOCALIZED_STRINGS[:ja].clone' + + [:ja, :ja2, :ja3].each do |l| + set_language l + assert_equal 'はい', l_yesno(true) + assert_equal "E381AFE38184", l_yesno(true).unpack('H*')[0].upcase + end + + GLoc.set_charset 'sjis', :ja + assert_equal 'sjis', GLoc.get_charset(:ja) + assert_equal 'utf-8', GLoc.get_charset(:ja2) + assert_equal 'utf-8', GLoc.get_charset(:ja3) + + set_language :ja + assert_equal "82CD82A2", l_yesno(true).unpack('H*')[0].upcase + set_language :ja2 + assert_equal "E381AFE38184", l_yesno(true).unpack('H*')[0].upcase + set_language :ja3 + assert_equal "E381AFE38184", l_yesno(true).unpack('H*')[0].upcase + + GLoc.set_charset 'euc-jp', :ja, :ja3 + assert_equal 'euc-jp', GLoc.get_charset(:ja) + assert_equal 'utf-8', GLoc.get_charset(:ja2) + assert_equal 'euc-jp', GLoc.get_charset(:ja3) + + set_language :ja + assert_equal "A4CFA4A4", l_yesno(true).unpack('H*')[0].upcase + set_language :ja2 + assert_equal "E381AFE38184", l_yesno(true).unpack('H*')[0].upcase + set_language :ja3 + assert_equal "A4CFA4A4", l_yesno(true).unpack('H*')[0].upcase + end + + def test_set_language_if_valid + GLoc.add_localized_strings :en, :a => 'a' + GLoc.add_localized_strings :zh_tw, :a => 'a' + + assert set_language_if_valid('en') + assert_equal :en, current_language + + assert set_language_if_valid('zh_tw') + assert_equal :zh_tw, current_language + + assert !set_language_if_valid(nil) + assert_equal :zh_tw, current_language + + assert !set_language_if_valid('ja') + assert_equal :zh_tw, current_language + + assert set_language_if_valid(:en) + assert_equal :en, current_language + end + + #=========================================================================== + protected + + def assert_localized_value(objects,expected,key) + objects = [objects] unless objects.kind_of?(Array) + objects.each {|object| + o = object || GLoc + assert_equal !expected.nil?, o.l_has_string?(key) + if expected.nil? + assert_raise(GLoc::StringNotFoundError) {o.l(key)} + else + assert_equal expected, o.l(key) + end + } + end + + def load_default_strings + GLoc.load_localized_strings File.join(File.dirname(__FILE__),'..','lang') + end +end \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lang/en.yaml b/vendor/plugins/gloc-1.1.0/test/lang/en.yaml new file mode 100644 index 000000000..325dc599e --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lang/en.yaml @@ -0,0 +1,2 @@ +in_both_langs: This is in en+ja +en_only: English only \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lang/en_AU.yaml b/vendor/plugins/gloc-1.1.0/test/lang/en_AU.yaml new file mode 100644 index 000000000..307cc7859 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lang/en_AU.yaml @@ -0,0 +1,2 @@ +in_both_langs: Thiz in en 'n' ja +en_only: Aussie English only bro \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lang/ja.yml b/vendor/plugins/gloc-1.1.0/test/lang/ja.yml new file mode 100644 index 000000000..64df03376 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lang/ja.yml @@ -0,0 +1,2 @@ +in_both_langs: enにもjaにもある +ja_only: 日本語のみ \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lang2/en.yml b/vendor/plugins/gloc-1.1.0/test/lang2/en.yml new file mode 100644 index 000000000..e6467e7a0 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lang2/en.yml @@ -0,0 +1,2 @@ +en_only: overriden dude +new_en: This is a new English string \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lang2/ja.yaml b/vendor/plugins/gloc-1.1.0/test/lang2/ja.yaml new file mode 100644 index 000000000..864b287d0 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lang2/ja.yaml @@ -0,0 +1,2 @@ +in_both_langs: 更新された +new_ja: 新たな日本語ストリング \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lib/rails-string_ext.rb b/vendor/plugins/gloc-1.1.0/test/lib/rails-string_ext.rb new file mode 100644 index 000000000..418d28db2 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lib/rails-string_ext.rb @@ -0,0 +1,23 @@ +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Additional string tests. + module StartsEndsWith + # Does the string start with the specified +prefix+? + def starts_with?(prefix) + prefix = prefix.to_s + self[0, prefix.length] == prefix + end + + # Does the string end with the specified +suffix+? + def ends_with?(suffix) + suffix = suffix.to_s + self[-suffix.length, suffix.length] == suffix + end + end + end + end +end +class String + include ActiveSupport::CoreExtensions::String::StartsEndsWith +end \ No newline at end of file diff --git a/vendor/plugins/gloc-1.1.0/test/lib/rails-time_ext.rb b/vendor/plugins/gloc-1.1.0/test/lib/rails-time_ext.rb new file mode 100644 index 000000000..d8771e4e6 --- /dev/null +++ b/vendor/plugins/gloc-1.1.0/test/lib/rails-time_ext.rb @@ -0,0 +1,76 @@ +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Numeric #:nodoc: + # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years. + # + # If you need precise date calculations that doesn't just treat months as 30 days, then have + # a look at Time#advance. + # + # Some of these methods are approximations, Ruby's core + # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and + # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision + # date and time arithmetic + module Time + def seconds + self + end + alias :second :seconds + + def minutes + self * 60 + end + alias :minute :minutes + + def hours + self * 60.minutes + end + alias :hour :hours + + def days + self * 24.hours + end + alias :day :days + + def weeks + self * 7.days + end + alias :week :weeks + + def fortnights + self * 2.weeks + end + alias :fortnight :fortnights + + def months + self * 30.days + end + alias :month :months + + def years + (self * 365.25.days).to_i + end + alias :year :years + + # Reads best without arguments: 10.minutes.ago + def ago(time = ::Time.now) + time - self + end + + # Reads best with argument: 10.minutes.until(time) + alias :until :ago + + # Reads best with argument: 10.minutes.since(time) + def since(time = ::Time.now) + time + self + end + + # Reads best without arguments: 10.minutes.from_now + alias :from_now :since + end + end + end +end + +class Numeric #:nodoc: + include ActiveSupport::CoreExtensions::Numeric::Time +end diff --git a/vendor/plugins/rfpdf/CHANGELOG b/vendor/plugins/rfpdf/CHANGELOG new file mode 100644 index 000000000..6822b8364 --- /dev/null +++ b/vendor/plugins/rfpdf/CHANGELOG @@ -0,0 +1,13 @@ +1.00 Added view template functionality +1.10 Added Chinese support +1.11 Added Japanese support +1.12 Added Korean support +1.13 Updated to fpdf.rb 1.53d. + Added makefont and fpdf_eps. + Handle \n at the beginning of a string in MultiCell. + Tried to fix clipping issue in MultiCell - still needs some work. +1.14 2006-09-26 +* Added support for @options_for_rfpdf hash for configuration: + * Added :filename option in this hash +If you're using the same settings for @options_for_rfpdf often, you might want to +put your assignment in a before_filter (perhaps overriding :filename, etc in your actions). diff --git a/vendor/plugins/rfpdf/MIT-LICENSE b/vendor/plugins/rfpdf/MIT-LICENSE new file mode 100644 index 000000000..f39a79dc0 --- /dev/null +++ b/vendor/plugins/rfpdf/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2006 4ssoM LLC + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND +NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/plugins/rfpdf/README b/vendor/plugins/rfpdf/README new file mode 100644 index 000000000..9db19075b --- /dev/null +++ b/vendor/plugins/rfpdf/README @@ -0,0 +1,99 @@ += RFPDF Template Plugin + +A template plugin allowing the inclusion of ERB-enabled RFPDF template files. + +== Example .rb method Usage + +In the controller, something like: + + def mypdf + pdf = FPDF.new() + + # + # Chinese + # + pdf.extend(PDF_Chinese) + pdf.AddPage + pdf.AddBig5Font + pdf.SetFont('Big5','',18) + pdf.Write(5, '²{®É®ð·Å 18 C Àã«× 83 %') + icBig5 = Iconv.new('Big5', 'UTF-8') + pdf.Write(15, icBig5.iconv("宋体 should be working")) + send_data pdf.Output, :filename => "something.pdf", :type => "application/pdf" + end + +== Example .rfdf Usage + +In the controller, something like: + + def mypdf + @options_for_rfpdf ||= {} + @options_for_rfpdf[:file_name] = "nice_looking.pdf" + end + +In the layout (make sure this is the only item in the layout): +<%= @content_for_layout %> + +In the view (mypdf.rfpdf): + +<% + pdf = FPDF.new() + # + # Chinese + # + pdf.extend(PDF_Chinese) + pdf.AddPage + pdf.AddBig5Font + pdf.SetFont('Big5','',18) + pdf.Write(5, '²{®É®ð·Å 18 C Àã«× 83 %') + icBig5 = Iconv.new('Big5', 'UTF-8') + pdf.Write(15, icBig5.iconv("宋体 should be working")) + + # + # Japanese + # + pdf.extend(PDF_Japanese) + pdf.AddSJISFont(); + pdf.AddPage(); + pdf.SetFont('SJIS','',18); + pdf.Write(5,'9ÉñåéÇÃåˆäJÉeÉXÉgÇåoǃPHP 3.0ÇÕ1998îN6åéÇ…åˆéÆÇ…ÉäÉäÅ[ÉXÇ≥ÇÍNjǵÇΩÅB'); + icSJIS = Iconv.new('SJIS', 'UTF-8') + pdf.Write(15, icSJIS.iconv("これはテキストである should be working")) + + # + # Korean + # + pdf.extend(PDF_Korean) + pdf.AddUHCFont(); + pdf.AddPage(); + pdf.SetFont('UHC','',18); + pdf.Write(5,'PHP 3.0Àº 1998³â 6¿ù¿¡ °ø½ÄÀûÀ¸·Î ¸±¸®ÁîµÇ¾ú´Ù. °ø°³ÀûÀÎ Å×½ºÆ® ÀÌÈľà 9°³¿ù¸¸À̾ú´Ù.'); + icUHC = Iconv.new('UHC', 'UTF-8') + pdf.Write(15, icUHC.iconv("이것은 원본 이다")) + + # + # English + # + pdf.AddPage(); + pdf.SetFont('Arial', '', 10) + pdf.Write(5, "should be working") +%> +<%= pdf.Output() %> + + +== Configuring + +You can configure Rfpdf by using an @options_for_rfpdf hash in your controllers. + +Here are a few options: + +:filename (default: action_name.pdf) + Filename of PDF to generate + +Note: If you're using the same settings for @options_for_rfpdf often, you might want to +put your assignment in a before_filter (perhaps overriding :filename, etc in your actions). + +== Problems + +Layouts and partials are currently not supported; just need +to wrap the PDF generation differently. diff --git a/vendor/plugins/rfpdf/init.rb b/vendor/plugins/rfpdf/init.rb new file mode 100644 index 000000000..7e51d9eba --- /dev/null +++ b/vendor/plugins/rfpdf/init.rb @@ -0,0 +1,3 @@ +require 'rfpdf' + +ActionView::Base::register_template_handler 'rfpdf', RFPDF::View \ No newline at end of file diff --git a/vendor/plugins/rfpdf/lib/rfpdf.rb b/vendor/plugins/rfpdf/lib/rfpdf.rb new file mode 100644 index 000000000..9fc0683ef --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf.rb @@ -0,0 +1,31 @@ +# Copyright (c) 2006 4ssoM LLC +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +$LOAD_PATH.unshift(File.dirname(__FILE__)) + +require 'rfpdf/errors' +require 'rfpdf/view' +require 'rfpdf/fpdf' +require 'rfpdf/rfpdf' +require 'rfpdf/chinese' +require 'rfpdf/japanese' +require 'rfpdf/korean' diff --git a/vendor/plugins/rfpdf/lib/rfpdf/bookmark.rb b/vendor/plugins/rfpdf/lib/rfpdf/bookmark.rb new file mode 100644 index 000000000..a04ccd18d --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/bookmark.rb @@ -0,0 +1,99 @@ +# Translation of the bookmark class from the PHP FPDF script from Olivier Plathey +# Translated by Sylvain Lafleur and ?? with the help of Brian Ollenberger +# +# First added in 1.53b +# +# Usage is as follows: +# +# require 'fpdf' +# require 'bookmark' +# pdf = FPDF.new +# pdf.extend(PDF_Bookmark) +# +# This allows it to be combined with other extensions, such as the Chinese +# module. + +module PDF_Bookmark + def PDF_Bookmark.extend_object(o) + o.instance_eval('@outlines,@OutlineRoot=[],0') + super(o) + end + + def Bookmark(txt,level=0,y=0) + y=self.GetY() if y==-1 + @outlines.push({'t'=>txt,'l'=>level,'y'=>y,'p'=>self.PageNo()}) + end + + def putbookmarks + @nb=@outlines.size + return if @nb==0 + lru=[] + level=0 + @outlines.each_index do |i| + o=@outlines[i] + if o['l']>0 + parent=lru[o['l']-1] + # Set parent and last pointers + @outlines[i]['parent']=parent + @outlines[parent]['last']=i + if o['l']>level + # Level increasing: set first pointer + @outlines[parent]['first']=i + end + else + @outlines[i]['parent']=@nb + end + if o['l']<=level and i>0 + # Set prev and next pointers + prev=lru[o['l']] + @outlines[prev]['next']=i + @outlines[i]['prev']=prev + end + lru[o['l']]=i + level=o['l'] + end + # Outline items + n=@n+1 + @outlines.each_index do |i| + o=@outlines[i] + newobj + out('<>') + out('endobj') + end + # Outline root + newobj + @OutlineRoot=@n + out('<>') + out('endobj') + end + + def putresources + super + putbookmarks + end + + def putcatalog + super + if not @outlines.empty? + out('/Outlines '+@OutlineRoot.to_s+' 0 R') + out('/PageMode /UseOutlines') + end + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/chinese.rb b/vendor/plugins/rfpdf/lib/rfpdf/chinese.rb new file mode 100644 index 000000000..731d582a2 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/chinese.rb @@ -0,0 +1,473 @@ +# Copyright (c) 2006 4ssoM LLC +# 1.12 contributed by Ed Moss. +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# This is direct port of chinese.php +# +# Chinese PDF support. +# +# Usage is as follows: +# +# require 'fpdf' +# require 'chinese' +# pdf = FPDF.new +# pdf.extend(PDF_Chinese) +# +# This allows it to be combined with other extensions, such as the bookmark +# module. + +module PDF_Chinese + + Big5_widths={' '=>250,'!'=>250,'"'=>408,'#'=>668,''=>490,'%'=>875,'&'=>698,'\''=>250, + '('=>240,')'=>240,'*'=>417,'+'=>667,','=>250,'-'=>313,'.'=>250,'/'=>520,'0'=>500,'1'=>500, + '2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>250,''=>250, + '<'=>667,'='=>667,'>'=>667,'?'=>396,'@'=>921,'A'=>677,'B'=>615,'C'=>719,'D'=>760,'E'=>625, + 'F'=>552,'G'=>771,'H'=>802,'I'=>354,'J'=>354,'K'=>781,'L'=>604,'M'=>927,'N'=>750,'O'=>823, + 'P'=>563,'Q'=>823,'R'=>729,'S'=>542,'T'=>698,'U'=>771,'V'=>729,'W'=>948,'X'=>771,'Y'=>677, + 'Z'=>635,'['=>344,'\\'=>520,']'=>344,'^'=>469,'_'=>500,'`'=>250,'a'=>469,'b'=>521,'c'=>427, + 'd'=>521,'e'=>438,'f'=>271,'g'=>469,'h'=>531,'i'=>250,'j'=>250,'k'=>458,'l'=>240,'m'=>802, + 'n'=>531,'o'=>500,'p'=>521,'q'=>521,'r'=>365,'s'=>333,'t'=>292,'u'=>521,'v'=>458,'w'=>677, + 'x'=>479,'y'=>458,'z'=>427,'{'=>480,'|'=>496,'end'=>480,'~'=>667} + + GB_widths={' '=>207,'!'=>270,'"'=>342,'#'=>467,''=>462,'%'=>797,'&'=>710,'\''=>239, + '('=>374,')'=>374,'*'=>423,'+'=>605,','=>238,'-'=>375,'.'=>238,'/'=>334,'0'=>462,'1'=>462, + '2'=>462,'3'=>462,'4'=>462,'5'=>462,'6'=>462,'7'=>462,'8'=>462,'9'=>462,':'=>238,''=>238, + '<'=>605,'='=>605,'>'=>605,'?'=>344,'@'=>748,'A'=>684,'B'=>560,'C'=>695,'D'=>739,'E'=>563, + 'F'=>511,'G'=>729,'H'=>793,'I'=>318,'J'=>312,'K'=>666,'L'=>526,'M'=>896,'N'=>758,'O'=>772, + 'P'=>544,'Q'=>772,'R'=>628,'S'=>465,'T'=>607,'U'=>753,'V'=>711,'W'=>972,'X'=>647,'Y'=>620, + 'Z'=>607,'['=>374,'\\'=>333,']'=>374,'^'=>606,'_'=>500,'`'=>239,'a'=>417,'b'=>503,'c'=>427, + 'd'=>529,'e'=>415,'f'=>264,'g'=>444,'h'=>518,'i'=>241,'j'=>230,'k'=>495,'l'=>228,'m'=>793, + 'n'=>527,'o'=>524,'p'=>524,'q'=>504,'r'=>338,'s'=>336,'t'=>277,'u'=>517,'v'=>450,'w'=>652, + 'x'=>466,'y'=>452,'z'=>407,'{'=>370,'|'=>258,'end'=>370,'~'=>605} + + def AddCIDFont(family,style,name,cw,cMap,registry) +#ActionController::Base::logger.debug registry.to_a.join(":").to_s + fontkey=family.downcase+style.upcase + unless @fonts[fontkey].nil? + Error("Font already added: family style") + end + i=@fonts.length+1 + name=name.gsub(' ','') + @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, 'CMap'=>cMap,'registry'=>registry} + end + + def AddCIDFonts(family,name,cw,cMap,registry) + AddCIDFont(family,'',name,cw,cMap,registry) + AddCIDFont(family,'B',name+',Bold',cw,cMap,registry) + AddCIDFont(family,'I',name+',Italic',cw,cMap,registry) + AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry) + end + + def AddBig5Font(family='Big5',name='MSungStd-Light-Acro') + #Add Big5 font with proportional Latin + cw=Big5_widths + cMap='ETenms-B5-H' + registry={'ordering'=>'CNS1','supplement'=>0} +#ActionController::Base::logger.debug registry.to_a.join(":").to_s + AddCIDFonts(family,name,cw,cMap,registry) + end + + def AddBig5hwFont(family='Big5-hw',name='MSungStd-Light-Acro') + #Add Big5 font with half-witdh Latin + cw = {} + 32.upto(126) do |i| + cw[i.chr]=500 + end + cMap='ETen-B5-H' + registry={'ordering'=>'CNS1','supplement'=>0} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def AddGBFont(family='GB',name='STSongStd-Light-Acro') + #Add GB font with proportional Latin + cw=GB_widths + cMap='GBKp-EUC-H' + registry={'ordering'=>'GB1','supplement'=>2} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def AddGBhwFont(family='GB-hw',name='STSongStd-Light-Acro') + #Add GB font with half-width Latin + 32.upto(126) do |i| + cw[i.chr]=500 + end + cMap='GBK-EUC-H' + registry={'ordering'=>'GB1','supplement'=>2} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def GetStringWidth(s) + if(@CurrentFont['type']=='Type0') + return GetMBStringWidth(s) + else + return super(s) + end + end + + def GetMBStringWidth(s) + #Multi-byte version of GetStringWidth() + l=0 + cw=@CurrentFont['cw'] + nb=s.length + i=0 + while(i0 and s[nb-1]=="\n") + nb-=1 + end + b=0 + if(border) + if(border==1) + border='LTRB' + b='LRT' + b2='LR' + else + b2='' + if(border.index('L').nil?) + b2+='L' + end + if(border.index('R').nil?) + b2+='R' + end + b=border.index('T').nil? ? b2+'T' : b2 + end + end + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(iwmax) + #Automatic line break + if(sep==-1 or i==j) + if(i==j) + i+=ascii ? 1 : 2 + end + Cell(w,h,s[j,i-j],b,2,align,fill) + else + Cell(w,h,s[j,sep-j],b,2,align,fill) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 +# nl+=1 + if(border and nl==2) + b=b2 + end + else + i+=ascii ? 1 : 2 + end + end + #Last chunk + if(border and not border.index('B').nil?) + b+='B' + end + Cell(w,h,s[j,i-j],b,2,align,fill) + @x=@lMargin + end + + def Write(h,txt,link='') + if(@CurrentFont['type']=='Type0') + MBWrite(h,txt,link) + else + super(h,txt,link) + end + end + + def MBWrite(h,txt,link) + #Multi-byte version of Write() + cw=@CurrentFont['cw'] + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub("\r",'') + nb=s.length + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(iwmax) + #Automatic line break + if(sep==-1 or i==j) + if(@x>@lMargin) + #Move to next line + @x=@lMargin + @y+=h + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + i+=1 + nl+=1 + next + end + if(i==j) + i+=ascii ? 1 : 2 + end + Cell(w,h,s[j,i-j],0,2,'',0,link) + else + Cell(w,h,s[j,sep-j],0,2,'',0,link) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 + if(nl==1) + @x=@lMargin + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + end + nl+=1 + else + i+=ascii ? 1 : 2 + end + end + #Last chunk + if(i!=j) + Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link) + end + end + +private + + def putfonts() + nf=@n + @diffs.each do |diff| + #Encodings + newobj() + out('<>') + out('endobj') + end + # mqr=get_magic_quotes_runtime() + # set_magic_quotes_runtime(0) + @FontFiles.each_pair do |file, info| + #Font file embedding + newobj() + @FontFiles[file]['n']=@n + if(defined('FPDF_FONTPATH')) + file=FPDF_FONTPATH+file + end + size=filesize(file) + if(!size) + Error('Font file not found') + end + out('<>') + f=fopen(file,'rb') + putstream(fread(f,size)) + fclose(f) + out('endobj') + end +# + # set_magic_quotes_runtime(mqr) +# + @fonts.each_pair do |k, font| + #Font objects + newobj() + @fonts[k]['n']=@n + out('<>') + out('endobj') + if(font['type']!='core') + #Widths + newobj() + cw=font['cw'] + s='[' + 32.upto(255) do |i| + s+=cw[i.chr]+' ' + end + out(s+']') + out('endobj') + #Descriptor + newobj() + s='<>') + out('endobj') + end + end + end + end + + def putType0(font) + #Type0 + out('/Subtype /Type0') + out('/BaseFont /'+font['name']+'-'+font['CMap']) + out('/Encoding /'+font['CMap']) + out('/DescendantFonts ['+(@n+1).to_s+' 0 R]') + out('>>') + out('endobj') + #CIDFont + newobj() + out('<>') + out('/FontDescriptor '+(@n+1).to_s+' 0 R') + if(font['CMap']=='ETen-B5-H') + w='13648 13742 500' + elsif(font['CMap']=='GBK-EUC-H') + w='814 907 500 7716 [500]' + else + # ActionController::Base::logger.debug font['cw'].keys.sort.join(' ').to_s + # ActionController::Base::logger.debug font['cw'].values.join(' ').to_s + w='1 [' + font['cw'].keys.sort.each {|key| + w+=font['cw'][key].to_s + " " +# ActionController::Base::logger.debug key.to_s +# ActionController::Base::logger.debug font['cw'][key].to_s + } + w +=']' + end + out('/W ['+w+']>>') + out('endobj') + #Font descriptor + newobj() + out('<>') + out('endobj') + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/errors.rb b/vendor/plugins/rfpdf/lib/rfpdf/errors.rb new file mode 100644 index 000000000..2be2dae16 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/errors.rb @@ -0,0 +1,4 @@ +module RFPDF + class GenerationError < StandardError #:nodoc: + end +end \ No newline at end of file diff --git a/vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb b/vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb new file mode 100644 index 000000000..ad52e9e62 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb @@ -0,0 +1,1550 @@ +# Ruby FPDF 1.53d +# FPDF 1.53 by Olivier Plathey ported to Ruby by Brian Ollenberger +# Copyright 2005 Brian Ollenberger +# Please retain this entire copyright notice. If you distribute any +# modifications, place an additional comment here that clearly indicates +# that it was modified. You may (but are not send any useful modifications that you make +# back to me at http://zeropluszero.com/software/fpdf/ + +# Bug fixes, examples, external fonts, JPEG support, and upgrade to version +# 1.53 contributed by Kim Shrier. +# +# Bookmark support contributed by Sylvain Lafleur. +# +# EPS support contributed by Thiago Jackiw, ported from the PHP version by Valentin Schmidt. +# +# Bookmarks contributed by Sylvain Lafleur. +# +# 1.53 contributed by Ed Moss +# Handle '\n' at the beginning of a string +# Bookmarks contributed by Sylvain Lafleur. + +require 'date' +require 'zlib' + +class FPDF + FPDF_VERSION = '1.53d' + + Charwidths = { + 'courier'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600], + + 'courierB'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600], + + 'courierI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600], + + 'courierBI'=>[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600], + + 'helvetica'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500], + + 'helveticaB'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556], + + 'helveticaI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 350, 556, 350, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500], + + 'helveticaBI'=>[278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 350, 556, 350, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 350, 611, 350, 350, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 350, 500, 667, 278, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 333, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556], + + 'times'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 350, 500, 350, 333, 500, 444, 1000, 500, 500, 333, 1000, 556, 333, 889, 350, 611, 350, 350, 333, 333, 444, 444, 350, 500, 1000, 333, 980, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 200, 500, 333, 760, 276, 500, 564, 333, 760, 333, 400, 564, 300, 300, 333, 500, 453, 250, 333, 300, 310, 500, 750, 750, 750, 444, 722, 722, 722, 722, 722, 722, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 722, 722, 722, 722, 722, 722, 564, 722, 722, 722, 722, 722, 722, 556, 500, 444, 444, 444, 444, 444, 444, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 564, 500, 500, 500, 500, 500, 500, 500, 500], + + 'timesB'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 1000, 350, 667, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 444, 722, 250, 333, 500, 500, 500, 500, 220, 500, 333, 747, 300, 500, 570, 333, 747, 333, 400, 570, 300, 300, 333, 556, 540, 250, 333, 300, 330, 500, 750, 750, 750, 500, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 778, 778, 778, 778, 778, 570, 778, 722, 722, 722, 722, 722, 611, 556, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 500, 556, 500], + + 'timesI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 350, 500, 350, 333, 500, 556, 889, 500, 500, 333, 1000, 500, 333, 944, 350, 556, 350, 350, 333, 333, 556, 556, 350, 500, 889, 333, 980, 389, 333, 667, 350, 389, 556, 250, 389, 500, 500, 500, 500, 275, 500, 333, 760, 276, 500, 675, 333, 760, 333, 400, 675, 300, 300, 333, 500, 523, 250, 333, 300, 310, 500, 750, 750, 750, 500, 611, 611, 611, 611, 611, 611, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 667, 722, 722, 722, 722, 722, 675, 722, 722, 722, 722, 722, 556, 611, 500, 500, 500, 500, 500, 500, 500, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 675, 500, 500, 500, 500, 500, 444, 500, 444], + + 'timesBI'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 350, 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 944, 350, 611, 350, 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 389, 611, 250, 389, 500, 500, 500, 500, 220, 500, 333, 747, 266, 500, 606, 333, 747, 333, 400, 570, 300, 300, 333, 576, 500, 250, 333, 300, 300, 500, 750, 750, 750, 500, 667, 667, 667, 667, 667, 667, 944, 667, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 722, 722, 722, 722, 722, 570, 722, 722, 722, 722, 722, 611, 611, 500, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 444, 500, 444], + + 'symbol'=>[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 333, 713, 500, 549, 833, 778, 439, 333, 333, 500, 549, 250, 549, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 549, 722, 667, 722, 612, 611, 763, 603, 722, 333, 631, 722, 686, 889, 722, 722, 768, 741, 556, 592, 611, 690, 439, 768, 645, 795, 611, 333, 863, 333, 658, 500, 500, 631, 549, 549, 494, 439, 521, 411, 603, 329, 603, 549, 549, 576, 521, 549, 549, 521, 549, 603, 439, 576, 713, 686, 493, 686, 494, 480, 200, 480, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 750, 620, 247, 549, 167, 713, 500, 753, 753, 753, 753, 1042, 987, 603, 987, 603, 400, 549, 411, 549, 549, 713, 494, 460, 549, 549, 549, 549, 1000, 603, 1000, 658, 823, 686, 795, 987, 768, 768, 823, 768, 768, 713, 713, 713, 713, 713, 713, 713, 768, 713, 790, 790, 890, 823, 549, 250, 713, 603, 603, 1042, 987, 603, 987, 603, 494, 329, 790, 790, 786, 713, 384, 384, 384, 384, 384, 384, 494, 494, 494, 494, 0, 329, 274, 686, 686, 686, 384, 384, 384, 384, 384, 384, 494, 494, 494, 0], + + 'zapfdingbats'=>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 974, 961, 974, 980, 719, 789, 790, 791, 690, 960, 939, 549, 855, 911, 933, 911, 945, 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, 754, 494, 552, 537, 577, 692, 786, 788, 788, 790, 793, 794, 816, 823, 789, 841, 823, 833, 816, 831, 923, 744, 723, 749, 790, 792, 695, 776, 768, 792, 759, 707, 708, 682, 701, 826, 815, 789, 789, 707, 687, 696, 689, 786, 787, 713, 791, 785, 791, 873, 761, 762, 762, 759, 759, 892, 892, 788, 784, 438, 138, 277, 415, 392, 392, 668, 668, 0, 390, 390, 317, 317, 276, 276, 509, 509, 410, 410, 234, 234, 334, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 732, 544, 544, 910, 667, 760, 760, 776, 595, 694, 626, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 894, 838, 1016, 458, 748, 924, 748, 918, 927, 928, 928, 834, 873, 828, 924, 924, 917, 930, 931, 463, 883, 836, 836, 867, 867, 696, 696, 874, 0, 874, 760, 946, 771, 865, 771, 888, 967, 888, 831, 873, 927, 970, 918, 0] + } + + def initialize(orientation='P', unit='mm', format='A4') + # Initialization of properties + @page=0 + @n=2 + @buffer='' + @pages=[] + @OrientationChanges=[] + @state=0 + @fonts={} + @FontFiles={} + @diffs=[] + @images={} + @links=[] + @PageLinks={} + @InFooter=false + @FontFamily='' + @FontStyle='' + @FontSizePt=12 + @underline= false + @DrawColor='0 G' + @FillColor='0 g' + @TextColor='0 g' + @ColorFlag=false + @ws=0 + @offsets=[] + + # Standard fonts + @CoreFonts={} + @CoreFonts['courier']='Courier' + @CoreFonts['courierB']='Courier-Bold' + @CoreFonts['courierI']='Courier-Oblique' + @CoreFonts['courierBI']='Courier-BoldOblique' + @CoreFonts['helvetica']='Helvetica' + @CoreFonts['helveticaB']='Helvetica-Bold' + @CoreFonts['helveticaI']='Helvetica-Oblique' + @CoreFonts['helveticaBI']='Helvetica-BoldOblique' + @CoreFonts['times']='Times-Roman' + @CoreFonts['timesB']='Times-Bold' + @CoreFonts['timesI']='Times-Italic' + @CoreFonts['timesBI']='Times-BoldItalic' + @CoreFonts['symbol']='Symbol' + @CoreFonts['zapfdingbats']='ZapfDingbats' + + # Scale factor + if unit=='pt' + @k=1 + elsif unit=='mm' + @k=72/25.4 + elsif unit=='cm' + @k=72/2.54; + elsif unit=='in' + @k=72 + else + raise 'Incorrect unit: '+unit + end + + # Page format + if format.is_a? String + format.downcase! + if format=='a3' + format=[841.89,1190.55] + elsif format=='a4' + format=[595.28,841.89] + elsif format=='a5' + format=[420.94,595.28] + elsif format=='letter' + format=[612,792] + elsif format=='legal' + format=[612,1008] + else + raise 'Unknown page format: '+format + end + @fwPt,@fhPt=format + else + @fwPt=format[0]*@k + @fhPt=format[1]*@k + end + @fw=@fwPt/@k; + @fh=@fhPt/@k; + + # Page orientation + orientation.downcase! + if orientation=='p' or orientation=='portrait' + @DefOrientation='P' + @wPt=@fwPt + @hPt=@fhPt + elsif orientation=='l' or orientation=='landscape' + @DefOrientation='L' + @wPt=@fhPt + @hPt=@fwPt + else + raise 'Incorrect orientation: '+orientation + end + @CurOrientation=@DefOrientation + @w=@wPt/@k + @h=@hPt/@k + + # Page margins (1 cm) + margin=28.35/@k + SetMargins(margin,margin) + # Interior cell margin (1 mm) + @cMargin=margin/10 + # Line width (0.2 mm) + @LineWidth=0.567/@k + # Automatic page break + SetAutoPageBreak(true,2*margin) + # Full width display mode + SetDisplayMode('fullwidth') + # Enable compression + SetCompression(true) + # Set default PDF version number + @PDFVersion='1.3' + end + + def SetMargins(left, top, right=-1) + # Set left, top and right margins + @lMargin=left + @tMargin=top + right=left if right==-1 + @rMargin=right + end + + def SetLeftMargin(margin) + # Set left margin + @lMargin=margin + @x=margin if @page>0 and @x0 + # Page footer + @InFooter=true + self.Footer + @InFooter=false + # Close page + endpage + end + # Start new page + beginpage(orientation) + # Set line cap style to square + out('2 J') + # Set line width + @LineWidth=lw + out(sprintf('%.2f w',lw*@k)) + # Set font + SetFont(family,style,size) if family + # Set colors + @DrawColor=dc + out(dc) if dc!='0 G' + @FillColor=fc + out(fc) if fc!='0 g' + @TextColor=tc + @ColorFlag=cf + # Page header + self.Header + # Restore line width + if @LineWidth!=lw + @LineWidth=lw + out(sprintf('%.2f w',lw*@k)) + end + # Restore font + self.SetFont(family,style,size) if family + # Restore colors + if @DrawColor!=dc + @DrawColor=dc + out(dc) + end + if @FillColor!=fc + @FillColor=fc + out(fc) + end + @TextColor=tc + @ColorFlag=cf + end + + def Header + # To be implemented in your inherited class + end + + def Footer + # To be implemented in your inherited class + end + + def PageNo + # Get current page number + @page + end + + def SetDrawColor(r,g=-1,b=-1) + # Set color for all stroking operations + if (r==0 and g==0 and b==0) or g==-1 + @DrawColor=sprintf('%.3f G',r/255.0) + else + @DrawColor=sprintf('%.3f %.3f %.3f RG',r/255.0,g/255.0,b/255.0) + end + out(@DrawColor) if(@page>0) + end + + def SetFillColor(r,g=-1,b=-1) + # Set color for all filling operations + if (r==0 and g==0 and b==0) or g==-1 + @FillColor=sprintf('%.3f g',r/255.0) + else + @FillColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) + end + @ColorFlag=(@FillColor!=@TextColor) + out(@FillColor) if(@page>0) + end + + def SetTextColor(r,g=-1,b=-1) + # Set color for text + if (r==0 and g==0 and b==0) or g==-1 + @TextColor=sprintf('%.3f g',r/255.0) + else + @TextColor=sprintf('%.3f %.3f %.3f rg',r/255.0,g/255.0,b/255.0) + end + @ColorFlag=(@FillColor!=@TextColor) + end + + def GetStringWidth(s) + # Get width of a string in the current font + cw=@CurrentFont['cw'] + w=0 + s.each_byte do |c| + w=w+cw[c] + end + w*@FontSize/1000.0 + end + + def SetLineWidth(width) + # Set line width + @LineWidth=width + out(sprintf('%.2f w',width*@k)) if @page>0 + end + + def Line(x1, y1, x2, y2) + # Draw a line + out(sprintf('%.2f %.2f m %.2f %.2f l S', + x1*@k,(@h-y1)*@k,x2*@k,(@h-y2)*@k)) + end + + def Rect(x, y, w, h, style='') + # Draw a rectangle + if style=='F' + op='f' + elsif style=='FD' or style=='DF' + op='B' + else + op='S' + end + out(sprintf('%.2f %.2f %.2f %.2f re %s', x*@k,(@h-y)*@k,w*@k,-h*@k,op)) + end + + def AddFont(family, style='', file='') + # Add a TrueType or Type1 font + family = family.downcase + family = 'helvetica' if family == 'arial' + + style = style.upcase + style = 'BI' if style == 'IB' + + fontkey = family + style + + if @fonts.has_key?(fontkey) + self.Error("Font already added: #{family} #{style}") + end + + file = family.gsub(' ', '') + style.downcase + '.rb' if file == '' + + if self.class.const_defined? 'FPDF_FONTPATH' + if FPDF_FONTPATH[-1,1] == '/' + file = FPDF_FONTPATH + file + else + file = FPDF_FONTPATH + '/' + file + end + end + + # Changed from "require file" to fix bug reported by Hans Allis. + load file + + if FontDef.desc.nil? + self.Error("Could not include font definition file #{file}") + end + + i = @fonts.length + 1 + + @fonts[fontkey] = {'i' => i, + 'type' => FontDef.type, + 'name' => FontDef.name, + 'desc' => FontDef.desc, + 'up' => FontDef.up, + 'ut' => FontDef.ut, + 'cw' => FontDef.cw, + 'enc' => FontDef.enc, + 'file' => FontDef.file + } + + if FontDef.diff + # Search existing encodings + unless @diffs.include?(FontDef.diff) + @diffs.push(FontDef.diff) + @fonts[fontkey]['diff'] = @diffs.length - 1 + end + end + + if FontDef.file + if FontDef.type == 'TrueType' + @FontFiles[FontDef.file] = {'length1' => FontDef.originalsize} + else + @FontFiles[FontDef.file] = {'length1' => FontDef.size1, 'length2' => FontDef.size2} + end + end + + return self + end + + def SetFont(family, style='', size=0) + # Select a font; size given in points + family.downcase! + family=@FontFamily if family=='' + if family=='arial' + family='helvetica' + elsif family=='symbol' or family=='zapfdingbats' + style='' + end + style.upcase! + unless style.index('U').nil? + @underline=true + style.gsub!('U','') + else + @underline=false; + end + style='BI' if style=='IB' + size=@FontSizePt if size==0 + # Test if font is already selected + return if @FontFamily==family and + @FontStyle==style and @FontSizePt==size + # Test if used for the first time + fontkey=family+style + unless @fonts.has_key?(fontkey) + if @CoreFonts.has_key?(fontkey) + unless Charwidths.has_key?(fontkey) + raise 'Font unavailable' + end + @fonts[fontkey]={ + 'i'=>@fonts.size, + 'type'=>'core', + 'name'=>@CoreFonts[fontkey], + 'up'=>-100, + 'ut'=>50, + 'cw'=>Charwidths[fontkey]} + else + raise 'Font unavailable' + end + end + + #Select it + @FontFamily=family + @FontStyle=style; + @FontSizePt=size + @FontSize=size/@k; + @CurrentFont=@fonts[fontkey] + if @page>0 + out(sprintf('BT /F%d %.2f Tf ET', @CurrentFont['i'], @FontSizePt)) + end + end + + def SetFontSize(size) + # Set font size in points + return if @FontSizePt==size + @FontSizePt=size + @FontSize=size/@k + if @page>0 + out(sprintf('BT /F%d %.2f Tf ET',@CurrentFont['i'],@FontSizePt)) + end + end + + def AddLink + # Create a new internal link + @links.push([0, 0]) + @links.size + end + + def SetLink(link, y=0, page=-1) + # Set destination of internal link + y=@y if y==-1 + page=@page if page==-1 + @links[link]=[page, y] + end + + def Link(x, y, w, h, link) + # Put a link on the page + @PageLinks[@page]=Array.new unless @PageLinks.has_key?(@Page) + @PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link]) + end + + def Text(x, y, txt) + # Output a string + txt.gsub!(')', '\\)') + txt.gsub!('(', '\\(') + txt.gsub!('\\', '\\\\') + s=sprintf('BT %.2f %.2f Td (%s) Tj ET',x*@k,(@h-y)*@k,txt); + s=s+' '+dounderline(x,y,txt) if @underline and txt!='' + s='q '+@TextColor+' '+s+' Q' if @ColorFlag + out(s) + end + + def AcceptPageBreak + # Accept automatic page break or not + @AutoPageBreak + end + + def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') + # Output a cell + if @y+h>@PageBreakTrigger and !@InFooter and self.AcceptPageBreak + # Automatic page break + x=@x + ws=@ws + if ws>0 + @ws=0 + out('0 Tw') + end + self.AddPage(@CurOrientation) + @x=x + if ws>0 + @ws=ws + out(sprintf('%.3f Tw',ws*@k)) + end + end + w=@w-@rMargin-@x if w==0 + s='' + if fill==1 or border==1 + if fill==1 + op=(border==1) ? 'B' : 'f' + else + op='S' + end + s=sprintf('%.2f %.2f %.2f %.2f re %s ',@x*@k,(@h-@y)*@k,w*@k,-h*@k,op) + end + if border.is_a? String + x=@x + y=@y + unless border.index('L').nil? + s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', + x*@k,(@h-y)*@k,x*@k,(@h-(y+h))*@k) + end + unless border.index('T').nil? + s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', + x*@k,(@h-y)*@k,(x+w)*@k,(@h-y)*@k) + end + unless border.index('R').nil? + s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', + (x+w)*@k,(@h-y)*@k,(x+w)*@k,(@h-(y+h))*@k) + end + unless border.index('B').nil? + s=s+sprintf('%.2f %.2f m %.2f %.2f l S ', + x*@k,(@h-(y+h))*@k,(x+w)*@k,(@h-(y+h))*@k) + end + end + if txt!='' + if align=='R' + dx=w-@cMargin-self.GetStringWidth(txt) + elsif align=='C' + dx=(w-self.GetStringWidth(txt))/2 + else + dx=@cMargin + end + txt = txt.gsub(')', '\\)') + txt.gsub!('(', '\\(') + txt.gsub!('\\', '\\\\') + if @ColorFlag + s=s+'q '+@TextColor+' ' + end + s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET', + (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,txt) + s=s+' '+dounderline(@x+dx,@y+0.5*h+0.3*@FontSize,txt) if @underline + s=s+' Q' if @ColorFlag + if link and link != '' + Link(@x+dx,@y+0.5*h-0.5*@FontSize,GetStringWidth(txt),@FontSize,link) + end + end + out(s) if s + @lasth=h + if ln>0 + # Go to next line + @y=@y+h + @x=@lMargin if ln==1 + else + @x=@x+w + end + end + + def MultiCell(w,h,txt,border=0,align='J',fill=0) + # Output text with automatic or explicit line breaks + cw=@CurrentFont['cw'] + w=@w-@rMargin-@x if w==0 + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub('\r','') + nb=s.length + nb=nb-1 if nb>0 and s[nb-1].chr=='\n' + b=0 + if border!=0 + if border==1 + border='LTRB' + b='LRT' + b2='LR' + else + b2='' + b2='L' unless border.index('L').nil? + b2=b2+'R' unless border.index('R').nil? + b=(not border.index('T').nil?) ? (b2+'T') : b2 + end + end + sep=-1 + i=0 + j=0 + l=0 + ns=0 + nl=1 + while i0 + @ws=0 + out('0 Tw') + end +#Ed Moss +# Don't let i go negative + end_i = i == 0 ? 0 : i - 1 + # Changed from s[j..i] to fix bug reported by Hans Allis. + self.Cell(w,h,s[j..end_i],b,2,align,fill) +# + i=i+1 + sep=-1 + j=i + l=0 + ns=0 + nl=nl+1 + b=b2 if border and nl==2 + else + if c==' ' + sep=i + ls=l + ns=ns+1 + end + l=l+cw[c[0]] + if l>wmax + # Automatic line break + if sep==-1 + i=i+1 if i==j + if @ws>0 + @ws=0 + out('0 Tw') + end + self.Cell(w,h,s[j..i],b,2,align,fill) +#Ed Moss +# Added so that it wouldn't print the last character of the string if it got close +#FIXME 2006-07-18 Level=0 - but it still puts out an extra new line + i += 1 +# + else + if align=='J' + @ws=(ns>1) ? (wmax-ls)/1000.0*@FontSize/(ns-1) : 0 + out(sprintf('%.3f Tw',@ws*@k)) + end + self.Cell(w,h,s[j..sep],b,2,align,fill) + i=sep+1 + end + sep=-1 + j=i + l=0 + ns=0 + nl=nl+1 + b=b2 if border and nl==2 + else + i=i+1 + end + end + end + + # Last chunk + if @ws>0 + @ws=0 + out('0 Tw') + end + b=b+'B' if border!=0 and not border.index('B').nil? + self.Cell(w,h,s[j..i],b,2,align,fill) + @x=@lMargin + end + + def Write(h,txt,link='') + # Output text in flowing mode + cw=@CurrentFont['cw'] + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub("\r",'') + nb=s.length + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while iwmax + # Automatic line break + if sep==-1 + if @x>@lMargin + # Move to next line + @x=@lMargin + @y=@y+h + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + i=i+1 + nl=nl+1 + next + end + i=i+1 if i==j + self.Cell(w,h,s[j,i-j],0,2,'',0,link) + else + self.Cell(w,h,s[j,sep-j],0,2,'',0,link) + i=sep+1 + end + sep=-1 + j=i + l=0 + if nl==1 + @x=@lMargin + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + end + nl=nl+1 + else + i=i+1 + end + end + # Last chunk + self.Cell(l/1000.0*@FontSize,h,s[j,i],0,0,'',0,link) if i!=j + end + + def Image(file,x,y,w=0,h=0,type='',link='') + # Put an image on the page + unless @images.has_key?(file) + # First use of image, get info + if type=='' + pos=file.rindex('.') + if pos.nil? + self.Error('Image file has no extension and no type was '+ + 'specified: '+file) + end + type=file[pos+1..-1] + end + type.downcase! + if type=='jpg' or type=='jpeg' + info=parsejpg(file) + elsif type=='png' + info=parsepng(file) + else + self.Error('Unsupported image file type: '+type) + end + info['i']=@images.length+1 + @images[file]=info + else + info=@images[file] + end +#Ed Moss + if(w==0 && h==0) + #Put image at 72 dpi + w=info['w']/@k; + h=info['h']/@k; + end +# + # Automatic width or height calculation + w=h*info['w']/info['h'] if w==0 + h=w*info['h']/info['w'] if h==0 + out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', + w*@k,h*@k,x*@k,(@h-(y+h))*@k,info['i'])) + Link(x,y,w,h,link) if link and link != '' + end + + def Ln(h='') + # Line feed; default value is last cell height + @x=@lMargin + if h.kind_of?(String) + @y=@y+@lasth + else + @y=@y+h + end + end + + def GetX + # Get x position + @x + end + + def SetX(x) + # Set x position + if x>=0 + @x=x + else + @x=@w+x + end + end + + def GetY + # Get y position + @y + end + + def SetY(y) + # Set y position and reset x + @x=@lMargin + if y>=0 + @y=y + else + @y=@h+y + end + end + + def SetXY(x,y) + # Set x and y positions + SetY(y) + SetX(x) + end + + def Output(file=nil) + # Output PDF to file or return as a string + + # Finish document if necessary + self.Close if(@state<3) + + if file.nil? + # Return as a string + return @buffer + else + # Save file locally + open(file,'wb') do |f| + f.write(@buffer) + end + end + end + + private + + def putpages + nb=@page + unless @AliasNbPages.nil? or @AliasNbPages=='' + # Replace number of pages + 1.upto(nb) do |n| + @pages[n].gsub!(@AliasNbPages,nb.to_s) + end + end + if @DefOrientation=='P' + wPt=@fwPt + hPt=@fhPt + else + wPt=@fhPt + hPt=@fwPt + end + filter=(@compress) ? '/Filter /FlateDecode ' : '' + 1.upto(nb) do |n| + # Page + newobj + out('<>>>' + else + l=@links[pl[4]] + h=@OrientationChanges[l[0]].nil? ? hPt : wPt + annots=annots+sprintf( + '/Dest [%d 0 R /XYZ 0 %.2f null]>>', + 1+2*l[0],h-l[1]*@k) + end + end + out(annots+']') + end + out('/Contents '+(@n+1).to_s+' 0 R>>') + out('endobj') + # Page content + p=(@compress) ? Zlib::Deflate.deflate(@pages[n]) : @pages[n] + newobj + out('<<'+filter+'/Length '+p.length.to_s+'>>') + putstream(p) + out('endobj') + end + # Pages root + @offsets[1]=@buffer.length + out('1 0 obj') + out('<>') + out('endobj') + end + + def putfonts + nf=@n + @diffs.each do |diff| + # Encodings + newobj + out('<>') + out('endobj') + end + + @FontFiles.each do |file, info| + # Font file embedding + newobj + @FontFiles[file]['n'] = @n + + if self.class.const_defined? 'FPDF_FONTPATH' then + if FPDF_FONTPATH[-1,1] == '/' then + file = FPDF_FONTPATH + file + else + file = FPDF_FONTPATH + '/' + file + end + end + + size = File.size(file) + unless File.exists?(file) + Error('Font file not found') + end + + out('<>') + open(file, 'rb') do |f| + putstream(f.read()) + end + out('endobj') + end + + file = 0 + @fonts.each do |k, font| + # Font objects + @fonts[k]['n']=@n+1 + type=font['type'] + name=font['name'] + if type=='core' + # Standard font + newobj + out('<>') + out('endobj') + elsif type=='Type1' or type=='TrueType' + # Additional Type1 or TrueType font + newobj + out('<>') + out('endobj') + # Widths + newobj + cw=font['cw'] + s='[' + 32.upto(255) do |i| + s << cw[i].to_s+' ' + end + out(s+']') + out('endobj') + # Descriptor + newobj + s='<>') + out('endobj') + else + # Allow for additional types + mtd='put'+type.downcase + unless self.respond_to?(mtd) + self.Error('Unsupported font type: '+type) + end + self.send(mtd, font) + end + end + end + + def putimages + filter=(@compress) ? '/Filter /FlateDecode ' : '' + @images.each do |file, info| + newobj + @images[file]['n']=@n + out('<>') + putstream(info['data']) + @images[file]['data']=nil + out('endobj') + # Palette + if info['cs']=='Indexed' + newobj + pal=(@compress) ? Zlib::Deflate.deflate(info['pal']) : info['pal'] + out('<<'+filter+'/Length '+pal.length.to_s+'>>') + putstream(pal) + out('endobj') + end + end + end + + def putxobjectdict + @images.each_value do |image| + out('/I'+image['i'].to_s+' '+image['n'].to_s+' 0 R') + end + end + + def putresourcedict + out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]') + out('/Font <<') + @fonts.each_value do |font| + out('/F'+font['i'].to_s+' '+font['n'].to_s+' 0 R') + end + out('>>') + out('/XObject <<') + putxobjectdict + out('>>') + end + + def putresources + putfonts + putimages + # Resource dictionary + @offsets[2]=@buffer.length + out('2 0 obj') + out('<<') + putresourcedict + out('>>') + out('endobj') + end + + def putinfo + out('/Producer '+textstring('Ruby FPDF '+FPDF_VERSION)); + unless @title.nil? + out('/Title '+textstring(@title)) + end + unless @subject.nil? + out('/Subject '+textstring(@subject)) + end + unless @author.nil? + out('/Author '+textstring(@author)) + end + unless @keywords.nil? + out('/Keywords '+textstring(@keywords)) + end + unless @creator.nil? + out('/Creator '+textstring(@creator)) + end + out('/CreationDate '+textstring('D: '+DateTime.now.to_s)) + end + + def putcatalog + out('/Type /Catalog') + out('/Pages 1 0 R') + if @ZoomMode=='fullpage' + out('/OpenAction [3 0 R /Fit]') + elsif @ZoomMode=='fullwidth' + out('/OpenAction [3 0 R /FitH null]') + elsif @ZoomMode=='real' + out('/OpenAction [3 0 R /XYZ null null 1]') + elsif not @ZoomMode.kind_of?(String) + out('/OpenAction [3 0 R /XYZ null null '+(@ZoomMode/100)+']') + end + + if @LayoutMode=='single' + out('/PageLayout /SinglePage') + elsif @LayoutMode=='continuous' + out('/PageLayout /OneColumn') + elsif @LayoutMode=='two' + out('/PageLayout /TwoColumnLeft') + end + end + + def putheader + out('%PDF-'+@PDFVersion) + end + + def puttrailer + out('/Size '+(@n+1).to_s) + out('/Root '+@n.to_s+' 0 R') + out('/Info '+(@n-1).to_s+' 0 R') + end + + def enddoc + putheader + putpages + putresources + # Info + newobj + out('<<') + putinfo + out('>>') + out('endobj') + # Catalog + newobj + out('<<') + putcatalog + out('>>') + out('endobj') + # Cross-ref + o=@buffer.length + out('xref') + out('0 '+(@n+1).to_s) + out('0000000000 65535 f ') + 1.upto(@n) do |i| + out(sprintf('%010d 00000 n ',@offsets[i])) + end + # Trailer + out('trailer') + out('<<') + puttrailer + out('>>') + out('startxref') + out(o) + out('%%EOF') + state=3 + end + + def beginpage(orientation) + @page=@page+1 + @pages[@page]='' + @state=2 + @x=@lMargin + @y=@tMargin + @lasth=0 + @FontFamily='' + # Page orientation + if orientation=='' + orientation=@DefOrientation + else + orientation=orientation[0].chr.upcase + if orientation!=@DefOrientation + @OrientationChanges[@page]=true + end + end + if orientation!=@CurOrientation + # Change orientation + if orientation=='P' + @wPt=@fwPt + @hPt=@fhPt + @w=@fw + @h=@fh + else + @wPt=@fhPt + @hPt=@fwPt + @w=@fh + @h=@fw + end + @PageBreakTrigger=@h-@bMargin + @CurOrientation=orientation + end + end + + def endpage + # End of page contents + @state=1 + end + + def newobj + # Begin a new object + @n=@n+1 + @offsets[@n]=@buffer.length + out(@n.to_s+' 0 obj') + end + + def dounderline(x,y,txt) + # Underline text + up=@CurrentFont['up'] + ut=@CurrentFont['ut'] + w=GetStringWidth(txt)+@ws*txt.count(' ') + sprintf('%.2f %.2f %.2f %.2f re f', + x*@k,(@h-(y-up/1000.0*@FontSize))*@k,w*@k,-ut/1000.0*@FontSizePt) + end + + def parsejpg(file) + # Extract info from a JPEG file + a=extractjpginfo(file) + raise "Missing or incorrect JPEG file: #{file}" if a.nil? + + if a['channels'].nil? || a['channels']==3 then + colspace='DeviceRGB' + elsif a['channels']==4 then + colspace='DeviceCMYK' + else + colspace='DeviceGray' + end + bpc= a['bits'] ? a['bits'].to_i : 8 + + # Read whole file + data = nil + open(file, 'rb') do |f| + data = f.read + end + return {'w'=>a['width'],'h'=>a['height'],'cs'=>colspace,'bpc'=>bpc,'f'=>'DCTDecode','data'=>data} + end + + def parsepng(file) + # Extract info from a PNG file + f=open(file,'rb') + # Check signature + unless f.read(8)==137.chr+'PNG'+13.chr+10.chr+26.chr+10.chr + self.Error('Not a PNG file: '+file) + end + # Read header chunk + f.read(4) + if f.read(4)!='IHDR' + self.Error('Incorrect PNG file: '+file) + end + w=freadint(f) + h=freadint(f) + bpc=f.read(1)[0] + if bpc>8 + self.Error('16-bit depth not supported: '+file) + end + ct=f.read(1)[0] + if ct==0 + colspace='DeviceGray' + elsif ct==2 + colspace='DeviceRGB' + elsif ct==3 + colspace='Indexed' + else + self.Error('Alpha channel not supported: '+file) + end + if f.read(1)[0]!=0 + self.Error('Unknown compression method: '+file) + end + if f.read(1)[0]!=0 + self.Error('Unknown filter method: '+file) + end + if f.read(1)[0]!=0 + self.Error('Interlacing not supported: '+file) + end + f.read(4) + parms='/DecodeParms <>' + # Scan chunks looking for palette, transparency and image data + pal='' + trns='' + data='' + begin + n=freadint(f) + type=f.read(4) + if type=='PLTE' + # Read palette + pal=f.read(n) + f.read(4) + elsif type=='tRNS' + # Read transparency info + t=f.read(n) + if ct==0 + trns=[t[1]] + elsif ct==2 + trns=[t[1],t[3],t[5]] + else + pos=t.index(0) + trns=[pos] unless pos.nil? + end + f.read(4) + elsif type=='IDAT' + # Read image data block + data << f.read(n) + f.read(4) + elsif type=='IEND' + break + else + f.read(n+4) + end + end while n + if colspace=='Indexed' and pal=='' + self.Error('Missing palette in '+file) + end + f.close + {'w'=>w,'h'=>h,'cs'=>colspace,'bpc'=>bpc,'f'=>'FlateDecode', + 'parms'=>parms,'pal'=>pal,'trns'=>trns,'data'=>data} + end + + def freadint(f) + # Read a 4-byte integer from file + a = f.read(4).unpack('N') + return a[0] + end + + def freadshort(f) + a = f.read(2).unpack('n') + return a[0] + end + + def freadbyte(f) + a = f.read(1).unpack('C') + return a[0] + end + + def textstring(s) + # Format a text string + '('+escape(s)+')' + end + + def escape(s) + # Add \ before \, ( and ) + s.gsub('\\','\\\\').gsub('(','\\(').gsub(')','\\)') + end + + def putstream(s) + out('stream') + out(s) + out('endstream') + end + + def out(s) + # Add a line to the document + if @state==2 + @pages[@page]=@pages[@page]+s+"\n" + else + @buffer=@buffer+s.to_s+"\n" + end + end + + # jpeg marker codes + + M_SOF0 = 0xc0 + M_SOF1 = 0xc1 + M_SOF2 = 0xc2 + M_SOF3 = 0xc3 + + M_SOF5 = 0xc5 + M_SOF6 = 0xc6 + M_SOF7 = 0xc7 + + M_SOF9 = 0xc9 + M_SOF10 = 0xca + M_SOF11 = 0xcb + + M_SOF13 = 0xcd + M_SOF14 = 0xce + M_SOF15 = 0xcf + + M_SOI = 0xd8 + M_EOI = 0xd9 + M_SOS = 0xda + + def extractjpginfo(file) + result = nil + + open(file, "rb") do |f| + marker = jpegnextmarker(f) + + if marker != M_SOI + return nil + end + + while true + marker = jpegnextmarker(f) + + case marker + when M_SOF0, M_SOF1, M_SOF2, M_SOF3, + M_SOF5, M_SOF6, M_SOF7, M_SOF9, + M_SOF10, M_SOF11, M_SOF13, M_SOF14, + M_SOF15 then + + length = freadshort(f) + + if result.nil? + result = {} + + result['bits'] = freadbyte(f) + result['height'] = freadshort(f) + result['width'] = freadshort(f) + result['channels'] = freadbyte(f) + + f.seek(length - 8, IO::SEEK_CUR) + else + f.seek(length - 2, IO::SEEK_CUR) + end + when M_SOS, M_EOI then + return result + else + length = freadshort(f) + f.seek(length - 2, IO::SEEK_CUR) + end + end + end + end + + def jpegnextmarker(f) + while true + # look for 0xff + while (c = freadbyte(f)) != 0xff + end + + c = freadbyte(f) + + if c != 0 + return c + end + end + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/fpdf_eps.rb b/vendor/plugins/rfpdf/lib/rfpdf/fpdf_eps.rb new file mode 100644 index 000000000..c6a224310 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/fpdf_eps.rb @@ -0,0 +1,139 @@ +# Information +# +# PDF_EPS class from Valentin Schmidt ported to ruby by Thiago Jackiw (tjackiw@gmail.com) +# working for Mingle LLC (www.mingle.com) +# Release Date: July 13th, 2006 +# +# Description +# +# This script allows to embed vector-based Adobe Illustrator (AI) or AI-compatible EPS files. +# Only vector drawing is supported, not text or bitmap. Although the script was successfully +# tested with various AI format versions, best results are probably achieved with files that +# were exported in the AI3 format (tested with Illustrator CS2, Freehand MX and Photoshop CS2). +# +# ImageEps(string file, float x, float y [, float w [, float h [, string link [, boolean useBoundingBox]]]]) +# +# Same parameters as for regular FPDF::Image() method, with an additional one: +# +# useBoundingBox: specifies whether to position the bounding box (true) or the complete canvas (false) +# at location (x,y). Default value is true. +# +# First added to the Ruby FPDF distribution in 1.53c +# +# Usage is as follows: +# +# require 'fpdf' +# require 'fpdf_eps' +# pdf = FPDF.new +# pdf.extend(PDF_EPS) +# pdf.ImageEps(...) +# +# This allows it to be combined with other extensions, such as the bookmark +# module. + +module PDF_EPS + def ImageEps(file, x, y, w=0, h=0, link='', use_bounding_box=true) + data = nil + if File.exists?(file) + File.open(file, 'rb') do |f| + data = f.read() + end + else + Error('EPS file not found: '+file) + end + + # Find BoundingBox param + regs = data.scan(/%%BoundingBox: [^\r\n]*/m) + regs << regs[0].gsub(/%%BoundingBox: /, '') + if regs.size > 1 + tmp = regs[1].to_s.split(' ') + @x1 = tmp[0].to_i + @y1 = tmp[1].to_i + @x2 = tmp[2].to_i + @y2 = tmp[3].to_i + else + Error('No BoundingBox found in EPS file: '+file) + end + f_start = data.index('%%EndSetup') + f_start = data.index('%%EndProlog') if f_start === false + f_start = data.index('%%BoundingBox') if f_start === false + + data = data.slice(f_start, data.length) + + f_end = data.index('%%PageTrailer') + f_end = data.index('showpage') if f_end === false + data = data.slice(0, f_end) if f_end + + # save the current graphic state + out('q') + + k = @k + + # Translate + if use_bounding_box + dx = x*k-@x1 + dy = @hPt-@y2-y*k + else + dx = x*k + dy = -y*k + end + tm = [1,0,0,1,dx,dy] + out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm', + tm[0], tm[1], tm[2], tm[3], tm[4], tm[5])) + + if w > 0 + scale_x = w/((@x2-@x1)/k) + if h > 0 + scale_y = h/((@y2-@y1)/k) + else + scale_y = scale_x + h = (@y2-@y1)/k * scale_y + end + else + if h > 0 + scale_y = $h/((@y2-@y1)/$k) + scale_x = scale_y + w = (@x2-@x1)/k * scale_x + else + w = (@x2-@x1)/k + h = (@y2-@y1)/k + end + end + + if !scale_x.nil? + # Scale + tm = [scale_x,0,0,scale_y,0,@hPt*(1-scale_y)] + out(sprintf('%.3f %.3f %.3f %.3f %.3f %.3f cm', + tm[0], tm[1], tm[2], tm[3], tm[4], tm[5])) + end + + data.split(/\r\n|[\r\n]/).each do |line| + next if line == '' || line[0,1] == '%' + len = line.length + # next if (len > 2 && line[len-2,len] != ' ') + cmd = line[len-2,len].strip + case cmd + when 'm', 'l', 'v', 'y', 'c', 'k', 'K', 'g', 'G', 's', 'S', 'J', 'j', 'w', 'M', 'd': + out(line) + + when 'L': + line[len-1,len]='l' + out(line) + + when 'C': + line[len-1,len]='c' + out(line) + + when 'f', 'F': + out('f*') + + when 'b', 'B': + out(cmd + '*') + end + end + + # restore previous graphic state + out('Q') + Link(x,y,w,h,link) if link + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/japanese.rb b/vendor/plugins/rfpdf/lib/rfpdf/japanese.rb new file mode 100644 index 000000000..7340936bb --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/japanese.rb @@ -0,0 +1,468 @@ +# Copyright (c) 2006 4ssoM LLC +# 1.12 contributed by Ed Moss. +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# This is direct port of japanese.php +# +# Japanese PDF support. +# +# Usage is as follows: +# +# require 'fpdf' +# require 'chinese' +# pdf = FPDF.new +# pdf.extend(PDF_Japanese) +# +# This allows it to be combined with other extensions, such as the bookmark +# module. + +module PDF_Japanese + + SJIS_widths={' ' => 278, '!' => 299, '"' => 353, '#' => 614, '$' => 614, '%' => 721, '&' => 735, '\'' => 216, + '(' => 323, ')' => 323, '*' => 449, '+' => 529, ',' => 219, '-' => 306, '.' => 219, '/' => 453, '0' => 614, '1' => 614, + '2' => 614, '3' => 614, '4' => 614, '5' => 614, '6' => 614, '7' => 614, '8' => 614, '9' => 614, ':' => 219, ';' => 219, + '<' => 529, '=' => 529, '>' => 529, '?' => 486, '@' => 744, 'A' => 646, 'B' => 604, 'C' => 617, 'D' => 681, 'E' => 567, + 'F' => 537, 'G' => 647, 'H' => 738, 'I' => 320, 'J' => 433, 'K' => 637, 'L' => 566, 'M' => 904, 'N' => 710, 'O' => 716, + 'P' => 605, 'Q' => 716, 'R' => 623, 'S' => 517, 'T' => 601, 'U' => 690, 'V' => 668, 'W' => 990, 'X' => 681, 'Y' => 634, + 'Z' => 578, '[' => 316, '\\' => 614, ']' => 316, '^' => 529, '_' => 500, '`' => 387, 'a' => 509, 'b' => 566, 'c' => 478, + 'd' => 565, 'e' => 503, 'f' => 337, 'g' => 549, 'h' => 580, 'i' => 275, 'j' => 266, 'k' => 544, 'l' => 276, 'm' => 854, + 'n' => 579, 'o' => 550, 'p' => 578, 'q' => 566, 'r' => 410, 's' => 444, 't' => 340, 'u' => 575, 'v' => 512, 'w' => 760, + 'x' => 503, 'y' => 529, 'z' => 453, '{' => 326, '|' => 380, '}' => 326, '~' => 387} + + def AddCIDFont(family,style,name,cw,cMap,registry) + fontkey=family.downcase+style.upcase + unless @fonts[fontkey].nil? + Error("CID font already added: family style") + end + i=@fonts.length+1 + @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-120,'ut'=>40,'cw'=>cw, + 'CMap'=>cMap,'registry'=>registry} + end + + def AddCIDFonts(family,name,cw,cMap,registry) + AddCIDFont(family,'',name,cw,cMap,registry) + AddCIDFont(family,'B',name+',Bold',cw,cMap,registry) + AddCIDFont(family,'I',name+',Italic',cw,cMap,registry) + AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry) + end + + def AddSJISFont(family='SJIS') + #Add SJIS font with proportional Latin + name='KozMinPro-Regular-Acro' + cw=SJIS_widths + cMap='90msp-RKSJ-H' + registry={'ordering'=>'Japan1','supplement'=>2} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def AddSJIShwFont(family='SJIS-hw') + #Add SJIS font with half-width Latin + name='KozMinPro-Regular-Acro' + 32.upto(126) do |i| + cw[i.chr]=500 + end + cMap='90ms-RKSJ-H' + registry={'ordering'=>'Japan1','supplement'=>2} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def GetStringWidth(s) + if(@CurrentFont['type']=='Type0') + return GetSJISStringWidth(s) + else + return super(s) + end + end + + def GetSJISStringWidth(s) + #SJIS version of GetStringWidth() + l=0 + cw=@CurrentFont['cw'] + nb=s.length + i=0 + while(i=161 and o<=223) + #Half-width katakana + l+=500 + i+=1 + else + #Full-width character + l+=1000 + i+=2 + end + end + return l*@FontSize/1000 + end + + def MultiCell(w,h,txt,border=0,align='L',fill=0) + if(@CurrentFont['type']=='Type0') + SJISMultiCell(w,h,txt,border,align,fill) + else + super(w,h,txt,border,align,fill) + end + end + + def SJISMultiCell(w,h,txt,border=0,align='L',fill=0) + #Output text with automatic or explicit line breaks + cw=@CurrentFont['cw'] + if(w==0) + w=@w-@rMargin-@x + end + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub("\r",'') + nb=s.length + if(nb>0 and s[nb-1]=="\n") + nb-=1 + end + b=0 + if(border) + if(border==1) + border='LTRB' + b='LRT' + b2='LR' + else + b2='' + if(border.index('L').nil?) + b2+='L' + end + if(border.index('R').nil?) + b2+='R' + end + b=border.index('T').nil? ? b2+'T' : b2 + end + end + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(i=161 and o<=223) + #Half-width katakana + l+=500 + n=1 + sep=i + else + #Full-width character + l+=1000 + n=2 + sep=i + end + if(l>wmax) + #Automatic line break + if(sep==-1 or i==j) + if(i==j) + i+=n + end + Cell(w,h,s[j,i-j],b,2,align,fill) + else + Cell(w,h,s[j,sep-j],b,2,align,fill) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 + nl+=1 + if(border and nl==2) + b=b2 + end + else + i+=n + if(o>=128) + sep=i + end + end + end + #Last chunk + if(border and not border.index('B').nil?) + b+='B' + end + Cell(w,h,s[j,i-j],b,2,align,fill) + @x=@lMargin + end + + def Write(h,txt,link='') + if(@CurrentFont['type']=='Type0') + SJISWrite(h,txt,link) + else + super(h,txt,link) + end + end + + def SJISWrite(h,txt,link) + #SJIS version of Write() + cw=@CurrentFont['cw'] + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub("\r",'') + nb=s.length + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(i=161 and o<=223) + #Half-width katakana + l+=500 + n=1 + sep=i + else + #Full-width character + l+=1000 + n=2 + sep=i + end + if(l>wmax) + #Automatic line break + if(sep==-1 or i==j) + if(@x>@lMargin) + #Move to next line + @x=@lMargin + @y+=h + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + i+=n + nl+=1 + next + end + if(i==j) + i+=n + end + Cell(w,h,s[j,i-j],0,2,'',0,link) + else + Cell(w,h,s[j,sep-j],0,2,'',0,link) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 + if(nl==1) + @x=@lMargin + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + end + nl+=1 + else + i+=n + if(o>=128) + sep=i + end + end + end + #Last chunk + if(i!=j) + Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link) + end + end + +private + + def putfonts() + nf=@n + @diffs.each do |diff| + #Encodings + newobj() + out('<>') + out('endobj') + end + # mqr=get_magic_quotes_runtime() + # set_magic_quotes_runtime(0) + @FontFiles.each_pair do |file, info| + #Font file embedding + newobj() + @FontFiles[file]['n']=@n + if(defined('FPDF_FONTPATH')) + file=FPDF_FONTPATH+file + end + size=filesize(file) + if(!size) + Error('Font file not found') + end + out('<>') + f=fopen(file,'rb') + putstream(fread(f,size)) + fclose(f) + out('endobj') + end + # set_magic_quotes_runtime(mqr) + @fonts.each_pair do |k, font| + #Font objects + newobj() + @fonts[k]['n']=@n + out('<>') + out('endobj') + if(font['type']!='core') + #Widths + newobj() + cw=font['cw'] + s='[' + 32.upto(255) do |i| + s+=cw[i.chr]+' ' + end + out(s+']') + out('endobj') + #Descriptor + newobj() + s='<>') + out('endobj') + end + end + end + end + + def putType0(font) + #Type0 + out('/Subtype /Type0') + out('/BaseFont /'+font['name']+'-'+font['CMap']) + out('/Encoding /'+font['CMap']) + out('/DescendantFonts ['+(@n+1).to_s+' 0 R]') + out('>>') + out('endobj') + #CIDFont + newobj() + out('<>') + out('/FontDescriptor '+(@n+1).to_s+' 0 R') + w='/W [1 [' + font['cw'].keys.sort.each {|key| + w+=font['cw'][key].to_s + " " +# ActionController::Base::logger.debug key.to_s +# ActionController::Base::logger.debug font['cw'][key].to_s + } + out(w+'] 231 325 500 631 [500] 326 389 500]') + out('>>') + out('endobj') + #Font descriptor + newobj() + out('<>') + out('endobj') + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/korean.rb b/vendor/plugins/rfpdf/lib/rfpdf/korean.rb new file mode 100644 index 000000000..64131405e --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/korean.rb @@ -0,0 +1,436 @@ +# Copyright (c) 2006 4ssoM LLC +# 1.12 contributed by Ed Moss. +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# This is direct port of korean.php +# +# Korean PDF support. +# +# Usage is as follows: +# +# require 'fpdf' +# require 'chinese' +# pdf = FPDF.new +# pdf.extend(PDF_Korean) +# +# This allows it to be combined with other extensions, such as the bookmark +# module. + +module PDF_Korean + +UHC_widths={' ' => 333, '!' => 416, '"' => 416, '#' => 833, '$' => 625, '%' => 916, '&' => 833, '\'' => 250, + '(' => 500, ')' => 500, '*' => 500, '+' => 833, ',' => 291, '-' => 833, '.' => 291, '/' => 375, '0' => 625, '1' => 625, + '2' => 625, '3' => 625, '4' => 625, '5' => 625, '6' => 625, '7' => 625, '8' => 625, '9' => 625, ':' => 333, ';' => 333, + '<' => 833, '=' => 833, '>' => 916, '?' => 500, '@' => 1000, 'A' => 791, 'B' => 708, 'C' => 708, 'D' => 750, 'E' => 708, + 'F' => 666, 'G' => 750, 'H' => 791, 'I' => 375, 'J' => 500, 'K' => 791, 'L' => 666, 'M' => 916, 'N' => 791, 'O' => 750, + 'P' => 666, 'Q' => 750, 'R' => 708, 'S' => 666, 'T' => 791, 'U' => 791, 'V' => 750, 'W' => 1000, 'X' => 708, 'Y' => 708, + 'Z' => 666, '[' => 500, '\\' => 375, ']' => 500, '^' => 500, '_' => 500, '`' => 333, 'a' => 541, 'b' => 583, 'c' => 541, + 'd' => 583, 'e' => 583, 'f' => 375, 'g' => 583, 'h' => 583, 'i' => 291, 'j' => 333, 'k' => 583, 'l' => 291, 'm' => 875, + 'n' => 583, 'o' => 583, 'p' => 583, 'q' => 583, 'r' => 458, 's' => 541, 't' => 375, 'u' => 583, 'v' => 583, 'w' => 833, + 'x' => 625, 'y' => 625, 'z' => 500, '{' => 583, '|' => 583, '}' => 583, '~' => 750} + + def AddCIDFont(family,style,name,cw,cMap,registry) + fontkey=family.downcase+style.upcase + unless @fonts[fontkey].nil? + Error("Font already added: family style") + end + i=@fonts.length+1 + name=name.gsub(' ','') + @fonts[fontkey]={'i'=>i,'type'=>'Type0','name'=>name,'up'=>-130,'ut'=>40,'cw'=>cw, + 'CMap'=>cMap,'registry'=>registry} + end + + def AddCIDFonts(family,name,cw,cMap,registry) + AddCIDFont(family,'',name,cw,cMap,registry) + AddCIDFont(family,'B',name+',Bold',cw,cMap,registry) + AddCIDFont(family,'I',name+',Italic',cw,cMap,registry) + AddCIDFont(family,'BI',name+',BoldItalic',cw,cMap,registry) + end + + def AddUHCFont(family='UHC',name='HYSMyeongJoStd-Medium-Acro') + #Add UHC font with proportional Latin + cw=UHC_widths + cMap='KSCms-UHC-H' + registry={'ordering'=>'Korea1','supplement'=>1} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def AddUHChwFont(family='UHC-hw',name='HYSMyeongJoStd-Medium-Acro') + #Add UHC font with half-witdh Latin + 32.upto(126) do |i| + cw[i.chr]=500 + end + cMap='KSCms-UHC-HW-H' + registry={'ordering'=>'Korea1','supplement'=>1} + AddCIDFonts(family,name,cw,cMap,registry) + end + + def GetStringWidth(s) + if(@CurrentFont['type']=='Type0') + return GetMBStringWidth(s) + else + return super(s) + end + end + + def GetMBStringWidth(s) + #Multi-byte version of GetStringWidth() + l=0 + cw=@CurrentFont['cw'] + nb=s.length + i=0 + while(i0 and s[nb-1]=="\n") + nb-=1 + end + b=0 + if(border) + if(border==1) + border='LTRB' + b='LRT' + b2='LR' + else + b2='' + if(border.index('L').nil?) + b2+='L' + end + if(border.index('R').nil?) + b2+='R' + end + b=border.index('T').nil? ? b2+'T' : b2 + end + end + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(iwmax) + #Automatic line break + if(sep==-1 or i==j) + if(i==j) + i+=ascii ? 1 : 2 + end + Cell(w,h,s[j,i-j],b,2,align,fill) + else + Cell(w,h,s[j,sep-j],b,2,align,fill) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 + nl+=1 + if(border and nl==2) + b=b2 + end + else + i+=ascii ? 1 : 2 + end + end + #Last chunk + if(border and not border.index('B').nil?) + b+='B' + end + Cell(w,h,s[j,i-j],b,2,align,fill) + @x=@lMargin + end + + def Write(h,txt,link='') + if(@CurrentFont['type']=='Type0') + MBWrite(h,txt,link) + else + super(h,txt,link) + end + end + + def MBWrite(h,txt,link) + #Multi-byte version of Write() + cw=@CurrentFont['cw'] + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + s=txt.gsub("\r",'') + nb=s.length + sep=-1 + i=0 + j=0 + l=0 + nl=1 + while(iwmax) + #Automatic line break + if(sep==-1 or i==j) + if(@x>@lMargin) + #Move to next line + @x=@lMargin + @y+=h + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + i+=1 + nl+=1 + next + end + if(i==j) + i+=ascii ? 1 : 2 + end + Cell(w,h,s[j,i-j],0,2,'',0,link) + else + Cell(w,h,s[j,sep-j],0,2,'',0,link) + i=(s[sep]==' ') ? sep+1 : sep + end + sep=-1 + j=i + l=0 + if(nl==1) + @x=@lMargin + w=@w-@rMargin-@x + wmax=(w-2*@cMargin)*1000/@FontSize + end + nl+=1 + else + i+=ascii ? 1 : 2 + end + end + #Last chunk + if(i!=j) + Cell(l/1000*@FontSize,h,s[j,i-j],0,0,'',0,link) + end + end + +private + + def putfonts() + nf=@n + @diffs.each do |diff| + #Encodings + newobj() + out('<>') + out('endobj') + end + # mqr=get_magic_quotes_runtime() + # set_magic_quotes_runtime(0) + @FontFiles.each_pair do |file, info| + #Font file embedding + newobj() + @FontFiles[file]['n']=@n + if(defined('FPDF_FONTPATH')) + file=FPDF_FONTPATH+file + end + size=filesize(file) + if(!size) + Error('Font file not found') + end + out('<>') + f=fopen(file,'rb') + putstream(fread(f,size)) + fclose(f) + out('endobj') + end + # set_magic_quotes_runtime(mqr) + @fonts.each_pair do |k, font| + #Font objects + newobj() + @fonts[k]['n']=@n + out('<>') + out('endobj') + if(font['type']!='core') + #Widths + newobj() + cw=font['cw'] + s='[' + 32.upto(255) do |i| + s+=cw[i.chr]+' ' + end + out(s+']') + out('endobj') + #Descriptor + newobj() + s='<>') + out('endobj') + end + end + end + end + + def putType0(font) + #Type0 + out('/Subtype /Type0') + out('/BaseFont /'+font['name']+'-'+font['CMap']) + out('/Encoding /'+font['CMap']) + out('/DescendantFonts ['+(@n+1).to_s+' 0 R]') + out('>>') + out('endobj') + #CIDFont + newobj() + out('<>') + out('/FontDescriptor '+(@n+1).to_s+' 0 R') + if(font['CMap']=='KSCms-UHC-HW-H') + w='8094 8190 500' + else + w='1 [' + font['cw'].keys.sort.each {|key| + w+=font['cw'][key].to_s + " " + # ActionController::Base::logger.debug key.to_s + # ActionController::Base::logger.debug font['cw'][key].to_s + } + w +=']' + end + out('/W ['+w+']>>') + out('endobj') + #Font descriptor + newobj() + out('<>') + out('endobj') + end +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/makefont.rb b/vendor/plugins/rfpdf/lib/rfpdf/makefont.rb new file mode 100644 index 000000000..ffc98b48f --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/makefont.rb @@ -0,0 +1,1787 @@ +#!/usr/bin/env ruby +# +# Utility to generate font definition files +# Version: 1.1 +# Date: 2006-07-19 +# +# Changelog: +# Version 1.1 - Brian Ollenberger +# - Fixed a very small bug in MakeFont for generating FontDef.diff. + +Charencodings = { +# Central Europe + 'cp1250' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', '.notdef', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + '.notdef', 'perthousand', 'Scaron', 'guilsinglleft', + 'Sacute', 'Tcaron', 'Zcaron', 'Zacute', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + '.notdef', 'trademark', 'scaron', 'guilsinglright', + 'sacute', 'tcaron', 'zcaron', 'zacute', + 'space', 'caron', 'breve', 'Lslash', + 'currency', 'Aogonek', 'brokenbar', 'section', + 'dieresis', 'copyright', 'Scedilla', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'Zdotaccent', + 'degree', 'plusminus', 'ogonek', 'lslash', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'aogonek', 'scedilla', 'guillemotright', + 'Lcaron', 'hungarumlaut', 'lcaron', 'zdotaccent', + 'Racute', 'Aacute', 'Acircumflex', 'Abreve', + 'Adieresis', 'Lacute', 'Cacute', 'Ccedilla', + 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis', + 'Ecaron', 'Iacute', 'Icircumflex', 'Dcaron', + 'Dcroat', 'Nacute', 'Ncaron', 'Oacute', + 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'multiply', + 'Rcaron', 'Uring', 'Uacute', 'Uhungarumlaut', + 'Udieresis', 'Yacute', 'Tcommaaccent', 'germandbls', + 'racute', 'aacute', 'acircumflex', 'abreve', + 'adieresis', 'lacute', 'cacute', 'ccedilla', + 'ccaron', 'eacute', 'eogonek', 'edieresis', + 'ecaron', 'iacute', 'icircumflex', 'dcaron', + 'dcroat', 'nacute', 'ncaron', 'oacute', + 'ocircumflex', 'ohungarumlaut', 'odieresis', 'divide', + 'rcaron', 'uring', 'uacute', 'uhungarumlaut', + 'udieresis', 'yacute', 'tcommaaccent', 'dotaccent' + ], +# Cyrillic + 'cp1251' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'afii10051', 'afii10052', 'quotesinglbase', 'afii10100', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + 'Euro', 'perthousand', 'afii10058', 'guilsinglleft', + 'afii10059', 'afii10061', 'afii10060', 'afii10145', + 'afii10099', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + '.notdef', 'trademark', 'afii10106', 'guilsinglright', + 'afii10107', 'afii10109', 'afii10108', 'afii10193', + 'space', 'afii10062', 'afii10110', 'afii10057', + 'currency', 'afii10050', 'brokenbar', 'section', + 'afii10023', 'copyright', 'afii10053', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'afii10056', + 'degree', 'plusminus', 'afii10055', 'afii10103', + 'afii10098', 'mu', 'paragraph', 'periodcentered', + 'afii10071', 'afii61352', 'afii10101', 'guillemotright', + 'afii10105', 'afii10054', 'afii10102', 'afii10104', + 'afii10017', 'afii10018', 'afii10019', 'afii10020', + 'afii10021', 'afii10022', 'afii10024', 'afii10025', + 'afii10026', 'afii10027', 'afii10028', 'afii10029', + 'afii10030', 'afii10031', 'afii10032', 'afii10033', + 'afii10034', 'afii10035', 'afii10036', 'afii10037', + 'afii10038', 'afii10039', 'afii10040', 'afii10041', + 'afii10042', 'afii10043', 'afii10044', 'afii10045', + 'afii10046', 'afii10047', 'afii10048', 'afii10049', + 'afii10065', 'afii10066', 'afii10067', 'afii10068', + 'afii10069', 'afii10070', 'afii10072', 'afii10073', + 'afii10074', 'afii10075', 'afii10076', 'afii10077', + 'afii10078', 'afii10079', 'afii10080', 'afii10081', + 'afii10082', 'afii10083', 'afii10084', 'afii10085', + 'afii10086', 'afii10087', 'afii10088', 'afii10089', + 'afii10090', 'afii10091', 'afii10092', 'afii10093', + 'afii10094', 'afii10095', 'afii10096', 'afii10097' + ], +# Western Europe + 'cp1252' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', 'florin', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft', + 'OE', '.notdef', 'Zcaron', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + 'tilde', 'trademark', 'scaron', 'guilsinglright', + 'oe', '.notdef', 'zcaron', 'Ydieresis', + 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Eth', 'Ntilde', 'Ograve', 'Oacute', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Yacute', 'Thorn', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'eth', 'ntilde', 'ograve', 'oacute', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'yacute', 'thorn', 'ydieresis' + ], +# Greek + 'cp1253' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', 'florin', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + '.notdef', 'perthousand', '.notdef', 'guilsinglleft', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + '.notdef', 'trademark', '.notdef', 'guilsinglright', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'dieresistonos', 'Alphatonos', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', '.notdef', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'afii00208', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'tonos', 'mu', 'paragraph', 'periodcentered', + 'Epsilontonos', 'Etatonos', 'Iotatonos', 'guillemotright', + 'Omicrontonos', 'onehalf', 'Upsilontonos', 'Omegatonos', + 'iotadieresistonos','Alpha', 'Beta', 'Gamma', + 'Delta', 'Epsilon', 'Zeta', 'Eta', + 'Theta', 'Iota', 'Kappa', 'Lambda', + 'Mu', 'Nu', 'Xi', 'Omicron', + 'Pi', 'Rho', '.notdef', 'Sigma', + 'Tau', 'Upsilon', 'Phi', 'Chi', + 'Psi', 'Omega', 'Iotadieresis', 'Upsilondieresis', + 'alphatonos', 'epsilontonos', 'etatonos', 'iotatonos', + 'upsilondieresistonos','alpha', 'beta', 'gamma', + 'delta', 'epsilon', 'zeta', 'eta', + 'theta', 'iota', 'kappa', 'lambda', + 'mu', 'nu', 'xi', 'omicron', + 'pi', 'rho', 'sigma1', 'sigma', + 'tau', 'upsilon', 'phi', 'chi', + 'psi', 'omega', 'iotadieresis', 'upsilondieresis', + 'omicrontonos', 'upsilontonos', 'omegatonos', '.notdef' + ], +# Turkish + 'cp1254' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', 'florin', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft', + 'OE', '.notdef', '.notdef', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + 'tilde', 'trademark', 'scaron', 'guilsinglright', + 'oe', '.notdef', '.notdef', 'Ydieresis', + 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Gbreve', 'Ntilde', 'Ograve', 'Oacute', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Idotaccent', 'Scedilla', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'gbreve', 'ntilde', 'ograve', 'oacute', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'dotlessi', 'scedilla', 'ydieresis' + ], +# Hebrew + 'cp1255' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', 'florin', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + 'circumflex', 'perthousand', '.notdef', 'guilsinglleft', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + 'tilde', 'trademark', '.notdef', 'guilsinglright', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclamdown', 'cent', 'sterling', + 'afii57636', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'multiply', 'guillemotleft', + 'logicalnot', 'sfthyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'middot', + 'cedilla', 'onesuperior', 'divide', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'afii57799', 'afii57801', 'afii57800', 'afii57802', + 'afii57793', 'afii57794', 'afii57795', 'afii57798', + 'afii57797', 'afii57806', '.notdef', 'afii57796', + 'afii57807', 'afii57839', 'afii57645', 'afii57841', + 'afii57842', 'afii57804', 'afii57803', 'afii57658', + 'afii57716', 'afii57717', 'afii57718', 'gereshhebrew', + 'gershayimhebrew','.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'afii57664', 'afii57665', 'afii57666', 'afii57667', + 'afii57668', 'afii57669', 'afii57670', 'afii57671', + 'afii57672', 'afii57673', 'afii57674', 'afii57675', + 'afii57676', 'afii57677', 'afii57678', 'afii57679', + 'afii57680', 'afii57681', 'afii57682', 'afii57683', + 'afii57684', 'afii57685', 'afii57686', 'afii57687', + 'afii57688', 'afii57689', 'afii57690', '.notdef', + '.notdef', 'afii299', 'afii300', '.notdef' + ], +# Baltic + 'cp1257' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', '.notdef', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + '.notdef', 'perthousand', '.notdef', 'guilsinglleft', + '.notdef', 'dieresis', 'caron', 'cedilla', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + '.notdef', 'trademark', '.notdef', 'guilsinglright', + '.notdef', 'macron', 'ogonek', '.notdef', + 'space', '.notdef', 'cent', 'sterling', + 'currency', '.notdef', 'brokenbar', 'section', + 'Oslash', 'copyright', 'Rcommaaccent', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'AE', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'oslash', 'onesuperior', 'rcommaaccent', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'ae', + 'Aogonek', 'Iogonek', 'Amacron', 'Cacute', + 'Adieresis', 'Aring', 'Eogonek', 'Emacron', + 'Ccaron', 'Eacute', 'Zacute', 'Edotaccent', + 'Gcommaaccent', 'Kcommaaccent', 'Imacron', 'Lcommaaccent', + 'Scaron', 'Nacute', 'Ncommaaccent', 'Oacute', + 'Omacron', 'Otilde', 'Odieresis', 'multiply', + 'Uogonek', 'Lslash', 'Sacute', 'Umacron', + 'Udieresis', 'Zdotaccent', 'Zcaron', 'germandbls', + 'aogonek', 'iogonek', 'amacron', 'cacute', + 'adieresis', 'aring', 'eogonek', 'emacron', + 'ccaron', 'eacute', 'zacute', 'edotaccent', + 'gcommaaccent', 'kcommaaccent', 'imacron', 'lcommaaccent', + 'scaron', 'nacute', 'ncommaaccent', 'oacute', + 'omacron', 'otilde', 'odieresis', 'divide', + 'uogonek', 'lslash', 'sacute', 'umacron', + 'udieresis', 'zdotaccent', 'zcaron', 'dotaccent' + ], +# Vietnamese + 'cp1258' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', 'quotesinglbase', 'florin', + 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', + 'circumflex', 'perthousand', '.notdef', 'guilsinglleft', + 'OE', '.notdef', '.notdef', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + 'tilde', 'trademark', '.notdef', 'guilsinglright', + 'oe', '.notdef', '.notdef', 'Ydieresis', + 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Abreve', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'gravecomb', 'Iacute', 'Icircumflex', 'Idieresis', + 'Dcroat', 'Ntilde', 'hookabovecomb', 'Oacute', + 'Ocircumflex', 'Ohorn', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Uhorn', 'tildecomb', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'abreve', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'acutecomb', 'iacute', 'icircumflex', 'idieresis', + 'dcroat', 'ntilde', 'dotbelowcomb', 'oacute', + 'ocircumflex', 'ohorn', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'uhorn', 'dong', 'ydieresis' + ], +# Thai + 'cp874' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'Euro', '.notdef', '.notdef', '.notdef', + '.notdef', 'ellipsis', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', 'quoteleft', 'quoteright', 'quotedblleft', + 'quotedblright', 'bullet', 'endash', 'emdash', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'kokaithai', 'khokhaithai', 'khokhuatthai', + 'khokhwaithai', 'khokhonthai', 'khorakhangthai', 'ngonguthai', + 'chochanthai', 'chochingthai', 'chochangthai', 'sosothai', + 'chochoethai', 'yoyingthai', 'dochadathai', 'topatakthai', + 'thothanthai', 'thonangmonthothai', 'thophuthaothai', 'nonenthai', + 'dodekthai', 'totaothai', 'thothungthai', 'thothahanthai', + 'thothongthai', 'nonuthai', 'bobaimaithai', 'poplathai', + 'phophungthai', 'fofathai', 'phophanthai', 'fofanthai', + 'phosamphaothai', 'momathai', 'yoyakthai', 'roruathai', + 'ruthai', 'lolingthai', 'luthai', 'wowaenthai', + 'sosalathai', 'sorusithai', 'sosuathai', 'hohipthai', + 'lochulathai', 'oangthai', 'honokhukthai', 'paiyannoithai', + 'saraathai', 'maihanakatthai', 'saraaathai', 'saraamthai', + 'saraithai', 'saraiithai', 'sarauethai', 'saraueethai', + 'sarauthai', 'sarauuthai', 'phinthuthai', '.notdef', + '.notdef', '.notdef', '.notdef', 'bahtthai', + 'saraethai', 'saraaethai', 'saraothai', 'saraaimaimuanthai', + 'saraaimaimalaithai', 'lakkhangyaothai', 'maiyamokthai', 'maitaikhuthai', + 'maiekthai', 'maithothai', 'maitrithai', 'maichattawathai', + 'thanthakhatthai', 'nikhahitthai', 'yamakkanthai', 'fongmanthai', + 'zerothai', 'onethai', 'twothai', 'threethai', + 'fourthai', 'fivethai', 'sixthai', 'seventhai', + 'eightthai', 'ninethai', 'angkhankhuthai', 'khomutthai', + '.notdef', '.notdef', '.notdef', '.notdef' + ], +# Western Europe + 'ISO-8859-1' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Eth', 'Ntilde', 'Ograve', 'Oacute', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Yacute', 'Thorn', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'eth', 'ntilde', 'ograve', 'oacute', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'yacute', 'thorn', 'ydieresis' + ], +# Central Europe + 'ISO-8859-2' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'Aogonek', 'breve', 'Lslash', + 'currency', 'Lcaron', 'Sacute', 'section', + 'dieresis', 'Scaron', 'Scedilla', 'Tcaron', + 'Zacute', 'hyphen', 'Zcaron', 'Zdotaccent', + 'degree', 'aogonek', 'ogonek', 'lslash', + 'acute', 'lcaron', 'sacute', 'caron', + 'cedilla', 'scaron', 'scedilla', 'tcaron', + 'zacute', 'hungarumlaut', 'zcaron', 'zdotaccent', + 'Racute', 'Aacute', 'Acircumflex', 'Abreve', + 'Adieresis', 'Lacute', 'Cacute', 'Ccedilla', + 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis', + 'Ecaron', 'Iacute', 'Icircumflex', 'Dcaron', + 'Dcroat', 'Nacute', 'Ncaron', 'Oacute', + 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'multiply', + 'Rcaron', 'Uring', 'Uacute', 'Uhungarumlaut', + 'Udieresis', 'Yacute', 'Tcommaaccent', 'germandbls', + 'racute', 'aacute', 'acircumflex', 'abreve', + 'adieresis', 'lacute', 'cacute', 'ccedilla', + 'ccaron', 'eacute', 'eogonek', 'edieresis', + 'ecaron', 'iacute', 'icircumflex', 'dcaron', + 'dcroat', 'nacute', 'ncaron', 'oacute', + 'ocircumflex', 'ohungarumlaut', 'odieresis', 'divide', + 'rcaron', 'uring', 'uacute', 'uhungarumlaut', + 'udieresis', 'yacute', 'tcommaaccent', 'dotaccent' + ], +# Baltic + 'ISO-8859-4' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'Aogonek', 'kgreenlandic', 'Rcommaaccent', + 'currency', 'Itilde', 'Lcommaaccent', 'section', + 'dieresis', 'Scaron', 'Emacron', 'Gcommaaccent', + 'Tbar', 'hyphen', 'Zcaron', 'macron', + 'degree', 'aogonek', 'ogonek', 'rcommaaccent', + 'acute', 'itilde', 'lcommaaccent', 'caron', + 'cedilla', 'scaron', 'emacron', 'gcommaaccent', + 'tbar', 'Eng', 'zcaron', 'eng', + 'Amacron', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Iogonek', + 'Ccaron', 'Eacute', 'Eogonek', 'Edieresis', + 'Edotaccent', 'Iacute', 'Icircumflex', 'Imacron', + 'Dcroat', 'Ncommaaccent', 'Omacron', 'Kcommaaccent', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Uogonek', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Utilde', 'Umacron', 'germandbls', + 'amacron', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'iogonek', + 'ccaron', 'eacute', 'eogonek', 'edieresis', + 'edotaccent', 'iacute', 'icircumflex', 'imacron', + 'dcroat', 'ncommaaccent', 'omacron', 'kcommaaccent', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'uogonek', 'uacute', 'ucircumflex', + 'udieresis', 'utilde', 'umacron', 'dotaccent' + ], +# Cyrillic + 'ISO-8859-5' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'afii10023', 'afii10051', 'afii10052', + 'afii10053', 'afii10054', 'afii10055', 'afii10056', + 'afii10057', 'afii10058', 'afii10059', 'afii10060', + 'afii10061', 'hyphen', 'afii10062', 'afii10145', + 'afii10017', 'afii10018', 'afii10019', 'afii10020', + 'afii10021', 'afii10022', 'afii10024', 'afii10025', + 'afii10026', 'afii10027', 'afii10028', 'afii10029', + 'afii10030', 'afii10031', 'afii10032', 'afii10033', + 'afii10034', 'afii10035', 'afii10036', 'afii10037', + 'afii10038', 'afii10039', 'afii10040', 'afii10041', + 'afii10042', 'afii10043', 'afii10044', 'afii10045', + 'afii10046', 'afii10047', 'afii10048', 'afii10049', + 'afii10065', 'afii10066', 'afii10067', 'afii10068', + 'afii10069', 'afii10070', 'afii10072', 'afii10073', + 'afii10074', 'afii10075', 'afii10076', 'afii10077', + 'afii10078', 'afii10079', 'afii10080', 'afii10081', + 'afii10082', 'afii10083', 'afii10084', 'afii10085', + 'afii10086', 'afii10087', 'afii10088', 'afii10089', + 'afii10090', 'afii10091', 'afii10092', 'afii10093', + 'afii10094', 'afii10095', 'afii10096', 'afii10097', + 'afii61352', 'afii10071', 'afii10099', 'afii10100', + 'afii10101', 'afii10102', 'afii10103', 'afii10104', + 'afii10105', 'afii10106', 'afii10107', 'afii10108', + 'afii10109', 'section', 'afii10110', 'afii10193' + ], +# Greek + 'ISO-8859-7' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'quoteleft', 'quoteright', 'sterling', + '.notdef', '.notdef', 'brokenbar', 'section', + 'dieresis', 'copyright', '.notdef', 'guillemotleft', + 'logicalnot', 'hyphen', '.notdef', 'afii00208', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'tonos', 'dieresistonos', 'Alphatonos', 'periodcentered', + 'Epsilontonos', 'Etatonos', 'Iotatonos', 'guillemotright', + 'Omicrontonos', 'onehalf', 'Upsilontonos', 'Omegatonos', + 'iotadieresistonos','Alpha', 'Beta', 'Gamma', + 'Delta', 'Epsilon', 'Zeta', 'Eta', + 'Theta', 'Iota', 'Kappa', 'Lambda', + 'Mu', 'Nu', 'Xi', 'Omicron', + 'Pi', 'Rho', '.notdef', 'Sigma', + 'Tau', 'Upsilon', 'Phi', 'Chi', + 'Psi', 'Omega', 'Iotadieresis', 'Upsilondieresis', + 'alphatonos', 'epsilontonos', 'etatonos', 'iotatonos', + 'upsilondieresistonos','alpha', 'beta', 'gamma', + 'delta', 'epsilon', 'zeta', 'eta', + 'theta', 'iota', 'kappa', 'lambda', + 'mu', 'nu', 'xi', 'omicron', + 'pi', 'rho', 'sigma1', 'sigma', + 'tau', 'upsilon', 'phi', 'chi', + 'psi', 'omega', 'iotadieresis', 'upsilondieresis', + 'omicrontonos', 'upsilontonos', 'omegatonos', '.notdef' + ], +# Turkish + 'ISO-8859-9' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', + 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'acute', 'mu', 'paragraph', 'periodcentered', + 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', + 'onequarter', 'onehalf', 'threequarters', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Gbreve', 'Ntilde', 'Ograve', 'Oacute', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Idotaccent', 'Scedilla', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'gbreve', 'ntilde', 'ograve', 'oacute', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'dotlessi', 'scedilla', 'ydieresis' + ], +# Thai + 'ISO-8859-11' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'kokaithai', 'khokhaithai', 'khokhuatthai', + 'khokhwaithai', 'khokhonthai', 'khorakhangthai', 'ngonguthai', + 'chochanthai', 'chochingthai', 'chochangthai', 'sosothai', + 'chochoethai', 'yoyingthai', 'dochadathai', 'topatakthai', + 'thothanthai', 'thonangmonthothai','thophuthaothai', 'nonenthai', + 'dodekthai', 'totaothai', 'thothungthai', 'thothahanthai', + 'thothongthai', 'nonuthai', 'bobaimaithai', 'poplathai', + 'phophungthai', 'fofathai', 'phophanthai', 'fofanthai', + 'phosamphaothai', 'momathai', 'yoyakthai', 'roruathai', + 'ruthai', 'lolingthai', 'luthai', 'wowaenthai', + 'sosalathai', 'sorusithai', 'sosuathai', 'hohipthai', + 'lochulathai', 'oangthai', 'honokhukthai', 'paiyannoithai', + 'saraathai', 'maihanakatthai', 'saraaathai', 'saraamthai', + 'saraithai', 'saraiithai', 'sarauethai', 'saraueethai', + 'sarauthai', 'sarauuthai', 'phinthuthai', '.notdef', + '.notdef', '.notdef', '.notdef', 'bahtthai', + 'saraethai', 'saraaethai', 'saraothai', 'saraaimaimuanthai', + 'saraaimaimalaithai','lakkhangyaothai','maiyamokthai', 'maitaikhuthai', + 'maiekthai', 'maithothai', 'maitrithai', 'maichattawathai', + 'thanthakhatthai','nikhahitthai', 'yamakkanthai', 'fongmanthai', + 'zerothai', 'onethai', 'twothai', 'threethai', + 'fourthai', 'fivethai', 'sixthai', 'seventhai', + 'eightthai', 'ninethai', 'angkhankhuthai', 'khomutthai', + '.notdef', '.notdef', '.notdef', '.notdef' + ], +# Western Europe + 'ISO-8859-15' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclamdown', 'cent', 'sterling', + 'Euro', 'yen', 'Scaron', 'section', + 'scaron', 'copyright', 'ordfeminine', 'guillemotleft', + 'logicalnot', 'hyphen', 'registered', 'macron', + 'degree', 'plusminus', 'twosuperior', 'threesuperior', + 'Zcaron', 'mu', 'paragraph', 'periodcentered', + 'zcaron', 'onesuperior', 'ordmasculine', 'guillemotright', + 'OE', 'oe', 'Ydieresis', 'questiondown', + 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', + 'Adieresis', 'Aring', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Eth', 'Ntilde', 'Ograve', 'Oacute', + 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', + 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Yacute', 'Thorn', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'atilde', + 'adieresis', 'aring', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'eth', 'ntilde', 'ograve', 'oacute', + 'ocircumflex', 'otilde', 'odieresis', 'divide', + 'oslash', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'yacute', 'thorn', 'ydieresis' + ], +# Central Europe + 'ISO-8859-16' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'Aogonek', 'aogonek', 'Lslash', + 'Euro', 'quotedblbase', 'Scaron', 'section', + 'scaron', 'copyright', 'Scommaaccent', 'guillemotleft', + 'Zacute', 'hyphen', 'zacute', 'Zdotaccent', + 'degree', 'plusminus', 'Ccaron', 'lslash', + 'Zcaron', 'quotedblright', 'paragraph', 'periodcentered', + 'zcaron', 'ccaron', 'scommaaccent', 'guillemotright', + 'OE', 'oe', 'Ydieresis', 'zdotaccent', + 'Agrave', 'Aacute', 'Acircumflex', 'Abreve', + 'Adieresis', 'Cacute', 'AE', 'Ccedilla', + 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', + 'Dcroat', 'Nacute', 'Ograve', 'Oacute', + 'Ocircumflex', 'Ohungarumlaut', 'Odieresis', 'Sacute', + 'Uhungarumlaut', 'Ugrave', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Eogonek', 'Tcommaaccent', 'germandbls', + 'agrave', 'aacute', 'acircumflex', 'abreve', + 'adieresis', 'cacute', 'ae', 'ccedilla', + 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', + 'dcroat', 'nacute', 'ograve', 'oacute', + 'ocircumflex', 'ohungarumlaut', 'odieresis', 'sacute', + 'uhungarumlaut', 'ugrave', 'uacute', 'ucircumflex', + 'udieresis', 'eogonek', 'tcommaaccent', 'ydieresis' + ], +# Russian + 'KOI8-R' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'SF100000', 'SF110000', 'SF010000', 'SF030000', + 'SF020000', 'SF040000', 'SF080000', 'SF090000', + 'SF060000', 'SF070000', 'SF050000', 'upblock', + 'dnblock', 'block', 'lfblock', 'rtblock', + 'ltshade', 'shade', 'dkshade', 'integraltp', + 'filledbox', 'periodcentered', 'radical', 'approxequal', + 'lessequal', 'greaterequal', 'space', 'integralbt', + 'degree', 'twosuperior', 'periodcentered', 'divide', + 'SF430000', 'SF240000', 'SF510000', 'afii10071', + 'SF520000', 'SF390000', 'SF220000', 'SF210000', + 'SF250000', 'SF500000', 'SF490000', 'SF380000', + 'SF280000', 'SF270000', 'SF260000', 'SF360000', + 'SF370000', 'SF420000', 'SF190000', 'afii10023', + 'SF200000', 'SF230000', 'SF470000', 'SF480000', + 'SF410000', 'SF450000', 'SF460000', 'SF400000', + 'SF540000', 'SF530000', 'SF440000', 'copyright', + 'afii10096', 'afii10065', 'afii10066', 'afii10088', + 'afii10069', 'afii10070', 'afii10086', 'afii10068', + 'afii10087', 'afii10074', 'afii10075', 'afii10076', + 'afii10077', 'afii10078', 'afii10079', 'afii10080', + 'afii10081', 'afii10097', 'afii10082', 'afii10083', + 'afii10084', 'afii10085', 'afii10072', 'afii10067', + 'afii10094', 'afii10093', 'afii10073', 'afii10090', + 'afii10095', 'afii10091', 'afii10089', 'afii10092', + 'afii10048', 'afii10017', 'afii10018', 'afii10040', + 'afii10021', 'afii10022', 'afii10038', 'afii10020', + 'afii10039', 'afii10026', 'afii10027', 'afii10028', + 'afii10029', 'afii10030', 'afii10031', 'afii10032', + 'afii10033', 'afii10049', 'afii10034', 'afii10035', + 'afii10036', 'afii10037', 'afii10024', 'afii10019', + 'afii10046', 'afii10045', 'afii10025', 'afii10042', + 'afii10047', 'afii10043', 'afii10041', 'afii10044' + ], +# Ukrainian + 'KOI8-U' => [ + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + '.notdef', '.notdef', '.notdef', '.notdef', + 'space', 'exclam', 'quotedbl', 'numbersign', + 'dollar', 'percent', 'ampersand', 'quotesingle', + 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', + 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'grave', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', + 'x', 'y', 'z', 'braceleft', + 'bar', 'braceright', 'asciitilde', '.notdef', + 'SF100000', 'SF110000', 'SF010000', 'SF030000', + 'SF020000', 'SF040000', 'SF080000', 'SF090000', + 'SF060000', 'SF070000', 'SF050000', 'upblock', + 'dnblock', 'block', 'lfblock', 'rtblock', + 'ltshade', 'shade', 'dkshade', 'integraltp', + 'filledbox', 'bullet', 'radical', 'approxequal', + 'lessequal', 'greaterequal', 'space', 'integralbt', + 'degree', 'twosuperior', 'periodcentered', 'divide', + 'SF430000', 'SF240000', 'SF510000', 'afii10071', + 'afii10101', 'SF390000', 'afii10103', 'afii10104', + 'SF250000', 'SF500000', 'SF490000', 'SF380000', + 'SF280000', 'afii10098', 'SF260000', 'SF360000', + 'SF370000', 'SF420000', 'SF190000', 'afii10023', + 'afii10053', 'SF230000', 'afii10055', 'afii10056', + 'SF410000', 'SF450000', 'SF460000', 'SF400000', + 'SF540000', 'afii10050', 'SF440000', 'copyright', + 'afii10096', 'afii10065', 'afii10066', 'afii10088', + 'afii10069', 'afii10070', 'afii10086', 'afii10068', + 'afii10087', 'afii10074', 'afii10075', 'afii10076', + 'afii10077', 'afii10078', 'afii10079', 'afii10080', + 'afii10081', 'afii10097', 'afii10082', 'afii10083', + 'afii10084', 'afii10085', 'afii10072', 'afii10067', + 'afii10094', 'afii10093', 'afii10073', 'afii10090', + 'afii10095', 'afii10091', 'afii10089', 'afii10092', + 'afii10048', 'afii10017', 'afii10018', 'afii10040', + 'afii10021', 'afii10022', 'afii10038', 'afii10020', + 'afii10039', 'afii10026', 'afii10027', 'afii10028', + 'afii10029', 'afii10030', 'afii10031', 'afii10032', + 'afii10033', 'afii10049', 'afii10034', 'afii10035', + 'afii10036', 'afii10037', 'afii10024', 'afii10019', + 'afii10046', 'afii10045', 'afii10025', 'afii10042', + 'afii10047', 'afii10043', 'afii10041', 'afii10044' + ] +} + +def ReadAFM(file, map) + + # Read a font metric file + a = IO.readlines(file) + + raise "File no found: #{file}" if a.size == 0 + + widths = {} + fm = {} + fix = { 'Edot' => 'Edotaccent', 'edot' => 'edotaccent', + 'Idot' => 'Idotaccent', + 'Zdot' => 'Zdotaccent', 'zdot' => 'zdotaccent', + 'Odblacute' => 'Ohungarumlaut', 'odblacute' => 'ohungarumlaut', + 'Udblacute' => 'Uhungarumlaut', 'udblacute' => 'uhungarumlaut', + 'Gcedilla' => 'Gcommaaccent', 'gcedilla' => 'gcommaaccent', + 'Kcedilla' => 'Kcommaaccent', 'kcedilla' => 'kcommaaccent', + 'Lcedilla' => 'Lcommaaccent', 'lcedilla' => 'lcommaaccent', + 'Ncedilla' => 'Ncommaaccent', 'ncedilla' => 'ncommaaccent', + 'Rcedilla' => 'Rcommaaccent', 'rcedilla' => 'rcommaaccent', + 'Scedilla' => 'Scommaaccent',' scedilla' => 'scommaaccent', + 'Tcedilla' => 'Tcommaaccent',' tcedilla' => 'tcommaaccent', + 'Dslash' => 'Dcroat', 'dslash' => 'dcroat', + 'Dmacron' => 'Dcroat', 'dmacron' => 'dcroat', + 'combininggraveaccent' => 'gravecomb', + 'combininghookabove' => 'hookabovecomb', + 'combiningtildeaccent' => 'tildecomb', + 'combiningacuteaccent' => 'acutecomb', + 'combiningdotbelow' => 'dotbelowcomb', + 'dongsign' => 'dong' + } + + a.each do |line| + + e = line.rstrip.split(' ') + next if e.size < 2 + + code = e[0] + param = e[1] + + if code == 'C' then + + # Character metrics + cc = e[1].to_i + w = e[4] + gn = e[7] + + gn = 'Euro' if gn[-4, 4] == '20AC' + + if fix[gn] then + + # Fix incorrect glyph name + 0.upto(map.size - 1) do |i| + if map[i] == fix[gn] then + map[i] = gn + end + end + end + + if map.size == 0 then + # Symbolic font: use built-in encoding + widths[cc] = w + else + widths[gn] = w + fm['CapXHeight'] = e[13].to_i if gn == 'X' + end + + fm['MissingWidth'] = w if gn == '.notdef' + + elsif code == 'FontName' then + fm['FontName'] = param + elsif code == 'Weight' then + fm['Weight'] = param + elsif code == 'ItalicAngle' then + fm['ItalicAngle'] = param.to_f + elsif code == 'Ascender' then + fm['Ascender'] = param.to_i + elsif code == 'Descender' then + fm['Descender'] = param.to_i + elsif code == 'UnderlineThickness' then + fm['UnderlineThickness'] = param.to_i + elsif code == 'UnderlinePosition' then + fm['UnderlinePosition'] = param.to_i + elsif code == 'IsFixedPitch' then + fm['IsFixedPitch'] = (param == 'true') + elsif code == 'FontBBox' then + fm['FontBBox'] = "[#{e[1]},#{e[2]},#{e[3]},#{e[4]}]" + elsif code == 'CapHeight' then + fm['CapHeight'] = param.to_i + elsif code == 'StdVW' then + fm['StdVW'] = param.to_i + end + end + + raise 'FontName not found' unless fm['FontName'] + + if map.size > 0 then + widths['.notdef'] = 600 unless widths['.notdef'] + + if (widths['Delta'] == nil) && widths['increment'] then + widths['Delta'] = widths['increment'] + end + + # Order widths according to map + 0.upto(255) do |i| + if widths[map[i]] == nil + puts "Warning: character #{map[i]} is missing" + widths[i] = widths['.notdef'] + else + widths[i] = widths[map[i]] + end + end + end + + fm['Widths'] = widths + + return fm +end + +def MakeFontDescriptor(fm, symbolic) + + # Ascent + asc = fm['Ascender'] ? fm['Ascender'] : 1000 + fd = "{\n 'Ascent' => '#{asc}'" + + # Descent + desc = fm['Descender'] ? fm['Descender'] : -200 + fd += ", 'Descent' => '#{desc}'" + + # CapHeight + if fm['CapHeight'] then + ch = fm['CapHeight'] + elsif fm['CapXHeight'] + ch = fm['CapXHeight'] + else + ch = asc + end + fd += ", 'CapHeight' => '#{ch}'" + + # Flags + flags = 0 + + if fm['IsFixedPitch'] then + flags += 1 << 0 + end + + if symbolic then + flags += 1 << 2 + else + flags += 1 << 5 + end + + if fm['ItalicAngle'] && (fm['ItalicAngle'] != 0) then + flags += 1 << 6 + end + + fd += ",\n 'Flags' => '#{flags}'" + + # FontBBox + if fm['FontBBox'] then + fbb = fm['FontBBox'].gsub(/,/, ' ') + else + fbb = "[0 #{desc - 100} 1000 #{asc + 100}]" + end + + fd += ", 'FontBBox' => '#{fbb}'" + + # ItalicAngle + ia = fm['ItalicAngle'] ? fm['ItalicAngle'] : 0 + fd += ",\n 'ItalicAngle' => '#{ia}'" + + # StemV + if fm['StdVW'] then + stemv = fm['StdVW'] + elsif fm['Weight'] && (/bold|black/i =~ fm['Weight']) + stemv = 120 + else + stemv = 70 + end + + fd += ", 'StemV' => '#{stemv}'" + + # MissingWidth + if fm['MissingWidth'] then + fd += ", 'MissingWidth' => '#{fm['MissingWidth']}'" + end + + fd += "\n }" + return fd +end + +def MakeWidthArray(fm) + + # Make character width array + s = " [\n " + + cw = fm['Widths'] + + 0.upto(255) do |i| + s += "%5d" % cw[i] + s += "," if i != 255 + s += "\n " if (i % 8) == 7 + end + + s += ']' + + return s +end + +def MakeFontEncoding(map) + + # Build differences from reference encoding + ref = Charencodings['cp1252'] + s = '' + last = 0 + 32.upto(255) do |i| + if map[i] != ref[i] then + if i != last + 1 then + s += i.to_s + ' ' + end + last = i + s += '/' + map[i] + ' ' + end + end + return s.rstrip +end + +def ReadShort(f) + a = f.read(2).unpack('n') + return a[0] +end + +def ReadLong(f) + a = f.read(4).unpack('N') + return a[0] +end + +def CheckTTF(file) + + rl = false + pp = false + e = false + + # Check if font license allows embedding + File.open(file, 'rb') do |f| + + # Extract number of tables + f.seek(4, IO::SEEK_CUR) + nb = ReadShort(f) + f.seek(6, IO::SEEK_CUR) + + # Seek OS/2 table + found = false + 0.upto(nb - 1) do |i| + if f.read(4) == 'OS/2' then + found = true + break + end + + f.seek(12, IO::SEEK_CUR) + end + + if ! found then + return + end + + f.seek(4, IO::SEEK_CUR) + offset = ReadLong(f) + f.seek(offset, IO::SEEK_SET) + + # Extract fsType flags + f.seek(8, IO::SEEK_CUR) + fsType = ReadShort(f) + + rl = (fsType & 0x02) != 0 + pp = (fsType & 0x04) != 0 + e = (fsType & 0x08) != 0 + end + + if rl && ( ! pp) && ( ! e) then + puts 'Warning: font license does not allow embedding' + end +end + +# +# fontfile: path to TTF file (or empty string if not to be embedded) +# afmfile: path to AFM file +# enc: font encoding (or empty string for symbolic fonts) +# patch: optional patch for encoding +# type : font type if $fontfile is empty +# +def MakeFont(fontfile, afmfile, enc = 'cp1252', patch = {}, type = 'TrueType') + # Generate a font definition file + if (enc != nil) && (enc != '') then + map = Charencodings[enc] + patch.each { |cc, gn| map[cc] = gn } + else + map = [] + end + + raise "Error: AFM file not found: #{afmfile}" unless File.exists?(afmfile) + + fm = ReadAFM(afmfile, map) + + if (enc != nil) && (enc != '') then + diff = MakeFontEncoding(map) + else + diff = '' + end + + fd = MakeFontDescriptor(fm, (map.size == 0)) + + # Find font type + if fontfile then + ext = File.extname(fontfile).downcase.sub(/^\./, '') + + if ext == 'ttf' then + type = 'TrueType' + elsif ext == 'pfb' + type = 'Type1' + else + raise "Error: unrecognized font file extension: #{ext}" + end + else + raise "Error: incorrect font type: #{type}" if (type != 'TrueType') && (type != 'Type1') + end + printf "type = #{type}\n" + # Start generation + s = "# #{fm['FontName']} font definition\n\n" + s += "module FontDef\n" + s += " def FontDef.type\n '#{type}'\n end\n" + s += " def FontDef.name\n '#{fm['FontName']}'\n end\n" + s += " def FontDef.desc\n #{fd}\n end\n" + + if fm['UnderlinePosition'] == nil then + fm['UnderlinePosition'] = -100 + end + + if fm['UnderlineThickness'] == nil then + fm['UnderlineThickness'] = 50 + end + + s += " def FontDef.up\n #{fm['UnderlinePosition']}\n end\n" + s += " def FontDef.ut\n #{fm['UnderlineThickness']}\n end\n" + + w = MakeWidthArray(fm) + s += " def FontDef.cw\n#{w}\n end\n" + + s += " def FontDef.enc\n '#{enc}'\n end\n" + s += " def FontDef.diff\n #{(diff == nil) || (diff == '') ? 'nil' : '\'' + diff '\''}\n end\n" + + basename = File.basename(afmfile, '.*') + + if fontfile then + # Embedded font + if ! File.exist?(fontfile) then + raise "Error: font file not found: #{fontfile}" + end + + if type == 'TrueType' then + CheckTTF(fontfile) + end + + file = '' + File.open(fontfile, 'rb') do |f| + file = f.read() + end + + if type == 'Type1' then + # Find first two sections and discard third one + header = file[0] == 128 + file = file[6, file.length - 6] if header + + pos = file.index('eexec') + raise 'Error: font file does not seem to be valid Type1' if pos == nil + + size1 = pos + 6 + + file = file[0, size1] + file[size1 + 6, file.length - (size1 + 6)] if header && file[size1] == 128 + + pos = file.index('00000000') + raise 'Error: font file does not seem to be valid Type1' if pos == nil + + size2 = pos - size1 + file = file[0, size1 + size2] + end + + if require 'zlib' then + File.open(basename + '.z', 'wb') { |f| f.write(Zlib::Deflate.deflate(file)) } + s += " def FontDef.file\n '#{basename}.z'\n end\n" + puts "Font file compressed ('#{basename}.z')" + else + s += " def FontDef.file\n '#{File.basename(fontfile)}'\n end\n" + puts 'Notice: font file could not be compressed (zlib not available)' + end + + if type == 'Type1' then + s += " def FontDef.size1\n '#{size1}'\n end\n" + s += " def FontDef.size2\n '#{size2}'\n end\n" + else + s += " def FontDef.originalsize\n '#{File.size(fontfile)}'\n end\n" + end + + else + # Not embedded font + s += " def FontDef.file\n ''\n end\n" + end + + s += "end\n" + File.open(basename + '.rb', 'w') { |file| file.write(s)} + puts "Font definition file generated (#{basename}.rb)" +end + + +if $0 == __FILE__ then + if ARGV.length >= 3 then + enc = ARGV[2] + else + enc = 'cp1252' + end + + if ARGV.length >= 4 then + patch = ARGV[3] + else + patch = {} + end + + if ARGV.length >= 5 then + type = ARGV[4] + else + type = 'TrueType' + end + + MakeFont(ARGV[0], ARGV[1], enc, patch, type) +end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/rfpdf.rb b/vendor/plugins/rfpdf/lib/rfpdf/rfpdf.rb new file mode 100644 index 000000000..5ad882903 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/rfpdf.rb @@ -0,0 +1,346 @@ +module RFPDF + COLOR_PALETTE = { + :black => [0x00, 0x00, 0x00], + :white => [0xff, 0xff, 0xff], + }.freeze + + # Draw a line from (x1, y1) to (x2, y2). + # + # Options are: + # * :line_color - Default value is COLOR_PALETTE[:black]. + # * :line_width - Default value is 0.5. + # + # Example: + # + # draw_line(x1, y1, x1, y1+h, :line_color => ReportHelper::COLOR_PALETTE[:dark_blue], :line_width => 1) + # + def draw_line(x1, y1, x2, y2, options = {}) + options[:line_color] ||= COLOR_PALETTE[:black] + options[:line_width] ||= 0.5 + set_draw_color(options[:line_color]) + SetLineWidth(options[:line_width]) + Line(x1, y1, x2, y2) + end + + # Draw a string of text at (x, y). + # + # Options are: + # * :font_color - Default value is COLOR_PALETTE[:black]. + # * :font_size - Default value is 10. + # * :font_style - Default value is nothing or ''. + # + # Example: + # + # draw_text(x, y, header_left, :font_size => 10) + # + def draw_text(x, y, text, options = {}) + options[:font_color] ||= COLOR_PALETTE[:black] + options[:font_size] ||= 10 + options[:font_style] ||= '' + set_text_color(options[:font_color]) + SetFont('Arial', options[:font_style], options[:font_size]) + SetXY(x, y) + Write(options[:font_size] + 4, text) + end + + # Draw a block of text at (x, y) bounded by left_margin and right_margin. Both + # margins are measured from their corresponding edge. + # + # Options are: + # * :font_color - Default value is COLOR_PALETTE[:black]. + # * :font_size - Default value is 10. + # * :font_style - Default value is nothing or ''. + # + # Example: + # + # draw_text_block(left_margin, 85, "question", left_margin, 280, + # :font_color => ReportHelper::COLOR_PALETTE[:dark_blue], + # :font_size => 12, + # :font_style => 'I') + # + def draw_text_block(x, y, text, left_margin, right_margin, options = {}) + options[:font_color] ||= COLOR_PALETTE[:black] + options[:font_size] ||= 10 + options[:font_style] ||= '' + set_text_color(options[:font_color]) + SetFont('Arial', options[:font_style], options[:font_size]) + SetXY(x, y) + SetLeftMargin(left_margin) + SetRightMargin(right_margin) + Write(options[:font_size] + 4, text) + SetMargins(0,0,0) + end + + # Draw a box at (x, y), w wide and h high. + # + # Options are: + # * :border - Draw a border, 0 = no, 1 = yes? Default value is 1. + # * :border_color - Default value is COLOR_PALETTE[:black]. + # * :border_width - Default value is 0.5. + # * :fill - Fill the box, 0 = no, 1 = yes? Default value is 1. + # * :fill_color - Default value is nothing or COLOR_PALETTE[:white]. + # + # Example: + # + # draw_box(x, y - 1, 38, 22) + # + def draw_box(x, y, w, h, options = {}) + options[:border] ||= 1 + options[:border_color] ||= COLOR_PALETTE[:black] + options[:border_width] ||= 0.5 + options[:fill] ||= 1 + options[:fill_color] ||= COLOR_PALETTE[:white] + SetLineWidth(options[:border_width]) + set_draw_color(options[:border_color]) + set_fill_color(options[:fill_color]) + fd = "" + fd = "D" if options[:border] == 1 + fd += "F" if options[:fill] == 1 + Rect(x, y, w, h, fd) + end + + # Draw a string of text at (x, y) in a box w wide and h high. + # + # Options are: + # * :align - Vertical alignment 'C' = center, 'L' = left, 'R' = right. Default value is 'C'. + # * :border - Draw a border, 0 = no, 1 = yes? Default value is 0. + # * :border_color - Default value is COLOR_PALETTE[:black]. + # * :border_width - Default value is 0.5. + # * :fill - Fill the box, 0 = no, 1 = yes? Default value is 1. + # * :fill_color - Default value is nothing or COLOR_PALETTE[:white]. + # * :font_color - Default value is COLOR_PALETTE[:black]. + # * :font_size - Default value is nothing or 8. + # * :font_style - 'B' = bold, 'I' = italic, 'U' = underline. Default value is nothing ''. + # * :padding - Default value is nothing or 2. + # * :valign - 'M' = middle, 'T' = top, 'B' = bottom. Default value is nothing or 'M'. + # + # Example: + # + # draw_text_box(x, y - 1, 38, 22, + # "your_score_title", + # :fill => 0, + # :font_color => ReportHelper::COLOR_PALETTE[:blue], + # :font_line_spacing => 0, + # :font_style => "B", + # :valign => "M") + # + def draw_text_box(x, y, w, h, text, options = {}) + options[:align] ||= 'C' + options[:border] ||= 0 + options[:border_color] ||= COLOR_PALETTE[:black] + options[:border_width] ||= 0.5 + options[:fill] ||= 1 + options[:fill_color] ||= COLOR_PALETTE[:white] + options[:font_color] ||= COLOR_PALETTE[:black] + options[:font_size] ||= 8 + options[:font_line_spacing] ||= options[:font_size] * 0.3 + options[:font_style] ||= '' + options[:padding] ||= 2 + options[:valign] ||= "M" + if options[:fill] == 1 or options[:border] == 1 + draw_box(x, y, w, h, options) + end + SetMargins(0,0,0) + set_text_color(options[:font_color]) + font_size = options[:font_size] + SetFont('Arial', options[:font_style], font_size) + font_size += options[:font_line_spacing] + case options[:valign] + when "B" + y -= options[:padding] + text = "\n" + text if text["\n"].nil? + when "T" + y += options[:padding] + end + SetXY(x, y) + if GetStringWidth(text) > w or not text["\n"].nil? or options[:valign] == "T" + font_size += options[:font_size] * 0.1 + #TODO 2006-07-21 Level=1 - this is assuming a 2 line text + SetXY(x, y + ((h - (font_size * 2)) / 2)) if options[:valign] == "M" + MultiCell(w, font_size, text, 0, options[:align]) + else + Cell(w, h, text, 0, 0, options[:align]) + end + end + + # Draw a string of text at (x, y) as a title. + # + # Options are: + # * :font_color - Default value is COLOR_PALETTE[:black]. + # * :font_size - Default value is 18. + # * :font_style - Default value is nothing or ''. + # + # Example: + # + # draw_title(left_margin, 60, + # "title:", + # :font_color => ReportHelper::COLOR_PALETTE[:dark_blue]) + # + def draw_title(x, y, title, options = {}) + options[:font_color] ||= COLOR_PALETTE[:black] + options[:font_size] ||= 18 + options[:font_style] ||= '' + set_text_color(options[:font_color]) + SetFont('Arial', options[:font_style], options[:font_size]) + SetXY(x, y) + Write(options[:font_size] + 2, title) + end + + # Set the draw color. Default value is COLOR_PALETTE[:black]. + # + # Example: + # + # set_draw_color(ReportHelper::COLOR_PALETTE[:dark_blue]) + # + def set_draw_color(color = COLOR_PALETTE[:black]) + SetDrawColor(color[0], color[1], color[2]) + end + + # Set the fill color. Default value is COLOR_PALETTE[:white]. + # + # Example: + # + # set_fill_color(ReportHelper::COLOR_PALETTE[:dark_blue]) + # + def set_fill_color(color = COLOR_PALETTE[:white]) + SetFillColor(color[0], color[1], color[2]) + end + + # Set the text color. Default value is COLOR_PALETTE[:white]. + # + # Example: + # + # set_text_color(ReportHelper::COLOR_PALETTE[:dark_blue]) + # + def set_text_color(color = COLOR_PALETTE[:black]) + SetTextColor(color[0], color[1], color[2]) + end + + # Write a string containing html characters. Default value is COLOR_PALETTE[:white]. + # + # Options are: + # * :height - Line height. Default value is 20. + # + # Example: + # + # write_html(html, :height => 12) + # + def write_html(html, options = {}) + options[:height] ||= 20 + #HTML parser + @href = nil + @style = {} + html.gsub!("\n",' ') + re = %r{ ( | + < (?: + [^<>"] + + | + " (?: \\. | [^\\"]+ ) * " + ) * + > + ) }xm + + html.split(re).each do |value| + if "<" == value[0,1] + #Tag + if (value[1, 1] == '/') + close_tag(value[2..-2], options) + else + tag = value[1..-2] + open_tag(tag, options) + end + else + #Text + if @href + put_link(@href,value) + else + Write(options[:height], value) + end + end + end + end + + def open_tag(tag, options = {}) #:nodoc: + #Opening tag + tag = tag.to_s.upcase + set_style(tag, true) if tag == 'B' or tag == 'I' or tag == 'U' + @href = options['HREF'] if tag == 'A' + Ln(options[:height]) if tag == 'BR' + end + + def close_tag(tag, options = {}) #:nodoc: + #Closing tag + tag = tag.to_s.upcase + set_style(tag, false) if tag == 'B' or tag == 'I' or tag == 'U' + @href = '' if $tag == 'A' + end + + def set_style(tag, enable = true) #:nodoc: + #Modify style and select corresponding font + style = "" + @style[tag] = enable + ['B','I','U'].each do |s| + style += s if not @style[s].nil? and @style[s] + end + SetFont('', style) + end + + def put_link(url, txt) #:nodoc: + #Put a hyperlink + SetTextColor(0,0,255) + set_style('U',true) + Write(5, txt, url) + set_style('U',false) + SetTextColor(0) + end +end + +# class FPDF +# alias_method :set_margins , :SetMargins +# alias_method :set_left_margin , :SetLeftMargin +# alias_method :set_top_margin , :SetTopMargin +# alias_method :set_right_margin , :SetRightMargin +# alias_method :set_auto_pagebreak , :SetAutoPageBreak +# alias_method :set_display_mode , :SetDisplayMode +# alias_method :set_compression , :SetCompression +# alias_method :set_title , :SetTitle +# alias_method :set_subject , :SetSubject +# alias_method :set_author , :SetAuthor +# alias_method :set_keywords , :SetKeywords +# alias_method :set_creator , :SetCreator +# alias_method :set_draw_color , :SetDrawColor +# alias_method :set_fill_color , :SetFillColor +# alias_method :set_text_color , :SetTextColor +# alias_method :set_line_width , :SetLineWidth +# alias_method :set_font , :SetFont +# alias_method :set_font_size , :SetFontSize +# alias_method :set_link , :SetLink +# alias_method :set_y , :SetY +# alias_method :set_xy , :SetXY +# alias_method :get_string_width , :GetStringWidth +# alias_method :get_x , :GetX +# alias_method :set_x , :SetX +# alias_method :get_y , :GetY +# alias_method :accept_pagev_break , :AcceptPageBreak +# alias_method :add_font , :AddFont +# alias_method :add_link , :AddLink +# alias_method :add_page , :AddPage +# alias_method :alias_nb_pages , :AliasNbPages +# alias_method :cell , :Cell +# alias_method :close , :Close +# alias_method :error , :Error +# alias_method :footer , :Footer +# alias_method :header , :Header +# alias_method :image , :Image +# alias_method :line , :Line +# alias_method :link , :Link +# alias_method :ln , :Ln +# alias_method :multi_cell , :MultiCell +# alias_method :open , :Open +# alias_method :Open , :open +# alias_method :output , :Output +# alias_method :page_no , :PageNo +# alias_method :rect , :Rect +# alias_method :text , :Text +# alias_method :write , :Write +# end diff --git a/vendor/plugins/rfpdf/lib/rfpdf/view.rb b/vendor/plugins/rfpdf/lib/rfpdf/view.rb new file mode 100644 index 000000000..185811202 --- /dev/null +++ b/vendor/plugins/rfpdf/lib/rfpdf/view.rb @@ -0,0 +1,75 @@ +# Copyright (c) 2006 4ssoM LLC +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# Thanks go out to Bruce Williams of codefluency who created RTex. This +# template handler is modification of his work. +# +# Example Registration +# +# ActionView::Base::register_template_handler 'rfpdf', RFpdfView + +module RFPDF + + class View + + def initialize(action_view) + @action_view = action_view + # Override with @options_for_rfpdf Hash in your controller + @options = { + # Run through latex first? (for table of contents, etc) + :pre_process => false, + # Debugging mode; raises exception + :debug => false, + # Filename of pdf to generate + :file_name => "#{@action_view.controller.action_name}.pdf", + # Temporary Directory + :temp_dir => "#{File.expand_path(RAILS_ROOT)}/tmp" + }.merge(@action_view.controller.instance_eval{ @options_for_rfpdf } || {}).with_indifferent_access + end + + def render(template, local_assigns = {}) + @pdf_name = "Default.pdf" if @pdf_name.nil? + unless @action_view.controller.headers["Content-Type"] == 'application/pdf' + @generate = true + @action_view.controller.headers["Content-Type"] = 'application/pdf' + @action_view.controller.headers["Content-disposition:"] = "inline; filename=\"#{@options[:file_name]}\"" + end + assigns = @action_view.assigns.dup + + if content_for_layout = @action_view.instance_variable_get("@content_for_layout") + assigns['content_for_layout'] = content_for_layout + end + + result = @action_view.instance_eval do + assigns.each do |key,val| + instance_variable_set "@#{key}", val + end + local_assigns.each do |key,val| + class << self; self; end.send(:define_method,key){ val } + end + ERB.new(template).result(binding) + end + end + + end + +end \ No newline at end of file diff --git a/vendor/plugins/rfpdf/test/test_helper.rb b/vendor/plugins/rfpdf/test/test_helper.rb new file mode 100644 index 000000000..2e2ea3bc5 --- /dev/null +++ b/vendor/plugins/rfpdf/test/test_helper.rb @@ -0,0 +1 @@ +#!/usr/bin/env ruby \ No newline at end of file -- cgit v1.2.3