pasdoc/0000700000175000017500000000000013237145537012473 5ustar michalismichalispasdoc/pasdoc-fpc.cfg0000700000175000017500000000240713034465544015177 0ustar michalismichalis# -*- mode: shell-script -*- # These are FPC-specific options for compiling pasdoc. # Path options (-Fu, -Fi) are not specified here -- they are specified only # in the Makefile (to avoid duplication, of course). # # What are the reasons for maintaining this cfg file # (as opposed to dropping this cfg file and specifying all compilation options # in the Makefile) ? # # 1. This looks a little clearer than typing these options in the Makefile ? # # 2. Using #IFDEF AMIGA below. Although Amiga is not actually supported # target now. # # In the future, this file may be removed and everything will be handled # only inside the Makefile. # Syntax settings: objfpc mode, ansistrings -S2 -Sh # Io checking -Ci # Show warnings and notes -vwn #IFDEF RELEASE #ifdef AMIGA -Ct #endif # Optimize, for faster code -OG -O2 #ELSE # Range, overflow, stack checking, verify object method call validity -Cr -Co -Ct -CR # Include assertions -Sa # Generate debug info for gdb, include lineinfo -g -gl # On Mac OS X > 10.4 debug information is needed in dwarf format. # Seems that it works also in Mac OS X 10.4.11, so we just activate dwarf always. # See http://lazarus.freepascal.org/index.php?topic=10972.0 #ifdef DARWIN -gw #endif # Uncomment to check for memory leaks. #-gh #ENDIF pasdoc/README.md0000600000175000017500000000054213034465544013753 0ustar michalismichalis# PasDoc PasDoc is a documentation tool for Pascal and Object Pascal source code. Documentation is generated from comments found in the source code or from external files. Many formatting @-tags are supported. Many output formats are supported, including HTML and LaTeX. See the documentation on http://pasdoc.sourceforge.net/ . # License GNU GPL 2. pasdoc/.gitattributes0000600000175000017500000000003713034465544015366 0ustar michalismichalis*.inc linguist-language=Pascal pasdoc/tests/0000700000175000017500000000000013237142323013623 5ustar michalismichalispasdoc/tests/run_all_tests.sh0000755000175000017500000000251313237136021017051 0ustar michalismichalis#!/bin/bash set -eu # Run all PasDoc tests. make clean # fpcunit tests -------------------------------------------------------------- cd fpcunit/ make cd ../ # run on testcases, compare with correct output ------------------------------ ALL_OUTPUT_FORMATS='html htmlhelp latex latex2rtf simplexml' cd scripts/ ./download_correct_tests_output.sh $ALL_OUTPUT_FORMATS cd ../ for OUTPUT_FORMAT in $ALL_OUTPUT_FORMATS; do cd testcases/ ../scripts/mk_tests.sh $OUTPUT_FORMAT cd ../ diff -wur correct_output/$OUTPUT_FORMAT current_output/$OUTPUT_FORMAT done # If you detect any *valid* differences, i.e. the new version is more correct, # run this: # cd scripts/ && ./upload_correct_tests_output.sh $SOURCEFORGE_USERNAME $ALL_OUTPUT_FORMATS && cd ../ # validation ----------------------------------------------------------------- # Validate current_output/html, requires onsgmls installed # This is unfortunately not working for HTML 5 now. # scripts/validate_html.sh # Validate current_output/simplexml, requires xmllint installed scripts/validate_simplexml.sh # cache tests ---------------------------------------------------------------- cd scripts/ for OUTPUT_FORMAT in $ALL_OUTPUT_FORMATS; do ./check_cache.sh $OUTPUT_FORMAT done ./check_cache_format_independent.sh html latex ./check_cache_format_independent.sh latex2rtf htmlhelp pasdoc/tests/fpcunit/0000700000175000017500000000000013237143041015271 5ustar michalismichalispasdoc/tests/fpcunit/testpasdoc_utils.pas0000600000175000017500000000376113237143041021400 0ustar michalismichalis{ Copyright 2016-2016 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { Test PasDoc_Utils. } unit TestPasdoc_Utils; interface uses Classes, SysUtils, FpcUnit, TestUtils, TestRegistry; type TTestPasDocUtils = class(TTestCase) published procedure TestRemoveIndentation; end; implementation uses PasDoc_Utils; procedure TTestPasDocUtils.TestRemoveIndentation; begin AssertEquals( ' ' + LineEnding + // whitespace line will be completely ignored ' foo' + LineEnding + 'bar' + LineEnding + ' xyz', RemoveIndentation( ' ' + LineEnding + // whitespace line will be completely ignored ' foo' + LineEnding + ' bar' + LineEnding + ' xyz')); AssertEquals( ' '#9' ' + LineEnding + // whitespace line will be completely ignored #9' foo' + LineEnding + 'bar' + LineEnding + ' xyz', RemoveIndentation( ' '#9' ' + LineEnding + // whitespace line will be completely ignored ' '#9#9' foo' + LineEnding + ' '#9'bar' + LineEnding + ' '#9' xyz')); AssertEquals('begin Writeln(''Hello world''); end; { This works ! }', RemoveIndentation(' begin Writeln(''Hello world''); end; { This works ! } ')); end; initialization RegisterTest(TTestPasDocUtils); end. pasdoc/tests/fpcunit/test_pasdoc.lpr0000600000175000017500000000236213034465544020337 0ustar michalismichalis{ Copyright 2016-2016 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { Automatic test runner. } uses SysUtils, ConsoleTestRunner, { specify TestXxx units below. } TestPasDoc_Utils, TestPasdoc_GenHtml; var Application: TTestRunner; begin Application := TTestRunner.Create(nil); try Application.Title := 'PasDoc - Test runner (using fpcunit)'; DefaultFormat := fPlain; Application.Initialize; Application.Run; finally FreeAndNil(Application) end; end. pasdoc/tests/fpcunit/testpasdoc_genhtml.pas0000600000175000017500000000601313237143041021667 0ustar michalismichalis{ Copyright 2016-2016 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { Test PasDoc_GenHtml. } unit TestPasdoc_GenHtml; interface uses Classes, SysUtils, FpcUnit, TestUtils, TestRegistry; type TTestPasDocGenHtml = class(TTestCase) published procedure TestFormatPascalCode; end; implementation uses PasDoc_GenHtml; type { Descendant of THTMLDocGenerator, to access here some protected methods of THTMLDocGenerator. } TMyHTMLDocGenerator = class(THTMLDocGenerator) end; procedure TTestPasDocGenHtml.TestFormatPascalCode; var Gen: TMyHTMLDocGenerator; begin Gen := TMyHTMLDocGenerator.Create(nil); try AssertEquals('

' + LineEnding + LineEnding + '
begin Writeln(''Hello world''); end; { This works ! } 
' + LineEnding + LineEnding + '

', Gen.FormatPascalCode('begin Writeln(''Hello world''); end; { This works ! } ')); { should work the same as before (there was a bug at some point where the lack of space right after comment was confusing the code) } AssertEquals('

' + LineEnding + LineEnding + '
begin Writeln(''Hello world''); end; { This works ! }
' + LineEnding + LineEnding + '

', Gen.FormatPascalCode('begin Writeln(''Hello world''); end; { This works ! }')); AssertEquals('

' + LineEnding + LineEnding + '
{ unterminated 
' + LineEnding + LineEnding + '

', Gen.FormatPascalCode('{ unterminated ')); AssertEquals('

' + LineEnding + LineEnding + '
(* unterminated 
' + LineEnding + LineEnding + '

', Gen.FormatPascalCode('(* unterminated ')); AssertEquals('

' + LineEnding + LineEnding + '
// unterminated 
' + LineEnding + LineEnding + '

', Gen.FormatPascalCode('// unterminated ')); finally FreeAndNil(Gen) end; end; initialization RegisterTest(TTestPasDocGenHtml); end. pasdoc/tests/fpcunit/Makefile0000600000175000017500000000005713034465544016747 0ustar michalismichalis.PHONY: default default: make -C ../../ tests pasdoc/tests/README.md0000600000175000017500000002725713237137561015131 0ustar michalismichalis# Tests for PasDoc Run all the tests simply by `run_all_tests.sh`. This runs all relevant tests described below. It requires a Unix shell (on Windows, you should install Cygwin or MSys). # Testcases The subdirectory `testcases` contains some short and difficult Pasdoc sources. Some of these are taken from bugreports, to make sure we don't reintroduce an old bug again. Some of these are written to test new features. To add a new testcase, 1. first of all just add the file here (follow the naming conventions below, usually just ok_xxx.pas). 2. add an appropriate line at the end of scripts/mk_tests.sh. 3. after you make sure it works, you may upload new version of "correct tests", see below. Or just notify Michalis about it :) Using these tests fully requires having some standard Unix tools installed and available on $PATH. You need GNU `make`, bash, diff. Also wget is used for downloading correct tests for comparison. And tar, scp are used for uploading correct tests by developers. Of course, you also need the `pasdoc` binary available on $PATH. ## Naming of Pascal unit files in this directory - `ok_*` Means that this unit should be parsed by pasdoc without any warnings. - `warning_*` Means that this unit should be parsed by pasdoc (i.e. some documentation for it should be generated), but some warnings should be reported by pasdoc. - `error_*` Means that pasdoc should not be able to parse this unit, documentation for this unit shouldn't be possible to generate. pasdoc should generate proper error message for this case. Note that pasdoc may report errors as warnings, e.g. "Warning[2]: Error EPasDoc: error_line_number.pas(26): could not open include file not_existing.inc ..." Pasdoc calls this a warning, since, after all, it can continue it's work by simply skipping to the next unit. But for the sake of this distinction, this is an *error*, not merely a *warning*. The precise difference between an error and a warning is: "error makes impossible to generate documentation for this unit". Units are divided into these 3 groups because: - These groups are precisely defined, so there shouldn't be any concern about "where this test unit belongs". - We should be eventually able to use output messages and exit status of pasdoc to automate testing as much as we can. Notes: - Please keep prefixes "ok_", "warning_", "error_" lowercase so that e.g. the file-mask `ok_*` works as expected on case-sensitive file-systems. Try to follow the convention "prefix_description_of_test_lowercase_with_underscores.pas". - Most of these units will have empty implementation. They are not supposed to be ever compiled by anything. - There is no requirement here that the interface of units placed here must be correct Pascal code. Pasdoc should be able to handle even incorrect units. Usually it should break with some parsing error on such units, but it doesn't have to (after all, pasdoc is not meant to exactly reimplement some part of a compiler that carefully checks syntax and everything), it may try to generate some docs. But even with incorrect units, it obviously shouldn't fail with some miserable error (like sigsegv :) or do anything that it shouldn't, like removing some files or so. - If you want to test unit with a special pasdoc's command-line, you must add appropriate line at the end of ./mk_tests.sh script. ## Possible tests to be done First of all, you can just run `run_all_tests.sh` that runs all relevant tests described below. - Generate output like this: ``` cd testcases/ ../scripts/mk_tests.sh html ``` Tests are created in `current_output/html` subdirectory. Some of our other scripts will use it. You can just manually look at units' sources and comments there to know what generated documentation should look like (in case of `ok_*` and `warning_*` files) and what warnings/errors should be reported (in case of `warning_*` and `error_*` files). Of course, even briefly checking that all `ok_*` units generate no warnings, all `warning_*` units generate some warnings (and produce some docs) and all `error_*` units generate errors (and no docs) is still a better test than nothing... Note that pasdoc messages (printed on stdout) will not be shown when you will make tests using mentioned `make ...' commands. Instead they will be saved to files named PASDOC-OUTPUT in appropriate subdirectories of tests output. This way we treat messages printed by pasdoc as important part of pasdoc's output, they are included in "correct tests output" (see below) so comparing with "correct tests output" also checks that pasdoc messages are correct (warnings are as they should be and where they should be etc.) - "Correct tests output" give an automated way to verify `current_output/html`. We maintain on [http://pasdoc.sourceforge.net/correct_tests_output/] something that we call "correct output of tests". Everyone can download them simply by: ``` cd scripts/ ./download_correct_tests_output.sh html ``` Then whenever you want you can compare current documentation generated by pasdoc to downloaded "correct output" e.g. using ``` diff -ur correct_output/html/ current_output/html/ ``` Note that *failure* of comparison does not necessarily mean that current pasdoc *has* a bug, since it's possible that current output of pasdoc is different (because e.g. we improved and changed something) but still correct. Also *success* of comparison does not mean that current pasdoc does *not* have a bug, because this "current output" was just accepted at some point by human as "correct". So, this is unfortunately no ultimate test. But in practice it often works great, and allows us to quickly check that nothing is broken :) When no output changes are expected, or the changes are very local, then looking at "diff" output is a great and simple way to test. If pasdoc's developer sees at any point that "current output" differs from "correct output" and also he carefully checked that "current output" is still correct, than he should upload his "current output" as new "correct output" by entering scripts/ directory and executing ``` ./upload_correct_tests_output.sh username html ``` See documentation inside scripts/upload_correct_tests_output.sh for more detailed docs. Note that before uploading you should be relatively sure that you compared against most recent version of "correct output", to save yourself trouble of unnecessary uploading. Beware that script `upload_correct_tests_output.sh' will upload everything that you will have inside subdirectory of given format. This is painful in case of output like LaTeX, where you can accidentally upload files like docs.pdf or docs.dvi (that shouldn't be uploaded). In this case you can do something like `make clean latex' before uploading to be sure that you upload only "docs.tex" file. - `scripts/validate_html.sh` This is an automatic test that makes html docs for all test units and validates them using sgml validator. onsgmls program must be installed for this to work. Links how to install onsgmls may be found here [https://github.com/pasdoc/pasdoc/wiki/HtmlOutput]. - `scripts/validate_simplexml.sh` This is an automatic test that makes simplexml docs for all test units and validates them using xmllint. xmllint must be installed for this to work. We do not have any DTD, so it doesn't check that our XML files conform to anything. But at least it checks that they are well-formed (all open elements are closed and such). - Cache tests: ``` cd scripts/ ./check_cache.sh html ./check_cache.sh latex ``` $1 arg for this script is required and is any valid pasdoc format (as for pasdoc's --format option). Rest of args are just passed to pasdoc as they are. This runs pasdoc twice using the cache, 1st time the cache directory is empty and pasdoc writes the cache, 2nd time pasdoc should read everything from the cache. The script then checks that pasdoc's output was identical each time (comparing them with `diff -u', so you get diff on output if something does not match). This somehow checks that writing the cache and reading the cache and writing documentation basing on information obtained from the cache (instead of from parsing units) works OK. Everything is read/written to a temporary directory scripts/check_cache_tmp/, that is removed at the beginning and at the end of the script. (It's removed at the beginning, and also by `make clean`, just to make sure that no garbage is left there, in case script failed for whatever reason.) So this script is mostly independent from the rest of the tests here -- it just happens to use the same test units. In case comparison between two outputs failed both outputs and left in scripts/check_cache_tmp/, so developer can inspect them closer. - Test cache is format-independent: ``` cd scripts/ ./check_cache_format_independent.sh html latex ./check_cache_format_independent.sh latex html ``` Requires two arguments, two names of pasdoc output format. These two formats should be different for this test to be really sensible (and better than check_cache.sh), but they can also be equal and test should pass anyway. This is similar to ./check_cache.sh test, but it checks that cache format is independent of pasdoc's output format. 1st it generates output with format 1, without using any cache. 2nd it generates output with format 2, writing the cache. 3rd it generates output with format 1, this time reading the cache. Then it checks that 1st and 3rd output are equal. This way it checks that cache generated while doing format 2 may be reused while making format 1. So it tests that cache format is really independent from pasdoc's chosen output format. ## Various notes `make clean` will clean this directory. Note that make used must be GNU make. Under Linux this is standard, under FreeBSD this is called `gmake`, under Win32 you can get this with e.g. FPC, MinGW or Cygwin. scripts/ subdirectory contains some helpful things for running tests. These should be scripts that perform some additional tests on test units available here (like check_cache.sh), but also some helper scripts/files for Makefile in this directory. ## Subdirectory testcases/todo/ It contains units that are known to be incorrectly handled by pasdoc by now. "Incorrectly handled" may mean that generated documentation is incorrect, or that pasdoc fails with some error on correct input, but "incorrectly handled" may also mean that pasdoc fails to write a proper warning/error in case when input (unit's sources) is obviously wrong. Files inside todo/ should follow exactly the same naming convention as units in this directory (`ok_*`, `warning_*`, `error_*`). In this case, unit's name tells what pasdoc *should* do with such unit, even if it doesn't do it for now. The idea is that when developer fixes a problem with some unit in tests/todo/ directory, he can simply move this unit to tests/. These files are in separate todo/ subdirectory, because otherwise every time we would like to check our tests we would have to remember "oh, such-and-such test fails but it's a known problem, so I can ignore it". This would be troublesome, because *usually* we will want to test whether we did not break anything that previously worked, and we will not care that there are still some unresolved problems in pasdoc. --- And that's all for now. Comments are most welcome. pasdoc/tests/scripts/0000700000175000017500000000000013237142210015305 5ustar michalismichalispasdoc/tests/scripts/validate_simplexml.sh0000700000175000017500000000054213237126412021536 0ustar michalismichalis#!/bin/bash set -eu # This scripts runs xmllint to check every *.xml file in simplexml/ # subdirectory, recursively. # It's meant to be run using `make validate_simplexml' in parent directory. # # See ../README for comments. find current_output/simplexml/ -iname '*.xml' \ -exec sh -c 'echo ---- Validating {}' ';' \ -exec xmllint --noout '{}' ';' pasdoc/tests/scripts/download_correct_tests_output.sh0000700000175000017500000000171013034465544024052 0ustar michalismichalis#!/bin/bash set -eu # Always run this script with current directory set to # directory where this script is, # i.e. tests/scripts/ inside pasdoc sources. # # $1 is pasdoc's format name, like for pasdoc's --format option. # # This script # - cleans ../correct_output/$1/ # - downloads [http://pasdoc.sourceforge.net/correct_tests_output/$1.tar.gz] # - and unpacks it to ../correct_output/$1/ # # Requisites: downloading is done using `wget'. download_one_format () { # Parse options FORMAT="$1" shift 1 ARCHIVE_FILENAME_NONDIR="$FORMAT".tar.gz rm -Rf ../correct_output/"$FORMAT"/ ../correct_output/"$ARCHIVE_FILENAME_NONDIR" mkdir -p ../correct_output/ cd ../correct_output/ echo "Downloading $ARCHIVE_FILENAME_NONDIR ..." wget http://pasdoc.sourceforge.net/correct_tests_output/"$ARCHIVE_FILENAME_NONDIR" echo "Unpacking $ARCHIVE_FILENAME_NONDIR ..." tar xzf "$ARCHIVE_FILENAME_NONDIR" } for FORMAT; do download_one_format "$FORMAT" donepasdoc/tests/scripts/ssh_chmod_writeable_by_pasdoc.sh0000700000175000017500000000160513034465544023713 0ustar michalismichalis#!/bin/bash set -eu # $1 is your username on sourceforge, # $2 is directory on sourcefore (usually you will start this with # /home/project-web/pasdoc/...). # # This script logs to sourceforge using given username # (you will be asked for password unless you set up ssh keys) # and executes # chgrp -R pasdoc * # chmod -R g+w * # This means that every file in given directory is made writeable # by pasdoc group, which means pasdoc developers. # # Later note: chgrp -R pasdoc is not supported on SF anymore. # Group is always "apache", and for security I would not like to have # files writeable by apache on a shared host. echo 'ssh_chmod_writeable_by_pasdoc: Not changing permissions, as it is no longer possible on SourceForge.' # SF_USERNAME="$1" # SF_PATH="$2" # shift 2 # ssh -l "$SF_USERNAME" shell.sourceforge.net < scripts/check_cache_tmp/pasdoc_output.txt } pasdoc_call () { echo 'Running pasdoc:' run_echo pasdoc \ --format="$OUTPUT_FORMAT" -S - \ --exclude-generator \ --cache-dir=scripts/check_cache_tmp/cache/ \ "$@" } # ------------------------------------------------------------ OUTPUT_FORMAT="$1" shift 1 rm -Rf check_cache_tmp/ mkdir -p check_cache_tmp/cache/ check_cache_tmp/1/ check_cache_tmp/2/ cd .. echo "Checking cache for format ${OUTPUT_FORMAT}" pasdoc_call --output=scripts/check_cache_tmp/1/ pasdoc_call --output=scripts/check_cache_tmp/2/ echo 'Comparing two outputs:' diff -u scripts/check_cache_tmp/1/ scripts/check_cache_tmp/2/ echo 'OK, test passed.' rm -Rf scripts/check_cache_tmp/ pasdoc/tests/scripts/upload_correct_tests_output.sh0000700000175000017500000001075613237135442023535 0ustar michalismichalis#!/bin/bash set -eu # Always run this script with current directory set to # directory where this script is, # i.e. tests/scripts/ inside pasdoc sources. # # This script uploads to # [http://pasdoc.sourceforge.net/correct_tests_output/] # current output of tests generated in ../ . # This means that you're accepting current output of tests # (for some output formats) as "correct". # # Options "$2" and following are the names of output formats # (as for pasdoc's --format option), these say which subdirectory # of ../tests/ should be uploaded. # # Option "$1" is your username on sourceforge. # Note that you will be asked (more than once) for your password # unless you configured your ssh keys, which is recommended. # # After uploading it calls ./download_correct_tests_output.sh # for every uploaded output. # This way it checks that files were correctly uploaded # and also sets your local version of ../correct_output/ directory # to the correct state. # So after calling this script successfully, directories # ../$2/ and ../correct_output/$2/ are always equal. # (and ../$3/ and ../correct_output/$3/, and so on). # # Precisely what files are uploaded for each format $FORMAT: # - $FORMAT.tar.gz -- archived contents of ../$FORMAT/ # Easily downloadable, e.g. by download_correct_tests_output. # - $FORMAT directory -- copy of ../$FORMAT/ # Easy to browse, so we can e.g. make links from pasdoc's wiki # page ProjectsUsingPasDoc to this. # - $FORMAT.timestamp -- current date/time, your username (taken from $1) # to make this information easy available. # (to be able to always answer the question "who and when uploaded this ?") # # Note: after uploading, it sets group of uploaded files # to `pasdoc' and makes them writeable by the group. # This is done in order to allow other pasdoc developers # to also execute this script, overriding files uploaded by you. # # Requisites: `scp' command, `ssh' command. # Parse options SF_USERNAME="$1" shift 1 upload_one_format () { # Parse options FORMAT="$1" shift 1 # Prepare clean TEMP_PATH TEMP_PATH=upload_correct_tests_output_tmp/ rm -Rf "$TEMP_PATH" mkdir "$TEMP_PATH" # Prepare tar.gz archive ARCHIVE_FILENAME_NONDIR="$FORMAT.tar.gz" ARCHIVE_FILENAME="$TEMP_PATH""$ARCHIVE_FILENAME_NONDIR" echo "Creating $ARCHIVE_FILENAME_NONDIR ..." # Note: We temporary jump to ../current_output/, this way we can pack files using # "$FORMAT". cd ../current_output/ tar czf ../scripts/"$ARCHIVE_FILENAME" "$FORMAT"/ cd ../scripts/ # Prepare timestamp file TIMESTAMP_FILENAME_NONDIR="$FORMAT.timestamp" TIMESTAMP_FILENAME="$TEMP_PATH""$TIMESTAMP_FILENAME_NONDIR" echo "Creating $TIMESTAMP_FILENAME_NONDIR ..." date --rfc-2822 > "$TIMESTAMP_FILENAME" echo "$SF_USERNAME" >> "$TIMESTAMP_FILENAME" # Do the actual uploading to the server echo "Uploading ..." SF_PATH=/home/project-web/pasdoc/htdocs/correct_tests_output/ SF_CONNECT="$SF_USERNAME",pasdoc@web.sourceforge.net:"$SF_PATH" scp "$ARCHIVE_FILENAME" "$TIMESTAMP_FILENAME" "$SF_CONNECT" # I could do here simple # scp -r ../"$FORMAT"/ "$SF_CONNECT" # but this requires uploading all files unpacked. # It's much quickier to just log to server and untar there uploaded archive. # # Old notes: # # After uploading, I changed permission of uploaded and unpacked # files so that they are writeable by pasdoc group # (which means pasdoc developers). # Note that I don't do here simple # ./ssh_chmod_writeable_by_pasdoc.sh "$SF_USERNAME" "$SF_PATH" # because I can chmod only the files that "$SF_USERNAME" owns # (so I chmod only the files that I uploaded). # # Later note: This needed anymore: since new SF username is like # "kambi,pasdoc" (not just "kambi"), so I'm logged with default # group "pasdoc" already. # # Later note: This is not possible anymore. # Group is forced to be Apache, it seems. # So for security we don't want to make these files writeable. ssh "$SF_USERNAME",pasdoc@shell.sourceforge.net <' "$OUTPUT_FILENAME" # Temporary set +e, to ignore exit status from pasdoc set +e "$@" > "$OUTPUT_FILENAME" set -e } # Run pasdoc with given command-line parameters. # First parameter is the name of subdirectory where we place test results # (including PASDOC-OUTPUT file), this is always inside "$FORMAT" subdirectory. mk_test () { OUTPUT_PATH=../current_output/"$FORMAT"/"$1"/ shift 1 mkdir -p "$OUTPUT_PATH" PASDOC_OUTPUT_FILENAME="$OUTPUT_PATH"PASDOC-OUTPUT run_echo "$PASDOC_OUTPUT_FILENAME" \ pasdoc --format "$FORMAT" --exclude-generator \ --output="$OUTPUT_PATH" "$@" } # parse params ---------------------------------------- FORMAT="$1" shift 1 # Run tests ---------------------------------------- # Make a test of many units with normal pasdoc command-line. # # Note: most new tests should not be added here. # It was the 1st approach to just call something like `pasdoc *.pas' here # to test everything. But this was not good, because # 1. obviously you can't do tests with specialized pasdoc command-line options # 2. in case of output formats that create some "index" pages # (like AllClasses.html in HTML / HtmlHelp output) small # changes and additions have too global impact on many parts of # documentation, so output from `diff -wur correct_output/html html/' # is harder to grok for humans. # # Instead, usually you should add new test units as new calls to # `mk_test ...' lower in this script. # mk_test large_test "$SORT_OLD" \ error_line_number.pas \ ok_cdecl_external.pas \ ok_complicated_record.pas \ ok_deprecated_tag.pas \ ok_directive_as_identifier.pas \ ok_expanding_descriptions.pas \ ok_hint_directives.pas \ ok_line_break.pas \ ok_link_class_unit_level.pas \ ok_link_explicite_name.pas \ ok_links_2.pas \ ok_links.pas \ ok_nodescription_printing.pas \ ok_paragraph_in_single_line_comment.pas \ ok_tag_name_case.pas \ ok_tag_params_no_parens.pas \ ok_value_member_tags.pas \ warning_abstract_termination.pas \ warning_abstract_twice.pas \ warning_not_existing_tags.pas \ warning_tags_no_parameters.pas \ warning_value_member_tags.pas # Make a specialized test of some units that need special # command-line. This is also useful if you want to just make # some units in a separate subdirectories, to separate them # from the rest of tests (e.g. because you want to test AllXxx.html pages). # This is also useful if you want to test the same unit more than once, # with different command-line options (e.g. like ok_sorting.pas). # # Try to place each entry below on separate line, # so that it's easy to temporary switch some test on/off by # simply commenting / uncommenting that line. # mk_test ok_const_1st_comment_missing --marker=: "$SORT_OLD" ok_const_1st_comment_missing.pas mk_test ok_link_1_char --visible-members 'private,public,published' "$SORT_OLD" ok_link_1_char.pas mk_test ok_auto_abstract --auto-abstract "$SORT_OLD" ok_auto_abstract.pas mk_test warning_incorrect_tag_nesting "$SORT_OLD" warning_incorrect_tag_nesting.pas mk_test ok_param_raises_returns_proctype "$SORT_OLD" ok_param_raises_returns_proctype.pas mk_test ok_no_sort '--sort=functions,non-record-fields,methods,properties' ok_no_sort.pas mk_test ok_sorting_all "$SORT_ALL" ok_sorting.pas mk_test ok_sorting_none --sort= ok_sorting.pas mk_test ok_introduction_conclusion ok_introduction_conclusion.pas --introduction=ok_introduction.txt --conclusion=ok_conclusion.txt mk_test ok_property_decl ok_property_decl.pas mk_test ok_multiple_vars ok_multiple_vars.pas mk_test ok_class_function ok_class_function.pas mk_test ok_latex_head --latex-head=ok_latex_head.tex ok_latex_head.pas mk_test ok_longcode_underscores ok_longcode_underscores.pas mk_test ok_longcode_comment ok_longcode_comment.pas mk_test ok_longcode_dash ok_longcode_dash.pas mk_test ok_longcode_special_chars ok_longcode_special_chars.pas mk_test error_introduction_twice_anchors_unit --introduction=error_introduction_twice_anchors.txt error_introduction_twice_anchors_unit.pas mk_test ok_longcode_float_hex ok_longcode_float_hex.pas mk_test ok_see_also ok_see_also.pas mk_test ok_implicit_visibility_public ok_implicit_visibility.pas mk_test ok_implicit_visibility_published --implicit-visibility=published ok_implicit_visibility.pas mk_test ok_implicit_visibility_implicit_yes --implicit-visibility=implicit --visible-members=public,implicit ok_implicit_visibility.pas mk_test ok_implicit_visibility_implicit_no --implicit-visibility=implicit --visible-members=public ok_implicit_visibility.pas mk_test ok_bold_italic ok_bold_italic.pas mk_test warning_inherited_test warning_inherited_test.pas mk_test ok_preformatted_test ok_preformatted_test.pas mk_test ok_dashes ok_dashes.pas mk_test ok_lists ok_lists.pas mk_test warning_lists warning_lists.pas mk_test ok_table ok_table.pas mk_test ok_table_nonlatex ok_table_nonlatex.pas mk_test warning_table warning_table.pas mk_test ok_macros ok_macros.pas mk_test error_macros error_macros.pas mk_test error_macros_recursive error_macros_recursive.pas mk_test ok_macros_off --no-macro ok_macros_off.pas mk_test ok_item_set_number ok_item_set_number.pas mk_test error_unexpected_eof error_unexpected_eof.pas mk_test error_unexpected_eof_2 error_unexpected_eof_2.pas mk_test error_expected_semicolon error_expected_semicolon.pas mk_test ok_record_case_parsing ok_record_case_parsing.pas mk_test ok_record_with_case ok_record_with_case.pas mk_test ok_multiple_fields ok_multiple_fields.pas mk_test ok_back_comment ok_back_comment.pas mk_test warning_back_comment warning_back_comment.pas mk_test ok_auto_link --auto-link ok_auto_link.pas mk_test ok_introduction_pre_link ok_introduction_pre_link_unit.pas --introduction=ok_introduction_pre_link.txt mk_test ok_table_of_contents ok_table_of_contents_unit.pas --introduction=ok_table_of_contents.txt mk_test warning_link_in_seealso warning_link_in_seealso.pas mk_test ok_caret_character ok_caret_character.pas mk_test ok_unit_uses_filename --write-uses-list ok_unit_uses_filename.pas mk_test ok_enum_explicit_assign ok_enum_explicit_assign.pas mk_test ok_if_directive ok_if_directive.pas mk_test ok_include_environment ok_include_environment.pas mk_test ok_enum_explicit_values ok_enum_explicit_values.pas mk_test ok_description_test --description ok_description_test.txt ok_description_test.pas mk_test ok_program --write-uses-list ok_program.pas mk_test ok_operator_test ok_operator_test.pas mk_test error_line_number_2 error_line_number_2.pas mk_test ok_dispid_method ok_dispid_method.pas mk_test ok_longcode_highlight ok_longcode_highlight.pas mk_test ok_non_matching_paren ok_non_matching_paren.pas mk_test ok_image ok_image.pas mk_test ok_include --introduction=ok_include_intro.txt ok_include.pas mk_test ok_class_var ok_class_var.pas mk_test error_line_number_3 error_line_number_3.pas mk_test ok_not_defined_omit ok_not_defined_omit.pas mk_test ok_abstract_sealed ok_abstract_sealed.pas mk_test ok_library ok_library.dpr mk_test ok_static_member ok_static_member.pas mk_test ok_strict_visibilities --visible-members protected,public,strictprotected,strictprivate ok_strict_visibilities.pas mk_test ok_weird_record ok_weird_record.dpr mk_test ok_include_quoted ok_include_quoted.pas mk_test ok_relative_include test_subdir/ok_relative_include_1.pas test_subdir/another_test_subdir/ok_relative_include_2.pas mk_test ok_list_item_set_number ok_list_item_set_number.pas mk_test ok_enum_field_var ok_enum_field_var.pas mk_test ok_back_comment_private ok_back_comment_private.pas mk_test ok_back_comment_class ok_back_comment_class.pas mk_test ok_excluded_unit ok_excluded_unit.pas mk_test ok_comment_over_uses_clause ok_comment_over_uses_clause.pas warning_back_comment_over_uses_clause.pas mk_test ok_interface_implicit ok_interface_implicit.pas --implicit-visibility=implicit mk_test ok_dot_unitname ok_dot_unitname.pas --write-uses-list mk_test ok_longcode_end_semicolon ok_longcode_end_semicolon.pas mk_test warning_desc_end warning_desc_end.pas mk_test ok_different_image_same_filename ok_different_image_same_filename_dir1/unit1.pas ok_different_image_same_filename_dir2/unit2.pas mk_test ok_enumeration_auto_abstract ok_enumeration_auto_abstract.pas --auto-abstract mk_test ok_ignore_leading ok_ignore_leading.pas --ignore-leading=* mk_test ok_ignore_leading_star ok_ignore_leading_star.pas --ignore-leading=* --staronly mk_test ok_ignore_leading_hash ok_ignore_leading_hash.pas --ignore-leading=# mk_test ok_ignore_leading_length2 ok_ignore_leading_length2.pas --ignore-leading=#? mk_test ok_packed_class_object ok_packed_class_object.pas mk_test ok_vorbisfile ok_vorbisfile.pas mk_test ok_procedural_const ok_procedural_const.pas mk_test ok_deprecated_const_string ok_deprecated_const_string.pas mk_test ok_external_class_hierarchy ok_external_class_hierarchy.pas --external-class-hierarchy=ok_external_class_hierarchy.txt mk_test ok_anonymous_methods ok_anonymous_methods.pas mk_test ok_class_record_helpers ok_class_record_helpers.pas mk_test utf_bom_test ok_bom.pas error_bom_utf16_be.pas error_bom_utf16_le.pas error_bom_utf32_be.pas mk_test ok_cvar ok_cvar.pas mk_test ok_nested_types ok_nested_types.pas mk_test ok_generic ok_generic.pas mk_test ok_helpinsight_comments ok_helpinsight_comments.pas mk_test ok_attributes ok_attributes.pas mk_test ok_final ok_final.pas mk_test ok_at_character_in_verbatim ok_at_character_in_verbatim.pas mk_test ok_deprecated_directive_note ok_deprecated_directive_note.pas mk_test ok_enum_links ok_enum_links.pas mk_test ok_no_link_inside_class ok_no_link_inside_class.pas pasdoc/tests/scripts/check_cache_format_independent.sh0000700000175000017500000000324713237136366024016 0ustar michalismichalis#!/bin/bash set -eu # When running this script, the current directory # must be the directory of the script, i.e. tests/scripts/ # in pasdoc's sources. # # See ../README.md file for docs for this script. # functions ------------------------------------------------------------ run_echo () { echo "$@" scripts/find_all_tests_for_check_cache.sh | "$@" \ > scripts/check_cache_format_independent_tmp/pasdoc_output.txt } pasdoc_call () { echo 'Running pasdoc:' run_echo pasdoc -S - --exclude-generator "$@" } # ------------------------------------------------------------ OUTPUT_FORMAT_1="$1" OUTPUT_FORMAT_2="$2" shift 2 rm -Rf check_cache_format_independent_tmp/ mkdir -p \ check_cache_format_independent_tmp/cache/ \ check_cache_format_independent_tmp/1/ \ check_cache_format_independent_tmp/2/ \ check_cache_format_independent_tmp/3/ cd .. echo "Checking cache-independent between formats ${OUTPUT_FORMAT_1} and ${OUTPUT_FORMAT_2}" # No cache, format 1 pasdoc_call \ --output=scripts/check_cache_format_independent_tmp/1/ \ --format="$OUTPUT_FORMAT_1" # Make cache while making format 2 pasdoc_call \ --output=scripts/check_cache_format_independent_tmp/2/ \ --format="$OUTPUT_FORMAT_2" \ --cache-dir=scripts/check_cache_format_independent_tmp/cache/ # Use cache with format 1 pasdoc_call \ --output=scripts/check_cache_format_independent_tmp/3/ \ --format="$OUTPUT_FORMAT_1" \ --cache-dir=scripts/check_cache_format_independent_tmp/cache/ echo 'Comparing two outputs:' diff -ur \ scripts/check_cache_format_independent_tmp/1/ \ scripts/check_cache_format_independent_tmp/3/ echo 'OK, test passed.' rm -Rf scripts/check_cache_format_independent_tmp/ pasdoc/tests/testcases/0000755000175000017500000000000013237143042015632 5ustar michalismichalispasdoc/tests/testcases/ok_hint_directives.pas0000600000175000017500000001276313237143041022213 0ustar michalismichalis{ @abstract(Test parsing "platform", "library" and "deprecated" directives (called collectively "hint directives") by pasdoc.) Related tracker bug: [ 1196073 ] "some modifiers are not parsed". We want to support all situations where these directives are allowed in modern FPC (>= 2.5.1) and Delphi. Their placement in unfortunately not consistent, thanks go to Borland. Quoting Delphi help (from Kylix 3): "Hint directives can be applied to type declarations, variable declarations, class and structure declarations, field declarations within classes or records, procedure, function and method declarations, and unit declarations." Summary: @orderedList( @item( Between "unit UnitName" and hints you @italic(mustn't) put any semicolon, and you @italic(mustn't) put any semicolons between hints. @br Same thing for CIOs (Classes / Interfaces / Objects / Records). @br Same thing for CIOs fields. @br Same thing for variables. @br Same thing for constants.) @item( Between "procedure/function Name (...)" and hints you @italic(must) put a semicolon, and semicolons between hints are allowed but not required. It seems that you can't specify "library" directive for procedures/functions -- why? Probably because "library" is a keyword and Borland was unable to correctly modify it's compiler to parse such thing. But pasdoc parses library directive correctly.) @item( Between method and hints you @italic(must) put a semicolon, and semicolon between hints is @italic(required). You can specify "library" directive for methods.) ) I'm unable to figure out how to specify these hints for normal (non-structural) types. If anyone can @unorderedList( @itemSpacing compact @item tell me how to specify hint directives for non-structural types or @item(explain why parsing these directives is so weird and inconsistent in Delphi or) @item(point me to some precise documentation by Borland specifying grammar rules with these directives) ) ... then please send email about this to pasdoc-main mailing list (or directly to me, Michalis Kamburelis, , if your comments about this do not really concern pasdoc). I will be grateful. Contrary to most units in tests/, this unit @italic(is) kept at compileable by Delphi/Kylix and FPC. That's because this unit is also a test whether we really specify here hint directives in the way parseable by Delphi/Kylix. } {$ifdef FPC} {$mode DELPHI} {$endif} unit ok_hint_directives platform library deprecated; interface { } procedure TestProcPlatform; platform; {procedure TestProcLibrary; library;} { } procedure TestProcDeprecated; deprecated; { } procedure TestProcCombined(SomeParams: Integer); {library } deprecated platform; { } function TestFuncPlatform: Integer; platform; {function TestFuncLibrary: Integer; library;} { } function TestFuncDeprecated: Integer; deprecated; { } function TestFuncCombined(SomeParams: Integer): Integer; {library } deprecated; { <- this semicolon is allowed but is optional } platform; type {TTestTypePlatform = Integer platform;} {TTestTypeLibrary = Integer library;} {TTestTypeDeprecated = Integer deprecated;} {TTestTypeCombined = Integer platform deprecated library;} { } TTestClassDeprecated = class TestFieldPlatform: Integer platform; TestFieldLibrary: Integer library; TestFieldDeprecated: Integer deprecated; TestFieldCombined: Integer library deprecated platform; { Testing on Delphi 7 / Kylix 3: Hint directives for properties are not allowed. Nowhere in Delphi help do they say that hint directives are supported for properties, and indeed it doesn't seem to be supported. property SomeProperty: Integer read TestFieldPlatform write TestFieldPlatform; platform;} { Testing on FPC 2.6.0: Hint directives for properties are allowed Ok. I don't know if this is Delphi-compatible or FPC extension, anyway PasDoc supports it too. } property TestPropertyCombined: Integer; library deprecated platform; property TestPropertyCombined2: Integer; library; deprecated; platform; { } procedure TestMethodLibrary; library; procedure TestMethodPlatform; platform; procedure TestMethodDeprecated; deprecated; procedure TestMethodCombined; library; deprecated; platform; end deprecated library; TTestRecordDeprecated = record TestFieldPlatform: Integer platform; end deprecated; var TestVarPlatform: Integer platform; TestVarLibrary: Integer library; TestVarDeprecated: Integer deprecated; TestVarCombined: Integer library deprecated platform; const TestConstPlatform = 1 platform; TestConstLibrary = 2 library; TestConstDeprecated = 3 deprecated; TestConstCombined = 4 deprecated library platform; implementation procedure TestProcPlatform; begin end; procedure TestProcLibrary; begin end; procedure TestProcDeprecated; begin end; procedure TestProcCombined(SomeParams: Integer); begin end; function TestFuncPlatform: Integer; begin end; function TestFuncLibrary: Integer; begin end; function TestFuncDeprecated: Integer; begin end; function TestFuncCombined(SomeParams: Integer): Integer; begin end; procedure TTestClassDeprecated.TestMethodLibrary; begin end; procedure TTestClassDeprecated.TestMethodPlatform; begin end; procedure TTestClassDeprecated.TestMethodDeprecated; begin end; procedure TTestClassDeprecated.TestMethodCombined; begin end; end.pasdoc/tests/testcases/warning_value_member_tags.pas0000600000175000017500000000173613237143041023543 0ustar michalismichalisunit warning_value_member_tags; interface type { @member MyField1 First description of MyField1. @member MyField2 First description of MyField2. @member MyField2 Second description of MyField2. @member NotExistsingMember Description of NotExistsingMember. This should cause 3 warnings: MyField1 has two descriptions, MyField2 has two descriptions, and NotExistsingMember does not exist. } TMyClass = class { @abstract(Second description of MyField1.) } MyField1: Integer; MyField2: Integer; end; { @value meOne First description of meOne. @value meOne Second description of meOne. @value meTwo First description of meTwo. @value meNotExisting Description of meNotExisting. This should cause 3 warnings: meOne has two descriptions, meTwo has two descriptions, and meNotExisting does not exist. } TMyEnum = ( meOne, { Second description of meTwo. } meTwo); implementation end.pasdoc/tests/testcases/ok_final.pas0000600000175000017500000000020313237143041020103 0ustar michalismichalisunit ok_final; interface type TMyObject = class public procedure MyFinalMethod; virtual; final; end; implementation end. pasdoc/tests/testcases/error_introduction_twice_anchors.txt0000600000175000017500000000016713034465544025242 0ustar michalismichalisSections with the same internal anchor-names are bad: @section(1 SecName 1st section) @section(1 SecName 2nd section) pasdoc/tests/testcases/error_back_comments.pas0000600000175000017500000000035413237143041022346 0ustar michalismichalisunit test; interface type MyEnum = ( me1, //!#lFrm/K~`QUthMX bNVA4R`[Ѡ~l&'ҐfM ze7hH䪒%G;Ei`,!Ċo&!1aAQq?!w[} ˡ}=?سFݹ}>v=9r8Eg2Fi״@mg#&`ݜ>4T#/Ym%Innv, ⩊:*0R\ fQaϿB&oW7hIS V!h>F.VeQ/m.)TYN>s4SRYw\> ~a*w0Ne~'媰#z޾NT=u\|T, b_~q 0k!Ocehv9 \+Y/*KAI >os5(0!1A?Nc [e[ț+Aoo \+;.q#ُ#!Q1Aaq?V mnY1!B>8" .SM=o` w,̡+3XCB;'sU!]<}\^\yw@;1 $!1AQaq?\nnPMqJQ[$ rtLtOF3-S8J&st ,4'X0xkZEe4&Z>-შ5Y<^7бCfF13)}j1&6I]I5X4+z9uxAToRsݑ7Y$fFL6Uci:z˸b+t?߀(,mSv_L7T#8Ɣ' [Cj~~aEXR2FN R dإ/ ۰.?|jBX2,9"dT|96VZQ0bk:xlT" &E8!_R dw@QE)<Ly9?N0I$3E &?ZۢXFE_xA-$_>q&8bޗ\:*HnnD4B|q";XMU2c5 %fZ /9MAfP``=@3,gT@W~?pasdoc/tests/testcases/ok_introduction_pre_link.txt0000600000175000017500000000044713034465544023476 0ustar michalismichalisLink to my section before defining it : @link(MySection) @section(1 MySection My section) Link to my section after defining it : @link(MySection) Link to my anchor before defining it : @link(MyAnchor) @anchor(MyAnchor) Here's my anchor. Link to my anchor after defining it : @link(MyAnchor)pasdoc/tests/testcases/ok_back_comment_class.pas0000600000175000017500000000120713237143041022626 0ustar michalismichalisunit ok_back_comment_class; { This should report a warning that @@exclude is used twice for TfmHardwareControlSetup identifier. But (before fixing): @orderedList( @item(An @@exclude was assigned to the whole unit) @item(Even worse, it caused dummy output @preformatted( Info[1]: Starting Source File Parsing ... Info[2]: Now parsing file ok_back_comment_class.pas... Info[2]: ... 1 Source File(s) parsed Fatal Error: At least one unit must have been successfully parsed to write docs. ))) } interface type { @exclude one } TfmHardwareControlSetup = class(TForm) //< @exclude two end; implementation end. pasdoc/tests/testcases/ok_image_picture.eps0000600000175000017500000003630313034465544021657 0ustar michalismichalis%!PS-Adobe-3.0 EPSF-3.0 %%Creator: GIMP PostScript file plugin V 1,17 by Peter Kirchgessner %%Title: ok_image_picture.eps %%CreationDate: Sun Feb 19 00:35:59 2006 %%DocumentData: Clean7Bit %%LanguageLevel: 2 %%Pages: 1 %%BoundingBox: 14 14 67 86 %%EndComments %%BeginProlog % Use own dictionary to avoid conflicts 10 dict begin %%EndProlog %%Page: 1 1 % Translate for offset 14.173228346456694 14.173228346456694 translate % Translate to begin of first scanline 0 70.98279830405815 translate 51.987401574803151 -70.98279830405815 scale % Image geometry 52 71 8 % Transformation matrix [ 52 0 0 71 0 0 ] % Strings to hold RGB-samples per scanline /rstr 52 string def /gstr 52 string def /bstr 52 string def {currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} {currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} {currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} true 3 %%BeginData: 14525 ASCII Bytes colorimage s82ojrVZZuS#!<[^]"0Un+l_Jp[nIbqZ$Qjl1OuEs8VWh]qqZl`rH)9s8Muss7(U~> s8NZ&qY^*brr8:ZZ_,,7s7ZBYrVulp)=m\)s7lWonb`4Js0nYrOi%.ur;6?gs8VV>~> !rMrmrr3T+le5]RBNBK#fD#==s82Qjrql^+nb`1Qs8V6BK3ht]K?N!8rr<#s!:PF~> 0DtVFs7cQ,VOq9u?"@W=`;BT7naZ;Gqtg0hs8)N`n*pASs8S-s@U3nUT9@.krVlfsqLA~> '`\%0rpfuqSsitc?Y=2I_tF!.p\k*k(]!b%rV?Hmr:U*`rVqaf>ZPWASWUhdqu6TqqLA~> 0E(_Hs7?#[H=Ifu$lC*lPNVuGp\Fjfs8Mrrs8N#roC)YVs6X>G&e60$@UZ,)rr2irpj`~> !qH9err4QlA6j"kAnk=M>lOcpq>'gRppO<^Du]Oqq"asip1&)JEH#2^H"LI!s8W&tr."~> !qlTkrr4Qg?s%,]AnkCO>l4QmrVuolrO,ZUC&Rl!s82irnm607CMHmDF_"jps8W)urI=~> 1\h"Eo]k6l)$C9S":t\L+OK98rr<#lpT@7BD?'V+rV$$XfebAh',1TS2CTu+f'iG3pj`~> 1]74Ms.spX?tjLj9Lhir?[p)qs7l2rD@dF+'Pt;Vq#C)o@<#@e86.fuBN7]B`;fl9r."~> *WQ-;s.jdR?"Rh^8OQ6g?$sTjs8)K(E"EL!$tm-Mrt=t-?Yr_U5ts4W?r9L4`rH) s8N5nk]f'+q>^X='/u'>rr3P@@K6B?$#@6Sq"E[*/hRGFrW!6J(CC-UHfY%upj`~> 0`Lb;s0,^E8TA 0`Lh>s0,[B7;Q@CCNX3)Bj59Nrq3j+&0Nhq&dpb*rr<"eA6rVM@UVZ?>Y/m;YP%npJ,~> #64DYhfK21quA)V#8@dN*om5!b>J 1\1SGYb#61KPtsUAUA;uAl`B)s/7=_&7qQ#9GS%3]Dhh@1Mp-'Ed)DAB5_U-Tu?p0s*t~> 0_#,BY+8m)IV&e(M?rUQorLbAN%q_Jt7M,o%]))D80kX3^@VT=`>@CrRS&>7*J,~> #Q+PgKj4i_%fHA.%g2e2(Ct6VY:9PQ,[Fb&!!#<^h9Qo<&HE:T$N:&*#R(W6V"FHYJ,~> 1]R7MQ@3^\:1\X@G'JXWD+A?5\h,KCBT\:IOA6Z+( 1]@(JPBgqJ6s"&_B5)Hs@mXdoYTkD#Bp4OJN_'os'$"cu:h*m3 "on8^C,m12!##Yq$k*jN!<=-]VBd)\-U0If 1]@@RQ?$\VCNsO*UMtI"C1;Q\1`@WTP+If#R?^5W*&_qU>]Fn<=0S]>E-OuTBp\l"rdX~> 0`(eKPAXo@?>*B>O^Dd6?s7\8.1[A1Oe@r'RZg&O)(fZ9[oQS=-ER_J,~> 1]R@=BJ'r*!Y>?64U28q!=q@6'`\4`5!:JY:08,/!"M@>!"TYe!)>i\!tkS<07 rr4[;@;0RoE)q$YIYVc[9hQrP,=7W`T9,2'O.9Ps'J"?5D/4TU;JUSiIWfFEQiI*bJ,~> 0`D"NP$DI+?=60-5&>CKAOA^)%3%ElS>2F:SWK@J(().!?:2"!3?BbBgJ,~> '*%jqB,hNk!XJc:!#Q[U'+uJirW!s(3Ai0;5=/Bl!!!0d&e"aK)#t-e#Tjot0REBdpOE~> 1]%.FX`HpKCNXlLK<'0-DI,UD4eAO@OcGQoRZa;.O=:PY;KR;VR\#.QDKB>^:Rq.UrdX~> 1\^n@Wbt%4@:j.eELCE>@8f#j17"W(Pa%T2TU)77N#r$27r3@7P)jTh=^P#c5a_?Es*t~> +9)/pIk1R(!!`lG*Cg\A)`8oA"BA5Y.4-T.5XA4;:]:>*)C$"E,;^\c(`!8T$%;45pOE~> 1]RIN]P9ZNCLMFcV5%m3BeC)MA!N7FQ^j2&MN*OTSrl5V%;ffhC7LZ5F&.$kC<$5Ps*t~> 0`CkC\S"!?@omH7QBYcO>U'S#>*+i6R\Q7@P*1icRZ'07!+B;CBU"Nf@R"R+?c)gBJ,~> #64MZNZnH+rW"B+4$aJ^-P6=Y+[.P600D3^4[;.o;cOJ2!&k_p!%BQ;)?:NQ*MrE'qLA~> 0`V(Ns-mP3C34T)@rQ!u,9/(QR@K\>R"T4.OI_f0PEhFW&humkDK]H&:2sZYG4kk7J,~> 0`CnKr0Lc"A8Q*[-DY3r.J,~> "onDcelWCY!<3`Z-ia5S5u9^"4#\uA8Q]A":IIcX"98rB%06_7$ih%F&22]2qYG^~> s8OhBs/BaDBkq1.C3=MM(d_esOJ%u'Q#S]F/L!N8R&5e59G\+;A6!DM@8Bs,T`>&jr."~> 1]IF@s.s:5@q8eg?u'C$&OC)nNguArQZbJY1*f/=Q`#h25mdWg@T7,I>Y.agRK* 1]RF0j)lRR!rr<:#p_&%!#7:f5s[Cb6So2p'EA_477fOY0*)%n(]XpD#QP2DC[Lunpj`~> 1\:YHq>^J$C1M9Q6 1\:YHoDS\h@U*S13`7%.5a7S/Q]d;uQ72qI&HO>'S!'>(S2pm)5\je%;,Unis8W)urI=~> 1\:M;j5JT0)@I2Y!#5J6(/@4n76 /H>P=s7ZKmHtIY;7Q)GNOI^iZTUhFC>UBLP!rrj&M4]ctNfQpD'0^58@;5W=!;_3~> 0E:h;rpB[_DH^pa4Y@X.O/n>+UR.(6>:B[T"98j!M5?N5PE&08#rcR"?tT<7r;Q]rqLA~> 1]$b3qrmS49.DhE"98E=@7_Fn9M%cX,7FSi,7k)"5sm(`5@?M['J2p(.Qub^q>:-hpj`~> "9/2tqYgFEU6\S1,#>%rMk$#oR#IDH&I&4B!=1QTQ]mSuRZ9N8/MW^os8N&urr<#gJ,~> "98 0DP;ArVucel@!@e!!"'g=th`j4\A.E2ujF53?JP4;E?9P1/qa8"YVBVhrsP(rVlZom=5~> 1\CV@qu-Hms0l&Z-X)J)Pa%r"R%'>7E#JcZ!=8lmNgl?*SscC@A-N#iVtKfQr;$Bmqg\~> )#=40rr;rss0PZM+B*o]MislmQ^O&5EZ4iU'gS"TQC=2&Ruh%^!^aKus8)cns8W"I~> 1\1MEs8M]]n"i2Q!$+[E:d7H'6r-Wj5lq6=1+<8*1,gU--o4Oj2?O4 s8)firVJ.Q?n!a)Mkl>7CMJ?<>%V)/*#f\B"ZgmpR$aJ9Q(=_:?7-L^W:TcSrqQ0dJ,~> s8N)qrVnFZ@jim$L7Nrl@Ujb%=Ctl.*#K/,!&o:sS!TS/MNjd"@PT9=]`8$0s8)HhJ,~> !VlWms"=*7UJ_a5)b*t"&K_rI-ljum)ZUO%6PLq&1b^F2-6=[%:e<8a>dO;'nb2G>pj`~> 1]%%Im/6^T=W/MjLnpP[3B9`>84#*J4Dd8K,]c>3P*1rpU8FKHMiLgQ!&(>Hq>9ses*t~> rr4\?s8T$*+!k.=/Ccjm(DF0DPR?s;5Tph+'Qt.?B4LY:irV-?lJ,~> 1\1GCqu?GS5l^m67orJ=!!!Z)SrV6!]qg\~> 0E(hJr;ODn-oP.hTU:UL7@BR0FupNV'/aK=P*_>pSrenfO.;`,QB@,0%0/Vrr;HYG~> s8W)t.D\A)4C"5LRYY?7Nff??1Ck$.1hpfhR$ !V#sbs!bN."q2\M;aro"%q&m^<@.nQ!#7gb?11E0W?r;V9~> 1]R=LrjP$5,(GH:QB@>J9Qc\D3@c$X+;Z).R$rW$LPq=\OHGWdQ%>?V9+h4YRK*<`pj`~> 1]RFMrO+p;.u9@^SsGRR6u.fs0-Lo3)A=-%S"GG3O-uf=R[')#RZ=A2 0CSK3s1C/i!(TCE4#f_i+@g9K,p*Zu$ig8P9LU@'4AK!R6U=1<=$C).8LPQW[Jp1+rI=~> 1]R"CO#8F.B9ngFOHc8P89[Qp/eAd92JFU0QCa5)P_P!RNffZsQC+2*NH-ET1p-9HrdX~> 1]R(DN\rF8E1rqpR@9[Y5&NSK,6nYj0OuM"R\H+9R[9P;SX>n 0^\$&Q89BY/Q+nl/ilij,>fjE*<69L,#A@I7R8dr<+B]M=CPu\@p3)@CiMWf;SiA4J,~> 1]@?23$^D;NfB9fQBRSB6<#KV+t>!%G@a*TNg-)oJOUt0.Q:L]PF%,^QBH&@$oOC=q1&~> s8Og02^LMHQ^FD9SXGaG2bYM4)C-LbEa:b 1[4Lf2&-j%7Q`[d1HA)`+ZC&A%h8ja>Z*"8;FF&>90=^<(+)ObDIQ+$>BORC+AB!=s*t~> 1]NUu+Z+2+NKfcmQBdY93Ai]7/MK\XOIR_:OdD5sBJ'c/*>^>DPa7B#R>R,N.0:lWm=5~> 1]NY!+ZOY=QCFM5S!B(2/hAUg,qD?ENKYGsO-l3#Da,Ns0dJc$R\,tFUQCdd/I=2$pOE~> 1[TfL'c0,53BK2S2*4AX(`ah2(_.R#DMf?3AlM5n4#JN4,o\@;FD=l[>[Vei//^pWs*t~> 1Uo/!5EM+mOd(lsQCsUc4Y\-3.3;;QD`BLO6X_W]=!/@u(`!ZqOI;&pT8&c(FYXRLXag~> 1V5J(6'Rh+R$a&,Q(*nJ0ddnb+rX6DD)*P76")Nb@5BSi.OH3XR@]G-U5>M=JO(M3]mp~> 1T2HI.:Q1;0fLgO3Cce+)&j;9(]Ycn7j]]U.PCcG/MBFT2C8l-C3F<3G@#3,>=:>1b('~> 1R][OP(/XfOIqf8OD7X'DBLS_.OJVCND1s1?\!*M>;6Nf)](D3OH6,qSsG[rNG9dYR=G~> 1S$!XQ%G@"QCj;4LgibN?5=k2+sC?3Mao-t?A!E\BLat1T7/jSX+1~> 1Q32#G"G1j/3c*d2%]g76k(Ro+:C4qA2bZ18ldoA1-.*?5:\TPDL%7dJT,=#DgY5=[=A~> 1UJbl8YCC(OIhf'[s3IIG=*;m/1iKEP*f$kPF7/bLbBGX"qaChN/!LLR@0>+M)YqnVLS~> 1Uo2"9r*37OI;/bVe9mUA2k8@,q(=7P*SmkQ_KS1RR\t_)^\^\PCnaAQ^aSARSG(j\ps~> 1T;TH/86Y(/3Z0U=W&Y>6o#`1/Ku!WDLFHSFDXlS?7-sO+ 1]'`g00l7lSuS6]YI(gPF?29E1a"1lU7I=7NJ!OdOErrC/8KT\BoedGPF7Mc9I_Q,m!o~> 1]L5u1.%dqR@fA*R\$+C>V.Ne/K,lYURm[EQ]\/KVNOkM6%FoMCl4L6Nh)W$>sCZ's*t~> 1\AKR@QZ@T6oRAn!PY3cTIj@>'VeG^+@Z 1\\:V00_n'T;&s5^U(tSs,*o/L5,7oRH~> 1]P6n0gA!tP`hoH\Wj+`;_C9e3FaB\2iXJpVlQ8MTW"TRQDL0#5'XJeSXPs94Z7f(s*t~> 1\.hL,974s77C9]>rGS[.4.M91gD%;,%YOe?"6r9A7oe.K8bpN94aB"IW0d9=$V;Ms*t~> 1[k"P 1]79m=#M]sN1coWV6H,N6RsTMRpn3+0f>W#Ts`%a^:V1HUl^jR0n5:_M3ggj2d+?(s*t~> 1[F_R<[SCc93G/!5t3S&'I5.[JPIL:+UhgZ9PK 1\^S1]2q'\>dqVR]Xl;*IR-+JOM3V74&MNPXf.bBKoqOKPZh1MPFS53S2;u;;6K-YqLA~> s8OhH]2C@?8>)rES 1\:D?a&XJu'3nNf.jR2F-n$qX@?_T^/i%6_D0UDGEboK"LLt:_Jokd 1\CJ>p:+Br5B3p@a1B+%JjCtSMoTBb/P1GpV5LP<9hgA&?7UU`R?Wu';`$@*WV?2cr."~> rr4PBZW&n<>a_@fR%0IL1G)+Zc"A[\:QE?-_8qL@=c\tc22XJeQ'I\92EY6UrVqB~> 1[t;As11uK"X?`05UnNO,pjiQ;3=*p.P4A,??_]U;*f/F;Da=ZIW]^Q5XSRf_>j 0_kPArqs013]`"pZa7N]ImPYpOi),_5Y.!Q^oNK"1co&oN/WBCN/r`n4Xk[NpAFphJ,~> /cG_Ks890*1G3m 1\U\Ds8&cc('Hlu83B*r)C6Rl?%tj$:+T=YCj:GR? rr4SCs8BN;6T0>%ZG4AK1bD=aa$EcdAtc]>L2Jt*4$#2mMi`d[Mde4gG,kH9rr2qJ~> rr4JBs8KT94tU]LS#3*Qu"N5Ha3JJJ,~> rr"G@qtRHO;VIp7:BeB?>j@lC0EttG]n1bO`j>jNk,,`rVlhI~> !WW,ss!mfV;b9)j[aEp:?8YZS\rK*ZQ,h45>t-+t/i?*QPE2o)8i&5.q"ajcrr2qJ~> !WN&rs!RQP:.$aEUV"F9=Z9 !WW,ts""'=XZ.I,-spn2> 0E:eHs8Mcjr4bft=a[a$b^tsHRETS76"QY*=%4i"3]o&H3B;Y[AhZ5GHMdC(r;HYG~> 0E1YErr)Thr4PNe:2Ql9]n)J>R*'2'3F\W">>$b03^#2R6:R*;F?DrtJH,K;rr)kI~> !WVros"!pAoWTkk+Z="QH:r*&H)!nW+tmGj3&`Zk?sH/_4Z%AH@lR(rOT5@Oq>L rr4PFrr2fpX,VU&4a,3#_9J.b^VO'FAsUAUH"C\q??.`2IueVK8oTWSqu$HmrVqB~> /,]DGq#:TDAM;~> rr2utrVn+=IUjc74HG2+E(,J0Jg"YI;ijC?4]>HuKKO+'P''o,I@7#4rrE#rs*t~> 0DtkMp&=serg\A-=@c(ncdKPL]@Y3>d(dcN]tLhbZbN((U@a6u:el_&T(W$\o_nf?~> 0DGGEo`"jds.4Y2 "9&9"qYgFASTg2_.4-s5E)(%QIs,RSD1@b"F`NJ5_5mU=rfTNO>*,#Hr;ZfirVqB~> !<2ut/,oA>r1T(XG>C\-=gubrb08)[`6ZT=`l5sip[%P=oOgin:OTO1R/?g\q>L>D~> !VuZmr[.I.`A/d*g:oa4&ANcI(, !<)co-`E*4DEp!?/oG]>A7T.a>]Ot,H#%cQm-X]Es*8![?AZ:[SGrQgr;HYG~> rVnDCr;?,NO1KFbF?ruG_TK[@_o^'p%n[ds*t~> *WGs8s7cQnpR7>^H\Zo9>A_:&`mi)Ud`9V^cdK].rsNXX<.UK`\rW3Xq>:*iJ,~> 0)bYHs8DutrLT@iFF\6e5X0a=>\-f3>@;AnCgh# r;Zfp-MrmhY^_]*Kh5L4c,IK=`l?'6a2u<6q#'XOBLYO9l%a5aPdp_lqu;0~> q>V4tS@OHBresNPNm5\bc-FY[`m5s8N#rs*t~> s8)corVn14T"'K;p4P_)E/emH?WC3BB5D?mFm/ksoQ+,ANrPMn[?IuprVQVF~> r;S8Gr;3[jXDER^UNp'FFN;hLaMc6@aLJn"s8)D"92fs#pjdOORY^b q>V2;WO6o1s/^ZN;0'e0bgXnedF?1\ci3qSHs^B9qYu=tR%K<5s76$bs*t~> s7cZlqu-No-FKeZFc6-pH<* r;Zfr-2`ag\T*B"p\]8=:PZO"cb7*(ah5d$p\B&+6u2J]q1X%&PF2:Es*t~> q>US]SA0B2rr4'_=&+^ic.pUibM:M$_>jOl?WDIQp&Bnr\sAc_s8W)ss*t~> s7e)?qtp?js,ib`GDuS#qeSM=9R(Si9NP.t;JKpplZQ*!HN4!EOF4NuPPG"SJ,~> qu?]q,c%0FCPVc\r;Ub[F-"5hk31ONk1AMgGuIOZX7>uXMJg\,V#'rfJ,~> q>V_=VS-u/s8DutE-HJhcK>!%n*g2?n,J,Q@=l)hs8%apc'kL*qYu'~> s8)`lrr"+?V7^`)rqlZh?<9d-Jol3aCh8'OW7kua=*h@Ss8A'ubE\aqqYu'~> q>Vh-R^6jir;?QopLRoGL;)^.bMD"#q0Y\&EqfA)p&9GaZFPhls7QBis*t~> q>USaS@*9prr3T0oOMTIO3m_$k5+f/s+jTSJc>ZUqu;.hZ+#Mgs7ZBjJ,~> s8W)srr3+eS$['orVmo8?s6 q>Vh4Zc[cSqZ$Tgrq^;RA<#'djl4DWIWJ\:o&fcDr;VM"[&&][s8N#rs*t~> s8Moq)Oe"RIu4%%rq$-cBmX]flKeKMjSt*eB7g*OrVm%VI'TN(rVHPE~> q>VD'ZcR]Tr;Zfrs8QqZ:/ZU`Is?7pJ9>7Qs6opcp]Q.mZ_icYs*t~> q>Vh4YI&>'s8Vomn,3'-?=8u+k0(VhD0BTlo_JC^n,J)a]SrBRp\smbs*t~> q>M7uXfl\qrr2ZkoDei q>Vh3Yd8D)s8Vroo)J`D?q+XMQ>LqbGBn#7s8VuijR[_9\W s8Moq"cBb'H?T2bs8W!8qsB,D?Z+?IIWojOqYC$_nc&RdLjc/4ScAN_s*t~> rVlco#)Tb$G] q>VgtZ+bX4rVuinqu-QnO]=k /,T)?qZ$Tks+HiOJ;!t#rVufpr:0T9C3G?#EHmQEs8Mlds8DfoJT8;[LA_)OrW)nI~> 1]R@PqYg?`re@#VIt.@hqZ$Qps7ZJQGD;?XGB\rCqtg*\s8W#sJon_aKDYQEs8Drss*t~> "98B!qYgF0H&oCfPQ1@JrV?0`r;VCR=^c>J@taaYrt4GZmI0q"A$(KEs8Vrls8W&jJ,~> *rG^'s8VNes,4.nEJ"#ds82HgrquT&K5ul^J;jO'rVmH'qu?%qFe$a>s8VinqYpBgJ,~> s8NW's8;*Yrf=P'Ee3o`s8)KhruV-RMKt:uJ;F6mrVQToq>C9\Bm6/pO8]%Ms7lQkrdX~> 1]$b2qu?Bis+./]G)>ePhrX"mq#CB-Jn]O.Ao$JZnbrLXj6ZF&@VV"HOT5@EpAb0hn:1~> s84VOnc,UMAr"C4FD6u%Ngt&T6T8d<;_hKrClOdQO^_Zp:e5b1<.Cj\IZKf.nbrIcrdX~> rr4\>r1c)XLW?cFCm^NQTlNCa3,:BL0j&O9OIDi,@U;f(7 1ZR]km/O(B?\QV4F]W0C4C:];68E77QbEX9n97SDKL&qiW&rUp4*~> !W2Zks"9?A#XGT1GB$Mp>?5)E#o3UF";:f8C3i\E(Ws0qtU0[rI=~> 1]R@Ps8I`W"$Wm'G&p`)@pECS"qq";!"K!0>\.P\CH*(>!!<3'>C!]^GZ\@cs82fds*t~> &aJTOp@s1=!'dj8HX.^'!!X_I!!rf@,mcji,nU+\q>^q&I^u(J*?pL0s8VQ\J,~> 0`V%Mqu$+U8;.**"! 1\p\Cp&CH\!'%KJGW'&ABP;*a)$9m>!<<*&?=@2hAoUoW!< s8NZ&gZF:l!&M0WM*4HH#8J6mr;Zg%rW!-_-k6Xc#n$Y3%LrJ(CRCbI+s;6`s8W&mJ,~> s8OhPeG[Q;7#[q<=@*WsCLUsmQV0M2(b?gL-qdB2 1\LP=eG@3.5`)83<]ppgC0tOfQ:Enu'.=n@/66+fD/X2l3&;=1B76kK>%huOWk.9ks*t~> s8Oh'N2_4*)etG+=#p',_o='Gpfi7pC^[+tYs)PdffPqLA~> s8OgnnGD_Ljj8!W 1\q!hp]('flI'ce=F+@i@V&ogoDeUcp%ldB@;B[g>[:?UaQ`EblLW\XDHL(\=]1[_s*t~> 1]Qr\Bie&PK82NG.7kp;*[),)Iu],>LSTo%;c["';F`?,IZKVHMkcb@;FjSr;bNAFqLA~> 1].3lnc&%IqO1i,B2`khCiR`"r;$Bcs2].rC1UUE9iG'"f\4^.e^@>c4$bh\5YIUGr."~> 1[tFfr;Zfms.!S:CfYXlASK6br:p%;%V/KA6Y]+s*t~> 1\fd)82MeoKLd:>.1\$Y*>Dt]4@c?r3!\p4*~> s8Ogqq=F:PGA1]*AR]7eERO^]s8Dfo_eO7)DcL^F:/nmPbgatTep0YI5Vb)D5Y[IArdX~> !qlT=rr4SGG@Y6!An,F`Ct&:Zs8Moq]jbbdDH_<`?uXuqpAb'Xs.3h0AR&\MC1!A.s*t~> 1\90o:+eP>'.Q()/0>oU&PHPIF_,KUD`_96FC9Gj7Q-'WE+WNjR:oW=J9#O1>XsA:p4*~> s8Ogjq"=JtH"pl.?#Xt+anbu:r:p$2G]IS5?>E\S?dcpH`lc`YCc=L31-.9N4'p)/k^W~> !r`/=rr3==F(ATn>]4_!`r5o:&,Q%ADeNTi?#F%iFnYG,q#::%RUB]0?"dkgBlqc&m!o~> 1\fTt>"2To-T!kM-8$Y[ s8Ogto_*ftb7K0f)*L5VXoN5.BkWrdX~> 1].3tq"\lE=BKQKCh%%prr)ikq#AHT@:="b?>=:cg]%6Es7Yo`@:O7`E+*-kCX)MOs*t~> 1]6-EDeoCm+!s9'1a s8N8>m=&\bF8fo&A8e[Js8Voor76[+EG8ipDdRG,kL.c"aLPG,4u,&^.Q'^TWn-+nrdX~> +8c)Tm<`;PBk:skA8JCCs8W&ts4N0,Ch6mcEFF%@rVca,m>G=iA8-'f@sDe?m-F3AJ,~> 1]?N^M%g1@2D-R3*ZIRgDf9B5LOrAbAn#"Q>WFTbIpQ>^Ef3acCLLmt>$ti%Q`IC %fcFBH#.P4G&_D&FiF1Vrr"#6aaI]@@;8tWChW,-n(Ph0`.'Bn3@m-M/4_>7cHcFanpg~> 1]I-_FCf8nD/=&mG/a=XrVuonb^'4$Iq<.eXpj`~> 1]?X)3ZfUf1,:Bf(fbm&Bl89PF\GJB?Z]^`7hg?"FC.sZG@a*VK5u0Q:KAI"L5X()hLG~> )#F8q?>j_!AS>dla8br7qXaZrEaE9k@:0"K([(;fnBKCrTg1_'-p0.=83Ej/`8LChrdX~> 0_ta0>A.SY?=[\cbl@P>q"=["FCAg#An5dqDXR9!r9jRNc>IB5UG%oJ+lM(;XJ,~> 1\^N\/i#%6.OQ2E 1]RBBCL;'pBP_,#r:L$ds7k-&>]=FOA8=o(bOb`2r9iF>90Fdi1+G=E6c[^/dbM;/rdX~> s8O(0CftFV?"[]ps7cQgs7t6)@!6QiD08sPd.[M9rr3SODIcjhAR01iF8#S2nF=Kts*t~> 1]?ZX0I8qM5;*INH>%/&Ee8O*/m;mhEbmdGI#EJeCk%V!6r-[!BOG74-\d%sG)11gjF@~> 1]I$9>$u,XB4\15q"=[ep<-oYCftL]>ZtpLlM1;Wo@U-J77Ka*4$#Vic.LFihr;?KqLA~> 1]R0A?=%2L?t?J6rqHHko?CoaEaa'*AnQ>%o)&=ap?0>3?"7JRARf@`oDJ.CoC0m%s*t~> 1]?N].lU+":cN3TOGT!RLj::-:.f5;B3%r_VlH>LK8>"P:gRX4>?t2eWgJHqS=tesk(!~> %0$%tZ(\CnR#:^%C6SYs$aQt?Z*:F:Z)l%3rr2p0rVj9tX/DkY?!;?DIdQt!r;Q]qJ,~> &HDV*[AC1$R>q01Cm=u!s1/-?rOW-?dI[88%Df$PZEp6@BnNUJqu?Kis*t~> 1]R.9Um@pHOaQ517;Uc0gm=P)VlR#-Z`1[kjQ#.JfAig!Ycb7&BkDaaEnK@&k324)pj`~> !qcKirqd&g[=l5FOL+ZYqtp:*bpAFa\rp?JEKsQBGp&+ads*t~> !;??j$1YWa_M"&Wp%\CZrrMroqu7-(qu?Zks6leLLUDfRqYU;C~> &G?)'rr<#c[tVPGN3;^DpA4X\([gkgp\"4RqY0a_qY'mUUm-V>J\_!XrVcbH~> s8E#irqlutZAYf?YjhYl!;cWgs8)]lrr2in$i9f#o9P'AL9L1Gq>L>D~> s8N)nrVm,4OKj\Jn,E=Nrs8:bL;8_Sp](6ks*t~> s8N)mrr3<'[#D,@XR#`[qt^'aq>pBgrr!6%rVc;PK=luDoDSOas*t~> s8EQ$r;?*^Ne"]uRK* s8NN$s8VclP_Hl2S,`Nbq#CBl!<)lr&H)M%q>^KfpA]l(_MZ,.s8MusJ,~> s8O\Ds8V`iOFb$!QM^RRqtp6eqYU-dqY'UVqYU-dp\OOTrVc9XrI]j=L:dE]qu-PF~> &H2M*rqu]kQ%6T*NrT+YqYpKks8!-!qu6QkqYU6krqHEhr!/XI]7-^Vrr)fqJ,~> s8Dlq#b-OcMidu;rqZHk$NC#(s8Dilrr<#oqYp\iO2-CMqYu'~> !WDrpru1j&J\Qqtqt^-^qtp(!fpA4^mRZ"h.WVuenrVqB~> &c__,r:'U\VN%p>Xo88!qu6Nirr2rtr;ZfsrW<#dp&=jo[=GiAOS\tOrVqB~> &-)M+rq-6jXHL)PYQ"M"qXsmgr;?Qqo_SRe#J,W(M3\,@qYgGE~> *rl*:rU^$eW/e6?WqlJfpAOsirVuirrVuirrVZNlrVZcdpAY!q[Xl&EOo,+OrVqB~> s8W,us839"QA2Vn]))4%r;Z`orr;otqYpEm&H2V)r;QWlp\;%B\qu^OrqZNmJ,~> qu7''S;Xe+]_hO)qu?]prr;otqY^ qu7?+R"qqo\+]Ikq>^Horr;utrVZWlrt,//qu-QnrV-)mICkB&s8Vros*t~> %%EndData showpage %%Trailer end %%EOF pasdoc/tests/testcases/ok_auto_abstract.pas0000600000175000017500000000260313237143041021653 0ustar michalismichalis{$ifdef FPC} {$mode objfpc} {$endif} { This is the 1st sentence, it will be turned into @@abstact description of this item. This is the 2nd sentence of the description. } unit ok_auto_abstract; interface type { This is the 1st sentence of description. This is the 2nd sentence of description. @abstract(This is the explicit abstract section) } TTest1 = class end; { In this case there is no period char '.' that is followed by whitespace in this comment, so the whole comment will be treated as abstract description } TTest2 = class end; { Of course, 1st sentence may contain other tags, like this: @link(TTest1) and like this: @code Some code. Not really Pascal code, but oh well... and I'm still in the 1st sentence, here the @@abstract part ends. This is the 2nd sentence. Note that in this example the '.' char inside @@code tag did not confuse pasdoc -- it was not treated as the end of 1st sentence, because it was part of parameters of @@code tag. Even though @@code tag in the example above used special syntax TagsParametersWithoutParenthesis. } TTest3 = class end; { First sentence, auto-abstracted, and the 1st paragraph at the same time. Notice that html output will add

to DetailedDescription, but not to AbstractDescription. This is second paragraph. } TTest4 = class end; implementation end.pasdoc/tests/testcases/ok_table_of_contents_unit.pas0000600000175000017500000000010013237143041023535 0ustar michalismichalisunit ok_table_of_contents_unit; interface implementation end.pasdoc/tests/testcases/ok_tag_name_case.pas0000600000175000017500000000023113237143041021561 0ustar michalismichalis{ Trivial unit to test that tag case does not matter. @code(Foo) @CODE(Foo) @CoDe(Foo) } unit ok_tag_name_case; interface implementation end.pasdoc/tests/testcases/ok_dashes.pas0000600000175000017500000000166713237143041020300 0ustar michalismichalis{ @abstract(Test of various dashes.) Triple dash produces em-dash, for separating parts of sentence and such, like "I know a secret --- but I won't tell". Double dash produces en-dash, intended to use for numbers ranges, like "10--20". Normal single dash is a short dash, for compound words, like "variable-width font". You can write @@@- in cases where you really want to write just 2 or more consecutive short dashes. E.g. @--long-option-name (here I escaped only the 1st "-", this means that the rest of dashes is also treated as a short dash), or -@-long-option-name (here I escaped only the 2nd dash), or @-@-long-option-name (here I escaped two first dashes, which wasn't really necessary, it's sufficient to escape either 1st or the 2nd dash), @-@-long@-option@-name (here I escaped all dashes; this looks unnecessary ugly in source code, but it's correct). } unit ok_dashes; interface implementation end.pasdoc/tests/testcases/ok_operator_test.pas0000600000175000017500000000662013237143041021715 0ustar michalismichalis{$mode objfpc} // Operator overloads Delphi and FPC unit ok_operator_test; interface type { @abstract(Operator overloads declared within a record (Delphi 2006+)) } TDelphiRec = record { Addition of two operands of type TDelphiRec } class operator Add(a, b: TDelphiRec): TDelphiRec; { Subtraction of type TDelphiRec } class operator Subtract(a, b: TDelphiRec): TDelphiRec; { Implicit conversion of an Integer to type TDelphiRec } class operator Implicit(a: Integer): TDelphiRec; { Implicit conversion of TDelphiRec to Integer } class operator Implicit(a: TDelphiRec): Integer; { Explicit conversion of a Double to TDelphiRec } class operator Explicit(a: Double): TDelphiRec; end; { @abstract(In this case, "Operator" is used as a normal Delphi identifier) } TMyClass = class private FOperator: string; public { In this case, "Operator" is used as a normal Delphi identifier, not as an ObjFpc keyword. PasDoc should tolerate this, for compatibility with Delphi and with FPC in $mode delphi. } property Operator: string read FOperator write FOperator; end; TMyType = record end; TMyType2 = record end; { In cases below, "operator" indicates FPC operator overloading feature. PasDoc should handle it correctly. } { Assignment operators, see [http://www.freepascal.org/docs-html/ref/refse57.html] } { } Operator := (C : TMyType2) z : TMyType; { Arithmetic operators, see [http://www.freepascal.org/docs-html/ref/refse58.html] } { } Operator + (c: TMyType; c1: TMyType) c2: TMyType; Operator - (c: TMyType; c1: TMyType) c2: TMyType; Operator * (c: TMyType; i: integer) c2: TMyType; Operator / (A, B: TMyType): TMyType; Operator ** (A, B: TMyType): TMyType; { Comparison operators, see [http://www.freepascal.org/docs-html/ref/refse59.html] } { } operator = (const c, d: TMyType) : boolean; operator < (const c, d: TMyType) : boolean; operator > (const c, d: TMyType) : boolean; operator <= (const c, d: TMyType) : boolean; operator >= (const c, d: TMyType) : boolean; { Boolean operators overloading. Seem to be undocumented, but they are used e.g. by FPimage unit in FPC sources. } { } operator or (const c,d:TMyType) : TMyType; operator and (const c,d:TMyType) : TMyType; operator xor (const c,d:TMyType) : TMyType; implementation class operator TDelphiRec.Add(a, b: TDelphiRec): TDelphiRec; begin end; class operator TDelphiRec.Explicit(a: Double): TDelphiRec; begin end; class operator TDelphiRec.Implicit(a: Integer): TDelphiRec; begin end; class operator TDelphiRec.Implicit(a: TDelphiRec): Integer; begin end; class operator TDelphiRec.Subtract(a, b: TDelphiRec): TDelphiRec; begin end; Operator := (C : TMyType2) z : TMyType; begin end; Operator + (c: TMyType; c1: TMyType) c2: TMyType; begin end; Operator - (c: TMyType; c1: TMyType) c2: TMyType; begin end; Operator * (c: TMyType; i: integer) c2: TMyType; begin end; Operator / (A, B: TMyType): TMyType; begin end; Operator ** (A, B: TMyType): TMyType; begin end; operator = (const c, d: TMyType) : boolean; begin end; operator < (const c, d: TMyType) : boolean; begin end; operator > (const c, d: TMyType) : boolean; begin end; operator <= (const c, d: TMyType) : boolean; begin end; operator >= (const c, d: TMyType) : boolean; begin end; operator or (const c,d:TMyType) : TMyType; begin end; operator and (const c,d:TMyType) : TMyType; begin end; operator xor (const c,d:TMyType) : TMyType; begin end; end. pasdoc/tests/testcases/ok_conclusion.txt0000600000175000017500000000002513034465544021236 0ustar michalismichalisSome conclusion text.pasdoc/tests/testcases/ok_link_class_unit_level.pas0000600000175000017500000000162413237143041023372 0ustar michalismichalis{ This is a link from unit's description to an identifier inside the same unit: some procedure @link(Foo), some class @link(TBar). } unit ok_link_class_unit_level; interface procedure Foo; procedure Xyz; type { These are links from class' description to an identifiers inside the same class. Note that @@links here first check *inside* the class, then outside (i.e. in the whole unit). That's why link to Foo below is a link to a method Foo inside this class, not to a global procedure Foo. Links inside the class: @link(Foo), @link(Sthg). Links outside of the class: @link(ok_link_class_unit_level.Foo), @link(Xyz). Note that I has to qualify Foo with unit's name and write "ok_link_class_unit_level.Foo" to get a link to procedure in the unit. Just like I would do in a Pascal code. } TBar = class procedure Foo; procedure Sthg; end; implementation end.pasdoc/tests/testcases/ok_back_comment.pas0000600000175000017500000000175013237143041021444 0ustar michalismichalis{$ifdef FPC} {$mode objfpc} {$endif} unit ok_back_comment; {< Description of unit ok_back_comment. } interface uses SysUtils; type TMyType = Integer; {< Description of TMyType } TMyClass = class MyField: Integer; //< Description of MyField procedure MyProc; //< Description of MyProc property MyProp: Integer read MyField write MyField; //< Description of MyProp end; {< Description of TMyClass } TMyException1 = class(Exception); //< Description of TMyException1 TMyException2 = class(Exception); //< Description of TMyException2 TMyEnum = ( {< Description of TMyEnum } meOne, //< Description of meOne { Description of meTwo } meTwo, meThree (*< Description of meThree*) ); procedure Foo; {< Description of Foo, (@name) } var V: Integer; //< Description of V V1, V2: Integer; //< Description of V1 and V2 const MyConst = 2; //< Description of MyConst implementation procedure TMyClass.MyProc; begin end; procedure Foo; begin end; end. pasdoc/tests/testcases/ok_see_also.pas0000700000175000017500000000067713237143041020624 0ustar michalismichalis{ This is a testing unit for @@seealso tag. @seealso(Foo) @seealso(TSomeClass ) } unit ok_see_also; interface { @abstract(Abstract of Foo.) Further description of Foo. @seealso TSomeClass } procedure Foo; type { @abstract(Abstract of TSomeClass.) Further description of TSomeClass. @seealso Foo @seealso ok_see_also ok_see_also unit } TSomeClass = class end; implementation end.pasdoc/tests/testcases/ok_description_test.txt0000600000175000017500000000053713034465544022454 0ustar michalismichalis#TMyClass Description of TMyClass from external file is here. Another paragraph of TMyClass description. #TMyClass.Foo Description of @name from external file is here. Some ordered list, just to test that everything works OK: @orderedList( @item One @item Two @item Three ) #TMyClass Another description of TMyClass from external file is here.pasdoc/tests/testcases/warning_back_comment.pas0000600000175000017500000000076313237143041022503 0ustar michalismichalis//< Back comment without anything before --- should produce a warning. { First descr of unit warning_back_comment } unit warning_back_comment; {< Descr of unit warning_back_comment } interface type TMyEnum = ( {< Descr of TMyEnum } { First descr of meOne } meOne //< Descr of meOne ); var { First descr of V1 } V1, { First descr of V2 } V2: Integer; //< descr of V1 and V2 //) @HTML( http://docwiki.embarcadero.com/RADStudio/en/Nested_Type_Declarations
http://wiki.freepascal.org/class_extensions_examples

) } unit ok_nested_types; interface type { @abstract(@name contains nested classes, records, types and constants.) } TOuterClass = class(TObject) private { Description of @name } FOuterPrivateField: Integer; type { @abstract(@name contains one nested class, type and constant.) } TInnerPrivateClass = class(TObject) public type { Description of @name } TInnerPublicInteger = type Integer; { @abstract(Description of @name) } TInnerInnerPublicClass = class(TObject) private { Description of @name } FInnerInnerPrivateField: string; { Description of @name } function InnerInnerPrivateFunc(AValue: Integer): string; public { Description of @name } property InnerInnerPublicProp: string read FInnerInnerPrivateField write FInnerInnerPrivateField; end; private const { Description of @name } InnerPrivateConst = 1; var { Description of @name } FInnerPrivateField: Integer; { Description of @name } class procedure InnerPrivateClassProc(const AValue: Integer); static; public { Description of @name } FInnerPublicField: Integer; { Description of @name } procedure InnerPublicProc; end; { Description of @name } TOuterPrivateInteger = Integer; { @abstract(Description of @name) } TInnerPrivateClassDescendant = class(TInnerPrivateClass) private FField: Integer; end; public const { Description of @name } OuterConst1 = 'Blah1'; { Description of @name } OuterConst2 = 'Blah2'; { Description of @name } procedure OuterPublicProc; type { @name is a nested record } TInnerImplicitRecord = record public { Description of @name } FInnerPublicRecField: Integer; { Description of @name } procedure InnerPublicRecProc; end; end; const { Description of @name } GlobalConst = 123456; implementation { TOuterClass } procedure TOuterClass.OuterPublicProc; begin end; { TOuterClass.TInnerPrivateClass } class procedure TOuterClass.TInnerPrivateClass.InnerPrivateClassProc( const AValue: Integer); begin end; procedure TOuterClass.TInnerPrivateClass.InnerPublicProc; begin end; { TOuterClass.TInnerPrivateClass.TInnerInnerPublicClass } function TOuterClass.TInnerPrivateClass.TInnerInnerPublicClass.InnerInnerPrivateFunc( AValue: Integer): string; begin end; { TOuterClass.TInnerImplicitRecord } procedure TOuterClass.TInnerImplicitRecord.InnerPublicRecProc; begin end; end. pasdoc/tests/testcases/ok_enum_links.pas0000600000175000017500000000157413237143042021173 0ustar michalismichalisunit ok_enum_links; interface type { My enumerated type description. } TMyEnum = ( { My enumerated value 1 description. } me1, { My enumerated value 2 description. } me2, { My enumerated value 3 description. } me3 ); {$scopedenums on} { My enumerated type description. } TMyScopedEnum = ( { My enumerated value 1 description. } mse1, { My enumerated value 2 description. } mse2, { My enumerated value 3 description. } mse3 ); { Test of links. @link(TMyEnum), @link(me1), @link(me2), @link(me3). @link(TMyScopedEnum), @link(TMyScopedEnum.mse1), @link(TMyScopedEnum.mse2), @link(TMyScopedEnum.mse3). @link(TMyScopedEnum), TODO: these should NOT work (scoped enum members namespace is tighter), but for now they are linked too: @link(mse1), @link(mse2), @link(mse3). } procedure Foo; implementation end.pasdoc/tests/testcases/ok_multiple_vars.pas0000600000175000017500000000046313237143042021711 0ustar michalismichalisunit ok_multiple_vars; interface type TMyClass = class { Docs for A and B } A, B: Integer; { Docs for C and D } C, D: function(A: Integer): boolean; end; var { Docs for A and B } A, B: Integer; { Docs for C and D } C, D: function(A: Integer): boolean; implementation end.pasdoc/tests/testcases/ok_comment_over_uses_clause.pas0000600000175000017500000000023113237143042024104 0ustar michalismichalisunit ok_comment_over_uses_clause; interface { This comment shouldn't be assigned to anything. } uses Unit2, Unit3; procedure A; implementation end.pasdoc/tests/testcases/ok_record_with_case.pas0000600000175000017500000000265713237143042022336 0ustar michalismichalis{ @abstract(Testing of parsing and making docs for records with case parts.) It does not pass properly yet: @orderedList( @item(Types for fields in record case are not printed (because parser does not set their FullDeclaration properties).) @item(Also, CaseTwoB field has no description (but it should have "Description of CaseTwoA and CaseTwoB")) ) Update 2005-10-17: now this test passes OK, both problems above are solved. } unit ok_record_with_case; interface type TMyRecord1 = record { Description of NormalField } NormalField: Integer; { Description of CaseDecision } case CaseDecision: boolean of false: ( { Description of CaseOneSingle } CaseOneSingle: Single); true: ( { Description of CaseTwoSingle } CaseTwoSingle: Single; { Description of CaseTwoInt } CaseTwoInt: Integer; { Description of CaseTwoA and CaseTwoB } CaseTwoA, CaseTwoB: Integer); end; TMyRecord2 = record { Description of NormalField } NormalField: Integer; case boolean of false: ( { Description of CaseOneSingle } CaseOneSingle: Single); true: ( { Description of CaseTwoSingle } CaseTwoSingle: Single; { Description of CaseTwoInt } CaseTwoInt: Integer; { Description of CaseTwoA and CaseTwoB } CaseTwoA, CaseTwoB: Integer); end; implementation end.pasdoc/tests/testcases/error_macros.pas0000600000175000017500000000042213237143042021022 0ustar michalismichalis{ @abstract(This is a test what will happen when parsing error will occur within a macro.) pasdoc should print error message that clearly indicates where an error occured --- when expanding macro FOO. } unit error_macros; {$define FOO := record implementation} FOOpasdoc/tests/testcases/ok_non_matching_paren.pas0000700000175000017500000000102313237143042022646 0ustar michalismichalis{ @abstract(Test of @@( and @@) constructs.) @bold(This is bold, followed by two "at" chars and two parens. @@@@( ) ) No longer bold. @italic(This is italic, followed by one "at" char and one opening paren. @@@( ) No longer italic. @bold(This is bold, followed by two parens. ( ) ) No longer bold. @italic(This is italic, followed by one closing paren. @) ) No longer italic. @italic(This is bold, followed by "at" char. @@) No longer italic. } unit ok_non_matching_paren; interface implementation end.pasdoc/tests/testcases/error_unexpected_eof.pas0000600000175000017500000000010613237143042022532 0ustar michalismichalisunit error_unexpected_eof; interface type TRec = record case (pasdoc/tests/testcases/ok_external_class_hierarchy.txt0000600000175000017500000000002413034465544024126 0ustar michalismichalisTMyClass2=TMyClass1 pasdoc/tests/testcases/ok_deprecated_directive_note.pas0000600000175000017500000000255113237143042024206 0ustar michalismichalis{ -*- compile-command: "fpc -vw ok_deprecated_directive_note.pas" -*- } {$ifdef FPC}{$mode objfpc}{$H+}{$endif} { @abstract(Test deprecated directive with and without note.) } unit ok_deprecated_directive_note deprecated 'Deprecation note for unit'; interface procedure MyProc1; deprecated 'Deprecation note for procedure with some apostrophe: '' here you go:)'; procedure MyProc2; deprecated; procedure MyProc3; deprecated #72#$65'llo'; //< Deprecated note should say 'Hello'. Handled Ok, we convert and sum string tokens correctly. type TTestClass = class TestFieldDeprecated1: Integer deprecated 'Deprecation note for field'; TestFieldDeprecated2: Integer deprecated; procedure MyMethod1; deprecated 'Deprecation note for procedure'; procedure MyMethod2; deprecated; property TestProperty1: Integer; deprecated 'Deprecation note for property'; property TestProperty2: Integer; deprecated; end; TTestClassDeprecated1 = class end deprecated 'Deprecation note for class'; TTestClassDeprecated2 = class end deprecated; const TestConstDeprecated1 = 1 deprecated 'Deprecation note for constant'; TestConstDeprecated2 = 1 deprecated; implementation procedure MyProc1; begin end; procedure MyProc2; begin MyProc3; end; procedure MyProc3; begin end; procedure TTestClass.MyMethod1; begin end; procedure TTestClass.MyMethod2; begin end; end. pasdoc/tests/testcases/ok_anonymous_methods.pas0000600000175000017500000000043213237143042022572 0ustar michalismichalis// Test case for Delphi anonymous methods unit ok_anonymous_methods; interface type // description of @name TSimpleProcedure = reference to procedure; // description of @name TSimpleFunction = reference to function(x: string): Integer; implementation end. pasdoc/tests/testcases/ok_preformatted_test.pas0000600000175000017500000000105213237143042022551 0ustar michalismichalis(* @abstract(Test of @@preformatted tag.) @preformatted( Line one ? 1111 222 ? IIII WWW ? Some long space Some long space Three empty lines below (*not* converted into paragraph): -------- end of three empty lines. Some html and LaTeX special chars, to make sure that ConvertString is called when it should be: < > & \ { } Note that @-tags inside are not expanded: @name, and consequently you don't have to double @ char. Just like within @html and @latex tags.) *) unit ok_preformatted_test; interface implementation end.pasdoc/tests/testcases/warning_not_existing_tags.pas0000600000175000017500000000036313237143042023606 0ustar michalismichalisunit warning_not_existing_tags; interface { pasdoc should complain (display warnings) about wrong tags : @firstwarning(blah blah), @code(Wrong tag inside a @@code: @secondwarning(ble ble)). } procedure TestWarnings; implementation end.pasdoc/tests/testcases/ok_description_test.pas0000600000175000017500000000024313237143042022401 0ustar michalismichalisunit ok_description_test; interface type { TMyClass description from source file. } TMyClass = class public procedure Foo; end; implementation end.pasdoc/tests/testcases/test_description.txt0000600000175000017500000000005013034465544021751 0ustar michalismichalisThis is description called @bold(main). pasdoc/tests/testcases/ok_not_defined_omit.pas0000600000175000017500000000064013237143042022326 0ustar michalismichalisunit ok_not_defined_omit; interface {$ifdef NOT_DEFINED} { Pasdoc should omit "blah blah blah" below, because "NOT_DEFINED" is not defined. But previous bug caused pasdoc into missing "$ifdef GLWINDOW_GTK_2", and "$ifdef NOT_DEFINED" was closed by earlier "$endif"... Fixed now. } ({$ifdef GLWINDOW_GTK_2} 0 {$else} #0 {$endif} blah blah blah {$endif read_implementation} implementation pasdoc/tests/testcases/ok_utf8_failchar.pas0000600000175000017500000002530213237143042021541 0ustar michalismichalis{ UTF-8 file with BOM ($EF, $BB, $BF). This comment contains three code points that fail to translate to UCS2, they are in the Vietnamese (nôm) translation near the bottom of this page and should not trigger an error with Unicode Delphi but being replaced by the default fail char "?". Text below is borrowed from the webpage @HTML(UTF-8 SAMPLER
) I Can Eat Glass@br Sanskrit: काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम् ॥@br Sanskrit (standard transcription): kācaṃ śaknomyattum; nopahinasti mām.@br Classical Greek: ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει.@br Greek (monotonic): Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα.@br Greek (polytonic): Μπορῶ νὰ φάω σπασμένα γυαλιὰ χωρὶς νὰ πάθω τίποτα.@br Etruscan: (NEEDED)@br Latin: Vitrum edere possum; mihi non nocet.@br Old French: Je puis mangier del voirre. Ne me nuit.@br French: Je peux manger du verre, ça ne me fait pas mal.@br Provençal / Occitan: Pòdi manjar de veire, me nafrariá pas.@br Québécois: J'peux manger d'la vitre, ça m'fa pas mal.@br Walloon: Dji pou magnî do vêre, çoula m' freut nén må.@br Champenois: (NEEDED)@br Lorrain: (NEEDED)@br Picard: Ch'peux mingi du verre, cha m'foé mie n'ma.@br Corsican/Corsu: (NEEDED)@br Jèrriais: (NEEDED)@br Kreyòl Ayisyen (Haitï): Mwen kap manje vè, li pa blese'm.@br Basque: Kristala jan dezaket, ez dit minik ematen.@br Catalan / Català: Puc menjar vidre, que no em fa mal.@br Spanish: Puedo comer vidrio, no me hace daño.@br Aragones: Puedo minchar beire, no me'n fa mal .@br Mallorquín: (NEEDED)@br Galician: Eu podo xantar cristais e non cortarme.@br European Portuguese: Posso comer vidro, não me faz mal.@br Brazilian Portuguese (8): Posso comer vidro, não me machuca.@br Caboverdiano/Kabuverdianu (Cape Verde): M' podê cumê vidru, ca ta maguâ-m'.@br Papiamentu: Ami por kome glas anto e no ta hasimi daño.@br Italian: Posso mangiare il vetro e non mi fa male.@br Milanese: Sôn bôn de magnà el véder, el me fa minga mal.@br Roman: Me posso magna' er vetro, e nun me fa male.@br Napoletano: M' pozz magna' o'vetr, e nun m' fa mal.@br Venetian: Mi posso magnare el vetro, no'l me fa mae.@br Zeneise (Genovese): Pòsso mangiâ o veddro e o no me fà mâ.@br Sicilian: Puotsu mangiari u vitru, nun mi fa mali.@br Campinadese (Sardinia): (NEEDED)@br Lugudorese (Sardinia): (NEEDED)@br Romansch (Grischun): Jau sai mangiar vaider, senza che quai fa donn a mai.@br Romany / Tsigane: (NEEDED)@br Romanian: Pot să mănânc sticlă și ea nu mă rănește.@br Esperanto: Mi povas manĝi vitron, ĝi ne damaĝas min.@br Pictish: (NEEDED)@br Breton: (NEEDED)@br Cornish: Mý a yl dybry gwéder hag éf ny wra ow ankenya.@br Welsh: Dw i'n gallu bwyta gwydr, 'dyw e ddim yn gwneud dolur i mi.@br Manx Gaelic: Foddym gee glonney agh cha jean eh gortaghey mee.@br Old Irish (Latin): Con·iccim ithi nglano. Ním·géna.@br Irish: Is féidir liom gloinne a ithe. Ní dhéanann sí dochar ar bith dom.@br Ulster Gaelic: Ithim-sa gloine agus ní miste damh é.@br Scottish Gaelic: S urrainn dhomh gloinne ithe; cha ghoirtich i mi.@br Old Norse (Latin): Ek get etið gler án þess að verða sár.@br Norsk / Norwegian (Nynorsk): Eg kan eta glas utan å skada meg.@br Norsk / Norwegian (Bokmål): Jeg kan spise glass uten å skade meg.@br Føroyskt / Faroese: Eg kann eta glas, skaðaleysur.@br Íslenska / Icelandic: Ég get etið gler án þess að meiða mig.@br Svenska / Swedish: Jag kan äta glas utan att skada mig.@br Dansk / Danish: Jeg kan spise glas, det gør ikke ondt på mig.@br Sønderjysk: Æ ka æe glass uhen at det go mæ naue.@br Frysk / Frisian: Ik kin glês ite, it docht me net sear.@br Nederlands / Dutch: Ik kan glas eten, het doet mij geen kwaad.@br Kirchröadsj/Bôchesserplat: Iech ken glaas èèse, mer 't deet miech jing pieng.@br Afrikaans: Ek kan glas eet, maar dit doen my nie skade nie.@br Lëtzebuergescht / Luxemburgish: Ech kan Glas iessen, daat deet mir nët wei.@br Deutsch / German: Ich kann Glas essen, ohne mir zu schaden.@br Ruhrdeutsch: Ich kann Glas verkasematuckeln, ohne dattet mich wat jucken tut.@br Langenfelder Platt: Isch kann Jlaas kimmeln, uuhne datt mich datt weh dääd.@br Lausitzer Mundart ("Lusatian"): Ich koann Gloos assn und doas dudd merr ni wii.@br Odenwälderisch: Iech konn glaasch voschbachteln ohne dass es mir ebbs daun doun dud.@br Sächsisch / Saxon: 'sch kann Glos essn, ohne dass'sch mer wehtue.@br Pfälzisch: Isch konn Glass fresse ohne dasses mer ebbes ausmache dud.@br Schwäbisch / Swabian: I kå Glas frässa, ond des macht mr nix!@br Bayrisch / Bavarian: I koh Glos esa, und es duard ma ned wei.@br Allemannisch: I kaun Gloos essen, es tuat ma ned weh.@br Schwyzerdütsch (Zürich): Ich chan Glaas ässe, das schadt mir nöd.@br Schwyzerdütsch (Luzern): Ech cha Glâs ässe, das schadt mer ned.@br Plautdietsch: (NEEDED)@br Hungarian: Meg tudom enni az üveget, nem lesz tőle bajom.@br Suomi / Finnish: Voin syödä lasia, se ei vahingoita minua.@br Sami (Northern): Sáhtán borrat lása, dat ii leat bávččas.@br Erzian: Мон ярсан суликадо, ды зыян эйстэнзэ а ули.@br Northern Karelian: Mie voin syvvä lasie ta minla ei ole kipie.@br Southern Karelian: Minä voin syvvä st'oklua dai minule ei ole kibie.@br Vepsian: (NEEDED)@br Votian: (NEEDED)@br Livonian: (NEEDED)@br Estonian: Ma võin klaasi süüa, see ei tee mulle midagi.@br Latvian: Es varu ēst stiklu, tas man nekaitē.@br Lithuanian: Aš galiu valgyti stiklą ir jis manęs nežeidžia@br Old Prussian: (NEEDED)@br Sorbian (Wendish): (NEEDED)@br Czech: Mohu jíst sklo, neublíží mi.@br Slovak: Môžem jesť sklo. Nezraní ma. Polska / Polish: Mogę jeść szkło i mi nie szkodzi.@br Slovenian: Lahko jem steklo, ne da bi mi škodovalo.@br Croatian: Ja mogu jesti staklo i ne boli me.@br Serbian (Latin): Ja mogu da jedem staklo.@br Serbian (Cyrillic): Ја могу да једем стакло.@br Macedonian: Можам да јадам стакло, а не ме штета.@br Russian: Я могу есть стекло, оно мне не вредит.@br Belarusian (Cyrillic): Я магу есці шкло, яно мне не шкодзіць.@br Belarusian (Lacinka): Ja mahu jeści škło, jano mne ne škodzić.@br Ukrainian: Я можу їсти скло, і воно мені не зашкодить.@br Bulgarian: Мога да ям стъкло, то не ми вреди.@br Georgian: მინას ვჭამ და არა მტკივა.@br Armenian: Կրնամ ապակի ուտել և ինծի անհանգիստ չըներ։@br Albanian: Unë mund të ha qelq dhe nuk më gjen gjë.@br Turkish: Cam yiyebilirim, bana zararı dokunmaz.@br Turkish (Ottoman): جام ييه بلورم بڭا ضررى طوقونمز@br Bangla / Bengali: আমি কাঁচ খেতে পারি, তাতে আমার কোনো ক্ষতি হয় না।@br Marathi: मी काच खाऊ शकतो, मला ते दुखत नाही.@br Kannada (ಕನ್ನಡ): ಎಲ್ಲಾದರೂ ಇರು, ಎಂತಾದರು ಇರು, ಎಂದೆಂದಿಗೂ ನೀ ಕನ್ನಡವಾಗಿರು, ಕನ್ನಡವೇ ಸತ್ಯ.. ಕನ್ನಡವೇ ನಿತ್ಯ..@br Hindi: मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती.@br Tamil: நான் கண்ணாடி சாப்பிடுவேன், அதனால் எனக்கு ஒரு கேடும் வராது.@br Telugu: నేను గాజు తినగలను మరియు అలా చేసినా నాకు ఏమి ఇబ్బంది లేదు@br Urdu(3): میں کانچ کھا سکتا ہوں اور مجھے تکلیف نہیں ہوتی ۔@br Pashto(3): زه شيشه خوړلې شم، هغه ما نه خوږوي@br Farsi / Persian(3): .من می توانم بدونِ احساس درد شيشه بخورم@br Arabic(3): أنا قادر على أكل الزجاج و هذا لا يؤلمني.@br Aramaic: (NEEDED)@br Maltese: Nista' niekol il-ħġieġ u ma jagħmilli xejn.@br Hebrew(3): אני יכול לאכול זכוכית וזה לא מזיק לי.@br Yiddish(3): איך קען עסן גלאָז און עס טוט מיר נישט װײ.@br Judeo-Arabic: (NEEDED)@br Ladino: (NEEDED)@br Gǝʼǝz: (NEEDED)@br Amharic: (NEEDED)@br Twi: Metumi awe tumpan, ɜnyɜ me hwee.@br Hausa (Latin): Inā iya taunar gilāshi kuma in gamā lāfiyā.@br Hausa (Ajami) (2): إِنا إِىَ تَونَر غِلَاشِ كُمَ إِن غَمَا لَافِىَا@br Yoruba(4): Mo lè je̩ dígí, kò ní pa mí lára.@br Lingala: Nakokí kolíya biténi bya milungi, ekosála ngáí mabé tɛ́.@br (Ki)Swahili: Naweza kula bilauri na sikunyui.@br Malay: Saya boleh makan kaca dan ia tidak mencederakan saya.@br Tagalog: Kaya kong kumain nang bubog at hindi ako masaktan.@br Chamorro: Siña yo' chumocho krestat, ti ha na'lalamen yo'.@br Javanese: Aku isa mangan beling tanpa lara.@br Vietnamese (quốc ngữ): Tôi có thể ăn thủy tinh mà không hại gì.@br Vietnamese (nôm) (4): 些 𣎏 世 咹 水 晶 𦓡 空 𣎏 害 咦@br Thai: ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ@br Mongolian (Cyrillic): Би шил идэй чадна, надад хортой биш@br Chinese: 我能吞下玻璃而不伤身体。@br Chinese (Traditional): 我能吞下玻璃而不傷身體。@br Taiwanese(6): Góa ē-tàng chia̍h po-lê, mā bē tio̍h-siong.@br Japanese: 私はガラスを食べられます。それは私を傷つけません。@br Korean: 나는 유리를 먹을 수 있어요. 그래도 아프지 않아요@br Bislama: Mi save kakae glas, hemi no save katem mi.@br Hawaiian: Hiki iaʻu ke ʻai i ke aniani; ʻaʻole nō lā au e ʻeha.@br Marquesan: E koʻana e kai i te karahi, mea ʻā, ʻaʻe hauhau.@br Chinook Jargon: Naika məkmək kakshət labutay, pi weyk ukuk munk-sik nay.@br Navajo: Tsésǫʼ yishą́ągo bííníshghah dóó doo shił neezgai da.@br Cherokee (and Cree, Chickasaw, Cree, Micmac, Ojibwa, Lakota, Inuktitut, Náhuatl, Quechua, Aymara, and other American languages): (NEEDED)@br Garifuna: (NEEDED)@br Gullah: (NEEDED)@br Lojban: mi kakne le nu citka le blaci .iku'i le se go'i na xrani mi@br Nórdicg: Ljœr ye caudran créneþ ý jor cẃran.@br } unit ok_utf8_failchar; interface implementation end. pasdoc/tests/testcases/ok_cdecl_external.pas0000600000175000017500000000103513237143042021773 0ustar michalismichalis{ Bug: Parsing of this unit fails with Warning[2]: Error EPasDoc: todo/ok_cdecl_external.pas(5): Unexpected keyword external. parsing unit ok_cdecl_external.pas, continuing... Bar and Xyz added as additional tests. Update: it's fixed now, pasdoc parses it correctly. } unit ok_cdecl_external; interface procedure Foo; cdecl; external 'whatever'; procedure Bar; cdecl; external 'bar_library_name' name 'bar_name_in_library'; procedure Xyz; external 'xyz_library_name' name 'xyz_name_in_library'; cdecl; implementation end.pasdoc/tests/testcases/ok_image.pas0000600000175000017500000000123413237143042020102 0ustar michalismichalis{ @abstract(This is @@image tag test.) Note that for dvi, eps image will be chosen (for pdf and html, jpg): @image(ok_image_picture.eps ok_image_picture.jpg) Note that using the same image for the 2nd time will cause the same image to be included in the output (i.e. in the output we have @italic(one) copy of ok_image_picture.jpg, not @italic(two)). @image(ok_image_picture.eps ok_image_picture.jpg) Now note that pdf format will choose pdf version of the image: @image(ok_image_picture.eps ok_image_picture.pdf ok_image_picture.jpg) } unit ok_image; interface const Unimportant = 0; implementation end.pasdoc/tests/testcases/ok_helpinsight_comments.pas0000600000175000017500000000155713237143042023253 0ustar michalismichalis{ Test of handling help insight comments, in the form "/// ... ". See http://delphi.wikia.com/wiki/Help_insight, example snippet with @link(Parse) function is straight from there. See https://sourceforge.net/tracker/?func=detail&atid=304213&aid=3485263&group_id=4213. } unit ok_helpinsight_comments; interface ///

parses the commandline /// is a string giving the commandline. /// NOTE: Do not pass System.CmdLine since it contains the /// program's name as the first "parameter". /// If you want to parse the commandline as passed by /// windows, call the overloaded Parse method without /// parameters. It handles this. procedure Parse(const _CmdLine: string); implementation end.pasdoc/tests/testcases/ok_line_break.pas0000600000175000017500000000035713237143042021120 0ustar michalismichalis{ Test @@br tag. } unit ok_line_break; interface { 1st paragraph. @br Second line of 1st paragraph. 2nd paragraph. Blah blah blah. 3rd paragraph. @br Second line of 3rd paragraph. } procedure TestLineBreak; implementation end.pasdoc/tests/testcases/ok_list_item_set_number.pas0000600000175000017500000000040113237143042023227 0ustar michalismichalis{ @abstract(Testcase for [https://sourceforge.net/tracker/?func=detail&atid=104213&aid=1533017&group_id=4213]) @orderedList( @itemSetNumber(0) @itemSpacing(Compact) @item(foo) @item(bar) ) } unit ok_list_item_set_number; interface implementation end.pasdoc/tests/testcases/ok_link_1_char.pas0000600000175000017500000000123413237143042021172 0ustar michalismichalisunit ok_link_1_char; interface uses Classes; type {@abstract(@name is used to specify the real-world coordinates of a pixel in a bitmap.)} TMeasurementPointItem = class(TCollectionItem) private // @name: double; // See @link(X). FX: double; // @name: double; // See @link(Y). FY: double; // See @link(X). procedure SetX(const Value: double); // See @link(Y). procedure SetY(const Value: double); published // @name is the X real-world coordinate. property X: double read FX write SetX; // @name is the Y real-world coordinate. property Y: double read FY write SetY; end; implementation end. pasdoc/tests/testcases/warning_abstract_twice.pas0000600000175000017500000000034113237143042023050 0ustar michalismichalis{ @abstract(First abstract) @abstract(Second abstract) pasdoc should warn "You used @@abstract twice in description of item ..." or something like that. } unit warning_abstract_twice; interface implementation end.pasdoc/tests/testcases/warning_inherited_test.pas0000600000175000017500000000200313237143042023061 0ustar michalismichalisunit warning_inherited_test; interface type { This is a class without ancestor name specified. Inherited is @inherited. Inherited class is @inheritedClass. } TMyClass0 = class { Inherited is @inherited. Inherited class is @inheritedClass. } procedure Clear; end; { This is a class with specified ancestor name, but ancestor (TStringList) is not parsed by PasDoc. Inherited is @inherited. Inherited class is @inheritedClass. } TMyClass1 = class(TStringList) { Inherited is @inherited. Inherited class is @inheritedClass. } procedure Clear; end; { This is a class with specified ancestor name, and ancestor (TMyClass1) is parsed by PasDoc. Inherited is @inherited. Inherited class is @inheritedClass. } TMyClass2 = class(TMyClass1) { Inherited is @inherited. Inherited class is @inheritedClass. } procedure Clear; end; { Inherited is @inherited. Inherited class is @inheritedClass. } procedure Test; implementation end.pasdoc/tests/testcases/ok_value_member_tags.pas0000600000175000017500000000154013237143042022501 0ustar michalismichalisunit ok_value_member_tags; interface type { @member MyField Description of MyField here. @member(MyMethod Description of MyMethod here, using parenthesis. @param(A Description of param A.) @returns(Some boolean value.) ) @member(MyProperty Description of MyProperty here, with some recursive tags inside: @code(Some code with a link to @link(TMyRecord)).) } TMyClass = class MyField: Integer; function MyMethod(A: Integer): boolean; property MyProperty: Integer read MyField write MyField; end; { @member MyField Description of MyField in TMyRecord here. } TMyRecord = record MyField: Integer; end; { @value meOne Description of meOne follows. @value meThree Description of meThree, with some link: @link(TMyClass.MyField). } TMyEnum = (meOne, meTwo, meThree); implementation end. pasdoc/tests/testcases/ok_no_sort.pas0000600000175000017500000000047313237143042020507 0ustar michalismichalisunit ok_no_sort; interface type { Enum values are not sorted } TMyEnum = (meZZZ, meAAA); { Record fields are not sorted } TMyRecord = record ZZZ: Integer; AAA: Integer; end; { Class fields are sorted } TMyClass = class ZZZ: Integer; AAA: Integer; end; implementation end.pasdoc/tests/testcases/ok_links_2.pas0000600000175000017500000000036713237143042020367 0ustar michalismichalis{ Helper unit for test in ok_links. } unit ok_links_2; interface procedure MyProc; procedure MyOtherProc; type TSomeClass = class procedure MyMethod; end; TSomeOtherClass = class procedure MyMethod; end; implementation end.pasdoc/tests/testcases/ok_longcode_underscores.pas0000600000175000017500000000070413237143042023227 0ustar michalismichalis{ 2005-06-07: Latex version of docs for this unit are wrong, because ConvertString is not called to convert _ char. So _ is not escaped and latex fails. Also, HTML version is bad, because "With" is formatted in bold, because it's treated like keyword. Fixed by adding _ to AlphaNumeric in PasDoc_Gen in FormatPascalCode. @longcode(# Identifier_With_Underscores; #) } unit ok_longcode_underscores; interface implementation end.pasdoc/tests/testcases/ok_class_record_helpers.pas0000600000175000017500000000127713237143042023214 0ustar michalismichalis// Test case for Delphi class and record helpers unit ok_class_record_helpers; interface type TForwardClass = class; // description of @name TSimpleRecord = record // description of @name SimpleField: Integer; end; // description of @name TMyRecordHelper = record helper for TSimpleRecord protected // description of @name procedure HelloWorld; end; // description of @name TAncestorClassHelper = class helper for TApplication end; // description of @name TDescendantClassHelper = class helper(TAncestorClassHelper) for TApplication // description of @name procedure HelloWorld; end; implementation end. pasdoc/tests/testcases/ok_class_var.pas0000600000175000017500000000071313237143042020776 0ustar michalismichalis{ See bug [https://sourceforge.net/tracker/?func=detail&atid=104213&aid=1489442&group_id=4213] } unit ok_class_var; interface type TPluginManager = class private FLoadedPlugins : TPluginCollection; FAfterPluginLoad : TAfterPluginLoadEvent; class var FInstance : TPluginManager; public LoadedPlugins : TPluginCollection; AfterPluginLoad : TAfterPluginLoadEvent; class var Instance : TPluginManager; end; implementation end.pasdoc/tests/testcases/ok_latex_head.pas0000600000175000017500000000050013237143042021111 0ustar michalismichalis{ Unit testing --latex-head option. Very long word: unitfortestingoflatexheadoptionveryveryveryveryverylongword. Another very long word, this time it should be broken because of \hyphenation: anotherverylongwordthistimeitshouldbebrokenbecauseofhyphenation. } unit ok_latex_head; interface implementation end.pasdoc/tests/testcases/ok_ignore_leading.pas0000600000175000017500000000063513237143042021772 0ustar michalismichalisunit ok_ignore_leading; interface const {* * Test *} A = 1; {**************************** * Test2 ****************************} B = 1; {* * count of preceding whitespace does not matter * count of preceding whitespace does not matter **** consecutive characters are ignored too as in Javadoc not all lines have to start with the character paragraph works. *} C = 1; implementation end. pasdoc/tests/testcases/ok_expanding_descriptions.pas0000600000175000017500000001111213237143042023557 0ustar michalismichalis{ @abstract(This is a test of tags expanded by TPasItem handlers. Of course with @@abstract tag using some recursive tag: See also @link(TestPasMethodTags)) This whole unit is actually a big test of many things related to pasdoc's @@-tags. @author(Michalis ) @created(2005-03-30) @cvs($Author: kambi $) @lastmod(2005-03-30) See also @link(TMyClass) for other test of @@cvs tag (with $Date, as an alternative specification of @@lastmod) } unit ok_expanding_descriptions; interface { Write two at chars, like this @@@@, to get one @@ in output. E.g. @@ link(TSomeClass). E.g. @@link(TSomeClass). E.g. @@html foobar. E.g. @@link . } procedure TwoAt; { aa aaaaa aa aaa @code(SHGetSpecialFolderPath(0, @@Path, CSIDL_APPDATA, true)) aaaa aaaaaa aaaaaa aaaaaaaaa aaaa At some point, this test caused the bug: final tag was inserted in converted form (processed with ConvertString) into html output. In effect, there was an opening tag but there was no closing tag. } procedure RecursiveTwoAt; (* Note that inside @@longcode below I should be able to write singe @@ char to get it in the output, no need to double it (like @@@@). No tags are expanded inside longcode. Also note that paragraphs are not expanded inside longcode (no

inside

...
in html output). Of course html characters are still correctly escaped (< changes to < etc.). @longcode(# procedure Foo; begin if A < B then Bar; { @link(No, this is not really pasdoc tag) } end; procedure Bar(X: Integer); begin CompareMem(@X, @Y); end; #) *) procedure TestLongCode; (* @html( This is some dummy html code, just to show that inside @html tag of pasdoc (note that I used single @ char in this sentence) nothing is expanded by pasdoc. No paragraphs are created by pasdoc. (This text is still in the 1st, not in the 2nd, paragraph in html output)

You must explicitly write <p> to get paragraph. No tags work, e.g. @link(TestLongCode). ) @latex( This is some {\bf dummy} \LaTeX code, just to show that inside @latex tag of pasdoc (note that I used single @ char in this sentence) nothing is expanded by pasdoc. No paragraphs are created by pasdoc. Although, in case of LaTeX output, LaTeX rules for making paragraphs are the same as the pasdoc's rules (one empty lines marks paragraph), so you will not notice. This is brutal line-break: \\ I'm still in the same paragraph, after line-break. I'm 2nd paragraph. No tags work, e.g. @link(TestLongCode). ) Note that text inside @@html / @@latex tags is absolutely not touched by pasdoc. Characters are not escaped (< is *not* changed to < in the html case), @@tags are not expanded, @@ needs not to be doubled, paragraphs (

in the html case) are not inserted. *) procedure TestHtmlAndLatexTags; type EFoo = class(Exception) end; EBar = class(Exception) end; EXyz = class(Exception) end; { @@code and @@returns (and some others) tags are recursive, you can freely put other tags inside. @code(This is link to @link(TestHtmlAndLatexTags).) @raises(EFoo in case @link(TestHtmlAndLatexTags) returns value >= 4 (actually, this is just a test text).) } procedure TestRecursiveTag; { This is a test of tags expanded by TPasMethod handlers. Note that all three tags are expanded recursively. @param(A means sthg about @link(TestRecursiveTag)) @param(B also means sthg. @code(Code inside.)) @returns(You can make tags recursion any level deep : @code(This is a code with a link to @link(TestRecursiveTag))) @raises(EFoo when you do sthg nasty, like call @link(TestRecursiveTag) when you're not supposed to) @raises(EBar when code @code(if 1 = 0 then DoSomething;) will work as expected.) } function TestPasMethodTags(A, B: Integer): string; type TMyClassAncestor = class private MyField: boolean; public //@abstract(This comment should be inherited.) property inheritable: boolean read MyField; end; { These are some tags that are not allowed to have parameters: name @name, inherited @inherited, nil @nil, true @true, false @false, classname @classname. Some of them are valid only within a class, but this is not important for this test. @cvs($Date: 2010-04-26 04:04:35 +0200 (pon) $) } TMyClass = class(TMyClassAncestor) published //This is the detailed description. property inheritable; end; { And a test of @exclude. This should not be seen in final output! } procedure TestExclude; implementation end. pasdoc/tests/testcases/ok_caret_character.pas0000600000175000017500000000122113237143042022126 0ustar michalismichalis{ @abstract(Test of parsing "^char" constants, see [http://www.freepascal.org/docs-html/ref/refsu7.html].) Note that while FPC docs say that only ^A .. ^Z are allowed, actually both FPC 2.0.0 and Kylix 3 accept other characters after the caret, e.g. "^\" is accepted. See also bug report "[ 1358911 ] Invalid character in input stream". } unit ok_caret_character; interface const C2 = ^A; C3 = ^B; C4 = ^Z; // SUBstitute SUB = ^Z; // ESCape ESC = ^[; // File Separator FS = ^\; // Group Separator GS = ^]; // Record Separator RS = ^^; // Unit Separator US = ^_; implementation end.pasdoc/tests/testcases/ok_longcode_special_chars.pas0000600000175000017500000000033513237143042023473 0ustar michalismichalis(* @abstract(Yet another test of @@longcode.) @longcode(# begin Writeln('Some special HTML (<, >, &) and LaTeX ({, }, \) chars.'); end; #) *) unit ok_longcode_special_chars; interface implementation end.pasdoc/tests/testcases/error_expected_semicolon.pas0000600000175000017500000000013713237143042023412 0ustar michalismichalisunit error_expected_semicolon; interface type TMyType = (A, B) record implementation end.pasdoc/tests/testcases/ok_macro_include.inc0000600000175000017500000000020113237143042021603 0ustar michalismichalis{$DEFINE CLASS_CONSTRUCTOR:=Constructor Init; Overload} {$DEFINE SPAWNABLE_CONSTRUCTOR:=Constructor Init(Param:String); Overload}pasdoc/tests/testcases/warning_desc_end.pas0000600000175000017500000000010113237143042021610 0ustar michalismichalis{ @code(} unit warning_desc_end; interface implementation end.pasdoc/tests/testcases/ok_tag_params_no_parens.pas0000600000175000017500000000322113237143042023200 0ustar michalismichalis{ @abstract This is a demo unit using tags without enclosing them in () Parsing logic is simple: if a tag requires some parameters but you don't put open paren '(' char right after it, then tag parameters are understood to span to the end of line (or to the end of comment). This doesn't break compatibility with documentation that enclosed parameters in (), because tags that have parameters were *required* to have '(' char after them. So they will still be correctly seen and parsed to the matching closing paren. See @link(SomeProc) for more examples and comments. @author Michalis @created 2005-05-04 @lastmod 2005-05-04 @cvs $Author: kambi $ } unit ok_tag_params_no_parens; interface type EFoo = class(Exception); (* Note that this rule allows you to not specify () for *any* tag that has parameters. Even for @@link tag: @link ok_tag_params_no_parens This rule doesn't create any problems for tags without parameters, like the @@name tag: here it is: @name. Such tags never have parameters, and on the above line you *don't* have @@name tag with parameters "tag. Such tags never have parameters,". Instead, you just specified @name tag and "tag. Such tags never have parameters," is just a normal text. Check out this longcode: @longcode# begin Writeln('Hello world'); end; { This works ! } # See also @@html and @@latex tags: @html I'm red @latex {\bf I'm bold.} And here is some code: @code begin X := Y + 1; end; @raises EFoo when it's in bad mood @param A means something @returns Some integer *) function SomeProc(A: Integer): Integer; implementation end.pasdoc/tests/testcases/ok_macros.pas0000600000175000017500000000336413237143042020312 0ustar michalismichalis{$macro on} {$mode objfpc} {$define UNIT_DECL := unit ok_macros; interface} { @abstract(Test of FPC macros handling.) Parts based on [http://sourceforge.net/tracker/index.php?func=detail&aid=861356&group_id=4213&atid=354213] } UNIT_DECL {$INCLUDE ok_macro_include.inc} type TAncestor = class end; TMyClass = class(TAncestor) public CLASS_CONSTRUCTOR; end; { Below is an example of a very bad and confusing (but valid) macro usage. Just to test pasdoc. } {$define FOO := a:Integer); (* This is very stupid way to declare a procedure *) procedure MyProc2(} procedure MyProc1(FOO b: Integer); {$undef FOO} function Foo(c: string): Integer; procedure MyProc3( {$define FOO:=1} X: Integer = FOO; {$define FOO:=2} Y: Integer = FOO); {$ifdef FOO} procedure ThisShouldBeIncluded; {$define FOO_WAS_DEFINED:=true} {$else} procedure ThisShouldNotBeIncluded; {$define FOO_WAS_DEFINED:=false} {$endif} const ThisShouldBeTrue = FOO_WAS_DEFINED; {$undef FOO} {$ifndef FOO} procedure ThisShouldBeIncluded2; {$else} procedure ThisShouldNotBeIncluded2; {$endif} { Test of recursive macro expansion. } {$define ONE:=1} {$define TWO:=ONE + ONE} {$define FOUR := (TWO) * (TWO)} const FourConst = FOUR; { Test that symbol that is not a macro is something different than a macro that expands to nothing. } {$define NOT_NOTHING := + 1} {$define NOTHING :=} const OneAndNotNothing = 1 NOT_NOTHING; OnlyOne = 1 NOTHING; implementation constructor TMyClass.Init; begin end; procedure MyProc1(a: Integer); begin end; procedure MyProc2(b: Integer); begin end; procedure MyProc3(X: Integer; Y: Integer); begin end; function Foo(c: string): Integer; begin end; procedure ThisShouldBeIncluded; begin end; procedure ThisShouldBeIncluded2; begin end; end. pasdoc/tests/testcases/ok_include.pas0000600000175000017500000000073013237143042020443 0ustar michalismichalis{ @abstract(This is a test of @@include tag.) Behold included file ok_include_1.txt: @include(ok_include_1.txt) Behold file ok_include_1.txt that is included for the 2nd time here: @include(ok_include_1.txt) Behold file ok_include_1.txt that is included for the 3rd time here, and this time it's inside @@bold: @bold @include(ok_include_1.txt) Take a look at @link(ok_include_intro Introduction) too. } unit ok_include; interface implementation end.pasdoc/tests/testcases/ok_deprecated_const_string.pas0000600000175000017500000000024013237143042023710 0ustar michalismichalisunit ok_deprecated_const_string; interface procedure Foo; deprecated 'Since D2010 a const string may follow'; implementation procedure Foo; begin end; end.pasdoc/tests/testcases/ok_longcode_end_semicolon.pas0000600000175000017500000000030213237143042023503 0ustar michalismichalis{ Before 2008-01-17, ending semicolon was missing in the output: @longCode(# Progress.UserInterface := ProgressGLInterface;#) } unit ok_longcode_end_semicolon; interface implementation end.pasdoc/tests/testcases/ok_ignore_leading_hash.pas0000600000175000017500000000046713237143042023000 0ustar michalismichalisunit ok_ignore_leading_hash; interface const {############################### # @--ignore-leading=# ###############################} A = 1; {############################### # @--ignore-leading=# ############################### (should produce the same result) } B = 1; implementation end. pasdoc/tests/testcases/ok_strict_visibilities.pas0000600000175000017500000000055413237143042023113 0ustar michalismichalis{$ifdef FPC} {$mode objfpc} {$endif} unit ok_strict_visibilities; interface Type TStrictVisibility = class(TObject) strict private // the visibility of @name is "strict private." StrictPrivateInteger: integer; strict protected // the visibility of @name is "strict protected." StrictProtectedInteger: integer; end; implementation end. pasdoc/tests/testcases/ok_record_case_parsing.pas0000600000175000017500000000143513237143042023017 0ustar michalismichalisunit ok_record_case_parsing; interface type TRec1 = record case boolean of false: (A: Integer); true: (B: Integer); end; TRec2 = record case Field1: boolean of false: (A: Integer); true: (B: Integer;); end; { @member C Description of C } TRec3 = record case Integer of 0: ( { Descr of A } A: Integer; { Descr of B } B: ShortString;); 1: ( C: Integer); 2: ( { Descr of D, E, F } D, E, F: Integer; G: ShortString;); 3: ( { Descr of H } H: Integer); end; TRec4 = record case boolean of false: ( case Integer of 0: (A: Integer); 1: (B: Integer) ); true: (C: Integer); end; implementation end.pasdoc/tests/testcases/ok_complicated_record.pas0000600000175000017500000000316713237143042022651 0ustar michalismichalis// Submitted in thread "Pasdoc tests" on pasdoc-main on 2005-04-11 // by Richard B Winston. // pasdoc passes it, but the test checks many important things // (line glueing single-line comments by pasdoc, record with case etc.) // so it's worth adding it to test cases. // // @abstract( This unit is used for converting to and from the BigEndian format. // See http://community.borland.com/article/0,1410,28964,00.html.) unit ok_complicated_record; interface type //enumeration used in variant record BytePos = (EndVal, ByteVal); // @name is a pointer to a @link(TDoubleEndianCnvRec). PDoubleEndianCnvRec = ^TDoubleEndianCnvRec; { @abstract(@name is used in @link(ConvertDouble) to convert a double to or from the BigEndian format.) @longcode(# TDoubleEndianCnvRec = packed record case BytePos of EndVal: (EndianVal: double); ByteVal: (Bytes: array[0..SizeOf(double) - 1] of byte); end; #) } TDoubleEndianCnvRec = packed record case BytePos of //The value we are trying to convert EndVal: (EndianVal: double); //Overlapping bytes of the double ByteVal: (Bytes: array[0..SizeOf(double) - 1] of byte); end; // @abstract(@name copies @link(TDoubleEndianCnvRec.Bytes) // in reverse order from Source^ to Dest^.) // @name is used in @link(ConvertDouble). procedure SwapDoubleBytes(Dest, Source: PDoubleEndianCnvRec); // @abstract(@name converts Value to or from the BigEndian format.) // @param(Value is the value to be converted.) // @returns(Value after being converted to or from the BigEndian format.) function ConvertDouble(const Value: double): double; implementation end. pasdoc/tests/testcases/ok_const_1st_comment_missing.pas0000600000175000017500000000045613237143042024215 0ustar michalismichalis{: See bug [ 1198381 ] "Comment on 1st const does'nt work" } unit ok_const_1st_comment_missing; interface const //Range 600: bla bla //: bla bla copy. ec_COPY = 600; //: bla bla cut. ec_CUT = 601; //: bla bla paste. ec_PASTE = 602; implementation end.pasdoc/tests/testcases/ok_directive_as_identifier.pas0000600000175000017500000000151313237143042023663 0ustar michalismichalis{ All calling-convention specifiers must *not* be made links in docs. But "Register" procedure name must be made a link. Yes, the difficulty is here that "register" is once a calling-convention specifier and once a procedure name. This is related to bug submitted to pasdoc-main list [http://sourceforge.net/mailarchive/message.php?msg_id=11397611]. } unit ok_directive_as_identifier; interface procedure Register; register; procedure Cdecl; register; procedure Foo; register; procedure Bar; cdecl; type TMyClass = class end; { Some other test for THTMLDocGenerator.WriteCodeWithLinks, while I'm at it: Note that link to TMyClass should be correctly made. 'register' should be displayed as a string, of course, and not linked. } procedure Foo1(const S: string = 'register'; MyClass: TMyClass); implementation end.pasdoc/tests/testcases/ok_no_link_inside_class.pas0000600000175000017500000000102313237143042023165 0ustar michalismichalisunit ok_no_link_inside_class; interface type TMyClass = class procedure MyMethod; { This should be linked: @link(MyMethod). This should be linked: @link(TMyClass.MyMethod). This should be linked: @link(MyGlobalProcedure). } procedure MyOtherMethod; end; { This should NOT be linked: @link(MyMethod). This should be linked: @link(TMyClass.MyMethod). This should be linked: @link(MyOtherGlobalProcedure). } procedure MyGlobalProcedure; procedure MyOtherGlobalProcedure; implementation end. pasdoc/tests/testcases/error_macros_recursive.pas0000600000175000017500000000051213237143042023111 0ustar michalismichalis{ @abstract(This is a test what will happen when you try to recursively expand a macro.) pasdoc should exit with appropriate error message. Not something ugly, like out of memory (or hanging your system and eating all mem it can). } unit error_macros_recursive; interface {$define FOO:=FOO} FOO implementation end.pasdoc/tests/testcases/ok_links.pas0000600000175000017500000000230013237143042020133 0ustar michalismichalis{ @abstract(Test various things with links.) Link to proc inside this unit : @link(MyProc), and a qualified link to the same thing : @link(ok_links.MyProc). Link to proc inside other unit: @link(ok_links_2.MyOtherProc), link to proc inside other unit that has the same name as proc in this unit: @link(ok_links_2.MyProc). Link to method in class in this unit: @link(TSomeClass.MyMethod), and a more qualified link to the same thing : @link(ok_links.TSomeClass.MyMethod). Link to method in class in second unit: @link(TSomeOtherClass.MyMethod), link to method in class in second unit that has the same name as class in this unit: @link(ok_links_2.TSomeClass.MyMethod). Link to this unit : @link(ok_links), to other unit : @link(ok_links_2). } unit ok_links; interface uses ok_links_2; { Link to self : @link(MyProc), and a second one: @link(ok_links.MyProc), link to MyProc in other unit: @link(ok_links_2.MyProc). } procedure MyProc; type TSomeClass = class { Two links to @code(MyOtherMethod) : qualified @link(TSomeClass.MyOtherMethod), not qualified @link(MyOtherMethod) } procedure MyMethod; procedure MyOtherMethod; end; implementation end. pasdoc/tests/testcases/ok_dot_unitname.pas0000600000175000017500000000013413237143042021504 0ustar michalismichalisunit ok.dot.unitname; interface uses dot.inside.unitname; implementation end.pasdoc/tests/testcases/error_line_number_3.pas0000600000175000017500000000204213237143042022257 0ustar michalismichalis{ Of course this unit is invalid, definition of InvalidConstant is suddenly truncated. So pasdoc should raise an error. But it's important on what line error is raisen. A previous bug caused the line to be "error_line_number_3.pas(13)", i.e. line number was not affected by dummy "function gtk_check_menu_item_get_active(" lines. } unit error_line_number_3; interface {$ifdef NOT_DEFINED} function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( function gtk_check_menu_item_get_active( {$endif} const InvalidConstant: end.pasdoc/tests/testcases/ok_item_set_number.pas0000600000175000017500000000074213237143042022204 0ustar michalismichalis{ @abstract(Test of of @@itemSetNumber tag.) @orderedList( @item Foo @item Foo @item Foo @item Foo @item Foo @itemSetNumber 144 @item Foo @item Foo @item Foo @item( @orderedList( @item Bar @item Bar @item Bar @itemSetNumber 20 @item Bar @item Bar @item Bar ) ) @item Foo @item Foo @item Foo ) } unit ok_item_set_number; interface implementation end.pasdoc/tests/testcases/ok_table.pas0000600000175000017500000000340313237143042020107 0ustar michalismichalis(* @abstract(Test of @@table-related features.) Example from @@table doc page in wiki: @table( @rowHead( @cell(Value1) @cell(Value2) @cell(Result) ) @row( @cell(@false) @cell(@false) @cell(@false) ) @row( @cell(@false) @cell(@true) @cell(@true) ) @row( @cell(@true) @cell(@false) @cell(@true) ) @row( @cell(@true) @cell(@true) @cell(@false) ) ) Small tables tests: @table( @row( @cell(One-cell table is OK) ) ) @table( @rowHead( @cell(One-cell head table is OK) ) ) @table( @rowHead( @cell(A) @cell( @bold(Foo) ) ) ) Test that everything within @@cell tag is OK. Actually, test below is a stripped down (to be accepted by LaTeX) version of a more advanced test in ok_table_nonlatex.pas file. @table( @rowHead( @cell(Dashes: ---, --, -, @--) @cell(URLs: http://pasdoc.sourceforge.net/) ) @row( @cell(C) @cell(D) ) ) Now nested table and other nicies are within a normal row, instead of heading row. @table( @rowHead( @cell(C) @cell(D) ) @row( @cell(Within a cell many things are are accepted) @cell(including paragraphs: This is new paragraph.) ) @row( @cell(Dashes: ---, --, -, @--.) @cell(URLs: http://pasdoc.sourceforge.net/) ) @row( @cell(And, last but not least, nested table: @table( @rowHead( @cell(1) @cell(2) ) @rowHead( @cell(3) @cell(4) ) )) @cell(B) ) ) Some 2-row table tests: @table( @rowHead( @cell(A) @cell(B) ) @rowHead( @cell(C) @cell(D) ) ) @table( @row( @cell(A) @cell(B) ) @row( @cell(C) @cell(D) ) ) @table( @row( @cell(A) @cell(B) ) @rowHead( @cell(C) @cell(D) ) ) *) unit ok_table; interface implementation end. pasdoc/tests/testcases/ok_different_image_same_filename_dir2/0000700000175000017500000000000013237143042025206 5ustar michalismichalispasdoc/tests/testcases/ok_different_image_same_filename_dir2/test_description.txt0000600000175000017500000000005113034465544031340 0ustar michalismichalisThis is description called @bold(dir_2). pasdoc/tests/testcases/ok_different_image_same_filename_dir2/image.png0000600000175000017500000000051713034465544027014 0ustar michalismichalisPNG  IHDR2#PLTEٟ pHYs  tIME4UUtEXtCommentCreated with The GIMPd%nIDAT8c 0ʌ! CxeU"d>ȣ"xQddcy47>=>1 This is a closing paren @) and open @( and "at" char @@ inside HTML.) @longCode(# // This is a closing paren @) and open @( and "at" char @@ inside longcode. #) *) unit ok_at_character_in_verbatim; interface implementation end.pasdoc/tests/testcases/ok_longcode_indentation.pas0000600000175000017500000000156613237143042023216 0ustar michalismichalisunit ok_longcode_indentation; interface { Should cut nothing: @longCode(#one two three #) } procedure Foo1; { Should cut 4 spaces: @longCode(# one two three #) } procedure Foo2; { Should cut 2 spaces: @longCode(# one two three #) } procedure Foo3; { Should cut nothing (there's a tab here): @longCode(# one two three #) } procedure Foo4; { Should cut tab + 2 spaces: @longCode(# one two three #) } procedure Foo5; { Should cut 4 spaces (there's trailing whitespace in 1st lines here, that should be ignored): @longCode(# one #) } procedure Foo6; { Should cut 4 spaces (empty line doesn't shorten IndentationPrefix): @longCode(# if something then begin // empty line below end; #) } procedure Foo7; implementationpasdoc/tests/testcases/ok_program.pas0000600000175000017500000000014313237143042020465 0ustar michalismichalisprogram ok_program; uses foo, bar; procedure my_proc; var my_var: Integer; begin end; begin end.pasdoc/tests/testcases/ok_library.dpr0000600000175000017500000000137613237143042020475 0ustar michalismichalislibrary LibraryTest; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses SysUtils, Classes, WeirdRecord in 'WeirdRecord.pas', StrictVisibilities in 'StrictVisibilities.pas'; {$R *.res} begin end. pasdoc/tests/testcases/ok_property_decl.pas0000600000175000017500000000033213237143042021671 0ustar michalismichalisunit ok_property_decl; interface type TMyClass = class private function GetMyProperty(S: string): Integer; public property MyProperty[S: string]: Integer read GetMyProperty; end; implementation end.pasdoc/tests/testcases/test_subdir/0000700000175000017500000000000013237143042020147 5ustar michalismichalispasdoc/tests/testcases/test_subdir/ok_relative_include_conf.inc0000600000175000017500000000001613237143042025655 0ustar michalismichalis{$mode objfpc}pasdoc/tests/testcases/test_subdir/another_test_subdir/0000700000175000017500000000000013237143042024216 5ustar michalismichalispasdoc/tests/testcases/test_subdir/another_test_subdir/ok_relative_include_2.pas0000600000175000017500000000100613237143042031152 0ustar michalismichalis{ This is another test unit that includes ok_relative_include_conf.inc file two times. This time note that the ok_relative_include_conf.inc file is already in the parent directory of this unit file, so once again @bold(no matter what is current dir when running pasdoc) --- you should not need to add any -I option to pasdoc to find ok_relative_include_conf.inc. } unit ok_relative_include_2; {$I '../ok_relative_include_conf.inc'} {$I ../ok_relative_include_conf.inc} interface implementation end. pasdoc/tests/testcases/test_subdir/ok_relative_include_1.pas0000600000175000017500000000072213237143042025106 0ustar michalismichalis{ This is a test unit that includes ok_relative_include_conf.inc file two times. Note that the ok_relative_include_conf.inc file is in the same directory as this unit, so @bold(no matter what is current dir when running pasdoc) --- you should not need to add any -I option to pasdoc to find ok_relative_include_conf.inc. } unit ok_relative_include_1; {$I 'ok_relative_include_conf.inc'} {$I ok_relative_include_conf.inc} interface implementation end. pasdoc/tests/testcases/ok_generic.pas0000600000175000017500000000401613237143042020435 0ustar michalismichalis{ Tests of generics, both FPC and Delphi style. } unit ok_generic; interface { Units to include for Generics } uses Generics.Collections, FGL; type { FPC generics tests ------------------------------------------------------- } generic TMyList = class(TFPSList) private type PT = ^T; public function Blah: PT; end; { } TGeometryAttrib = class Name: string; AType: TGeometryAttribType; Offset: Integer; end; TGeometryAttribsList2 = specialize TMyList; { You can also specialize and make a descendant at the same time. } TGeometryAttribsList = class(specialize TMyList) public function Find(const Name: string): TGeometryAttrib; end; { Delphi generics tests ---------------------------------------------------- } { A simple Test-Object } TMyObject = class(TObject); TMyGenericList = class(TObjectList) public // To Something here end; TMyNewGeneric = class private type PT = ^T1; public function Blah: PT; end; { Sample for a generic with more than one type. TPair is a Key-Value-Relation } TAnotherGenericType = class(TDictionary); { All standard Generics: } TArray = class end; TEnumerator = class abstract end; TEnumerable = class abstract end; TList = class(TEnumerable) end; TQueue = class(TEnumerable) end; TStack = class(TEnumerable) end; TPair = record end; TDictionary = class(TEnumerable>) end; TObjectList = class(TList) end; TObjectQueue = class(TQueue) end; TObjectStack = class(TStack) end; TObjectDictionary = class(TDictionary) end; implementation uses Classes; procedure SampleProc(); var TestList: TMyGenericList; TestList2: TObjectList; // also allowed for vars begin TestList:=TMyGenericList.Create(); TestList2:=TObjectList.Create(); TestList.Free; TestList2.Free; end; end. pasdoc/tests/testcases/ok_attributes.pas0000600000175000017500000000113713237143042021210 0ustar michalismichalis{ Simple Delphi attributes test, from http://www.malcolmgroves.com/blog/?p=530 } unit ok_attributes; interface type TPerson = class private FName: String; FAge: Integer; public [NonEmptyString('Must provide a Name')] property Name : String read FName write FName; [MinimumInteger(18, 'Must be at least 18 years old')] [MaximumInteger(65, 'Must be no older than 65 years')] property Age : Integer read FAge write FAge; end; // Test that GUIDs are handled gracefully IUIContainer = interface ['{0F0BA87D-95C3-4520-B9F9-CDF30015FDB3}'] end; implementation end. pasdoc/tests/testcases/ok_paragraph_in_single_line_comment.pas0000600000175000017500000000067713237143042025557 0ustar michalismichalis// This is the 1st paragraph. // // This is the 2nd paragraph. // // This is the 3rd paragraph. // // pasdoc should create paragraphs when glueing single-line comments to // a description, but it doesn't for now. Update: now it does. unit ok_paragraph_in_single_line_comment; interface { This is the 1st paragraph. This is the 2nd paragraph. This is the 3rd paragraph. Here paragraphs are correct. } procedure Foo; implementation end.pasdoc/tests/testcases/ok_longcode_dash.pas0000600000175000017500000000031013237143042021603 0ustar michalismichalis{ See thread "Patch for Latex Longcode" on pasdoc-main mailing list on 2005-06-09. @longcode(# P2DRealPoint = ^T2DRealPoint; #) } unit ok_longcode_dash; interface implementation end.pasdoc/tests/testcases/ok_procedural_const.pas0000600000175000017500000000027613237143042022373 0ustar michalismichalisunit ok_procedural_const.pas; interface const FnTest1 = function(const Foo: Integer): Integer; cdecl = nil; FnTest2 = procedure(const Foo: Integer); stdcall = nil; implementation end.pasdoc/tests/testcases/ok_vorbisfile.pas0000600000175000017500000000612413237143042021167 0ustar michalismichalis{ This is a minimized version of vorbisfile.pas from http://vrmlengine.sourceforge.net/, just to test pasdoc2 macros/include file handling. } { API of vorbisfile library. Usually libvorbisfile.so under Unixes or vorbisfile.dll under Windows. This is just a quick translation of /usr/include/vorbis/vorbisfile.h header. } unit ok_vorbisfile; {$packrecords C} {$I ok_vorbisfile_conf.inc} interface uses CTypes, VorbisCodec, KambiOgg; const NOTOPEN = 0; PARTOPEN = 1; OPENED = 2; STREAMSET = 3; INITSET = 4; type TSizeT = LongWord; TVorbisFileReadFunc = function (ptr: Pointer; Size: TSizeT; nmemb: TSizeT; DataSource: Pointer): TSizeT; libvorbisfile_decl; TVorbisFileSeekFunc = function (DataSource: Pointer; offset: Int64; whence: CInt): CInt; libvorbisfile_decl; TVorbisFileCloseFunc = function (DataSource: Pointer): CInt; libvorbisfile_decl; TVorbisFileTellFunc = function (DataSource: Pointer): CLong; libvorbisfile_decl; Tov_callbacks = record read_func: TVorbisFileReadFunc; seek_func: TVorbisFileSeekFunc; close_func: TVorbisFileCloseFunc; tell_func: TVorbisFileTellFunc; end; Pov_callbacks = ^Tov_callbacks; TOggVorbis_File = record datasource: Pointer; {* Pointer to a FILE *, etc. *} seekable: Cint; offset: Int64; _end: Int64; oy: Togg_sync_state; links: Cint; offsets: PInt64; dataoffsets: PInt64; serialnos: PCLong; pcmlengths: PInt64; {* overloaded to maintain binary compatability; x2 size, stores both beginning and end values *} vi: Pvorbis_info; vc: Pvorbis_comment; {* Decoding working state local storage *} pcm_offset: Int64; ready_state: CInt; current_serialno: Clong; current_link: CInt; bittrack: double; samptrack: double; os: Togg_stream_state; {* take physical pages, weld into a logical stream of packets *} vd: Tvorbis_dsp_state; {* central working state for the packet->PCM decoder *} vb: Tvorbis_block; {* local working space for packet->PCM decode *} callbacks: Tov_callbacks; end; POggVorbis_File = ^TOggVorbis_File; var ov_clear: function (Vf: POggVorbis_File): CInt; libvorbisfile_decl; VorbisFileInited: boolean; implementation uses SysUtils, KambiUtils, KambiDynLib; var VorbisFileLibrary: TDynLib; initialization VorbisFileLibrary := {$ifdef UNIX} {$ifdef DARWIN} TDynLib.Load('libvorbisfile.3.dylib', false); if VorbisFileLibrary = nil then VorbisFileLibrary := TDynLib.Load('libvorbisfile.dylib', false); {$else} TDynLib.Load('libvorbisfile.so.3', false); if VorbisFileLibrary = nil then VorbisFileLibrary := TDynLib.Load('libvorbisfile.so', false); {$endif} {$endif} {$ifdef MSWINDOWS} TDynLib.Load('vorbisfile.dll', false); {$endif} VorbisFileInited := VorbisFileLibrary <> nil; if VorbisFileInited then begin Pointer(ov_clear) := VorbisFileLibrary.Symbol('ov_clear'); end; finalization VorbisFileInited := false; FreeAndNil(VorbisFileLibrary); end.pasdoc/tests/testcases/ok_lists.pas0000600000175000017500000000350313237143042020157 0ustar michalismichalis{ @abstract(Test of lists tags.) Normal lists: @orderedList( @item(One) @item(Two) @item(Three) ) @unorderedList( @item(One) @item(Two) @item(Three) ) Empty list is accceptable: @orderedList( ) @unorderedList( ) Whitespace inside lists is acceptable (and empty line that is not inside any @@item is @italic(not) a paragraph): @orderedList( @item One @item Two @item( Other tags inside the items are allowed, e.g. @link(ok_lists link to self), @true, @longcode(# begin X := Y; end; #), @bold(something bold), URLs: http://pasdoc.sf.net/, paragraphs: 2nd paragraph, dashes: em dash ---, en dash --, short one -, two consecutive short dashes @--. ) ) Nested lists are also freely allowed: @orderedList( @item( 1st nested unordered list: @unorderedList( @item(One) @item(Two) @item(Three) ) ) @item( 2nd nested unordered list: @unorderedList( @item(One) @item(Two) @item(Three) ) ) @item( And a couple of single-item ordered lists nested: @orderedList( @item( @orderedList( @item( )))) (Source code of this example begins to look like LISP :) ) ) Definition lists tests: @definitionList( @item 1st item @item 2nd item ) @definitionList( @itemLabel 1st item label @item 1st item @itemLabel 2nd item label @item 2nd item ) @definitionList( @itemLabel 1st item label @itemLabel 2nd item label ) Item spacing tests: @definitionList( @itemLabel 1st item label @item 1st item @itemLabel 2nd item label @item 2nd item @itemSpacing(Paragraph) @itemSpacing(Compact) ) @orderedList( @itemSpacing Compact @item One @item Two @item Three ) } unit ok_lists; interface implementation end.pasdoc/tests/testcases/ok_link_explicite_name.pas0000600000175000017500000000047213237143042023026 0ustar michalismichalisunit ok_link_explicite_name; interface type { I'm a testing class, oh ! And @link(MyMethod don't forget to look at my method !) } TTestingClass = class procedure MyMethod; end; { Some testing proc. @link TTestingClass.MyMethod Have you seen my method ? } procedure MyProc; implementation end.pasdoc/tests/testcases/ok_table_of_contents.txt0000600000175000017500000000077013034465544022561 0ustar michalismichalisFull table of contents: @tableOfContents Table of contents to level 0 (should be empty): @tableOfContents 0 Table of contents to level 1 (only top-level sections): @tableOfContents 1 Table of contents to level 2: @tableOfContents 2 Table of contents to level 3 (should be equivalent to full toc): @tableOfContents 3 @section(1 Sec1 Section 1) @section(1 Sec2 Section 2) @section(2 Sec21 Section 2.1) @section(2 Sec22 Section 2.2) @section(3 Sec221 Section 2.2.1) @section(1 Sec3 Section 3)pasdoc/tests/testcases/warning_back_comment_over_uses_clause.pas0000600000175000017500000000022513237143042026123 0ustar michalismichalisunit warning_back_comment_over_uses_clause; interface uses Unit2, Unit3; {< This comment shouldn't be assigned to anything. } implementation end.pasdoc/tests/testcases/ok_class_function.pas0000600000175000017500000000102513237143042022030 0ustar michalismichalis// Test for handling class functions in PasDoc unit ok_class_function; interface type // @abstract(This class is designed to see if PasDoc can // parse class functions correctly.) TDummy = class(TObject) public // Test To see if PasDoc can handle this. Class Function MyFunction: integer; // Test To see if PasDoc can handle this. class procedure MyProcedure; end; implementation { TDummy } class function TDummy.MyFunction: integer; begin end; class procedure TDummy.MyProcedure; begin end; end. pasdoc/tests/testcases/ok_include_1.txt0000600000175000017500000000012013034465544020721 0ustar michalismichalisBlah blah blah. This is file @code(ok_include_1.txt). @include(ok_include_2.txt)pasdoc/tests/testcases/ok_vorbisfile_conf.inc0000600000175000017500000000014313237143042022155 0ustar michalismichalis{ Yes, under both Linux and Windows we want cdecl. Tested. } {$define libvorbisfile_decl := cdecl} pasdoc/tests/testcases/ok_table_nonlatex.pas0000600000175000017500000000251513237143042022022 0ustar michalismichalis(* @abstract(Test of @@table-related features that do not work in LaTeX, only in HTML.) Test that everything within @@cell tag is OK: @table( @rowHead( @cell( Anything within a cell is OK, including lists: @orderedList( @item One @item Two @item Three ), paragraphs: This is new paragraph. Dashes: ---, --, -, @--. URLs: http://pasdoc.sourceforge.net/ And, last but not least, nested table: @table( @rowHead( @cell(1) @cell(2) ) @rowHead( @cell(3) @cell(4) ) ) ) @cell(B) ) @row( @cell(C) @cell(D) ) ) Now the same example table as before, but now nested table and other nicies are within a normal row, instead of heading row. @table( @rowHead( @cell(C) @cell(D) ) @row( @cell( Anything within a cell is OK, including lists: @orderedList( @item One @item Two @item Three ), paragraphs: This is new paragraph. Dashes: ---, --, -, @--. URLs: http://pasdoc.sourceforge.net/ And, last but not least, nested table: @table( @rowHead( @cell(1) @cell(2) ) @rowHead( @cell(3) @cell(4) ) ) ) @cell(B) ) ) *) unit ok_table_nonlatex; interface implementation end. pasdoc/tests/testcases/ok_back_comment_private.pas0000600000175000017500000000101113237143042023165 0ustar michalismichalis{ Testcase for [https://sourceforge.net/tracker/index.php?func=detail&aid=1596563&group_id=4213&atid=104213]. The comment "This should be ether omitted..." should not be included anywhere (if private members are omitted, and this is the default). } unit ok_back_comment_private; interface const ActionDescription = 'blah'; type EPingError = class(Exception) private FErrorType: TPingErrorType; //< This should be ether omitted or put for FErrorType: TPingErrorType; end; implementation end.pasdoc/tests/testcases/ok_sorting.pas0000600000175000017500000000107613237143042020511 0ustar michalismichalis{ Test unit to test various @--sort settings. } unit ok_sorting; interface uses ZZZ, AAA; type TMyClass = class ZZZField: Integer; AAAField: Integer; procedure ZZZMethod; procedure AAAMethod; property ZZZProp; property AAAProp; end; TMyRecord = record ZZZField: Integer; AAAField: Integer; end; ZZZClass = class end; AAAClass = class end; ZZZType = Integer; AAAType = Integer; const ZZZConst = 1; AAAConst = 2; var ZZZVar: Integer; AAAVar: Integer; procedure ZZZProc; procedure AAAProc; implementation end.pasdoc/tests/testcases/ok_static_member.pas0000600000175000017500000000071613237143042021642 0ustar michalismichalisunit StaticMember; interface type TMyClass = class // All methods are static unless they are virtual or dynamic. // but @name is declared static. Even if 'static' did not // appear after the declaration, @name would still be static. // @name is also a Class procedure but that is a separate story. Class Procedure StaticProcedure; static; end; implementation { TMyClass } class procedure TMyClass.StaticProcedure; begin end; end. pasdoc/tests/testcases/ok_excluded_unit.pas0000600000175000017500000000035313237143042021655 0ustar michalismichalis{ @exclude This is unit is not errorneous on itself. However, pasdoc should refuse (with proper error message) to generate documentation if only this unit is specified. } unit error_excluded_unit; interface implementation end.pasdoc/tests/testcases/ok_param_raises_returns_proctype.pas0000600000175000017500000000063513237143042025201 0ustar michalismichalisunit ok_param_raises_returns_proctype; interface type EFoo = class(Exception); { @param(A Description of param A) @raises(EFoo Description when EFoo is raised) } TMyProcedure = procedure(A: integer); { @param(A Description of param A) @returns(@true or @false) @raises(EFoo Description when EFoo is raised) } TMyMethod = function(A: integer): boolean of object; implementation end.pasdoc/tests/testcases/ok_include_intro_include.txt0000600000175000017500000000014213034465544023423 0ustar michalismichalis@section(1 Sec2 Second section in ok_include_intro_include.txt file) Second section dummy text. pasdoc/tests/testcases/todo/0000700000175000017500000000000013237143042016565 5ustar michalismichalispasdoc/tests/testcases/todo/ok_record_in_record.pas0000600000175000017500000000077513237143042023300 0ustar michalismichalis{ Bug: Parsing of this fails with Warning[2]: Error EPasDoc: todo/ok_record_in_record.pas(8): Unexpected keyword end. parsing unit ok_record_in_record.pas, continuing... Update 2005-05-28: now parsing is OK, but type of field InsideRecord is still not correctly displayed (there is just a word "record"). This is duplicated problem of test ok_record_descr.pas. } unit ok_record_in_record; interface var Foo: record InsideRecord: record Bar: Integer; end; end; implementation end.pasdoc/tests/testcases/todo/warning_no_params.pas0000600000175000017500000000113613237143042023001 0ustar michalismichalisunit warning_no_params; interface { Parens are missing here, generated docs will not be as expected. PasDoc should warn about this. @returns something } function Foo1(A: Integer): Integer; { Parens are missing here, generated docs will not be as expected. PasDoc should warn about this. @param A means something } function Foo2(A: Integer): Integer; type EFoo = class(Exception); { Parens are missing here, generated docs will not be as expected. PasDoc should warn about this. @raises EFoo when something is bad } function Foo3(A: Integer): Integer; implementation end.pasdoc/tests/testcases/todo/ok_record_descr.pas0000600000175000017500000000074513237143042022431 0ustar michalismichalis{ Bug: Docs for this unit generate ok, but there is no documentation what type TMyRecord fields have. Update 2005-05-28: now type of field B is displayed OK, but type of field A is still not correctly displayed (there is just a word "record", but there should be full record declaration, i.e. "record A: Integer; end;"). } unit ok_record_descr; interface type TMyRecord = record InsideRecord: record A: Integer; end; B: Integer; end; implementation end.pasdoc/tests/testcases/todo/ok_accidental_exclude.pas0000600000175000017500000000041313237143042023563 0ustar michalismichalisunit ok_accidental_exclude; interface { @@exclude. This test shows that simplistic testing for @@exclude tag in pasdoc is not good -- since it excludes this item from documentation, but it shouldn't. } procedure I_Dont_Wanna_Be_Excluded; implementation end.pasdoc/tests/testcases/todo/ok_comment_for_hidden_field.pas0000600000175000017500000000204313237143042024752 0ustar michalismichalis{ @abstract(This is test that comments "stick" to the items, even if the items are hidden because of @--visible-members value.) In the example below, note that @italic(MyField description) and @italic(MyField2 description) should @bold(not) be shown anywhere. In other words, @italic(MyField description) should not be accidentaly assigned to TBlah or TMyClass items. It should be assigned to MyField item --- and so, because MyField is private and thus hidden, @italic(MyField description) should also be hidden. As of 2005-12-25: This test doesn't pass. @italic(MyField2 description) is correctly just skipped, but @italic(MyField description) is incorrectly assigned to TBlah. } unit ok_comment_for_hidden_field; interface type TBlah = Integer; TMyClass = class private MyField: Integer; //< MyField description. public MyNextField: Integer; end; TBlah2 = Integer; TMyClass2 = class private // MyField2 description. MyField2: Integer; public MyNextField2: Integer; end; implementation pasdoc/tests/testcases/ok_longcode_float_hex.pas0000600000175000017500000000031013237143042022635 0ustar michalismichalis{ @abstract(Test of FormatFloat, FormatNumeric and FormatHex in TDocGenerator) @longcode(# begin X := 1.1; Y := 1; Z := $FF; end; #) } unit ok_longcode_float_hex; interface implementation end.pasdoc/tests/testcases/warning_link_in_seealso.pas0000600000175000017500000000035713237143042023217 0ustar michalismichalisunit warning_link_in_seealso; interface const { @Seealso(@link(rsSetValueOfEnclosedNodes))) This should cause a warning (but not a crash). } rsSetValueOfEnclosedElements = 'Set values of enclosed elements'; implementation end.pasdoc/tests/testcases/ok_image_picture.pdf0000600000175000017500000000531113034465544021634 0ustar michalismichalis%PDF-1.3 %쏢 5 0 obj <> stream x+T03T0A(˥d^U`jhgan77, ̍ LA)DK>W  Kendstream endobj 6 0 obj 68 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 9 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <>stream AdobedC  $, !$4.763.22:ASF:=N>22HbINVX]^]8EfmeZlS[]YC**Y;2;YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYG4" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|Wa Al%dp=*)Eʬm]wyK9Li]b7 sWe73Ha?#K7R/A}P^])քsYy$ǒ}1޳t9,UYT/nY \?h:M_w@;Jӵ6 Ӹ~]$}+2M"C4Y{2yZ]ޯ2 +')s"zllD/u 3h4XbHWqxmm#i`/|1zYY\Kq5oTA%iW}̅P9\5%ݼrZof–ž%y$7& w=V.Ҟ-c9k Ʒʋ$K&V륶ӭEFusI+D⿴I,n|3tg_7NsI4l<5ywuTU2' ԛjw7\ȲD ;if̌@ 8(!]=5琑OK)3&1WW-ANە9MY[AL{hgVFdVoOHHP( 5uDS3ɧ؎Brc5r+Af;ӥr^j(m"l)ce}ozbK. *ն^_7}4,I#_x7#FHޢ((ڈӤ6z ߯r/\mvD^\@*|g޵j/N }AXBMg'ͱ_W` endstream endobj 2 0 obj <>endobj xref 0 11 0000000000 65535 f 0000000383 00000 n 0000002211 00000 n 0000000324 00000 n 0000000171 00000 n 0000000015 00000 n 0000000153 00000 n 0000000431 00000 n 0000000531 00000 n 0000000472 00000 n 0000000501 00000 n trailer << /Size 11 /Root 1 0 R /Info 2 0 R /ID [(H\(!f^)(H\(!f^)] >> startxref 2418 %%EOF pasdoc/tests/testcases/ok_if_directive.pas0000600000175000017500000000327313237143042021461 0ustar michalismichalis{ @abstract(PasDoc fails to parse this, it seems that $if is not understood at all.) Bug spotted by Michalis on 2005-12-04 when trying `make htmldocs' on fpc compiler sources, in file globals.pas. Update 2005-12-05: $if is sorta handled now, and so is $ifend. This testcase is parsed now. There is still work remaining to be done with regards to $if and $elseif, this is documented on [https://github.com/pasdoc/pasdoc/wiki/ToDo]. } unit ok_if_directive; interface const {$if defined(CPUARM) and defined(FPUFPA)} MathQNaN : tdoublearray = (0,0,252,255,0,0,0,0); MathInf : tdoublearray = (0,0,240,127,0,0,0,0); MathNegInf : tdoublearray = (0,0,240,255,0,0,0,0); MathPi : tdoublearray = (251,33,9,64,24,45,68,84); {$else} {$ifdef FPC_LITTLE_ENDIAN} MathQNaN : tdoublearray = (0,0,0,0,0,0,252,255); MathInf : tdoublearray = (0,0,0,0,0,0,240,127); MathNegInf : tdoublearray = (0,0,0,0,0,0,240,255); MathPi : tdoublearray = (24,45,68,84,251,33,9,64); MathPiExtended : textendedarray = (53,194,104,33,162,218,15,201,0,64); {$else FPC_LITTLE_ENDIAN} MathQNaN : tdoublearray = (255,252,0,0,0,0,0,0); MathInf : tdoublearray = (127,240,0,0,0,0,0,0); MathNegInf : tdoublearray = (255,240,0,0,0,0,0,0); MathPi : tdoublearray = (64,9,33,251,84,68,45,24); MathPiExtended : textendedarray = (64,0,201,15,218,162,33,104,194,53); {$endif FPC_LITTLE_ENDIAN} {$endif} {$if defined(CPUARM) and defined(FPUFPA)} Included = 1; {$else} NotIncluded = 1; {$ifdef FPC_LITTLE_ENDIAN} NotIncluded = 1; {$else FPC_LITTLE_ENDIAN} NotIncluded = 1; {$endif FPC_LITTLE_ENDIAN} {$ifend} implementation end.pasdoc/tests/testcases/ok_interface_implicit.pas0000600000175000017500000000052513237143042022654 0ustar michalismichalisunit ok_interface_implicit; interface type IMyInterface = interface procedure PublicMethod; end; TMyRecord = record PublicField: Integer; end; TMyPackedRecord = packed record PublicField: Integer; end; TMyClass = class ImplicitField: Integer; public PublicField: Integer; end; implementation end.pasdoc/tests/testcases/ok_macros_off.pas0000600000175000017500000000060513237143042021137 0ustar michalismichalis{ @abstract(This is a test that macro support can be turned off in pasdoc.) With macro support turned on this unit would cause parsing error, because it would have brain-damaged declaration like @longcode(# procedure interface interface(a: Integer); #) } unit ok_macros_off; interface {$define FOO := interface interface} procedure FOO(a: Integer); implementation end.pasdoc/tests/testcases/ok_enum_field_var.pas0000600000175000017500000000054313237143042022001 0ustar michalismichalisunit ok_enum_field_var; interface type TServerConnController = class public AutoConnectAction: (acNone, acConnectOnDisconnect, acLoginOnDisconnect, acLoginOnConnect); end; var ApplicationStatus: (apInitializing, apReady, apClosing, apDestroying); implementation end.pasdoc/tests/testcases/ok_unit_uses_filename.pas0000600000175000017500000000025213237143042022675 0ustar michalismichalisunit ok_unit_uses_filename; interface uses ok_auto_abstract in './ok_auto_abstract.pas', Classes, ok_back_comment in 'ok_back_comment.pas'; implementation end. pasdoc/tests/testcases/warning_table.pas0000600000175000017500000000052513237143042021145 0ustar michalismichalis{ @abstract(Test of @@table-related warnings.) Various incorrect table tags nesting: @table( @cell(Foo) ) @table( @row(Foo) ) @row( @cell(Foo) ) @cell( @row(Foo) ) Table with no rows is not allowed: @table( ) Row with no cells is not allowed: @table( @row( ) ) } unit warning_table; interface implementation end.pasdoc/tests/testcases/ok_packed_class_object.pas0000600000175000017500000000025013237143042022757 0ustar michalismichalisunit ok_packed_class_object; interface type TMyPackedClass = packed class Blah: Integer; end; TMyPackedObject = packed object end; implementation end. pasdoc/tests/testcases/ok_enum_explicit_assign.pas0000600000175000017500000000024013237143042023225 0ustar michalismichalisunit ok_enum_explicit_assign; interface type TEnum1 = (e1One, e1Two = 12, e1Three, e1Four := 15); TEnum2 = (e2One := 3, e1Two := 4); implementation end.pasdoc/tests/Makefile0000600000175000017500000000021613237142276015273 0ustar michalismichalis.PHONY: clean clean: rm -Rf current_output/ \ correct_output/ \ scripts/check_cache_tmp/ \ scripts/upload_correct_tests_output_tmp/ pasdoc/old_docs/0000700000175000017500000000000013237143042014246 5ustar michalismichalispasdoc/old_docs/pasdoc.css0000600000175000017500000001057613237143042016244 0ustar michalismichalis /* start css.sty */ .cmr-10x-x-109{} .cmr-17{font-size:154%;} .cmr-12{font-size:109%;} .cmtt-10x-x-109{font-family: monospace;} .cmti-10x-x-109{ font-style: italic;} .cmsy-10x-x-109{} .cmbx-10x-x-109{ font-weight: bold;} .cmmi-10x-x-109{font-style: italic;} p.noindent { text-indent: 0em } p.nopar { text-indent: 0em; } p.indent{ text-indent: 1.5em } @media print {div.crosslinks {visibility:hidden;}} a img { border-top: 0; border-left: 0; border-right: 0; } center { margin-top:1em; margin-bottom:1em; } td center { margin-top:0em; margin-bottom:0em; } .Canvas { position:relative; } img.math{vertical-align:middle;} li p.indent { text-indent: 0em } .obeylines-h,.obeylines-v {white-space: nowrap; } div.obeylines-v p { margin-top:0; margin-bottom:0; } .overline{ text-decoration:overline; } .overline img{ border-top: 1px solid black; } td.displaylines {text-align:center; white-space:nowrap;} .centerline {text-align:center;} .rightline {text-align:right;} div.verbatim {font-family: monospace; white-space: nowrap; } span.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } table.minipage{width:100%;} div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;} div.center div {text-align: left;} div.flushright, div.flushright div.flushright {text-align: right;} div.flushright div {text-align: left;} div.flushleft {text-align: left;} .underline{ text-decoration:underline; } .underline img{ border-bottom: 1px solid black; margin-bottom:1pt; } .framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } .framebox-c {text-align:center;} .framebox-l {text-align:left;} .framebox-r {text-align:right;} span.thank-mark{ vertical-align: super } div.array {text-align:center;} div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em;} table.tabular td p{margin-top:0em;} div.td00{ margin-left:0pt; margin-right:0pt; } div.td01{ margin-left:0pt; margin-right:5pt; } div.td10{ margin-left:5pt; margin-right:0pt; } div.td11{ margin-left:5pt; margin-right:5pt; } td.td00{ padding-left:0pt; padding-right:0pt; } td.td01{ padding-left:0pt; padding-right:5pt; } td.td10{ padding-left:5pt; padding-right:0pt; } td.td11{ padding-left:5pt; padding-right:5pt; } .hline hr, .cline hr{ height : 1px; } .tabbing-right {text-align:right;} div.newtheorem { margin-bottom: 2em; margin-top: 2em;} span.TEX {letter-spacing: -0.125em; } span.TEX span.E{ position:relative;top:0.5ex;left:-0.0417em;} a span.TEX span.E {text-decoration: none; } span.LATEX span.A{ position:relative; top:-0.5ex; left:-0.4em; font-size:85%;} span.LATEX span.TEX{ position:relative; left: -0.4em; } .marginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;} .marginpar p{margin-top:0.4em; margin-bottom:0.4em;} div.float img, div.float .caption {text-align:center;} div.figure img, div.figure .caption {text-align:center;} .equation td{text-align:center; } td.equation { margin-top:1em; margin-bottom:1em; } td.eqnarray4 { width:5%; white-space: normal; } td.eqnarray2 { width:5%; } table.eqnarray-star, table.eqnarray {width:100%;} div.eqnarray{text-align:center;} div.pmatrix {text-align:center;} span.pmatrix img{vertical-align:middle;} div.pmatrix {text-align:center;} img.cdots{vertical-align:middle;} .partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;} .caption td.id{font-weight: bold; white-space: nowrap; } table.caption {text-align:center;} h1.partHead{text-align: center} p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } .paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;} .subparagraphHead, .likesubparagraphHead { font-weight: bold;} .quote {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; } .verse{white-space:nowrap; margin-left:2em} div.maketitle {text-align:center;} h2.titleHead{text-align:center;} div.maketitle{ margin-bottom: 2em; } div.author, div.date {text-align:center;} div.thanks{text-align:left; margin-left:10%; font-size:80%; font-style:italic; } div.author{white-space: nowrap;} .quotation {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; } .abstract p {margin-left:5%; margin-right:5%;} /* end css.sty */ pasdoc/old_docs/README.txt0000600000175000017500000000013013034465544015751 0ustar michalismichalisLatest documentation of pasdoc is available online on [http://pasdoc.sourceforge.net/]. pasdoc/old_docs/pasdoc.html0000600000175000017500000017435413034465544016436 0ustar michalismichalis Manual for pasdoc 0.8

Manual for pasdoc 0.8

Marco Schmidt & Carl Eric Codère & Johannes Berg

April 19, 2004

Contents

1 Introduction
2 Directives
3 Adding descriptions
4 Formatting your comments
 4.1 @
 4.2 abstract
 4.3 author
 4.4 classname, inherited, name
 4.5 code
 4.6 created
 4.7 cvs
 4.8 exclude
 4.9 false
 4.10 html
 4.11 lastmod
 4.12 link
 4.13 longcode
 4.14 nil
 4.15 param
 4.16 raises
 4.17 return, returns
 4.18 true
5 Switches
 5.1 Documentation file format
  5.1.1 HTML
  5.1.2 htmlhelp
  5.1.3 LATEX
  5.1.4 LaTeX2rtf
 5.2 Format-specific switches
  5.2.1 No generator information
  5.2.2 Specify name of document
  5.2.3 Specify footers and headers to use
 5.3 Comment Marker switches
 5.4 Output language switches
 5.5 Other switches
  5.5.1 Include / Exclude class Members by visiblity
  5.5.2 Output directory
  5.5.3 Read file names from file
  5.5.4 Change verbosity level
  5.5.5 Show help
  5.5.6 Specify a directive
  5.5.7 Specify an include file path
  5.5.8 Specify directive file
  5.5.9 Set title of document
  5.5.10 Include uses list
  5.5.11 Full link output
  5.5.12 Non documented switches
6 Known problems
 6.1 Documentation of program files
 6.2 Records
 6.3 Non-unique identifiers
7 Adding support for another output format
8 Credits

1 Introduction

Pasdoc creates documentation for Pascal unit files.

Descriptions for variables, constants, types (called ’items’ from now on) are taken from comments stored in the interface sections of unit source code files, each comment must be placed directly before the item’s declaration.

This way, you as a programmer can easily generate reference manuals of your libraries without having to deal with the details of document formats like HTML or LATEX.

Moreover, you can edit the source code and its descriptions in one place, no need to add or modify explanations in other files. The rest is done automatically, you should write a script / batch file that does the actual call to pasdoc... Download the latest version from
http://pasdoc.sourceforge.net.

For an example of source code that can be used with pasdoc, try the pasdoc sources themselves - type pasdoc[.exe] --format html *.pas to generate HTML documentation.

You can compile pasdoc with Free Pascal (version 1.0 or higher), as well as with Delphi and Kylix.

2 Directives

As you may know, Pascal allows for directives in the source code. These are comments that contain commands for the compiler introduced by the dollar sign.

To distinguish different compilers, libraries or development stages, conditional directives make it possible to make the compiler ignore part of the file. An example:
  unit SampleUnit;  
 
  {$ifdef WIN32}  
  uses Windows, WinProcs;  
  procedure WindowMove(H: TWindowHandle; DX, DY: Integer);  
  procedure WindowPrintText(H: TWindowHandle; X, Y: Integer; S: String);  
  {$else}  
  procedure ClearConsole;  
  procedure PrintText(S: String);  
  {$endif}  
 
  {$define DEBUG}  
  {$undef OPTIMIZE}

The ifdef part checks if a conditional directive called WIN32 is currently defined (that would be the case for Delphi or FPC/Win32). If this is true, all code until else or endif are compiled, everything between else and endif is ignored. The contrary would apply if the directive is not defined, e.g. under FPC/DOS or Borland Pascal. These statements can also be nested. Using define and undef, a programmer can add and delete directives, in the above example DEBUG and OPTIMIZE.

As pasdoc loads Pascal files in a similar way a compiler does, it must be able to regard conditional directives. All define and undef parts are evaluated by pasdoc, modifying an internal list of directives as source code is parsed.

Different from a real compiler, pasdoc starts with an empty list of conditional directives. To get back to the above example, if you want to write documentation for the WIN32 code part, you must explicitly tell pasdoc that you want this directive defined.

You can do so using the Specify directive or Add directives from file switch (see sections 5.5.6 and 5.5.8).

Next to those directives already presented, pasdoc also supports include files:
type TInteger = Integer;  
 
{$I numbers.inc}  
 
const MAX_FILES = 12;

In the above code, pasdoc would parse TInteger, get the include directive and start parsing the include file numbers.inc. This file could contain other directives, types or whatever. It is treated as it would be treated by any Pascal compiler.

Pascal compilers also know switch directives. These are boolean options, either on or off. They can be checked similar to conditional directives with the $ifopt directive. Pasdoc does not yet fully support these, but at least does not give up when it encounters one.

3 Adding descriptions

You can provide documentation for

Providing a description for the different items is fairly easy. You simply need to provide a comment containing the description before the name of the item itself.

For units, the comment declaration must be done before the unit keyword. Example:
type  
  { This record type stores all information on a customer, including  
    name, age and gender. }  
  TCustomer = record  
    Name: String;  
    Age: Byte;  
    Gender: Boolean;  
  end;  
 
{ Initializes a TCustomer record with the given parameters. }  
procedure InitCustomer(Name: String; Age: Byte;  
  Gender: Boolean; var Customer: TCustomer);

It is possible to specify that items will only be documented when certain comment markers are present at the start of the comment. Please refer to 5.3 for further information. Furthermore, undocumented items may or may not appear in the final document, depending on the output format.

An interesting feature of pasdoc is its ability to link items from within comments. If you are currently writing about an array of integers TIntArray you’ve declared as a type, you might mention that the number of values it can store is specified in the constant MAX_INTS. You’ve probably already documented this constant when you declared it earlier in the same or another unit. Now, if you write @link(MAX_INTS) instead of simply MAX_INTS, pasdoc knows that you are referring to another item it has found or will find in the list of units you gave to it. After all input files have been parsed, pasdoc will start substituting all occurrences of @link(something) with ”real” links. Depending on the type of output, these links could be hyperlinks (in HTML) or page references (in LATEX). If the current output format is HTML, the description of TIntArray would contain a link to MAX_INTS. Viewing TIntArray’s description in your favourite web browser you’d now be able to click on MAX_INTS and the browser would jump to the definition of MAX_INTS, where you’d find more information on it.

If pasdoc cannot resolve a link (for whatever reasons), it will issue a warning to standard output and will write the content of @link() to the documentation file, not as a link, but in a special font.

4 Formatting your comments

All comments recognize special directives that are used for different purposes. Each of these special directives starts with the at character @, followed by and identifier and optinally followed by text between parentheses.

As an example, lets take the well-known DOS unit. Its top part could look like this:
{  
@abstract(provides access to file and directory operations)  
@author(John Doe <doe@john-doe.com>)  
@created(July 12, 1997)  
@lastmod(June 20, 1999)  
The DOS unit provides functionality to get information on files and  
directories and to modify some of this information.  
This includes disk space (e.g. @link(DiskFree)), access rights, file  
and directory lists, changing the current directory, deleting files  
and directories and creating directories.  
Some of the functions are not available on all operating systems.  
}  
unit DOS;

Pasdoc would read this comment and store it with the unit information. After all Pascal source code files you gave to pasdoc have been read, pasdoc will try to process all tags, i.e., all words introduced by a @ character.

If you want to use the character @ itself, you must write it twice so that pasdoc knows you don’t want to specify a tag.

Note in the example above that the character does not need this special treatment within the parentheses, as shown in the author tag at the example of the email address.

Following is a list of all tags that you may use in pasdoc. A tag like @link must always be followed by an opening and then a closing parenthesis, even if you add nothing between them.

The following tags are supported:

@@
represents the @ character
@abstract
This is an abstract of the description (nowadays called ”management summary”)
@author
Treat the argument as an author’s name and email address
@classname
PasDoc inserts the class name here.
@code
Treat argument as code example
@created
Creation date of item
@cvs
The argument is related to source versioning with e.g. cvs
@exclude
The current item is to be excluded from documentation
@false
PasDoc inserts the specially formatted text ’false’ here.
@html
Inserts html code in the output
@inherited
PasDoc inserts the name of the ancestor class here.
@lastmod
last modified date of item
@link
The argument is the name of another entity, PasDoc will add a link to it here.
@longcode
Format the text and output it in fixed width font, with correct formatting.
@name
PasDoc inserts the name of the item (class, object, function, variable...) here
@nil
PasDoc inserts the specially formatted text ’nil’ here.
@param
Treat first argument as parameter name and all following arguments as the description
@raises
Treat first argument as exception name and all following arguments as the description
@return, @returns
Description of a function’s return value
@true
PasDoc inserts the specially formatted text ’true’ here.

4.1 @

Represents the @ character, for example if you want to use one of the tags literally

4.2 abstract

For some item types like classes or units you may write very large descriptions to give an adequate introduction. However, these large texts are not appropriate in an overview list. Use the abstract tag to give a short explanation of what an item is about. One row of text is a good rule of thumb. Of course, there should only be one abstract tag per description.

The abstract text will appear in the overview section of the documentation (if the document format supports this overview section), and will also appear as the first paragraph of the item full documentation.

4.3 author

For each author who participated in writing an item, one author tag should be added. The format of the author tag should conform to the following specification : @author(Name <URI>)

Author tags will only result in documentation output for classes, interfaces, objects and units.

Example:
@author(Johannes Berg <email@address.here>)

4.4 classname, inherited, name

PasDoc uses the tags @inherited, @classname and @name as placeholders for the names of the ancestor class, current class and name of the current item respectively.

Example:
 
{ @name is a method of @classname which overrides the method of  
  @inherited to do something completely different...}

4.5 code

PasDoc uses the tag @code to mark example code which is preformatted and should not be changed in the output. It will usually appear in a teletype font in the final documentation.

Example:
{: how to declare a variable.  
Example:  
@code(  
var  
  SomeVariable: SomeType;)  
}

4.6 created

This tag should contain the date the item was created. At most one created tag should be in a description. Created tags will only result in documentation output for classes, interfaces, objects and units. There is no special format that must be followed.

4.7 cvs

This tag is used to extract the last modification date and authors of the item. The parameter of this tag should conform to the Author : ccodere or Date : 2004/04/2002 : 01 : 52 string of cvs or rcs.
@cvs($Date$)

4.8 exclude

If an exclude tag is found in a description, the item will not appear in the documentation. As a logical consequence, no information except the exclude tag itself should be written to the description. Whenever high-level items like units or classes are excluded from the documentation process, all items contained in them will not appear as well, e.g. constants or functions in an excluded unit or methods and fields in an excluded class.

The following example will produce no documentation, as the entire unit will be excluded from the documentation process.

Example:
{@exclude }  
unit myunit;  
 
interface  
 
procedure hello;  
 
implementation  
 
procedure hello;  
begin  
 WriteLn('Hello');  
end;  
 
end.

4.9 false

PasDoc inserts the specially formatted text ’false’ here at the location of the tag. This tag does not have any parameters.

4.10 html

Pasdoc directly outputs the text that is between parentheses, without any conversion for the html output format. For other formats, the text is converted to standard text.

There is no syntax checking on the validity of the HTML syntax.

If there are no parentheses, @HTML is directly written to the output documentation.

4.11 lastmod

This tag should contain the date the item was last modified. At most one created tag should be in a description. Lastmod tags will only result in documentation output for classes, interfaces, objects and units. There is no special format that must be followed.

4.12 link

Use this tag to make your documentation more convenient to the reader. Whenever you mention another item in the description of an item, enclose the name of the mentioned item in a link tag, e.g.
@link(GetName).
This will result in a hyperlink in HTML and a page reference in LATEX.

4.13 longcode

Use this tag to output code, and pre-formatted text. The output text will closely ressemble the text typed, and will be represented in a fixed width font. In the case of pascal code typed within this tag, it will be pretty-printed first.

To be able to put special characters in this tag, the tag should be followed by a # and finished with a # before the closing parentheses.

Example:
      @longCode(#  
procedure TForm1.FormCreate(Sender: TObject);  
var  
  i: integer;  
begin  
  // Note that your comments are formatted.  
  {$H+} // You can even include compiler directives.  
  // reserved words are formatted in bold.  
  for i := 1 to 10 do  
  begin  
    It is OK to include pseudo-code like this line.  
    // It will be formatted as if it were meaningful pascal code.  
  end;  
end;  
      #)

4.14 nil

PasDoc inserts the specially formatted text ’nil’ here. This tag does not have any parameters.

4.15 param

Treats first argument as parameter name and all following text as the description of this parameter.

Example:
{ A small description  
  @param(Filepath The file to open)  
}  
constructor Init(FilePath : String);

4.16 raises

Treats the first argument as exception name and all following text as the description for this exception.

Example:
{ A small description  
  @raises(EMyException Raises this exception)  
}  
constructor Init;

4.17 return, returns

Treat the text in the argument as the description of the returns value of this function or method.

4.18 true

PasDoc inserts the specially formatted text ’true’ here at the location of the tag. This tag does not have any parameters.

5 Switches

This is a list of all switches (program parameters) supported by pasdoc. Enter pasdoc --help at the command line to get this list. Make sure you keep the exact spelling of the switches, pasdoc is case-sensitive. Most switches exist in two variations, a short one with a single dash and a longer one with two dashes. You can use either switch to get the same effect.

5.1 Documentation file format

After loading all Pascal source code files, pasdoc will write one or more output files, depending on the output file format. Choose the output format according to your needs - you might want to create several versions for

5.1.1 HTML

-O html
--format html

This switch makes pasdoc write HTML (Hypertext Markup Language) output. HTML files are usually displayed in a web browser, which available on all modern computer systems.

It is the default output file format. Several files will be created for this output type, one for each unit, class, interface and object, additionally some overview files with lists of all constants, types etc.

This is the preferred output for online viewing.

It is to note that even undocumented items will appear in the final output file format.

5.1.2 htmlhelp

-O htmlhelp
--format htmlhelp

This switch makes pasdoc write HTML (Hypertext Markup Language) output. It also writes additional files that can be used to create Microsoft htmlhelp files. Please consult the htmlhelp Microsoft SDK for more information.

5.1.3 LATEX

-O latex
--format latex

This switch makes pasdoc write output that can be interpreted using LATEX. This is the preferred output format for printing the documentation.

A single output file, either having the name specified with the -N switch, or the default name docs.tex will be created.

With latex you will be able to create a dvi file that can then be converted to a Postscript file using dvips. Or you can also directly generate a huge HTML file by using htlatex, or a PDF file by using pdflatex.

It is to note that the output generated by pasdoc has been optimized for pdflatex and htlatex.

It is to note that only documented items will appear in the final output file format.

5.1.4 LaTeX2rtf

-O latex2rtf
--format latex2rtf

This switch makes pasdoc write output that can be interpreted using latex2rtf. This is the preferred output format for adding the documentation to word processor documentation.

A single output file, either having the name specified with the -N switch, or the default name docs.tex will be created. This file can then be converted to rtf by using latex2rtf.

This output will only work with the latex2rtf tool. Using other tools might not produce the expected results.

It is to note that only documented items will appear in the final output file format.

5.2 Format-specific switches

The following switches can only be used with one output file format and are useless for the others.

5.2.1 No generator information

-X
--exclude-generator

By default, pasdoc includes some information on itself and the document creation time at the bottom of each generated HTML file. This switch keeps pasdoc from adding that information.

5.2.2 Specify name of document

-N NAME --name NAME

When the output format of the documentation is not HTML (such as latex, or CHM), this specifies the name of the final name of the documentation. If this is not specified, it uses the defaultdocs filename.

5.2.3 Specify footers and headers to use

-F FILNAME --footer FILENAME -H FILNAME --header FILENAME

You can specify texts files which PasDoc should use as header or footer for all generated html pages. This option is only available for the html output format.

Example:
pasdoc --header myheader.txt --footer myfooter.txt

5.3 Comment Marker switches

It is possible for pasdoc to ignore comments that do not start with the correct start markers. By default, all comments are treated as item descriptions. This can be changed using the following switches:

--staronly
Parse only {**, (*** and //** style comments
--marker
Parse only {<marker>, (*marker and //marker comments. Overrides the staronly option, which is a shortcut for ’-marker=**’
--marker-optional
Do not require the markers given in -marker but remove them from the comment if they exist.

5.4 Output language switches

-L lg
--language lg

You can specify the language that will be used for words in the output like Methods or Classes, interfaces and objects. Your choice will not influence the status messages printed by pasdoc to standard output - they will always be in English. Note that you can choose at most one language switch - if you specify none, the default language English will be used.

The lg parameter can take one of the following values:

ba
Bosnian (Codepage 1250)
br
Portugese / Brazilian
ct
Catalan
dk
Danish
en
English
fr
French
de
German
id
Indonesian
it
Italian
jv
Javanese
pl
Polish
ru.1251
Russian (Codepage 1251)
ru.866
Russian (Codepage 866)
ru.KOI8
Russian (KOI-8
sk
Slovak
es
Spanish
se
Swedish

5.5 Other switches

5.5.1 Include / Exclude class Members by visiblity

-M
--visible-members

By default all non-private fields, methods properties are included in the documentation. This switch permits to change which items of the specified visibility will be documented.

The possible arguments, separated by a comma are:

private
protected
public
published
automated

In the following example only the private and protected members will be documented, all others will be ignored.
pasdoc --visible-members private,protected

5.5.2 Output directory

-E DIRECTORY
--output DIRECTORY

By default, pasdoc writes the output file(s) to the current directory. This switch defines a new output directory - this makes sense especially when you have many units and classes, they should get a subdirectory of their own, e.g. htmloutput.

5.5.3 Read file names from file

-S FILE
--source FILE

If you want pasdoc to write documentation for a large project involving many unit source code files, you can use this switch to load the file names from a text file. Pasdoc expects this file to have one file name in each row, no additional cleaning is done, so be careful not to include spaces or other whitespace like tabs.

5.5.4 Change verbosity level

-v LEVEL
--verbosity LEVEL

Using this switch in combination with an integer number > 0 lets you define the amount of information pasdoc writes to standard output. The default level is 2, this switch is optional. A level of 0 will result in no output at all.

5.5.5 Show help

-?
--help

This switch makes pasdoc print usage hints and supported switches to standard output (usually the console) and terminates.

5.5.6 Specify a directive

-D DIRECTIVE
--define DIRECTIVE

Adds DIRECTIVE to the list of conditional directives that are present whenever parsing a unit is started.

The list of directives will be adjusted whenever a directive like WIN32 or FPC is defined or undefined in the source code. Each define should be separated by the others by a comma, as shown in the following example:
pasdoc --define debug,hello,world

5.5.7 Specify an include file path

-I DIR
--include DIR

Adds DIR to the list of directories where pasdoc will search for include files. Whenever an include file directive is encountered in the source code, pasdoc first tries to open that include file by the name found in that directive. This will work in all cases where the current directory contains that include file or when the file name contains a valid absolute or relative path.

It is possible to use this switch more than once on the command line.
pasdoc --include c:\mysources\include --include c:\3rdparty\somelib\include

5.5.8 Specify directive file

-d DIRECTORY
--conditionals DIRECTORY

Adds the defines specified in a file DIRECTORY to the list of conditional directives that are present whenever parsing a unit is started.

The list of directives will be adjusted whenever a directive like WIN32 or FPC is defined or undefined in the source code. There should be one defibe per line in the conditional file.
pasdoc --conditionals /home/me/pascal/myconditionals

5.5.9 Set title of document

-T "STRING"
--title "STRING"

This option sets the title of the output document. The characters in the title should be enclosed in double quotes.

By default, depending on the documentation format, the document contains either no title, or the name of the unit being documented.

Example:
pasdoc -T "This is my document title"

5.5.10 Include uses list

--write-uses-list

PasDoc can optionally include the list of units in a unit’s uses clause to that unit’s description.

Example:
pasdoc --write-uses-list

If a unit in the uses list is part of the documentation, it will be clickable in the output.

By default this option is disabled.

5.5.11 Full link output

--full-link

This option controls the behaviour of ”@link(unit.procedure)” type links. If it is set, the output generated will look like this:

unit.procedure with the ”unit” part linking to the unit and the ”procedure” part linking to the procedure inside the unit. If it is unset, then the output will only be procedure.

5.5.12 Non documented switches

This lists the other unusual switches that are recognized by pasdoc:

-R, --description
read description from this file
-C, --content
Read Contents for HtmlHelp from file
--numericfilenames
Causes the html generator to create numeric filenames
--graphviz-uses
write a GVUses.gviz file that can be used for the dot program from GraphViz to generate a unit dependency graph.
--graphviz-classes
write a GVClasses.gviz file that can be used for the dot program from GraphViz to generate a class hierarchy graph.
--abbreviations
abbreviation file, format is ”[name] value”, value is trimmed, lines that do not start with ’[’ (or whitespace before that) are ignored
--aspell
enable aspell, giving language as parameter, currently only done in HTML output
--ignore-words
When spell-checking, ignore the words in that file. The file should contain one word on every line, no comments allowed
--cache-dir
Cache directory for parsed files (default not set)

6 Known problems

6.1 Documentation of program files

As was said before, only units are regarded by pasdoc. In an OOP environment for which pasdoc was written, an application is usually a class overriding an abstract application class, so all code that is ever needed in the program file looks like this:
program main;  
 
uses myapp;  
 
var App: TMyApplication;  
 
begin  
  App := TMyApplication.Create;  
  App.Run;  
  App.Destroy;  
end.

So there isn’t much to do for documentation. If you’re not using OOP, you could at least try to move as much code as possible out of the main program to make things work with pasdoc.

6.2 Records

Pasdoc cannot create separate documentation for members of a record. In object-oriented programs, records will not appear most of the time because all encapsulated data will be part of a class or object. However, you can give a single explanation on a record type which could contain a description of all members.

6.3 Non-unique identifiers

In some larger projects, identifiers may be used in different contexts, e.g. as the name for a parameter and as a function name. Pasdoc will not be able to tell these contexts apart and as a result, will create in the above-mentioned example links (at least in HTML) from the argument name of a function to the type of the same name.

7 Adding support for another output format

If you want to write a different type of document than those supported, you can create another unit with a new object type that overrides TDocGenerator from unit PasDoc_Gen.pas. You’ll have to override several of its methods to implement a new output format. As examples, you can always look at how the HTML and LATEXgenerators work. First of all, you must decide whether your new output format will store the documentation in one (like LATEX) or multiple files (like HTML).

8 Credits

Thanks to Michael van Canneyt, Marco van de Voort, Dan Damian, Philippe Jean Dit Bailleul, Jeff Wormsley, Johann Glaser, Gudrun Plato, Erwin Scheuch-Hellig, Iván Montes Velencoso, Mike Ravkin, Jean-Pierre Vial, Jon Korty, Martin Krumpolec, André Jager, Samuel Liddicott, Michael Hess, Ivan Tarapcik, Marc Weustink, Pascal Berger, Rolf Offermanns and Rodrigo Urubatan Ferreira Jardim for contributing ideas, bug reports and fixes, help and code! pasdoc/old_docs/pasdoc.pdf0000600000175000017500000045473413034465544016246 0ustar michalismichalis%PDF-1.4 3 0 obj << /Length 241 /Filter /FlateDecode >> stream x=Ao &VݡNm%iK*y流Wlz t; q,gE^ƛ&yV(T{C(Edu#5Ъ^ Bpk@h`OH=ӆ4<1/cMΡ^D6Fi,s{ZyEߏW5֋,X׮iυ!.unG9!萏2uZURendstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 595.276 841.89] /Parent 13 0 R >> endobj 1 0 obj << /Font << /F16 6 0 R /F17 9 0 R /F15 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 16 0 obj << /Length 1044 /Filter /FlateDecode >> stream xYM6Q*ߤnM,"i!@҃"Z2d)i}g8{ǺXEgᯋoM*2bp [2^pMxfiܿt8d/.(YX U(]KK?A(NGtTeg@gg'D:D77KgHp~-,/?5LjASZ7#ªB,p9?'DH7ȰRs#~3ɉ X1]XX& "pm!DAG`S` > endobj 14 0 obj << /Font << /F27 19 0 R /F28 22 0 R /F15 12 0 R /F18 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 28 0 obj << /Length 795 /Filter /FlateDecode >> stream x՗[s0)x PZu3o lNe^Z|)I~ߗ I8åNpY埘@v_0baȺ[gnsXw=I2>/7P~p㡯d".%{]eyFlqsV]G-izo4N]Ǎ5O2]^_fKj"S{x[8O'oM|=|07͑MGlg k |i- p)V (-u$WdRa1]`P~QzQYȏXOj-aK*o"'s}QqCaLCiޝfi%Μ=ZYjDVǸrN;=Dž80@zӓSBVo,k=lڕ =d([KyeYD//܌W0ڡ IT=}AZuaX"UPRRf^ >s?],*Cfi} {׉7 q'Z@Rendstream endobj 27 0 obj << /Type /Page /Contents 28 0 R /Resources 26 0 R /MediaBox [0 0 595.276 841.89] /Parent 13 0 R >> endobj 26 0 obj << /Font << /F15 12 0 R /F28 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 31 0 obj << /Length 1866 /Filter /FlateDecode >> stream xڍXKF WP rkv$mRh{ƶPY2$y HdzۜpH9~u'z3 _l~du!ѽ : Κ $o~${|g3T"ov"@2sM5 Lj"Xp>̜K?WEiu0 :3+"v媌g:ک$􅰱 ɠ#ZPi~ S׶:Csmid'lg: }+?%7 -I.bS.lDYCF)ǪF%!lvc a\cwE;wT)-*8yX_Hya ؽ;/I;Nb 瞕LDԆpPhDpntzw58S];JQh=]sAL&mF(K8Ga1̚/qvF 0|X>{!m5DD ٍlSr/9WZSdaP;aBxuuLWF&P!޷ ihwt'DTN SeYْ|)S_qP%?Nźrtx{:N"$_f" <81ق,Al. EK85=ߊѲS SgS:Ey eůJ;c7K7uL 9 drjSא4aVHR 7 {ٳw^>i):!+y\1e0@VB*4;G&1,ӯK,U/N"=?۾n-X!ڶNpN _R{9Sw^AI̾eB?jXDeKx?J>rs֯\E+?eDM)FX{K}9M)1½rTM~{SW_]HmL߷xPB~C5XWB]_\onmHjMn?uNeQ}ʂغ_߶jkhnp-ijL0A%|~\?&endstream endobj 30 0 obj << /Type /Page /Contents 31 0 R /Resources 29 0 R /MediaBox [0 0 595.276 841.89] /Parent 13 0 R >> endobj 29 0 obj << /Font << /F27 19 0 R /F15 12 0 R /F18 25 0 R /F31 34 0 R /F32 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 40 0 obj << /Length 2151 /Filter /FlateDecode >> stream xڍXK6WЃ Q^ zHp6"}ZZ,܍Qw^bhșf_m=B~dnt⇑^iGYzQ]Y* #W?~ͷ`RڏL&bY/oH[|UQ`޲,(]PܡkeZq1o뗫0v#x;^.RM]bٗM ϼEdm/Te僼l1w@ڸ|\[MQr wkmՙA&N.o2;[ߛ-~GM= VWq'&^[Tw4K3kZ~VGKr}Z+"ozv,B!@%ʰGOfGW366+`}!x*K[uva<+AC]7 )[9y9l Kp V?BPA0s@L'S}֕ց(]4hCݴ) JK _ htGV%/n)#ek#;KwyPCan 6m02?30;a00 ~獬j o2 Y&υnwc}Am^_rGuf@ ItǟË܁:]):#ByhÁ2!(dPˠEuF8F)k =Ek(5TTTM45y`tHt2%1H=D4cOel˯&/H*AlŜ$Y -P&sD\|0 Ԥg!o T\.JjrJB*YཬюRrw3ȵv&SGg Rk NFa&vPB /q OjCZYR5;`-Cn&uk#q75힔.re?9'e$ NB!PAN!Hqt8 Ri>\QCՐ=;(܃M7 J n9V:x#rB!17c:e_hK?q){N}c ЉY3a@McOc8t'j4#VKr)3$R{yuTq<%-#?ЎD]؝M /;~Gb79B ׺KsHÕK"I>">bi{|F~VW,! 2nP3ulsI*uU;a82qMKSV'i/9w_dp0N\7뺷Hp?d텫(aU2po·3s%o߽0C/fLu]|Bؒk抎szp݃ᶛ-iA$I0 0S^nd0J" _ޫ# ,lO"%&Hẏ &:qU8# ?cn@o:.˻mr3 玹Цc˛~!p# o%? .e.Y< F?C>BAA.Jc fQޱk|7BUtfX̀[HkfeeۛU9D <:-)Q过^{,-hn I B5IHtRڱ(tXټS6GbPj.u:ݖx !xS.D+ Nq> endobj 38 0 obj << /Font << /F31 34 0 R /F15 12 0 R /F32 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 43 0 obj << /Length 1613 /Filter /FlateDecode >> stream xڭXK6WVI^ zI-h[<(Y@{YppV/ڗzwXAi=em|'MulE,\YGs|ݽ׾^<6 no=Tŋs7A<\^^oS-&0?rE$Abz> VvM/g;mjY/L=n* FYJ  Zmr& &?u>+B-{Ӱ$`Tf:UǦ w SH1n"Ak]$$.BD6kiE`qQcYc.,hѝ4_@[ (%rdK ӚNC c&kl鸛>Vj֔ge"71|ʔ,΁0MP1$:(A`^0ta~d[4.]Q+M[kkKrInJ1l!GίhjoGLڽ;"S[I95;m0HjōNa̪|8.{ ĹOerC9CqRUAĞM`zhF yT1AnfeO\h*%*[EA`bҹ]p \d}3.4<6MWѿi  ɂ;4Sx /vaaw_uwM. ෵Y~IEȆsX/p:\S- iJs< @?΃:nX$9bIaZJ"s^+3r\0zHK9ښT3%Z.&S I/ ::17Yݭ0LY q7!0+W>[_#=Ou *VV> endobj 41 0 obj << /Font << /F27 19 0 R /F15 12 0 R /F30 46 0 R /F31 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 49 0 obj << /Length 2548 /Filter /FlateDecode >> stream xڭY[~ׯ Xg8E l64"@YH=^Vܭ\Μ9s~[zµ"z_+?qc .˛֏lUez'^_䛭Nc?F$zpz=jsI UuJXhϴqW֓[ 3,4-zea-[E҃wRl{7( ɳgAx\Ʈ7endstream endobj 48 0 obj << /Type /Page /Contents 49 0 R /Resources 47 0 R /MediaBox [0 0 595.276 841.89] /Parent 50 0 R >> endobj 47 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F18 25 0 R /F27 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 53 0 obj << /Length 1741 /Filter /FlateDecode >> stream xڥXnFW=dsi 099ɡMQc.HA."[z~K@A;X,JvY0ww6ҡ3 l3籒z^`Ĕmjӗ(\O. y `t|mQT5p# y2ETX\\0E{4an\ $!'3a[(sE$ݍgB垌9"Jڕg,4 *!'ī;|Ƴ`{A,l'S$'D%֠ ,-qӔb<,iѮ]EzJjӈٯCelKg9$g> !<5TV# =3Br$=˳n9~)/^^L{SFJ Nunԍͺ*6/~{}0Ě,Ob,#%@Nz x\OV\X^|t44#s:DRk{H`@a=NqEA j.Yd[y.pa廓 XjI?ElvhM,)O~M?:~ 'ʇK52 Wq0vԩ:,dw<1Ժ۵ƄwAD`T; S(3f9L"4|bu"^/jyXpeN:풴"IHh1mJ kH-K9e!:.,S3-ʡƤm^$A*M NS(4a-q3m&js"$g-HMeJgхvJÖC3Gf|.^6vBgbnd3t'2עи`[1F\`XI $JDفKArIYϺLA;E/VΠ3ۡp*Ŷ? +Y{WRxN\# qo%Qq bعb `[>ڷOT(XR"%-fֳ?1/>ȏNM(L=MyQ#Wl^U6ԵfueکdV[ORB., wͭ`+_58 X9xr¹^d NzӑzqK˨Pє$~*V:tRҰSyZcu!Ev f ܕ7>MhC8M\|u9k2m,pxO=~߈hCMq&uw+XQdy钎n9q?׎o}3+n?UƺGCtmRFl*duaDlSBa<7L]f5rnDe:u<խ /(,?]FvaP[dr ՅɆ/*t~//<!U4T~ۡjW껇R\YۣE>"wмEfܝ3N2E7YyLxYPǞ=C)݃"Bse?L4.O pv.RPs{;t?q+{׽}3% o:b*ȶw[Lq)T>^n6&S&%UZ]g*sWf8Ǚ}Һendstream endobj 52 0 obj << /Type /Page /Contents 53 0 R /Resources 51 0 R /MediaBox [0 0 595.276 841.89] /Parent 50 0 R >> endobj 51 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F28 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 56 0 obj << /Length 1771 /Filter /FlateDecode >> stream xڕXɎF+t3X45av`ȧ$Pe\F'TWUZ[o/^K7F&dw.5߫pFz(D;maN󇧂rN=0?۝rꭟ81 h2EMĤPUTUܮe ǎ a;w}7Ni7 IׅA t?8΋Ib_65clǮk*7֚Ovȫ[.F7Or8!"G~5cH2"9!"w|VX(:b~0R-a]֯M Xk)/vu xoomh93WK}D0bMk+vvϞ{f4xmX'h-TK"m߱I.@l(wAgQ}'_{yKpVF)7`[N*[Ԟ&}˖gzqj%(R͚6l 8 'HY_X]P@y9_*JС<#* <9\+}'8y (Q!"JrJhu#ޚcxd_,``|xo؂3-!jk08B7yX߸)')+1$BePT^6c$EC9ĻWJ =q PJȄd[]%p>J8Xc9VZykHcEzY_|%TPv+kmӯ\(-Y D%`N:-y(+oVe׃A:_FuN(00֑xeаnAD6SRXm.Y6f!Rz}A~ܓ+6^!TTLۊ!̲Dpe#9ݫ zaԑJ3uks!!T}A="c6rfAd\X˳^*"7B=Pfh?YcZ*HJ0-/*_DKB!p͎a%ex~<7PVn!lz+'IZ[9OB/['e"֟fJY@z|ýB E䣓+zגk pg}U c?HN:i`aaK@hNͰ*U?5DyÌwX nOf89+kKF9pG紱 d%s U*2 m |,3HUb@ Tq -dth:>A[ >=3 qf7æOtRefX<כ:8\b~wGϿP Yy "侊B/"E.3XcD32Zȱa(d84G8IvN}l iڜmw]k6q)|j5xSG1Lq6eug26~ Q#ߚҍZ'nO8DcOۗKé?Fy'}WNOR_(_3tz\rC+m} Q-gh1riz~矚*)A\ߎ$rC̣;%\cQ;H6'YŴ͚J.樝*HG.b-g9L!)-ަ, ?y?uʐ0wF)kna)x/mendstream endobj 55 0 obj << /Type /Page /Contents 56 0 R /Resources 54 0 R /MediaBox [0 0 595.276 841.89] /Parent 50 0 R >> endobj 54 0 obj << /Font << /F28 22 0 R /F15 12 0 R /F27 19 0 R /F31 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 59 0 obj << /Length 1590 /Filter /FlateDecode >> stream xڍWIFW<hEےsQrs3=-S[cpbi4T/U]]?|]eX]A^ȃO{5Vf[gж5 (뾚G[rk]I Ҥ$m^ucji t㉇νm'= 3^ssk,X&>_UYzr"(:F;>mL{Kw32/U.Au;: GT肇3D/]fc *:"bL0JpyG?#HO:3c͂RW{{F!-z}0 ½c X/7}{ 6髀2Zn6< k0 7@W@QgHo~\M¨v -aL$ tq645t|\jYh8Fq3yDk:wfʌzͳeznAILk EL@Dy?O1mpB z fқ1B(>zoʂ.W3$"z y&&Ǫ;&}$ˈb,Ih ȁ, ~;OWRQ'_,>8I+hmx  <\z/"`-Wͪ?gRof܋[Z6I j8C@<ͲR^ fupF]l+@X@{,芃e 7]Ca%$E>Ul$ =mA[+ǶNHvOai0dzgv"endstream endobj 58 0 obj << /Type /Page /Contents 59 0 R /Resources 57 0 R /MediaBox [0 0 595.276 841.89] /Parent 50 0 R >> endobj 57 0 obj << /Font << /F31 34 0 R /F27 19 0 R /F15 12 0 R /F29 62 0 R >> /ProcSet [ /PDF /Text ] >> endobj 65 0 obj << /Length 1191 /Filter /FlateDecode >> stream xڕVI6ϯm(VDQ -@zhzHV!Q1屑b?=}ȟwodQXDj[$3H2W/=`gM Eq.5|v{>4/=6Nn8 jD='չ# +SkICOVۺGJ"*ևjD,E&o[&,T*LSʈSJ'rk#ڕXbG ,a鯇LG8Qf )eXIAqaMP1oQ̓qJNw{3UZ39)OX:lOHE, ntY3tin4484 N!hMJx20/P[}RBS7]u+[`\^2,P|GBEKEBI}(!bawF/V0-R@lHYl)#IMsbt'9ּX}D8y;0[ n.3R2W3c> Iԣw06e5we⠱>G QA 7~2v$(Iڑ.QPM`h-[e'MW!*?s &a/Xs&ͣ_8GNd4aƎ},1bd9MCհ@ f˜@!ȕzo ]z? ;b FghEu 1XA**?jpVn&I֤ڜ> 6gTٿuCK_MaՖ;/$?ltOix#_Q1 Ύas'P{B*Ɖ?hr&*{~ㄨAҺX kE۳\X#gn^<)ZPE՝-ÄFcm"6XۀI5GO\pVE֣EfZ#C-EIH&`J;Km]2h{6H^ ^&fJRLyf~ΊD> endobj 63 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F27 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 68 0 obj << /Length 1407 /Filter /FlateDecode >> stream xڅWY6~ϯ0"1WaI MsH E[4}%VW ͢,m"9>|<~e )En!TdEB)d/6՟A"2r%eM f2]Pa{* EZ^/WIuYVqְnQh؜;֩@'ʂ<grānQ*qY1PZ%m>:}'UD &XIAv5^>rD)FQZc7$>iyxCP}'\7*$ !1=!6&NV݈ducuZ.xСAԈэOxD^prZ:Wװ}} PΔ[ K؊{VN6tC?4,tK.i&LDe8紱xz?GD!I?Pp^zf8iFQdr,#ΊE$fDda8(m(][rqg 8*DJF xD XKh8 *~H.S(6: w"Ų?[0'TETf^!ƟC8u?X\q mWWѸ>nݚ{0q=%VҶA n+I 2i<Mlt=\amWP&`G,Q8En̝aJHalEхN#8R9ʡT_!pLڠ_҄*iYBZ4*b]87Ӗ=N7cDHn(˼"ע),҈󑯸MU~eY, - C UJ;pMv(w(U{g#JNhڣ%|EAgRr&W1U!hmQn9Gw5Hz]|KUw\7NuwInS7~^|}':3wD!3F"kwvTxW Lh'O)uuƸ( 6/MwwZYn+=ulnUǙH@ˍjgn;"VV>a5օl4WJs<;83sx忬!o[,\ߩn^ T~Ώ7"t'5lXȟ_W:.J1;>>`]~ r2xAS -+D")rF9}FʅIT.[> endobj 66 0 obj << /Font << /F27 19 0 R /F15 12 0 R /F31 34 0 R /F18 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 71 0 obj << /Length 1238 /Filter /FlateDecode >> stream xWM6-)(YRzi-@R4=6m %A(;o+EЋErș7wiP*|.TEU.D*+oA*Py)fP!}ӻ/TWIdIW9۬R #]Dee"`0-ikΌ"x#i[lion'<_8w64 N+YkHƆth[|++ H1R˸řg=5%Z0 4Ւ <̓c|f 7ƮFvAUQO~CӚv{1]!liYFo? nF}gx\~/?v~þ/n!73GU*}ވմXc YRQդea$xK.LD@Ods -a ozQiZ$~1RuwLs63dϱF!Ǘ{J?f'FfRo0,Nh"Gvo)ż~ee\3%.1+VgaP#3Tb_a4N`Nɧ0_N)=(=#d̺fYIk& a-ftV&>C4@"0Ml_D,MuTd2CڎLf~k7eH-)P8)IZ\6ջ8!ˈְw2̞yBz'}| E ^dryړdΖ>Ú&E\49̓i.r4/[˧e2$8%sEdlH@,s (Fã{d f Su3Cs{iUyAGQn#Skr @Q=:ѬVy<(ڛv(,,E^Pc l ݙٔz0ԆPPs9X39 U'`U[9 o[Ý&߀[<[iv31&vt6S7¢euSG(^yndLmx8V =3B$SjXypFN%=??Os <5,3<9Ny62g3iMbIr'ē2cs K{Z'PЋhYEVQ~uIendstream endobj 70 0 obj << /Type /Page /Contents 71 0 R /Resources 69 0 R /MediaBox [0 0 595.276 841.89] /Parent 72 0 R >> endobj 69 0 obj << /Font << /F27 19 0 R /F15 12 0 R /F31 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 75 0 obj << /Length 1590 /Filter /FlateDecode >> stream xWKsF WHXc$qۙ萙5ElHQÇO|ˇl:MϽH ˷~zazK$//zz*uSnvtWG!Aba9Uc%TOӁ535CK2O:r:gDŽD R΋쭒洝7M=8J); pL{zҡO8[|Dȓ:TW-`?6jN", k m-z8M4B4y Nc2C'onلVl6EN9cw[vەͩ6qFp'p枂>Fvw"x+` Yh;ʢj%VQx^ &rS%\/lK,hS6_AXjY.>YbϮv=oXfx^}ڀe84方HFW. ":RDn:\C7P?`S%G+<ɿ{D,Mۀ^^Ċۄ -Vkǔ|MZ'w!^Z%kj)=tŚWS .z.Tc-f,eq`lrFBMDعv%=TfD 6RAJV?~c5hA&Y48+H0*MPZ,/rȚ*́1חZB ]KZh;ѨR6-9>BWF}}@8ehXټϾ -UHAi%&p.5Neh.4y.FxU)#@٭VߎXl1ɠyCm?ѭfS1 fsMkO)Vؒ:+7NH;dV?<|;-M?Q_Ӭ3ʿpوٶNH7D gBqLj24ˬm8v͑kiD BTxyׄIDfP$8.h2Ce+:澐x|z]l6H׿ Z(`Ց>V"LR" lp4 7rX+J OL{)RQRRoFrnf꧕RE.Ղhx~]:Wqb^%&J q!F,yZ& G*o4p0wF8ua2*5^HIn G _;t\Qyɔ:_%̹2sUƜ94fV #Ca@W pɹ͏y;#0Ϧv4eA'<7bOq_<(;0XyI/Nps+V6~ǖ>~'T6tvff&G!E,ygӐ [zZnGIs%|t^3]dy9GHTrOJc^ɑ&z uh&sG,Zz~bk0uh?CXendstream endobj 74 0 obj << /Type /Page /Contents 75 0 R /Resources 73 0 R /MediaBox [0 0 595.276 841.89] /Parent 72 0 R >> endobj 73 0 obj << /Font << /F27 19 0 R /F15 12 0 R /F28 22 0 R /F31 34 0 R /F34 78 0 R /F18 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 81 0 obj << /Length 1658 /Filter /FlateDecode >> stream xڽXMoFWHᆻ1AcEh{`D""Iq}R%9%k?fgg߼-_v#GlĨ44J'lYYsl,}s둴IUDŶE_}ʘ49ǹɂ8]Z99JV+0@?/?~ 8>=_pQxwJ̽`_N(y-*V~ ‹8Nά^P8뫦Xl11Y|/Zu<U†8fDfa c[k׏Dl]C߈$#{%Iڎ{ٗEJxbdؚIZPٺ=aV#RrW?h+Z%M_bU9^"ْlp&6yBl ܹ·ɧϮH3 8n`,^TFtʼn}Yu>;m{^ ?!#K:Y! fSkIGHqT/UCqj=67եoiF6G nURZL*> ~u"~9B>Ŝ}!CNlEfyhwT,1-pЩ+j8]?,ayOY\fw kk2]ҁm>_oU/7jR\A%L?Ht`F8cA.g=}Rhl/]UKW۵Xz_q-O+SRW]<Ê&|lBp.e*_"Ys?hbW)'ƚtzozNfzrɄZ@H8a8Un:h0:X)9vo۷ߋa( Mk1Z[baEBA$endstream endobj 80 0 obj << /Type /Page /Contents 81 0 R /Resources 79 0 R /MediaBox [0 0 595.276 841.89] /Parent 72 0 R >> endobj 79 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F28 22 0 R /F27 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 84 0 obj << /Length 1975 /Filter /FlateDecode >> stream xڅXnF}Wa.Av$Eh@KĆ$[wnKQ{9sV7W" Ȫr2H|:>E\ydl]9%T.dLgKȪ̢\~Q(Y;^tc*cYׇ myF=gN"hd~&$ ;4q`4% ephXŢle7u儕p*#{zw>~yKcz8NٹOn`N6{o*$"yp> endobj 82 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F28 22 0 R /F27 19 0 R /F30 46 0 R /F29 62 0 R /F32 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 87 0 obj << /Length 875 /Filter /FlateDecode >> stream xڕUMs0W(f1iI2tZߚ0ȁdՊ7rۧ:_]L< b5IΒ@pE9r(*0Λ|Mn{xÐ,1 /AHv]Sco-x<߶Tb?"|\MȌp%\,&HG|e<3@;Bs[/ u <SWH0 98Eƒp;əL:702h.yc):YE~FT:< cn ,b=uz56'xpIxp#2P4k~"v ׸| ErZ ?ZX%/xŲB$#q.h "㌌eVK :q qΑL1f\0[,M;y"4[%%Y="VM9dҕ* lzu=-"G6%6vr#S>J Pzښƪҹ;d8ҥ4$֋mLm,3 6GDd鎾 MSD&+!ZsۭȬ++#rckHI7Ǻ#/4KkkJnrR-*5ՠ 6v'GM}")̋>H#W9]k8ګOFPDP;%>x}U_m g9!%"AǓTnendstream endobj 86 0 obj << /Type /Page /Contents 87 0 R /Resources 85 0 R /MediaBox [0 0 595.276 841.89] /Parent 72 0 R >> endobj 85 0 obj << /Font << /F28 22 0 R /F15 12 0 R /F27 19 0 R /F31 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 90 0 obj << /Length 1410 /Filter /FlateDecode >> stream xڅWKo6W(VÒݭ-P4=m+D wlNb gy|3?>=Db!?zayH8[iREOĒdr4eDrnkQjR\/2T q0uuEj^ya*Q gd_d,]ɇ{l"[Zn9׃ci,=MދOY=bԴ*pA Tf{T ƈГ|;GNt?m)9R$~\&9IC=ԛFyj7 DrybZ1``GBI|~4c9eM񠗅A<~}OrΣbo~} W8gOۓ4CY9o H )Vbm ESJ5%@](<^3X> Ca:ρ$YBibbH[tX^AN}u⬑5mApT\7acIGSG^CvAMh+s珩jk1ec~P [; B'C. ^I\Y=Y >2ۃ\ځdžX{Z%/wX;V¹w7~(BХMX_C> endobj 88 0 obj << /Font << /F31 34 0 R /F15 12 0 R /F28 22 0 R /F30 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 93 0 obj << /Length 1461 /Filter /FlateDecode >> stream xڥXKo6W(^v7C[l.nDʒ!q;/ɒ<^LgՇ Yh*]l ~&Xi_Ŧ _^;-W&1Ζߛ?=R@a(:yFD~jbP*eε_hu2Hq,#eY[KP2и*xձ8`":YUlv<Ingq~͈ ф&W/# 1ƫns qSdeSd]^.{#`fqfP4cZ>9{<ď=9?u$R0@6"`0w_n>mIa3oǢ=7$H(Ѱ5H'"Q'aS^|0C$JB[\cIC<>f:7uY#;ےqhV?ZW=(9VXr":Zقpso KO,Ynh̊6=ϞppǪxmiF0>$z f Q$@ou}Qh?Cq Ek$*r^ G!"7Z<5>ɥD` ɄhEîF)e}&Up4NAvaKf;XF7hϮex+91H}uY QfCi?@Mk? yD$gҙRPaאT7i:VVyy,$=ɔ8hMjsT]H)&g>G~`#&5) 2 nC˻ma^#*-_ D >)"TP0[xӰCh!E"|I0e>800SG;L/r'zB* /+A:轒=VǤ| k0qXg8" Jc+gy R[q` kܧpMϤTkD|,_cf0R;VRMcjS}u4[v2c%,JǚK̾62 2N8>‚2jh2hhr'c5mֺD&Xմ9Q16x x.T/ݐښh %ieBoڬO[ϊ8@ݏ73%fk*2*/қ٨~s6'u531duY6t:fYD 1*f(%v͔|Q+3}IBtԈ<&ǹk7z+RP)(Xk۴$4)Iqx 15nh> sxbZ"Ç*Ε {7޼Dl `I2n6WP`endstream endobj 92 0 obj << /Type /Page /Contents 93 0 R /Resources 91 0 R /MediaBox [0 0 595.276 841.89] /Parent 94 0 R >> endobj 91 0 obj << /Font << /F28 22 0 R /F31 34 0 R /F15 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 97 0 obj << /Length 1412 /Filter /FlateDecode >> stream xڝW[F~ϯR;\Ɔ>Ui!K}hxM咭}m^MZ 1ÙssfxyswETvġb?ŦEATe:Eٺˁ7LRaKD 3*CM ' \ǰ^9PEH _1%,8cV`b{vٻ-Ý33iCkfRD~?pY @. 3T72q Ui9R~V~g`P3$ |Ѡ3\{`(jss*K1O0BKi=m<NjR NWa|-:ZK5'q=TWe`endstream endobj 96 0 obj << /Type /Page /Contents 97 0 R /Resources 95 0 R /MediaBox [0 0 595.276 841.89] /Parent 94 0 R >> endobj 95 0 obj << /Font << /F15 12 0 R /F31 34 0 R /F28 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 100 0 obj << /Length 1613 /Filter /FlateDecode >> stream xڕ˒FPbT`vS.9>`V-/b==7O ҕV d*񕧢t)>:U ૴k7LCh8`5ق7rKB帹g Wn{:$j/{C*q @zD(S!@p(T1-c;#uW~-nx:-b|"pEna+ۡ=v/U #[gQX ˮ9bWQerGnxZŬ]ԃ͒ VEmX%A,2g aA57ázcV eE8+I5$\WweeksX+姞h}k=ju9ٓʇwvPm)ghwlp2@iCyb츨M$!41SAͻδSK Δơ{ߕ(Jÿxf:"%YA(75[HġRkX nbfc[{J)Qh UbD!`$,#5. VBΕPjLJ|mÜu~n +ߑ0a6#mtD`"1\Hc&TbR;]0kpANU*fOB'U} $Y7ɱщRUtvSi{~v`578-b~D}֋>bEqZ#GM9? C|rDHw;Gygz<]b.@JXе $j=By)|S~v޷&ҭg18 U2JnDnԦf%dVBt4g&Gv,-UU7ή> endobj 98 0 obj << /Font << /F28 22 0 R /F15 12 0 R /F31 34 0 R /F27 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 103 0 obj << /Length 2057 /Filter /FlateDecode >> stream xڍXKFWjĐl>c;vśIVC[TRHn4>~<t[c=f)Xʶ ^^ r:G싎?u덉#wܯ\ocگh6 KSH{ݧ haF;`lm0(5F2Z';,cqZ҂W59U ':3ZC︰D!)Cߵ#[OW(LcNM;JA6_XE 9l;!غa#1ݫJcYث=،Q6jT 7j谖K)0ρ{^!;m% "JĞ8^ j 0ϡEg.҈?|4? ?8n#y^Oq(=,Qt'e{ޖmIһ}i9p,+KLفDkz ;c|*MA_~b;WgyHc iVƋLztfqˋ7cY"t#x{hFG7xSHL^X5}`҆s33* H%p=hY<„Y5Q՜U$3C=mA/tϝ)Jk2H4_ Y4fN)^A/9K}щi `FWx=)fz1|MO=(ZK Ң}y~.K` (O#=S8y*P)C \I2w!\&ʥLx_gwe8'S?ໝ l걚[#Nfĥ_3-\=Ȟ\ WvnvjB/dW7ⷔ-Ks9#W/共q?~g,@T8UNt;qڦR_GͶ;K2ߗSaE.v #""`w^*t*WPG`qDR8+kDxYJx1p0J5endstream endobj 102 0 obj << /Type /Page /Contents 103 0 R /Resources 101 0 R /MediaBox [0 0 595.276 841.89] /Parent 94 0 R >> endobj 101 0 obj << /Font << /F31 34 0 R /F15 12 0 R /F27 19 0 R /F18 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 106 0 obj << /Length 491 /Filter /FlateDecode >> stream xmRMs0W2c0plfIzqhzhzAcȴڕhվtS->,,-YU,"O* u, 8;'.q"ō3@VzLfsOqM_؛ֱO5xx=kWc1\j@~i5TE i9S,rk9ZIh*%s|~]VKŸ,W@{ąx|[д0M PT#Үwh$qy-G%yePŅm5.Cݞi5VG}FcMVw~܍7n;t{*̸Įgc:j@6Dnߞ7ڢm.Jy=2ڿvmh[2G?X:`?яYrx@ѥ@^'"\E.$c*hkendstream endobj 105 0 obj << /Type /Page /Contents 106 0 R /Resources 104 0 R /MediaBox [0 0 595.276 841.89] /Parent 94 0 R >> endobj 104 0 obj << /Font << /F15 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 77 0 obj << /Length1 756 /Length2 1101 /Length3 532 /Length 1656 /Filter /FlateDecode >> stream xRiTg*j JYEY$L 6a!d&L&Aĸ[.(PEE (bpCDJEң`Tz:g}ݤPgA| rf1Y+H1΋D` %poB<ÃX Ӎ 3!WhlI/CHT !1JQR3ÀhB&!&TL$.aR M:ڢ15 RK0ABh'} C PLɕB B{od1Tc1@!TዪIJ-Щ p{8͡^TZ yfUِ DBLbDY>8.IV3轠+Hf *h.L#N$H 1x\mrb| JvxgW(y8DހA;;$|(&1HY(go} &șF+x,$̸Өs7VsJmgҒe'"e;_yhRQ`NÝE}raAw؃-UG&ޝu楯-6Id+h=;]tۖkkRGpT;*hdﭐL2wۚsc>/]8lqqn!g=%@ޘ%m+S%YHoz?p]"$m =}& zy4X#l%%IJu?nصats# $_SWiPovuIm*=myG1y&Զa3-,Xս=euk4NᝒX"* ;f}ml閻\~/liΘr#~:~küK舿خ}g~wϬaMA"ܽQPhm~oL"v/r[Elсh+.1\#ֵ{p˷}xG򵝻n@i| .:ߵ4_ZO`28ԕ8|g|yЦ++6PS*bB]*Aˊ7o֜oyy p@gޡ([L~ J$?(=)C6MN] ÇB@!0I2L`܀endstream endobj 78 0 obj << /Type /Font /Subtype /Type1 /Encoding 107 0 R /FirstChar 65 /LastChar 65 /Widths 108 0 R /BaseFont /ANCKKP+CMBX8 /FontDescriptor 76 0 R >> endobj 76 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /ANCKKP+CMBX8 /ItalicAngle 0 /StemV 122 /XHeight 444 /FontBBox [-59 -250 1235 750] /Flags 4 /CharSet (/A) /FontFile 77 0 R >> endobj 108 0 obj [922 ] endobj 107 0 obj << /Type /Encoding /Differences [ 0 /.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/.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/A/.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/.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/.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/.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/.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/.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] >> endobj 61 0 obj << /Length1 972 /Length2 3243 /Length3 532 /Length 3911 /Filter /FlateDecode >> stream xy< e9l!-dYdqFYY= cFcƾeY S#](KYJY:2w%R|A"p,p$'C !h|A æ,0#CfdF7?ЈD3?&oq 7 RS2zÜ)#м5bɍ SS?3'PC O'1>k'c$u7~f`Of Ba0x|sG34 KHnBYP(  ?1TD2> d ^U`|Wԇq kd/M$51 $$E!7<@63J2 mi?߷KRPB e6j2,'ڐi> SSURSbi H06' A "cգ3y_Q[Gxy<%Җˠ8Z +hO~ټL+OE'Vn[ߏ4&9VazGx9hxhw=3(M|1$<0K_:M't :dn NzN@&䘲 ǿ0˸.q;T3S\ ^ϴ7|1lI" P^'M/?gBڵ~}{- Y'=)Gݥ5JcY %9#|t')KMmʭl煮Gx&).Y4 >9,VH,)2. XEr#+7mws()@qئlU;.;G-$ i|;謳ޠ=˻AaVO]vގ"сiߢFNӸx}=oȦ<4 ۲-gh[( xA0|t)\R~)\.MfT˔pCc@*}v:7]"N5rE:aXKcbd&4It՚$D< :-r|x)U vy!89J3{Ԧv%BarI.0n~]lP(("p$dQhފ)AFG^{^|%}B2:2ꥶq̊e㗮 ӁCwD>B})lL{9o։Xr8'I8UhEEׇ;>~uψÞ]0Bbcodj'm|ޟkZNZ>hXvXw}AE56UXq)~oEI.Y/PL/"%\k÷OȲs9gJ8tnj|*m?2K vs oJ ?KĬ[iz |{`ћ~>vjkb3车q- ncW˶BKLI'I{II.NXD} ɟ=j~槶< <% bx߄5IL 艑6tx4BQ~ *B&CY^NYp] ]@Up х,8l`)[ %.B*:)6P=CreFZy(bIC U@"pk*彠DMoD23?q,S!+c{ Ȯ[ٙ'{">Ԕ&l:햲O)< E@GR4"F_=kqȥ11aUIׇ: 1U.y^+'#lnV lr  tyUmβ6qս}^gWQy`)z[ktrMmICv>oE+6 !'.0IRЦ GYKU>aCYIk˭W)ԋaB]=S0X۵'[,eD17O÷[}ŏU_"?U1N@=Abgڟ'=ϟOEf&?ײ]ySvQ,rvtzi?bNC{=yӖ,h HW[! 6b/,a Mi:DH8 JpUF}u׹ir|ΚU.!WcT[X&ЊeCsDƵE;U#ȝL'!$gG1kEzXy^/ t,M/R QIsF}4GX8iiuqMz4emOMMY@eP,Ht8=F9:k=,3XNsޅ".W^Y lxit{*TL\ oUgv,݀" >+kwLB0A Z'NT(\h*Fف̪ |' o#vؽ~7ԞD ƭCvBpeJH)WaD/7+\ih6Y4Uu=R)aθoGBy kUj+ wQ/0R> endobj 60 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /UKHBUC+CMMI10 /ItalicAngle -14 /StemV 72 /XHeight 431 /FontBBox [-32 -250 1048 750] /Flags 4 /CharSet (/less/slash/greater/A/D/a/c/d/e/h/o/r/t/u) /FontFile 61 0 R >> endobj 110 0 obj [778 500 778 0 0 750 0 0 828 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 529 0 433 520 466 0 0 576 0 0 0 0 0 0 485 0 0 451 0 361 572 ] endobj 109 0 obj << /Type /Encoding /Differences [ 0 /.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/.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/less/slash/greater/.notdef/.notdef/A/.notdef/.notdef/D/.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/a/.notdef/c/d/e/.notdef/.notdef/h/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/o/.notdef/.notdef/r/.notdef/t/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/.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/.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/.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 45 0 obj << /Length1 820 /Length2 923 /Length3 532 /Length 1517 /Filter /FlateDecode >> stream xSiTWF*DTEzL0 UAVPCF&*V7G\8ڸD ( RJ;=WO{gcrЛ)F܀g@h˴$!JaR pK\7׍´D$1#w$1!2PBAJR)H!0Pf"aB DC 39:E.i<#ZEDK@LςCrTt\ GeTA$A!$> "L.R),d.oLEA%bTB7$'(C_ éqp?bSLDb esMǿ-%w(IJ&=AtpTs8A[mM*$SVz8ѴR<p$$m \M&Q!B0{xd\i! \\'Xz>˝vB('ISCG1ct# T@!߸voS%5 8Fou62jVbP~~*x~d[ii~MKs٫z-멾 ݬ2h<`#lj{|,oUĻ& [Lg_=8K4*GP޸oQKB'wQGXh.^*<;#-oq|p8k͂k}?o;~e 9O]8PlgءĈ[͉ Z_ )~/wwfyJR]ެfgۑw̍YkqIos>5"=5t} ' %)B̿׿> endobj 44 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /HGCGPY+CMSY10 /ItalicAngle -14 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/bullet/greaterequal/braceleft) /FontFile 45 0 R >> endobj 112 0 obj [500 0 0 0 0 0 778 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 ] endobj 111 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/bullet/.notdef/.notdef/.notdef/.notdef/.notdef/greaterequal/.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/.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/braceleft/.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/.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/.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/.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 36 0 obj << /Length1 1191 /Length2 6996 /Length3 532 /Length 7766 /Filter /FlateDecode >> stream xe\T}ip(P@@:$a!fK)AD閖 p]ܗ~^|̼ߵ^^^Y] i A"`A,02J:LHLL.~^A0/(sw[X:_HU9&%aN@q_w8Ua0 N@SIa+ll))mL!6@39|P=xa?8(I-*vN0 R-ؿ)ζu2C60 ;_q f wZMlaat0}t45hN*Nv0 ?3~ 0eC CLE@./Dzp s{p @ n>Lhtu`. WoH[[" w!$A$o{) RL.2@?,?\6l#!?>:Nr=s$$n`^n ;/Y^^;dNNN~.PgWa{i$T(C]g"L')AڂkR8'GaOOŏKAf:q^O5P,Q/>)KvtO/6#lknݮe6;`p3ӿ|}Vp͞m$ &4c_#ss}$wsT )ЧRDnqitsڙo+j9]Sf >$ዦ_/Vq0,=aLc RoOls2 ^GNn؛hTs]O8ENf3b 8{yuwL~Q t(jhiQHĹ% ȕYИ+?ɔŋl0-l$ $>5 t9OZ&>  C Wc7洘 =~_3V:1/MK ;(hn\,U5p])N\Iju-.U\TX1Si0W(njSȠM~FR5=dԨX¥Li/ ͽ+ ͓VuDkvpYV+{GAƗҳV;5mDMoٷ*D}`0Κ Pɒȥ~l`5ԛe<*֥b7 񌐰֥z ^37tF I}W\+Q%R`0A@m"ґ~lYv|}% =OSפ_\>Z= N7fdMQ|hc&*FzނW/hDJ>X'O.LhKhnZ.KLilQ˭וN?Wls(};KE3Ktfu{殖6%(WK*xX.BLdn{"rrH1|q##D1)m]q +2PpŜʹ)֧nTaDsՃOx4i3tEtnl|GAxLjgp49B1b^OP]wBhWMH aFpmbyBA(:o M D8NnNclL$s'$7hS6Gv|?W@Zwz)\M~H֜hq,]mgA82$Cw. %z4?sso*d?3L|Vd&P]'ab=oIJ I6dpd?{]fv(TIŧ\C:cgjd}c$Dg|q]|煑I6kP4IIx{K=PQa훨L6wn,Rrf.-/Pw XVOyC}^Y[# Eh|%0FUQ۰FZ$a5"ݞ]1ԑntsq&B%1{c:'.x3J>=~F-IV5r.#k5%MG@plE_u[ m v2|+L谼չll8rd dM~ xZʜ|1f_JY )逑&+nˬP1 I'$At%&v<[<:ώƝY& n~#C[coQJwlXg)Wp{1WܻV5_c8$݂kd7o񯆌KgK^c'u`K +HeS()+x^XL՞m_wv /wH Ԭ'ʗNG)/8-?<d QbgkpI8;l>/pjSZil[PJXB߾))}ơ_vLw%]{@mDQm(5n~0SZ ;DɞI#6Bl/?!wujoP/zCXT}jBn7:#.CK_Z@CQCS_Q,|@VT߮|dǭ*{ѸVK.LɏG2'BBAn:huфES@:gՔn#+Ru"q-~q ڑqsREЄ-V9TߧD(Bv~|nZuÕlax*.iT1uz½Akba?G;NHX嫸xDllnlNq_An ;+:>!?+g[Qv:IVY!%?m?ʒf{濵pGH (r+j ~#[*"P[`eoofPOm{ѭsMF?{יN>7k+=OޔG䠭2rʍGF]zl1Qm4/e23.F=BZYbGKVYS3$^[.uiSʪ,ZI#p%ݳQ,$ {Rl uva֥+vyyo3fd[s \4q{X׎դ*^}p;8+D?`#q7m-bB9h0IֺN]аS- kؚ53!X~ $ʼnl?}%"!7*)oU Znm=8J<>#qZ,2O߰EC>Iomˀ/BCH~R0s3٧;{^&;(xr?Nbmw֣js,mbbO\MI!,||))5 c}%g Wb8Y?h֮KA!7^@zgX ieaJP{tٶ%8]T~Mj&N0v愽sǞ{pЄ6%8h{ϴ#{'#9׻\g|4)=lA1qi?8N:9@,lXw鯗nnW P*i|;\5sŴ@e nV\z+!i) g_gC,kNں~%$#Ʌ3%7E,VzMީx_OOf2j{ Q]*B ұ4.&S!$)- I+4i6 Ӽ⢈g7ӐsbhBMzèO2L]䒿͂׼ ^/V?WijHԒ`'&8b4" I',rt  , Gd)nZ>Z n8I 6]{;xg+3Oa<_?mr a+jO~Rێ2܀Řl^<)^zɏzGj1Ո+U淉'Ugkŋ.mQ,dB}a] !f'4ȅrLWy<3E\`ɞM Cf.}I)}EQy_TG Qbr8UL2jnv'8ͻ _(ט< ;b kٟ-+-NHp<XR4\`PWW*)t -\жj=r(xc(?&o%:1;T!sx֗RegB S%oӜƟ|%(\9Q<@"yVbBQ>wKT2lDT1[VO;6l쐗%[l(.b=6Vm֯9JIyO`f 9T4~hr⭻4i{&[*[rbs'_љIzGGW ElUӾu=}xlk}-B:.D #(Mp<f\Q WqD]x|C];*` Dh@-֞xdW2wΏ@_䝷q58~ƙKZz(oog@|;سS킾;;s@:z4E4 UY<*C'5'󅜡< ):ݷمdF cQPXWbVh_(\ Wn(A)<lk=o{bXh}iza8>lT8"Y}CϤ;ڏ]؏Gmd~Yl`)͐\хLaIc:qyB*Os mxԿ6rϟvkD5H{g  w68*ω1 ׷]p="JoP rū-44<m_̘@*i<TCܫ;zA=ĐxE<ذ'%*)Uc^):Gέ [$>0ЁIyׁ>|c_RMEKTg, q(ͩ֩OgH a9x63 et-)K$"ֈM>AmҭĭnP\m)R\`4&3W)DLżOtPk6"ꘓ*b޺IO^Σ'yX?/ j KTϥawXHBx< J&BV|4}-0:!ŋ[j>l{HZdbpij2 ]`@2O UX³`Kmܛ%Og)f%Z8&=9f\_d;L|A/Kf$]QW=x4mXEi]롥N*6!O_(Ad4bioq䱰nR?E0 k;,iu2Rc 3#7M5JH@SJٮ?N汾#a_><1d+UO8f.Aj|HdLksB>lߎf3`4Á|IQ!|&t.Z@!Y K}?jQ-+5{^' . c]ӎt{c>ͤAXg p gR(vUk7R2QVV4/GB*ѿckQ 03\p6E^%p;h13~ؑ}/qX+k'e<]jHbH=w d~ Z㍮}c-7_6euЗrmme%쯃>ڼ~J {AWmwxyy.Ht*ezN? 8h-bZ|щMlA;m6Vyf+¥q;/5t < TB&4MxFwMX'pb+v3®%)!Wd"4XUP]Nz$ޤ0:Zpg4]#&]5DMRX4 0~kZurD]\FE6Gs6 ?j3qpBښ8X4fh-endstream endobj 37 0 obj << /Type /Font /Subtype /Type1 /Encoding 113 0 R /FirstChar 12 /LastChar 121 /Widths 114 0 R /BaseFont /ZKJUNV+CMTI10 /FontDescriptor 35 0 R >> endobj 35 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /ZKJUNV+CMTI10 /ItalicAngle -14 /StemV 68 /XHeight 431 /FontBBox [-163 -250 1146 969] /Flags 4 /CharSet (/fi/comma/hyphen/A/C/E/M/S/a/b/c/d/e/f/g/h/i/j/l/m/n/o/p/r/s/t/v/w/y) /FontFile 36 0 R >> endobj 114 0 obj [562 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 307 358 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 743 0 716 0 678 0 0 0 0 0 0 0 897 0 0 0 0 0 562 0 0 0 0 0 0 0 0 0 0 0 0 0 511 460 460 511 460 307 460 511 307 307 0 256 818 562 511 511 0 422 409 332 0 460 664 0 486 ] endobj 113 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/fi/.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/comma/hyphen/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/A/.notdef/C/.notdef/E/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/M/.notdef/.notdef/.notdef/.notdef/.notdef/S/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/a/b/c/d/e/f/g/h/i/j/.notdef/l/m/n/o/p/.notdef/r/s/t/.notdef/v/w/.notdef/y/.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/.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/.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/.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/.notdef/.notdef] >> endobj 33 0 obj << /Length1 2121 /Length2 13522 /Length3 532 /Length 14686 /Filter /FlateDecode >> stream xUX\ݶh -knwNp]CSk/y~Z}ުJ* ¦@ {;F^* 3YB hbio'ff^vV jdin' l t41XmAsTM,.ap|:܀,,SK1'i;3{M]{ PK4AՀ 766 FLN_F6ΰupu:MNv;U_r@SKW=*bdci"lgn0WYhdbbpqr+ 3ˀIMASJCߋA%#K;UOOAq0Jz9`d> x,LH_?+`rtw3_A?ln09x-ٙLFN@;_QGW2+)߃l\WH=t @ٛL6Fn=v0}b+lf_ 9g_n ;˿plJ![[ :/'>ރ.d)NW@bq% d'N 3w9IHF@.r{';\ (wUWy'PuwUW{'PuwUx'PuwUkNF&@q@81(?%α]LdeN + 3H/gladd,BPB_ AVB_r AN?/i ׿4ߑ4ƾN.MLJ6hhɉPS~VptkWpyI`&0A"_[37t6b`Jz(j2jV:W{U2;E4^1jn{Ч>/: PPrP<cQM"b+|laBR Yq=;CKzhcy$c>J;9|72zŬ V1VUl_>@IlW}G'hžwŇgrq\brTv~S@71ݴ5s[KۆdǗGe<_zWh<<טd|kN87=}-`$hpNVVDVQP[IwET^Zf": m'#e̖1*p,}^fAPGcoQ J0άXøٻ]B-Wwxp I}L!*q1b3ganXa_sB F?CXn*k`LI8Е;:C3OQ/ 񩥖7ұ%p;ϙF\֍peqKW֜nl/XH RaTL `etڦ@pCYu2#J &vm2ƠCe_]mUP"rkx#10DݔH.~Z9ɚRZG5@hVul@) fthŋ~3S Rx(^DY8g6o4~2|C NLxQz1RӶ_1.)$hC^cC7:M0LǶ_S簛:B̜yD,VeΑFdG52.'Gg~L*ǦܲaSS;?ϴ,H'K(C7ә`#.r6hPGޜ0\ըT5" "hHi͡ As{)xtA,3g'Q X X(-ؒ44f,=nq/љaBju,2w'~|6Ψ-HI6oeNH BVd^4P'HM}7c#Pbh Ϝ4RayD+ Jx{jB03es 05`g\7TZM~ꍝ~PO lL3n=T&Ӭr0-[=ʏchRHW^?.^>bm[]VFr6rϵs`=M=8?|㯼R⧱A;&O\t}Q-!}n[v̟df~]xmα=θO|Le/n?O;rF6ίX>gù˦(qu8¥/#P_ LK>Π,n0^/ "B|I؟9Z a7a\]Sk.ƳӦ4*Vv"gHK0%i=_F}wǾEB5}::Gn [w/ J83 2t178DwӲ P(8iG޾~!T9qWQ d&U/$쿁b1Gv3 V'`YT1IA+psjoǧ!4DSI?גoK|c-Ͳ/i6HȻ܉W"2y N"(rȕXNh>Z$Zx) ͒۬Y0ˌSz~d(ļV᎘`{m'8$E'_ͤέ*B Ob'7O4]*|HŅcGZO%]S^u__y1 "DH3y]?| if`c25+d% $ ğBA Φ5"Z:Xq"05Q.L'SR]AgJʿ[^tLՒL)@7 9lG&frl9Z%]:)z:۫=AI(pVVm\\7[k IxPG>80TWUj,Xm >**b~0TRϟ~ԿyR{HedkbJEzt/Ex6F_k0} a,cCڰgXxvw8hV嚳&Vo^ TTh&G u``w5u{7d t55,,Zrr\rcEQ_` aJF C=+ge ^k3:vV+-bzf:U%=ORȽ4 S0o#݄R6A_@AJ^¶Z-M5H̤TCM$P|kw]釢//iOW(WK]f|4 `1)K֢\mR\͖(U?še^D!` +5K#?*3瀚vC`ܓ*.X 9FDχBq<.5DUyy"E*uݕ?-me˹lYpg$Azζ M3(qPPd8vw {ª=&" ߒ]3q#6Sǣ)+_(Vr?x Z k0.Q]Zi'7Y@`n066B'0YWC8+LNe vٽcvϺP?9]İ,a !^uʦܬ# >6j_ c~} PgK=O?E?4 }X))#$!@1 )뵾emٽΆxۍM_K'7k8!j/^dq6rfdQ׆%p#g)X+f3g=rؕt ZA?.rrǨyCEc^X %׷,2֕e,]/VgWWÄ6}֑&j?os \ILk֥pUe٬}ɣ۬z`FK >; Ϛw'ck!8e紴qRIi Lk7|SS?%tPwF2nbWrܝQD"<鄫Тxsk3ڡ`c7fa?z4ıܗL:kR"hܗʖKդZ!UuH74ΈD,2 -c Cy~9! gBjsr9XiZxn2P]P+KkyR4ڇ?=4/p7c.V&w>'pn9N-m10 2 db{SFIb:GPWIqAcnM@ ~# 8wk1 K##x3iwsK'M1 ;cz0uϛ#Zg}2 o S6 G2r u:"sϿ0)G $:7G%@ stl(5*e=֋'oH,7TT9!e@ޠd [/.I\)eKiP\zs[8 L-j&WMFk7?[ Ҵ?6`36U EU9nʝyRrmaGyTW!ojEVeՙ*eFjNKQ7y re8:Vp`AjђiDuF32Od#t#M7jml3kF$g-Gad9r:Ti.& RG!(L¾ B_G0MxSs õHb韼JxYjh|tпa\ڳt hYFgc%&xقzkQpE\A&Zi՛ݖQkL;g+N|'6M{֋6""o91jT,$*:-g~_qHteDl D̙ׯ+%~xy]_Y$[׮dd-<UGαOv3y{"B PC:N ǵR #*E,1zy Fse3oLVz$'_  ;!zZ>9(1XQe6(v8^w.r yXI'Qk)ޯ,Šm欍b}Gf+:KyƗUn7LPEN~dT+jJaoH$!G5M"K^P648O߬~x&T:wGQGa|Mc t=/DI,JۉL#{ܐD QkԿ䦮 )ø\?7h@O ӽ86wA_CGIo]&%nr֭1#ke8r m=B]EGŅNL:a^=p잆&<6q$ՊjwvfB;`Ѡ)G/=h.,}2h\).}Kj-e;8(667,deJ-51WmA+nqS6oQt96[oD}%͹I~j 8;<ρEw)pFcGuu4V3rHގYn`%|BДF*ghs6"#@@[ca$>bîNdeߑic? *"4i3j~s80fceH3 6.*%~G~peY/=(n7VN" A|>uظ'WA/X8NxX#l6uѽBv隁 \#Zh3 cKjBrO uK Zc}x9#͢h[h`Yw4ԺMD؈PuA˳-Kɂ8{Tq KE'_KG>R sj p{K+Dg m|g4%veatg@£ f][pȲxN %!V:I q>}"KJ8mpcdfs^x|XZZ~8||,w[պ (~ʧ2(n". V}k&-E} LPeVoN&>`/UWoBcn"O M0/RlK:s I'${Bw %[\?i-q=S> ՞H6O }.&c%hY "lO K qSR(& ci[M?U7 jxR*bp͢L9_2IX ONX%K"'x?8~e9%^Pt` z6Ru;2A 5WDwF jݞX-z*!Ͱ?B, OyZJXma_TN2 ϶wu=4d1qrz96A~1jl@jFw<^[! V] ^u xԞbj7sw/ʄ_\)_Eg9X0Kߊ!Sw)y@;k?t7+ǎ Q;,pԄGٞJҧVXyp_LB |q͗tQY%2_>,//poȌMFDv!*auSOģD2k (#.]H GVQq+5 $| ٔgl65 Yo3.J0Gr*) G9DwT/x T;8"i~D\O^JWaT%{LSFڦ_ȮO)}ˢ-n~C W_\e aj۴fJmC~:iiT F./´(g]#.K JȀQOohN]1AO 7E`3=<l(Ѿ~Jx[ o*'nP>yVzcR m[?XnCd=|qV<A:A[1w\UBoDrW72v`#2e93q-Kt;zҚP'v=`; N샋ǵ=x͗cCt:0(BطuVf%XΜ6ZyA$|U}Op(Qbgݼ * QѫEŊ?uJ-`LXlXf77_>F^7MW7k gIhߨr47*K9:J=)han]7%DmSAG?f&v5$9xOuq-4j#q)u qT46+f.*\tk nΪçXf w2t,0>jNàk' V[li)p ց<I鷟Նh#jP:%M)]';MW=|E@N;ؗj!u I`"OA0j{B͐$S([Q2j 7ʂ[ipnqN&$k_ݟfݸ#)+^Y'${OTN6FʿeZ|dUc+D5Ƌ{1ٷgU~"*Y"M_h| cAeP5'{JEꃁZԉa$J*h$h2BzaOf|2E]AfA' GZ#xb1VȄ2똈$Kxnǖ*}-{ىK:@¸dW+CTd!wr#OVCYKbW[ߩ3tZT:a?"":E+%Ht:p ,>[nhPRRx̑2kKUZ͠8TE6({?#^4Z3S}Qv3NW#\p2e{6yRIZN"f n`+v4$,"DzpDWMx?ώgk-gAǬ {d}m@d\:܌Iji<U"ך?D*nu!qeV~b*lOhmV,KNP;-ˉKɕ[ɨ"IN4 )pjgKBՔ7KzSܠ'VBD,r!ɴ$5=Eh^H; q1өf:jZ BwmymF-;|ݙFEh}E/6 h7<Ȩ#e8L߂"-1KhGF{kG;jVpHHB`y Ӵfhv$%([G\O{ϥpmf:e[)K=j*a'k*k'ᓦ=ėx3?yk}1t2'p C$DԖ,F+۷UzؤA֕\%Z;uا'8~cZ^#Nbx?CsB͛*EUB |(+_~SFSB  KP#jG 8M_mMo&Qzkk JS5GbtГA{f 6,|rnmc:Fڔ16`[B%M$OG$ ԰(]n.yr/۫|m2VsAsSAOG7%"dBW72k_C:{3)|=Sp:+͖P[l%}Mg-9\[\*3k8ZOz 3'3uN_S:&?Dv-еdu#@d;/wD/8მK6Q>ao `K֥JIOn+̩,r`DS*9 ABwD UxV" *Aܖ`8jMaѵl&l2d] bUQ`6u-I y: Z[~0c8 zg2)Uت[ԝy`AYBY.sfy(bөQ|t>`CP KFuKF:Gݞ!/,PpKա"*x\Yx[l.kQYɟOQՈXPlS!BMݧ*x~)dh߇ߍ"B<]4ƥ'8Mv8fe9a?7%i ܅uc]ժWYy15|Յ0Qp|lxm#Vj` }⏁=i`֟BỌnB4z01ꐂz>p fY) ,Hks*ױ*߈sU~iM3"hp`wȥ^[~d̙7)<ߝ[ OѤp#`GNHC5v2>!MzL0 w{.kr-c^$1Bĭ'Ll^ ~LS!bDHv!hd>q=,`E`5/X.,.Eb ;[ܬaI˂W*o :k؍|R ]# lɁ%u gl6)|R+pBB=rXIv<;Ǻ z`! +)=dMSE~l6!˵p,{ܥpR^L`7ҶvA߿[Ks DQyy>[;dm:?p\JO:r*{qW> :XWGikF7Kb>}WK*$.W{SOUʶ½'.lurII:Rԟ]tIs'ѓ֑Uc!Ia*~ĺ'{hN"2vT51\7Y啝A9;ܟcgDH+Re[>ߍ?Rv33_;<.jBZQJљc8_oyD]u1ZX-֫Z)J}ׅwҥ5i)QRh<k'T!ŗ$D|g+ȮwPs!E]%g,Pduw|̹nRz&ry%㬼dЩBG^,‡{ˋvNÔK$ĵ)P^v^(ԝ!h$ig.UKrG-1h Nby?UI7bևb9 —"k] &OL`\m(endstream endobj 34 0 obj << /Type /Font /Subtype /Type1 /Encoding 115 0 R /FirstChar 34 /LastChar 125 /Widths 116 0 R /BaseFont /UNXHWF+CMTT10 /FontDescriptor 32 0 R >> endobj 32 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /UNXHWF+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-4 -235 731 800] /Flags 4 /CharSet (/quotedbl/numbersign/dollar/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/seven/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/braceleft/braceright) /FontFile 33 0 R >> endobj 116 0 obj [525 525 525 0 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 0 525 ] endobj 115 0 obj << /Type /Encoding /Differences [ 0 /.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/.notdef/quotedbl/numbersign/dollar/.notdef/.notdef/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/.notdef/seven/.notdef/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/.notdef/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/.notdef/underscore/.notdef/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/.notdef/r/s/t/u/v/w/x/y/z/braceleft/.notdef/braceright/.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/.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/.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/.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] >> endobj 24 0 obj << /Length1 755 /Length2 1111 /Length3 532 /Length 1671 /Filter /FlateDecode >> stream xRkTSW%@0#$Ą׀!PKACrW{MFPp!ڦb8.P *>yTQH ť\pYCNu=}gϖݙ#ƣ/)4'(T8*'`xx0G \dzxn$I˓4:F yIn#*b P2RC$$H tzB$⡘0@ F2][! M{@Z4 q ɳ 05[W% edFB2T/UJH@\ l65 ŨJ6W EK!k _4Q(HRCL<ی>c.Ǚל(ܑ$4wf&!DN Hڂp1b!Ar.Ȋ0a"_+-$Hp~L6 p[ȯol"5ntƢ7q'Ʃ?tǻKT1Ȑ鼯%(%Pt"CW~ORd(8q~fs#;[ J /$L|ȸӸɾ}} F ׾<[rugѶGctu^?wAu΍ 7 ҝivLjY~ fr6kRT9vWTƊL̝3S'XS[GLL#shUtXIMf]v>}2WR.cKS=i޵ MYt8+l]csIY{3,-iG><5$|Ɜy%\޽vWE o% ԂFU DGwF*&l=|],--4 >9!sȁG-m[t}R/ceP 1K6{|{ֿR aQE'Vԍ<4y-R$05^1xEuFgE~ 5w:q)ތﭫ"zo<]!r#e_|IDaƃo.:o+c??Á^Nxm 1ֹ)l5jL`9>_PR='w>xyPc[uwC=˂߆5.'לcܑܾK ZP}hBWB2l|l)_ȿ5-l++HpVpC}>RK\Net FTlES!:kw_<{P"8EZ"FJsҸ~|ܒ35 GN{US5̛r#T2 OڿN^:h]j"{.-vlΨdH}K^!+7|OW .% Gb]qKEG˰ }iQb´_(lPj'v>Rfn:23Tfg50Ogkn6=Qgv5?SzAuS%quͰݏ~A_v_n jR?-?"aO+t Z:tI*dL2ԏߘhmܒ/X3/~-74k#2Cͩ]EQK}zBIWw^?~~")J\&$b 2endstream endobj 25 0 obj << /Type /Font /Subtype /Type1 /Encoding 117 0 R /FirstChar 65 /LastChar 65 /Widths 118 0 R /BaseFont /DAFVBY+CMR8 /FontDescriptor 23 0 R >> endobj 23 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /DAFVBY+CMR8 /ItalicAngle 0 /StemV 76 /XHeight 431 /FontBBox [-36 -250 1070 750] /Flags 4 /CharSet (/A) /FontFile 24 0 R >> endobj 118 0 obj [796 ] endobj 117 0 obj << /Type /Encoding /Differences [ 0 /.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/.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/A/.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/.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/.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/.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/.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/.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] >> endobj 21 0 obj << /Length1 1586 /Length2 10789 /Length3 532 /Length 11713 /Filter /FlateDecode >> stream xUX\[;ݝpw5;=Kpww'еϗ9WtU]wQcS֪"'VT23:330D5 LL"@Cg ;[QCg  4]>ZU3r$WJTvGǵ'=SSha@"ߠ|(.}Nj\'qx(*(=]1,]hT u*a\mfcN fkoP`] dq˺Kn̻<7>L8  ܳfeA#Yj17! Oj_~BP?"ͥ!;)^5& ,5[,;iMPdz ؆BRig+b7>s :n"SPn~1G Sүx7c: 2ܘtA(fkUdq4eu݊_ 0uRVhsG_SLfs#`zIr .:M^0E`'hMYua|BEmWйd>xp`t#hXP|ae^Vurٶ.@_PuDj.w80犎b{ⱺeaT_1iycp*t5χ`]"x>KqiZYk@إϑZY۵e  Ed]wgfZ1/J5m Hv ?C ̸Yz4YhQIWw*M5O0?/][bVEZW!Khط֕:Ӿ^Џ(l&nna{_#>1+qTplݝf1$QI:U]yecR21$A6u8_s0˟=n%JkOPd83SeIUظYEg:3 fIGH733Ι#0Җ%mUH`dg#}aux#] wq c80rqgmz@󪱩Ih،Fr F)3ełL_7DwazjY-|f(Byt"/yl͵f"qt̡!q f2#m +=WEdl0߼&:ycmAwx {!P{ 7hwJSGi$MWx8<~uS:VoRΚO8 f%$=6\سoq-$sWpٹ?|Tw`,[|KZQ(J&Un&,W 2itĸr'Z lDp*0"UV;~ۨqy]B3,#ca- Vgޮ̆Gr^(ͻX۲:*  SO\n0̦R:ji' uDD%ivL|'E4c՛B:F 3aMmoD&F7F/xZNwI}2TDp!gzf_T)d #.AQBJؖk2{8?XMFkTϡׅޔz.Ϲ dE3<;lJwj;(QZPE{d y0{~4]! d\ƫP3X@/^ YBɇ}_z_B[Xs3#n3w) uݲ.-K;a)߃֖tǢ0m2%1$عϼ|&j*BAI.hMtbƥ'dGs6 H I_j\ ˞(a6]*4Cø?H{~OexBt V/%fn"h~ IhCN4T?`pK CMe ƺ@}~龎ޮy ią_UEsC 5%aAY'M-G^3C "З< Lsg)63DnG7sQTDèHbļO|T|O,I% 8; jo·WMT%/z-5\hHOLI\u &H %f+ h"])嫫6=rڵ*2\.k[Lw9w2;0Kq") CFM8i{s`$O %w! 'p=Ur~*Nu}0|gD: 7Hi f͑\#x[Ipv<pe-Oþq%o }U,qv"%LXԱcwXs k2VoȰ}򡬈J0apO3?XF>PVROoWE]XY/ĩF~Dϥ".!m1:} ͧc#E|x.DRl$x^GĴ3WJ26R?:ld\ TnQC+m{*4Bz/㧚|߾7m ei%B5-|!lYGx?yxdXvWX NrzcH{~휭C&"׋!R0פ+QC. |}Rx<cw̩< ZVʡ19֋Vx_#v a쫍 O!Ŋ^Ra.F`(б0phE^.QUk*-š.sE" !N )\^BL1y7h6SXzEDqe;0,,z5 Ne4|ÐF}x$f0rt'Rm&&hv=D vjCC}5ЯY[-3l:e*r'\'ż6]k meM rltNϐVJ"R e\!LK ` (bн]5Ly3:0 ,$1nsSe!6ӱmpW /֓5~CƘ%[zo ZWf3 Tʨb[ OCs8j''㐱я %L;Kt !hU @&6ؼF#regPi&܎ϣVTYZvig@Ɩ$X,{w55Φ#m*@g?@JeݠQַ)+ ޏVO3nmH>Xn6Rʘ1L):&;%cS& X|Ó H3dZS֤XYq YlM[Ӗ e/\09`#!%5[<5Eᵷ!Q֒4"$}<,'8:>_ K1y9 x({ 1 )3njF>K)!씐}?Wb{ vD(h veWT<#6VǢdDr@uYD֪thB He_L~ÎAUv ҢGڎ"E~4tL a̞&zJG\r&rQDɵlH|ċGpvЯuqHPVKj\Q>Fˀyndцlqz.`I!y 8֩~mf_DRI~hB%vAW=d7ˣ'%1릦N]ײOa$T0 AoYtlSȌ2IqցfJ",A kbg| Yb3?)fͱ5Jhu-L= L〇.޵ B8CŹ!;pYf$&m𪓍&#}]QnTrH?En?,h-,8[s8Ȁ5ue>U:mIvlZ@kAKZ**\``{T |#Eǎg]DPWP! 17 |"挏֤nQF'M;Q74-g5 C [~#M$1g<tDr(SZIf[W֌ Š5'8-Q%oE, [dY;^ԔӑF)zv:}ѯU~&cl)!:Zє]r>Wm' MM~8T.V{ RH LںeE~iKDnllM~b$)IBi Y@tj?c)O{~{ BRX fM~qҿW ӓzJ":1<~ݻ}GSԈGі92=jw/Q 1_OCT"nkK~[Tب?ֵEӫ߸$wk5&5BH~GR^,lMhI\7 ac jK\SD{`}c#"טּ5ֈW,owmlW2xo奆*KxӭIBFrx0T^\VOl2 %Ow,CN ΅$EYUjF1f#4"ENG4{kO{P{WY^kc'rnF|E Z~ъvi"E=4 Mt:"SÓߪ趛>:#j Aymm՗0E(2PPgev>9[ PBu*I. Yq ъ\OOHK`(8riĸ'2>|?)W=pi`Q\׸LlI|:5~Jw.!bBtIӕr7qחآ" 鍨16S%l!/;dגnr E#tVu8w"%Df=/]:O"{̢WLha$,v+u)g1Ln(&"E&n3g|SĜ O(yRtDV 4TUu4Ux2}hG,qZz\ exӺ%bkxTqIςOקW%WӶMu629^Alt\FRPKV7[8ٖD]f/,.NOTa.lef@w3dO7&FYd*?O>.sBpPv **yGnKu뾚'UfI4 s7433}JAьam?991 &s:R*LqFQi?h1ͦx2q#[ %v(cm_KyJ`ݤnd -Wb+X^YT{pパyoFt^8} pED\0? Ӏ1>B]|Y-xOl=O0(Z'ie>,&MorKG5{7Q3sF:ru'˓- '%bF4*t!`zCq#\KtzHj99<*ᥞkl S1R׶& -V3a]NSf[]CTE၆s J ƁC@ Z 1\3Q `)IK_};˻:YE;mtCf݈'`|3H1V%#{ TzP˰>;g_qFSu/v+DlU+rp:/? cK+1@Y҆`,ɀ+BV?J2JLoX,K-8;Zz_*b( |W # ϚSV xP7d2S{S)xIXDY5.=c]`hgQ~GJ{{|j"!eHBntr[! P|ajnrFMYL)MEh>%M6I 3Wu"RK~eY"ȬP9% c.;oilZWhᓸ`¬nh??{٥|PĀxhqeq*~tO?(O!ꖊk" mFdLncT$iP|Odmj %wR= YHbZiX%@삨uT k5asmg'BjdXIYÊǷ FI I)W 坧霰8 ^ufa5oRdWV k-sB"e[XJs҈/Uqr1I}7哽\jDpxGoXK9aT̜=qWU8vWu&g~{koQ 'eSO|VWڙo:`13=ř8xf!8+xcwOw}^>YygR6 DVMhнL8sO0Ͼә$,?ԞBt= R'1'RrqA}uFزM,{ P ClWRqo^WwD?2@M}?AvP>)i+5 Gb߷{B8UrA,?8Д O/e 6"]Ss| V:=:-h 곺#{)v=RH5D%  BNx6FNt7s\y^ò!jjҒ6m ꉊgr$2^S*[)7V=ÒCMwn2J0%n$@c?ڱE~^1C[O^Xߵ^W` ;;& Jʒ#plBvj9S cb`¥e[w\L8¡XƯY' qztZb_cEa'"/(IDJ+=pOΘ`f>!o#Iybv8֬Bډ$mv6L xuðM7PЃ\\'QEAmC#X,F@VVsB#һQB^>/' [ l /XDendstream endobj 22 0 obj << /Type /Font /Subtype /Type1 /Encoding 119 0 R /FirstChar 12 /LastChar 121 /Widths 120 0 R /BaseFont /NQATZQ+CMBX10 /FontDescriptor 20 0 R >> endobj 20 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /NQATZQ+CMBX10 /ItalicAngle 0 /StemV 114 /XHeight 444 /FontBBox [-301 -250 1164 946] /Flags 4 /CharSet (/fi/comma/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/at/A/C/D/E/F/H/I/K/L/M/N/O/R/S/T/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 21 0 R >> endobj 120 0 obj [639 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 319 0 319 575 575 575 575 575 575 575 575 575 575 575 0 0 0 0 0 0 894 869 0 831 882 756 724 0 900 436 0 901 692 1092 900 864 0 0 863 639 800 0 0 0 869 0 0 0 0 0 0 0 0 559 639 511 639 527 351 575 639 319 351 607 319 958 639 575 639 0 474 454 447 639 607 831 607 607 ] endobj 119 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/fi/.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/comma/.notdef/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/at/A/.notdef/C/D/E/F/.notdef/H/I/.notdef/K/L/M/N/O/.notdef/.notdef/R/S/T/.notdef/.notdef/.notdef/X/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/.notdef/r/s/t/u/v/w/x/y/.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/.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/.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/.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/.notdef/.notdef] >> endobj 18 0 obj << /Length1 1512 /Length2 8641 /Length3 532 /Length 9536 /Filter /FlateDecode >> stream xUX֠] \ݛk!H=k X%x!?;s.g~Wo[ꫧ4 N\@n(@VUrb21g'9Kw(("H{x@!Q~QAL& bk`e+I A@NUKw;# vA>i(n- ; l q襓3@_akyanp)+\ Wvv6'Aq{pcn'gw#xK60̿c+7 x@Ύ#;;ֿC<`  xܽ~ l񗉳w/5?2rnp57fkSx XאMl_?$ _o˽M*ʿ ^E7&x_g5k&xMxp5?[Wc@, v |%?.- \7N \kp ?? [yp+(y@/q'\Q{R~yyD<`0߷$B7@ a.;Z" *Pdl[{gB%] n+3 qPh(ݢ5B\<-2}) e_u~?DP^-O6,9:`G[{gԗ&$l }OZ)z ?-dhk6 .̑,OS}pnƮEo{S02^CdͲ\rd,TG'PRƁDwt>Oel]+貳0R+SV|l;lxHf2ֲf1>*+/χW7eи%+Fk0Fp\o^<MY znW*.m!OX!bo0U \\VI[c{7VYYDה@?:j hS8 XY2) t;RAunu.S8,YT   fdOjxyKObmpv `]\|vmT;yX6ff3hgLAևYcCLUUB@ᦶѭ +$qgZpxb˖n^ݗmBs%N3 (>g mANsg>TF*_W7Q|7!"Q>/Bϣpa-A4 l.4Is= 1OO.IanaC9E)9v ̬C\4 ׮*^1V)=TU\3XF>ck'|xTQv M/??f\+D5osBzx7/TE1$3)?1<4Ulv0Vg5Yej; ԮKReS0Y/'+'sIq2=4ą4;t:cU#`}'0w2cvPJ[sPe]]ҼuϊPՀr3DWK#:ks^Jy<ɯ9tKqrs<> "&yDvxǃ= yHSKқ;qH}}&t݅A*-w i8/B59*E Kxi1ϩ"d0`+iO49bn330=xӥ-}N\d6MҎLzפC|-Wtm(VT(1HBPP>`clL+ίeB&M;"Ήv LTl*oK7\Y@'ghE]yN~)ZGcuڋԋ&>FIc٤R>I;Ik٣B!BI׫޽R3~$Rg'c/=ya7TUF4Eăǘ^FBNҤ""M@}ˆ'vn*NJlz;3{c8(ҥ?Ve[C/i.1"m ^tαت[AvlQelkR#?Hgi+C(v<5%S "Ƈq3OF=3yjed5'ޅ x=|nY'^Ym^<=N99VLi 5_eʥ H_vB P<-ŹN(g; (gZ`{Q-}ӤՠMsud6fsXG9WbvO}IC*M:9+=%p==@N_9Lҙs43h8xAd q 8V_lIYhcBѯ>w]/,U"}Hy'A(|)A Ӓd\4 5:1$eaخwq:̂HB_. 5ʺ*GvF3?-2cy>*ibpkuai<Â\ %Ci񎴩_3SRD +y~mEֆ^9bYDY \{g.%-0Ģ4KeiPIk* $HtУC&fBENe@ -3@)j}@XdnUʼng,=(7FbJ*x5ڌj8$`wU'S$Å#?KڢOf]ګF_D02j$o@[EOTL {N;x]9ЂM$r;t(]-eO~X_ܠ} thB>ƒiY0u,PBLTvwx?meeҹ?ny ʝ3h1a8zl#;C| lҩ++fg;!߽N̪&z㶬A>qq}0&3*<-$Əi,si G˟9[˳UM%ja6HíHJc2ugC/;vzfO9ȼujOªY7k?2n-6.5w\Owr꾥t/{Ia}nwDZ \r--xEgȡ(,ґߴqO# ב蚹pNb>y5L'\_53hL)}ݠn$-̗Ƙ%+N6Uk;ulhOab۠' =#dwp=?4SȆ E۷Q`z J"HȞk'-L7g=V?n j3tI a2&f1[OyQנ46l]89u٦X$. ߣmQ3[z)tY&"-5G| RJ-ew3*^ָ!o J +o7oB}f3ZΨIӸ,b昅 XZ(vc+h,25d&PY|O8փA9ET-+{~sJ%(C0sEP[nPXfڼ+){r^p3ԫ=1 ?f^xʼnd(: >̘NusVUqB&TVɵ57_G V'-"b Kv+0b00JxY+߱gelV;|2 Fbᅯ|(x-Rn{ QNv6>Y#Yw*^a EAuzqPgԙ7 !|LBn{/~ XMiTw#>GtJx'%>EB ['«<*@-ey6l9ZB&GyJ({rgk~Z_'/ oK6Gmuʝ췉O\j }̕VY?v[Zu'Zum9|#S1Sԁh:|I&0jw[зdp 2b6Q )[^=D0j]-v}wUezc6yʱcmLQSJdPA  G⩢VFDbܤ ^Hfˮw,wLkRՙ69P+kW6Dܬ/fԎK_[΋R" by>Z#?u {B*Dz>R,x^U&b$mS6hqp+p ӣ&ß9+.~W1$WCfd}5)Uh捣/Q$կV+*/[yI0,}AH7+ O5k>,x=ljoU)ܪVg"٩+bzvͽq.'B_89t$0j҂ n1b8el7T$k\The4g,4t@gUB uVl4 DnakA_` V"RU"CŰKM)# *V1l/% /YHyH+֗bU6"g= O+"eG RSeV0v:50RٮXjDzǻl<a? Ţ4j=zyn\56 ;ဘɾfU?5.:w[BUFʸ 3 u0KO>`!y)օ lEHcۜ`Ulq:=(nF^aXR/vt#|m+rcYTJkq|y{(,V'e7-J-䞃)BJU2M:ZjZ\l#}q\J|n;՜ߏr[ >m|N G4v4~ۖZ.dNJ}S#IBV*v ~ܷ48䐮`Sv{zLSY!7=;Ć] *Y2ǾeR O,+Hrb1â a~ꭆ=a %jI>3BO]gp{Yc G(KAaќigg{Ղx_4poƊ :.QbR~CV3aq4jq) OgE^X7;BqnouR&>"I- 715^~p*#=lmftԻn rY;~ans9enn)\{tZ(hHcaAu-I۔"ohplcrwZ&̎Z}>%w%4LּRBdQ/?(R,}VUⷼ>ף`|W_ OwK[NVz`$ VH̎[Gy?TT_=<I5Bfj)0X4N^GV)Mp[s8$FK ot0P]2WQgn_̼\.{byJОAh%f} ԭ. KK^{;NgS,:|5"NQ,57ϰڳ/^-7ȩ0㙻2q[XnKBb5OF" SpY:1rT+x:3žb+5|6+:.96up<Ueڟ2)RnVPPm9ñ[}]<ŘNbhT/ p-ct=m_J.nuE A-o3Zg>LzgH#wV%⭾IVBOH: ́H8l1^S\6"HiɡoH4f$Y__|rqe,@,?m=^~\2"Qhd0W^􅾙㌄Kni]R~a]e_!+V~ǀĶTةhl=/{4eF"pr'0WS˻]07|Q%@p+I\}#cyB;trfS&[R>lKf*ޖ0HU@kjhP۫!Y +zdum8@ej:ӷJO}gƋ}CGyT/C$g}iV?.6IBB1WOL.#,!Qe$da)O7eu&Kko?,izgkzĴ8gO>fDLp6x.2v"$'m-Ul33 |]RxJ$𰂕^deB_Be3R}cʻ赋+=eC(> endobj 17 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /XBZPKP+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 /FontBBox [-53 -251 1139 750] /Flags 4 /CharSet (/fi/comma/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/at/A/C/D/F/I/K/M/N/O/R/S/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y) /FontFile 18 0 R >> endobj 122 0 obj [625 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 313 375 313 0 563 563 563 563 563 563 563 563 563 563 0 0 0 0 0 0 875 850 0 813 862 0 707 0 0 419 0 881 0 1067 880 845 0 0 839 625 0 0 0 0 0 0 0 0 0 0 0 0 0 547 625 500 625 513 344 563 625 313 0 594 313 938 625 563 625 594 459 444 438 625 594 813 594 594 ] endobj 121 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/fi/.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/comma/hyphen/period/.notdef/zero/one/two/three/four/five/six/seven/eight/nine/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/at/A/.notdef/C/D/.notdef/F/.notdef/.notdef/I/.notdef/K/.notdef/M/N/O/.notdef/.notdef/R/S/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/a/b/c/d/e/f/g/h/i/.notdef/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/.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/.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/.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/.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/.notdef/.notdef] >> endobj 11 0 obj << /Length1 2118 /Length2 15348 /Length3 532 /Length 16510 /Filter /FlateDecode >> stream xeT]ݲh[p='݃9{^{@^>kYXQN noBDM$"HD( GF&0r5rp1qq1llpdD"N.D"T$q ,M\,5LlTM,.DB66DL p8LᘘL-M\vp (Iٙq;lߗN@)"iR%Ml"(#=qFM$QR(#.2".r". !NVWC*X]!`u?5 X];addb p?yS 2CB&^_F`%ӿ#sBB`A!g N!P)3//Z@+h^h\B_rkHI.1TڐV_32{1!e8$x f 8Y!X S)BUf)tev FH:wm' J'Xa q8~\N <Ĵ2K1ɿ@_wۮKDi煠m5(Hi)PRJ[:ͮڜGԕ_pߞ)vf]~LLBnq|)Z' Ly</*݅qq =e~s2@bPW'\blkgKفC8RtjVAY),qTV\T׶$}٘-Eԓ8(|ԋ/ƣ:8s8y H3%h<\3dEvYWClA΍@/ùa TML0eCWضn}R/rmmX".VX$ yJΤ=iͺzbj0p蜺SBki~ĭDcCոq#/fe1&y`Y\buepra =DCG㲐9c[AZ6Pt+!vӾz\Mcę ^R%[,h<+.,V.& P} ,f?F{\m@=~ĘE wȿ}횰Q(3"a8o$ҍ.kEwFoz3W/(cm\ $tl:kF1E)SGճM\n+g(P&. A&9e0d&MW/ y teB$uQ)DvkM5NUtX~ډ?U;qk߬)DWIA7hVxV;SR)ng랠^)kD2^x]j6Qv @<`G3uNF&r&-ll: V\SwU= ɡ9,jU7nAɶ/Xs1~Tѝ/CyzPȳƃv%9݋⢞*3Z2|9E;y˜Cl I.UiHhrfڈ@;QgSz#}xArk\RR%Y]8>̨|;Sm&,79-:*7CdݹWB{dKUJ*6S{=y#KXI(  _IT j/ZVq*^}'*=x^B?mrGdr&@:Ej=?Gr){~W~v}Y~]s8 pdTЇj5t$\Cj{Ss>#7=):qQ6-X.w>2@YaЉ b,Іs"5"XE^dga 룝Dgxn$ 9CD*ˀ3vƤ|.$p :"R]֕CdBuO2T_Dٲ+~'g:vm"@cen~6uS܏zW x# >sëRn9J}fLԃcdZkl'/;5D4 [.t@оwhܻ̞Q} ldX:,7k25ͧ8qIC@,9> ZH|wy6 G[ŋIfq?K-bUX[l#K/'kRޭS іVAZJwl躍J/R} Y97"ՉnsoK,t.tvN~7J8 ]/6󤐴h: rUwfmfաgZ<<`_>: mGƬQE{ ԉq8o4#f6-eD+ZL 5GKx 3NpLnd=rR,cPhlפ#CKc\7Xu:f $nd9TyPC'%c\Ao@a;yfdful<ϰx _,Qg ^28dIfibsR*8RI$PehN&׺t jlM#2A ־\:JpJw" 71Jݘ5wme{kV b̬0NѕsNF7L_O'*^1|OYg#gs$+!J<QHfq2Lnѝ?%S`L3Ҿ^OieMoV0p<=ƻCO=j|=߯-T.W* e{oޑ{ z} [ jY`Fx+xԒ~tcdNqUT. El,oߎ8x)*XZ2;Ձ ZK`P{ Ōر~GNc}yt8}EC~kd5b1tX^YKPuw {FIQ_#t$jǎzN?/ʔtVr%Y&MSَ\M5r맦m_dtd_+6' &q ^cx$c}٫쉓]4#EWwj VKZ17AvvA謻J*XSkݳh42hc{Dzm'GwAD,Pȩ p0[YVc y#4o1Ѓ  ؇֏HR;0 ߣ B蚵3-Nsc~ ,I]YWT|kNzJK.(ݳS>%XX 2ߔ)N1cNW/l/lY-8_py1 ɠ ~ נ7foEnSXee` gatQ@o$\;AGj&V`#sMZ)Z⽪A-!ky_¿ zWiذ/k k6W#s4 k2nd$ni^V'rgo^5eqFԞyQ4KqZPd“a5i myRHYaC '! %WW}U>+U:Y$16D}7> LIE6 t u22.IzBcA0ϑw5i#I`b^e٤Tr@JQzJ:j.T.D.θ/V}c')wRtW5)-=-8Rh'Jh'#d9^1NFc)f)î/H+8zEn,G@lSspHE^# @2TÃC@PO5ږ9%f8فU"ӼG3 C""N=Kvxd#[Rg}d?-tyƷPīLYw\fa>^d1|яB2i>utqG|]Q,,TDiRL,mfCULvV_y޳Ay[Joh<^9bd٘ڐ9`v}/Wnvp qZ `nykdA2OM;_ə0CVi6{fYLG44N9 U;z`~ÈW0+67nkvSwFWXڧ2v;/*tQ:vyRZJ7N鲞/b+ d&CgCWպUgQ N!v|[sfUeg5 xHNO9ACIjAaW_1ߜn|R FRcVu2UG*ƚQ"7@5@B *!p˜ {)-@cBN⮥$mVV Q*%3u!o;LyvB/]dYA"r`t S`z(o@ ?ru=İ}%BG\w*rwm;?N{-}`u c@8TlĉFsP=Ng /! -%/r/s52ljA%kp$ KReaar4UIBI >wmL(E]׏pSV S'MT`ZXflLX' L~[$ 5{.$gu^hv0OV8/1c6]slNJd,`]#!WA}ƻSw湦ܤ _ 8P;E"xzM ; -d722@2zG9L=s7y)Qnkϯ+`e|X`3":)HntxXֲr>uP8ʜrpuuʥ7&P&$ϴG+N*a|S$62M*^V9=ǐ}b4q\y d֛ed'wBߍR h:@<0O'no QX}$k1*yŏOƬ}Xa`'fbkQSqgcg(.][}*֚I~L-2(uldž5j&Byl*&/mE0ru0K<Q!R~Sr'ؕ;.[Qm6䃛ol 0ߥ혴r>I K pbx?UP3Ϩ2o%m}t M ^-WA*^霹oDs~WU}SϪ\dgLC^M}gc݄ u/49Z_ }Irs8鹅Mvj])ZNڈLǃeDnX͎_ 7h\7K~2)k7' '5=44`L[S6))^>Rz˺UVu&j=c uF[9 hYCɀdKU CE0 Ú쉡(=ITXc4 4dep =,[Ct A@"꨺2Ac}':qjrبl!3R5e*|SjQswkP/D7 -gI_-V"$v|)lt_ Mg.y%rޕE{2*&OV(TdxZ3_ER:%_4˙C+us.*s{,1XEƜ8W(]3c6%Y-/L/֦ʑ=++|cʀT@DIgODzON|pabyVXc^y_DWG}gB*~@dwÌv`~܄ wUIul .$V bzs흢9MQ(hxunxֈN`LwROF\LVM{qyb/`f OA(+ Ȓ.Kɢ"H=uZduMr\L N^B)du㵘:&Tu]&]9{CڪK{ڦzP2ufR)}!Tbϒ *۠4SwR6PB.B3+B^\/ QzY t<˥(׵1|M s5i}b <0GR DxEҜݨGZ]Ȧ==U?,iΟQR&eSw@8[\!:;t6E49<J^3Zu' :Sow0B |a H4xmTJL%{CWAzWo{G65 }ph+C\IkCܷⅱmǘԱ8W)ד.˂X*Ibh72f6>jNgZu|$R |i4 2zؾ,*R&땍>VӘvޗpޕ:b;Kf"f8)B{3rFfgL#M mxaRU<`r(o NZuqCLD{mJ'8m?&ca7i yWQ֛O&fE4{l .Vٱ",$'LIboB#C9&S}vZz1X@JŽ܏wR"8_7ڗ`pQ{>'3Xul(Zl{ԃ^BrZ68E \? ahi%)fYon-T|U[B("7uº4AҴ u;F(I4 9UޘQ5dj6=s{k{jSB<-Rv ^, ϮpvH;xgxChc>ÀbgpIiz¼SdqUP9uB$prJrX,qLg ^)(@73ǻg;x ,mܑ";'3 D(2jOR61 `K~24,(>%-T8ŶWIrON g/u3:0<>wRrΧz7"`惷o2&T/acuD7:^BѩhTh s< \DO F`3v(\Pbro2UW/'7%]iq?T5W~H ,cc8sQ߾gh 2\$M85_N7aҴl4c~yG󘖱=$iF;{8XeL{ S7IkXyV 7YPBͳ4,HtB=4]-+#͖gݫѩ}D ;:)2?:_(. E8BLb2" F1Qye meU< E5[fYɭ[ `au:,sXg~Ӽbj\D؆ !l&S@*1 G*U?Q %NPЇ7ɾaP3RAɆoRH[i0($j9(쵇٤9_k̐]".e7ԆT $IN:"V3縲 J B{5>vVX;%b1$Zced g`Pm?ň\`&N'Zv/^a79|ey!nh?u|DCqTys Ѽǻi=鮴, 0Ǫ(5TϔK 6S$Q;$mWCYaz Nt+RqA5}ۏs_X[_&^[kJ0Kʰ+ %XϨh]j< >\:lpL[G1Ƿϭ6L:<װ#e j}cr#-w-": u?` 4>H}󗖍;F5v4^9B8M6e#xدj}7)%$9O3s=Un[{Ehl37|CC?$~{֒l'Xx 1UcNm~6gq0jTϛ7톟|" ְ4<*1&igi9-;N]M.hƯr9fwSjfq.  b5endstream endobj 12 0 obj << /Type /Font /Subtype /Type1 /Encoding 123 0 R /FirstChar 11 /LastChar 123 /Widths 124 0 R /BaseFont /PROATU+CMR10 /FontDescriptor 10 0 R >> endobj 10 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /PROATU+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/ff/fi/fl/acute/exclam/quotedblright/numbersign/quoteright/parenleft/parenright/asterisk/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/exclamdown/equal/questiondown/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/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/endash) /FontFile 11 0 R >> endobj 124 0 obj [583 556 556 0 0 0 0 0 500 0 0 0 0 0 0 0 0 0 0 0 0 0 278 500 833 0 0 0 278 389 389 500 0 278 333 278 500 500 500 500 500 500 500 500 500 500 500 278 0 278 778 472 0 778 750 708 722 764 681 653 785 750 361 514 778 625 917 750 778 681 0 736 556 722 750 750 1028 750 750 611 278 0 278 0 0 0 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 500 ] endobj 123 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/ff/fi/fl/.notdef/.notdef/.notdef/.notdef/.notdef/acute/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/exclam/quotedblright/numbersign/.notdef/.notdef/.notdef/quoteright/parenleft/parenright/asterisk/.notdef/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/.notdef/exclamdown/equal/questiondown/.notdef/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/.notdef/R/S/T/U/V/W/X/Y/Z/bracketleft/.notdef/bracketright/.notdef/.notdef/.notdef/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/endash/.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/.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/.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/.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] >> endobj 8 0 obj << /Length1 1205 /Length2 5728 /Length3 532 /Length 6511 /Filter /FlateDecode >> stream xe\mN$!EiafCB:n$D[TKs>~ڿ=חkk:Ŧg(`|UE"Ђ@! @I( pq)`4 P24f%dĤdDIJHg/ Q+I`0 FC A^B''_'\PW(j#Dl`4 ː: l;1`, N^- qWusr*א[ 9y$ E6P?SM 3; ;'(@_U у![+oOmA\PGQ_wL CW ͘` ! &襂 m`BK(؋0 B ј#LH_ ۡп1;cy @L7-H߅EhqqQ- [#`+& o$+&L/HcN7a2!)1?YA߯ "6  1@LO?cbb#b!@̜@L#ib **"=}@AQq @ZJ ).#`.nPuemHJV!n(lPO( rCJChJX)>]cNmd;iKlAM455VK&6_aս@5w4f&4m'[ Sűu'>$eo( \`pN!!idR-f@R [J|8Fv<('ɯ y iY=8*?5:?6"CXnL;>1 #,jzpѷ._(ha*cPZqy7 o5DHdQb]Iw=?gܑGV]ו~t4>K L(.UcqYc5(ʌ״+z×;ꆈJ W=/ћM*Am3ZD# V*]vqUڼ7~7I%X^%,Rr͜޽gQ2n<4I>4;͢ o1uxZi:}7j4մ9/=yxuzy<}˪9 0=3YE{':,np7o2tOmP.8T2 gx9 f2_5xPDF%L%X"t ;!T67[d'Q=ת;t`fkq89, ],IOBf Oҟ9st,o2Ƶ?'E$|8<䖯59jSip1L k(uTȧ mW]>ȘlwWU>J=xNm2/)Й,i^&;DleM2=qK4BMi$xJCur^$k$qqí 8[A_SH[@Eʻ<-L1@7pY`Zӛy1Zqy3{WX*KZ3\tw ጩ 7i[A3bYCLq-Qo54D)ؙ?gc))XkVي޻L+&~H['ya.]zoE|NĶnB+OٓcͬS7j?ǰ2HD桰Ͷ-]j jr$ [{DlXF=Ƨgx[vr䍸<2%+曦QRcHTTcSlArj܏;劊Ao,IvR{9NQk:J&%hS`ڢ>U|4z`HZ2@_0!Vͭ!t{+Uva|Ǯ6cIJE<=DG*)/U÷/ix';tE^0W# j?voj?puE]+tX a*rds=|K%Np_HQ;)[d  ǧ[~|ǺZWo鲙PYm,}y|˝;qcG7"s5+9HF5?wW&&;8}.YH{ZSWdDk9~;Y:ǙhjV#EԘyblkX %1OgٔjWH{j)}9[3ܫRmՈ\rEr&j{݌c쫶"RI"=Y%gͫiqTF|@ uG64D.#,^L6>мa_e˱verv:b>*^v%˖Y,ONnCVztϰ\x4pgPI"fnl"io\I喡WK뱠 gn+ͦdeè%/u^-qs Ƈ tԟZ,Io e^f7i$d?}%RE d$Rw֮ΟA?bn%h+@=ga:'l3 O@_U Aڲ/'ZZ`2'm!iMys~fWwˈ^n>oj{**Wsz@fXOQ P߷T"۰时B b'xÔ!?/&]iz2s :uQD>{H9jyb0f uyQ Vj6m-g-r4ǻ:^u|J[Ezq ^ݹ~#ƚ!r ⨌>.%"[D o=ě\wC)uI¼X\.4mf\Oi]vn]i> Wi2 ,׾.)U,ijZ`w6`K܀E:C$1g:V=0 =I[!\[u&mpec=jUK'cL!$PQj(Q+v;}m)zdOnu ϲI|jpծ^d%\O|5 G+i;.' &dJ h?/TK"Du hbN$^)!!dQwo/11> yO3&ȟJ#nZ})}SGdڥUe}^,%R e$nքVNjɊƓa/F_νGh* 」=R[$ OGF )f5?ZYMz|*~U2g:J_C>KK<_ "$ih(ֺK'*/3;j'l |b =k8q3mRwM׷[SSL.YۂnJMjs}C\&| ?X79m|,] 桧pFe&#">82'+&F|bVw)KGz82)My+%zO `_J)YTMxVe%>A/7>~@[rlC!nkTVhfBH'8[(z{`pη0qQmЌNpC >떡ܾs6cH~Lǰ_;Va>;<8:}U/4Tzw&Oj~]须9%se $;X3, !' :6Py´{Ts'jt5ITyz3IA5!={o gR 8'.3N^z'ߕx&h6keQCDZ=qfLKH@#'6}{6 m to7kR"C:uwjYkSUf`~aq,#bO/ }OIQK=\bljχ|X#W3pHƯF˜Фo j sR[p#>jhUd=rYJȝIy4ZG Io}o~wTu6oR$F6 e•#,q82J~j3|PbLLȜ>Km$َ:>3ϟ?p- /r5o3螆}P?WY{d6.IE$N[dK*aebR~|-> endobj 7 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /YMSNBF+CMR12 /ItalicAngle 0 /StemV 65 /XHeight 431 /FontBBox [-34 -251 988 750] /Flags 4 /CharSet (/grave/ampersand/comma/zero/one/two/four/nine/A/B/C/E/J/M/S/a/c/d/e/g/h/i/l/m/n/o/p/r/s/t) /FontFile 8 0 R >> endobj 126 0 obj [490 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 762 0 0 0 0 0 272 0 0 0 490 490 490 0 490 0 0 0 0 490 0 0 0 0 0 0 0 734 693 707 0 666 0 0 0 0 503 0 0 897 0 0 0 0 0 544 0 0 0 0 0 0 0 0 0 0 0 0 0 490 0 435 544 435 0 490 544 272 0 0 272 816 544 490 544 0 381 386 381 ] endobj 125 0 obj << /Type /Encoding /Differences [ 0 /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/grave/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/ampersand/.notdef/.notdef/.notdef/.notdef/.notdef/comma/.notdef/.notdef/.notdef/zero/one/two/.notdef/four/.notdef/.notdef/.notdef/.notdef/nine/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/A/B/C/.notdef/E/.notdef/.notdef/.notdef/.notdef/J/.notdef/.notdef/M/.notdef/.notdef/.notdef/.notdef/.notdef/S/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/a/.notdef/c/d/e/.notdef/g/h/i/.notdef/.notdef/l/m/n/o/p/.notdef/r/s/t/.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/.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/.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/.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 5 0 obj << /Length1 974 /Length2 3179 /Length3 532 /Length 3848 /Filter /FlateDecode >> stream xi<}-R.Z('3 ,3#ØaeK %2v~U%[HY*d{纮8NAS3)  %@Q `6-Aq"Z `@  JJ2rl"ޝD\s&Zߓ 74D#FD`3<& ,? ўh7%( 8aplqNx@᧌r+&xL4" Òډ d݅90{q]/,&['ED#< Mjx'" JO]/e!"'CGP.~<Lќw?ӺC6`i0BK}vGapAbm?Ph_K3 ቴ#'}rȝ6ůz-ň4.T;7zFI8}bkAvTn ""JTV~$ك)1s$A.,g'>yqod]eb㩠2 3Ts'J<)%awebķ=@^[=/,䓪O6M*HF7. {-.o—, E4 튅6dKg()l gw>ɘ9_rgc+zߖ7T)W1Y͆4>2/^9yυ:lЛR +ĉ\-ʼm 1,;!y2.J я qnwv\6L9P.aefhWNѡ=f߀结u՞//+6Ӧn˵)L]I|o?w#draX6+f@ ._ѝJ| ;rUVemri,ޡ!#sqY%&5ߢW6x32}|xg+1qvnwKQHD<ָ-,4褽jz%ʺS#/^ƏόDr5_>ɠѺ4h+̍x:fpMcC܉{M#?tO=:G% A/"oiLC;IK_> [wKQxjq)gV튦 EzH)GyJR=dk=}|hpu$iL=]m߸V4&iOBCI`W]b&=OА,XT3SSx鎂ٳJxVkV>[۷ޞّx$u#=3:WG%f_@r|pT`O>КB msΓמ[dj߽+x8ue,I?N*tjIhBR踥*^p NVc|" de,v)qA\]O/y>n_ƛD%qP3Iܔ dՅ%B|Qcr=()Ψ#k܉CtDSGj-0þ~V!H''kG51ΌgӪDKʡp8ߋKOvpkZY3ZXiExb-Qk{xB;#DyWyb# o4Y1Ы@ew9ŋl:+X]5]a7[19Cܴ լc*?>39fH>AdSF8yޚQ9LGr@ޘbVWbO ,X]<6Z0 *py>*gfW}6Ә]1 a*2W}^^Hil=κjPB{Z(ɢϺ27W nd,4xcȘ Im+57/Sʮ3W ʎE#CVʲ{EgnmBνLwЧKڬm*Q i#: ǥR{]bq7ZQ!M.-C'Jn}w#E??7/kl$zWZyEsQf%Ydb7عicWrà]y \x&2ON/g;w%{lpi%xvEl٤׌ ,6Å7nJyd?֛h,뉵RiFޱ͇/Vvz{W*t$upc|a@f>nvvصw7¿O :=+-#$V %xWe37JZԫFJ9KHίt(xEU}C m1yNeo?-aqBmi}佂b<\ ?>l-QE#D/[endstream endobj 6 0 obj << /Type /Font /Subtype /Type1 /Encoding 127 0 R /FirstChar 46 /LastChar 117 /Widths 128 0 R /BaseFont /PXVFRR+CMR17 /FontDescriptor 4 0 R >> endobj 4 0 obj << /Ascent 694 /CapHeight 683 /Descent -195 /FontName /PXVFRR+CMR17 /ItalicAngle 0 /StemV 53 /XHeight 431 /FontBBox [-33 -250 945 749] /Flags 4 /CharSet (/period/zero/eight/M/a/c/d/f/l/n/o/p/r/s/u) /FontFile 5 0 R >> endobj 128 0 obj [250 0 459 0 0 0 0 0 0 0 459 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 850 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 459 0 406 511 0 276 0 0 0 0 0 250 0 511 459 511 0 354 359 0 511 ] endobj 127 0 obj << /Type /Encoding /Differences [ 0 /.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/period/.notdef/zero/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/eight/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/M/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/a/.notdef/c/d/.notdef/f/.notdef/.notdef/.notdef/.notdef/.notdef/l/.notdef/n/o/p/.notdef/r/s/.notdef/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/.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/.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/.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/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef] >> endobj 13 0 obj << /Type /Pages /Count 6 /Parent 129 0 R /Kids [2 0 R 15 0 R 27 0 R 30 0 R 39 0 R 42 0 R] >> endobj 50 0 obj << /Type /Pages /Count 6 /Parent 129 0 R /Kids [48 0 R 52 0 R 55 0 R 58 0 R 64 0 R 67 0 R] >> endobj 72 0 obj << /Type /Pages /Count 6 /Parent 129 0 R /Kids [70 0 R 74 0 R 80 0 R 83 0 R 86 0 R 89 0 R] >> endobj 94 0 obj << /Type /Pages /Count 5 /Parent 129 0 R /Kids [92 0 R 96 0 R 99 0 R 102 0 R 105 0 R] >> endobj 129 0 obj << /Type /Pages /Count 23 /Kids [13 0 R 50 0 R 72 0 R 94 0 R] >> endobj 130 0 obj << /Type /Catalog /Pages 129 0 R /PTEX.Fullbanner (This is pdfTeX, Version 3.141592-1.11b) >> endobj 131 0 obj << /Producer (MiKTeX pdfTeX-1.11b) /Creator (TeX) /CreationDate (D:20040419220150-04'00') >> endobj xref 0 132 0000000000 65535 f 0000000440 00000 n 0000000328 00000 n 0000000009 00000 n 0000148083 00000 n 0000143960 00000 n 0000147926 00000 n 0000141448 00000 n 0000134661 00000 n 0000141291 00000 n 0000131944 00000 n 0000115154 00000 n 0000131785 00000 n 0000150537 00000 n 0000001769 00000 n 0000001654 00000 n 0000000531 00000 n 0000112620 00000 n 0000102804 00000 n 0000112460 00000 n 0000100281 00000 n 0000088287 00000 n 0000100121 00000 n 0000085969 00000 n 0000084022 00000 n 0000085812 00000 n 0000002864 00000 n 0000002749 00000 n 0000001875 00000 n 0000005006 00000 n 0000004891 00000 n 0000002946 00000 n 0000081312 00000 n 0000066345 00000 n 0000081152 00000 n 0000063840 00000 n 0000055794 00000 n 0000063680 00000 n 0000007469 00000 n 0000007354 00000 n 0000005124 00000 n 0000009370 00000 n 0000009255 00000 n 0000007563 00000 n 0000053254 00000 n 0000051459 00000 n 0000053094 00000 n 0000012218 00000 n 0000012103 00000 n 0000009476 00000 n 0000150646 00000 n 0000014259 00000 n 0000014144 00000 n 0000012324 00000 n 0000016318 00000 n 0000016203 00000 n 0000014353 00000 n 0000018208 00000 n 0000018093 00000 n 0000016424 00000 n 0000049023 00000 n 0000044833 00000 n 0000048863 00000 n 0000019699 00000 n 0000019584 00000 n 0000018314 00000 n 0000021394 00000 n 0000021279 00000 n 0000019793 00000 n 0000022932 00000 n 0000022817 00000 n 0000021500 00000 n 0000150756 00000 n 0000024810 00000 n 0000024695 00000 n 0000023026 00000 n 0000042513 00000 n 0000040580 00000 n 0000042355 00000 n 0000026792 00000 n 0000026677 00000 n 0000024940 00000 n 0000029067 00000 n 0000028952 00000 n 0000026898 00000 n 0000030278 00000 n 0000030163 00000 n 0000029209 00000 n 0000031988 00000 n 0000031873 00000 n 0000030384 00000 n 0000033749 00000 n 0000033634 00000 n 0000032094 00000 n 0000150866 00000 n 0000035449 00000 n 0000035334 00000 n 0000033843 00000 n 0000037352 00000 n 0000037236 00000 n 0000035543 00000 n 0000039713 00000 n 0000039595 00000 n 0000037458 00000 n 0000040509 00000 n 0000040391 00000 n 0000039820 00000 n 0000042733 00000 n 0000042709 00000 n 0000049424 00000 n 0000049260 00000 n 0000053682 00000 n 0000053480 00000 n 0000064403 00000 n 0000064105 00000 n 0000082227 00000 n 0000081857 00000 n 0000086187 00000 n 0000086163 00000 n 0000100983 00000 n 0000100632 00000 n 0000113302 00000 n 0000112961 00000 n 0000132890 00000 n 0000132475 00000 n 0000142005 00000 n 0000141727 00000 n 0000148509 00000 n 0000148315 00000 n 0000150971 00000 n 0000151053 00000 n 0000151164 00000 n trailer << /Size 132 /Root 130 0 R /Info 131 0 R /ID [<7642862A4CE41D90B9896340699319DC> <7642862A4CE41D90B9896340699319DC>] >> startxref 151274 %%EOF pasdoc/old_docs/pasdoc.tex0000600000175000017500000010063213034465544016256 0ustar michalismichalis% % pasdoc.tex % % Manual for pasdoc % Written by Marco Schmidt % Updated by Carl Eric Codere % % \documentclass[11pt]{article} \begin{document} \title{Manual for pasdoc 0.8} \author{Marco Schmidt \& Carl Eric Cod\`{e}re \& Johannes Berg} \maketitle \newpage \tableofcontents \newpage \section{Introduction} % This section is present in the wiki (more-or-less, i.e. sometimes in % different places with different words etc., but I think that all the % useful informations from this section are somehow kept in the wiki -- kambi) Pasdoc creates documentation for Pascal unit files. % equivalent paragraph is in wiki at the beginning of WhereToPlaceComments page Descriptions for variables, constants, types (called 'items' from now on) are taken from comments stored in the interface sections of unit source code files, each comment must be placed directly before the item's declaration. % This paragraph is rather obvious, will not be moved to wiki docs ? This way, you as a programmer can easily generate reference manuals of your libraries without having to deal with the details of document formats like HTML or \LaTeX. % This sentence is rather obvious, will not be moved to wiki docs ? Moreover, you can edit the source code and its descriptions in one place, no need to add or modify explanations in other files. The rest is done automatically, you should write a script / batch file that does the actual call to pasdoc... Download the latest version from \begin{verbatim} http://pasdoc.sourceforge.net. \end{verbatim} % This is replaced by section on CommandlineExamples page (at the end, % ,,PasDoc autodoc'') and PasDocAutoDoc in wiki For an example of source code that can be used with pasdoc, try the pasdoc sources themselves - type {\tt pasdoc[.exe] --format html *.pas} to generate HTML documentation. % equivalent (and much more elaborate and up-to-date) % text is in wiki on CompilingPasDoc You can compile pasdoc with Free Pascal (version 1.0 or higher), as well as with Delphi and Kylix. \section{Directives} % Sense of this section is present in the wiki. % Begin: Block below is in the wiki docs (on the ConditionalDefines page) As you may know, Pascal allows for \emph{directives} in the source code. These are comments that contain commands for the compiler introduced by the dollar sign. To distinguish different compilers, libraries or development stages, \emph{conditional directives} make it possible to make the compiler ignore part of the file. An example: \begin{verbatim} unit SampleUnit; {$ifdef WIN32} uses Windows, WinProcs; procedure WindowMove(H: TWindowHandle; DX, DY: Integer); procedure WindowPrintText(H: TWindowHandle; X, Y: Integer; S: String); {$else} procedure ClearConsole; procedure PrintText(S: String); {$endif} {$define DEBUG} {$undef OPTIMIZE} \end{verbatim} The {\tt ifdef} part checks if a conditional directive called {\tt WIN32} is currently defined (that would be the case for Delphi or FPC/Win32). If this is true, all code until {\tt else} or {\tt endif} are compiled, everything between {\tt else} and {\tt endif} is ignored. The contrary would apply if the directive is not defined, e.g. under FPC/DOS or Borland Pascal. These statements can also be nested. Using {\tt define} and {\tt undef}, a programmer can add and delete directives, in the above example DEBUG and OPTIMIZE. As pasdoc loads Pascal files in a similar way a compiler does, it must be able to regard conditional directives. All define and undef parts are evaluated by pasdoc, modifying an internal list of directives as source code is parsed. Different from a real compiler, pasdoc starts with an empty list of conditional directives. To get back to the above example, if you want to write documentation for the {\tt WIN32} code part, you must explicitly tell pasdoc that you want this directive defined. You can do so using the \emph{Specify directive} or \emph{Add directives from file} switch (see sections \ref{specifydirective} and \ref{specifydirectives}). % End: Block above is in the wiki docs (on the ConditionalDefines page) % Begin: Sense of block below is in the wiki docs (on the IncludeInSearchPath page) Next to those directives already presented, pasdoc also supports include files: \begin{verbatim} type TInteger = Integer; {$I numbers.inc} const MAX_FILES = 12; \end{verbatim} In the above code, pasdoc would parse {\tt TInteger}, get the include directive and start parsing the include file {\tt numbers.inc}. This file could contain other directives, types or whatever. It is treated as it would be treated by any Pascal compiler. % End: Sense of block above is in the wiki docs (on the IncludeInSearchPath page) % Right now PasDoc handles switch directives and $ifopt correctly. % The only really meaningfull switch for pasdoc is $M, and this is said on wiki % page ImplicitVisibilityOption. % So the up-to-date sense of paragraph below is present in the wiki. Pascal compilers also know \emph{switch directives}. These are boolean options, either on or off. They can be checked similar to conditional directives with the {\tt \$ifopt} directive. Pasdoc does not yet fully support these, but at least does not give up when it encounters one. \section{Adding descriptions} % Sense of this section is present in the wiki. % Begin: Sense of block below is in the wiki docs (on the WhereToPlaceComments page) You can provide documentation for \begin{itemize} \item types (including enumerations), \item variables, \item constants, \item classes, interfances, objects, \item procedures, functions and \item units. \end{itemize} Providing a description for the different items is fairly easy. You simply need to provide a comment containing the description before the name of the item itself. For units, the comment declaration must be done before the {\tt unit} keyword. Example: \begin{verbatim} type { This record type stores all information on a customer, including name, age and gender. } TCustomer = record Name: String; Age: Byte; Gender: Boolean; end; { Initializes a TCustomer record with the given parameters. } procedure InitCustomer(Name: String; Age: Byte; Gender: Boolean; var Customer: TCustomer); \end{verbatim} % End: Sense of block below is in the wiki docs (on the WhereToPlaceComments page) % Sense of this paragraph is in the wiki docs (on the WhereToPlaceComments page). % (and note that *all* output formats show *all* items now, % including undocumented ones; some reasoning is on the WritingDocumentation page). It is possible to specify that items will only be documented when certain comment markers are present at the start of the comment. Please refer to \ref{specifymarkers} for further information. Furthermore, undocumented items may or may not appear in the final document, depending on the output format. % Sense of this paragraph is in the wiki docs (on the LinkTag page). An interesting feature of pasdoc is its ability to link items from within comments. If you are currently writing about an array of integers {\tt TIntArray} you've declared as a type, you might mention that the number of values it can store is specified in the constant {\tt MAX\_INTS}. You've probably already documented this constant when you declared it earlier in the same or another unit. Now, if you write {\tt @link(MAX\_INTS)} instead of simply {\tt MAX\_INTS}, pasdoc knows that you are referring to another item it has found or will find in the list of units you gave to it. After all input files have been parsed, pasdoc will start substituting all occurrences of {\tt @link(something)} with "real" links. Depending on the type of output, these links could be hyperlinks (in HTML) or page references (in \LaTeX). If the current output format is HTML, the description of {\tt TIntArray} would contain a link to {\tt MAX\_INTS}. Viewing {\tt TIntArray}'s description in your favourite web browser you'd now be able to click on {\tt MAX\_INTS} and the browser would jump to the definition of {\tt MAX\_INTS}, where you'd find more information on it. If pasdoc cannot resolve a link (for whatever reasons), it will issue a warning to standard output and will write the content of {\tt @link()} to the documentation file, not as a link, but in a special font. \section{Formatting your comments} % Sense of this paragraph is in the wiki on the SupportedTags page All comments recognize special directives that are used for different purposes. Each of these special directives starts with the at character {\tt @}, followed by and identifier and optinally followed by text between parentheses. As an example, lets take the well-known {\tt DOS} unit. Its top part could look like this: \begin{verbatim} { @abstract(provides access to file and directory operations) @author(John Doe ) @created(July 12, 1997) @lastmod(June 20, 1999) The DOS unit provides functionality to get information on files and directories and to modify some of this information. This includes disk space (e.g. @link(DiskFree)), access rights, file and directory lists, changing the current directory, deleting files and directories and creating directories. Some of the functions are not available on all operating systems. } unit DOS; \end{verbatim} Pasdoc would read this comment and store it with the unit information. After all Pascal source code files you gave to pasdoc have been read, pasdoc will try to process all tags, i.e., all words introduced by a {\tt @} character. % Sense of this paragraph is in the wiki on the SupportedTags page If you want to use the character {\tt @} itself, you must write it twice so that pasdoc knows you don't want to specify a tag. % Up-to-date sense of this paragraph is in the wiki on the TagsParameters page Note in the example above that the character does not need this special treatment within the parentheses, as shown in the author tag at the example of the email address. Following is a list of all tags that you may use in pasdoc. A tag like {\tt @link} must always be followed by an opening and then a closing parenthesis, even if you add nothing between them. The following tags are supported: \begin{description} \item[@@] represents the @ character \item[@abstract] This is an abstract of the description (nowadays called "management summary") \item[@author] Treat the argument as an author's name and email address \item[@classname] PasDoc inserts the class name here. \item[@code] Treat argument as code example \item[@created] Creation date of item \item[@cvs] The argument is related to source versioning with e.g. cvs \item[@exclude] The current item is to be excluded from documentation \item[@false] PasDoc inserts the specially formatted text 'false' here. \item[@html] Inserts html code in the output \item[@inherited] PasDoc inserts the name of the ancestor class here. \item[@lastmod] last modified date of item \item[@link] The argument is the name of another entity, PasDoc will add a link to it here. \item[@longcode] Format the text and output it in fixed width font, with correct formatting. \item[@name] PasDoc inserts the name of the item (class, object, function, variable...) here \item[@nil] PasDoc inserts the specially formatted text 'nil' here. \item[@param] Treat first argument as parameter name and all following arguments as the description \item[@raises] Treat first argument as exception name and all following arguments as the description \item[@return, @returns] Description of a function's return value \item[@true] PasDoc inserts the specially formatted text 'true' here. \end{description} \subsection{@} Represents the {\tt @} character, for example if you want to use one of the tags literally \subsection{abstract} % This subsection is in the wiki on the AbstractTag page For some item types like classes or units you may write very large descriptions to give an adequate introduction. However, these large texts are not appropriate in an overview list. Use the abstract tag to give a short explanation of what an item is about. One row of text is a good rule of thumb. Of course, there should only be one abstract tag per description. The abstract text will appear in the overview section of the documentation (if the document format supports this overview section), and will also appear as the first paragraph of the item full documentation. \subsection{author} % This subsection is in the wiki on the AuthorTag page For each author who participated in writing an item, one author tag should be added. The format of the author tag should conform to the following specification : {\tt @author(Name )} Author tags will only result in documentation output for classes, interfaces, objects and units. Example: \begin{verbatim} @author(Johannes Berg ) \end{verbatim} \subsection{classname, inherited, name} % subsection moved to wiki PasDoc uses the tags {\tt @inherited}, {\tt @classname} and {\tt @name} as placeholders for the names of the ancestor class, current class and name of the current item respectively. Example: \begin{verbatim} { @name is a method of @classname which overrides the method of @inherited to do something completely different...} \end{verbatim} \subsection{code} % subsection moved to wiki PasDoc uses the tag @code to mark example code which is preformatted and should not be changed in the output. It will usually appear in a teletype font in the final documentation. Example: \begin{verbatim} {: how to declare a variable. Example: @code( var SomeVariable: SomeType;) } \end{verbatim} % ------------------------------------------------------------------------------ % kamb says: All the content above this line is already present in the wiki % documentation (i.e. it's sense is more-or-less preserved in some place % in the wiki). % Content below remains to be carefully checked. % ------------------------------------------------------------------------------ \subsection{created} This tag should contain the date the item was created. At most one created tag should be in a description. Created tags will only result in documentation output for classes, interfaces, objects and units. There is no special format that must be followed. \subsection{cvs} This tag is used to extract the last modification date and authors of the item. The parameter of this tag should conform to the $Author$ or $Date$ string of cvs or rcs. \begin{verbatim} @cvs($Date$) \end{verbatim} \subsection{exclude} If an exclude tag is found in a description, the item will not appear in the documentation. As a logical consequence, no information except the exclude tag itself should be written to the description. Whenever high-level items like units or classes are excluded from the documentation process, all items contained in them will not appear as well, e.g. constants or functions in an excluded unit or methods and fields in an excluded class. The following example will produce no documentation, as the entire unit will be excluded from the documentation process. Example: \begin{verbatim} {@exclude } unit myunit; interface procedure hello; implementation procedure hello; begin WriteLn('Hello'); end; end. \end{verbatim} \subsection{false} PasDoc inserts the specially formatted text 'false' here at the location of the tag. This tag does not have any parameters. \subsection{html} Pasdoc directly outputs the text that is between parentheses, without any conversion for the html output format. For other formats, the text is converted to standard text. There is no syntax checking on the validity of the HTML syntax. If there are no parentheses, {\tt @HTML} is directly written to the output documentation. \subsection{lastmod} This tag should contain the date the item was last modified. At most one created tag should be in a description. Lastmod tags will only result in documentation output for classes, interfaces, objects and units. There is no special format that must be followed. \subsection{link} Use this tag to make your documentation more convenient to the reader. Whenever you mention another item in the description of an item, enclose the name of the mentioned item in a link tag, e.g.\\ {\tt @link(GetName)}.\\ This will result in a hyperlink in HTML and a page reference in \LaTeX. \subsection{longcode} Use this tag to output code, and pre-formatted text. The output text will closely ressemble the text typed, and will be represented in a fixed width font. In the case of pascal code typed within this tag, it will be pretty-printed first. To be able to put special characters in this tag, the tag should be followed by a \# and finished with a \# before the closing parentheses. Example: \begin{verbatim} @longCode(# procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin // Note that your comments are formatted. {$H+} // You can even include compiler directives. // reserved words are formatted in bold. for i := 1 to 10 do begin It is OK to include pseudo-code like this line. // It will be formatted as if it were meaningful pascal code. end; end; #) \end{verbatim} \subsection{nil} PasDoc inserts the specially formatted text 'nil' here. This tag does not have any parameters. \subsection{param} Treats first argument as parameter name and all following text as the description of this parameter. Example: \begin{verbatim} { A small description @param(Filepath The file to open) } constructor Init(FilePath : String); \end{verbatim} \subsection{raises} Treats the first argument as exception name and all following text as the description for this exception. Example: \begin{verbatim} { A small description @raises(EMyException Raises this exception) } constructor Init; \end{verbatim} \subsection{return, returns} Treat the text in the argument as the description of the returns value of this function or method. \subsection{true} PasDoc inserts the specially formatted text 'true' here at the location of the tag. This tag does not have any parameters. \section{Switches} This is a list of all switches (program parameters) supported by {\tt pasdoc}. Enter {\tt pasdoc --help} at the command line to get this list. Make sure you keep the exact spelling of the switches, pasdoc is case-sensitive. Most switches exist in two variations, a short one with a single dash and a longer one with two dashes. You can use either switch to get the same effect. \subsection{Documentation file format} After loading all Pascal source code files, pasdoc will write one or more output files, depending on the output file format. Choose the output format according to your needs -- you might want to create several versions for \subsubsection{HTML} {\tt -O html}\\ {\tt --format html}\\ This switch makes pasdoc write HTML (Hypertext Markup Language) output. HTML files are usually displayed in a web browser, which available on all modern computer systems. It is the default output file format. Several files will be created for this output type, one for each unit, class, interface and object, additionally some overview files with lists of all constants, types etc. This is the preferred output for online viewing. It is to note that even undocumented items will appear in the final output file format. \subsubsection{htmlhelp} {\tt -O htmlhelp}\\ {\tt --format htmlhelp}\\ This switch makes pasdoc write HTML (Hypertext Markup Language) output. It also writes additional files that can be used to create Microsoft htmlhelp files. Please consult the htmlhelp Microsoft SDK for more information. \subsubsection{\LaTeX} {\tt -O latex}\\ {\tt --format latex}\\ This switch makes pasdoc write output that can be interpreted using \LaTeX. This is the preferred output format for printing the documentation. A single output file, either having the name specified with the {\tt -N} switch, or the default name {\tt docs.tex} will be created. With {\tt latex} you will be able to create a dvi file that can then be converted to a Postscript file using {\tt dvips}. Or you can also directly generate a huge HTML file by using {\tt htlatex}, or a PDF file by using {\tt pdflatex}. It is to note that the output generated by pasdoc has been optimized for {\tt pdflatex} and {\tt htlatex}. It is to note that only documented items will appear in the final output file format. \subsubsection{LaTeX2rtf} {\tt -O latex2rtf}\\ {\tt --format latex2rtf}\\ This switch makes pasdoc write output that can be interpreted using {\tt latex2rtf}. This is the preferred output format for adding the documentation to word processor documentation. A single output file, either having the name specified with the {\tt -N} switch, or the default name {\tt docs.tex} will be created. This file can then be converted to rtf by using {\tt latex2rtf}. This output will only work with the {\tt latex2rtf} tool. Using other tools might not produce the expected results. It is to note that only documented items will appear in the final output file format. \subsection{Format-specific switches} The following switches can only be used with one output file format and are useless for the others. \subsubsection{No generator information} {\tt -X}\\ {\tt --exclude-generator}\\ By default, pasdoc includes some information on itself and the document creation time at the bottom of each generated HTML file. This switch keeps pasdoc from adding that information. \subsubsection{Specify name of document} {\tt -N NAME} {\tt --name NAME} When the output format of the documentation is not HTML (such as latex, or CHM), this specifies the name of the final name of the documentation. If this is not specified, it uses the default{\tt docs} filename. \subsubsection{Specify footers and headers to use} % Text equivalent to this subsubsection is present in wiki % (on FileAsHeaderOrFooter page) {\tt -F FILNAME} {\tt --footer FILENAME} {\tt -H FILNAME} {\tt --header FILENAME} You can specify texts files which PasDoc should use as header or footer for all generated html pages. This option is only available for the html output format. Example: \begin{verbatim} pasdoc --header myheader.txt --footer myfooter.txt \end{verbatim} \subsection{Comment Marker switches} \label{specifymarkers} % This subsubsection is present in wiki (on CommentMarker page) It is possible for pasdoc to ignore comments that do not start with the correct start markers. By default, all comments are treated as item descriptions. This can be changed using the following switches: \begin{description} \item[{\tt --staronly}] Parse only \{**, (*** and //** style comments \item[{\tt --marker}] Parse only \{$<$marker$>$, (* and // comments. Overrides the staronly option, which is a shortcut for '--marker=**' \item[{\tt --marker-optional}] Do not require the markers given in --marker but remove them from the comment if they exist. \end{description} \subsection{Output language switches} % This subsubsection is more-or-less present in the wiki (on OutputLanguage page). % The fact that ,,stdout is always in English'' is *not* stated in the wiki, % and in fact it may change some day. % Of course the list of languages is much more up-to-date in the wiki. {\tt -L lg}\\ {\tt --language lg}\\ You can specify the language that will be used for words in the output like \emph{Methods} or \emph{Classes, interfaces and objects}. Your choice will not influence the status messages printed by pasdoc to standard output -- they will always be in English. Note that you can choose at most one language switch -- if you specify none, the default language \emph{English} will be used. The {\tt lg} parameter can take one of the following values: \begin{description} \item[ba] Bosnian (Codepage 1250) \item[br] Portugese / Brazilian \item[ct] Catalan \item[dk] Danish \item[en] English \item[fr] French \item[de] German \item[id] Indonesian \item[it] Italian \item[jv] Javanese \item[pl] Polish \item[ru.1251] Russian (Codepage 1251) \item[ru.866] Russian (Codepage 866) \item[ru.KOI8] Russian (KOI-8 \item[sk] Slovak \item[es] Spanish \item[se] Swedish \end{description} \subsection{Other switches} \subsubsection{Include / Exclude class Members by visiblity} % Sense of this subsubsection is present in wiki (on IncludeByVisibility page) {\tt -M}\\ {\tt --visible-members}\\ By default all non-private fields, methods properties are included in the documentation. This switch permits to change which items of the specified visibility will be documented. The possible arguments, separated by a comma are: \begin{description} \item[{\tt private}] \item[{\tt protected}] \item[{\tt public}] \item[{\tt published}] \item[{\tt automated}] \end{description} In the following example only the private and protected members will be documented, all others will be ignored. \begin{verbatim} pasdoc --visible-members private,protected \end{verbatim} \subsubsection{Output directory} % Sense of this subsubsection is present in wiki (on OutputOption page) {\tt -E DIRECTORY}\\ {\tt --output DIRECTORY}\\ By default, pasdoc writes the output file(s) to the current directory. This switch defines a new output directory -- this makes sense especially when you have many units and classes, they should get a subdirectory of their own, e.g. {\tt htmloutput}. \subsubsection{Read file names from file} {\tt -S FILE}\\ {\tt --source FILE}\\ If you want pasdoc to write documentation for a large project involving many unit source code files, you can use this switch to load the file names from a text file. Pasdoc expects this file to have one file name in each row, no additional cleaning is done, so be careful not to include spaces or other whitespace like tabs. \subsubsection{Change verbosity level} {\tt -v LEVEL}\\ {\tt --verbosity LEVEL}\\ Using this switch in combination with an integer number $\geq$ 0 lets you define the amount of information pasdoc writes to standard output. The default level is 2, this switch is optional. A level of 0 will result in no output at all. \subsubsection{Show help} {\tt -?}\\ {\tt --help}\\ This switch makes pasdoc print usage hints and supported switches to standard output (usually the console) and terminates. \subsubsection{Specify a directive} \label{specifydirective} % this subsubsection is present in wiki (on ConditionalDefines page) {\tt -D DIRECTIVE}\\ {\tt --define DIRECTIVE}\\ Adds {\tt DIRECTIVE} to the list of conditional directives that are present whenever parsing a unit is started. The list of directives will be adjusted whenever a directive like {\tt WIN32} or {\tt FPC} is defined or undefined in the source code. Each define should be separated by the others by a comma, as shown in the following example: \begin{verbatim} pasdoc --define debug,hello,world \end{verbatim} \subsubsection{Specify an include file path} \label{specifyincludefilepath} % Begin: Sense of this subsubsection is in the wiki docs (on the IncludeInSearchPath page) {\tt -I DIR}\\ {\tt --include DIR}\\ Adds {\tt DIR} to the list of directories where pasdoc will search for include files. Whenever an include file directive is encountered in the source code, pasdoc first tries to open that include file by the name found in that directive. This will work in all cases where the current directory contains that include file or when the file name contains a valid absolute or relative path. It is possible to use this switch more than once on the command line. \begin{verbatim} pasdoc --include c:\mysources\include --include c:\3rdparty\somelib\include \end{verbatim} \subsubsection{Specify directive file} \label{specifydirectives} % this subsubsection is present in wiki (on ConditionalDefines page) {\tt -d DIRECTORY}\\ {\tt --conditionals DIRECTORY}\\ Adds the defines specified in a file {\tt DIRECTORY} to the list of conditional directives that are present whenever parsing a unit is started. The list of directives will be adjusted whenever a directive like {\tt WIN32} or {\tt FPC} is defined or undefined in the source code. There should be one defibe per line in the conditional file. \begin{verbatim} pasdoc --conditionals /home/me/pascal/myconditionals \end{verbatim} \subsubsection{Set title of document} {\tt -T "STRING"}\\ {\tt --title "STRING"}\\ This option sets the title of the output document. The characters in the title should be enclosed in double quotes. By default, depending on the documentation format, the document contains either no title, or the name of the unit being documented. Example: \begin{verbatim} pasdoc -T "This is my document title" \end{verbatim} \subsubsection{Include uses list} {\tt --write-uses-list}\\ PasDoc can optionally include the list of units in a unit's uses clause to that unit's description. Example: \begin{verbatim} pasdoc --write-uses-list \end{verbatim} If a unit in the uses list is part of the documentation, it will be clickable in the output. By default this option is disabled. \subsubsection{Full link output} {\tt --full-link}\\ This option controls the behaviour of "@link(unit.procedure)" type links. If it is set, the output generated will look like this: {\tt unit.procedure} with the "unit" part linking to the unit and the "procedure" part linking to the procedure inside the unit. If it is unset, then the output will only be {\tt procedure}. \subsubsection{Non documented switches} This lists the other unusual switches that are recognized by pasdoc: \begin{description} \item[{\tt -R, --description}] read description from this file \item[{\tt -C, --content}] Read Contents for HtmlHelp from file \item[{\tt --numericfilenames}] Causes the html generator to create numeric filenames \item[{\tt --graphviz-uses}] write a GVUses.gviz file that can be used for the {\tt dot} program from GraphViz to generate a unit dependency graph. \item[{\tt --graphviz-classes}] write a GVClasses.gviz file that can be used for the {\tt dot} program from GraphViz to generate a class hierarchy graph. \item[{\tt --abbreviations}] abbreviation file, format is "[name] value", value is trimmed, lines that do not start with '[' (or whitespace before that) are ignored \item[{\tt --aspell}] enable aspell, giving language as parameter, currently only done in HTML output \item[{\tt --ignore-words}] When spell-checking, ignore the words in that file. The file should contain one word on every line, no comments allowed \item[{\tt --cache-dir}] Cache directory for parsed files (default not set) \end{description} \section{Known problems} \subsection{Documentation of program files} As was said before, only units are regarded by pasdoc. In an OOP environment for which pasdoc was written, an application is usually a class overriding an abstract application class, so all code that is ever needed in the program file looks like this: \begin{verbatim} program main; uses myapp; var App: TMyApplication; begin App := TMyApplication.Create; App.Run; App.Destroy; end. \end{verbatim} So there isn't much to do for documentation. If you're not using OOP, you could at least try to move as much code as possible out of the main program to make things work with pasdoc. \subsection{Records} % this subsection is no longer relevant, pasdoc handles records perfectly now Pasdoc cannot create separate documentation for members of a record. In object-oriented programs, records will not appear most of the time because all encapsulated data will be part of a class or object. However, you can give a single explanation on a record type which could contain a description of all members. \subsection{Non-unique identifiers} In some larger projects, identifiers may be used in different contexts, e.g. as the name for a parameter and as a function name. Pasdoc will not be able to tell these contexts apart and as a result, will create in the above-mentioned example links (at least in HTML) from the argument name of a function to the type of the same name. \section{Adding support for another output format} If you want to write a different type of document than those supported, you can create another unit with a new object type that overrides {\tt TDocGenerator} from unit {\tt PasDoc\_Gen.pas}. You'll have to override several of its methods to implement a new output format. As examples, you can always look at how the HTML and \LaTeX generators work. First of all, you must decide whether your new output format will store the documentation in one (like \LaTeX) or multiple files (like HTML). \section{Credits} Thanks to Michael van Canneyt, Marco van de Voort, Dan Damian, Philippe Jean Dit Bailleul, Jeff Wormsley, Johann Glaser, Gudrun Plato, Erwin Scheuch-Hellig, Iv\'{a}n Montes Velencoso, Mike Ravkin, Jean-Pierre Vial, Jon Korty, Martin Krumpolec, Andr\'{e} Jager, Samuel Liddicott, Michael Hess, Ivan Tarapcik, Marc Weustink, Pascal Berger, Rolf Offermanns and Rodrigo Urubatan Ferreira Jardim for contributing ideas, bug reports and fixes, help and code! \end{document} pasdoc/old_docs/Makefile0000600000175000017500000000016713034465544015725 0ustar michalismichalisdefault: @echo 'No default target defined in this Makefile' clean: rm -f pasdoc.aux pasdoc.log pasdoc.toc pasdoc.dvipasdoc/LICENSE0000600000175000017500000004310213034465544013500 0ustar michalismichalis GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pasdoc/ChangeLog0000600000175000017500000006271213237135164014252 0ustar michalismichalis2018-02-08 v0.15.0 * @links to enumerated type members work now. * New @includeCode tag https://github.com/pasdoc/pasdoc/wiki/IncludeCodeTag (by Silvio Clécio) * @longCode and @preformatted improved to better honor indentation. * parsing "experimental" directive. * Allow to customize HTML output more, with your own CSS and HTML, by --html-head, --html-body-begin, --html-body-end command-line params. * HTML output is now HTML5. * Add our tools to the binary release: pascal_pre_proc (Pascal preprocessor), file_to_pascal_data, file_to_pascal_string. * Improve CSS and HTML, in particular for accessibility and mobile browsers. Among many improvements, we removed fixed font size in pixels, changed some tables into divs, and fixed HTML validity around Tipue search box. * pasdoc_gui uses now default font size on your system. * Updated Spanish (Spain) translation (by Guillermo Martínez Jiménez) * Tipue works now more efficiently -- the (potentially large) "index data" is only loaded on the "Search Results" page. * Automatic tests rearrangements and simplifications (see tests/run_all_tests.sh). Authors: Michalis Kamburelis and contributors mentioned above (thank you!). 2015-08-09 v0.14.0 * Many fixes to parsing "deprecated", "platform", "library" directives. * simplexml output fixes (by Denis Grinyuk) * The document creation time is not printed in the docs by default. Use "--include-creation-time" to show it. --include-creation-time is orthogonal to --exclude-generator. * The build duration time is not printed in the output by default. Use "--verbosity 3" to show it. * Brazilian utf8 translation (by Alexsander da Rosa) * Upgrade tipue to 3.0.1, update jquery to 2.0.0. * Fix Delphi compilation (long generated tipue code) (thanks to Marcos Rocha for investigating) * Add pasdoc_gui icon (by Karl-Michael Schindler) * Copyrights and docs fixes (thanks to Paul Gevers) * Various other small fixes and code cleanups. 2013-07-14 v0.13.0 * Handling of declarations nested inside classes (of other types, classes, constans and such) (by Arno Garrels) * Handling HelpInsight comments (by VCejka) * Parsing Delphi attributes (by VCejka) * Parsing "final" standard directive (by VCejka) * Tipue search upgraded to latest Tipue version, fixes problems in Google Chrome in some cases (by Michalis Kamburelis) * Parsing of "deprecated", "platform", "library" directives for properties (by Michalis) * HTML ouput changes (no more , so external links/bookmarks work naturally; tipue search input+button layout corrected) (by Michalis) * Mac OS X version includes the GUI. * Many other small fixes and improvements. 2010-11-03 v0.12.1 * Parsing Delphi operator overloads (D2006+), Delphi anonymous methods (D2009+), Delphi class and record helpers (by Arno Garrels) * Fix handling source files that start with UTF-8 BOM (closes: #3101708) (and clear error messages when encountering UTF-16 or UTF-32 BOMs) * Cache files get version markers (closes: #3101524) 2010-10-31 v0.12.0 * Class Hierarchy diagrams are more complete, because PasDoc knows about hierarchy of the standard ObjectPascal classes. You can also extend this by --external-class-hierarchy= option. See [https://github.com/pasdoc/pasdoc/wiki/ExternalClassHierarchy] (by Michalis) * Support for Delphi Unicode compilers, improve processing speed by using TBufferedStream, parsing some new Delphi features (like "deprecated 'string'") (by Arno Garrels) * Many improvements to pasdoc_gui: * Better adjusts to various themes and font sizes, on all platforms * More intuitive UI: "Generate" button on the left, "Output directory" on the "Options" tab and filled by default with temp directory, and more. * xdg-open is used on Unix now. (by Michalis Kamburelis) + --ignore-leading= option, see [https://github.com/pasdoc/pasdoc/wiki/IgnoreLeadingOption] (by ) * Translations: * Russian localization updated by * Simplified Chinese Translation updated by Liu Da * Czech translation by Rene Mihula * Polish translation updated (by anonymous) * Bulgarian translation by Andrew Andreev * French translation updated (and utf-8 version added) by Yann Merignac (see [https://github.com/pasdoc/pasdoc/wiki/OutputLanguage]) 2008-06-22 v0.11.0 * Various fixes to parsing by Richard B. Winston, including fixes to Delphi 2006 syntax parsing and library files. PasDoc now parses Delphi 2006 RTL and VCL sources. * Various pasdoc_gui improvements, including * "Display Comments" tab (by Richard B. Winston) * Many options already available in command-line pasdoc are now in pasdoc_gui too * "Store relative paths" option * Proper "Save" command on Ctrl+S (doesn't always display SaveDialog) + @image tag (by Grzegorz Skoczylas and Michalis) (see [https://github.com/pasdoc/pasdoc/wiki/ImageTag]) + @include tag (see [https://github.com/pasdoc/pasdoc/wiki/IncludeTag]) * program files are now parsed (their "uses" clauses are shown in output) (by Mark de Wever) * @( and @) construct (see [https://github.com/pasdoc/pasdoc/wiki/TagsParametersMatching]) + pascal_pre_proc tool (using PasDoc scanner) + simplexml output format (by MfG TAK2004 and Michalis) + --auto-link-exclude option (see [https://github.com/pasdoc/pasdoc/wiki/AutoLinkOption]) * Translations: + Chinese gb2312 translation by Liu Chuanjun * Polish translation updated by Grzegorz Skoczylas * Hungarian translation updated by Gergo Jonas * Updated Spanish translation from JBarbero Quiter + Mac OS X (Darwin) port * Many bugfixes. Authors: features above not explicitly marked by author were done by Michalis Kamburelis. 2005-11-26 v0.10.0 + New command-line options: --auto-link (see [https://github.com/pasdoc/pasdoc/wiki/AutoLinkOption]) --implicit-visibility (see [https://github.com/pasdoc/pasdoc/wiki/ImplicitVisibilityOption]) --no-macro (see [https://github.com/pasdoc/pasdoc/wiki/NoMacroOption]) + New @-tags: @bold and @italic (see [https://github.com/pasdoc/pasdoc/wiki/BoldAndItalicTags]) @seealso (see [https://github.com/pasdoc/pasdoc/wiki/SeeAlsoTag]) @inheritedClass (see [https://github.com/pasdoc/pasdoc/wiki/InheritedClassnameNameTag]) @preformatted (by Ascanio Pressato) (see [https://github.com/pasdoc/pasdoc/wiki/PreformattedTag]) @orderedList, @unorderedList, @definitionList, @item, @itemLabel, @itemSpacing, @itemSetNumber (see [https://github.com/pasdoc/pasdoc/wiki/ListTags]) @table, @row, @rowHead, @cell (see [https://github.com/pasdoc/pasdoc/wiki/TableTags]) @noAutoLinkHere, @noAutoLink (see [https://github.com/pasdoc/pasdoc/wiki/AutoLinkOption]) @tableOfContents (see [https://github.com/pasdoc/pasdoc/wiki/TableOfContentsTag]) * Dashes rules: em-dash, en-dash, short dash, "@-" (see [https://github.com/pasdoc/pasdoc/wiki/WritingDocumentation]) * FPC macros are now correctly parsed by pasdoc. * Each detailed description in HTML output is enclosed within gray frame * Various fixes. E.g. * --spell-check-ignore-words works now. * @links to @anchors and @sections work always now. * Many improvements to pasdoc_gui (by Richard B. Winston and Michalis) * back-comments (see [https://github.com/pasdoc/pasdoc/wiki/WhereToPlaceComments#head-7ce7157fefbd0d84d3577aa636f758baa813e201]) Some compatibility had to be broken: * New dashes rules break compatibility. But actually previous behavior with regards to dashes was broken, because "-" was just always directly copied to output. So previously in HTML "-" always meant just a short dash (there was no way to write en-dash or em-dash). And in LaTeX "---"/"--"/"-" meant em-dash/en-dash/short dash, but there was no way to escape it (i.e. there was no "@-" construct). * Back-comments feature breaks compatibility if you have comments that have as their exact 1st character "<". Now they will be interpreted as back-comments (assigned to previous item with "<" stripped). To fix your docs, just add a space inside such problematic comment right before "<". Authors: features above not explicitly marked by author were done by Michalis Kamburelis. 2005-07-09 v0.9.0 End-user visible changes: + New command-line options: --auto-abstract (see [https://github.com/pasdoc/pasdoc/wiki/AutoAbstractOption]) --introduction and --conclusion (see [https://github.com/pasdoc/pasdoc/wiki/IntroductionAndConclusion]) --latex-head (see appropriate part of [https://github.com/pasdoc/pasdoc/wiki/CommandLine]) --link-gv-uses and --link-gv-classes (see [https://github.com/pasdoc/pasdoc/wiki/GraphVizSupport]) --link-look (see [https://github.com/pasdoc/pasdoc/wiki/LinkLookOption]) --sort (see [https://github.com/pasdoc/pasdoc/wiki/SortOption]) --use-tipue-search (see [https://github.com/pasdoc/pasdoc/wiki/UseTipueSearchOption]) --version (see appropriate part of [https://github.com/pasdoc/pasdoc/wiki/CommandLine]) + New @-tags: @br (see [https://github.com/pasdoc/pasdoc/wiki/BrTag]) @latex (see [https://github.com/pasdoc/pasdoc/wiki/LatexTag]) @section, @anchor, @title, @shorttitle tags in introduction/conclusion (see [https://github.com/pasdoc/pasdoc/wiki/IntroductionAndConclusion]) @deprecated (see [https://github.com/pasdoc/pasdoc/wiki/DeprecatedTag]) @value and @member (see [https://github.com/pasdoc/pasdoc/wiki/MemberValueTag]) + pasdoc_gui, a GUI alternative to console pasdoc version. + Spell checking (see [https://github.com/pasdoc/pasdoc/wiki/SpellChecking]) * Cache is now independent from output format (see [https://github.com/pasdoc/pasdoc/wiki/CacheOption]) * Many fixes and improvements to HTML output, it's now structured a little more consistently, it's more configurable by CSS, it's 100% conforming HTML 4.01 Transitional. * Many fixes and improvements to LaTeX output, it's also structured more consistently, and it doesn't omit undocumented items (see the bottom of [https://github.com/pasdoc/pasdoc/wiki/WritingDocumentation]). * @longcode improvements: it's now formatted in LaTeX output, the look of float and hex values inside @longcode in HTML output is configurable by CSS. * Parsing improvements: * Better full declaration of items is now displayed in documentation * FPC overloaded operators are now parsed * Delphi hint directives (deprecated, platform, library) are now parsed * You don't have to enclose tag parameters in parenthesis (see [https://github.com/pasdoc/pasdoc/wiki/TagsParametersWithoutParenthesis]) * Many many other small fixes and improvements. Many internal improvements, like: + We maintain a large set of tests (regression tests, conformance tests etc.) in pasdoc sources (see tests/README file in pasdoc sources and [https://github.com/pasdoc/pasdoc/wiki/RegressionTesting]). Documentation: You can find the most complete and up-to-date documentation of pasdoc features in our wiki, [http://pasdoc.sourceforge.net/]. Unfortunately, with pasdoc 0.9.0, offline documentation (previously in docs/ directory of released archives) is no longer provided, this is intended to be fixed in future releases (see [https://github.com/pasdoc/pasdoc/wiki/ToDoOfflineDocs]). Some compatibility had to be broken: * pasdoc.css will be always overwritten when you generate HTML documentation. You must use --css command-line option (see [https://github.com/pasdoc/pasdoc/wiki/CssOption]) if you want to use your custom css. * By default no items are sorted. You must use --sort command-line option (see [https://github.com/pasdoc/pasdoc/wiki/SortOption]) if you want to change this. * @links look now a little different, see [https://github.com/pasdoc/pasdoc/wiki/LinkLookOption] and [https://github.com/pasdoc/pasdoc/wiki/LinkTag], use --link-look=stripped if you really need old behavior. Authors: many. See @author tags at the beginning of pasdoc 0.9.0 units. 2004-07-12 v0.8.8.1 to v0.8.8.3 Johannes Berg, others + applied a bunch of patches that were floating around on the mailing list + some code cleanup 2004-05-06 v0.8.8 Johannes Berg, Richard B Winston, Carl Eric Codere + fix a lot of tiny bugs, range check errors, etc + implement consolidation for // style comments so that you can now use // style comments in multiple lines like this: // @abstract(something) // and a real comment and both lines will be added to the documentation. + @longcode tag implemented (fixes bug #802469) + \LaTeX output 2003-11-20 v0.8.8-pre6 Johannes Berg + fix 3 logged bugs [ pasdoc-Bugs-842325 ] bug in function IsMacro [ pasdoc-Bugs-844324 ] tag "returns" very together does not insert a jump of line [ pasdoc-Bugs-844325 ] The tag "return" does not work, "returns" with "s" if + corrected output of @raises tag (last character could be cut off) + javi fixed and updated the Spanish translation + added proper warning for FPC operator overloading as it is not supported right now. TODO item: write a ParseOperator function + added support for FreePascal inline "calling convention" 2003-08-04 v0.8.8-pre5 Johannes Berg * more CSS, completely new style 2003-05-14 v0.8.8-pre4 Thomas Mueller + more CSS + code cleanup + if class has no description, write ancestor's description and a warning + reordering by visibility + @param, @returns, @raises except argument in parentheses now 2003-05-09 v0.8.8-pre3 Thomas Mueller/Johannes Berg + write complete known hierarchy in class descriptions - remove calling hhc.exe, you should do this from a script + fixed HTML-Help output + fixed numeric name creation wrt. cross-links (there was a rather BAD bug, now all numbers are sequential too!) + automatically turn on numeric filenames for HTML help because hhc chokes on extra dots in filenames + bugfix: "~" is a valid character in a URL 2003-05-02 v0.8.8-pre2 Thomas Mueller/Johannes Berg + better HTML output with CSS + HTML output has new section links + fix hierarchy: objects descend from TObject, interfaces with GUID are now shown properly 2003-05-01 v0.8.8-pre1 Thomas Mueller/Johannes Berg + hierarchy is shown properly with everything + name directive for imported functions parsed properly + proper HTML entity encoding 2003-04-20 v0.8.7 Johannes Berg/Thomas Mueller Based on Ralf Junker's changes, I did the following: + added enumerated type parsing + made work with FPC + records (handled like classes), + case statements in records + nested records + spell-checker for linux (currently disabled, use an older CVS file of RunHelp to use under Kylix, will not work in FPC, need advice) + new option-parser + uses delphi streams instead of files. Supposedly does not work on all platforms FPC runs on - need advice + commentmarker (for example only {: comments ) + declarations like "var a: function(x,y,z:Integer):Integer cdecl = nil" are parsed correctly + dependency plotting with GraphViz (AT&T ) (not very useful) + uses clause will be included in doc (optional) + links "http://", "ftp://" etc. are recognized automatically + varargs directive + abbreviations "@author(johannes)" can be expanded to @author(Johannes Berg <...>) via abbreviatons file + @cvs($Date ...$), @cvs($Author ...$) is recognized and used for lastmod / author + duplicate authors skipped - name search doesn't look into classes any more, if a method reference is needed outside the current class then the class has to be specified: @link(class.method) (faster and less error-prone) + HTML output uses unitname.classname.html instead of numbers, but has option to make number-only-filenames (for short-name filesystems) + class member visibility can be specified in output + long option names (see PasDoc --help) + images are no longer carried in a .RES file but in include files instead, as constants in code, for FPC Some time inbetween... (0.6.21 to 0.8.6) Ralf Junker - LaTeX documentation removed - see http://zeitungsjunge.de/delphi/PasDoc/History.htm for more information. 2000/04/20 v0.6.20 ms - added Rodrigo Jardim's translations of pasdoc's output to Brasilian Portuguese; new switch -b (and --brasilian) - increased STEP from 32 to 128 when reallocating description pointers, this makes pasdoc crash less with RTE 216; bug must still be fixed by changing GetMem's default behaviour 2000/04/17 v0.6.19 ms - fixed bug that prevented pasdoc from skipping code until an $else conditional directive (thanks to Michael v. Canneyt for reporting this bug) 2000/04/12 v0.6.17 ms - added Marc Weustinks Dutch translation to pasdoc; switch -m (or --dutch) now creates Dutch output - successfully created docs on Delphi 5 rtl\win directory (222 seconds, 16 MB html files on a P-II 350, 256 MB RAM) 2000/04/09 v0.6.15 ms - added Michael v.C.'s update of the tex unit (changed chapter/section/ subsection nesting of LaTeX output) - moved LoadDescriptionFile and LoadDescriptionFiles from main.TPasdoc to gendoc.TDocGenerator - worked on external description file loading - email addresses in author tags are now displayed as mailto links in HTML output - hard-coded HTML colors in body element (already added colors for tables etc., as long as the whole thing is not CSS-based, it's better to have all colors defined so that unusual default colors of a browser won't ruin the overall impression) - released 0.6.15 2000/04/08 v0.6.13 ms - released 0.6.13 2000/04/06 v0.6.13 ms - fixed bug that made pasdoc ignore a unit that has ). in a type declaration; in scanning.pas, ). was supposed to be a replacement for ] while it must be .) - empty author tags are now ignored - fixed LaTeX bug that kept pasdoc from converting identifiers that were not found in the list of items to output format style 2000/04/05 v0.6.13 ms - added -u DIR switch to make pasdoc search for include files 2000/04/04 v0.6.11 ms - moved objects.pas to directory 'other'; will now use default objects unit from FPC - for the time being, I stop trying to compile pasdoc with Delphi, there is some bug I am unable to trace; Delphi 5 compiles pasdoc without problems but crashes when running it on appinfo.pas between the second and third constant for no apparent reason; I will try to fix bugs that are more obvious in the near future... - fixed bug that made default keyword after a property appear as a field of that class (thanks to Andre Jager for pointing this out) - fixed bug that made pasdoc crash on an empty author tag: @author() (thanks to Michael Hess for finding and isolating (!) this!) - made pasdoc skip property declaration; property parsing needs some work, I will do this soon 2000/04/03 v0.6.11 ms - created sourceforge.net account; pasdoc is now at http://pasdoc.sourceforge.net - modified homepage to have frames; single page has become too huge 2000/03/31 v0.6.11 ms - on a totally unrelated note - I just passed my exam in theoretical computer science - woohooo! again some time to work on pasdoc... 2000/02/11 v0.6.10 ms - changed directory structure of the pasdoc project (added src, bin, man etc.) - added -v (or --verbosity) switch to be able to change the amount of output 2000/02/08 v0.6.10 ms - added PDF version of manual to homepage, thanks to Martin Krumpolec 2000/02/07 v0.6.10 ms - arguments in functions and procedures no longer become links if there is a type of the same name (THTMLDocGenerator.WriteCodeWithLinks) - HTML now writes Class, Interface or Object (translated to the chosen language) in front of each CIO item in a unit's summary of these items - removed some unnecessary methods from THTMLDocGenerator in html.pas 2000/02/06 v0.6.10 ms - added Catalan and Spanish translations sent in by Ivan Montes Velencoso to gendoc.pas and corresponding command line switches in main.pas - removed tabularx environments from TTexDocGenerator (for LaTeX output) - added equivalent long command line switches for most of the short ones - added check that will detect unknown (=> invalid) command line switches and react on them with an error message - received pasdoc DOS binaries sent in by Jean-Pierre Vial and created a 0.6.9 DOS binaries release, then updated the homepage - added IOResult check in TFileInputStream.Open in filestre.pas; no more crashing on non-existent files - added explanation for non-unique identifiers to manual; may find a workaround for this later (bug?) - fixed bug that made the time in HTML documents always be 00:00:00 with the Delphi pasdoc version - started new unit chars that will be the basis for the handling of special characters in other languages 2000/02/05 v0.6.9 ms - integrated fixes sent in by Erwin Scheuch-Hellig (no more destination directory in HTML overview file links, path names of source code files are no longer dropped, destination directory gets a terminating slash) - renamed this file from History to ChangeLog - updated homepage and freshmeat appindex 1999/11/26 v0.6.9 ms - pasdoc now seems to work with Delphi 5 1999/11/17 v0.6.9 ms - updated French output TDocGenerator.GetFrenchString in gendoc.pas 1999/11/16 v0.6.9 ms - added support for user-defined line feeds 1999/09/28 v0.6.8 ms - improved TeX output 1999/09/27 v0.6.8 ms - continued work on Tex unit; TeX output working again partially - added -j switch to suppress headers and footers in Tex output (Johann Glaser's suggestion) 1999/09/24 v0.6.8 ms - replaced numerous calls to WriteLn with PrintLn from new unit Msg - moved TPasdoc to new unit Main 1999/08/16 v0.6.7 ms - fixed bug in main, wrong parameter (units instead of file list) - fixed bug in TTokenizer.SkipUntilElseOrEndif that would choke on unidentified directives - fixed some bugs in TParser.ParseProperty 1999/08/15 v0.6.7 ms - continued implementing handling of @descrfile tags 1999/08/10 v0.6.6 ms - fixed property index parsing bug 1999/08/08 v0.6.5 ms - HTML declarations of functions, procedures, methods and properties now contain hyperlinks - started adding support for descriptions in external files 1999/08/05 v0.6.4 ms - added support for $ifopt directive - added support for resourcestring key word (now handled like constants) 1999/08/04 v0.6.3 ms - added -s switch to read file names from text file - manual updated, large part added - made HTML doc generator suppress Properties section for objects (which never have properties) - fixed bug that made HTML generator write no empty method section for C/I/O - added @exclude() tag to disallow inclusion into output 1999/08/03 v0.6.2 ms - various fixes - initial property parsing and output 1999/08/02 v0.6.1 ms - made 'include private fields / methods / properties' switch work - added dates, author to classes / interfaces / objects - cleaned up TDocGenerator - moved STATE_xxx constants from unit Parsing to Items 1999/07/29 v0.6.1 ms - rewrote part to support different output languages (TDocGenerator.GetString now calls TDocGenerator.GetStringEnglish etc., each language gets its own GetStringXXXX function) - integrated Jean Dit Bailleul's French translation 1999/04/27 v0.6.0 ms - added support for directive file switch -f 1999/04/18 v0.6.0 ms - added support for getting ancestor list in objects / classes and skipping interface ID in Delphi-4-type interfaces; now Delphi 4 d4system.pas and d4sysuti.pas are parsed flawlessly! 1999/03/11 v0.6.0 ms - replaced platform.inc with version from latest FV snapshot to detect Delphi 4 - added CompVer unit to store compiler name / OS / bits - moved TItem and descendants to new unit Items - started adding support for interfaces (Delphi 3.0+ feature) - added a stripped-down version of Objects to work with Delphi (Delphi command line compiler dcc32 now compiles pasdoc, but execution results in runtime error 103 at the beginning); don't use this Objects for anything else, only TCollection, TObject and TSortedCollection (IIRC) will be used! ????/??/?? v0.5.? ms - added test.pas to test pasdoc functionality - changed switches to one letter - added --version and --help switches - added -d switch to specify conditional directive on command line - added new units Scanning and Tokenizi for decent support of conditional compiler directives - created a basic pasdoc.tex file that will be the manual - added applications pastype, pasdep and pasconv (no functionality yet) which will use the Scanning unit 1999/02/25 v0.5.2 ms - moved TPasDoc from parsing.pas to pasdoc.pas - added fields Language, DestDir and Units to TDocGenerator 1999/02/24 v0.5.2 ms - created scanning.pas 1999/02/22 v0.5.2 ms - unit Parsing exceeded 3000 lines of code, so I moved TText from unit Parsing to new unit Texts 1999/02/11 v0.5.1 ms - fixed several bugs - HTML links - property parsing - class parsing - some changes in tex generator - added support for German docs 1998/12/10 v0.5.0 ms - added "nogeneratorinfo" switch 1998/12/09 v0.5.0 ms - continued work on ExpandDescription 1998/12/08 v0.5.0 ms - first entry in this history file - restarted work on pasdoc after 2-3 months... - now pasdoc can only create one type of output each time it gets called, not multiple - TGenDoc.WriteDescription copies all data byte-wise to output stream; replacing of links and special characters is done in additional procedure TPasDoc.ExpandDescriptions to be called after TDocGenerator.BuildLinks and before TDocGenerator.WriteDocumentation pasdoc/.gitignore0000600000175000017500000000247313237135764014474 0ustar michalismichalis# Output dirs and files bin/ lib/ source/autodoc/html_by_pasdoc_gui/ source/autodoc/html/ source/gui/pasdoc_gui # FPC / Lazarus generated stuff *.o *.ppu *.compiled *.or *.lrs source/packages/lazarus/pasdoc_package.pas # Emacs backup *~ # Tests temp stuff tests/correct_output/ tests/current_output/ # Resource files are binaries containing manifest, project icon and version info. # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. *.res # Type library file (binary). In old Delphi versions it should be stored. # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. *.tlb # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. # Uncomment this if you are not using diagrams or use newer Delphi version. *.ddp # Deployment Manager configuration file for your project. Added in Delphi XE2. # Uncomment this if it is not mobile development and you do not use remote debug feature. *.deployproj *.dproj # Delphi compiler-generated binaries (safe to delete) *.exe *.dll *.bpl *.bpi *.dcp *.so *.apk *.drc *.map *.dres *.rsm *.tds *.dcu *.lib # Delphi autogenerated files (duplicated info) *.cfg *Resource.rc # Delphi local files (user-specific info) *.local *.identcache *.projdata *.tvsconfig *.dsk # Delphi history and backups __history/ *.~* pasdoc/www/0000700000175000017500000000000013034465545013316 5ustar michalismichalispasdoc/www/screenshots/0000700000175000017500000000000013034465545015656 5ustar michalismichalispasdoc/www/screenshots/html_class.png0000600000175000017500000031126213034465545020524 0ustar michalismichalisPNG  IHDR pHYs+tIME  v߰tEXtCommentCreated with GIMPW IDATxw\Ggww:GE *RD^b7&j_zM71hb{QTHqn A~9vggyyffgv@ @ Ƚ U@ @ C @ r4MQIEQE4 AEQ0 EQA[G@  hi fsKKJP){ @ <==95r6 @  h$ITQQAttt ˅zL2J d*//7Xڙ+++ȡ @  pVpp 4)0999"(00FPűX,oq 4 AHp@ d "5660$F _x׷LJ(/(`@ d;̆@NBaB!AET~썢(@V!@ 6L|>:{>o6-4M|N @ 0AP{fSտ8 @  t9*r,{f@ %~} |.}o~~&O J0p @  `զ.ZNQG}j[~ѧ67+,|W{X;9Uig0s|(o'#@ @ (TӆX; $Ihun3iO=|+oH3o} ٳ/|R^ #GΞ5˫oYz[vf"gzl+@c dm/j tVE $I}쌑^=C @ w lM^}'t?g%ɒSe0Nf~ÏH[x-{; 20vk/AoFJe@Ǚq, o!@ 9y|Q/_{}H(?g6{=2EQj5 Hq'I-*hy?kjkxUyBgGӴR%bk Amxogfs|xZ^mEӴZgj΍JM!@ MwE%q}}/:|hrytd$oVW\FDHpЋ=;$&flw?xS0^Ǟv[S[+x6ok}.Q#xʙDm Li3&M|g`?$믖>HUu `qY F㚟~ڵ(A0 oWziʂ~XmTde;V-圙9NؕDMR!G1,x/iгO~A8 @ 0%Ќ V;wtLT"Y@F5_{cǖM:_?oٜ+W*RLIJ/]̸[?v3O[4޵~7^w͏}`¸Z1֙Dm 0x\(Gٽw_vΙD"pw,#O=շ}| Da=o[XAqnEQIW[U@.(Z7m=Vbph@ pm {fԨ=3rnMM'N9z'}ZfXU]Ǧ͊f" FcP`@\P=lhl7IMMJ%MJr-33^xid6 yyyf޽`e>`Jr(M<=c&Y|JvΙcF3KI{{,@`@{Kk[Tbיt|Y "((RTi`k@  t(ɫ;w8ܹJ%= {{0M&}Kʚ[jjk:.,4侙3vu|aƄfΐ{;:rFd25$Ga;jĈ_׭/)+$Il{ᮯ3^|@B_9 &:WO9Η=E Tl3FwJP4MS\.{rʚJh ]8 @ p"9=xqk3M3򕫇 ܿc׮;wmݑ%KysƳޚ A`|9={ M&sr"wv<<7)pnҍ={L(uZC5 @ |N_=#O^M_zq_ vmiie:D2!m< ,4Eѳ -EG.]r D &p0ou !bHn1_wE )J(Jł^E@ @2gWx|#kVxwW$. ڵ^V^q!c\d.uF)4$V۱sd67*ǎ ݷV1'xϟ3{ӟ[\!CWUmؼebFzDX )1q{N>8v n͸yD|3:EѰs Ϟ/dY/Yܾ}PTMKMq aJҸ{d:՚Z&>?Pt  u"YwVNHlmk/_1b+/^Yzŵk|񙟯cղt,!)PߗQ@ @ ;KĒ򲲈HOI' {u'|~ʸq }& Ç 3Z6>u]?/OϽ;pG˖.;[\a#`qӯz+7$82!֘3:GZ33;΄0@ 2A^|Ů\׮UlsV}_{m9`ɒeu"haa'ڕJY*@ӴSպyA--bH"d6fmT(bL*EyJE[Wo8A>Yf/?pnڌaO?j*ؠ@ @ +_{A$} .7s BPh홸d.2meY܇Dm D_zzzWz)N.mp@ ;`{W\7<rq;\߮Uj@ 6@IvX @ 7!;+A @ wV1 eW{A @ )~? d_s{ux1@  Cff&T'%%СCAg-b"##!@ V @ r?\@ @ t!@ 0@ @ w @"l6@`-J@Ph4U  @xakhnmnni*@ : ^  ]4=hll R @ gX5 r/@`-p@V#:شЅ JGZNբlJlF$I0 x~MSK*@ 2J>@_?kW3̈́ ,8Tu8Gt+Еu.FI ~t ^RePZHʼD"0 AEoBQEQh4kXoЗ_+U*]=#\~5P Z j 2`" {T˝ ;YiԔ._Lq77T}Զ)L z& .Eq;`wRi,5ی P &b??j4A; Q*56ø=KܻkڳRSlNYՊx؂C A`VثmHu4\N˕1(S읿ЕZ/2hڢKƎN\TS9'G !iXء6H0< C z]'/,LscΟ- rV2^\@uM_[n+| ~oi^懜3;U;d+F=8u),[OZ11>\]-pۙό4K(⸸2#5]L(. T_3}d2e9?"~^5,+ vuuyg,AUcG%AS$E2\nDR<8dPf6id22='*Z;)q:dw?cu##KwS#EQf%a9~sΜ2iozZssj}~qbXQ/<[YU?@3b$iۺ7ztG7ppI]ݾe]{ŭhdVoB2Q9ٲ1e`o]L;UnQ"7{yzM6S$1Wz;>ur.fO2W^Fl֬(n۱%#-#$8۬%н 6;z4uM*fmv]tƎ-ZKQQŵ\i+c   4MsؘȔT}Ιq9ׂ;0LӀ"J#Y"Ҡ#Q5 sC}FS5'h @ 'ON{55Ii(&M&ŵ}Y,q)ovaĉSGX䜜2iP b_ERKNnNxXXfkERƟ?w62*jƴYe%93& ѐ555y{{3cAt{HP_z5&&:ʋ6寢(>iahjeRSxD0K0g4ݨP8)(pf3&=-b0=Faث/`-Rb]F4eND"U6q$I̬h/d<.ג^ŶwWW͸IaU9aKb lJAqtvItuuS'S, pwρljd3ul dӭ^;30[ZZ|>nGr^Svt2l *Λ%<6m6yr /k{ꚚGou" bX]o4S4>#iT4n9 Bh؞[n3EF 5 IDATpTRZ1!`TutwS]z V7~9SN\mG>cfP^Qq⥨K1;ܲ+A @hAQEQ&o%?r>7T0$őҳgk9ʵYmSMhDVWc<emNΠo Ւju'aFiACcY7ǎMPt!kg֤0 Ox&tƄJZ(זrEPH@Q6X,;Z7%R3(fBAѦdqZ۲O&'|t2Fڋ/S`'Mi땟O4U4|&#rbP$-[hRڝ5s}h4޻C&vsy!!aPVXlޟ46E9`{zxٿ+%i|Ee [}:64 "gP&`ǟZRH?aO9dh4~ŗ7͞/=lRb"๗_/8˚ot \RR2cv% (0O>dڵV핖dl6qiI/]Rk46Kjjk?㸧@nb$LLS|eۺ;Z- a/?Av>C ߪWDG[ϱtMJI_}S^QADhH+/`F{!$ɴLdG.{Q6W327sFiYYŵaC~63kONMrm]͟Ǹe/r?nɸ+Y6F*e]0?ǧ$g՛T''S\RSJ O&Ć[w~q=Ml-M{9ZK>:hޙƧWOm2Ez1!swli,NuZ <^HFb-}ThΞ/ x֮敒+WvT(,$4~X%[4M=w¥K8 |Pt́*  )Iゃf܌l.`,APBrfE{U jSVA.e-8r!1O5Qi4  m%z=^q= q CJi}85i55RT{-ذa"p'N׫+2QF)I(EjTU/w Tk;/4(ZZ 5M(x|*5áz3=ftju'$$=QwDѣftXyd: Aqɻsn?O&zO="*J,23&ޓPړ51cґc::R,3Pv?,m%!H]\\||| / C srOWTT]G  hڐ///Fcsg/~$^{Mn}mO$J$o<3 cݿp!MMͯzk?rYfXp_׭~Uax,",oVo>h2|ϿzoHnS g"7>k,7TZJȤ҇.  j_}+j_lNLZB:Сǻ. ҝ>3>%eTT*uRl@mmn͹JO>aO]Z^_zC<ÕG%Xy7<Yv>I$O_uU fg Ϛ1}p̠ڏ>|?t6~gz-NE?}&Je~^ٳf>haŵkL{E&E,xO Ν}oWu׿-  h4fmw M {~|X]5S3vL]~͕+왞i+"û&yo|7kVg|5l(>uJ֮y`B@gggNn;ESqy:SOڳNYչ=?mGilTguVAo/g5ZmΙ+WKM HomCZj\,.5czjbGX0ϯօ*'ۘs,s&e hJ,,!N#h2(K*0O`Œ?8.LxVsZ%Ӧܽ'Cձe&%Ɍi5s"ƧN8xhbbws{EX7c̸?y,8(xԈ4MpLΡBCÒ{0W`T*d2Y}}=EQTV@`]!bب#֥`~457>z瞝xe>zCKd^]9~H$9|Du=^_0w *"",4AR~i73&q8u…aqCgN1RqS/ ), ɻHc]{]*;_0ᇖuSaKUUim_& Z7BpRmGZ˲\;f=\Y{MOLB#G ӟ[-Y|L&."mFֶs2CYw۞8)FIHxdqBPfࠫzlfD|oXRZOE۔x|0=|X\77sWʘΛ83}-БcǙU<[l)6J /Y,7YA7)'kD2gzK[vҥnmE^^#3p}}öt頨ࠠ},^AG1eRkF딢RֶչMn[43gkUA & O?񸽂jO pwgпڰ#nyzz(JOU(/E@0w?ԡ%,p;00:4$4&:ĩ,~EPLᣇJK'OrmvZxti쯗^ئ=CP-;b7tY-w}}3'^0(2r|J20 Ϟ*/ esIYy[[3U`FS~ZʸqL0bDYyŵʑÇCs3zH@O]UMLœija]gqd0oI0w VaO:J.!{K3ME"@Q;RvDD$C|D%# WF۩16.T^/'(R"2*Uqـ:k'tkx|.N8A1ڡT̀6FŤ944@(ʤFVO4tА^pƍK>jaJR*U &#-F{LU;A]~ͫ#K2uג« Eܽ͝;KթӧL3X1q=II u>r?vϳgIKMOKM+D:iҔIJ *gРAjbN8wgSSSTT)/p++aLu7XG7rRS\W2{w$9:!rkQ?kIYYTdDק<=5!̟n(ɻa`׮$74֦b0Y*kjz&7o?m/8{nRf<ΪB:CSbwKAcFTVUfS]a6#~uSKimѺ:0qn&t|9Ƨ25q)VEQV:M︭͖Ce^]6}ꔯWڵȈ F"hu%eAt o'YئAe2#=p<}}|,zy\\\W7_lP(h4 E-w`ČIU/<8dHlUu%%%yzx66*8p']t!aԘ~a ^bI_D||?oI}&O9W Z̛rimk  ,8wh4:EѴ"( 0z2+ \aUAj w庑n\>/*% ̩<~U"hd ϥҒYa+]}>tŔ&oF4;e[4w\NmE8z#Wc~@BYG R:HHWbш,ֵyh>_86rSO̟Ap:dq=<'O۽'kʔimmEE33R1plMQYoTT*4@]dR6A4 4x"Q@ߵ* u6yq ɿVog$KJq\1H1c8vw\gB*-.EbXಌJtY}cܓ/>mS;@o$)ړ% ZC?9 D>DDD{yyxpp݂{vI[wزm?~)I y:tY{u^l;2@,Sffi۟1 ;~]ueI矛6y۷[2 nl]Ez%E][LjC._3yvb>e3SֺVKNqCFwP I3@A3pܒҲח8Bt["ii#Emչ=WM ysf;hQlW-LoVL$)b:rzDžB9 z w&tvrR}TWW>sQ8m Vb&N3ıv'jZ5B"Bzv\kUu`yߣ/,*~9ٹX޼LNfOo'G sb!|PqW=9Sha.(JUѻoɽ=SRR.o/1IZJ} DsԞV\~CtkD'|Vz%Ry B#<FD^L[5((eמ#Ν;p|ّ#G<5,4\ ܵo Id$oh ")(MF,e.~ގ=q}<]0:ѤZ6YQNNq؋Uz5Ҹ4MД ӧ$=\&͘6 uzH(Coؼ6[#(z*EQ/A^^^!!!smE`g̶붮>ȑbh^i Ν MJ>;qR'eOn ܳ9QRZvҥ3O=9l[b3AQo\mP˺Ekm!39fg4`3!z-y%WP 󃃂f! ]$@ 6u%ګJ>PQYʠojhld.Zq@Dxj+,`{uxWKJ-3kV72tӪXkcS63eOU`d5)q#Gvr}Aldh8wVlܼǟRiFpq1g2=ҊV\.d2-\pg zm``%z}囋=(tv[]U=z9-a,/|0<sMR8AflM{~42jȨM#rE6 ch8M8IɊis@̞9g[RSRryYyIDxԬ?>w~ni>sLvv\.'II 掎cڜT{1 E?9dpLzul5 #G /|٧a&L^^D`߸]\dž'EED47&)c|tpDwX'#ǎ{yzu:''7o嫯p9{겗S?Ԕ;wT3|Z86orf1}!|K~W{ d[ ہ ݴ1!A^n}Уw!ceeY9eD`kOfJ$ڻ/=-M}㈂iS>qəSƜ3TȑMOKۖ0rD}Cc}}CꔽW=%0hu?m#G{2g6?  ÌFcMM@  EQ,88K Z; <<<%b^/(xX,~8s?k~0bJO7vPFl<_'ej7911'7w݆ ᡡR 7kj;:TE"Q¢,ǧ ёWn_, :;՝Nl6QV)^ᡡ /0.EQT IDATmm~~L$Ob|z*ڕ+P CeW}x1ue.P|`AC#żU#3i@08[ |wPp-b4 t ,fvf ح$HMAqO`M_|3O?N qP$#:PFxՕZNw7J (@S8EQkR4Եx1fˣ|(**w'\L` P@ )FS4棑j hI1_ =<>>ሻi2G~4;xR٩r1'OPov"JݍHwQ.[74 \aa/L?BǍ+KI$1ܚ~ l EQb82>>}i|~K /"p.B"⿰l"X}? g~ J"$ޮTyB9 cW/xqGLO+j,:[Pwܒ0?gSݘXlzCoiObJ8A@N[I4A$AS+^9a|+QhFO(pq)/R\o y4 EcnuZ=AR(F!4i+C|>|x~~y!2ARʌk# R؁61 }g3T*FQ(ٹRCBB/]Xq*Ⱦ="A&X,J{ j|}km34ݡRi4.6$L ff b$2s7V,w^]sJD{{G>蚯[)է=^/a4ﭨHlkksss~Y< U5cI:sח:pꔳt{LsϷزӇJp'_>vxxp{Ŧ[l?ѡҹ&Fnx4Mz>kV]uNbnMӴV d6nʕ-y@P8H5X c4_=z˧~hL9k]QZh`<zU$z(+JPλo}ѧzw/|R\S[_<34MzYE_G1!E%Ea~!8At(M*d6 8,6+ eB`l 5ťZ1|DOН/HE11/1^.1@D#‘b4p I4*@ j?xHO^pV7QTT5jS>|XT*MӅEiE j:.+DԻT~k{tg;M|W 3wgSf^/z)Sf'*(9v$>.^5>c6mS'HhȖs\`zj&@Ǯ7]yvz$;ۋ#&fF,1 I:nSNHM7w/~=++kƌAAA4(4M׫> hQ|jMD"Jh0a0 AhTNG@HqTa(*;;d2[%pEMѤ4` PIK܋\nRRRx%RT"xyyFD>ǹ=]ϻ~1"]*"eSq^K҇ۻIӦLqF>s…EE 6ƇyBi_}C^R}CBy\?o6)("(*ZTh]ն>jj+(.-Ӫ꽭Uk;*EqAD@ $$靛' 1 Zə33眙朙jUWRԵb sI>q}\Zhju]]Nh BnoT {P(l\ϫjk׊«|ͽf|"ʲ!eZm]]Bk׮G\Ourt e,Js`555qƶ_[-[;:;%b /h5ZOVשյ B!W>zX\RSqkשoxJSN|%_n4u$kji5|n/[XX4aKbo7ݛG^ ^b_?x_֭^6?p?.?_OhyIj2RRaƏc/Z;9 pxx<+7 Jb/DFBкe[mˆ>fY(Z[YY49Cv;tjȀ~Al4I:V|ὬKwoHbX(W(k LѐCKV^φ1?~…ĉbxMSeЕ+ ~4_ݿJmmmڵk-[0)R)^G&@?˫gs ^o` tCFFSWWKD`VUgA|=?ieۣoCwvǞm ~JU#xXX񠠲TP_3ydi#ڹso^dh4G}2ڵ9rd IXYY=zP^+fD"Q=_~zo#/U>3_w;!g$g;=+v.=\|>ϮItmy;G^ιҵ%jt<h@PVVVX\XSS͐D"qkXWWgb 4j%4TE(D"yj> jFwtj / a|||ܶm&٬\. p`jjj0///KKKKKKOOѣGo޼YTL3l<ˋbwwѣGoݺg 4T@1LH8j("2d˗R?? 777"*--MJJxV%">?p@ϧn;99kVVVoڵk+**XkkCvF.߸q㕕GѡC>_\\ID ֖ ͬDӸknW7GwpY6[nÆ Ϗ3Rܙ3gx㍂̂#GMPsR 9qcǎIgrWWWZޒF5r… ,mooSLiݺ۸q̖1M"b//I&pرcIIIDdaaI$?00N H޽{ϙ3ښ={X,nժԩS{A#Mk6UV&Mrrr ofC`+ ?~ذa`׮]S(wԩݹsgСwy.ok?~ٲeϲ T83g钒իWMMFo6o2}a￯}QvL%%%%:t!!!DtŘ 4+`ccCD޴iFQ*?cdd$WtLӽ722|lC &y^p!::://OoO$ji$yݺu~~~~ĉ)))ݺu#>1cl߾_ۇ3S uqX mɍ 0?\lc'+KӧrٳgYDשSÇ+pŋ׷t `Ξ=[SS7 kݾ} -J~[o5xaÆޔL&[v޽{oݺR¢\\\t=x믿V(-Zh߾g͚eaabOU׮]xr[o֭'N5hf6o6eJ^ Jeff?\hQ==%%%{ywi4P}-ѽ{MR<==O裖-[ZXXtyƍRsŚ N0Ef͚;whflذAPњ5klcc3dȐ5kB?Wwӧ37,\0 @7̙3OZ)[ZZф ,X|rggWrQ-X[[6, rsX~FFK[ZZܯܼy%[nGGGϙ3p qfO,ѦM6؆DPP+A)Is(JOOO5 5bdSdzwԩ233s׮] *G'Nظq#]O6AN8GL-f]a_=EDDSn ;܃jjjrrr:w"ؘA1Bo6l-\.ߺu+ y汧sJJJ[T^;;?JR1t}ԴW^yE7qㆻ;,^hV]`7c{qZlҋ/h4Mw4Ah7QjjjllKݻW[[kKe˖qD$u6hР7|W^\]ӄͬoF37=[]P54@ `J=J755|.)p~,є#qqq999?ÇݻW]]&&$$8pPR)ƒF7U[[[\\n:.eW?Å *++***6nB>"JRwۍ| cvRk.>lw޽WլJ4ݻ}۹_0fn®a#3J8۽{۷YX=`\ˣ5]|yڵ{lPgi Mōs7$ģZsxJx9>|+WF}۷'"3Ut5m3ٳݵ_2}7o=I@7a@9Zh??Wܹs߾}/_~Fqqqի믿>i$9Oy7U*ʕ+<==}H>r777"rvvNHHwޝ[VVfii١C系j/5m3z꺺'Y&11Ҳ{fҋɟDy0`4h< ` @ 0 @ 0@3"4СCKKK?$5đfw!<<|׮]ޓ'OV(o~ g)AAAoVշn:~xPPmLLH$""Pb [[[T:}+V̜9S"@ Xdccc Ʋ]hccd@@DD/^lccMh";;{y2 IDATƍ-[VVVmۖڴiS\\\YYVXXrʼ#FQ]]D"jK.5,mSoELv}V}۷'md2<hں{)lVVVCYYY,X=}J:{_󓓓kkk s WLKKe.\Ю];"ҥKZZ4(33s,ݽ{7⨨(VLVnhyC  nnn?PةSGJ뛔^v)// -,,%Iaa! t׭[T*j׍VT(EEE999J2'''((HP@;CС@ h׮ݰaN>]~W^3gggD޽{Ϙ1pSz9FWLKK $̐W@C;p;+((`y睟~0aBTTԣGg)+fee3,rfa0G1??? pswB6!^DD_B Ɇ8O|sIɆK d >^0`]$6B=ukrm&, `xp/͉;ߺv}y5b*ЈS,ïtu{^رsO?ur>ͮvWv}N| D_-k)S pE(4Z)kni74` 4@ˇJrDTSW;q}\\SQzy;Яo\ߙgfޮMD:W׾zdh`\s)]t|x]tk랮qol |W lo9qط:Uljl~qїuJA ~t 8p`w"Ɇ]f80߁~Ϋ3,cxCwB>7o\_Ϯ{GE>3,\RR2k֬ӧWUU7n\ppɓ'}ѽz;vŋљ#"iJI {IER [dLC cϿ"4ȁ>W\7^wb· :wmv`"ϏgUk#}ɓ'[[[O8trr:qăF{ntoC@?Kh5ߵ ?؃έkcE֤y^цz.|e@}p0@)W؁Q@>-<65v;o.x(vT$5ܠu?x6":mUVWY-iTY-ٰZQ2x.g yuUwiY5,c<;!-F/8⽛7zNddi UUUDe~76mz7\]]#""znnW:qDIM@~ؿ&F?*UDd#aяEaQJ}.|e xRKS(%ܬ]sQ[́- +=wo֤5It_~p}GKZYV[F9 2}޸J\qzKK o;va繡cwCvv!n!8 / ''8kkkKRieeCiX|e>qqtcxY{yxs;vV0mZ]ͯcŜ?p"A` 4@(~D ib睟GD VWA cJn{MMq6AK_)H~:N?y 1F0z&Q$q{;e22 :;wlyݽ1x555{1c.]or~㮏L_WWhЇObkeׂ[CG=Y~Oac_]{^bL3 >h]t +zhgێfT_g|-Wu_DDw~j oyνv[2kj֧h5[_cc`HQhq|f7>\Y>*URWx)4 虬O^[nq׏~zezJ֣W[C?%KBBBܖ.]>϶lٲ|r :@0wHwwe˖(n9pͭzp} ?ttZ ";65vVY| F֨~,kKs>\i__{-^ X3K67ZF𶭅햐-8j8.$'9 8lt@nhhF 9"VZ)Ќ=k4sG g/-9w4ka e=h>xC5:t(55Sg̘akk~zP;;Ҹ><3O:hbۗ_~7|pݥ7o&1cڵkN O3J2337ިL&ҥL&KKKKKKCl8OsGZ- zZ-x<^}[زeܹs?6mڠ9...Kww|޽_|ř3g&M;vlرBkܸqǎ3gE\.JhΜ9|>@1`=Փ'Ovqq)//?{lzz9+8p?>~xxx믿^^^o>t=);~111QQQ'NaM[' r9M/xz~ hɓO:aB1rg_H3h  :uç~ZWWx۷8q"==***:dX]vNNNy&ٕԗiXK҉'z{{m۶F ,Z… AAAK.5^WWשSJ$={\~4MϞ=G]WWw;wQT"hɒ%[UUK"Diioya򫯾rrr8 sG[laLxxѣGǎ2njk׮˗:u*,,Df\2//oĈDTWW'HZmLL9rdBBΝ;G5k8p 44}DԶmۂD`&n|>d…,g۶mu'?΋&dMuu2ׯg &L&ҥL&KKKKKK3뱷o~ڵ*ٳs+󓓓kkk뫌nVZڵKT][T*333|M"ر#h+V8;;W&";WUUږ(Ӷmۑ#GD".s˖-;wnUUտL]zsD aXj˗d&*[@"T*r"h4l/==cO?sDԲeK}Ь\e&O|ȑ,V2w>iҤUV՗ 2lݺuJR/;j2 %xS^^.;vR=zH YUWW[[[̊ +/Z:'&&4GB:$$dʔ)zeJJJ>|(BBBr͙3ߟ痕q7Fl`HԻw3f0Z]OL(===44/_2ϟ?m۶}`9.**ڱcGPPвe,XWȑ#ӧO7oݻwϟODǏ:thtt Jlx'N0Z]G ~뭷=j:vss{=m޼yW\O7o˜:uj#ߊތ'&@""" Dlժn~ &&&**jĉ666,?66oo:̜9Ӝx+VtШQx<ޡCRSSg̘akk~z\ @hѢ .) "ZtiddѶN:U"ٳOX砠x޺uAAA\7~;vQll,0Tnvqq1QÖF"rqqy7mmmclgΜ f/ͩ0N4ˣGtҥKVAg̝ݲeˌ eÏ=8vX9f̘]v-_ԩSaaa&2 W\7b%hbۗ_~7|p"ڼy3EFFN"hژ6F2rȄ;w5ܢEl7ZlɽXjUZZZhhފFwW7VaKv#YH$ wf9yyy_|ŝ;wXuN}hƦt߸qCVrd.]HҴ 6l߾ӧU*ٳg}||L4A $&&*L{{{Fw󓓓kkkۖVZ߹sgڵO^gkkk.dmDT*SRRiatl>F[jjeE/b̙K*ܮ]g*ʤ6mh/-s@WUUږ(Ӷmۑ#GD".s˖-;wnUU Ub8**VMn*x<"`A9mH$*4,⭨᪪*V( DbN+ fnnH$lx}_sH驻3+lee%ˉH.[[[hMOHH0QfGj,|޽<{&MZjU}2lݺuJRwFK6]V5- Ғi&6hf}}}N:qK---e2  úY-5ҲZwPmmD"qqq)))iPXuC\@Ӟ!ZʥEN.V?jR[i@Ohɭ5;:11qРA=z !!!SL+SRRC@"˝hΜ9|>K4,z=c %J.KvaѶܻwO>y:>}zС:tڵ6lӧ}ݩaݸVі¢O>_0`7lfoݺտ [nY&9COnUGƖw{mˁeA^ք̫M[tuhX\TTcǎe˖-X5..N̑#GO>o޼w&''ϟ??>t &۷4| %ۅQFrzѣO^缼GGG+(( "@P[[[TT1԰n\tK:vX.\x}Z:y.^ꫯ6ދ/7[QuFܹycڸ^ߘ6NCDi&oS^UܼIXQDQ)s}v㒯5yTj`Kn7{Ki--3Khe]o˜fkTJM"JvJ϶eG?غrV|+%</^DDUcT>/V;XygǝOg eO渡i|fλ)rO]QW_k5ojDUQr}V? [|kJHDDED$ڒVKDQmQ_./#K]Ke~.Hw[;Ъkͩ6s.xrw>{_/2퇄v;s?!%GVDUuHD"DT'RW<""QK7"Q]eEj%$%}rV,2gV0K&"DRe#Ҋ'^uU:K: `|K+>#"1Z51D IDAT%"u EeTWg/ͩLw+w!ݓ4 yޚhMLo`kVQ_kS4/S^rz z`np% M9r֬Y...K+233Z-]xyhϝ;չsSN=/5 } "ڬ xW_}5//+PZZi}ܹo1wܙ4imobw{0`T*ѣǦMX*y<֭[FFF.]lllLoʰuÇΝ??lB`+++Njoo駟^ X37l@Dc}޺uKwݞ={&%%YXXQqqqn݊u l۶2˦Mf͚W+V,YD|"h߾}bb"[*??jXQQѧOlb/_vqqvޣGÇse XVVKKJ6\:_ K` {,Wfodddee姟~JD/_׿`ڵkO:% R?`t[l /^~QlƍrQQQmm{***L7y,>}zii)k`~~>|~II… 4O˓+JDBDr:ut "*..vuu-))quu%aÆ=<< {YSSceeh4gΜ ۔UoѲ:uꔝCD;vd_r{D$H N'x0 차KD-x<~ڵk,q]PUUxzz ʒ+o*sKx{{QVܹ3lْ͓]222Xm۶KŢ}?OxbkkUw0h+v.X4[hZ" c 6pJDZ*{yyă_%ͩs<ƫ x1,YdD`VܹsפIXY_~9wP( 4;KKo{Y^^]MLLd7-;v,K|W_~%{9ftxN!XiC899 0,++ ebq|||HHu޽L-[MF=z#GX]HHȁN>|hYWmA $6xf,g/"""##~199yܹZ G>}4~ܹsm~ˢ_C|---uv᯾*00Ądӫl޼gϞbpu[[sν"sܹgϞս`9 F 0 sD"P(={c2=RA3y󦯯/sηnzZ_h&JOO6lXZZ{ٽ{Ǐk.<<ɩ7o-pBPPҥKcccY lXmo񕕕;v(..ݣT*8qw^^޶mjjjXP;;Ҹ?0Y#wvv""KKK''GFGG'&&;$V]ݰ$jժP=\2//oĈ,s̘1vZ|Sp`"']L_ƍj:55ɵ-IDIIIJ2%%Kow۷?}J:{˔d]tJiii6l ,>jԨݻ9rڶm;rHWWWc0UoJVWWBH$z⨨(V,e˖ϝ; M988xyyɓ9jZVoJZZZd2+++BL&[nR,//߻w/޽IVZf2w V `9%%%>!!!rɩu+ٷo_ {魒,z=c 9g>_VVp`"JOOo۶k#GL>}޼ywMNN?~}+EEEǎ[%>>#***88ĉ,C0a¾}p|ƢGQDt.)p~,GO0 @ 0`ǍرcqKN.h\0j 3Z-2pk׶jժћmnѓc{pii ^JD)VqBGi{~On"ݗOnÆ ݺuFi襹׮]:uj#6"ںukPO/ͽvM; f>~vTkmݺYq۴iEDEEE*Xh+RRRJVWW[,,,lt5Zhdɒ˗/ѭ[Feii9dȐwNիO?'kݺCCC.]OV/Yaݺu&Jv<|ͬ@j:eFT"{/vt>y2?L:1:kZ.%LzfMQSZK0o~뾸1mlW+M7nÇ`.>y$ٳ'<<‚|(l2KKÇ/\(..^bEϞ=(,,l>+0uGdTF̌7ۋcsWڻd!!!`ti٫W^t1c,--NzVXXس>9p@SSSBcc6mk׮rVXQ__ߩS~ݓ/Bvԃ_|fݺu;w2>Y֎~ŋg;vS?ϫƩusҤI111o=*RrmB/_w/<ĵ]1nm?if^P_|Cޠ>KZϘHUZi]qI& g>cҤI)))733/[𡻫4w~}5qQQVX$=o+\vwCcǎm۶mVV޽{ ,Y"bccϟ?/)((IKK2eJ6m upp(**:xk״^IA.<fСna` ݪU$ vTFdž\޺u 6 2D*9jԨ={\رc#FBl߾]zለxFJWi 055dƍT,}`KKKoԩS555gΜ2 kjj._zFyyynݬ.\yfv6mtʕϫڎFT;vL,#=˕Y[[k}UJ U0+ jv4s̲jX6l[dAZ?~񡊊 ssrssV%EEE2Gcǎ]nї^z)...99YTFDD3* gy"00_]~211߿u42c Brnee"??Ν;MA>ٵkW~VX1od_)тp5|*H]fիWnj÷ Myץđ#GDTTBs}R?XJ\r̙3ڵUեwƍǎ322裏#𜜜[nhG MO?taaԩS׈ޛ%E'O.((xm/adee/^Xw=Z}RJ,Y$666$$D&ƞ?^!:t %n߾-%bbbļy󬬬-Z$FGGO6M.I6m4urUٸ8)/iӦq "**Mؖ.]jgg`iυׇj… ϟ/ڸqzUV9::Ξ=;**J7{|pCC\.oݺ bbb "6w Bl߾]sذak׮MMM ڨQٳrcǎ1Bc t~zWWW266n}T(JrZxB#FdggY&##cС-]GM>!*MOO...2Yx%)1k,)ٳm۶R͛7V>>>fll!h׮RSSԂTv*hժQ jt344|p}N9s挧˻ufeeu~Ku6mrJ}}tӮ]ge:wZ500HHHV䴎d;tpĉSNuY{zڔ ))IJxyy.YPP %VZk׮ ccc!DVVʕ+ϟ/UILfkkkݩVURn}:Z?`jho֭~]VmjjZjyeeBGk;v 9sfYY5[zyy 6Y+tJuH)sKJz={ڣ֦tzU+aL&7nܸqʶl[o !>-[!nܸ!k۶]Lz[xǁ4~._,HOOܹjQ f IDATx0-JRZ¢CUUYaU ׮]{ɱcj}饗N>vڕ+WZUo>^;!;STTzfQxಲ.]@=ZݺucRNeezׯ?S&&&xy3f6^Ͽs玡a```eeCSܾ}_FӦhs^zƽ{2eޛ=Z}Bނf)qrrI+666Ǐϟ1cTsΉ{n߾RJp{{{!ěoٯ_?BQQQ:?\~q;;;)D744;wtHqWBeѢE:uBl۶4EqGy.\S[[#:|p'Lpa)Uyxx,YM6whw <8""b_Ѹɓ'Ϛ5͛ _o{x⬬z=Ɠ=rH6m.]ڿGS)'(333ooﰰ~Zooo0sLwww###[[Ç8q"00P!o޼ߗbi!ӧGimmmmmOFGGO4S(ׯIv/ھ}{Ϟ=r~֧O6mq۶mgΜyԩfo<L0 tg?= C$99YJ>Ov/g 8 0$n4 ` `@ GFFꙩԩSd#FZZB=R+G0ji''[[[߿_iee5f;wVWW,Y$666$$D&ƞ?~ʔ)֑6m7o^xxܹs˗/bƭ[?c~/_lccSPPƅ׻2Gf͚C !ry֭7l3d!ۅṹREk[S(JrBQFٳgʕǎ1bWpv%$$Ԝ={V١C'N֞:usRa|||MM˗mmmBkk uuuBnݺYYY]pa\Eg~m^LMM_y啼L&F~[=?]LYR|7U9gY5O=.)FT߸aK!RƆpx iUUB)˗.]*URBѢ_j\Jر#((h̙eeed 4'O?~֭΢EW{"\ݻ3M6rT*~2_" *:?tJW̄ʕ+×-[;Tk_׮]{ɱcrq?_>""brm۶* 0`@zzqΝ...λvB <8++K&%&&ݻw733ҥ˿/FZ ! baaT\\,sppXt˝;wnժUll,W_u;>>^GD}"箮q#j̨񔛝Kc?|Q![/ĩW/KKiHϝ.,9Y@ߟ::^zֿ,zugYU]\se_~26DQZ"PҽmA̾_{?ףݝ{?9?}^>ݾ}_^zƽ{2eꕕVVVh3fqE.^8j(/^&022*--p/YDqQ:s̉*..^xi[ZW1o޼=zHƥ2@cƽklVk`jfsfy;Oʺڟ:8HU.=o;x۸7nP8ף /|tt7{O7W?HNN$4>}[//Gzyy5>$+++  yMMF8;~… SRR*++뚘HOz644hl066100hi7--mڵpuu} Tf]Ek#HUEG{0_M-3'3.qJ44Hej2nfmP]Kv+[<5 3vG#iݗq 8S@Q2**jeee۶m8UV͙3gĉ[nJjl<sڈurKϡwԟҷLcFBbr)5l0gggcccg'jhhdq\ZZZXXxw]VWWUTTXZZNJnMMFassr33j%gGUUUISNnMMk٪FK/%''+ʈA>sFFFnnn?~OJ+++۷oBīWظwSLQ}unݺ`)'11QXdff\.ׯ֦ܹchhXYYr|^ZbŘ1cΜ98׈{x⬬z!đ#Gڴit=zTU8777,,RNS%wÇ?aU׉[NJJ(yȑ޽{/Z۪U&O ''aƛ ̙ibb:sL*++¾IIIݺuS=mO?߶mۤZGԱc[[[?S|M㱕N4n1cd6mڨG=zd-A O€ׯWٳ3gLLL׌ !ڴiӡCxmi `ժU˖-kJnn풝;wN0A5*++XU5k,Y$..nBgG*O&O̗&=@p **J~KKK|M!Ĺs>Sh9''֭[^;vϪg}:DEEIƍ;fdddeeq_zyyL&_xS1tP)܍򥇽^x0pdKwaUH9o<++EI5nW(QQQnnnBSN󩧞dee'mdddiiٷo_/ZXX:uj߾} "aaa^^^BHWUUϘ1CG-i79rcǎMU BS({`ii9fBq77@.>!!a̙FFFÇ?qr˖- 033=t;ӷo_GGG)#G~'g;O-7n\FEzF~bNNN[lQl9gΜiv$]tQǨ^6z҄  iiiBݻsZ@ QSRRbgg'ׯ_9{SS=zݛsG +~cmm}^2L17Oum pNfϞzK3Rʏ榵?t<dē  {{'_x饗SRR,,,?lذ/NAzGG&&& !JJJbcci߾}hhCQQ]&)((IKKk*j̘1;wnJCCCϞ=P(:t!Ddd7n|(S/ijj*...~SPUU%)>>>ǏQ楗^KNNV*RfQQQttL&ѣرc׭[Tfyy[SSަ֒zڠBPlV/PUUeff&EM)**ԩSmmF[SS#kܼL:>>g322 |5߹s000A1c Bҥ̫WظwSLQROZlvnݺ`%&&kBdff~iry߾}oݺw }Wsrrv5tի111e׿VWWBs._ }|!#G=zҥźKIkXÇ_}U\;~gwx/R`7;ܰ;v{BY= q˫>ҧAkpEFFrQrr>Ō8Sӊ+Ƈx=zlk?+oXRzp`0dH۵kW\ޭ[JvZoPP] < x P*SB_3gݻ~'O?nРAͶW3 7]vr|VzwUG+;;'x"11Q?K!CXXXK/_ܹsVbccʒdT}W;v455ק.@  p;w.==}ܸq_=oS IDAT޼=z,YD\xqXX؞={.\(8zBTz{{wUVVdɒ編.pf <"##mjjZZZjbb"}Jfffy{{WwttLIIqtt HKKB888Y[[7N_ޡӦMk׮]SC8cxj*77W1//u֪NNNB;;NNN2%;;[iiiy8x;wN8uxӧcaaNKiiRT*R~ܶm[NN΂ &Lu0{7\bw}W[[?,_|ѢEqyy۟|I6lOTO~ꩧsΝ;K9999o߾R(- 7 ZrZeLǬ{GJ|ᇳgNMMСܫW/!D]][۶mKk׮l۶N͛t"- WUV͙3gĉ[nm\x,hqGlF35[xq #`۷<౥3fp+sc8 ~@777Nc"##h0vVq`:8\ܧ0*ZiQ)cCI#*U 5՗G lQ 2UJ !JN|ba-Y[~L6~fSUu!̀AE9-e=l`Z[.^iTܺ_PKsoQ-m/ ]u*~uy9W&..)cC%R.ګ} !RƇfmgeձf k2E-T]\26'Z%ZyK;~{ê;;s)@ @6?:z}QfyW`~^ w{ !XQ^&t.%RWpAɹN+ZZ9'To~Ra!.q[qܼFf!ϻF&Hd_Xg|kysɼ;9u[+~ZXf]efh\LfdPQ^t'ۛW,sǚwo=@0dQlھSܯRNƎ΅0rtr2KOᜡE/|^S*ahii7d\g--=U=V`*8-^^+1n̛[zdRhOdO\}&qe?2ee<ζWm^nS4UA!36Bnh#gaxZY6=7fmÅLLgNy盽7Mq&Yaφ׳=VGACuUޮO̻zKw2ꨬp}Mz_ czSwOⷕv9[kyʸ6[)Z{,7`3sK>^|,e-}# =m2٥}{Y4}=׽/lhezy]<־x zJ])Z{,f ͘1͍ȘTe͖dc 4@ x,{pFF' |gf5#-C@zARRRe)y0;f5L灢c^^^pp𫯾z]\zo>mZIxϘ1#""B?̝;ڵ{ "ꫯ322:t=00PU}YYY2ҥKӧk[[z''ϯwkkkz뭆{oʏ>W^9sDEE/^xڴiRwUVVdɒW?zBTz{{ϛ7GK,B?ڵk~9s_Ht7< daaa@dB^33'|r֭۷W/_[[+˥*ޡӦMk׮]U GGǔGGǼ4h~~;wjkk ESGrr>Xn=*=~x>}T%֭[e2OEEŪU̙3qD[jTټys.]׮];ydww>Hu7<x!X!X ` `@ 0@ 0Ba)2LJ(J`nΞ=K.]t3gNZZgx` XLL+++U9W\rʧ~wÇYcЁ`e_>nܸJȢ~bر7oBd2ooo={d>̙3u̙ҡJL&|}}ufiilPmr###Lv1 r Lֺuk.:ƍs y뭷O.شibرB[nIo߾믿 !Ə/(,,۷͛o޼YWW 4Vaff`gΜye)ݦ]XZZS?KUǥO?$E\tGJW_}U=^~bцB8)?66Vadd4f!DTTׅᥥoܹs~P{UNNN]]ݭ[JJJmS.V  ɓ'{?3\t )奞߱cG)!-:;;K*X=xbȐ!B)޼yVVV->FGG7P(ܬmS._~_VV6hР$%%ݹs^Z[fcJ6Рzo?VҎ~~j{ӥL&svv>^tIGUZwtwѯ_?7nKT*㓒\\\vE08׮]SOMMȨ">>ᆱ6775j 4rUkSkRh?;vĤ_~ ǥ xL :TJl۶M=>#F BI{Giaa!%%%J5CM v!moNHH8}t@@yU07x|IJpDDDqqqIIɺul";wc9..СC*Ju֕޽M654ۅo߾|BL&YXXgBDFFYcƌȷoԷ H+999ҡ>}6NKr#GTufԨlNNNRxi6mz7NNNyyy|1KNN֧+@ 6,))iٝ:u233333ڵ 5n2d=z*Rbׄ3g>ĉ>uYG[nB33}JU_ G +o_@a`0@ 0@ 0` ` @ d2P]]hW o߾1663 ݼy3*@ <>ر^Ϻќ@xXZZ:::~JRZjejj^>޽y>s)S&?~\gCCG<͛7U|G;v411ܺu*~ԩuJJ}˗/s`nTWW92--~B>}ʕ+#GVٱc̙3nܸꫯJqV=܅ ***gϞ-ӧO~z]]͛7_ҡo߾*==zk/r\\\QQQyyӧx .@ ܍c !>!ħ~*7nz{OS]]}5u&@H{hu:ֽEتmU[QkQ>ZZQTp  cK Q_|%'s9|s97l@DEc^oxT*,J׮]KD.]bҙK.---]b}wKv"˗9sW@DgΜeee'OĐ'<<f3{{{=|088)))B\@` LDIII /477EPD"ëD*ږb{{{TJD"HP0/IRDbjȑgj1bDxx=^aqqqd 0@]XXX?^TN:tĉOsNNW]\\H('d"jh Ngtǎ6lѣGzz+Ǝ@ PwaaaDt!3q*6oޜ?R qwVY"YfDi&BqFCDCDB`Δ66m磣,u׬Y:Q׮]:|"0`p8`ĈKDԢE @` D ܹsFID"`bjՊڶm@ P/"0Æ c~Z";vK_UvLܹϏ߿K#G ؽ{7 L*.\X,߿Ν;1R`y,x&X0` @ 0 @ 0`]Pk=Nks `^ 0˔5q3lUhF`O3 ~2M R|gZN3ϺWےc,i*k8O|&vQ?4`0%r5Ng~ I:]@g4xT#Sy0,RsM9"NURCx_k7UWnn)zE-ݘzbaͭ?c\].İ3uۗZ5D7i^䴡^[^6>bHc}Vu.ʁS ^~҄҄5/ߴYfYB:*!}!!ZbÆw'uz"R$ۙμd;]=^)N3lm, K6%fuވu: ã걁1-.ؚh6nKx̸M-"fv%q2.>|Hrv58Y9u87HKSO~۽ѬɅi&vDt1V:YWb՘%wɦ2T(S,h/ڻ ^pkPg)=Jem@$}gmRL=z{#xh"'Sڪ6^(S/}/`eOWlc9[BFDSj[kG؋,9uDEZ"0N,ODC;"*zJ$5jDqS;<;!V舨RaU4$K%F%"N/O*x+υ6AZ6du8d.s<>j[x:̐7zn'9]T۹tZᬑ4d;x1od崡^g&u[{5e۵m+&Z0wr戧4yf Og{U ruQaQaT+?'V+ص-\zƗ>S)(+R%B}>;9cg'U o |"s;le+~~DExv|UQNwIwb>mGTUTKg:"Ҕi(S+g}kwӬ&DT^SlmH{^WQf-4Q-k;׭zpTfjͼbUZYNU*̜KŏiȖ]X=otz=1hɎ3W}.5sֱ6)On$""SODX׀{Tݒ{S˳z} }43lFӥV1z2M ,z04<+Bq=z:[?.oq8U>p)ӵ6v=b~$To~{87;nYUI. /ksϔYݵg/?%ocSQGQǑ0`")N>0HOh_6ܱLKUW{:SZ]'tΰn7Ƨ>)xƎ=};HK)4Xv (4㽮.Du$S[+*OU<1Je2UnaD!1~}ERh!nfGD\KS]+Ir,!ʱ?yNUdJ+QhOE5f.]?S/}2f;4C7]my -U)Öeo%FǗ:ٵ'Bgp}i}gmҀPSe spbހЪwk=ҩ<QׯWֶT`x9ZOgaK W3] wAp 0@}7g9 Vീ`ڋZZ ;~Y^+熃`x-  \ P/Sn1a˗SK^[f|9 ]c||lb+ƼJ;i h0d6]̕eG{={CSR[)RNCǠ2GXIDϭB/ twkWnn)zE-WݘmaaͫBY}Do\~@ jۤ$7g7]{:Q\J~K>kN*]abH7w׹*ou>7zܦi#;I-@ Pk/N tCH`yZA&t3[z=CI5_66D[A^#"EB;z{|J*n'2lm'| O;d&>{-wmḫ2O2E%}w1u8&"O;ݛ8~ѝ1^  ]3_x[TazetD[$7m7m-34Zݗ[֡ϲu#DEj}usvA)'Ux ?c\KMZ&i\kc&\>ODjwuo]S uԈ%Ǐޜ8vm<'n|ӍIȗQYj~7ص&zڞ*$&%{?X}8z_U3|_iLƱ z57lzLd{C;$dkɽ:QbFрv -5הbӝ\{;+sHSk9s_.?[1Q3> uJU҆?'[Z*7͙.?cƅ 1@ IRqtv@/65N?}5I)g7nvdV_N3yV~M)hy/8VGgU洪JeItJ5]>9yneq\JJ:V  *?X=ɒ1ɩ[OQCv1~qM};)ҫ R]&4>S$v4Q=CSwS1bM"O-H>W$2a*>/xX_]¬ gjRvi:=Wʔu97uYg:g-/{JYCܫ_):^_ҫ یQ OܭGmA)2DQo4)?VVǨOo{1}Ƈaƾ.߲kCf2_vTxq!!o.n7I:=j_"ҞV0k uXGDdͷT4LUcoUir͌SjvIi2fE:5G/U0U^;봩i2jmMD}.$VMʓ*9˜\eΛ;TyC^Ϝ|1w?@֡MR}F%SӶ+,k3h?"sO({mSZTe1m֓tz2jOD<>)*)nI )!8Op1Npdg-;W~t?̒21pH"67$Z-+T+Ǭi0=xްl*NDDۭMbṂVv 61Fɪ]cGѩ?oq8^_e8w=Y&WZvӇE6mj zaۭECQSeY ){ڙs|/vWDOF2)Z?s.j7Oju:Gg}^gujmV{zd1}z^Oz/XoڟڽA5SNW!+xsl}Cw]Z65SІj>SY?!+z|ގNƖUF?A6 ܈Du\UQXej'$"eNZY/;H̶Z[7z+Igrx!{fY2M7~P=n'&NU% 񓱺,]wZHpzR6a rgk2\Q,.MF{#0ob";oeR+6jҟ/T4o&zaGSR[:6 eizV[<+3@xI:5N/B/IS7?x70O`2س%,Vwl监&}qxZÙy)ݧ\o2ٺ ^`[a/&q>c1h exj>Z&+7[zaJҩĞD>$ .9qC>GAgbX4&嘴.;Dd'n<`R}y{{Vɼ|jߡv3e Ԫ;Wzc%'*D?}Ll?r6$}ڲ &cDmboy#r˃\ّkfUq"Nxx8z/_nn֨u7tVBΡc/6eS {Mzl>|U;b>?!..ΜlXhxU>OË2gnֳC]sOFqx Wu-\|=^0 kwAp 0@}7g9 Vീ`o7q^V +Z@ ^^3aˬ%-G3j {YٟmJ5B r`q/jӛ~/rP/-6tK1Ol=ևhUbaTX2+6}X#zswm玓tupzIL{;Y<`J2ʂ=m^ãꝮ;Nf:ܻn3z\ GzL#Y'kԣ܎'9{鎇vsY0S/r,O Cv./|&0<0!>MWn~؝qGv~];)0Q&k?&6[8kq{VZl.VBDKK=Gzx nd]_bHSUdũSĒ{kJZn[x%>9go޹CЎMwh,6Œ*Cc5}ITgu oԯQ۷qHV9$z jCJeLoyG&m] }<^RQа{^}c}6%d1)NdoM_1%V8{r(S MTdBTX$9:HDB"R$!NU[:MllHn#Y -5r-^'"IġE=-jKYr9w<7hQԻw;ǍZ[7c4Coq;bލh\FJ&żœ6ӆz1*ܿܣ3y8OjWI{j>"˙#|[bff^SПZhcҞ˷pZ_h9eYJA`mk^/iamڷٱ9vvb&<p8ٞOD|RcR2n:X S3gJj`\'tӔj lv쓍`Kg:"ҔiXJ uGט4WTZ5urw=t8]ZY35x`Z|^*-WɬH*ULD4}Wɑ537%O+Si aBW^JZ^uWKw&.s.џf\tZ=2߀PSe U^:x1o@SРWTZK[NEYGמ]BYz^Ӗ, OS<||$D7UШ +\3xA P_S{6x+? zo役,{Uhψ.QhgRX߾o*w6KM~E4b`?5ҫ@/]Ⱦ]QTe`;/ԸoIB$kwN/;?thsbq+:ǐGc *34v~e\$z Lە;o9)_Sܥ=9^Nxx8z/_nnֱֿ9ɷK-mxԭߋ<Ѝy1ml{kf{u0Ɇ`x?Ŝn>ab/ `x\n'ܳ%z+k.xnph@ Ԟwc&@`^ Xuܰ|~n8X`@ 52e|9UhF`ϗ͜ЅK0v&||lb+Ơ+^!sw n @ R+zqmM"9ku@z5beҙ PVq_d?zD,xziC B[Z \iC_2~Zgl=nӴ$bj0\KY94_1'we>poӽ>Xz\<)/H g.}þ{ 4BY)g}#H>a;Zx\Djw]*t5׍caν[]x;| UPy7>d)nb&lڌ/\${rxQ#V[(r-}J:gr]ZZnC cdv2ppBnߟ[Ż;至ןK)pq.Am&"7!zdc{IֆfvT.XmڶwMELlRk(VG[5VжoFNG#IЦ+ڳphL8:UtvӤ3O\y@DN7sI;2M<+v\M?+#V8SLM[f-/WӪ*JED`'9G܇wv9hT(K6.cgfHD5%BVq\RCWDy3wީ[+ןKn4Ez5wS KDn&a F MqY;u8(> g_}sƓLʄEثsOp! z jZq\2k\hшN?蹛L?NE m6AtM7QiC_ϳ9oӗ2wӟZQH39տ9[ =q]G$o <1NE&29rjg۟77*x =s-I<8k\洪Je**RheXxI:5tjBD6$\(M!"D$UFDZu棊B(%K5F$"m Hεv_Ғr+NY;u8(|b7jۭ +g;Iyi.m vz^6ZЦʆmOD vYZKͪlDۭ}nz=.k``:5vۿ|80éVZpL[jtedݜFݑr=YMӛ{]:(p 4@2.?7_+B&WV@09W72 v)R?aj>SY?!+0qҲ;6H2Yı~AYS=KDNݛJJ<9ߐ(nUy#?wD)~ق^і3 7ieٖB+qK"Z>um|]SNfV#}RkK'rg{qY`AUkBFoHQ%ZNX Yyy鈻*Yi&64QwQu&`ה,gc3=ߌ4ۏ_ts-$ΛصL>E~I\~_+ޒ{1˦~ArZ>$ .9qC>[6}EyB5m7#E\S'{ܻ{S\w}媛or >EmOo%Z9Ƌ6v[~O^S=^qg3ř +sDTjǮM_`+D\^5z'g%j*K6{2 xοRwAp 0@}7g9 Vീ`o7q^V +Z@ ^^3aˬ%-G3j {m)T41X;98&I^=2 xc/5'3y8OjGD299hmۉ3 \+1/-/6LtxZᬑӪ*J[%"K'(Ok目ݡD $"UVǂõBgxIZ6_ y2_78XYK&z=7Ӧm,uK(3uZ0wr9Mte\w\ :Ł_zF25U7W ]X=otz=SyǛӪ*B#h4l`+~ؓcIߟ.WRK!".D$V$VDD] aϐӜ2)f(yJ.k=a_&isqs&eegc3v_|É[?ơ{2.?7_+B&WV@09W7r/l`kdKpIޫNIKroj~'iґMKto("ET@D~U|̎ IDAT2A@EDDD_(‹!l@=6񔐦Obڂ"|?{W{s}sr{U_ HdSBY|c9glkuK7a9s TfN ' FVj^QU'O&1\])eR&"s6IL#\Ǯ4WDT[,3L%ݯ*I6Nw~{l`J,ma7hв6?N_{|삟%%HX8 ~V+jUݼwڊ __r?&F4hS>vZɏٟ$kο4{Mc '򣗋w fKdZ{T"j5(1$&12D!v$s(Mݡɱ{Gud41}Ydk cc.=6(dl&~R~!xW̙3@DK,qrZ1Ӹh~}>};c)A쀌 G 0`@ @ 0<~=͂3P`;ҿoQw ݃3P@ (ERgovF|J ! unGW%Χ*䟿Qtsn3 !?\:Zn Ă6 xN\uў[(w=yH%CzH^|q;&I^'HǯDB[b!%Uq\NHn7+R_6"TFo6ǙJQ.PLl9|M $"X<]*uO:N+g+{`ej= ч_卌|`O2-ͫJvO8Wqk[/7ukFg}Xbjv<)W_gU!0YW;|څ%"()DeRfոGyDD=|H}^:Le]ǚXg6G~--jr4[@-Z]61B-熿֛5/27kZ=P˭)eT)=H-/x(SyZl[viN=]NDsjꞿg\p?17?R\Y|.>o9vm= L[FgXg\uC2 +,[8$(pHP¢݅ ?8Wv dsa`D@D|5hOtXp蘰C%~ 2Bܤ#5`zK[d]y""fd">pb>Vt>z\%2 [:Fy 2hkƯ@9Y_MV/_gŇ v*Y^%2X5%ЭÊ.m q/Sn,wkNَ[\ÊN^ 7kwA+E; l|@׎v6Ͳf=yMk+,3$y^l5||.i=-kEK$ނ}w"}g*o>L滽EƆD3JNtsz*g*fȬFg*rrGGչ ZW鉨D}̉?,Hsy~}3%"$S,$"ӕ qWTU5:&Yדuh0O7%˹JӦ;ᧅmx~9':;7~$dϩYχz;Mqg׵pXE'^~WH"/ş Ű a.\7㛔lEгR Ͽ+ˍBy.9&epPv[ϧV}9o?}_#s:j6uV RZk%vfUjB_ʵ{n~fFߛ[wui^N\widt\>DS^wK=5h׭z>dT*#<0}T u.z5k_/>ӲR+o)iC-|/}kX~ stFg>L9FǼwaʹkDJ똳D$5,#J-͜<;b ׽G{k~zd_;ɺ:E{l{;[˖ӄ)yȀaΚ@9ݛ4yK~"~qe]害J-' 0,9y8u@'Y6O9"~{y.\G%N8,~! F'7Ȳ,\St)}.89&|kB_->v"fZ.ے׿K}[)kfͬ֎_r HdkB_͐nר K7ٟ$kNV++o*M򦒈D]BDUg*TOw{pfΆՖZ Ƣ=EDן|{Q᯷ PM[Ayt6wnwRɺFgR7V +pj|9z#'{v=*L]g5\J?o\8\0!b7bƥ:M`LϠ-^&IQ'ɚoI9< O'CFQ@pkZ=8ރ#Bn(H}L&'|֥so  $2QV5%pp C<]!x Ǥ&I%ζ֓u >#[i-?BsUAAse]Ȭ:n6Mu ֜v^MyZ/E=Ϡg>rrM_-_wCp/6~}1@p+t_LSO,ESkK︲6̻1c7;"ޯ ??; ##Ñf8 ;7dW**؜0(pg;c͡O:c P'9bԉp+17Ҍ RרX \7s%kGLꉀVO`"<P=MIwh4ux0??=8 A{Z$eZ ־U@ XKf<,?Io:{-NXjYۈcĻgh޳xmǻCL/ `RQ'd=pX~1W IuniUi4o8Rv8$ڇMNL2j﬙~ zִMBY9Q&Ww B=c[8PSsΓ5T{Yul񪳙j0?d.-Ke mjcV>2Y `/dG~fEQrٖM-+|ogB/[-%^^qAaL\soSĞ-G3 !?ȼ% {m㹻sJ~9Ռ {r#R?!I (8Iִ6S|%B^яT*-؞vY ݰp؝¯osIbi!"F᯻OhDTZ5o۩+)#-G7jt֜s]>Fľ=LCǯO6czrxmgorN8INd2ݥݧ/dͩ++xTUd IufZ[Ys]Rq;31 Mˏ_5⤘rn|OX6Tuسmh̻*5Z|/З }1m7?H}FD|ogīy9rW֘DFݽ{1/~t 5_$4#zТi%׫jC^kjUZ<PV$U*_u ჎}ܘ%JwR?Ϝª0e ǥ -4wNw8Ufe5:kN;с1]J}̉J"V*L*Әw2&ëȅySݸU['pV<ۄ$|sVV4. Nj?ǻ/ߘP֮1nQvOdZ.xR;NY'H^VzLpx6?WU/V_ HdSBY|c9glkuK7a9Ye.ݡ,2 ""Fo6DTuzD;B"-#>ZQeʴkl6@1)3 -ޝ#7*r:{ %"9w@DO4Z"{&sP퇮e6Ո[YUu rٌB9hG(rov l洳iYY=HGP(kWnIsd}%?U_7՚ŸRȫ}hu]Ѯ3CpU,S[V[V;1hixys0k/2`hy n+O=b=8hf;q-:h#4.I:hYRÙzkuRVLpK}_E/cL~lԼmAY>z^|oU>Id;!RYB_" lPkoJD%>d'tt[[H&Q::Օ(nm=AD'=NЉwmfh~wHٳM0XF!q V1JZ>:ph\k(ph7;7>vϓS}*+y6~ȷDmX8Z;WNz.(:aMu ֜v6-7?BсSeIo5 ƚ3hDOY#d}44}T^H"`pWwmikoĔ;(~=v}',3߽}K̙3@DK,q;[!w 텗VH ֝ IDAT>|F1)ۏY}kXWkmǯ&i̛:,xeoyOXC222i30=m|,*zfǙ]P5M#CJ_L;?8x苉XCp `x~c BCW$Do~oVI"ֺH8\7s "]1}#jpbX{)0h:~O@ 0<pof>[| 0<P `hU@ XKf<,?{tʟFD]Ovܘ5(/t8xrLù}vUk[ " goWP1mDj )3vp2m3ʵ]>2,rtV_[ΚUj3'IL0=vf 'ˈȧ$xd0ǡ`%$g* e9o78|nPqW"*=Xrkd0 #Ƈ98r4煩awF*OiUgl]<5ʶl>g+.D4竬֡[zƅ箫sS/+|m#ŕuLpٮμ-=3sj.Sٰδjt֜\]uU7y*s⽅C-,]qe ]O6_l5kNWW8\)U ﵋Z.>IEyujkoPf>4cdS5㢥no;Ѿ3L7 wiޢUSc\ERc 'Fx9lsL33FwwdVVd99#֣\fԫDTqĉ>D"*̲tX0יׯI9.bH!iL$|bߋFDʛ&䪫U:=>\Ns rŦ7%ӲR+o)i:c8cC2A|nHDerUYs!py#jU_'"JϜ*'u7U9v%"2KD&j2 Io?yd0axHw_5OүؖDW;w3-mߥSV]-֔ɵo] ~fVKk/$|5O/ߚo@qڰtsIdd02 #<ȷTV$"v2=DT[Rk?'+r+R\eJnl4xxic߿,q<)뇷Qa:CUy™ >3.ՙhb`RԨ ?n襯D5L?I֜|{H~QixB8Q2*4[;eDꉀAv2HGQ>LsXs C^Wʼnbxs-j2jl'̙3@DK,q-~q};/p4ӡO׀Mp0{?@   t?tf`x( 0@ӝ^̎]iQw ݃3P@ (ER`;)X%d6sΜS'NXJD]2G]w8=xG2_s;ĴZR_(@ pu8xrLùjMsZa_$Qhk?&b_\[ Lk{VMUPښ5g>0 e CX;2oݣy9կL{C X`˲Svr{=t⣥/5{mգ׶t0/WGƃ\+.H|hbġd?=J9W=` 8Iִ6S|%B^яT*-؞vY ݰp؝¯osIbi!"F᯻OhDTZ5o۩+)#-G7_j9YU_}# }{8 ٦ǯFqRL }ώ]agMye :a_3w*\$ROqL~ɣ*O^w >D r7+׶2A]u,DT~rogk aI ҽnj1a_Xsj+kn~K[*kuO`^p䶃_#K ,Y6 Ďߣ?޵uGDĺ?YXzk>\N{f@/z喴7`33t⣥.vIgz3.맆xEj~^L:[ttO[~r:}5mu/;ȽgZ?Z]ߪeR\[,x&C&-`ӳJ%ȹ\d4%Mas*3mꖳj:xerB-5}tߊ5l쟧;U[&Ilt)!(3vp15sGHD}Ѿ,c;uioV(ǙCWSȤgꯞ=-kƘjt֜"x#^Zu:YWQD$N%FQe&-NODG.KB$QoF~e)` .D'ՖqZjؽLb U¢ e&2&.*swGfe5:kNV.EU=PyQ3L[$sW2mOV;(rTz_N5Du3|X&{f^WVMD72s 6*g oYs2s0OAZY|M8t6d2R3?ߵrЌ-gtM[PٟAǧd0;\NZeZax9V$U*_/78Ӡ2rcZT*% KٔP.ߘju ؟$kNVKw(3Lz2D; 4hYEšjGO"'gP":坡VW)"ba5U^u:y 5kw:QtUJB!"2DsTҠmtD9=ۄ0S| ~Z ap&8Z]oUu7\Ri+3|35o[РeO^9kվ&?f9mՐyPؐQ$bk(phsz{Gud41O;g)?ٱ`1B2Rlmg "RW/mkw8Jv:kD6w2o'7xs#bVK/rw0_0o<9lf޸VݗL+5̥/㯦->/h2v'kuSs(~=v}','.wo)`p̙U %K8f-J #g7 >|FKGs3onr߾bñ>Jpw8pΏG7b"Vp0<p`@ _4Oc'Yp 8 tG7c-Pa~~{p (0H Έ*x%Yޟs=`:؃ZfSq\@[5L- Y'ҖwNVXԮ^o{4ϡ\`|>P>P",EyѢN"L-!kRgY:rƲIU2?q6 ޕC)DtWߖ/_#w<ߋ:3>ItB%S<_h'1v8+yHߋ@ 8}x$sW?QP-~1r*.]U$VH@Dzi)T/DLBDZCim#ܷoLDrEOe( |!VdU}I#pGD&IS~yjhw 9;錹_u|UPk u]q8^HsKcgK)3LHaf\d9n2 T,#"n@KRyҠ1t>4^gk o1 R߷_ W[ނƫDY ߋ4DCz7m]8'ߝVxמ f }(zʪ/TukYZލ7{ɖ6|)kmD` barX;#uY.7ZH1'y(gx 4?O]km.}77-V\)wsˉhWYC ]W}G?^V^G+o]yy[zL}ޢUSc\ERc 'Fx9lsL33FwwdVVd99#֣\fԫDTqĉbQ'UlDT~Tv vmNee'C-؍('#N!?,U:,g8 + !ZSqEak/"1ao߃w1KvrV,b }oԜ^̜D>nμWH˛:{f'tt|Js0O7nԖIDNrh3\ c ?Lg+K:X`n)+>YTQ2&ae;9Yr*[!tQkѹW/{fu\+QJ){ /ܻ}mZ}EQ@S6H7itfLYKDڪydkA,Ke"YR]y+ktW ?I|Bdױ~Ƶ|VolvOf6e:;֠Su} .nAZnǭ+k|Kt^ ~z*3}L˒JĻTSaQd|dwW^ßt7:љ-[WVCF܅)jU_į+e"ύ׌%LXVW+;Z* 쎟u՘5&SVij*ٚPo7 vxFmX9$Ys\y]ySi2+DÏ e5n.DT[Rk˯NBgk/":r p9 &"r+R\%DTuL%tm`]9gO[xoɵj]ƼX;9u~ԲqWiWou$ނ:il)%5eJ` ΓuJvc43-2X |'hq摶v}r/KGO&8{Tkj~޸p&`BĴoČKuu-X{F-3hq˧@/}%ťWg r=$y?4bVϋer3.uX0AowE(gddd8 g*=3Vྂ{!)>f IDATࡀ30\p?/~x 0@ /{᧱ߓ,8 hӋٱ;-Pa~~{p (0H}'Avfy Gd4co>q0 m/6<)G>@DY)w>ӭmmg'7Ko[:h#DB"b}#YN09I}/̀;z<۷-i(uhV'5]5-O_p"4u?wpW>{ζq ZkfVo}QZXOa^+yڻZeA2 f(/eƘ{RoX# ODҲoMw]X5s`x_K퇮,|Id3ӲfȬFg*=U3/^/zU-ULDQbU^kDT~*-DXgq8qrU[ƥw` Oy-t Fޝ#HYXODh[n5"=ւ>CD D|OWhZcy=PqzkA~Ik[ Hrs:yMmc igdMo֠Sus^)tdIDZ|vhXHD~"a\mܴ\fZ*&(+Y%,P ^n"hr9LL2wwdVVd(_4ZY'9ôJ":7~%F{d"PK.E ;w ]uu{N-t\sX#"VKx)YY=Qjt}ƼV RWVMD7vr<]+5ĈCgsL&S.7<=]+ ζqwGBmt|J%ET[+5.V'J$,RzY9ӲR)UXSX<,Hqik?{ AgSV,p*Fgi0:0f V\) "{]wSyBf,g'것|ךD?eju/WO[Yh[q+dՒySݸU['Zձ[TѬ ,*e.⻵l6p`s_/~:m232L\O S{}?x\r쥦n;7kuSs\>>up 4]prLV9}TvŏOtӬR$rq=E*_`M~bLp@r'RS9cC|6^[d*sefIoPf0:|{'QV#^{wDI6M6iRRQ?e_D_ȵ ,("^Eܸ@Q@hfi&Mcjd ޯ'9=s933Z.YKND||yWs2d:yc2H Uq=c5Yݪvi{0.whJmޮ#ퟜeN#7tsdtɋ./Ioy6VU sc8xǬ74@`Mdm'k8ۤZ?  ^YЉ/[lo+ ΠOWNa<1L۠1#U]u?Q/n_MbggF3o<7feޱ| [ >fͿF]97g]CEDA8_RA^AOU2{UՓ.]]R}*Cɑ{r/x$pusJOwus|‚B8h}=9Yd<1o/tc^0)%_ꛌ+eUb'-ZU\:6لwgsdmG7m)#}>q!>!<0 DvZG^:j@bם{jנ./L/M[jΤ߽5{q._O*~n׫Og9 +mb4pڨ q;aŁ#=602w>mqz<'}OZ0 {Q+ګP[#;o-||ޱξ9X0?}Y/bZ[faEU uF62F2oݕ~Χ?-d2;f!6E#,ϔLx-ۙ)y8Ze;_L?P҆|&ypQt|҃Rjs6L~:WэLb]a뗼⎎XxI,="y8iLZ콶LV*3g7_wSH܍LSWy,HݝcN9e^V|ͪUQyRkl'*.z3/,:Wye$kd?]Y3U͑<4:>8bMd${=S#O=vLUk[zhs51БwrYPr՚'#}!==[ iϴqPi;Y:JR$'-ߕepOU2(m0qxp?ʲLlѹ_J"J؞C.jx;u_yI1ꞡͧ+vey_ {ϒ9n.)L78*Yd%6gh̉?( YXh l^|}K9HemU-ޞ%~oQ 5W,_w=ysop:W^Yǡ_="+bd®a/Ѻ]o(_9O!uuZ0g^ּ#LVuq^\si-ךꚈDy"ܵ.ޜZkN@'"zlLŠ*̜i͇ qĚȊIz0+T4;6БH mK9|m' =[[7+{9 _L}g7U޴qne7=y3֟^N=@{n/{ +jo8 t`R sV4؞5T5L;n2dxLbEiUer}YϺlMޜUF!nL&e-F"mjRcD-겲 Dkl0QB;g95\,.;|.V7k6b{fjOxzary^ʼ=R%jVd* "Xo2$\d>*z5kSDD."~Ƴi[5}~eAisdڕ~v}aƷ̛"w#nZy[gy332W<%64ܣku2_Ǎ w7 B&gYϳ9gKNI}weNKĂOonNtFg!cYঐD۹WUD$67|8@*hHL&F:MMFDĬIJ6WT_\Թtr({GF}YOW[d/[B:Z{+$gUvb[3;69ް)4o ʦ#mԙ8 la=X Fh=rN+]_MDedD~j^x??.޴qDk٦/v{K;|yw檲Ot&8Xo<{e2UV`}#35g" C| ]|:9]kI3 YN<]e)jԙVns|pq&2kxo+{)MM NJylO*f8^}v1œ?; --͑lncu:w#b0Ѣfn2ݿv1@ǂ>Ί'ܾ\ ?⧆O 8ttx @ Ё`sidsh` @ 0 @ 0` x<q@ ps"LL&{kkkoc{6oތN6+..޹sgCC޽{oWgd2a 0@[L&pQ"矉Hx=<<͍ɹu.]D۷3Lf}) X<{lNg.>իkDDĞ={,1m0_lu 4k9Dt{{{^rz]֡cc`t؀R(Rg~~>ロ4i{={6Y 8;;kZOڊ+hsεȑ##G6,77"IIIab<9TZZ#ٰ <ĉJ0`@YYF! 6իju7g6 K,h4L의i&";{Va ȭi" CL&Vx0Z̐H$SLy͕LooJVۚsfFI"j" *,*,|r3m4&V(SNMHH`< -85š`0X2OkVhs9{>|}N8nݺ` @d!n=h˖-uuu7o&={ZV(,,Ig8p@16٫qe^r\\\,XLDIIIqnѢEDtRD|r"Zx`ժUnnn ͚5I_t)7N$x>>V(g#Iұc1!X|M;n|x~ 0c3H.~a @ 0`0` @ NV; G֮)̓`' w  .קqgRw` q;o!"2%]wfU|ax̻SDD<$P@q70p`s: ƔQ.|˺XgN^YygxD'` 597%jXg3NR4=d\b-g9S {Lښ兦a3Oxow[i.jo8OYx<>DT_T$.+_h2%sB}]ڂ55p|WmI`*&*;df_$8=甴G]FC/LNDkjҞdd0ܝe]'/N !"{#vd-1v%yÌ:Oъ9yʪռ_̓H?ؗcVT^_i&w6dqO7?NǢNVFOY{Z{R?cSWBV:?o' e'>U$ξ.DJS|W_R/t=7^Q9f9]9j\;F?-3r`\L(ty뽼;n|pi{KQeog_NWQrIWû-ݑɱ]bgAWd{&G1u\5}GYP_"2J"˚˯ZӻڼݹD9CZb τ,_T\r$xrgcGʊkZuEg}>:Y|uM-Śkj2Y"Kʤ1W -nd|z~]6Wx5&7.^#c~Pc>9d":R@h)l[홽%5s6iAw66&mZ*rd~#_ٙ]H;Y'wpN/tK(cNv ƳW'LmIcﶴ:]Qy^YN}E|h(ς ̙hWw՟-6j@Xn 'Tpg7\!5J6wx(=R#7rz1yq|~qU.)*?^.84M~Nw)h"Lstg86RW:J(~^Sj(h-ܿeJ{0kGD6O!vv%"M F"uQ{jwW^:}=n8-:29˪u~Be>, lb=wn8 q3+nЉd/*wKLDDҨս*}|z c> ppT_SQޞ\V~.9%n.&_VXu2#)5ʺ&7=W3}T$s9c_ߛ{iϛ8ozZ#7?;=zui&M|$)/f}r#20jMs<ȖXn޺+?ķQgO!B]i*!7܅yPo834 $=4g}a͔ӑS$³p 4MpL|yʺy ߛWy}86rmj9k/MyΦ,SFG{>X}@C|QEzc}q},{jyN _W&9c_؜[Z_Q{egۚZlɨ3HoխpJ]7-mVuiD~>SڵǙtՅ, 'ΪGRO97dyѶx:bꋲ),˺ohI[4]xkRX;kXk+/ʦ{y\m~Bf30Mg>[*2WˉJlO t4CIM ,/uyH qV<*׶Vn.f\cXs(~jHw;^X: z?lm`@ 0` w/`"IENDB`pasdoc/www/screenshots/gui.png0000600000175000017500000020307313034465545017157 0ustar michalismichalisPNG  IHDRp; pHYs+tIME  )X4tEXtCommentCreated with GIMPW IDATxw\g'!!$$= ("8QPm݊VV[ڪWjUTW{aMcHB~lr\_c|DB2͙3@_h,1WX}d2TP`0=P.FgTD_+j$Jj@%6j+* z"t`UY̻%%%xId>PW$tt*t2ni35r]դ̵) \RgWV EQj2N:RoQQ^3?.[ʤ˫>ftiKDSatUZBPY;tі(\P(rZU-yyyxaW7N46b(bXt4eX^ƤK[_B-cqff&^6<&f---lOV5%yIWv9'CWPPӧO]L*}:r!k&&&wM>>> 6<})5Ww5 c{ve2 b.윙iiiI?z_U=AM9N֞HP;yxxbD"HRL&RW)ǣ36<O&^A9.dF*C#@P(bJd4:j+d2yX,fb1]LL*')@г ^II4Ԙ,[^=PIR0(B`[դ u%*tUB`-ݳ =TtgWj..~tYy=h>ГBq8 5vqc~B]1>d2LLm+3Ι͔n.5Vjx~lX[Z5kڙ5dilo֨A.ںsxա3?-H8G;[xSgϋW{t̠]5,P^ڒ.{vU^K@Mp_b' TՕ?k#6 .)Iz.{L451Li4=3+=3+.z?^Uu>zܶUu׉iVDXa2KJOQr$mѣLJZg+3JJ0|pw~Aarjަr5sV )S32Npƭ'O7qoȣ-uG!|ulo_Xu♋PW?=WK$ɳM=^&1Osܟ!RӦ.zJZy+}B ل\w9\{+Q^#KZr9u\+גLMzvبa}eͳDgnմD"}hi7<Ԅӽћ?~]j!&sV>+ӆC6^<.^#R(ۖC!e66p_~K\µG7t-FٸBijR0L&ˌF>Mj*JվD4~;Vu[TkᔜHз{辘Xr +Q>Vo3|666ydΒUbo2O8XYBffM=ܛz BȚwrY>f LxL0}t/' c=zT=~p ͒Ie,6k[Xj`IFV6lPMGN%|XZ8wOX+ CVBN2{r1_P(/bbû>ݵjU",ٸUNQlkX^;SԒ[ΞU ȻP.7nede7oI V|!l(7/[$jbBE"nt;k+Q^ !xFOge[ U?tefjBɫ7o]!C6[GW{|3Sm}ĽAp@lQi>zR,^=(J l2+P"geƚ jiZ}'_>}r\p8l6fX,ɓ+J_ttthhaՍOÑBBAIIT*e2K=Nd* &AQd2鉪,P( TZ a2uަON1X*}6gjҸQBahhh``@WWxL&S,kmr ХSmժWktK(Ey<.Ę^X!&$}(_2@G&%% BP(LMMy<p8 UO,3 Hu\.WRSAҶZYG&hVztP[jX;.`LM E:ZD &\ELQ>am-:s>eqC>LE|R b.vwbvFPGg>ZV=\.y(&>V|г  [dr]|EmH{w@]j_|5'f&T\ڣgn@?׻QUU%ڳXmwNLJڶajW l.;~4 ۴VS&}mxj:B|A)2 aݚ6i\}5V.!DcʔdRtvڽc7 l} {tqv5ރ C#] LLMz6dف* ~nWI"Z[YiRIID*ئϜ=.;~5 6MOAQԶ B@nnBAN:ڤchh``@(*/?e26ѿ.tQ%YO53 XuTjme5[lYU.**ZqE1 V?D7x(!$]ンgEmk/Ko?,;' !3Opoqjy{߽w6V={EPmPnA~cǕO6l{?/})_99:_n\ֶ2urrjFYfqz7._&??_mQN0i&&&eJKOfh.[yEn<=^'&-[j}GнJk p8>lA.N֭q/;nָGU~YUo߾={q^j:H5b8{Pî(7wɊʧvS_0q!8{>¥}Tf]:vj{LȞ"zB\0/v[amZwkvv!Ą~*JzRmwoHB~} !͛5۵wOu J+njVnB5 >rY٥ yu}5隫۫!$[oaC566jouttؼv˿zsBBAIIMNL$4rrt gdpwĪuʵG&M(:v3޼!d;?z)S+Ѳ[4n䉷ް[1ڶuW>ussb%iu1JB^^ɤ;5 ![v곊\.6s/{vn~ݳj+aBJ_*N].΄a*ߊ3!!t/I[V,W2]_ͬg:*[S:vP.k+PU=yr&v B#$NUk;Ys^7MLT"2@ L&{q/Y[Y5j{~W*>{¿kU;Aڹ}`N >ͽrs޼y%B8nmFMDGڰyˈ1c;\q#-=OH{;;;䤭@W116!ܺsW׉IccuQnj7l@ycLML$7SWRa` gs͟FS&~ijjgv3L'G͚X!탃 ӧL^r_lپ)==mZus ׮wZޭ{}7qJ x5kI!A=Wquq=rmϞxRRRQs4nEEn~AC]]]~x@`Lzd n]ưw^=#,*`0ƍRN{ _|enn>xY;=zx瞽'bOeX[Yѳwձⱃnw(7̬{>7j8bC6sxrX +a1|՚ٿΥ(Jd.sg޸eUry#O![vڭCawzG]7ouc[l*QdJo1 >%|YpP>+:)+0C}5bx^^޺kabtq*2&YxUuK_IW9ߖk-ܠ~?<''3(Eaei{vзoH .Ѱ1? B`!vY&F;xX\\Yںa]8k+ƟxQ('铻Tk5"RC_LƍZ|کC==<)Wl:@$R]!H!L&Sº p%fa`PUWkei`rAXdoz/223}Tx(Zi-Io~3uD*7@º 1(o Paԩ]M]SێBx@ح[vNVzYj.] *էm;tR>qnn""v\lccg_oal+;Ɵ^ª0S7 npܢ"!y~2EE\.JR>V[\]TTԧWd (ub⅋FFz!ȩhصNqКD,9;T.j#:o/ /\XKc2f^Mz5mڹ󤯿vsuZ1~]Tk!5Uf@-7@HQTJj . p8;[;@(+P =jQ# zbFf8ۇ5chH),*ڴuۅ223Y,VcO}zi-Q7l0_]{Μ>rv|Rm䰡˧۸.Ç ؾj+F^ pYmB:ЏtWW+V}a!_Zr%w>DE+˭,lp+vІ(%v<}fmmEO;#G|>6:77w굛l=˼l-ZhiaQXTt l-BB}Lzփ~Wlղ(]1gE ~oȓ=֭\niaٳ;wvЁr%] Ѷڪ`0ĝk^9 Gmʤ.9yԯ o!=MTxæ]KJ1e}kro޺tASE?qӧ~52z,߸qd^cccB,MkmJvvvYYm5&jThOe )??_;͙MYqcnQ#s6i<9j`B=:J{79ozoڬ,  Pg\.ktԨn] !%vﴴtztnV9Rϭ((Jٍ)Tcnq뫖.]бEW[3]۶;v\q3:*JunX S?y:uDm&\zR ]ʢjJp^㒫֬}4\nDܩ ✟~X|E6kҸ]PPP`eC[jZ=+''G(4W]<;;"X[N~+^*}e7msjN cQn\K uuEVV88kvnkFM(CXJJra{*H<|y۶}.^g \ʕwssE_@訣+^&raWwAVVrnVv2ʠ\!J$C6[4  4xgΞQԳw7h`˪ \N?n؉P gG{.|q fÃ~߲ũ3gT瞈=E]+֥wzmo]Zv:բ˳srܕ5/O:!˳vӼE߹woU_~5IeAk֭=}F$rcOYaaCQQ1Olؼ%5-M*=xYߩee(Φ+1ixيhǮ)ـ /s^IIIrJ5ksD"\G W ('ON:fC;fȽٷ?+;;+;{o޾UƐ>[vu]^isJjD"p:k&O#~NdH /!{صw_JjyG .{?-yLQry~+o߽14lnʤ:us2wj:i??4|:bccBP(fff<r8]#a:WgOy#a'kA1|4vR o+J[woBx\eDqj9AQu*XQUuD)WfP*Lo`x\^Qqa\@SȈM.jY_x_K!$}E蓅zT_6Zf)XFWeԿgiMzYo f{!}=zf]MqQf-*-q'N_*@U]ZD"@!O$x<n*uW/D"@G}ꅭ-@ =P7B>~(ؙPr [[[E@B!J7]Kd2\{AMQ@]1͒ӯy3G X~]ٯ2K*\c×~Y>-;׵ի]{ݾ{7//̴yf_^-ܣNaݵ:s<8@m S=o,-x~dUAnaW4p#BaHtoa¸! U4u:j UvKHa2*%f#z&rVM^|/_=Qi`Uz&)Rs Ƭ.* x2SSN˓6`8 =lgL^ڎQ.kWҳ%X[Yj[ʸ{Ck,-,rs*\Z»5bϧ(H̱fЧ2GGSā[_ z=|[\bQb\pH9%Tu3e,ͽn&SZ3y^UHW%'p5Y|/ku1>LJ~lbb\P7R϶̬,>߬¥mɓ B>{oS>sc҄b2,LX= v\,(t2h. <ݛ v^z8s\&<|42rG @TD'o%ZoinjdP -.;mlՐlwEUobŌq!V3 I W]ј tA_͛WIIM(){́}+֬Y"6kdl(7W׊M;]zs0rPtWl\.o1d@8xD_H x<.p'nPaխY]M UCW"7`2qحާt8|KIa)ݺPNa9N _o~]WбEar(=|г uBHHKIM)*.BkGX08_a>iiYY^M,qR|̲?}LEkD5tak 'ZzB7({%h)Y{FKobs }3>iN([:&y))^Mf|D-|f|Owϻ"P==5!RPݎ`Pv !jOf=y\C0էO>MNIQ]15---=]p[Ea.|㯽g#>:q߁?Q.)]*>E,Su ={>.?@91?ʵkAADe֮_uоCG]J1]*]+YQJi}ĉ}SbNh߮R]=Py6i1ǎtxbq1996UaȱcKJJbX>o٢6o@I柄ajg;ж|遶D>##zX,Lv$؟ϧĘ]Bw>q2&Gsю;p6''̌ߡ}\.ǘ]v7lwo5W]ru}9'Edٺt#4.5"R]B|ŎC]pohiamEp8]NޯP(LMMv q9VF}׮\L_mko\WTj zN#|m8|xمʻ;w=gllڹxtj 8XYYN;:JKo BHnj(T\;xgQ.j+W幺D֥S'z[/[s 1FFF(׾h2 mt|\zFjڸ0vRن-[rIFP}8F]:w& i;p|ۤQCG_{/ӧN WEk4{ŒM7ҧy bXccczJjjڈ}zEn^'[oĤi3fN2%(ͫ׷2-fϱ[|eaQݻv݋[3ݪ=AM9GXk}1n2Ւw:w }\gӿ팘cZׯWV9wmFw B? i?էwYuu"GGz5k 76^iS'Oں}v :ʼzZl:̂"\ح1(tҙ~v6>pح7/\cƍ<{ BȣOOJuࠠ;ҳ!jS._~J ߹{ǫY VsuYmeѣ5vgWw }qxn P}(Bab``߲}d~?-.lnnc]E#ָnZzzdS&CG~%K#j$$888-Xc.=vpNmCKgƹw,Cî* 쥌99666*i5%(&W!zAZzSMlniiQ-L{͗H_pq/8k&j %B}"̑iяyz]Ww񒧇{sѽVG8 E,АްaȞy8j(\.]gS 1fC]{1\܅7nǁs rrrD99V]7rPzpѭwbw\#ܸ1c[acrJD"wogEGEݸ㹹׮ߘ8ej%[DGQ?.˳c&S`T cشv#GX8=#4_oͽݬ[W'O,e2T*H$DfBh&NkZܼw|m1qX+rw035Ck#666))I( B@`fffjj\.aN E5#pl!P%vnVVvv@mFQ64.|ZR) :a0K^zkw囙6ol`իC)1g.NNJEطbƍ}/\?hVmlI *Bݐ|溹S,-{Ez [gEtW&]%7Wݻ?x~kO9dѲ IDAT g?NLR[QJ{:q?{%+V^$Xd٪}?Zԝ{&L*g#F=ZlZzo 7xh'|yUr_M 'W/pj6˗AuzvnyO}qVP`_-3c4]dLj! !.\6c撅V4U))gl@S&BΞ[d%X5|ǣy&2_noo׼Y3BHzz)_wt s/^޷/];Uzɂ?O7LJ0ȍpoqӽ{F8t8j!AuzvnHKϰtH!_w~!;նvm޼Q˻ޭ+B@{:>>۷R+s lZmGR>mִɋ's'=6Un6b"8tX9xC" c*99Źw)VV(Jwɖ=ͫpirJgdf'977R:D">_:E txБF E9ì8az{_v/ЏML MLsSt:B73+7piff >dy<ͅ6336"B@ YYYsEBPǦ|~6m<9h B;@0ޑ==uWI?uwx'OV>fRTsqqOϞpi|} ?sY~hUJ Կ|+W5__{8s\&<|42?@^Ǝ6c#G323e2YfV֡#G͘9aXe7g^WwAIIIrJʆ[r`owMIo:r4G$9zh̰*\a:rTY#G%'빿C ڶs3['z!CbOԴ4DJټu΋D"Qo޶toqIouW1'r%]B*o@651quuiںj:ڊդ!NNk|S^^~J?evyyy,^. BC'M؉ܱZ3׹E)/՗_XvY&Ey _ݰqݦCà6S&~쬫ٳ7nٺlj\c,kk% l޺S ]]맭JM7M_eڔ K3sfA ucr\&IRD"Hm&4 ф]z ^~}|gL~ >b%o޺5tTT@PpxdCG }N)))m៝DǶ4&o@?.]5MH6!EYuKoZ:-^gu@g'' 76kM7:y׫}F6_.Vmk77o6~lt.B\( :>z̦tlZ:\vm(;[[73 jbb)լYRRիWLW]7fanH?sޘQ#|}/\+(`>$Xmmk7=~2}WSKǦC=7EKEVGdD-@m`dhdoooceCQPe_˳] P[®=!fy굽O69"7UWjZzzdswUSrJƛ:U Ug[KGZQy璥}y5mHHKKOs5 R!v6vuVvWS/ rۚcB-joՑ/AZzLMM LMMTP tt横y{o9.h[6:nFۜl}Ni7O6_"N|} 7]㬙Ǒhkge_jTb߽nJjWS/_"_ߌy]]aWVG0ne\޿k>)2[og':vJc==W,]r_&:{wEDڵwIZz忧edbs{ޱ#j_l6h3[j vZ))n=͆MJ8,\"࠭;,_p{ 41^2,aj{Yfdhm;zbΈFu5֭M  V .ێ++\.Owt1,A[3B֎NxZ׬Z'2+^w|f9F{O-oXcD9c}඗dແ3@Rޯ[[Zi9N6I|]ͳ9 r+yW/aί;CڝNfl.\)Iy ɨ!n"{u n]7BTI|p+#Aĭ`X`1h? }M:ƈ! ?~|=;9 E:KHH .B$$XMeH+ $H*v0@ ?&-(--516ovs豳/TVUiO7nĹ G߽ꥧ7k4+ slQ{\˖e<?kWr\ב!uϹF~ҬF mRw3ђqng3ppfq8>WT9z,-=CQQo,4o 74:p='BRRҰ_?,-x{al4%*[ㅖW3쏹|*N-]G콚}` 21Y8n$wD葴_(-d0!bVc{%}s=~t?|g;ƓCK{Iaou =~@Y'm|kLss3ߛȰ?a !đBFs>6+BP9l#r .!DnﲦH+0.B.P˿aa>޶3JիP'GGg7l޺(8ha\Ľ}u7ܶհ?l͛PSSf4(`ommNu{ȇ+Xlea^PXu::$zxJK-}`oʫׯ^!0?hάD:|$ߏ Xi* O~xŷG6o7,Х+WCݣI@ }SZ !uyp!"xod_s}/l5X^m;#6]3h8]_?` ޏ-* " &J .bp!p9ҺkR2DBoU 8W{.GYIo,lzCc` ǎvq"6gڄcI} ]]BdC~[2o(W"<^xD$e0}ʔN#BY0(;$zqqn|g^ 0ܼ~(}DNI&de.^4?FsϞLR E2zAdQ%ֻW/, _PJH=&o<6=:?e@ܡc:'yO8x(q5_E `Svi<\ A(W;>q808FF2ꙵ5 f(GH!.!$b7p31ɓf7WW 6+˯z%[W~ O.5h7o[jn޹R `8mHW ;ϒҖݽw_yEE%Xը E}'{}1n_3:r$U\F޹{f0q/R:;6+[+K޹/^Ħo޹>U5MM|-VEBw}(YFF>}]h7h1 oA?yjkm67Cј]$e(PY)la|fn.qcc۾PgvOwf[.ܾCy99|-M ?)5X FRx*))UUU%jtnK뱗eSzs.]YMZktzZKI$1VCGGVVsW9>nQ{7yC[+K XըИcNV"'+[2^M/@ # zu`4FPsTjUUߖx RUQi]wSM uޗdZ%JLJ:zk A4j{D >S &س6O+;G PNa=Bp8X .ixeWsٵ\äqՈE粫.qam$|?Z[~8Rt555%Qÿ&8;z}KMZ|BWTt}>^zЁeqq`֍ O=OH[2^,IUnuu %-A .z_BU]PeUJi5DAP#`s0(00`AЎ{Rc:!`=jNv0GCD xf!aq\V5]eѹj.epؿz. cb p87oZ[nyK50hG3 |=7W 65%f.cE!͓+*R}zmk֕\ը޹.\lw[ (} lfV_`3.e  4> $A>cxFnߖu*Vh6l(_iɿ;7'/_߾4_s\KKKXVG,S,~[hpPТŏ?n1 o;R$$$==K$wo`f28%ޗ陗1\.1bsYU\V%YeUrY\ˢsYt.n@X삎.luU'h̸Ei4zƥظӦsf͊=|BZzuuucc㝿.]֎&4:Ŵ%L&VXZGSUUEӏ&/.)!JKe*)%u8HuU5l,||tz5ՙӧbs'O{t̆~gcaijjХD o >|H9q*Nϙ5eiasWTeee?AZFfiYͮx=况kVkBC y-{'?1 '.ZTh ,qN:x~$瀎V[\.`y$˜'OUhU4ZS'OYg.cW2HV*asȔunjⲻ@Gٿr.igkcw FMW.=>!aÖ!^zVndhHnK%"mۻ?f{D$6`8{t 54F98sm]]/=S CvD4m˱Yb9;7v766:ۭ_Bzn(K"L:lH6m..)QVVoϜ=׾ {[Z]1q &s@:ڭ :ڻwڳ7*z?IZv%عVCR[`\pn^o)툹P&FQ;B/)+////CB0z{Ia'9x| 7`doO\Vu' xf7%%b9rɇ.(((--Xp!fXL&`0dwWw._0kywuvtfMٰvM!|'Il/Z0+;y9~Cg:ť;]vtҐACFZ Dz!V 퐑QXX￧P(QFP@8 ωcޤy䤟 ܻSƈ%DW}v۶|f'O,##Άd:{ޕp |}Z;2W@ t8W[[۞dKII)t릫sؐ!^!۶}d޻ojnyf>@i awoA@ 3C-;?go8 >Y<}AkٓXdGQV_ysȂÇ 3u U;~%pf|'NNN4K.d A&&n{鵺[N>k)0ft*V1} L4)1)iu؊~޿;7~gyyʱQC,K6[wVTVjjhL0qlq^.+/424mwNP( Qٽy&^ґ9ۅ,^M|(\|P+>,_PSS,FmܺJDGRQV~ŚTH'':XNKK3:jJ}CãGSS!hi}V_O]u3Bp#GĔR6=deCcba.An8V^^!H&X[AQRRB={񬩩 vt*pKt]IPJ.cٳYm޶]JF cV쥧sn9?6KN2LPjjhs= \\MyM;WC_KS%YA:7sG.45M <;脘L&gNvf_*˥$&(Nm-- f'Og_SǒO6dȵ;)--eЧ81Q;wdf] nq8E Yl.67&.܅ՍJPeel621)t ػ?woܺ{4WO/6lݻg_3!;!^Gm6EqA7'OQk%6wݦ-BW_i(;zkQcW]:9U]]~ѣGϛ7+o0faRRRuu{ p0^zw%|660goA~SOlب6~Ӻ2׮D4oL*JsosmmD̺xVk۹{YCMM' ?EGIw&u`ˣ\Xx$^.)-PW-,)--+/^zp4)4$>~$%%SRRtuu׭[wĉȍ7JJJֶ'g} .J K5TPSSQk}6m퉕= Pqؐ!b`+ײ׭D";)beu&yr=uy'OtweH~km3{&YAv1eee}||̙2LI  'Op3]n1'O Z8 $srpޘ9y&FFs|u{]QD9&΢>~}J:y(&^LϨTUǍ3_]+*+OuYQQz洩RR_:?znD.\FΙ9d;p0zqrt׵kW𹒝``wm [SS{PR˧L?aa~Dƭ[GS tuNdn6CB}ظGOH$;s|&.9?6.z hee ߻_WW]Gg{[ۖDAM/XwwV=PZ=ZjI[u{|hr?w)ݺc%uu7={KQj0:T_׵! @'4^.w_rY6VVk7lh,Z կoߙS ^Y|Edv[^2?~*sf ?}ڰy@ccln䞽dMԗ_oTT$bsC/>oq GΜڵgٳjkk7m۞zLgMVWWi.jx=xM%++c|+ײjn޾mmid2}Rm;" 2x0@߽e{x銰.K蒑{w.NN ݺiijΝ3c{vqv"+(hij͸tIz&Q.iKY])>ʵ195uƴ#)EiSRR;$G3ziki ].QDgi>554 [jeKmh|*C!@MMMN^(qnkׄ"LDx9w?7:whw6udo޾O`€Ν;|ٳgC ?:`g_X_ x={P6ΰ"ld&K5c2|IkK |ZOgSSoI/]%4Zߧ oݹ=}AqXE*//G޻ߓ[fs-MD|y%xBjܻ$bZ ߦ%%%==ObFEQ{I|G]*yDoFwݞ=]A];נ*1, Ut~L&III bA]Mb|4-j-~q8S\]]ڪbƜ.o,njq ?} [ t34v򌯤AM~aYWq鲓B.-)>YWXj At"w.Bhwkjw#D h5SvPp.ΜpΞGr7ׁ]Nyy<pi?)))e˖Q(a 4 ] L  <QB%5WTTЭTT$='NI*t.Aޙϫy >+g7Bѽ;^22j߾1W`S'OJXt( #BӰNR;d(ɂ^蒼ܵ42\^Q҈6uP--/L@.;Ў}'CMMdNG[{~@+N=W^Qb**+Ϝ=dciss5_$hki. ?~1j` mG._FW՗^OH}7o֭^5 ld2 h?Jvw B 3Q}b{D䋗/FFr~ Ƙ ^u칏EEAs!>y^Ȣ0@'QXXJ@MNNNVVD"0fL)\g/?TWWzb_:Qvxƿ 1Di̓D" 55]x߬ݻ >hI% @ x1 X0ӂ3@󗣽" a2]Dwa?EMN=yJ'{7[GeIHH@7 |dW^wkׯ_;ޣ{w^zo Q{fs`PHοO4SS[\FY;.X{{پ6v^Μ=R M-ol2*r^.ܼq6N#`٭Vz{A-;F7]DcS ?3ћlvtԮ˗Ο>3;95U?7nꥧwX⹓s}*̷L%WL4r-޽Zyv㳧N=pcIn324)nK@p xIv,-+^~|҂o[oϝ㫩!))H&X[퉌POWgD ?xoYӧt724\0HіZطo_OwwBwcH&wYtyQ^o>6qվfveޓIǏO xg^zz;w.+/'p K7W[w-c;kA^iBG{;|~Fޒ>9WjE[qੳMqž x@>ct Bso,Y*ئ9~{;;;k'TUUzB)-+0/nyj4vƔ^jEoMq%ٕs|ߙ3O9:Y^NNp1m-- f'Og[Xyy֗T*MRUTE:!)W+z=Ľ ފdkTx@۵'8}3',)--eЧ81Q;wdf]\ =3eZFa6d- ]VKЋmոb_Y&:}^@G[[2s/gĤdA{_PZYUUYUr⤿le}}c]X]]xX-A/ں}m%-+L{WK O=mgDccM .evFD8`2owdwe{ޱ#j_4vw[csfw`hVD/ _pB6bL&`0M'S&\H`afwoXZAhUN~3בQXXHRT*B! rrr$ 2fd@  !od_x$g/p삟 odHvXod_x$g/p./rrrA] f45 ?}|L' u $!@,(Q\&Bhk(Ql6D f(hjhJH7rL&łP$@X,Jv=~r8Gkj(ML&;|0q鹩`Ὓnc `JvO+رy-!^z/!ɓ7ZaV3f4jM5F:hΛI<KPc[ srrȺx%X'x)>xM=A74;tZvYyDok+l\>znC߼}꭯7{%^g+wFd]*ѥy #ᅱ{豝yWߴ/ Yo>)oXZZp>+rm6>t̙kׯc>- [eeax(66z^Ϟ;vWSџ7:ttՊߏOy1A;iϙ]5UҲ::pMs-MMvvv6-=)JU-QRRm >a+yMO.]HYA,9+R(33f ǒmmB ǒƏ3ڣ-GKK%hr d RNhl ;,!CnܺM*(tSP膗|..Ƨ·lf0 <}:lЪh*u/&h*eee`fṦ\Jb6|' &x׮3 _#NN _TTM߻σ1vv$|F}4,c셝tdw ,sq[~ Y{"뛝=~^ۯoaC\~ƶо`ܡO–--##`2|Yj_֭RQV"(6J\myEŌ9sySst|ן9m,YW677?~4t}1L5|>޻F QZVf+++M fuͿRL2eoLN225cڏoL\ܹ o;8tq}?LvN>222b?#d2PEe>ݭ|]WJJKE(qrr) Y2ϟtd!4~ic'Lvt ]Kѻwas]|&zݰi߼$i%~W'Ma0bv@ ޴n-6kQpPd3k[> MW ;vX7ǎ_*GH;2.v0>~ɭ0 CD\t\ޒk׳i-g/Mϼ$Fdbw5ǐlMM64wM?vCMMv 47?zVPDrٽ3\pal}1̖%32Wb|&/ZLNN![X]ԾK]YUYS[+F4,D" ~ӧ7]\.?_ vsFΝr,,.'J:- IDATڛ} VD7zn.+f{DdiYJqsq ?BZ:6`qڸGvf:i\;Za5MlFTl3Z$]2a? fm޿?jXT PFFFaa!JR L&+((ʒH$ s'OsGD`9qP׳NZ@ @XYXYKh+[lllPPڵk}tTZZ喖746@49Y9M MuU4=[hjj]|СCaaa$SSSHvx(-/412QVRh+U/^@ii@4- [5gBBsr#wV7e ++)546>̹s͆!XP()-9ᬇ\SSㅴ4Z Ovڵ9v66Bgu4WOv%$l6XgтKf R(ӧ`FZ[#%6 ;ݭ MܻCrrrnÆ6t b9-͆1@ye0v8<~Ű 'GGgӧε=x3=w2yl H$H jNr\בn2BBd!޿;7~gyy~9 WV^w )@?46w=x@"G8RQ{.e]Z:ZV^^RR2ĸM{7o"z͞ece\l\>:o7v%n ķAPUQ]@^N+P(sEe;4ZÇ Ol FkFŚyn.Σdeen @B ,_44W=;/ `oyt:=2joؠyOEEAfL_* !yύDsӶff ˷ZYZtE<~t.573"[WY'2ban c.ښ ]+Q$+**4JdWMU5lR&W8qZ@ȐdF:˶4k] n~dW\bgM:!ddhxaȑģxVw)lBNV6Sf’7g76wIXg}}l\ĝQ.#B7WCGoܶE.3m@M\(7x1_~栖/P"UgOݞ=-͇Ϟ;/x^`Y+#<…- gv%]1`==KAmǦ i%%!TwV6*&6:Bvmnhl|іԩ/^. ][bgcs1Q .n@NVX ʿy"dU:; 0R(/4!d܍_"mUiYׄ%xF{>lZgeee [{lNWUU]KUEE:BjMq󖉱l:RUUE*())UVV2Ma x+xfނ zTKSsu؊#$ii gLϻqdg⛚T-0]~Mr] Er)**B.]tʑjjˢ"|B)/K+*D!$)J_sZ%%%Jgp'V%sQI-~!tx:Bݞ=֬\z葶ߺĀ߾ ~"fX,&`0 FӿowÆ vƍ܌{!t|zٰ9f%ESufyǓ4WL&SJJCz7o%|n,ًL02T(_(0fqJvS؃X?ykG8BbE $t91sq1Vs;;@ef].Q:[c 5utO7nB7os`wQvͿagcU..`86:X҇\n)'Z[@l6]KoQ`F̜Z8t[Mr֬Zu١]vG`ji٪;[vtdaqc7Akͪ0#CCQ. s[~Æ62]EĈ… [O]~iݟ ]H`af^P)$i[SBL3(,,RT*Bd999YYY\u:8 bMKSsE"Ch+MMj6q@P9NqI1vofOH$M M* d]:VUQlӞcq8lHv`L&`&p @ $@ 1Ž}tCKyuojWM+**460s,'7%Z.}.GǴy׮]f좊#/t^5?2ǎ߼0h^Ϟ%iRƟ$ ?bCTUo[\Qb؈DWi\s÷lF:lő4?SY,Hv@]%ee䤥ʫY oVh|uA+++L$^LϨTUǍ3{֭) BzS'O27ݻu6v':,LO'愞~-[s+*+%%%i>L0 1qPԩ'ruѷ($g#-%EUj͙/+׏ӵ6|5z4AUS5Nl,z?qc<[?r^E2yۦ JTׯGD**mmB_ܶ#b܀!# {[o^AYY46*r-֖x^H&2]QO-whho۴AYIٳgΝ#N7"㧢?7n`n6ӧ jiibn삟4$ G\z_Uq^q*o~okc)touy`ݞ=.@PfNM46^07 X2\&Θ6u=6ѡ>)%u\3d7RVy3dbz(v=ݿ<񈜜B`>ܬ.q=G'MhoK9qlZ`c@]iiR][ݔyE%3?+뚳 rUi)E#v^RRRy7nrFĻaEEE7o-N, B֝;5yc!TS[{2TCgVTV~c ypр;qKv%I$y_y&Uy ?b47f\uhHVKv:x@vc &sOc6WC ݺat:]Q;B`rnÇ ˺ruόKBvviOɺrZpP%A{4ihkeii1LBB b~:{l[:2PX|r@V[޻{ $%&.vZ}-yVfWySy]j3kόY R]MWUUKT*vuo+Dp_ҩ'edXDhݺw& DSCc 㧏/^:o CzdSR~;v]2vmeߨN$'e1a W] Z=s._@W^XDr9!c=䕞U||}95^CsI`}NVVVʊ>o-qvo}}lzQ3ۣBHEYYSSc222zB~9oIz楶DJJd I奥{rϵ׮紻Bdbw ަu[&<ӣ#2}EIHJړ~i箨{ǏАRRG:9%M< b +%jqgfڱ57M0SeXe9wn~Ȣ7<|q6/Ѣl{# ^ӫW'$N8+!!윜zy#FT^Q?~򴹹sqqlꚚD[KwyEKe]Z^Qfi4ډgLz$$%ef]ijja5mݺ u ޼8wQ]w++XƐx,gD5UK.CiSsW#\ʺ\E9"BqGƖϿve{DךM ZK>r'L?lV}CÁCWeKJJLSRѪ+_}rB&WO$$$)RX,vKGnv1#cJiii=ݞƸ8;[ᑻBz=.g`/0iDr k+K`|MKu:l,-+R)n..!]HKoSLFۿvFݜk洩gΞsQUE*lْv4ݞ=6]w}l6S'MjuV+MK~.]4 /Xp!fXL&`0dwWw&Lܵc{ gjnnnffce)/e8׸9N#tzd^my# pqȺ|CbtP)Oweg/^Y!(p.ve˵4}&z74#3 9YٰߗN9 KvBz>iuuu\DYI)2xš1db)"lcmub\.^Yг.Vgn \ՙ3S/G,8`NHL,))+G.2;`.rW'M ^zz;w+8?n>ztF+YIvԊKt{Lpy^s?|شϞݻ63\UUޅUUTh4:RKsdMs-MMvvv6pcN_NWn* L&+(`CjO;l\ݞ>ċIJW~#q=ˊ * 6e3,P윜a+`s1I>}n$H=wnzf&˴Æ!2gט;2.îIv{8\#oh(pB"VwFVVVVhG\\;}AArJjeUUeUUrJjʉEieel621)t صvw3'رĤʪ*IIIM f)GZ8t[Mr֬Zu*>w˶팈>pd4p::4&xm;#ޙCս 3(X]Jo$D,%RD{-6Tʚ!;Y=Q*E%[ 0~L}'3sg o~99̝3P_Z'kjr.-}vx<@ gFd0ؤyueJnc%eB+t5S7YaNCU#-WWwuL ˨301cv.v=k/)+  FY I E]Y{PUMQM;&F 0r^|il-<LֆⲒ$$$>qB\(&4Q /NIKTx-52 F<|(PfdէVRϫg[鉉O(3EI\sɳg!x"z o}l`bzBHhYŭ^i"R'XR(J|bRNn׶VK~_L% 9o߽ K4=ojwSe>G¦W8/^aܸ"W:ލMH} 9YYG;[M,#Y`s Hv:(^^4WGdp۾mI_u#aɋG9ĩb~G{z^J̤?:SScvǏG2HFp2yAťe; ?%)!R76pv_j%@ssuV], @-ijj޴uqo&'n@,{TUSslkٷ AOvywv߽cAe1tʦGp8yZׯX/d]Br xTS+O?~dI'2 l4DxyQh4]so^r!_;/s1RDi!޹4 |jL5 jр&$Z[/ЛA%̊葖0[YwuuE޾+~>>m]yYYY0Wbb NU\\UT6K`" ':.~Rs[,1#vu1tΆ} ceaseKyxx2sΞ:ə$'Džzu[ 8'F_BUZ͕bN-,qp2]d[Z[^VUki΁Twt@Oυzs" pfLw4Yje`bf¶ n9Ok[?WV0vUS?}ā]r*=ա՟?p6[APaNnjĉ227K *.)4ITDyVO>TΙS Sxx m. FkNMt,Wau}ޞ⻗-|p:X(C IDATB3f1BDX@`֘B+a>~޵Sj>>>lbaI^K\l<ퟂu ["ۅ !,<șBCUaeߺjyHɩ<=8ގhKp8\[[;8 ٦`VƳnɱ}e7.'|;ӱLKKKG"?WzpΝ^! ӊV-XǍK$vC Kc#|̾YQRV~i8mhhz3`[Z&HJ2ԁOv!b0:T! +gs,u!a#)ЦB(͇v<Nl<O,c2h A*r ̳oTULRTum؉@q<#O.OD/J>s}UD> ENwqtL̊L&?}@me--mmmɩiӦQ :::}3hĽ}c[W_ޞ`OZfg_~nhBa ٳ.RX>sqt+(H"_<|ae.edgBzVv]ǟgIaNYlYdTtQvB{;fdt5;09gi#XeǷZ_}100@ekC\\\E.)!~鸫{AȬAgNiBB{zzDEDtyA>q%KS&;2`( lr%&D&L#T?_ـƦ&<gbdyCU3+֯p)m:eܹ;n)-@E"b6xm%vuHZ[s05&>q)4ўf{iyW~k-^qWB$'+c%%v"a`sF.//>2L"H$ҷ1z?sY, ֊~D̓;>z|pgWWWx<`0h4<2z{{0R#^ Y*& uuu<<|i|ӥVi5tay,9%j)l2rkjm[od|o߾~d/ee$1_y9丘kIZs5lgju;u-9qHxl{ù4gȱ~ݿwwLB"tK "Cˊ wdO~YyŞN=ʒ~?խ䥧(/8<_4ݳs{RJk`Ѕ _ j '+koBXXXXXf20jUxdJgŋ ǎ;mm^bb췩Ylra!k<&N矩k֘,jnfj$ ū2|43;RXxxEuC7$<ؤA]}GuD9]]]k Qو>L9gDbW|bҦmۭl-,V <7%UXRq/2#ƛo.XXNAm% IIKJDbWW8hnP}BbRׯ_&$&%&_wps !===?شu**(:9XSx[w]Y:#+;$5U. )xѢG] ٰ8 (*O-]~_?l~6*UUػ= k'+M:wƟ~!ɦ2ާቴ̺ HRBA2rSQxP޹wOVV\,8OB *fdէVRϫܾ̄{ONVfLԗUմ,3N-~?n߽X=ArvS])-3h LVRZO,_籚ھ5jbAavurD2VƦDĉ6za6Z}OldL!O?GuмV'ϞG־vF9,D葖v? CJ<{vJnnIV,>蓙~'sgLWe !ez{{UMtwVu'Wjimᙢdea9GP椥G]3tcf04 ﳃY<ʈOL6^Tbc-C%,c里B f#3e\dƅYk6`!OQ֝&)ǏΜ](^^4WGdp۾mI_u#aɋG2%- %fɩy>!~w53 .9Gy=A=vA||v6p@)'::@T\ZcSԍYN:-..{TXH˪L9̆2 L557g?0뚙+dc"4f>D `| jjN b1J,'5#;͑{G֟hGf!ι,cfN95R g%0~5ƀ'`jlthRȨk"o @F5f>JG26AzMM;:/Pd&]mmww72g욷o46rOBRB}=b :9'&  ǍXhdhtw+(FF񉋉ym\Wbb $Q(ީS|@]yu?%eƋGY,10x<~RFblcub5vNLq} j"C,b]f|JKIXYF~OMG.b`5h?r:yYY̺Fqd8;ah;>Τp\%%$lX㙜yd9Kg?ڑjy.zCEȵ刃66]E& .(uFTDb#$([Em\銪/./)һL@aia}cbdkdj޼;&*s̩yr2߾}-$29:.d & ܯ424`Xž@s3ӔS9y8,G hK ._VUkѼ[e_oղs"f"HEZj"Aկ_ϥ5ꁠN"e^ciVv7G,FpK8;7g-2Aʟ>}bK:4gُvdlސƅcQ#r`9` L2hKvyPh4ZsXoc #߽mQ_+ £O6_/Zv=ۓc8)"j jJa>~޵Sj>>>L}5s:D|k ̐.6ZR(ތWw::WMkQsKt"y3zdnU.@p8z{0UbbSL5w~@ӱCY!Fp&/ vy9; ?hG`! i\85" #&'Hvxyyyyyxc/=j[rl_~كͧ yƦ&c/'/o%Aƍ%ƍ W!/rpB(MZ֎i(.嬡`0Z™@,kocs!<~LKK+[iCE z"Dq()MQR!P=x>c;G"?WzpΝ^^yx;WCYzp&g#8A\Ry.zCEȵ刃63kv 4o`Ah>-5ES^:scvn___fQY%'=+7vd2v­hKn߽i$vB~a4fӶdS C,-3rR3fZqI m 3TU+nDd# 45fC_XD ::: nP~դdG{;v8Ȗ7K,3bC>7KX%c 9;a lI&]lֳa(s9VSEȵb#&Hva!mhAl%tK⹾*r}}} M--PWT.)!!#%UVq eK_ ~Eoo熆+ )qCگW,[]T|N(*cgc5z!ammmB¸8:Fil$Uկ>R Cde&^ͬ}ZFfZFf[{{[{{jFϟZ'{¢o߾=z윈y3z2˥7JJ^׼QUovήsvm& p5G mILrvVmٹFqsKK[[[rji,`@pKEcG6そ1 Qs9VSEȵb#&گW__L&H$?xxx`Ŧ sjeٌJ8Ay,-#ɳ===""VX;P5+爌E CdG i1+dXŬHMAG;×cQ )D CakG(0/)D^^^]]u `h4Hv,BPKI$damsQͽN=sB}EycķE#09h.`100 _@$v/2Xgi̚u%,$#;'*&C]]Ww,uVKAoHvOh4zm[~{clZ/  e9L$Hv^{?ê]58SKv!zYUaP#~dwҸ cO;ٵ\jWPIK:; h557?寭rA$\]SicSf<}fhb AGVi7]j a( +Yhv 0ҿ ==T\5ߵT#}: 2J>L9 2_VUݸ’Zxu͛6 OIKK-64Dxi\9uʔ U~''V޹E/b'YneCݎ={lmrsN;yAe%>/,+*Jfo"!) oC E]Ysʚ Sv\ojn)9wnSv_mo?3MfKaav*ٰsj/n.QaI}&8t88,|``LoPYvf;[k)!NK{r㺵ԒI 2|QB\ȕӦN9*&v:39w;v,AX FG{<0ҿ M *g3BAQ^=d)Bddس;*.NOWg4z)7ugid{X466MU22+n  ٿﯩpI喖ƋCWbb_VU] 秖 ŰOջ7 IDATuT߾{ONVfLԗUմt3k+pзpw&$־AlkCJ+ƌ16ZB&/S( y榶oimXPXbuu]Q ճ)2:A#"(5q.@zlزVm*o߽> ' LrR#JJ 0?+#>1)'7k[xQQ+ s%f̞k x9ݍgB#jkxG;[cEf![D-74]==1 ZZ[yxx()YYk@wj#G#ƒ.˪uv_bj¾iuxdh\qStxϿSuAo#L@ 3dG,a0‘ABܡl^~@Ç&)>yW55~-j]!))~~^i\0gRkfI3#N/Pu2eXF1LhA{|Dw~w53 .9e0ȳyxx6lp[pرYwn*G3AR‚GGF: FFxyxCQ(d jk79g׼};-\pXk@1>e⊊FIJHqwSTT424 JJHxc## ļ6YVR+11FNv(T)> UhUT/Q]7]írq㛮agrj:8%fVx</\:AR_clMQRZ:1pC;z+=rq?#(9G,{,qD/,wIpf|܂MД:!CA9Usg:s} j"C,bϘg|j㓭Rr)pK̤JvVX_^N_ۋ9#+f۽6ݸ'ߣ̛C~U4j3 HN. fPhnJz9-Q*C[`͝3Ϳ,֚ |D^Vs1Lw4Yje`bf¶++ V/4%FN^QGc2̠[*+HLG hK ._VUki΁TwM oimR/CRe4޿quk`;:;!}B.\kss3A#>g2TAPYp|x:7Q0_neʒԙ-6ps%ўwٹ{- =nD]+B=xڟnk.[tp{{{BR`dF~3AAJv £O6_E׮sqgLy{v,G[?EcjJa>~޵Sj>>>lba!Bê! 4]lc3P(Ypo~~Arr96MVt%!A5fB3K]Xq;7ӓ7_7n80ҿ h4ӧ/4g̜1éGCӳu&JNxYâdL&NRTum80D"fyhTmɦ@XZgdg.5_¬2NAfЖ~Zq6b܋gݡP Ƌ},-7hd:;{M2D> 㓓H!;d}pAB;$;hj.,* !8,<@ tttݸ A/&%;G0pJu%e崍oG M ML+-PWT.)!!#%UVq eK_ ~Eoo熆+I{~׹bٲȨvBQ;kLӘ=bHX[[[;x-!}0.yq_I$rU9Y)Wbbh3kF Fg̴̶ԌO?õNE߾}{^ݖ o7%N6oшط{a;YMCßkaBR2s> b2>Le8O T!ϝazY.QR捪ʴ}{vg_ϵsvw]k6IOy!\*edgBzVv]Gp#uFmWo_пkk(~|__?sS3\V-]Jl|m4658#e_ϥ6tw;11 Bݼ毩۷x]JGNVfV/в~K!nkQ(ݱu |fxȨ ^[]]2Ҷ,2|a[^AAv")!qˑhJgMoRkeeD\:wRɎEp/C1-#BHhOO<];4kcG?ҲliAAQ &$%k:"#e#쐡Na*q|/ y ӓbm޴޽3TUhk3d9pʉ&>q)4ўf{iy9.d2D"Hǘ.6nsje\\(~@?D9-!H6aC O6]\ ރ~Ξ9`رcD¢b瑃~}>z|kWWWGYa0AAA~~~4 FF"+%=}BF܂mlR 1k֕율uu]՗[-5u>p谵L~EPpJ''0  34=K]}׶-ҹ@-nkbpawS(976yQx;У3OKfM9`4vcd.]$Hv>QFOoʺ)pKK*+Vok"&=nP3OFZx"_XvAn1755\˪^|I$b:D} %`._Q)BQWTaSTiǎ /?, bhhwO=_<m{}=7)%e6M|hvHvAeLa1c/!ex!.nDBa4`0'O%=az8,?0־t4<Ёq V\WWã6Zc,MOOB *fdէVRϫgaWonn|YHxDm{<hgkljljyPH$JMhocK}nlBb:jj̆O|]H/_h]ykWZ.ge'&}mk/*jea?O"@@֙c&nIMX tak`bzBpHiyט1F]]dаҲ~ `:ָEX,VWGˋsҲvv@t'Wjimᙢdea9G^f-7l6hd}'62h< ?{B\\lJW А?utxnuAoo( HC"e}|&G٩+#捈?:SScvǏGAPSSL텅߼}{59xUU;}vϙjjaSǏ4 >`{6JOU =*ǿ9u6i4XR ny8y#**B=~C:=0肪~RR?|ىH$α4_BmygիVЈ87WdS6SMY@@Z<'N=*,$eUZf&dYK+ AnZfSjl( s.c`fk=7lUT ЋA<{%N{ Gr0S&Ovut lǞ$%đMf8lz,gd7k6u*1Ow7JρF5f>JG26AzMM;:/Pd)@ Tܺ}Ԓ؄[kz()X|Zu%&NB\❪jUBRB}=b :9'&QkY.573pxbxnt kgnArhJrrQ9d9VfQ,Mf8lz,gOvI$Җ JvK._y-A Wԙ?Ľ]R||PAa׶;5߯n/UBzUZ͕xQb[Xzwbi%yS&OUմ_ͫL+0~e噓'?~vOڒs$^KɑVQ hk*+> 8}⸰K$̿'+-hdh0ikͅde}F["/+ D&_MJ.yD"AF9Ah32aN|f0kcnfud^CJéWܺ>00 ,7XPȂzDwtvbk߿P( \KKknn|xM,C!ٵ@Oυz^;vc29d걜}$KY9-#fg_RoO^uB@M:G.CA"nc?8qA!HJH/6;>TM=\R&d K>$޽Rh*wq1S&Қ;G^2BKF+=ָ:cX }{Cl8U+w}1fBƍ;gVyEԜX7uu!GѐB;&(C@˘=;o۽'+;Gs qq62:zF$_v[S;f҃FzZϺ%=|ؑŅՅ zz\\\ABBx e$8@h@h b0s+iOٵ}u*MTbfB0L+!*)+?4644sh@HG"?WzpΝ^%#bZZٹ66()q1p*WW:9wtgnXLbE/^03Qrb`D}};wr ɮVx.A-X,!CP<KڸB,-wv]٫Z[UjaI$ANF9WA^x!eH0KM\oXK&4Ǐ4ӚkbmǏI2D.n㓓eHEQq}f d:0".AgY{,7+CBB艓Ԫ_?|O$$$q/0$ M $ci8]>W]߯q)4ўf{iy4}bHŐPB*[Yif: f&r׮]_w%_yRۚuʼswlRZ^ AW'Ǵ !===""w`(eK+ >lmxiS"vbc :p]X/֟t{N,LHJwh aS-7\%*:ylɜ KFdW__L&H$?xxx`Ń?}feRoծ۴9/+mvX MLv-u5uʊ ؿm~Ksje\\(~ @?D,= >H$ k0;ioE-˫nz0???dCBRR"uýSÅKگ_ ] Pj[i100EGwwwoo/8t֭Sg-] rB$v%$%/2X2Q}CS32N9܌FlmtU#\9t E{O:AMOٱg/B{~? . { "'#lT/k 0e he $ @ d.L&oذ.~ܹsywޞՕuS(?ᖖUVR zӹDLMzO>L\mQ營^Vκe_;R"5^VUp}]L.ɂ{ @޽{'##ooxuuuFUR(ueMnnAUZ6EUϟ6Qx.ʃ]Mur22 _ ߹]``Μ;zYcƀׯiKDEE%%%A e46L)",J!ex!.nD?==3  >7*6xuS_Ƈ3grqq!# F5555fff%aaa ..`'B}LCS[+UM Ӊ]]´%3[wck߿ HNVVSc6|JNZJpxDIiY;ٳxP(6Y3c*.201Nv!$Vooin2(FU?{zb+nLQR0לP%RĦ!̆9<ƦDĉ6z3Ha M g:P(!!!))) ]hf^^4WGdp۾mI_u#aɋGOt=/œvU"LU+gׯ񜩦qAV8J .TSssqtzOOMu?=~RRRb }b0~GW55`=]]XyJZd7-3k 2hygիVЈ87W h 'H(^d UwAS&Ovut lǞ$%9P 'N=*,$eUZf&dMC5~hXljj޴uqo&'2t_{q|]`A`hDAbDA%b쀽ؒ5N,(ػQTƒXQdaw?&N6 ,1xfܹ{yv;#5?OΝN:1 \nieeGjKw_y+ͫur/|3Wu1rk$KmگOwZ(J-eTG)1.{pXXj![m7qR9_Y[[׭]{voyInݸ$<|ԙ3A-MƵmZ*\]GE|p)#$dMRZ>fS%"A*wART.;th~F:fdU_&֬U?x@5zΝ;%2CX{7ntp(M:7wæaCuخ}))E|HZrJ*{]FJ4D N|cZnjgW^ -Dgc;R)(~}rV/D^e9s&%%i (maWfiee]쩳ّOZ5C`:~7~˘⥲鴂 ta™=si秝VqVVF6_lV/IKKQ(e\?T*oz=A ozyyzu9w8bBܱÞ}v۩{%ڶ8UՖr#r=8x뎝InmݱghtC$±'_&?Ѡ^X~,^+v)Ozy`6n@L6>&PnTZuŒE>{gxؐ_6pho }9Gsyyy 4{JVu霗|`3?~ɓon9R@|| /ᐮ]׮p̬̬ǎ#4[sCll>|oɧ4yzTrw.fcҭ[~Jmqz۸Vڲ}ǽiUQ5z8ҡe C$Bҭ[ܵgřܱFw$X&##c]ujzy`#6KIQs'ӢL<_d4[o_x͊e.R lrŌ)^*gKFV/3k#Ǚ9\4m9Zb僴4KKKOJ];u3tVLlVoT[=js,c凑RSD[hrFVjw/ KL=Tw8 ]|akuڦ>>F>yLa#!ݺ[h`~/ 0:b+lT֮Us=gߧ={\\lfM'ŞFvyN#`ccJ6>ylԨQ&///77WVτ٫l3c!E\t_Ӑg }/=n{ssܭ8;qK9q9X~?55z}(wZ 4+U.qاS"t:FQbOQC7D=Ryݑ.{ݾ ¡C{;*J{{{;;;Baeeeʕ__գ7n&}8~Ho? x3ϞR*/^X駫W?LR719{7n<|P[[[ :t`ҕD~9lo_)W(t:]NN?ؽu;YEaG% $&&ťVT)*** @0m7W7u֬];o߶[֪Qc̨c}ÆWP(֯?nLdLlXK\^w>F(_ď=jZ(]>}A;,X! Xj;6tШ`t?L?g@wԯ7s15NII=-"Qm*>޽񂟑o(^{w$~N{(R>z_12"@2zh;;'N5ʕ+isv{v}@ɓ&%mcei)ܳoliiipt{WĉO8hݥ[v+{zF16.-:'7n\!F6hdeeegg_1i6|7{^{7N=t{W\HHȺuZh1qӧ&~AvUTٰiSLl\ZzL&+Ӥ ^=͛xYsi4ڵj߿8-tñc"̝߭G/Nɓ$W1{Ojb{W\ݺu슅}5sV6>*?ԙm~xIZ-BACN1Կ^Ơ{Nm5w%,¥+W ԩˮ={TծrmP.M;n޺MxxjjLh4/?rDxv\L"]D7>R| _0lrnn2ޯY% zzx qrrrrrܵˊի׎lMhlѣ lq YYYGҩc ‡ۦJtTڵm6 ժUdog^B+VVZA*g>*Yv@߾m[UƘQ#lqrt`P  EǍ\.jsifff==/\t?5MmFemAzΡ}[4 h&9 2,k;mެJeB%~~?_*l/-U9;;[5WIԯߤwNIII&';-kP8#j ;t ._\Z5I˖4haђoޜ1mj%wwBV4WuԱsH)JVe3>+o.)S+T(*~cZZ~ ҲmǏP9Na'W=|]0>rɷ40(||fչ7nǟ֬]{ԩO&Nצ>Fyr*wMXZ;wUJe@]ɲNNj(o6 ---=#cMw׾UãU߸ꝖuM/}zv$Grrrȱ㖭\%V۫+:աe+W eAVFG +++;;GD)Ά8}V-P8A\./ckQonX?-U6dmsNӦHk'}4n/Zͭ_E 4;&rz-?

wM/7Θ=G゗/Z(['&F[7u 1C:yba"^ ʞ[lxڵj߿81{Ojnj5٨Q4M^^^nnZVO W zI[annnaa!B>$ 6 [ KKP]IՕa]*Qu:iX6K<%))d^IM:Y&y1!zI $$$Hrʕ+Wf͚P(^}vq@(Nޕ.揼 wci bCV];;Tu㳳ܧOkkO:555… W0aX933sҥǏOIIQT#Gӧ 6jժ6l:~ ]v'%9sDFF޽{ŋ >|xڵ򋙙YŊ{ѵkW335kJ;-?(BFFƒ%KT*]]]F>x;wZmʕ{ݾ}{Nw =B_P?LIENDB`pasdoc/www/screenshots/html_intro.png0000600000175000017500000040632413034465545020556 0ustar michalismichalisPNG  IHDR pHYs+tIME  :NtEXtCommentCreated with GIMPW IDATxw\R;TlcF͋/$c%5+E.[!, ~?~,3w=26XCC @ OG&@ @ @4EQ$IREQM.88qð.,m#GG @ L4AFVRiZd? P(\]]\.2r@ @tk$IPTTDtDD#CvA30 J@R`f0 z}PP#v&b&r#@ T$''s\@Ka`4ϝ;'JKKbbbl6Mӏ0 _ @ @tgAEEEX,$E|`yEg}h0gSnZ`.z{y1200)pOw@H@ W[6o6}fHHEQ_|o_mټq;]T|o-xnӳOC9USq ng@ [;j5mo$5͚V3i/zoX9y!;!٫ouߤp\I ƍuws뜪fQng&r%ںqu6c{z/OAiǍ 8lĨ;-ޓ]$vv-f@  &>t?mJgΠ(Jef/HQgNFAy}:GEGeïlu ry%c8H/cF EwecǾsWWg Þ=Wdd7=# $E2LIRF{@ lqj·>v^O>EH4eY3>Ʀ&# [͑L&$|OlW^]7F$٣M H%'Gl'{&EL&SGgFSuMuGzsOơǞ=jU>|ݮ^A5CېZX,8kC_4lW6JC@ 8K ;~B{F@^A.+{ jm3\utQ#c{(-+pw:sTluW^q_}ٻ0QٓEI6ͮݼ_p9˿nμg3 5oCB^b{( 0e^Q\8~ mm۱A Ϸt8$&:ѣOھk_x{32-<<>~L*ʿe63n񽘨?1|Z.۷KطmReg/zoɌSf#ӃG,r[sjjhvqUj}Ja'Y4M@3e1 C3@ ^ig_?bX:8Hsg?Vb;޶Y}m[>>>C{Bi#Ԕ+WݼuqWeæcnj>eun_R{+V=p`i1QMsϴ5{(0MZ³;p0_T*uؖ>vKU(U?,_^[WQDBT*m;[]S[S[;"}(ku+m@ʡG^1<=}OzjsrZ7\]|_vVpwsSSRƌp NK۝\>Y3[Jഴ.)L(ػ>/aSE u*mRˢ(Z58gt 4@ p-~&;|bbRggOHHluz?$&34M{j[VUP|c\NVvvrBAӴBشuۈo2 Lp֮0mr}N8YmRTe(`ڤ[Ν׷N4aWR[W9>xR(V;''GFO̙5ðOD}kjN:ڿ_<0 ̚yNϜ6^yslchyXMmfM&wq99<}d:{>Ҳ2_SgNJrG_aX`aI6\)(pqDZh0@ p)j;y8#cw[AԓOr\77Www/OO`wP~AAuMmiY477\:xO0P ]$w׮ߐWPi֐$٫^$jQ`lֵ!DFDt)zQ 톆|c ||egOݻnۙ8yPQQi1!1 ņxZ{5ywӗ^{#S&9{6)1BDgMVX5M@ObE3@ /ch_nqѣzFuα'ð҈{ػc}'s\64^ۣ0 t:=eIԚ†O֫-nnr9嶼,6!._!!Fh R1;{,&d1?zlRu…7oEDg;իgCbPZjWv7)7ǿ{I&JݞOGؑ,@ ɫ>Ҟ ns/≮1cBpVSXh7oeH(\pkkk^*4qt9WGD/\yӆH&0a8  l6ݵ!!sܶ<^]2qRZrUK-#Ǐ2Yߤē3=~~  Ǐ}/6&bBchN:u|jJ ܝB잪)J$9H@ @tg,/ZveѢ?3{pؘҲ={1 Μ=۫g̱` 0?inޝ FceUSMKo]\Leݫ׽7m6l`HIN޵'C'k2&c|l=ࠠW^ra߸[[Wo^wڐ052,wLcz}g׮OBZ)2q{$&x¢YY-^h>zxzJ٧\:`mGDQqqlY6X-48ðAi̭ro_z*3sȠmz|tl#)`p6˗Q @ ?Jaa6,,(Jv&3Vĩ  08zįaq{睅0{\X`.EI؟XsssB,fiZبh\\\|~תGDMmD,f>3D- D[YU%Hdmg;;*BpqqqzPU__ Eb@Aǰzܸqk֬7o^bV^dԠ @ !!y0$H?D"Q}1 seǢm^܉D- DUv^;![`K;3F @ p۾{K\7)op}[Vda@ [0t_iG@ 8h&J;D@ njjbX~Ycif@ q ݻE9!__{y>üZ| @ @tO:.=='55ѣaaa Ate-bª@  Ԅ@ @ AhpC6|pl +z|:6) 2%SDFs~}Rd2GJy\f|x1NTʒze'@O0| ״͍p_\2S4lKĒ8mdAbӆFJa4mwb9ɥk}8;y;w<o.욊%@ h,++0ۛ=T(*)WVZZZVJRH$H$cYl̓Ob_uZZ\B/=)K(Gko|z*\ 4/]wIۤ >9ban b@\Ƥko2h(kjRI$ҡҏ;#յ;(<К@GcEj\=h"-,RqWjH!*؀mi X<Ɓfnb S;MdZV(cvb^uĉo6~^=ɧڪz:@ ;T*׷q$9(wqK6l$aRO,0qrC} Y&LmiWR KaE0/RAÒ7"\|ܧDKR0T)||9Q N #8l6J3"h]=4W5k@@tͦe*J0PY,Z(KFsAN؅zt;YzU @` @K6.HW__X(h44MsT;R{h>/e#͡IXMf\tXa~cOe&X߲:pm~~Y,VWU1T]]zí[%fq,@;b}n4tJiv㊃,5^3 \./εעb"Ԛ&O0tgeMJ~qڢK:eA,V0hl."q$)sl)--ޫ7I:8' Cj77񱽜*UNcbuՔ>,^M4-'ivv }S'< r]}N]xX-:֭[oPPL&3LE쀀\f]űY7y#FM5Ͽd>6YY:tؗ_EQ6L6O?솉e?ڟD&9b/zt6 ң0zw?UUsϝx߮b+ʀ2lZQ tߣۼ` 9C-^{$ EMMMeeeYYY}} S***jjj OGCIY llT?_4}&+Li3(BCEk!ػbk7bv̽u .oi^b;O~&vekk\33ӦL9k/>xqɢqg^zo÷;V l;VfR1f\G g'ʲ 7U7"A{$}03 Y C3>> Zh4 9>A 9lNQ}9~Pw.W]T n"@pnW hHRal։]O.iF0)Hό˯7Ԉ:`JUuoó/ެ08 *!Jn|PAQh|tIv_ۓZx iEEE6od06}k;!u#^R"J% EQMMMǎc\_FaI%%%ŃY>WEoq9.4^njeg10-CW HKMqĘяaMd*9׬[2xh]}}i".VX׮0`Hz}CC'eOBoy tGyW8NZPwR1 %I.sNp8H___\HDMMMǿۭ65kWt:ݶ[[ݼquz[8ƚ8~ܫC ]Y3游guZh FZEYlW/\8p^׷a}d7oS]200?O"i| IDAT_,'C௟iHI p%s8K_6θgH"i:ة#!ajuEQN5MR ´At FCMmedD~Iɻŕ׌ZEcEHAQa"pGO_ |؀a4 bg67.''Em)ܵZ􉝻u[h2QB\C9 .;bޛ:OWTW]_WtgEvZl߭jwgieVmΝ;ZJĮn;vn4qrEEISn [l:uz]]ݴ3~ݸs3*duuT*;{,AXor9w.H29/Ͷ6ATD+ʒRY2ATTV,&QYUMӴŰ3B`#FP6-߲ԡiZب4[_AS[ i:]KZ)kۼmc켭lGn2e  iAѤV|LͲD6+466)JLdq+lElXժ^Z˂J ~ ee&XpNosۂ5(L.[*, myvkWA;zKTۘl6b3cl6ϗJR3/xzxܵ]bf0wQ]]aQ&F LƼ>I}Y,aZQT61:Ыiug]);)%c#_7Xt:aEw^q3<4tɽz OPVkYqV[rvCn-c r!I0DQ݊Ղ|hRq1ϖ8zÝ ڤ&CԈhطѹoR?&Kquqߓ %^^}_8+JDR0X(8|..DV65r9 XIsBLhP+\A?EggR,5 Y'':'e0My&Y?Xv. z4{GqDh$Gm]}{czݾ55nnƙmk$^}}۶OؿLLo^ qgϞ>|ݻz@ޱϟ>|];{vnj_PPtwt|eQYkSl$g}*!6F\]ǎ=}df.kku+Wړt.Y, xkF-9{KY90uD kd렴ʪ*姟dglںm3MYVtx`>?xАUVΝf̘}jw7KǍeĤcǎK'NڴiS||{%uRR.+MH$0Ljۍx+W`ݯssoYL/{wew|5>bH*|˾`4v Ş1mjtTw|_V iS]~I,a*)-}B]l Xza{W,[jCrbaKӞ}̚;&Z֘K5udO͙ha[ ߽F6կ>翟}psobRmh# MoM kѝ:{n`j1cx\5e-Nh!>.8(hG= vIj3w^@@@@Q|GDžBᤉSآP*~ݴiEb˫c08vp qUTq 5'D,}Qk#&Nc֖L0E$YS(UȈpJt!W{;:ApR1lP۷/\t1璵O,{`PZ͛>uq5>;7(x~QHh.MaEhʚp?N4]3M7[Ez' : =Y]MM Ů,<s.9b M-Q<⨢Cѝt=}**%bqIiSC[>7$8T$۷_~>~r7&R $MSX Z/rvhbnqqE`0:pyZtQ"р4"2lL2^`bߒGjMFSjjs&Iz@Od2|>YjԨ/.FҤqѣۿGRn۱iTq?ŬVLQT||š׆ f͚}6a)[n?zi3h>}ƍz;|'t KUb@&SbT*U]]P(l[!{!wvYx8xH.󣺦؉o갡C`Ss=vf?twZr*X,N7GbϕА&@xhhpPP~A!a bæͣd0<=wΡ#G<ԠY,U5maUm"ٷIL -m?eg픉 ,$$8( kYon+҇ qfw7X./ع'9sz<|x洩;q Ç|SڭSU5:ժhw-P*9}df'2"bCEEw;jn7roZ=##kjVLpҸK5\]]KKK E۳6J%EQn;BpҤ۷oQtĩbZ`?ȈgN͚$c'6Y ^ C`V^Clz"lz53DԑH$Rl_']/!^#,l`fX/]S'ޒHnDED39YR`Z]xnjL_PXt8!.yݜ>|syܺ|V&s%i/~PX^>$C,E>B{[+2^LNJmU]fa~͢;~J3MEb@0iVW+|N0L1ʛ,y8݁' 1u4訨׮+$(R*q`>d ffeu&$84-e@GS|D&bYRzsFB"4`EɜdJFKԣWr:hBQjJP )QpD>>_KѸpA ^E`aشI{{gU_Ep gl1-v3g  t,n[lo2 ]M5mT[YoЁQQvɸWry̨/ݰDGy{yIwS/ e;!-6φ6JTWuQFTAElcsGK/Zsdߔۆ&R*L=Q]OdXʲҙ1FiLpy$]$'Y̟n!X0_rIIcJřLVQUq6+q]䮃޷ȑ_1tHz'ss)_a$r9Z}Uhe2 h0(X}7>^~V/HvJN\l@ 䭑)L&,, w4HM&uIi&H6<^aKnjwԱ{h}W+Mqq ^^fO۶}+ݽōnnn]]]U*VeX8ij S0چ̾p`0 ֡+6$mFoXlHn @(oݽ;aQz̽uvow޽m-w|чRo-ІkVd@"[3ȍFS' E0 35%p?bcY,֩3\ac9ŷ^mw2+:~;F8uH$)Z6gO,n%^u3֡#GZŜEڶYumt4 $0 1,?8tpۦcH-VaCpbO$6Q@,X,Mf$IQ1F$M8`aag2`%%Ϟ?SYY7z??Ffs{ag\!LWԩ}WPNNKJu:@ ֕W[ھb{trrtY%"wx~Ɇ I0O;Q{|46]qp>_|kjjn⠩Yf6dM՟PMpiUwɞE? IEh" 6s .`Tc951:''ǽ3#&Mq=/8~'ŒKH9 "!0d 2 D xܡqAn$EQV%2H(a>󋊊qUgųXiSg̽s)G͝w?s/ӧs;ZjToy>_#Ԕ&#zgq]\p ++{`U^^6n1ԕWTX]@&p^>^'|?cu k8K &eRpL9%睱2̨9m/pN-5w.>؋?Dž/>X[Q1qGQ[q0_רi2H1hm0y ե_1&ަ[·$o?7 ƕ8).tctM&4$;|VVIBh4*~Y}[]X,@pfS\]{2hOb"AEE qa!!~ᕫ׾А`p…7s܋\>c_7ox11wo4jP~Kۓ0>%==2tv mN? h2 I{fWҕWc{/)ٱk~2>~򔛫kp#y23z99:@ƌҚ SjCCB.\s\~JkZ4/ERvpΝ8H%gΞ;}ay\5sY{PZꮌNNN q&vVr2}M[x-N30}!~gs=3ŸWfsA6 ZYuA6tyۮd#뭽w[^=#w<ϑÇD"[|/3묃Ts p#3n޺mDz:aJJH&אAv#$%ėWTWtNYkXņ^^z8Ϙ;K>\z%o6|%9bz}iiP( q 9) H$y3v "J%RV[XTxMD˯q-ɜof TZRIMV9%S^^egߴ)$(Af2K)b8&:l6ӳʵkaarq+$(8-HԨj4p*bw+W1.EQu>L$OrlH憅wɾzvm -ݾ+&ϘF kwS1픬vo[]o~æko>I}NA}_XrՑcDžBGKk3;ʘGp;t/~e$ŽܳMm- ·濹p+ogdAI[T֢y|b3?4;v|g)jEVF(6?܃jmmKiڀƌ9z ƎmDgB[~ɈaúsJka5,ZvN= zmEVیO4.KVr8# {QT9|Zl֩>6w"/~] ӵK)s۵φK~ֹs;d^.((^dI%;yyRoؘ&9 y{ڵ9l6loaN9|؀ɞC oܼ|a2Mos[G/I45(`6΍p0-jɆw,^1 H^yRNq;0Nf3T+/IG5c,? l$h" LG@@A&$h2E.`\~(¨7z_$tt,̽_u/4ElԬ$W3FCZy2/`qqq/^VXӺyOQ%"UF(8,@4o粵W \n\W)v$T*l7D"ѹg_}c]]]m|®+ׯ 4fz>/[PWW'st8އ>u>=W(7K>u. jDn`FSc 4M+U*Z-˅NQ(Ő_^Q!Je2{^m[0$ɤԱcFh沭)A rC6Z(ţF7bk&V,r>NkKٙݦoo/)ݻs{Z$g@1]){[G^߽m_+6C؀b;yػ(cAnDED[@4ͫL-RPR-jQyykj" " ?>5mwXEE}=1|3cvg>ӹSN%u-y yD:L*!B΄t}EEP(ԟ([) 3ss]6*aFΝI4ku~ LSj˯gշwބ;yIco_عP) \~amkomCRIHkPWVB?-]J x1VE._`$#W}z:H$fo=F|˭Ufn5juIqeQnRVUx|X(J%M,-%R@$WUUu;EQl%ٟHZ… ]۷0e2D& Sxڝ;b8 N9ï:B222lll.]j|<ۛ"Iw+_~}v?5PkIQ_,/h]g6o#Ľu^=Kꢢ!GL7ipg!ߩo"/+>Sk4V]]~i6t+|:?rMCB9[]\xn+g'E&YtU{{_ :Jt^￿Z:NKKO|?ޭD<1Hhޖ'5DK!/ޅQZVVk4FںנV/'a+ iB ЙB㵼ZvP>_l88FUh4UUU^^vQRZl:ttLqI]C`oߣgRJK-\}_瞳D*K$|@xZVT)*+ˊJ JmS϶n])󃂂Μ9s>fk8EBBKtD(QUyD?n='0%ܟxBe*iw5x^ug|e|ڻuzC7nH$mZE*֋WF.'%'_zU(:;9|sDӆ{ &Nך4m<ƼXe_-/!D$=v/ -=*;ͲP(07fݶ^m=Z hR"H']‡7(7+R&H%B55JJYUUPiƹkVvcq z3Wu$NH$ Ce}Cf\}*555o;;9qQRD"Q 3:,j5~ XVhR:XVʈ'&V|ΟJ4@@j]FcHN}Y9#VV?*/.RUUѷ󈙥Lfelamg٤qMɮj;j"?Pa#iss&M b6M$uZ[wչ r#}OͲHMR ΀Xjӡ :t9t#igGRXSSqU)X@ ✼R^FH*6ujjkkhL U F5BH4N:NძM/FDZg ^h0)% xYO8V?NHH@+B/d.0^  DK:afyyy&M\[4Dो~kj݈˹yyyy];bC%`M(*.6XS\R^6:J@  @ i ^~ rxx8it .ܻwˡNS*w޽zjEEET5**J(,XYx<bW1@xogg׹s޽{;V*++ ,,,׮];KKʻw|֭[韻w~.lݺ_H$^^^k׮}?8O&cǎ---%,\p׮]2ҲW^{ƍkЧё@'O6l9ҕ(P") @V/\pL.X[[oooY}!=zѣGyyիWcbbL\[32-]())pOf ]sztCabz)104iiik֬9p+WB&YVV/Nb%KDDD0bcccccWXZ!Cܽ{WwK.]tiݺuǎر#ĉoFUUŋ/^ܽ{ѣGb;99߆6l駟Xc׫`ܙ3ֆ V\c3n8&-((8pC~'ַ1N )3gBv٧O~ԩSg* :b&0`#P:+Gҥ˗u:K9s!&&w1@ѯk'T;Xhя?DaÆʊ;uԎ;hieeկ_CYJϵ#s8AicjH$w7U`SzQPPwI&?Mī48qbQQQaa! B222-Z>sLMEDDT޽{B]6o<& B?P^^ѣKČaÆ sԩݫ~ٳ !999aaa]cVUUYZZa„'NЁm۶-//OJJڱczY0f{Eڳg]0)SЅ҅G҅aÆ1ڵkR `m\\\._|XSS… /^̬;v ;vlΝt(\o<<=RRVVFlmm yc>w\LL̅ ^'HzDgVVVVj+ؤIO3JKK=OUUU4zj׮]u:]frrr!'OBo89=((ۗsΝ .Xήt˖-Nxx8}wÇM?/pր=BC>p@zzzMMMNNΖ-[9Ê zsjJsСUĬ^ZFPJaÆ+Wk4K.mܸ|yÆ *JR=|p֭!_Sg.^T*U*խ[vݷo_vvZER߿&55u֭Ba6?ieeE9;j;%%%L(Bo0){w9?:^opFP(߲fw8V^w/V} !˗//XӬZN 6{lf#G7nܘ?ҥK !~[82Q?9s_}ѣJKKbʕ+?sww&Mݻ3ӆ9c̃k֬qww ؼۛ6mJHHˣsB72&@rMܘ 6ݺu.0ojժ]п-#THꫯ8psbbV*gz9K()XAOOOUgu+!ۍ74X0f ?sܼy3;;y.W?M_.b={H$k׮ !<8z(@B t1w?!D:(EA3fg1sppLHvܩ͛7zȑtaݺu5F LC9rJoѢ:޾}?믍;v.t1 FBΝ;Ǭ_+$cf"$$$d2///=U`` ޙLEDDl4!D$Ѧtk֬#;tc@ѥR)M (Ϗ_|9]c< `F>mUUU۶mbn13WTT\xh̙iiij'y՛6mR(c 3ut={L>555wޝ}^ϙ3D-ZD;w.\P*iiiWf^ W!s̹sNUU3ƱӧO7vܩT*SRRLP(ݻǔcnڴ)=++ ŋGIg~jٲUV_:T[#s<:m":i1@@塳dbG'g޶m۸q׌37=z4!ݻ `rYf履~w?z?ξFIKK:thJJq:t8|03>w޷~`jO>1]CM0B%KwW޽ۥK@Ht3g555b&zcw=~x㻸o֭[C6Fq֐;vOiZWWG?z9ys9k~9fj+LV\\˙bccu3رcgOOOXuQF͝;Ɔ ov( e2 n߾M^zÆ RƦo߾GL`hX 7wQ` @ 0`0`!-**:ydbbb :::<<="nݺuXX؎;222njSUU%@ !Ё'NHMMU?yd``UTTH$"ŋ[YYd{oSNJ@W_ 0 ::8}tt4=_}@ DGGB|---yӽ{?޽\^^Aiٲe^^^yyarrŕB4T*t ,0NiBΦ[jUQQѪU+BG^^B@@̟ ރMNNnݺ5!u4X>߇/_\SScac||7tOOOBHsP/\oYYrBHRRҘ1ch@k.BD"j~;޹sO>BiӦٳBa۶m<8++ҥK϶mfffBrrrbT*ɡիU*A:5~lcUUUnnnPPPzzJJOO ͭB@pۯ_֭[ OOM)))}e3߻w/((H$ueʔ)YgDIJJ NHH@ 333^{m=۵k'Nh֬YDDDPPЩS2H`199Yӥș6x^xlz,44^p SZk:O?577z;i Ѐex:3yRߢO鄐n2),Q(B:/4 6F:_^r|azvs\./ \Y|5kFuzc=>^cc+..+..i~ FAh2Hzp<ꮮ>ķnnr7zOKNjB%lԥ%q]2MoI^cU KAh)''~{{Mn߾.ٳuRٳu&ׯ_vv6KLLd=VNN΀,,,BCCKKK koo3+=z*zAW&%%yyy9;;>|ؠx̲ZٶmO?999988l۶jёԯן١C333f;L1͚>]|}} ! 555fffwﶶLLLkT[/?I1XsfĸOkjj"""0㣰Vm|ژ>835k YSRq+4Hh.633$(J lZ_| c_ƵYW[c@Pw[\']ZMIVsMv']C7ڻuĄtBU@0Sװ/x8$Ş''wvnJe{ur+9C{;'z%U$Yzl9f.5q]V,wtR{w:)/#$Amz iBoth^^:5ONVoM8EvV &1h!h_o߾vp~mr?21>|||X5k֬N:u}9ofzz͛7s޽{vvvpp03dܹ_~;̙S[9B\.u_?̘1Ν;_~=sht~f̘|ҹsN6`bx,|O"HT޺u+++kĉsΥkT[/7H̚1HT^^񊊊XZ}'6sژ>835k YSRq+4Hh.wqqi߾= Tbcc]\\LK6k}1hz\aqqquذugfUJRnWd-_Di![F*]0oQRV&%trͱ_]cz3 <5}9-'f5fҕ\.9.y|_xNff .~W˺f-[ʯ~8sݖK Ȟ3[&,"irBxGɈkF_o" !e(>\2.N7iUJPȚ^y2)76=jU?[wa˛{ݎ!.,,SD 6m8&c=}JJ}~~~utts玃Cvvvfh>...7otrrcӭXk_{{jDBS]]mfff<{1)H<,5gFmIZ8;;k׮t5:_kZ֣Vڰ&N ksΚҸ` 9V%%%WϭZK#׷|~b^S4f=t6 ·a-a_h[B}]27X}SMQoe0YUftzBZ+;ݚ8~+ οeDvy9)ovmsޱ qpѵ;KYsfDqY8]MQAk!/߷:&wTO{ɸ&@hkƁbw@ó!ϔ]l:tPaaanӍqLzrd1BHii)}Бvvvu|yy%}b1SX\gy[)&&k׮2qYm:vi&888BlllMԈXsWݝj; k\9\~R1 Ҩ:c_{5:?x`',~{֬Yeee&۴1jD#KJJMԈL̚Im}ܑ3> k}sXwgM aw4wIPŕwر[[>Ls=ɉ/XOcCY`.~ſE7c4uI!D]V*g~ҧ~2yt;'f3$-[._w#ORgMRSѣ.-Z]Ȭ9fB|RSO]\QDtːwːw7MghaBs9׾Aw xEc׮]j`\dvvv;hР+VTVVO}5ڵk͛7+M61|[fMEEʕ+]zcǎsyyy5M6=t\._|P(XeaW۶m/_nggZkbq'iaBƍr{EװֈL?٧Ga>4ٹ3ź;k>CIGsaâ [gO=ɉ/XOcCsZZZt:.o3]zX׷¸֬Ů0\vy&x{{3SֈL?٧Ga>ϙښxw֔}4^^{mǏrqm.oW[{r/1 1 mol+k쪛;K+uգt8}%wǽ&Y/[Kx{tIk6;"cYS%-\[.[w/#S?~7w%RZ (u{q]<-;uXw[G}MMuL#9f|΂y_-NG}b|C} (p?j"Oob-r.,: CcIVI𿻱vڙx :|UrO_ߗ(/}^/J=E۷{)|K$X ?_z55B'ߡ0kמ: `'9~CG uFv.n`e$X0`g]֭SNE+ Wxx8]G+s'|ϟ?Ç >|-BHtttxx)S;AY[[8p ==̓jiӦ+V8p㏄𼼼ÇرcѢEgΜ6l^"Ξ=R4iR[2BѾ}{LvZ4=4X|W1VTTB4 ǫ-}ь3Zl;880H%%%[tsF?~7ptt -Z1bǹXYY)!ӧO&n<֭[O3f… GuҥD.;#>>gϞcuB P? Çg4wݻgggӱB<>> !N"t:Yfu)//{tk|۶mϧM0o@J$M...7otrr#y IDAT^AA}uuF+ijooboo߽{:w 6mz `4SҴiڞ-**'2JXj v/xNNN999\v9tPaaanbcc#!={ڵuCQQߛmSyyNtJ.-[ܼysnnٳǏ@ T̝;7::z֭J`#Gf͚+WD&vvvAX~K=vڥV=<$***""bԨQt}tttÖ8CfMq!}̘1KII l3,,ήСC!gРAEEEHOOm%4dFrww_J@ 7oޕ+W,X`\&LJ{MII!hZCj4#G}QQQ"諯or9N!w1&,,رcgϞ}7ÇرcѢEgΜ6l2lذ:33sF#Ju:]TTka  <8&&fC ѯ7|sAGjՊ#D/.w---+**L­[FI E E||||||UVV>˗/V;vPTVbĨTcBܹ啔ԦMz^X.[YYH1x`GGGHĬGCά+|ِ???Phaa_\\Loֶ^ݻ$t2eC___wwٳg8PbbA0Epnnm8bRy޽9zɓJ !3g\`ɓ'z뭒º^N81rȈRX رcD"ٷo۶mù ܹsK.=~83n277UR6]nn ^-/PHԻwoWWW<*s굆hѢ4dVUgkdpe={>Zʄ zyyE P_111!!!;i{Igo~CBYiBN]5k^⣿'wvnpS:~#οeс]t2~B vQ7 )ׯ/++CS@㡭'~όsZ/Ojg$"BN?>`,5풜Q_'jʤDUY=]%t1IqV hv@ U7U7Y\'?ɫMB7RefЕ:R3BޱG?r OegKKCUYtljS2+hpc:mUsK#Rj׋B^"),Dm7vHLZF#/6%5GKw^lLr<Ή $-[._w#ORgMᒧR#/'Td04 fmu59?ت2 $Z|xNi4\4W}F!q-Zcx<O.?^n-"aA AY+9i-E;Xv̗Her3|'0~ t:O{=W[n)eMc"{[}:0JO-ܿC[Qa֮}e ^N .Xv $%%XXXtʕ+HWS>=>>}J1@ Oņ >C331cܿ5|VUfKYfy~26&/窛nRunv!׽G T=zHѩk:fX|ˑsXVur+ܷGˢhʴ 7:4/u/GZD:w !Nٳ'ǽqw\XVUDbBHm!2f^ޙ ,]/l!!'irBxL>::WtN%7lذŋ?b~g_~c:mgnֳ`'<!|}o9~۷po;Ş6HP~N_@WjwKS5.?XZ ΢+78N*Y9Otrכcn߾=|~};Mi҇~:Mb!DV]\Ĭ;|m!uTbb"!i<==JJJ:_B||| dmm]TTtVdQFgffJ?|!Cx<Çoݺ5e++`޼yW\ ",X <<.&LJ{MIIy28qF?yd`` ۶m#DGGeӯה !cǎڻw鳥ܹsAAAO.&XYY=y;w,-- ^gH#Mߐ{)n^Б'B$nչ DvbXd%F^.7#vvvs4aaaǎ<{oAW>|ǎ-:s̰aL6lXNN_9p@)kj%IӦMWXqB~GBHxxx^^!4T*tQQQtT- 2Y2x۷2t=ϻw:;;36klٲe 2ؑeӯה ! JLLo\\\LwT* y!5K.MKK P33g̙3B2{jTS^| mlk !V!y?ݴ* 2W}F!q----+**L޽Voݺ~L;>G]\r%rEB?!.u}E-Uwlؙ/^>\@r++bSvttD}\.?tʺR"DDDн5i4h4!hť.R 9FeeeL<, jQUU%J¸ltMYQ*QBoD͛c+++ !ƽZ8C;?5k-,^e(Bةi Yf]PyLd}OG|9gddĘH3f̘G&''tȿ߭RRRo>שSѣG/[ b*J?O֔k]hf"Cetm۶V333BannNC:ka\6a)+RiffVQQXMMT*upp(((W+**iC\wX аgȫ;fڷ\ /CϞ=' -,,ǍgP WVVBO󋋋{+ݻ$t2e)뫲R&vVuy𡯯ٳ̱kݺ@ ߿ll,{bk׮̓ փִ[nb[noW&''09zAAAtT04o>rv>hxpm۶1BT޻wi=:ydR~B̙3,Xpɰz'P^믽cO81f̘gffڵcL/_d2׽Re3g$-< tpx$''Ӆ .o ك._ 2-/w̙clxܾ}gϞ׮]cYw>i㫳MSFAK wyƍWNr4iһ[XXL<^S?}/:yUi+M0͛}33dzN*g/8/U~rM~_o2zS:~#οeс]蚵bu/GBHųt!!Կ,4!$elXM^U7YݤC{;'zx⣿'wvnj-[q;M fݔ9ܻߍ4 .DBxBF.LJMpZMd)E|!$c~كy3 !m"tːyygF/w{`ֲƻ??s;k $1 [9VQZ?jѪm"֪n*XR( ""N Ǹ4 W<vJyV]ǗDJBsgRls+SjUͭF~t*?12BzD'J^bP7+Wcss[sݜ/.;~'_"~m FظcǎYfi3ׂZPՉY2&2ϙ~Lu{wB(~'җ/~ĽKޚڻkkYe<+1!׹Tw> 7³X\DJl.ܱb+|-,IenjX/]v}Wbx۶m_~%H$>=6[+k,-qN׵0~8 i1C䧷g4L?zcB7W~1[k]CWnnQ/{[2ef5|Wy9ܧo}c?>^oA4p( :?Zm6l0wVmnj2T]U{Sy1+]}BGQBȀ\37*Գߕ{f~Eћ܏XnؽA4vgXHݩS'B_jettt޽W\tRL5k֪U̙cbbB'zyy-Y$::z...x$''wڕMZ6U*Dmfgln.{k_6Qzvff6sޯ<{NKˎi(*6O`P `vJ2??[nWWJgkk:vX:gPPPAAիƌC'N8q+W<{lPP^6111-jI 6i&xVbBsUY&MJe%'> >*+J!J53pww'#==Nxb}}}JJҭ[744\pOիH$JKK۲e ^6'Nׯ} h=@f>}Ս 573)|DUQFQU|uߌwJDK~Wڼų1(^[ntbuu5!V <~-DFFDDDDefff ,Xp!.^^^-%7 b+Epf!Љ<.E w=_sq󵀲C&wxڶYyyyMMM=***DSSӪ*PXWWGTUUmܸ^kCQvZ EQؠN6s+K22rذaOO:5jԨ7x~Sк3޽{geeh.nS]]{nBܹat=< `'|"˿ Z)a `, `, `,*))_~&&&7{:R֢V?SSSĀ{sk0=x)/ofdddeeezzzϞ={ソRjuY^^iӦ|ĬCja @xz  |O7o޼iܛ<֭[z' ÇO=, R$޽{e2uBBb822>y̙޽{ B'O &??? @$ ><77W. šBH]]\.程(D $Icc#!$55Wmdi\rr IDATEEE"x{{Bt5j]Wzz={$}uLoooD?2Y Gꆧ ÛOw566 -==]_!}MLL9z@ !7otwwILLԌ `vwdٳgvvv[O-^׷?""HPeggt"kN>P((*--%,\066"44tܹ #F իF:G]5555G&;wriDriBȹsz-EEy!Qz[ZEQԍ7ݻe渡ɓ'ЫPniѥ =]vÇofhh&B͛T*#"">Cy:1,,lK.Sp^Z&ݫ{nϙ3g:u,88X,=zΝ;˖-߆bŊVNBHLL7|3ydB@?a6DSLqvvۻwo]]!+00Ҳ999?@^  +**8F($IffD"y葿?=E)*..H$ B#gAAfu .(իWe2٣GWZU^^q%KXZZ._.L-ڵʕ+[n3f̀~Ǐϟ?O>g戊5x&XRG1322R\.*4e ~ YkfgϞ%%% ;wwX,ɱ>anݢz1E! :,% }eP(ŅIIIQQQɯ:!DVGGGknfoovڴ@ V^7f:qĉ_rٳg0L0^uBJEd2&#tԩ;'s"ܹsDB#RpXL&L@_:{ &Xn~L4))).--?~z]]ݱc&OUb1!E +++o 46_kJ+++BѣGKJJ wy`yBann=~[n_ݻ7޴i۷U*յka##kr ֜/_tAnݺ?… tbUUU^D"QZZږ-[0xL 4~`\d2BAї9>>-֥#H++޽{_~M7n她_FܝiiiY^^N-wإ0ר喖A~G3fܹ֞撞K] .X **J|oUUֶrVWWBjkkMLL6111"Nܽ{ق .\g"44tՇ/((Xf kBjjjv5rHBZ+޽ZΨQ6o\]]~zh*i֭[kB&N;uTCE_KҶ.߿|||UUՎ;O X;.n!7ەJ֭[ф8p@R2Qk̃޿/|///s cNzر[nꨨ(&U UUUZTUUmܸ^3СCE]OwBB²e˦OޥK)S07]fͬYd2m8 i1g\\ܫjiiI/ot˙>}={ &;֥; &̛7oqB`Qڲea]vԩׯ711QT<ӘZ Q"0gf rժU .9s;8z5+x:E{/ nżdr~"̙3'))lȐ!ܺukii)s+qG+}9O>/ :~޽L4IP$''ܹ2 .dddtu$XQTXt -==ƍǎ5k{wEP7qcccaaaxx'NGFF6BȩSFoh~ E8 ׆3/?  `, `, `, `,:=z3fu}}۷9s&ANzСL33aÆ;k)lXdĈONOO'TVV&&&2OYXXtU.FFFƍ(*11ڵk//@KKÇ̞="&&fӦMbѣwa-GsTU F(j@` ֧Ǝf͚{Bm\\ÇGM8qW\y٠ BΝ; !EEEIIIQQQɯr47-)E5K$c?~WXWWW>v…/Љ7oܹ3XUUիW/Her6mtmJu5+++r<ͥǏ;v={P-A<R`}ԴRSScffƤ 榦&ݻw-X`…R`htrS4 bnn.kMM }'##W^ ܹ7|ÔƜp&ҏ ̙3;wleedɒ&fnݺ #Fܾ}ɉުc/'C}9ݧMMMLMM%:t(__ߐkj>;ucǎݺuKVGEEwOy.]Jy;0y];._\(҉ ,y&gXXX\\ɥKf̘QQQ`MLLOO?_^,BΜ9r'>zHksg_y???gff6bĈSكԩӰaò9 ?QYYs:F$BKJJGQSS#lZ T]]yf`ݖ<˧OoN4ngUXXJYB۷/^hjj?Ȕ ˍCCC锽{6oL~g͚UVVWWW93 cƌ4iR]]]VVÇN81uԈprԩ+//#G|QQQǎ{-Zb rMX x:VEZ~|ZfVr\3SSSll1`ӦMs̩2dj*DB,Ybeeo>  6{ !"FSJe~\y*1SBee%˗^igg;wԉ g]]@ hjjxD"QUU!F(644 %nݢz1E!x)XI~vbrjXnժU.\hll+W,..9bcp3];AJJ EM6̙3k֬J2~KĠ`  BSr[{ yqlܸ7H:t(O'L@ٽ{w}+~щo[̆۷oҥKzz: `>\(Oׯ8pD"quuշIXXؖ-[|||E"͛5o*FڶmP(9r~K+2]3./\gggBH.]JKK1c]q/hƌ={kjjaÆsॅ0_А!C233J̙3qGGGs `7o.J|wxiI&M4i30X` 0` hΊ̙OO7 yyy...~jYwȢWD"yv,:6>?hР)Slݺ3௿֥yޒ~ldd8n8]F9s333gϞmaaiӦŋӅXXXtU.J ,--=|pNNfTnnnbѣwWT*>}9ؘ2rHBe~CXB7fBD"є)S[WWv.ժ(nnnqqq=z4>vs۷oܸq;wBËmǎf͚{r6q\ٳAAAZ1'%%EEE%''[ΎQ|>???dbbVYcm,!$((`yyycƌiUZ5!кpl7oܹ3蘞~޽ 6… /^tqq(W^"(--m˖-Zlڴ*ڵkVVV899_t˗/wwwg466Yݺu;|CCÅ  AҨ(\]]Mijj(N111ihhԴRSScffQݻ,XT*=uůرc|~Q2O䪪*u+"##*Ykd-C;jظܜ;gmmP(׊fSSӪ*SSS5ayyC( YvSN=vح[juTTG9uuuBunc6nX__b(+J@0bĈf;d@=`KN"sUnΚn`m޶PeȗΞ=kxZo^SSÄt A743 omtVV 76m*++#{8XLݱ#9OIh(giskʘZλono|Tx{k=d!JTrh>}\J`mBnN~Ga+1aܪLb822ԔRPP0zh33 :ϙ3gz- =<\SejowۺǨ 7*Գߕ{f~EB(I}sS^O UUm !l%𛪔P}X|BAQTii)!džEEEt VTTΝ;N Z2)Arwxq:XB l|gR&) ZViӦ-^X.WVV2XZZBx_XXG͘1U=Z5wR䵴T*}p##F4عsgrWȊW.__ߪTB39!rĨj)vO洠}&ycKV@ ٵkȑ#DwwXX|]BH㫪v,<xJJ_ӫI,jkɣFڼysuuMlmm=T*cccy<>>DRxUV-\p̙;v*|˖-Z55kL>Ϟ=t⧟~B>3sssZ?~R7vEY;@^\XM0aرǏ7`q)2)Arwq7pXsr.}&;k/kLH$2es^^޽{ꚕ$ IDAT"""ǍGQTbbkfϞmaaiӦŋ/ZbŊz [e~CX+00Ҳ999H3֭c V^7fBHss@ ;|ѣ !;w$-DVGGGB&N+W={6((vrrJIItح[744\pݝN466NNNyfΝ 4##FBHUUU^D"QZZږ-[0ТV_mbbR[[KfAdd$XR1t& B_iUUUݻw,X@T=z@@/Bauutƍj5СCE] Z} Ç ЩS0+ҬaÆ~͞=cH]E͟?ȨU `C?~744T.T*###Bȉ'### vi͏9rWbiN5jTTTo?`ETXXz?(:Gu׋)4~`0%'?BHu[!cx^ Wu }QoI y{O')jZ>{@wp;XaLWg;ݝu I1GGGB[ip-k0tɺV^AuH9r&ܻw;wBΝ;G@Ï/ U2o+DŽ v7}N~Aw=HizI&M6=) 9y׫[v_t[ ,_}ȑ#?%Km ] GܞS`[uZ3$͏}MLLĂѣGTTTpd9swBɓJ%H+ɬ6эG&d6 Q,GFF2f'Ԙrוaee{nSSS]3\C<3deO[S?zpw{sC=ر2}W>kosuDÇj215j\.(*==]whn9-6ʼnنH !]ty!wZ]gee陞o\:uYu`eyrG9 {}G)ݢhll }=:p7ߟrV .=XXK֬ u* VVV 666tɻvdR)\n`7o$&&r1+ yC.\. 555:333\ކW"0!ˁW\!h.#Hlmmgx` uI,Wtwb|A~!|U>l!ʚ;Gox.J_"!$7*Գߕ{f~7U) yJeDDs;ŋGDDpd,\066"44tܹP(Ҳ 6 Ν;׷o_,Yr:-Ŭ0w)[?O4*K4σ**ݶzۭ}9iq:#FhcBktǔ;ZyۆCwy?kJMM͝6m]E8ţN]x(㞫O(;"asc>![4|>ڵk>|7CCC[{xnUVK&V.XXi:pp9z)k׮ݹs/\paFFFvv֭[9ڮohhhXX.]ʱks:Xc-XvivzE/hϟ?igg׆W"pHH7nܻwo˖-s7xU7ҽ*/~u6# !>>f| O{71]%'Qy]Ɔ{HTKLu>"n,-9_3~R̋+88xܹNNNLND)H=z/'I@@NQTqqD"ihh MMM-úuFFT*tN )*((Wtׯھ}E\\\/^]D"ȐdYYY /=ڿWү|uciq!~ =pG zƎuk2bW7|  ndggwUL#??|i 1ժE+Qsuӆy0|НxmۏXJn<43)Ϸ{著ףG8Oiܻ'N]DCGsQuDth^Q|C wpMZgϞ%%%:p72::z]vG!ӝo>nm{~j(JJJb18Qf✜ -:kq~2Z<"qXvijժ7.YryGRRiaa[nnmllEѝR3pn?! S%pt5Ǯ=~NlRifS\%#xeO{Hh1!w"MJe%'> (QbmHG-))0`PHRd2YAAGNƹs/BfD"!tԩYt7b"i7iҤ$BȩS&Mb]b Te<+1!׹OKoXXZR׍;(UovpLR(XL{ 19iۼmޡ;ڶWvrI*B*++?уuX.|֥op({ G:,D o1NPXKK˸8BȦM+Z5d4mY՞:jp[sZ5m:0? gnVUU* iUUV4)*b?x}׿KGzvW76|gե>uWXU_͵5ɜđѣJ266nPTu}qqq555v9r$GN{CCCllX,{nêUUU;v`^Xd5i$[7g߾} ņ <C_)ϗ5Յ;6[ yI7qzCN{ ;ڃ0ͼ|0koX$5j͛ׯ_=Rc* [5aZ =1|a?2<^۫v9h b8֩=uhr#„νC``m߾]Tnݺ :ᅻo#G!Ǐwww&#LǾnv~hώoٶ_~6nZnt;AAAAAAm~%Ǐ3 cǎaܞ t̍ m'el,8%s:!Xdv cl]?^t^j_WqO}]Bg}fnnV)Zj… gΜc:5kf͚%mF'dŽ꫖1ۛrka͹vکS_>>>DRx< YMxZn>>>ǚ :EWSSg]xy1vݻ[[['$$C} z<8Ua7`밲cNCȑ#_uUU7 +Zdƍ2x ! 23 0 ?,ڻ ` .Dӷy{~Ph@@z<'+i>fM|U?=[kdee=?l7.|f~W^ʲ{)հ>8Uog8pUK$ ,ꫯ!}ْ%K4_6m76lFiEߡXS{笭!/pByfȸ˞6lGgvC2IQIQTN%]ǥ߳?Ľ9UuJhLq|겻f}MLLD=Jeee`cc#Hݻk.L&J!BᄈtssKOOg-(( Ԙ2(###O( Fmff@èQr9EQ隟2ҏ57WTt`2ښJ_gΜݻP(8y$i sƍ'OmQ\[˗X ME.g:N}*~~|BL/^Syg}I3p.=a}pO8#Hlmmۧ"}v3W-Nw܄c'jq0Uk+..'\~]sF?Y٥KBHffD"5VZ $>OB?lT;ߪfeeyxxXYY޽qXv800cRϟ~zyP8cƌl:q۶m SNeB➫'mt慏N56בu)s}zРA~j}gΜI+L윗w޺:cc+W8p`{Kͩ/+ҷ̙3MLL<GGG744˗gJY"ѣ'N\r%EQ˖-߆b 77`X\^^~;wkݧ~z755OQU\\,HAIIX,nhh pEٳ|YYY۷o_hŋ5˧LD##f"fLTb9! *{&ի2ѣG~~~UsE%''>}~#Ѣ6ǩov?_sR关ׯf9|$!$ cs/~& 7t KvXn9O&$zΫT*@@oZklww" n=Veeettv_1uY[[gddHR\nooO'rOQgYiqNuC8j]D"dddd,www}erԫRRiaa[nnmllֶsJ(ܹsݺu< ;~#GՋ5jI S{_3|nOxy#C>驙hooou5//oРAg@E=zH*YYYBϟ?~xwwN:NSf@`kkwѣGk>sNl0%[ΎI *((Xzu^^ޘ1c y}wuugVq]~=66ё577755hBHpppRRRTTTrr믿:Bͺu9EKU^ƳBxJ88YR|Itkã?v^1!w"Z%7~u(/ѣ%%% ;nO,ӏ5J+++BI!N4iV2sT n ;e3|膭8XZZџs\QQQaeeE|wϲ8+++dYZ<ѣN& ݺuO566.[l֬YLʍ7Ək.o^Z;O0aJpk,#u>|ꪕXRRBwL&+..z/gbbRWWGW\7n\.]o2KKo޼ٹs;99_tI֭.\Τ_x>%%#'k Wĺczz{6l@ȠC .0466/طoVT׮]Zgddt9:KKK,#_\|DUQFQU^礪s/Q@_NoԪ{r_,m/l~G3fhCzyytqq'N077}2LP###ztBFM6mrU-JuYKٳ/^4EUW/U86,,U?oټ=Rvty[&s(c~vfLx敁{lNV+Wo Xw1r!볬pǯowHD?}mo>BOBB3k Cc.-تmm\ں>*<^nHݫ}_U "!4L&Ǐp.ss΂3h Dqg},?LLL1bD*M?**u]B ;:+᭬#Ɍ鍺^^^G)**:~ op2Lmmmyu`υyHZWWpJ#""6o޼zjCCCY,2hАBqDg~eee)H,c1݈D{{o&** B>xFc4lD/?w4i}?}+)+A]CG}93'ET8o'kUgϞ]vON="EQ|ܸq111b811qԨQmyssӧO766FGGS?FSNNN$::>\{LѣGMMM;w~i(i\EWm6Է # {ox:I~crzՐ̪:(O\NRH"^_QttDV,s9uBܹsWɉ1[BBH$Pj IC-?Sw> B"q|9<>s uZjULL.ڵkwܼ~fŋSǴ4Dk0Q5+u֑Wxg-Z 800066!&&&00=z$HBBT_zF~=~¢V&[ZZwNJ۷oommUȬ'l6~DYN6Dfc(BN,;88H$@kgΜΖdQQQV{hn{} <oQUO v>vjźi, kM?b_|ž}r ֯_hѢٳgk)p(((hڵ(iӦs ݻwc;vprr߸q# m۶d2:׀;M)0"06mO|}}'lݺu|[H{D_NVO~. mmҭWnxyP{nR"6>tx4v{9j9ZJae(O\Ne]#6D*'_ Q9KKXjiw#BBBٲeKppplllBBT*e2%Z~RW''} Ϲyw3܌ ݽUzZlٯW_:88$$$`JJJZx1ӧO DO40sKI+u֑ B0""wYfYYY8p:  ~C၁ o>0ݗ`yxx <㵵SN|2v'5k|O~煅o>|x@@U*BÛ7otҭ[ fii9DjX|Μ9AAAFꚑ./w7n4Ϟ=[[[;tڵw=|JddK,o۶Ν;ΝEѤٙ,.Bo7W^߿iBBBRR۷͗`믿|~]]ݭ['ԩS˖->YYY?Kljj5k/++XrԨQgmzk׮-I&egg|,7nhkkkggqFoQط+{*)) 044/,,Dq܈=ѣG2Lmm}x|8P`0jjj".]Š2Gر%K<<<***|}}W^-/us(d׮]$x<׮]8p@ J1LPٳ;wb̘1ݻ---L&SPֱ𠠠|,5lG/| Żo---!dggwm ggRD&H[YYݽ{ʪƆ%XŭkkbkkkT$Ҝ666sΝ5k֘1cҢ3iҤ'Nl|c<Q`a0\.W*Xvxj5׬,[bbbjj]Ǝss-\뫯I$6˖%rssr󍌌R!MMM|~ii%V uPh `+Je2YGGIZbD"Db`kLzz+.^jhhL$ccϟc76WUU_cgXbX[[]OO;A\!LݫW/eΖS+;;ӧyyyNNNZ6f&f,ڪ-}jddNggg^Tt[kjj|0j#B!v9E98cccsoJ4aCC (\; {'i`QMVWWŋ>Lcǎkhhՠ &DGG7449ee裏nܸw^FO#"" ֬Y3{lbѣGMMMFrqĈDzh6Gm̙[nB~att4~NHH qqqģ~~~7ottth}РA "(>>0^@ hMakCRaذaWjI$eӦM閖;ƍ--- ; D痒2aj???co:t(F7mt-33TwDQOZZ@ [n]'#6e1qDB Uy?>>> GcccnJ-[8ЧOOOO{e@3Ngݻ;9r5k/W^߿iBBBRR۷A'3ZSS{'r D :ux߾}?3(K` ՕmU+g۷o=t- ˖-khh}5h۰aCDD W ҦUWwLgmmm??ȑ#aV\ v4 ~ҥLPCCCJJ 1O߾}'OrN>Sq㌍kjj~|eӧO-**ڿKK8^^^'Nloo322B7ob`bګV? vZ LMMgϞ{رbyyy+VذaD"YfͶm1x<ޜ9s O>[``ݺu jjjڷo_EE{ YVVuɓ'={6**}&''[ի&MH4iRYYٿcRTl֭N7n!b2lÆ +d?~k:4aKJJ/))_Є >|mccd2;::d27oޜ6~x:=,600hjj?yD*_KD 044رcEb~nܸ!HnݺHo鵴]ccccjiiݽ{Mlll233┵Uݻ---nb04@ݹsݻ{z{ -ЍFFFyǏojj'ݻ7 oill<}4v3i"ŊJIRbPGGaVgՕH$-fffΛ7Xz ]khnnfXtz tY\XXv5O?USUUU]]=|pXrB .tssҪŷ.Isss}{﫯I U ,ϋ/lmm/_NPffqFXaÆT&/]ZZtRPPPٳgO:% w믿ojԓ'O֭[b ,%22f3&,,Zb+WD" Z_zBN"퐞|rJ>vPPСrKJ7[bo9#Eu؅K v18Ill]->䔷o9 654lcB79VFV'vH5`D]ZΛ7_(ܻKJCC˶mZU<;mqUIjRf5">gW\WYkUד}R$oq޺V\\AB^30=Bh }!>?!$U砠#BMMMXԁ&''wFFFf}y?cǢK.ɟ&?MLLBCC5h̙3+V011YluY%lЙvxZz:y!z;!MtMBcǢFDkuYcٹgn=lic)uKK/)%am8%QVu'n:t5޾Ұmn"޾K0JItBBZbDccBhҤ$H$5CY払}*wzXFfϓzT@ o3![[[D,p8!TRRbXZZzxxYYY'*G궴`)eee666&&&xNgūB_+++B4/ IDATeelh1~džn  uV% B/UXfF{IIESzc#F>>SYh_ƾ%RVV7sJ;rӨM__[#Z)Ȩpv3Zwb2Yd]]ܹ Vq^ O[ zuޚq2djYꄃzGޓGeU]Os*]n“ՅT!o,`KKKP]]]]]')镕7n,++ꫯzRxKKvLޮs}|>!$<Hw{i /B>>GW+Bхe}x}vY}z6~BG]̻H27Lcǎkhhՠ &DGG7449#{?291'.!t>Ov7 -쟺xwNǓe }СCa-^'NyfP+]IN?n#CDo+ZQZ|}~w>߽]xU|TZy29r͚5W~ܾsxt?sNN΁w3~[y Lsss{{{WWn o5@3 Hx[MUeٲe*? ^6Eo_wB ): B֠w"Pop 40@ 0tLPГZ2&k3Bղ{yVP o#KPPfc>'!`-Ւ(-m=Dgk81&h=*[gbBGVR{VՒac)a g椖c(_XڠMebb3cBsn[[j]t<4dzilsB:dK{|T v*Hrߵh0rP91ʏ>j}Z `ԨQ999p0v*}wftPz;FU#£_?d,,ղ7/2LeJ魰:s*+N/Wn06B^y01o~]Unn^Ywх.DJ]]_[[j;G=෯v(d|vGCW&bbΝ;?w .yzJ!ɠj|y; vK*x SSӤ$+Wf.\@,^VVf\OOf f-})1n\Fɤmi618"jϜ|8~ޣ@ƻRmOf}I3cBXJ =ڿ]]]WWׯ3f~@@@}}=ENBeErrrx<ɓ'5 d[[ˍ/`Z\'''w^===TҎ:ץKB׮]633hG`@OP2,+X!`괋bxe" V/.6ņ/KE L|hk5 ,HJJjll\ze˰%KxxxTTT ͉CT2j`𠠠t<3QHP`0jjjTZGY[!!!3f((({nKK ^'N]P{f1C^y}W+71Q8C q/-H雃TtiU&RBGG寿*..3gNXXX=l ѣGyyy;vXr%3Dx><<<!T\\p^S8>|0"JQʲԪ9iT/uH]3bAs<$<<<99944Te }'f% 'T9][ `17\\\,,,T R{iii3gTp~ M etR\???uښ8ӯrȏ>[κ8bx4ݻ58LKgbQkJ$#b,(X:zC:cvWg…½#-ͼ˫5GJvO;D;#6X+N9Qg7{qu `TUUxnWҘm5UpPJĻ\]]'O<>}oxJ__|e9((B155XNR! FYY*u[</++K :::PDEA 6=Lm? !n~;KX 6}O~DoRmDZ?J着*ggj jRR!\T*eXA5ki6R,,,AeegII "OQ.]Z~=DȤ.D]ZtFѲ4 җHu}fRПĸ\n~~ ;©(k:~~۷YF*VRRbaaQYYZYYrQ/ M%]ws M_`%n*(.k0aC ۷/l*ĢH#S5ߙDdg|;$w2v%%Z6YkGړܵ|sZ6B( A:[!z2ԿvڠA l:NzYŋNJG FT:J_᝛Y?p1Ϭ{ywKkkO9~h㟷4O{} ӽ%RԜ>}ƍ/% |>eee9q)Rs8[HD !rB666ec+bCaC!/M#jӗϦ\C1雃T4-|>BBbe5=y01L\H jZL\.; FY3g٩4j4IBeUȢoPԙ9fł$& Et, tvʔ)؝.\2e Uv 77垴4Z#t!΁}UtџBY7X,|2NNךS"qPO}C|w޼@ Mh͉|VDIZb /g`~[9s%KJKK/=Ag}aB{ϼ3KmL}n/e7*"AO2B'$$/_|֬Y+ %"Z#)uuu 9I$^W:X J Q{IKiK LLoRݪ [`uuu j{ɦ#lj0R|>vC]MM vBLW^MIIsnjLR.K-#K3g u}fAG311Qؤ&:!""(--M(XeװWL`^ԆZJ#]ws]9"Hh/ZzbQwJ$jk'aw.^ߛX{}^ۯF:k1D"rϟ?Wv{ī3m:I~crz*_ڔv]CG}93'Qonn~hُ>|X*7.&&F,'&&5"R)) JHHDjD*d흐  hh㪒҆vaCQt{C^.6޾6a'MViۚ9HuK.-ظk.???Q}F l~Ҏ=ljj;w믱S2SGBee`di`PTPL=Ob~~~7otttTw\f NAI&mذaҤINDrٳG$?2dH' 4%;9P.М~I[gAٲ隴ʙ3=i1R~G^3M4x xgxG;zߕLvq{7Oi(Dp8[[ .YFOOHVVB(77?m (=LKhKE1;*d~)c罾3Fx]>%J|1ަhx<_LLL:::d2{嬬4iˍ7DҜ8Ԋ"U>YRRlt///XL_fRuרe Ys2AsD1I5Cζ'OTk=R8@T:!QK4ܹs NDĜDOOرc&&&j mR"ͮ;rq _rT 1]YWY*E隺8͙VٞQ)#Qw9!V$$? /;Q,|7Z;𖬮 _Mm۶ݹsܹsZի755MHHHJJ}6—j*)++svv!;#~(>ˮxdr[Eٽ>O&QEG.--e0ľ+ǎfff)))X xP(d0555%KxxxTTT^˳hѢcAAAxm ,HJJjll\zeH[d2B0##ٳg;w[!m&ʃ=? #CW,6_`b,`?2oC_lXI]!lol?tvC\(NIB>lG$ҥK!LJ컲zÓCCCRo7t?z Q !rrrx<^eeo~~|NDb[|MMM|~ii%:yӇ!,xf &ߜ @Oj |`/kŊ< 1=t֗,Keʧc^͕I;}*&"}'EmY gw }:@ `?B!~X,ǵkBCCsrrb1^`qxM6XXXZJիCis*QB_v͢Mϟt47=\S#t}m5Š2d3vfo.B Mj);Ph``Βx[@m P(d2YKK 8s%K644EBx]BBByyg͚0i0rgޙx".'f^fn|kcV(|X*+Y%iem㘜ޭԦKumd:<*9-ZEiVUA_$Rqr痜|MGGG o7$iӦs ݻwc111XԴe˖؄]]]Td2ׯ_hѢٳgk&isUeɧS l@ ƣ˩\Q|,k-? A?{ܖl̾4'*awf MHUc''z}8qbcccBBOo^4_͗`-;0@ 0@ 0@ 0b BH&-]TOOmf@@[5̔ilwkKWu5 ?^Oՠ 3]~Zn<Sеklll^_mw2dȽ>̿gOu1Ou1zH9 IDAT197-d6?ա_s:jIHk,eb7&4￯}[; ]("^~*yP;kj.=T痑1jԨ?##]s9=6/za#dk7GTro `tĮB80qGX,X^MpssCf755!b^yyyIII@@aa!Sj\YY٘1cKKKlX,F뗖*Aq܈|G㵵! Fzz:BH* bD9G]ZZ`0233sʕl'' .jkkcG166۷off&QTR:99q8{IRRFR)IJJ233xOLL|>?))I^*ikk۷㙛:tHY(N*b SSS-j5꺺^~u(D}@矶&jRZVو 8vؤMt.ZTxuD Cs\ΩC"Ri)F20 TǏ;::q`"]b0BƍKMMEv`4W(RHD"#>>>00~t47Lz󖸜2r~03ݻosX>p? jq!$Jx$ș1]؀Imc?p43UA&*su,srrx<ɓ')f®,WIyiΌ \̲m-yp??=ïv*3SAGRKm uOH(X̎CqqGsss//K.!]mff[ZZ:|p:.Yãw f7nXXX(ABQSS#<==]te8p|~XfLJlNEEGGׇ͟?_NKK_U\\INNրJsjQfY!_'iq:r4)RK Oݣ.^b%*I!v!z$ QH$i\n~~AA4D_~痗۷Ʀ̬Ҏt ͥ!󳳳y<BEA 6=Lm? !n~;KۀINY~?.Vɽ>^\Y'AYbG+iܶSFrz>x;+s`kGlFmSSӬ,>_ZZjii3 :}P׳uxm5Uz28>p,2#^8+(z3:*ݠͭR3v)kԎ]Kvgo߹K<:t`dԩgϞE]xqԩlr 2B!g0 !4e솓 .L24OE%##cŊ>lii9sLPPB~j95qڵAl| DQInhhr!॔5UիW/BwGG±lL&ϦGDvm1jOO7nk&曔-բ̲4$-N*GJH-E*<u+Q4%vNRQiq9e2K5(zRL&)))nnn6z8'%K!Bؘ,[ ;$* EzͬwC۽!N/$4O{} ӽ%L5p$CLٚHhp)ei.429\Ӥ-g}TfDRh. `q޽{RB6eEp_Tڱǀ;;;.{ydcy` BHKK {X@  2L& <<`b6R9\nyy朜%Itt4}B={466ڵգM{{{'$$¸8~lk+.BcQ>|X*oVIII,kǎ2 {蛃Բ#N4C&Ѥ RK Oݣ.^JTΩH'e$io޼؅sTWܹsx|I~=Rk:} # EWm6Է # ox:I~crzG,u_I)3CLG-4hPBBH$pֲ]Ѱ!n*h<]׾þh`Qizw߸AVm*_^3He]/ܴi'|bffo>,qƍCm۶@&OO6m;w@ ٽ{78eʔǟ;w")SLY`ĉB&L@a ʹc''zbbby {. _͛7/R*QʩP4AX*UD-={m||ZR&dcccxx8vm>ɓ'Sh9H-K:"H$-NÖ4G2H-E*u˥~|T싯/^5;v| Y,B{}`ߧJ).mv< ='SիWojjtmPA'-KxYY|cE{;Bss/]dkk I`y7yq233_w,xzz9rTIN:uHFZY,}vL&޷o'|rea>>00~F[O0kqcO}p2BH&mKs)Y!T{4޽j,2Nڅ ?bĈD @ ]̉'MF'gG`@OP2,+X!`괋bxe" V/.6ņ/KE L|hkԴiӎ= v-YYYnnnyt^>~^}q~L*|/-]6BHgZ{~0t,5+if_xb)77L wqQ pf`DVAImWK]u[6ђlSIV VZmnbVe *_f`@GO93|=|ޟϜ'c[ٓ^7ZZ]-#´q_JM0rr=ij666jZ['^_BV;a Q(DB[ao!'/B\bvwkֵk|}}` ˳c*|@~m^S[ 0#ڡ;LBI*yXsŞ?>::q`>}VüS0:`cyեq:2Ea7s'{9*3~Y>`֬YܱcaEJJ !dݺur9ro߾]+WL<9??\x;8q[G|'؆Jڹsܹs[~[V]OKK˼yvڅ/r``3FoVɓ2`B^)+f;8E+~|/9]UGW][-]·K[S.pWLOO/w6l3Q0'*f;8E+(j3];;no.-1owwnMl6ɓ'?#lL0\P'q߿^zEGG=zb.7d2ꬬ@Vk׮LNEiooWT *++KLL3fLII 7RѬ^]ؗ_~R"##>-ʭĶψJj(XQQ1i$Ć)ܹS޽ Hs"UXXj8FÅ """:$/g$|a)v,[v+֭JնBrrr Enn.'JUUUqG(|}QSB" Ùv ֨mSy# u?lW ܮbSe#XvX]z??߶*Jhܾ}{||-]\2 SWWg& &֭U3 %@Rtti-ZʖPSSjjkk5M[[JTTT 8骫ʄ#qŋ pX@V[XXj9d2q,+/u.5R{fA{{{[jTOVL3lMNRegX3glݺ>|駟.YdС>P닚lPGԇG!9Ӿ5m-|MM]\YYm_| ,Xvj:(""B.v q*jȑ6tFm5Z{ @x"wpWG 0Ç;vc$={rZƍBZܙ:nFt: Æ RTE I!C{^W(:4RKHoԹH544jXRv$Laʔr8dF}U*6sO>ܹs<[[[?Yf9qv}S]~ڪ8Cs}9CMjzQ5afM/]VYs/v\ҍ!!!N)U;F/w[ eSWW:lp>aaaO?y]b}||(i:!Bќ9s.]Z^^hR=Ez&e[$u.5R>>>*QI J)LϊujGPuS1117n3f %M6EGGsَDGܷ!?j5u5%i_PӃN)|9}*ˑ&/4kGۑ'쥽8KKK;:+Pf:~{)Y'h*++/1b޽&_~沕;v [5;3a„͛7777oܸq "###""RSS5͕+WŸ^ɓҌFcffX ëRQFK԰a222;QFڳg#""lJYvI}ՎmΜ93!SSSgϞ"3AAA4 /RGR_SRb3j·lVWwqe)}̾ڑv { ^ku%X~K3;{%\}lٲ%22p͚5III۷ozz#DEEhZW(׮];w;w2KKK8qw,P.\PӅl߾]W !TS~ΥFjg޸qcFFF^L&R:eaSTϪL3uZm/2e !䡇"pa)dFW^y !6tg IDATl4RO#VSG$8Cs}9C 5RVMo_u>f_|Hu;:u͞=;-----ߖe(3:~eLYtp/&2Ko]IEE<TֽW_}տ'N 3t 2 OGY|M>{)661 3+ޕT lڴ o!3G` ` ` ` ` ` ` ` ``````n?* f)n9~BGtuuwwX[r"]`:.-ۓx9WSOuRZV(?F]'O9rdKKE;#dlocj frPBȩP/?dq!'BKc\mBfs=l]l>> 5իGOT&MHLLlhhoX&"ɤjwڥO0\PV[hK]89U\\\vܩjv0{a2juVVV`` g]ffN #x2f+Q%q8#3ą,Sbcc !~~~a EprT;'Nد_?VZbӸlddZ~wM&!*SҼdvWTTTfBhtww[+U7KKu ;vT{ilG][m6ւeKR~3$4w!pS^܁3. \DNhޤ'm<wΏ}moN^){`DΐU>nn.OˍoS Ө94N#|lXdZݹC ^7߳^]ü#u?ԡo`6F&%%644$''/Z;x⬬,jժe˖q'SRRf͚U\\KKNNNHH(//;vlJJ 2%%eϞ=+VHpuummm={lii Gb\]]zBt!CTUU%$$ZJn =ŋ':z<h/ovvaü_;x`mm;ƝlhhP_譫h-^+@kq[LQz!D1dzB***ijxl2J,ӪE={޸q! -uigPh4S^1)1 ƑGjL3p0$O9BpP)$V3>c⤕_MLKok?sO>Ϝ9«&Rqpnaǎj4&wQ2{RGQ(6J?-!DaնQcR'L{:*kVwaڸG;hlTB\4HS5ZCQSG݃0U2"꺶"%D!(\{Η!'Pܡڪpl`l̙tFdXXXFFFeeO?=o<O}}=!J>[WWm{!/PQ czD@*Szn*#(LQ7bTxmKS=C5G&RNq\ŎYRcw8iLPT@zn_82___^+ i^^^|NĎ&SXXF<==-r2&RŽ^;Bnfl-X'[[:BןsoHuIܩ0>}R߈;s%oQ^S͏thM !k>&==1QPv^[!M_P100R-n6[DFFFDDj4+WBFw^ԯ_?3uÆ hjjJOOf&LؼysssƍǏϝ5jԞ={?!\*VȎ; ֭[GPϪɓ'L^+*ʴjpF#TPcUmGj8O9q!8ESصtA}*)d ˓'{Q+gdd^{M 2 X ̙3oZ j6^-Q#.Df6ւu*~5UBHhjޕ c^#~'< Ы_s{[Ŷהj%ń 3+$|"t47WgMnv\{z'\h7,J"֐:.Oπ#t45UlۤUBbb|NLcͿwΙ*%XM$--mĉ>>>MFlllss5kϟ߷otngϞqƌ^zL&Rvڹs&$$ܹ:e!\*VHTTTHHV㔪Uk׮]pN پ};|FQeZH U-["##Pzj/ǎUCGW?`#?ądNa+B6li6Uv?|vzZMZ+[niiiiiiodkGYf={,Zm [ر[Bnf]Kuv>qh|~@Q<;2O3ܰS^)pV^/;YwP=0ªO.yaŕ [ȔVw-_|ӦMx p?6t:ΏB9;"R"rOz_!O?;r2 ~HS^[Q>2 LmR䠴.r>( Ba4;*8ữ&x'/Bjr !ƋyCrh)l&ܟe44g܄wPݚBlGe{_~ l?=z |n3n1,!bw͛pzġǾ M!ٝ;_а%Ν^Uq*ԫ Օ?̛q:RWCFNN땢F [7tc=gpHiښR2}|MnkvrXtAZ*2BZ^>8L}?`6~LgbpnnͿwחn6><3(bZ~`ՍVeJb[fh* ~tT}zO pܸqV` pl1Qc !^<6 VYfh~ie?>$!DTv }W_"Df$ /1"J^Jv;s#_}1c9nb5+(MBCϕHqbE+~zy-3=b%Ҩ#ʳi|s)[Jpʍ&cأz +Z.; |W5uYuUR[^h~^Gq.{%t ܿ?짽arB ^Ӎŗ}Lhzlj^Z o=zi\4ڃ,sTOrrw}";hS.ϸ3O Nl2TR2]>B3q rmp ۘ~e )i 5.`c.^ށ}#hSܔ}c+=3`cMgOˉUYp >"w'HGۢ 9=r wP*ݣb|3-wGFO#'vu˕n4kOrㆅ!'M=nllTB\4RKU9_{H0m.(WFKP_BJc׏ҳ}O!D;\%(}|; hUYp R!(}LHkhh@`93n"Os!Gy/u Y)D8(ks䴋𤋷Umc5z0J_ W(2 K}79yIMxxvJ_[E}4׹jL .rh_WpUojʑ|5___,-4w1?11 _*|@~m^SKUk!>c'TF; L^NGssu u:U ~Ş G>hjضIMZ 3+$vU?$=&f;MʷT+KT"|vhx;m7͕雽G磣Q`'~r>|kp}`4!=*Fk_vS}VüS0:`cyRġy9lN|ʌ-z>sn@=z tI~9T^]#._~3oV`2_ιF{ˎhGY>CV?w>;4BɆOޜw(̚5;V04-(RRR!֭cjwSw`o4T]w lrɓܐ*b.^u':zg!0ȥk?sY5pP7rIoKK˼yvڅ/3\B_zߕͷ>~Id90llllllll` ` ` ` ` ` ͅ F1xN,-<==Ǐ_XX ¦ә2 VoXhKtNYq$[۲Sda8G!z_槞z{^\:#+HnXbQvo)zSḄ.\g_nܹskkkxܦ\]]=yGy+ujәfYdEQQMءDw*vVҎ&~0{0uXyGZ_ w6j΍xޟȹ;ќNS<ǩ 0۷/^XR͞=˶Nwww_dI~~>/2&&FREFF>|;+::ѣXV{^ZYYYbbט1cJJJ.\ ǎ fj4-\pJRَ䴚vv V[䗿<ٳ.]ڶm[RRRAA˗n/*DV)ӊ;$Tj1?P=oa+pv հF-lXM-gEMNyvjhQdΜ9|8rɐ$Y,JՊW}Qc_-B+s[ۂB*?Xn]W.WXX8eʔ>hРAj*jȑ p IDATmmmnnnDtti-Z(((///ݻ77288877WUWWqFh4:P 5 8p`mmzH)ZPVWW'$$[.0:BQ[[hL&[GGRjjjZm[[Jt9K#TCR?UX1aƍvO-]TjjQ=#6By32|͚56mZ|s=VU"7Hr2оpS#->(!#vzqss4 5 d3{SS;EHuqjl T/=/Wj85-̴߅n;+lg_BjhF0.I2`H`_tz%uVv\x;8q[G`nyyySL̔ofh/ovvaüT*?Ç;vwAV_hF/ZzSUBZ !:!S+ NWQQ!en<}t]$KN;Muf[djCD~in N-SdB{e^Ѩk֦gn;Z7^F/v_,`H9ZwW8ljgff7qisYtiyyׇeddTVV>NB} L]]C !2I]S}|| Pet:^බJ=I7)Rˋ}AGj|wK4g}iqѣG{{]d5؞j 2)''G<ت ف#iGα#';ФH{5*wZ9R~7uU/=/Wj85-;B ;+Z7۩׮]lj^U^dxUպ``VXO:eKhkkKMMh4W\!1b޽&_~' Ԕ7 &l޼yƍǏN5jϞ=ǏE+dǎa֭FbgUɓҌFcff&HYgU9FRgdd^{(M!Cζ]̜9 T.ZTfT^jugN/O:U.$Mu9Ŷ8'UMxJV!žv;+VW[D5V;d_j9%jnbMz-[c%IRo}|:%t-wz'^t7 Pl&N5k$%%͟?o߾Ϟ={ƍz2LJrڵs LHHعs'7255uʔ)!##CUV%U=2׮]pBN}v9~uPue˖HL֭[7{촴~[<%Gj|w "ζ]sg͚ݻ+ 6xzzf˰ةE oLVg{f>য়~* ,\$3KN熛EA0?jX8'UMxJV!žv;+VW[D5V;d_j9%jnkjje?|j:.."$' Еv6mp% O p?6t=Z"i*pRtPI[7;11Ss:gy>Ŝ}r܁l~ꩧy$:;򅈵ʼu}t̴UH!bbnKI)@QQTuҷ+/g:+?iٲe=Ђ l-99zYYV|ޮBk+peVΊu2`H&LP^^P(ƌSRRb1rӦMfͺ~zEEŤI<<<7LZv׮]:. +++::ѣ}r*j߾}>>>_ĨTÇ _2Lj:+++00933Sj pBDDD`` g\\\vܩjv-H3EEEjwuww7LB%KP n vK{{FYz5V::V3h4t:wwwoo+VdXXҥKZ\@~Q5UBg9ݍVK*ӎ rR,Dg\čQ%8bv_\\ (((///ݻ7#d P J!u'Fb{*ݲ$Nh4EeΜ9aaa?zBtKٳ73>|x\\ܱcdOQzVU9 RyU9 jzOOOR .ǿM p~UjܢlM r6ϴ~%%%}GikeZg5cTmll$L>ÇO.dFa̙| !?9sMcW̎AifGd)>R hzl7Z-mL;BIvJ~֜GeuJjUZM~]RW:gID5>ޣʴڲ}` ?:)s|W0zl6ͭ aaaO?y,{D턐*yX__cҥKaOu2^^^pÙ P O UF︔#\hkeZHƲC)U)׮]NrwrC ijj*1F4g}iQ#{j')>R 9 7Wv̒Yog\uՠA+Vs2s*ǧ™TczRhw o.`H4 4&LؼysssƍǏ0`ocqwؓ'ONKK3abFw^ԯ_?҂zbccy|*P길8]7m?d8J 0w(3H/` `@APp?Wx*KjYhj:?nP5rx9Wyur*Ki9CB/mbUWp+3JQ-@w?7[/[1|ƒnCkc%6,_qzO.Q"zFjgeGKZl}`0..d ͽ7uG);TWn|8w`,8wz̠si'G̦vx7G&%>qh/>>p~k&7|5wJQ#r_l,/|Qe?]*<ZJtҐ:.9*w; b!f)gHhv34{:ILiaތӑ‡7ZGG ˴=Գ>Q:9rX$n=gpHiښRm 0CפH:H^b;s;p4VC+Κ縩D7ǼGJWVYfh~ie?>$wUK7Oɟ?_ yN]Jmn|.ho+,,Jiteh2(|j*P*; cZ/P>d3W=՗,t#Fis{\-3=b­Pv4Q =W"eYl2-Y饞4zE)cE.k:{ZxarRc>?@n??̸j}Q[Uf-Ù?Bo>/ߝN6# QP׵=x2OO)KM?)g=w6|y߆mpM&ݟ֣J4[؏RGQ( 0?-!Da7H 9Fx 5^x𯽦kup֞QKq#Mהj !DgVwsd݃0U2"꺶"%D!(\{Η!'PܡڪѱI+!U?0pՑ1{Y 01BL .oW.;u9>֧oXqgW>ʝt656BkikS5WH0U2"꺂lj'V3gE-jSTpajѱ[ڽy.V+M!~Ŋm)[W(~5UBHhjޕ-c^#~'< Ы_s{[Ŷהj%ń 3+$􈍯NGssuv\{8W|µN}s>1 d!b S l8IGSSŶM #&NDV܏Wpwҫo?[ UKPQ(?(RRR!ֵ֭jAud|5vqEoů9;G6p@ > l}Xp 6666669cСY[xzz? MhjxbbMl=iLcfSO=uSH~hl Aq,۝^b7|9r7@K]>Fj9)-؉tɑ#G[(uEWv) 0<#?_Wfzɏfp,ۻwܐ_evHH;W䔞Ҳ`_RuvGn}mW`R͛we[/Y$??_~R"##>̝ܿ{}QdaaallV=p/,11k̘1%%% .DDD:tH=b9U*վ}|||굷k4իWsoFReVTTL4#11AjuTTq*???ie*^ZrDlzHQ,%Dl# e2 BΊ§FXpE[OZ\^^RF#!ãݙ SUV|2!GJXE~ gW a#eEQ#Z6酞 IDAT뼞>qDVNQ(tNWUUE /V+߲.w={ lS(&w[۷sLJJJMMmhhHNN^hwrYYYaժU˖-N̚5 cǎMIIOٳgŊܙ)gϞ---]`Arrzz^PI\t!CVZ%%BUEbK9r{7::apB˻z-[V\X&J`8{KmۖTPPp[rT*zs._or'eZ'FIIɜ9sxWW)--2fYRK@Ujhx!'IXvUIFȤ-bDlYwA]YQfਹ! nU;B*QQ>Rː#u%b"񋅰ע(Ƒ[Qk3??:....;;j9111:}`_,5/ 3r|:gz/(7S[KkOݻwvvo~J5rpံ6777=mڴE {͍ tqqqǫ4MqqTB +**kjjX[[+?RJV-,,j xĪR-R(u 4~Uyd2uttHe 555Z$J[[JV:@ʫ,(VWWWGGGWWW3Va0l__5а$R,&)1Ԑ  [.0lԒ_txSu͚56mZ|s=g3,XT8l9+Heu:;b!쵨})Z뼞EVy̙[>Ç?%K :GIԽX+WFuŋߊ_=rp;ioog.\( `_aÆyyy rÇ;v;РVɯ?SWWSO{zzBj^gGt z_Pt ,TP2\M7nͱdϞ=Uzɯbu,([#(X)ZUjQC) :lM.5@2E(ؑ6]PVUrZtvxSug ><}t[;x$ʬ8l9+{%`u]JՎ̵do l|;jzfCC!d̙|IkksyϷ~dzfͲzᰣgRze[]l[ 0]ѡT*?>}AisYtiyy93D Ȩ|͛ǝ񩯯'TUU :B|}}_b+kuEJ=mLN kkxXUEbKH.vR8hհk׮qzr7RVW2,{:Uj1BIZ&l KN Ev {Me~ԅ= ML[nO2)''G<ئLI2#ZW"*2K꺷%# :gr2juLLƍnj} wӦM|}uA^u`~---v튊rPZdddDDD[[[jjFr !dĈ{5L?3lذt+M0a7n?~( k|GWX1` }2~?--mĉ>>>5,66y͚5III۷ozz:7rg޸qcFFF^L&R\vܹsvɍLMM2e`㠊jߊgUڵk.\BBBo0_*բޝ5u?` $$lZЀVˣh mhcQjKb˔ #̷hѢ8iK-\@A#a m{ssQ_G}\o9Y=,L`斑]w0y?|j5t={9ŪYL||: `xy 98Zn0Ok֬Yd !dÆ A ij]O"O !`|bѓ[>|7Zϙ{/~R8:::66v̙3fBݘF%ܓ{Ιw >kxAMMͨQz7DÇb Al3iҤ#'0p7Rߔh&E!{w5IEEDD/7\YY=L~_Աߺ?C4Ν;-Zt-LXe޻w# tQ#`Xp!f555b7N@|TTZRvppL6mo0OD'/**Ow%RI\uuuddɓ!z^"*JLcǎlB!sssZH^OP(ݩ# Uk$mHB y֋^-++ H$~^7SV\d2YWW!ETy E]]݀rrrd2Ǯ]l(%1,@WWX,޳g<#xlLGX=jW^b #RRRZ[[.]<#44Ä#G)J%j`PTF 455Bǎ[WWzjs'ѧKLLLJJڽ{ʕ+=jzʔ) BV{ܹ+Wlݺ5..|˖-,ZHPhΟ?_^^S; UHڐb[XdX_MHH7o޵kN{pP7nݺ~=V~ ={ҥK}||uvvD"j'*VVV}7x/>>@ 2T&GDDTVVZ<M*VVV:;;{<==  E}}J644d2*FT)ZHTYqDɸ6$1 U0gz*Ɋ EYYI{>{-[zӧO}zjjN~'9NL>iҤݻw?~ߟiӦ7oѹk!Yхd*6$az'-,,,++KlܸY+?g!<)))SSR?YvU!??~mj@@kר޾}oUII q"$G'N6jAAASO=`5ަB~/^ԴdBשU74_̭j]CCCbb"gǎƦMŋU*e]qDTZQQAd6l^b>ΥWÆ 3>ڵk&{kYn|R6joo?ydsss\\\uuNG3\ѣ:sQ{ZZZRSS>쳽X1cP---ׯG{3Hwډ'ҏpivvv{AAAKAь?gO:E~}:88"9s̙3q`` `, `,, `, `LWOJmDFFtlj(Ei̬2k3s(s t%ERS>NFMy? 6wo2K{ %zttt|'KKKCm۲m_oM{%ԄsZ9U̕6??ĉw Mo,:.""_~N~UWh #3t]=(&wFY-Nx6JZPDKl?J^6zQQA%7^,|{eyo|G|f60'%Ilv3O/> Uݖf*vL֖ܬ+CR&c/g}&^ Ъ888ܹsѢEnݲN澋UWz zP/dXd2]vQ;kjjM6xV$-zL&۱cBpww5~5**JV "vbŢWtew֮^qfBdh۱艹_0eSõ'}z;QZG}y3*KnUzB0lx-t쮺S>N/u^^̙Eݚ6BA?,w#F 4(((ѣ&bq@@CL^t钿RƯP ch y)ֵS]v_hq!ou _L)?"2U*#sxw|l鍂>!?ݤ]M sz5MJ3\Pf<=R^f1Q* Fjll4I,,,T(*:99%===!!wޡ^\\,j!C4{KpS$4T*tvv0 iD"ջX{tƸ`ӳ>((8 wfօ\q&.qU> &gLKK+++۾}oϬ/k+pב rwc#Z`bAXx૯/s)YjkkCBB]fXYp_W"s0sXr>&3 ,{QII q"$G'N`$Jݾ}ڣhr@ P(555<󡮝F} l] MS*OGG'~T nz^v'Y(Bn;뾡0؆tk*S>N:~Ӭ"HJl, !DmhjjE[h>6ΪU"߿R;fR#G?ɉc`x&=]\r?sa[[}Ysƍ;#b躛2}kL8gΜow͙3ZO- w+p71b1,f-2`0 :￧W,֗#7f2I܍h5&/J\X[gSe|qqqygNq#LkqV:::Ο?[o]p믿;w6e=mWز<'a17wkmxIabx33OwBh4_GGس>~SWW맮xOʗ^U*+R;E^~)Ug+~"eքy;~Rom޹״P${{Xq u6J#TL---ms'\NͦZ;ƍf̘1Yk#eee־ .4)RLLL||Zf' !&BZ\rW2+Xss3Z̺p5nmu7We*[*~V:ZlAVocbXX Z Qcl ȍ5bN"&ݘ*=;fхA޾=<{OFscm5fQtn2[1"$888--m;ӃL.gfWWWͽŖ9 [9s'hmlh4}TNO~V" d(J/&>rаΚ[UKD6Эg6IYVglh|-jcOsmMΏ>At hj"U|J"u5B\DfvҘY~?G!6 }7n|''N3ָq'Cb[pW؜9s-w+֑gZմXG`5Xx*T,wNԬI,v`ޯWJoQx2鵡[5 ;cɌ|QGxbϧzvOfE%Ї~3B}ٔ<\p;J,{+-U1(,Sc3w[[\0n3/yof>Ay?BdhXQзZ2 lwy\i2%T,X@TFDDP;~MzOKK4h^ h"__L|RSSNB- BBB̜9SfeeqҪnƝ6̂:88yyy :tϞ=Vaf]7`dYl *;wロg.ܭZGi-VbcbuXl8݃@ ]f-NŬcEX'j$; _<W |5Z5 ;cɌ|Q=_|A2jOzIb,ΊƢcccgΜI1c!Z 6|_ 91fXoYZ9F9pڈt6>/ê/~1NNaÆ|M0F|a__߇ӧO/**D555Fz_So~D srr,X.\cHDIHHHOOG o?a2<ڂ>p֭#}iҤI?Cϧg'공.@-00_J}c(GϬðVwO`0,_slj31'f`j>h祉\>2o{---}Qss3~)'SݮɼbI嘚< .**JV iӦ <822^/HrssJL&۱cGvvB幹T>{1bĠA=J_WW'ɺ!SP1 0`Lk.rz ݝ>;~b, b$PjZ,t:BHGGj53]]]Rb:N`.̺k)W###&O\UU3c.bt钿R3T̚Bܬ^ѕ]igF/D SƜ!85\{' fw՜qj|g(JִB zM+ ^0֧] +P6;`Ç !!(((>>~رuuuW&BV{ܹ+Wlݺ5..|˖-\Vz+V9+ Ju,2:ב#G ŋW^Xjq9BF9|yyLښtRиT̴&=z4Z;vX``'3F tP:aaaJۅ\KqVLB:S3 ?bILLLJJڽ{ʕ+Yׯ+Wn=8XE꽕^C{Į7Vq%5u*?D`٫UPx ]񅐣}|Tc|~1>>&>{-[zӧO;UNu bb*99%===!!w1̚RVVV}7x/>>ۅ!GK{ӳPP׫Tj>f-0kg--[5TZYYj)k0y 4 ^Abp"? ]RI.N wz}K! 鍂>!?ݤ]M sz5MJezJ(q3tu)l`())6Nd wn<)h4r\ (!dԺھ}6U*ձcnj33g7|qz… _ܹs͕_(5k1̙0'bmKiӦ7o?uO Z :ܭllҤIw>~?RVSn# aٺQ(qUUILd/ A~F+%n] u)Qݮk<4f)0m@lںvŋ+ oom۶Lh"__LWcccgΜI1c!Z 'HMM:uKff@  ff͚%KB6lh0,-]*AYO| < 5jTL:nÆ ,<ޗJ$JgDl0>nd{-l/, `, ` `, `,jjjV^=n8Dboo/ɢ>쳮~^K. 4"Bw}xa7p@OOe˖R/ @h-Z*HƌS\\fڵVÐ!Cy䑣GB CVV֟gb''';w> 2C-((βrT6o޼l2%c%%%ƉW8`>|xWGFFVUUP_BHJJ v]jFIHH  kQZmggАHٱcU9vuummmO?E(9s.۩җgJJ ]xqSSӒ%K!ׯ_"`,T˗/;88|!o 0<⎎BFqrr82 ˄:wwwwwBԩS:d,,,;vluuСC ! joo*Ǐ?c&0 ԑo6NB/?BFI,z3vll+2vX|+x pW>>ƕ+WlˡdH$" 0˗o޼`0y*kr \G͝%99977722ޞV׿X=x@L:ʢwҟ5F=P%Lj[{6N$44T$9;;O8|ĉKzzz:tٲe?'~222ƌ4f̘M6oC~ O< 0X` 0X` X` 0X` 0XXPm$2΍UŠOmC{R^9]׮/ ܋;;}=uW+hRS>N(QQf퉨|!f<O{O`s4 ˗/wppׯ6rGC+=nk6~'U3)=}blͧ߫Ow_~eLL̾}}>fmW{{{`Xw- < ɑdvvL6mb8 СCν{1bРAAAAG%DEEj@PTT̄;^d;vP(&ϝ;֭[V%4> 5t钿RLU>Ig6fkrĪ{8[ k楥!!!2̆vbŢWtej~>zqZę mǾv6”1G.N מ8y]u5|/_ꪯ3y35m^6xhӿ ÆirW9 TMcjaarGمFۮޗ2$$fqeX۬W$77WTRV(r#ڬU0wb0mt7+H>ϻƋ3r]&Ö5OfakqW55`@pūWfddZ?vغ  IDATիWKښtRjglllnnV]z+!d.+PhΟ?_^^4//$//O$Y64111))i+Wk5FMMM%a͛wڵ'OvttB$<Ҥ̪8111""BVO2%))ّX?~|̘1Jrܸqǎȍ5mvl'%%͝;v*UZZt#vŵA:~+|m2N^V:{uj?|" o߼+r[^Vrү>kTU*rGمFۮޗ&Ucf6Xff"^˴Zs\uָ-[pD Q?G-^BAAAUUULL :w 6sg䘻L-k&mm.r jk";뾝uYu=3uRT׋DnBL&+--d9B:;;E"3((hK.HB1hhhdb*@ 8zÇU5!aT*VVV:;;s5!?ݤ]M sz5MJezJ(q3tu)l3UrG\bFۮݒ僻4m+sF$Qm+ ՖsC5===냂뭺[m0=wYmq`ajzNPRRBm?|щ7IR~oߦh4\. EMMG?~X,w߿1<<\R1qd%!ِ5h43aKP(j jF%62kfI;,MMMTRgG׿?I  3:rck:k; w+ȚykkD"Sx6J;r}Wx3##on4r\ZmSaߞI !6]_B{[f-e۬Wеm<$Kdo\.'H$6kl/3Z~}O[sÿ< wWﮉ=|Pa p( Fc0 CGGbbbj5}!eee־ .ya~}M]]]9>̥?ó-luR}Vܑ֞tɹ"˩<555Q.&t3gxyyggΜήRWW=XԓA -V5sڦ?)_zUu5wM'M{Ǐs5#cZ6%%P;V=$bY3?~|VV֍7233{[# aٺQ(qUUILd/ A~F4:B˔̿n5|S3W&rG{[X־ͼ"޺G;4s]Cؾ}7>䓉'Z{`xak̶fC__>W:Z/D6$eڵ/V(۶m3wXjjԩS]\\7o&''-Z733:2### TVJ3A 0)' \]I 9TKvMJͰ-add$=i_^dzdrt$Š|f{ޑ =0uan `^^3پʶ: */Y[aߝջoM+mKXVV?a<ܣaf{33\tOYwc"Xs&@Q:oFb 4~0tXA_ӿU0zjwBE)v{BH]u5|/_b$(Z- #<<|xQQS*H''ɓ'WUUjX!AeXZZ"Gfڴi~T^5) !DK$\R)vؑP(rynn.ٍ?$ɧ~Yz*BΑI~`Xp!nks-.]T*8@a 2GSH65~ 9Y+ڵLD" ,**Ft:ZH>ro;fv{a=y6:ffpdh݌ciG݌{"eV*Jc9s3V3kO?Z;0ϝ;֭[]ryQs8uVS*wx7oYMѕF=͚[W ![]* 9v?|7BWB[*9Gky^2jÇ /^z5##cժU&GjիWX%{{s]~^HLLvj4@DILLPSLIJJ=z4u!i ͻvɓ';::B!kPhΟ?_^^sdnĥKv0k{+W7̞,pğO!۔kʲv-cUUU111III9rHXXR(nf7InC1y6:ff"pdh݌ciG݌{"eV*jOvEcχ9X4 %//$//O$qw!xggN8oc+ !G}s^PSe1cNpt)-n7PDF,CMp)1'cB ݤ#mGΔ7tu~DJOv#@(JzH$6~5((hK.aͤFT6445x'!ӳPP׫T䖖wy>{qq\.WC vdRLV__QYYiT2KBA&uvvD"*bi2XPsDܙGFn/V TZYYl'+:}b!-4'b,k2μӳ>((>--lo񆟟_||b}Y>XNsrrKׯ_癄Otbbbj5uՕ'l(>cC*;;.]Xss37{\???T:::{Iu{:mgcfvfb7.NȼX;]]]/wwww~>iƊiO=^~[LYVglh|-jcOsmMΏ>qR^/D=v筮ZT;W)Qݮk<4f-#G6YuPv"u5ԙ+*Tj>L0!//O6]۷oj[l4iըM6ݼy3--'vΚ5>5˴ǏʺqFff&}>}zjjNΦs.뫬%촰,FqFIgN LIIJulM4iǏHkC,Ryxx߿_զP3]ˤ߸qO>8q"gΜ9ԧz{ImXɤ#o^,Nξ3~WZ=VLJUNϮ]bcc[[[Y?]Io:t(..wƍ3g$ٳW^d ={6"""''ʫo駟>xiӌp겲.\hBaCCŋ9m۶bX_e- kݍYN;s[[[SSSccc%៹gϞ:uKffn޼`jQZZ:sLV3ϘKk Dj2/.Ne|Fj6??V!Ӭkx^{]nO?{\W? ! \dt Y,/[֭_붫hKJ˶ZZ%niV}\>u׺^xA@H r c4L~G;眙Cn?s !xj|06l5:nndh4'N`{:UVLjkm-pL=&$$&''Ϟ=" z nܸaÆŋ+%%e̮%''jV;rH!Qݼ=FТXҕ8 C|^ !aߟpyT߻UX[xB˶̯=bm*kv#ԏ-̃?aSc?677D"ꝺ޽{2Y,B rVӧ{z}}} EeeJ*++#foUUURd2D"@LVXX(*++juqq1R)JBHXXĉgϞK t6_8\ןQ[ N,|ΰ֓cFx|?b^[kk}ޙ}خ6ݹ,SM5)!DtZ O'M]浇0TsC[-G>[_kC}lȑ#IIIFL&#nki}Z(j*)&%^-*5@nU" F3АtTzMk)5M}}}VV=zu233GEJ ?~|FFhΦ>|M&SWMQ{'E H]Q~tɭ +ޑf{<c1kzͿ}~k@7f 5$,k-| 41fOOOj[@[bԩS3335d HMM6mRT999ׇR̔:sLBi&fe˖%$$̘1# ++1L4!XC)hFjx~^ @,Xf^ @kl`l``l`l~ַoߦ&q\rG6OFYYg}fw6`n`ŊZUU5w~/)++$+1}z鵵s `0$''OSߙ3gVWWϚ5RZZF1s[[kzz:]p^_`!$//o˖-T͛7S]vI777`oܽ{7;;`ԃ$//yQ2[Abb{Gk.ꁓO>Doߦ O5? 0\]]=jZZI[nQ!~~~ԯ%%% P(7KoO?۷ҥK9ބ zyYHpYf)wnٲOyjmm}4z{UWWS-[Kեj?Ce 86'yxx4ߟz@={m4sń63s ..СCթstT\*)aC̙#ܹC?OKO=̬?yҤIO=zh4B&NHYb^ߺu[~LB===v< 4]\ h:͔B}>Mkgn-ZD'hk(!!!O+ +((0uhH?9/\Т= . x6]zO2xu-_< g36` 06` 06 06` 06` 0` \]]^j~D pS,4(;bu`X`#x;)0(3ZEՑ20uƳ@GiwqkYޖSB eO?tPWWWL?ݻO}"b`` mXg⢢"&bG!Onnnȶ)ƮNmU{mw~f˔};;@~16؏8r`٥1 ~=mbKkWZ*˯Mlpʋ:BHt.oWzyo1??ߕ+W._|ҤI"HT~G~`f]9[`],ze.'iGf.6]EkkZ7PjV9rdJJ !? RQQV/^l<@ tҭ[֯_pB*ABBBzzzmmmrrٳ-,΍ϟ/--}WAuu5!$>>>77`0,^x޼y*Ec/ z nܸa)))'O...v#G ! ,2e۷O:( YXkr;akXeҬ{蚗m۶$kB`8?ӄ7nlܸ$wVZ6[ BR9rJ/ɨ\G W(>>t`J%巻l=X xFku ^y>0V~3\EZAR"/ϻʼnA }+GܽeA%KzwRB@(|Po,qBǟ|jıה\GJe ŋ'Nnqa3Y@5Qw EY/ř$<#gVZZ;7|s˖-B:BW(*NOd2RV3TUUIR$,^k,C.ft:Rw8RB&N8{l:1kE湘,ʿwL&knnT㽽 rVӧ;.  EQQQHHbmβ;kc;4ְi+f/.M*{xxGeD1Ojl9Wf۸#1*ϝ;qq 6̙33gNddoa>s{:\Yyt2Yb^HfffQQ͛yD; ]pecֳVĽpwIĺYCVfiw݉=\Ž"X/4O|WR*˥1z1  8'T߻ OP̿-RF/JZ +G3ȧX\[[+_ҽ.L6CZ;Uށw }g.h'iGf.7ӃgI$+W4?X]]-ɨ6r@ P(:pTJwÇԑ#GDGGb-dbr"Hz=w`{6lJ:vwEt.0ЍH$:*͓lr;kc;4ְpC^BwW^|OWA$`l9G۸#1*^y… ŋɓ'um5s97m8: k}aW^v{ڜqs̰N"5u'ơ*C'Lyv9rW&psZC*ി{~dʊ_B.c>ڜ|Cd3s9[`. f;sA?I;2s1G:6vnnn>JZa-^g+...11Q` OOOzKj4O>"gMM !±wwwj/--d,ws{Z!wo˱.^W=w?̶qGK$̘`k֬ n2XCZ+Gga-f_R?ЫW/}ӱqO["2;u rMpו:}#S LM_߾rg^ՑfpA}ҿo˅f(Xk^sx\wvd*a` -Z(##Օu֭khh5j/=]Əa4鿚c`BCCCBBӥR͛7YpB͛ ƍGQÇo߾d2ߟ~͊e >++yّGEEi4^zj⟒ܱ2.mĈ۶m;~xHHuw^N#&f۸#}V\/B&M>uv:6fr5\y8e2l+B[ lz֊]O6nki}Z(j*)&\y9]m&W6F{ϑ˳>|`MNaG֮orrwԤRSS ҽ.L-kX*sA?I;2s1G:\\\͛7PN6MTꜜCCCkkkSSSgΜP(6mdQ1cxzzR zDDDCC3 w! 4O&џsZye˖%$$̘1# ++gEbMbŊSfffj4WWWd/HҦN矷 6Sr;1c3aY&k/8.,==}„ Apd츏?x֬YUVիw$2f3'^0a!_$Pas{v W3f̾06y u5;YZRs4b]QѦ~K>痜=V'qÇV䃤oXgiȨe}8)>/ȷ_@Zk#?"""77wѢEӦMHtpw0ٷr9[`]l>#3sW,_nw>|888[8qsUVUB[3:ZZZܹCZRR3/S*kSjDD!|\1sVk +tf\.OIIFIKKݻf48OFcxuLdVgm"ۼ02sɵo v6-V*;V֖wOH1az233h̘13g_BONNVZvȑ)))Y'Ⱦ}k+kL?>x`R9tcǎqՊ{{BԥvXCjsUt%ұqK$)--g[n۷gϞ?1vXBo~~BTT(@ J&I$Bd2YaaL&Tyu:Rw,©'Ξ=ߟNZy.T*-..`vߢ{dfXLu k|м rVӧWlXfffQQ͛yD:#kOH̓B<_adԾ($$dѣG=cƌk׮BD"htrrjmmussx"nŅz UNccE^d2ܚ%%%Ƈ҅?|...NMMݳgڵkcb IDATbUd_MMM=z"k510ƇyIpqq1B|-φ9Ν; ڿ]kln'2{kWggFXg|_0`cVjsЎr&22իׯ_ uVhhh~~D"=3ns7y#_cbb>펬 gJbE~V$ ){XoՊ{{BԥvX{m=D:#ӹS7x 4@? H\NZ.LBwPxzzRGZm]]3N|ӧO箈q%ҁqlg|AMMMmm… yѣ׭[А9j(\RS,?>##h4fgg3B6ol06n8bHhhhHHHssszzT*yEÇo߾d2ߟ~q͊h#FضmCBBxȍ5>̰DGGk4,zU-+ԻnĊn޽{ CzzT'<(FW^3ˀ6loRcXe ...nʕ/2!dҤISN/mfvO^;7n͚5ƍkW.kgT63|ݻwV\IY|~̙"d]O֙LzyN^Uy-ZSi׮]kԩSZKܑwߟ(.ukq%ҁq/.))3gO?4ru׏jMv9Zkk֭񵵵/w̙39iӦ7]۱cǛo)GΝ3fgVV333 ?p@BBBqqq@@ի'L`"֗QN0`0h4j=Y# ]XCŋSNh4ӧOB;vʕ_EEE%Ɗn_|`BȪU}S%c"^ a<{ԩSkkk322 GUUU^t5oGVܫߓE.ukq%ҁ{:eh4Zɓ'&77ĉO9z{!L*QX;u qY HT*Վ;u/W_GDDh4=ݽL*Q x> )6A^z5*hl7;+++Ǐk! <̙seCPwvQ+WBBBJ}82VVVSRRB4z"J,YN7v؞={ƚU6[XX!vM.`h4nڴ)**5!!!==699y\xyQSRRmۖđZijZՎ9Cݝz@ fmCbb!C***jŋ-3ӳ֛2y|:/w  _D?*{ "񰰰'Ξ=ߟN J=<ӧS{mVXּLrUrѣRQQa^5 BS{FYdlАtTzMB÷on2J1bĶmێ?‘ѣG[!33sԨQA{ tP,نgddlFGGk4,z]2c#D"##c̘1/""aٲe 3fʢRO0`0h4*XKKMM6mRT999?x֬YUVի[ymHMM9sB۴iEլXbԩd2 B֒pl,Gx~t5,l`l`V`MxoIENDB`pasdoc/www/screenshots/latex_class.png0000600000175000017500000057165613034465545020714 0ustar michalismichalisPNG  IHDRR8 pHYs+tIME 1tEXtCommentCreated with GIMPW IDATxwx~ !!TP|EQAEzE)"+AD+顷.ߙrpד'ݶۙݽ aY|W UՅg /Ll*f78*x4& ̸BVy"4" 'VXeY:QX~a/*f[m4BQrfUP9f#Z?g42㨌_ PF=3 ``Y0*4}DTjȅd@ x;=F7jh42lРAS'Վ9)Hďi*:jZZ]VVVO!888''ɉ<@3FєJedd$"4KP*>b*t(4ڸ&M2 cooo0aooϲV5Q РqҌ;7nHЫ>,V~z=?+ `i8 41ʴ=V#AMpÞz@ڿI qC١& A@ reN#IsUFiWUl5׮\Μնu>={p=#N,Z7Va4:[⼽+7}ڶ6B|ʂ:jI%G>7,ZG_82_qß}V_Xe Z]:p2vqZ VX_5iO1]&|>ťeZ_O&\Eaٹ=HM_dGg eoO%.+7oM,:9:ٲ G.LJ\eENzx;B :;7!y{ئH_<[,X<חQo۵_(Yo^j41 h:k(4Ԍgz{xI !)'.J-lYRh7=\O&\D %5Z>\Ȳlp'fIJJUx_ZG)hy򣴋oz{W34uZL8<GUo%/0x/XB:C#B[lV?!Dx򕌬9t(""Z6$?J#pwqVRcVGOMNM+,BZGG6lBx 4MȰ:ǵi]=FoRIvm80-\ngZ-ݲ,k< lPs^Ҏ"^;{=~yBju``BϫcnYe,e2Rx͇\r¥{I[EE,xMӷC>O &v`3ڧVj7lj`P8~00̆[?hᓴxe^WT*lIII\.nfRB!w <݌c`Bȭ{Iy^Ҳ7 !aN[w? #5H#+(iެg"y޼{_V̅| xrҍ[f.NLuOr; vD<#BBVo^ X6nAN$\>k!M !}v:~6a'k|r Mmb" !=;w]Ba  ~Jͽ;D0c;sʣL&Mڶ5faN'j-gu:B;}aZ}Tx3g''Wg{RRpo =흒:uC5 v5iuP#Txz=moٛ/%%E 6w呑[m%!D, B>0 ˲@RѨI$D":Kk k,y hZeb@ x  :1Gw%B=uz;/ mY33bX,ztܻwN,& Fh4UjƁYkUׄC ?eT*k3&v0546 !NF3h$A@ !F4 ;@Ʋ,3hlA4 ҔJVUմ~ZhZN#I ֭[:Nj4JT* Bhٲ%j5H߿?)R\^\\\\\LPPA0 34_>:rHsGԤנc34k9F;ZtOQaQa&&9^M^N΄gNWIPM߽[OkX.>{njZZdDs+YgҒ.t%ܼT*bcǽHyXRZR!!wn8TffeEF4߰zE.]=K\'TZiܾX1b}pΜ6`qfVkoNů{i/\þ}zB s=<<>X0}^۴i\l j;Inn#x'O:cڕ+:vmݪKR^xI_eP[Mt" ==,u^_E_mXr)R'O}oOI;vhחFet7 !~ڵ3:dub|Ɯy<o+*Uե,<<<)9yk>8WcБx^K/bBbZo/?IAjzԎmk<73+aP:򦳓s^}...$ԘE7)TQ9H|ңK7HD kv{Iu LQA,?x]tn AвBC֬D$Y$HDq:Җ.$X#N3 .BƏ}^pRŋI#3}vfNw6mJ3|ku=wD7o%͝5o^ࠓ\vrf!DK57Ŷo7o}ے+?nMyhB!ֈ-a#i+*Bg.{Y֪f̙h}_q.;'G(:>zB~Y3JնudW3f;cf~A?TaʨԴ3fqXjEhP˲]M=rVzGX,X$%vf¢4;W|[p_e%%NN\n|?_bwMH]a]X>aA9?BCB6^eggg''bqqNNsjuBci(U;WwtGЯ/boo?JJK\| !^'%BBL*@''8;ӷفn߹[P0 c0|Dr-~>@<u HG -ٻ|Ͼ4B1lD"3i$*Owsu]'աbb'O8te2v̋<<Ǽ8j+cY=p223-XVVT\JM"BHVvNHp˖nN$Ϥod˶m Th͉DRu#AHppsSSi#݃h2!Hk܅gΟxee\Y.!'Ry/wK%R*C8 L/2eʕO~oKeIc\?eEOeNBH\l4wƪ{qd'!\I'޷?3++//Oyyz.?TY߸qoΤ)oՋ=LyS@ Ϟ5,e?xN{Ző۝K>tDu%R ϛۺeK:?x[&6T*H$:|CʋFh͛YB,Ţ5+VD4Ξ5ovČj a\6yͿ\޾ʊ:Ix#;99=+DB1Y~~IiiHpH(*~.~놻{ۿq&ڵnShյk\T(-5-=]ո8;BR)˲o &>&> *ܿڰ.y)ޛ5D3 JJ]]\v,H'/eg'=uu:]Zz'V<}=7hPИ" ^Ҳ299ܡs3z3o}X۬W_xyzs׮"7BѣG?;xڬ9ii8Pg!<=hZ\s䯿t:˲_+K!MCL76O9/YǎB:sַ6[c>^ҏbMX,Zt |~@ӜY(~xK++,Rmx&5i& !:}-ܒ>z.]l'moiiyV-ZwS+.q:rSNNb8vQVvvNvp`p˘BN#[H&3 k>df/XrRwKjńrWN ȭF/Oyf._S'Ny|aV[rR& kf| Jo8b^S!By<ޖۢ##~M:kİwǁ93֪a?#qBC]]\k_zqT@~i?}+/:spp9b4!eE6t ?7!DVi-P_^=Ige O9t;xCj IDAT<3j?_*`+;>x0,4d'q˲vvV}:sSLdU tkWxvvRs=yo|q@ $T*u0($(YE._Ju2);xyXfGirEt[F0{]G@'FZS<O*/&OQPzY-_䧨Z>w!\i4~]{&\TTT)6߾*5-m>YV]JD"ݣDZ'^: Rܵww-!TN !JJ$U74%_wz6b6a⏛6y{[2(/OX}e-eB[~uBHݭ Ѐ,^y+;'gmn6mܘ t:^)cPD[VœG,V+N,Ip3SB4RU/Ubj*a6@0~c'&\qrqwwO&=ușZygD"QbIy<^XHXU%a|}sey b٤I,z]VyB\]UiBHQQ!$;'G,K%R13a4RJ]9;k&;88M,.Vz`a-_ь9R>\k%Rk7N<9㽩GSrrrb;FXBoryfVC?pGÞB{In$H^⨗_ Zl \D,k,;yҤU֗<H0##eپ{;wuWW1C/_÷iӛV-Zdd\zCvO+HpNjFR)rEBP(unխX]xfeZO{.\|~s{j5M !۶TV'znyII~AA@rriԝ M+iEEr9!k=zҡ08*D$B3R҉By<5 EFt6TvY曨C)ZRZܩcGE{Rs9..K?`/]ٚ l黿g-ɪ|`0vuN]:u/巛7W|ҫGw=9gBe!dO7~k_D2};B钯q8p`̬IME-[y'Oī׮[*,4ys<=G>YQLtJY~0똰VVUjuyyyYYYiYYIIIIJ8(nα~LTԕg\8yfY촌|]]\<\[hcݣ-,bz1oog'gGG{;{I ӳ2x<^ R&~05= b >\o  A?LRi4W׊cK}k|rZzFƌ:7%BH^Ã|};Fnݲ女qԠiCG/V,x-'l_|6iڵiӮMZB|\ CST"T !PjܫnJUsG?}==SRZNΕFIKOkkNG [~8N%qDh泳31jVŃ{7 ETc9mַgNjޏ{^B-3MFsGc|%7s ?;2 C9cY)H#ZftTDW˟xR,,2FPg8 UMn {w|ZLLОzrj;bC l$h Ed,\M ,u"& !4rդxzz3~.j5iֈ;6lihp;h*322RSS|AT Bk$z5itm{3(+ J2ܰo%eeeO=<)(< \n吧Ua'pIIIAAAt`{h>>y.N.'zQ꒲osIIM btgUeeeE /++4?|j_6ᣇB!NC -Cl#dF($%%EDDԸ;aIN^ZQ,UlJҦM is6 .54j7l b!0Jݝa+3 M4McFt:sni6ZMACbG߾}a <3b0L&JLLlҤ ٕNkŬB|7Z{Zj0蓒 |oo ,JҠ PT*qZXۣG|>#2*,>0AAAM4tU*X#KAiiiAAT*5* ` "yxsHč._윙CDHpHTuBax<^YY j/Au^8۶U;h4 4 $:2"[F볳[j%JAp7eFӕu YV( -,ʚ^je2Y۶mHCGejeYDxi022 |>VU8j+66+Jct}w B^ ,bQ(cYV К4a,q~۶mTwX.H !|>Y@3B7tD}ؾ (͸Kz1ee'*0àaz=ǣϤ!Hk\ ,XPxF5>ldH Zh3iG7M`V& jЀucv)B`f٪h˲z^#gpe ΜtF(JeRP)e@;X?\v[n}z&?~3clI  \GP4*#7BIm۾m6ڴj*:*:yDXHXP`5Cϔ#|x&^f1.oLn%ӧGR#锣two oo PܑnVPTjZJVj5RjZ=[`0t:tztKu'cW?$n]:w @ E"`@x@HE@>\^T\\yNV+rtq`0p:F3ò%$ >=v|p}z mvN]rRyn]i!O>t @\4dE0Lgܼ˰O)Z̵i)5+* D"EOvvvvvvbX,D"abb`\~ڡ]^Ųl˘mwKJ"?:za/<0o&4H;qzvƲW=vԙGܲN#4PZVVCbbq֭0xe 4koX{BLڽ mtL!}z[5&n `?-r=unnnnnnNNN4ZH$sOFQZ*!ǟszfй._9s|}hF1l.\Я!Cp~X#N[rՕ! ̶TvıGtt9?_Fb6-o\%Iwci?f ڢpq hYԂYaV#&Gӫg?6$c;tNܠA[޻o};,B~Ï:R!$^8/`@A4JuuN] I#@@ -z0tݸu,:X,ܳ_Lt"8Y0wN`KD^`[H$;w̰Nןׂ ?270Y3 Q1u hq].x^zMo?k֭KJJ2jڧWʲlvtz];t EK֔?ukKꚑjBCBp~4#GӐ4e̙v?凭Bd2:kοڽ|>?0 MVƫx{|f݋#?4 b;߸Wp~gq˲Bi-2KiӦU׻o1pj;P hZ7nńVKߊD"PT\ܤI>g/=KJ˛xxH$^Dq]B@*5z(N:!J߿,{gYV&7Xnz=B4\.h*obY[xk poqtpptp`YVWiSf?wm n:$`=31&JQ  uWZ<֏ziA*hTƲ,L;@jኣ?M(-iE0 *niuUe Aո)@=P=pPظ.[CѸO9h Bzta.-[ΚZIKKodMۼxxv?/ ܽkגGJZŋV;uؿ_pp _^TTakk( u:w``mz^(wb.]]]\\\2BVCv#7af %"ѱ*:`0p}8]חit.zra1V|866OOO/ 0enS@23I-[~HJ"XqLt4!Vܽw`04o-bbLLWTW:T6Y8on]L,ofخS&޾Ci߶ի~aJ !g !_|i`0u2j;wONh4^%ԅ2fsfWL,pq^=-W2AA,޹sC8h`L5"Hk2\:BڵQTJR.߼yHII֭UVPXXXTԿoGpuuƤАUO5'eeIS r:@p͂BBHiiY !.Yv? (0ǟ~9gޝ:9:U޿?jV-[s6|o/N՚a/vrr߯)+V/(,*>pC nSDW10̞._#BH<8(h̋~m }f̨QMB!dӖ+y_FffuיT*.Kۇ'B5Hc^xÅ :v ;uL {B2sհDA݇7@p*{Ψ &}/)iq/_>t$gz~sl׵ѽ[ui'(0xxꖷqfEhC=+--aơX,{n@z v8 +sr-,[ ?͛=SR7sv~p!+׮͞> Bf͌Zw&J7ojbzhH(!D*1kӺI%^q_w#,}n4n"z,[[ |ڹwCգ{pP0iyy[]z-c>޴*¥K۵{{~۷O>ӺUK77Դ4Fjbz`~}7u'uYQW?N9;bо3X.N:,?***[iwgΛڛ۞ݻ/7ƐEE.<}3gFfO7p_(Z[ IDATj4:<`X]sϤYʛ6mq!ZVoK/=9::ҷ ϏfŲlQqB4R锁aܸǨ\+O2k{ƾlU3UO\|GEFa w5gotJ_p2Z #HN:8iiiNJOO/++ oӦM !2… C h4///W(Zٳg#HuFFo%S=e\rС^{NwK.d2;;޽{>ndǏW( q{mڴik'222%ĉM,Y\\|ӅB_PP[xD$INNvttYڕ-d23KMOOwssssssuuuvvvrrH$ a'B*D&<=(0B$VtJx{GGU.=!`*yA=o GEo 'OY}5.`ZRRҨQsnݺ ˗2ɓ=zؽ{7-߿ԩSN=tP8vܷoߠA k'7ΊRSS-oz~ܸqqqq>>>M6}wOހeo6((hҤI矏uVLL̠An߾mpAAݻ'M4mڴ7nԸof=zHLLn[PZ]lٔ)SV\izÇ>|xذaÆ 9s&}}I&y{{kn˖-I阽Y#skeDqmHAs'TTT^x*j„ /`&B1tлwjZkԢ_~̙vvvv>|89uԋ/߿V:::n߾}ȑ4fkzw}Gڸqcf͚z˂믿n߾}ܸq&MZh )P6q-[ 4hϞ=/z<̄ zw;wl֬ÇkAskJZpaPPиqj\2((| !$66~_}oܸіO2,Ǎknt Uꦼ<55^#f@_u3- >}:0v1bDRZǎwiknW?,ӧOBZjEydž!k֬ٲe?\F۶m,XP^^/z7vlY2lӦͫJol c,:ZfA0 Wf|<ŋ+mɦ̱aÆ<+%ATs={4hP 0 `/_l* l*H 2D./Y2z*8qX,K.G1cXH+JG_;w2X-srGsGh*u$Fݡ:s̑#G/^ܫW/kl?!pMΪ4n8Uyeee/_NKKSAAA:u\.DQT#F-9rƎK;w.}n:BH@@}T* !ǎSd2߻w/7nŲN3f }eYիk\k<1wt͛ia+lt`Bs=F33::ʬ6'Y=r!$<M! jNh4mڴ,CDff1q(-,sNsHRI B"""<"4.\p·~{}ٳg]柺3ՕJefj>-Ytݻ !-ZXfY bW^y;]njh%u-ޞ"^~eK|&Ԙo{snBf̘A?~<7(͛gϞ=zzUD]%}!*ի7HX,O"ViVn"gL'nb2|ܹsMϢOB {svvNNNfĺ׺uʁV5VI0nrܡCZy5tR %&Q MDV۫XV_W]WWWWlX֎Q4 HSP"c޽,{>޹S̙3s)vEE^=heeE5vX o h4-SwES-gYYY27)"29iViX,EyD[-6lXeeeXXϛ7ow5tٳg޻t"!BѣGh #e;,iI/qP ׯ_|yzz:s7&!%p/RSSy&'ڽ{I&effHoCsκuz :t(>GO˼bٳĉXr-E"Yi~ S fI)RuuuZ_vߥKE1qKG2%,"]VTT7J{K0fP]]իW[N73XF뱨HbC+^wG%]`Iy aHLl_,kĝ>kR(X_FΜ9qƦi9suu} ~w~SSS}O>=z(444--...M="|͹;99I'-'ZEl#Guu-[lÚКvi4#tq:LG677ˋغutRRRp,Yl]‹cJrHF~UB,T"X,* ͛7-j'uK[X,%,W9< I2&%@cc͛7#FYt)~tͻw*KCEEE6l'%%%''67ط^pp0 Iܑ9~x.K"t2iҤ(PQQG](7w\H$]ܼ]]]oݺ2+9^!lZ"ҦGFEGGݵkWIF$)55ƍM6!lmm?K5JiE~h4ȯJbiue)NfIPN: ⌍|EzffiiiaaLiii!"JO% WO] ?W\G~ X[[?xb8p`֬Y!$.\`SNaXZZ(ǦGm[n%ɡ#FD";wd|>?((HOOj9feeƲlq/viGO>g:)R>ܹs߹sߩ[hQ^:RNRQQ={6>s={vddd߾}oݺ%s߹sl6;s挞^N-ȯJbiKe)‘#GLѣG bYYY[?[XX`鍍׿|Rv"GT****;wO>|xmkkkq1-Ę_B<: |>q\. ,:u*TЮ?M -=S'=FrSTxUUUeee{;³Ax@KPAZZZN jhh6m80~x$cbb8P(444_nʇG[rر/_ZZZHϟ??a28Xyyy~8NccjNrrr߿vL2ljj:wI&|BܼyS[[{ĉ'NLOO755GA:;;?{G8O>mذ!&&ʊFld ‘#G>\]]PNٯ\HP>}D&TjNADDĸq㪪x< |2vl2`|>9r$ >!>>~ƌeeeBPSSNGGGcuuu5USSSWW?pw#ԒuݹsZWWv&U;v\vMWWI ܿ_WWw ,8!dkk;uӧoܸFq8477m۶Io買OJJ믿rJ׬dfLWi&؇֬Y+UUΝ;#"""Miiƍ# a"{?͛#GZZZfgg߼y[,KYa{.$$$33ʪ177w„ ׯǕ.c-f+*'''GMMFI%6;D::::::ښL&SMMMUUUEE4VH$@ |>_(r82P *** kjj,,,C,Sͫӓv$  0luuuBɔH*&nS]__˗/wjjj:w`ڢT7%m USS#) \6`0LLL1P__/ǝ]rrKF*omfD:uP(. CEE-;D"QQQQQQQN,,,jfyy9>ZE:XI;5BG+i8V  E,# lŋMy!&[# _EX: 9;8#m JPz!4 Czddɒ+Whkk !bZ!pJj[*YH$1ud2 wۣ511!NMhEӕ/LbrL"Z])t<4L&PNһ{~G{;&,j|>H/%x&KRJ+ǎ]*PڡEw? N>)E1#H|>Jܾ_Ổ@k;BGҗt}'Jcg;Ҳ2+'N'eiC;~X3Y__-[ uta 6uz:4,ظaOn.~LWWDܾc?d@Ӂ3א(W8rșӧ!إO-^D"NSUU}/W^^%?oO~unag\td)Я(J˗Ƴ٥ ?LG&9}ďKKxxÇ[wv77߶eR  Facǰ&Tzذoܺw#E"t}Y̞U]͉1j$Bh܀;D 28?N2x4)eq.BexgN/_pQ$[SPX{>|=h6,l(T*^X__+~x<Fc\I#HuVvv=n޺e7x D" upHLJ~WYY:~2 Lw' cxN322vB㄄oްO!L>~H\Ifj06cOwQn9i"HfcQF բH>\___SSSYYϟ'Y4/O}qkטlٔBL fEEBhnI$Һ5Ǐ:ҙg_ﮝÆBj#|>;%Nt={{D H;ءR؉2Dk|uN:Ç u.WSUusqqBf `޼iἹSf>q(iJi!C(-+KM{9{ts޽E 8@JP(]oHy6(bI_!~?.:6Ǎwի_ԌKHLf bdaH$vrphllԷOo>466tgUm--s3KW <ȲGw;jb?sBwgGַw璉M]NŮuvv9r#4'Gκeez߯ ?f-,Æ:7 ;}d2٬[HڍGBh%Vffģzzddf}ɴVq !ZG44 >RҚt~)d۩zzz^21v=L&:SCjõ7B81'|>4 ؘF >|>c_sɯ\޿_߮&&9݃L&STt wb=M'YJ߻kgg]] EVs{ IDAT5_^KlENl'<^T*Uܩ#Ӏ~U񴝪w}=i/h]]lU>54^%PA>#H E(w@,m3^QME"f0<*Mfkkub&ٽ{wHT]]nggtRO#H!pjkkmmm===̙*kצMbŊ;vH nf[L.\p16]ZZ`0X,V߾}٣Ȼ*** ]t!C>}*8n@'q-{Z/o O!XO!mѣGcƌ|r\\ҥK^~sa>s77)STUU+666..ŋǎy󦥥[1ccc={8zK:99u={֢rssgΜxd2y7ǏzzzQQQ jhXξvZ׮] Ɯܷo_@{@O !((i=AFlӦM%Iرϟ?7+|~@@alWϟ8n8%zUjW9sEo%$$(%p@9cNlCS ؓ|P({-4$u6{l9H$Җ-[HLLDyyyu;>ݻw۶mrEEE4î_VZuʕ|ӧ322֬YC& O?ϹӧO_>g|Ν;gϞe0%%%vvvAAA !^WW`mmzjJrrfkjjV\YUU/p8ŋ 脆%K԰XSN!ݻgϞÇxӧOFFFAAAÇo۶Ǐ#GBx0'N ݺuKMM qppXboVRRfW^"G8_ߺu+Bɓ'}ٽ{wSyh*{ɔS2engg''u yuuu;w޽; P($<+#(i7+h`Lk øYZZz}PǸWٴiӹs}zѢE\.ϯO>...sεqqqqtt GtP(BQQQÆ C߿&**jРA7ntvvVWW߿-[z1~BMMͦccc#EGGK.蘙]v 4GGGIŗɓ $S橩rR˗'OgϞ+VHT@{@"x<F#t3Aa# l@qH#jjjjjjJJJnܸaee5k,qٳgϛ7O>X Chӧ3FSSSPxYB}vPP6/þlb03f̈JOO˫|ŋ3gμ~~;nݺ"*#x!7(??-..F="00000hɛ7oFVVV:88 $z"H֭S\8VVV #33sΊɓFccc(..ڔŠ_CC"+<ȷJ*""(++)/*DBOh |Sw}'&&_͛ګW>x Ñ滑 ---&&{8鲲2+++"LqqqMMMRRRaa… .\BBB:$K"cOBEEEzzz-G___|ܻwO!JB>}sJKKL|ךB~1ȩdޫW/ERH/f:hobҽ;% !&-= ,i_UUU]]]ׯBGUUB_|H'VLMMvd2Mv]//f?y|>Ν;F޽{DDΟ??))ѣG8Xccy*++7oތDѼlll(UN<_:uj+SFFFii)޷oB_~e777G`ř 0/!!{OA]rqǎʝ .y[ҥK߾}K 5=ׂ@BPTkؓ&: wY_mHiZ_˨QAii)NB{ŊNxm„ ˖-C:ujݺuaaaчҥիO8kllb:x=z8pg4iRPPvZxSg8ŭ[!=֖XbժUk:deehѢ=z쐐=z<hٲeuuuYYYsNccTTTߺu+F{kxx8ի˗h3fϦf}}7o\xqĉCCC9ΩS>w=y>}ս{.<<|Ϟ=[r%F+,,tuu x!F \v@ ?>|@srrw^/zyy<ܹsȐ!M塩s-SMɜ`I]NB{500:t(NRuuuNNNϟAq~'M+7on!(B!BP| " tttttt555L )00P |r\n?,X`ԩPTTTbUSSk]$N#_|k.HqGO ﯣ?P$4';'|81Bh(lhƽB(666ֲl'''/KAAAUUUϞ=t:555IUWWoVS[[Kx/Dq\IL&^4p8 k򊈈#H^.awcBG !*ͨ1cKBݻ>___뵗^t= **;Nx&#+'n MMq7le֯m*G{\L]M %D"aϧ_ssg*w" Y!M/ݎTSUurtPa\yI~Yx<>CZkѱq׆0LCCfϜѿo¢59 B?|dؤfz_Kx6IS>~d2GqbbWVvv>Ϝe{j7Y7H2ٳgϞ T*a*.%Atpg5wJZS utLM{2\|OeS&",{zb:=v손`Шd203BÆ:^Dܹ*+/wuYW/\D֬Fۧ`&Jƈ%wt4 >T}a%-.Qm]Lt B]~m***uuP`ONH{ j4} TaukV-_d2ARw&ORb58E߉v]P;7D[07@CI Lmwg[$N>rrA<=}.mDҸ_Gc $ /AI?~Alx#<ܾ9?`v(]|N}}}XI&$&9ILNF V BQZV{q4䔔ظ 055UR$rGG;DJ%|>C\=jſ/gfe[[YZY|LRxfp,Bsl4G6ތiSO9`0שӾ>>,ss.]2d =ܳ!VSU0G.7$JbUB%Hm!Cozyz\w, ^l9Bg "pgnݾ>#\%r2#7n\qqe3MvV{,11qK.urr,?{LWrssgΜxdBn'o |mm盛9rܸq/^&ۮQWL'> ;GP's* _HAIk? ~̙K`+lm)ėnc{ J,i7 g+O>~9s;w={`1 P|||xxz]]]CCիBׯYrݽ{~xbPP6dɒuԩ{ٳfᦦ/^铑QPP%B۶mcyyBȑ#fffǟ8qN744hhhw !RSSbŊ~f^9G4ͨT* !ܶmۦMbcc"##srrTUUB۷o/,,D͝;wǎgMMNfffjjaJKKOb\\\7n8tP__ߟyȐ!x{.,##Ӌ-r~~~}􉌌tqq;wcxx8BN#LMMA8p 888**jذaDEE9::lܸY]]}[lQSSѣ 555K$,wy% 3 oEþlb03f̈JOO˫#R r;k;wFս{x?TQQu֭[i4ڃ\]]W^-_F̘18MCCc͚5o޼xĉ#۷s8p_:ݻwOuuu޽ hk׮% pd>OR~Z/UVVf;::`;ZPrAL&78h>55^^^uuu$ {r8]]f#p_|իWz@A=j ? c?qĉ;7wnbRN: bbo$!Ҩ-M㩫ϛ3!Ç޸y񺹸r]YY`o?zY7ѻܼF.wX/kk&LYBI IٳgϞ=A|Y*Myi7\JPH`2Y|r\4S'yO ;{+iBFjhhH j4fLB9g̙s^ڥ i+Jʴ~'y>H;`@1TT))%e銕cǮY(MfBhVJORwGH$#aQe/,,8uVo o(c, Av?؉0y!Fx;.xfu-MJЖ.n=Ky:}ݰvÆMN,q;5gOѱqX_:e,{g)$'Tf6֊Bٲq(qa5mWu|lllܰ'7YVM&Fb)Ɋ"c 3i@B }YKЧ]uԊeKZkѱq׆0LCC#u@Hظ7ӧLFikk/^0en^UU˾_W߻uéd)Я(J˗eerr2G^}OM0k֛CG ݺ!w\7BRU]u&?6xۓlݼiؙ3A!W/]040@=4}El}J'a<]ä)?~d2#Gd1sMfr:wvws]x|-BLdV%aWvFIҨ&]۾-nٳB 8q]CS^Fƹ ojOZ~A{G1e颅K73O=f646wgПNDSE0T t116](r?C՚u6e$$9PNNt2sB=ɰ7o A}Zmnݮ}QWg̕-Bɰ/u_PXۥP(|ciG&n x؇JiDT*N!@{khx@+>UAP-V=fTUU(W@L&sD_`⥙ٓ& {X֬?Kgϟ=Ώv:TB}lm Fi͂L!#anLM=,Y]]XMNKd E"24 ltP(p5Jq%6( g{*Gk+˜9EEĝ¢שּׂZ{JĊzًkVXdwO 񧽬޼ ƉSOǎ謫jٳ'L~DvRb!N=gFC]}"o1LPRJ^vo:::?|hllc9՗._A546~Ͽ{/J$55555Ӧ:s` ?3+S}}|X!7s.8ry`]JyiӮ&G;E"q\. ,:u+Ҳ2cc«BH$WTI|OŚLm-(@(dٝttlxlvӧ$LfoP$4';'|81Bh(BIx<aNNNډl&IW9DG"(??_GGGGGG[[[SSdPcihhhhhHj$nN:)=9*jդC! vyyzv;%-ħ+Y)B!;W VP(*;x|CD"@nܼ[H$w/lߥ/W^U0+@I^Ėc= $j?~tRyڵ+44tŊIII͛7mۦh1ou|{gڵ_aRn~%Oܼy޾}۫WPׯ_ڹsW(vsS$$$,_dܹ{ٽ{+BCCڞsm=]NyT߿߯_իWxÔ4.4.! :xs8998ph!!!ׯ3f#q͚5KѾ}`'Ol[EQϟu6WURF/+ =<<٣ }I{_# 3f4888߿ӧO[zupp}.\v(TG%)o{Kh5" %DR% "QI b&C ׋4664h#9:rÇ 9Q~UX_UI3/JO"&M }C->NW|9VG =>1+y(+)I&}||֮]{I+I?_OOoKu]Mku^L⊙M{{{|(0^9==bػwo])--U$ggSS|]PTb:`cax]`–-[̰`Ayzz"ܹ`0:wzՇ>|@P^~]TT@R={VTT-Çѵ߿r...8PZZׯ>ljت*##XTTTKj7ox{H$}}}Pzz H$6#©$'''&&盛䜜UUըfx-z]"ib!޽{MBX)R}i*Nu*]嵵jjjoKIeJRUYH(]ْ{^^^dddAA-(]eeIqqݻw+**pN #S_G ®] y"ٶ!bccMLLmmm;ׯ544TUU?~G.Z|={p~)&&fԩ\.wT*:p]pavv6J|BT*̙3˖-;v'6mڄht:]CCo!֭[g___5s̆ rÇxyy9rŋe(K'-[_|K&-CiHVWt~d)Nee˚ZӖJ&TZZwK!S;NWQQ߽֕{g&Lp3gHBf_&џ>}7n\dd-[JBBFEƜ9snj3b H$aBaHHȁ/] 1KGʬyQDD,X`ff'WؖOwGtvxsNQOZXW!,d h@8$ D8O+# dNyyyqq<<}~Ǫ*CCÀR===MM#FرC]vmذA]]rРA[I$ܹsoߞ늊 55e˖I'NH$*jllܳgaÆUWW2ז]vussqM]]=44ѣIII={ҥK.] ԭ[7[qqq ƍ1tm߾},#G$Ɏ 8|]fҹTVVzxx&-CiH(={&3?q6U5ڻwdJ-%Jf%2#3EJBwcccsss}}A1Leƍ^^^d2>..Nf)ô2߿#F[bٳgSRRd&!.ϟ+mO7n۷gϞM";l>}6mڔ9r%bV_K|$䣠l+EA=<<|}}Ү\'WVײmw_d91SG|)qS)PJB"BJbeff۷#44Ν;/^rd2YGGƍ\.wΜ9&&&t2}?}||233KKK޽;o޼W^1L!Ԓ}uuuF'O8::JP|C|cc#}]NҹMZGNɏxM)͖AmmmeպĥJkɓ'rR..ErhޕXr+?L[l]x<&IPשٶAPV\55`? oi*V|RPX,Hի}*omtJ{S͵u`S,?fM"ˉ@A%pt?Ճ `/H ª(룃ԩB(55!ta>wD|waaaѫWDbQOOϬ,bְM0!990ݼyө;w1cϟ=== l6s ?HANYYsVVvS߽{'񖯯/˸81\^RQQ)**׏P(cǎ%,믿ڶmD!v,HO|ZZZ=zq|||.]CѰ5lhYYYeee&L`2 رcLLL4448vXVVVcc!CB>~LYmbZBl޼9##o5'UVGNˊFZZZ*Xg=--mΝUUUʪuttjjjv --Ϧmto۶mٲezzzYJ}bX:=zf{xxP(M`x< BzUUUB8|P(჉IEE;Baaa Jp8***jjjb+`ƍW.++355k$JJJpP~%,((066&7!66vĈJTdK+8C3| BMk*4e nEՓRFFT_Nb1_gT(Kŋ>}d \ bbbN:%U;qQ&")?_r7e7sxݐYfxꕦ&FmpG*Gg9 f# IDATB077WWWWWWWGGGKKKSSda@&\JBt֍@"_Yd-t8rOAUjSK5UoY([eL)kDlD155mD*eԩ^Aݏ?.Kt_ՏR6MM#)ü)]]ūeE7)kCU#<*C*@3ڵk88ۙ3gBBB)9hiGFF۷O[[fٳßppIfEGGiӦ؞4XW ò5+nFZ8t:=<<'B!c)7"pRAו#3 6'h~}spڱMs~&%9nCC\䳹8LY[KbQ}QӦ?WbjbsԈFFJWζч']WȠϿpܼ̈́| Ν%oڽEVfLk\~Ä́ DkIP 섿/:RNlFXh$/^OԲ _ :w/|{ ttt~6u[7Y]U]`P(:sP(s]})!QFBhǮunҹڕ+zzyF޳jn~ѱڸa}@ŕ 6Xs䰓co߽?uh~H@n-)-ٴuBul I),V ]?dH7o>A7n\[[~Ecuuu:J![ _.**Ÿ\R\\<}b>}zUŠAFD}6+7n\˗)K3*z$&& M6fm@k1Ұבƕ% Nv<BȭGI!w}]$ޞ3'&%kVn^^7wOBsg$/fzuq]ϮkcgYEEŵGw%GX ^xB(0 M;@_ߧǏ=cF(A-_((0!4m?vTBK!~@鰐!N;`oaEeE.]*-+@_g'bO ¥  ]]UUTVYCp0 !7WeGOHþf@TTٳgѣG"V( ŢB:ᛮ/PZeJj&''ݻw_Ko\### 2|֬- ɖhrt:] vډc(!D⦤ e-Ec07cU'3gCQ۷oBj?X[>,[Ӄ9lUUU!==ݬWÝMLL|cWe5I%-|d!_@Uv6B¢Aul4 !~X #чTlܹ}׮c11ZZv6ڎ]+BFM$##bq\MMM==L{{{mmwvܹHPPRRbmm/޿իWVVVnnnt:۷>477wwweNNJMLLrm۶޽TQ+Qb?b322RRR <<TG }:tMKKRƊgIg5 7nP*dK/0NurF<9|g}hFFx(Վ𡡃z ϟ:c; BYp==܏:49%U;#!$iT! >~cF 9vT؊% cxmDEN)*.81eOoDsTÍ7222{i&vٳg}6888::zժUǏ/ vƍ}!V^p~Gu阘*ڧNtTQbŐ,,Qb=DL,J=ydTTԽ{ {'OSLqrr ]zkEv}444l6J%):bHNγv:tP߾}555oܸ!kI2tKٍ;fKўF۵k]e]QRBHEEEUUihhH6߬`۷o:u꯿kibHj@jooUTɖh֚u44ڷ~_P@^/(~Cv Bٳ->w̐O,N:Xu #Zb#Ia} |98q+y7]PN"<|6B` !5`Sq?_ɴ?.\x⸱˟BZhW2~,Ǐ={V^^d2gϞ秮/ݻΝ;˗/|ߟBL:x-Bȯw'Lfowwv9{mQ%'a r^𰳵QDtmmlN9ڣ{;{7997m00v N+*X㱱j }Qbar')L8qذa...k׮]UUUggx77q9|'!!'Q0SIQ&L>|X1X3jkkKV|9rСǏ߻w/''ӧO=J4|VV.P(;vqFEEMMMrcc>KjZ1N7oر#7FV|YnLYӧO66gggw[*H\\KJ-YQ<}Y}}}?~ܹsg*5֠,Jbb\b"MUVQrkF'?6Ho/? |jJjZ}P;gEs?~{>s.*|h@PqcF656>{¹ --3* Zj[F:%x{wwM%iI1b2--CGMJSGOs/Y2yk=/YD6pBLfA3MP Yx9~Xk׮M2ӧb jkkq<_}tQ>}qIIIG::: ޼yPI)5#D!;>۬ &tС]vrtHׯ QD$7nP(R)))<WU3_HCniTwww<1>...]tiSQQ{uGPjj:J7֒t5^ шWGI۶ՕC[[[ȯBII", W#tlv4䬬,:ҐL ;::"ڷoi&:naaѱcnݺ믚&&&ɑYYY_޷o߫WLLL޽{wW^{xxD! vTQő/^044͛]veee뗕ƪ]~Jb[K,uttjjjv ---___\,--cǎM4IR÷nݲ)(((..޶m۲e%iii2eJdd֭[٥K۷kkkQ(1R (< DJv6kkݻwq KK3fR3m۶566޻w/d0:t\NWZ6 s̪*ɀm۶!&??Թ,455"펎ȠSTڼysFF/В)--UQQhb\UT*FTYY`0TUUUUUt:Nhplq\p1mڴ0hYy"223KICB\.DNj@>GEEPMMMWW!qƊիWKBĄ4ŅB~ATd1d eCk0 G\bccG!+@ (..611[)!*ŋO>]d >… 111NjT;܈&&&<OOOOAuL9M(wO@PRRbdd$<QYl[\RAn֡'Z&t:;! I+d2jjj4P1ЪCt0Ik xm[1B\.1 ы6 ԔETd1d e?4bX.|>_~\ LMM ԩt:CjG6"TuL9Bz!Aș T|D4ZTCU꺌\lPuo) pܯy5(\.䐀=iڵk?xgΜ (RkGFF۷O[[fٳ:[k{kVo! /-B!Jś*? hAAAdp9@qut!t:=<<:7֬*kq* 4@d<0-L )4 ^#M+{/0%dq0Ҁre#v|lff{HSBìaF VG>r  6B4|c0Ҁo gJmi\.| oBB3BG:QCo4{<7Gu:@fbG*[FZxxlPTr&xBnQAP`|;6pP4xIXG0!BGlakĠRA8vB%*Z^C$k/,dd9/h4 iI̤4Ք;ʞӦ?ğtS^F022lL|~7wϡ!CV.]e.]OĹS䭢]޽r֌i}/y;Ǐ}hJ4XLmnq;v'&[WW\'151YdqO/Og7m~F,_=o\.w_O{g߽5737p14M ts ,y!g?7zZL횔RVVXZX)iS IDAT㟒fyf488)[=~{(#P߈u޿6bաG/Z|Tԙlm#JR?yRRZݼmgN8KjSR t{ ǖeee?͚9ϞOLZd؃;vE?xhI=ʊܽ'_֮w_|9,4korr~ϝ=I),V ]?dBMM>?d">")//V j >ƿA#M__!TZZVXz\ŋB&Oz~{յu欢ڣ;~ߧǏ=cRZ0/\(ncGB;{R(.]!ꪪjͺ wߌO@y*qx \.JU ! ׋JtD# !5BhCbby^~bNu;=Æ ^fg|'ǮMQGo޾uENʬWÝϱ& p8XioCe_>'b#dOvҴvU%ϱ!/cn4@Zv;!Եsg<gmeE޵oۆB,]1'O=s,&vo}zz!|AWى_]mSUUىvG =7oƍ8n/[hJ?LfN /}$jJY6󵳵C1a!?'GGS"V$>|!]X>lx[SS!#`OvAJC^I{!ԥNhyB䅒O|%p2cc*ByFzՀFq0ϗ:Dh'*QUUW:}!Į{8P}&&id>tBxq<:xw]PG[ԙ3=qfK cǐS $%-xlCm_TX<$( #h}vښf``ŋ x F;wܨQΝ믿YO 2$''-==]jWW j hZ&֑4վ#|Bt:h@PqcF˗iii:rth l])tŽ:\H!kW}C]ooE'bX,V۶mvn _3\MIM 2XHC͛3 .\03{̨wӜKL#ګgKijR¥˫o@3!͘6UC]]hl6 V^fD3TRR}ZYYeff=x@]޽{[z{ǏAHLNS"p>\.p86mZXX:%; ²#CCI +Ph|>_3XS(DlmlDo|^xHF^niwB~d#RT@rkjjJJJ<<|0Tk}}}'''|iҤI֒SNζZ&y+Wܹs?|ŋh4GXZHHȦM@70<&@EݻwGoߞXTTTSS#y}\.wőhZ\,Z5IBܹؓԩSܹO2B2Y^~M[DDDee%BN0cǎ`42 ޜDK.x4uoG 4 Bhxa9Up{!\;Qm3<)eOZÀF*GMDT**Mqu@E'MϯIۯCԎm37qWVϿpܼ̈́| Ν%oڽEVfL,kJ 礑;p8L&WztqX4w7lݽo5y̩3g 2^zuɊU6m/y<J2CYt:]tډWu}_F C:ǫU0=tܻ7kA WSSU__=\\mR?# =iW@hx扃|G=}9z$z6jL|n嚵|{ vK~z9_گw˖HI)eeF '(K 55Ҳ2䎇Bx;{R(.]!ꪪjͺ wߌO@y*%wHCDuX4+4OAF!!_&DVba1'OݺܿaLMMBo^#'b#dOvҴvUYe ;Bs_x2LR>4r7bUUU]466\pbN:z"XL6VY@?k++)md>TUUx6vvQEB~uvr?44ĉfff...-BӓzJ&J~z@Ov5wBxw5-[ "vhɪ;wRRRjkk;u4h }ҥ3g><%%pԨQ7o\bEYYف CBBB)))np8^^^~~~'BZ,7o~𡑑BhƍG!gYYYZZ+YYY...>|x捗f~~ׯRRRJKKT+++<<< T !BByyy~Ӭ,&d2eb233i4[eeÇmmm߼y׾}{}}}R`޾}իݻ~:???88w&AtЈrWVmmm۶msrr?zZ>bgAacSx! ɻQQQo޼yyEmذ!11dfff߿!zh„ .ĒeU!իW>^UUǧuō4 υ"c)H;}СC[' $Ah46MLL[#Giii[lٽ{5BhŊfff6lODpp0B}iii.]nnnx1[||޽{wacc9s̙3y\ &M:r䈗P(?~|TTO?hѢ_rBXZZ1bĈk֬qwwm1c8p!4{;w\RR,!m6\z5..M6QV7oLOO)..&bƌ3fXd7 qpp K.oѣ(. d};֔LWPeee\\˵# h-x< 8o t:K.<(,,trr;hРT%'':wLJp8R3JOO^EEBʪ\yQQ>TWW{yy!(O?}?}6//o޽{_$Aӧ7۷o=ztMMKhh"O-X@GG4\ :"cS \(4fEEرc233aKZFP(h<Lf̙3'O|^ >|8^gHN!rQu,+==v;Vy8p`K֤{uuuBl6/--dVUUq\PbihhO?] ''G(iFKK ɓ'Qy,-- *D),))IKK}͛KJJ&M]: ߿o߾>>>o߾t [ #:lvYf!RRRݧMֳgϻwށV46T*W^14'7ĉv=qÆ GP(IIIyPSVV֓'Olbbry܎\.w„ u i4663f̬Yx<BСC Bxyy/B?9r|Q:::5k\v !d``tyWWWoo;v4TٸGm\5gϞgMM̀???Q~]xqڴiO~8r短߿?}I&.Z(##[n[n|}>}]PPпmm-[dffΛ7F988L8))) 5rk׮1 }}cǎmu'Np8ϟ7oBh111t:}ժU/_NNNӋ~ITUUϞ= VTT߼ySMMĉ$ Aq8''c.]ux]}}}v?NJرc/񣶶68|0.[XXXJJJee%BZre)ۻ_~>444$!""[nz'''W@W^ihhfA(+?i@+6ҨT*yt@ #MB]]]uixzu( xyՉkNmmmmm-O:P"<N2%p8L&)BQQQb0䑕͚cTTԣG"##tz}}ӧOG0?|m`Gvv^E.B)4P1J!,!AB( hE1+$Qq MɔjD)hYږj4d i 0ݔ9x;vd0>}b0w9wܩS` sp4u#z 3g5ݻw/))\p!>-!!_l 3g_ IDAT3MHZ=xT|msʕofggwUY'4% HZ=xNFFԁ)|*x&4Sr: F 2j9>}ny-=[kz4pPJ-w~oM0g|YpunץJ?<**+q =ܢ_9oawz\gC:z4b2l!kki+J  HS :>޽#FcÆ ?BO׮],y游83jP Bq㆓ӂ Zoc38ȷoJ_5,VOo/U[}B><!t?zjZZuuuRF9rɱE qnN+,8 H7 @ $&'4q7B I~s~MMM}"X%%7صѣBB?q=Ds8Lu CGe˖m޼yҥeee˗/_fɓ'BSNׯ̨A}z ,g*z4E1v|#2-C}PiYY;m\qu^͜6-(0Cv&Op`^A?(Khv99v524Ts3^}PTSvӵ~eׯ_Jwv.ӧzKK %fh9>Ht:pqqU$^QaƎ`F'yYP"6+aS &ٯ/O[U#9q}z!VI-VI)BH_OB YYVɩCCtz%mYdIdYsO<|6j&$% [UUKSS,\`ei`;h7Bn).KE>/h@PeMͽEYXXxxx ޾}CssswwwPFFrb6(qff̙3mmme &$$X[[IV...յ]vz͍Nez䉉ׯ322 }||X^ݻwTjvvvFF]JJ6$ͧgdQ܊RSSMMML#Y){7a}MOAJj}b8D~AA\v=f<40 9&lQa+,ؿԌJS,i}\nrJN:8v)!9ÇUUAA?iK.# DS^rMY|½-.]Ⱥչsgw9JW5((h<Uk ..F^^^^yN<# 111u71BKTzFiݹs} [f aZ%˺'` ϤoHԩ@ HOOE獄.^:}lCc&O``fuu#\)nXf3c8wppSSBjcPDKlHs:*07[1={ڱe~|6oQ# XwR)1o޻yDhODyyyTTϿyٳSRR8N?x055xO₠o֭ qFRRH$ڍ+D!Ďh8i"bE77662޿G+Zg2e@=fSK$0DjⳄB n Ď`0|7Z% fl~ ##HL&sk_U^^n{DR )6RAU`og(.VӯgoՉD"-<#H8KR4DʵW @ 7n\=MѣR֤{`STTx5U `߾}psrDDѣ_<dРA"\VPPP^^W\3f aJX,b)&==_UZՍ1bJiJRK#66vԩZ(,}b(=f3 @mU^$JH$FM@|w.):&l&$F//DT*ymØL&|] B|Z-|u=U)-/EN@"⺺:N&O8y󦺺:55ajjZYY .[UU322(ʫW***fݻ{` C1 ֹsgMx{{wiΝ %!!VMqܿJߺuD"M4c۶m,+!!URJ:,,}\!CT#=zߟtBbz꥔q?s挝ccc[n 0@5˚lΝ PzVͦj1 SM˗v޽l6a$ׯuW®]9P( x‹'F@N4JRT'LƎ9jff~HsN<EIOO%XrZx6_ך2L&D  DFFFt:6?L&LZ.[ZZj~>h4D"gDS%%%O)%*߾}kffP[[kjj 7/Pi" oPL{uפ&Qt׃D ό,& 4RGr&]ڱi Dm&4ƣ lF 0Hk/&X9< k+l@ D!Jᷠ G60 n5ȕQp$VbDl8F madRI}LV5NyFȢmBļz䍐E#M4.kxQX )ZIu e5`G{nϙkG[[)Zv=EBAHtYWx.kJw(Z 0>iW+/Zw0"Z>.&CK/=RI6^Gb+ɠS8{Foqtt?_WVV]6f̘p+++?۷acc,={Z[[kVZMCuiʕ .tͭꓨMU###QCF D@"Zb_x?k,[[VΒ9 hϪ2jט2&L2NQJQJQ}rAǕrj[)^. 2߽.k<ˆ tfj $ .SV\-Rق 0J2 zCRMLL6lPTT4r>}9rp~</ GGGK$oرcX{H$0`!C`䅅.]*--eÆ ѣ ++ի ,HKKĉ1 ;|aaa޽}}}{];wnԨQ'N֭R. ,4ׯ_uлw &@s0;; ..D" 042ܷo_@3GGGggg@ # u#;;Lggg9`D"M8̙3/&Ʉ#!«J(((033z׽ pz`0ׯ_tԉeddd~z% 77733#;;p|D@  Hԩ@ HOOE+g]ZفَNžc[lxk/}ave)^3 ؞=8[?jmwEUZo*D÷HA'5ccy(Zmja(6\N&FAݬ[nٲe 7陛w1!!K.666,޽{uuuǏt钿ybbbnݺEP׬Yrݻ{C FZZѣG)J׮]w~%?Ç=z~~~{Yhѣ=zdiik3Ҕ&ѭ[7@|3g믿^rŋlR$=R+ICCYBBBx .|葧gaa˗>|TEݹsIII| r <od2ѣ7n0a3Jx^^^@ bH! #((߸qWc-׊+ WKZWiFR4NJ~6QŞ>>GJ@ҥիWԊ+8"''СCX[[`l6{ݺuQQQ555 пK~0 366ׯL&kl3gܵkϟ5kVFUÇ{yy=|P \NPD fy{{1͛+y;ṇ[F hFJ5A~+Kd_ofi SI?oeJCKM:X*O7[ H\ xx>vg*:Z*,YA"*U?=/"<ϯSj<\q8`ڟ뤪1,L&OI$T*E<D`VVVpX1PXRR ""ׯ|i0 s {nmm3h4ZCCCaa!aV5OTbEDDۗ4e0]tx/]^J,8NQQ`ӦM}Yp?sܼ\ǩBc[H4IdӧOꫯ&N_[hQ]]݂ |}}RPP!%G2lԩ&LQ@ /V8"K:2d߿_*J$X63=O(6*}P]'x7|0DRy˚ȝ :V>b1 6'N /^CdҤINڵk믿^xٳي+P>22rٲeFrqq)** b0SL}5k|IRpwqqٰaC^`bHC &}辎H8O6@K.%4H$3w2wTe0־Ӓ i X,T1hrbI$otEo0@ ;ߴG%JLJd zxJ$I}}=^;D$)H"B6ݜMD$D$h4##(J8~ ؘ2eʔ/^"\h"JVV$HxTǑ\,r\.l`0t:J%##>iL4 PL&=aU!H `*!Yh2L&nx(~L&\kMD$fl6҅*gggxJv҅F Bh=z(<<\q@ շ<B8f(4~bAA ZX`)SN:V\I,7::$> %}@|UUU~Aa}CFU:4ꌅT*j?[@ 빹YYYݻwWZC@ t*>*3^Zeƫ.\uӐ< GGG?Ȇ@ *2L*egAaҝBd!_4 VЙ4@ DK8\!{_BRxa]HEIOOo~ xG@ ޻HP\OS]6hBTq\~_G@ hΐ]\' z q ?/r@ - qA N4'l\F6T*EA @@TqLqI i 6H$ @ >dL&#>fwGħ2@ h(BU5DJnĚ2L[kE.s.zF޽{q,^|YWWk6V.Ϧb iI9OE#Hd2Y } iON3R~9Aq@Sߝ4vs޾}{W5 fϞ&Z"Ϟ=X|m&Nػw-[lذ᫯Z|9 ~ݻwO6RNˡEZjޅ_r&""s?O>ӹs7ե̙3oILL$$$8ˊ٣G+V(]+qN:m߾]8qťqɒ%_}.s[hd2C;GFVa @;m={Z[[kVZCuiʕ .tͭ~c zذas =&&F&ܹظ%v]vYf֭۴iӹsjjjdڵ[n4hٳGV6Aڵ&ܤҖ5Joƌ3c O:uo޼Yr%֭[HH2dH޽W޺uرc g޼y0k%Ǝ;uT2dȐٳggee͜9cǎ)ַ?Q(*7^GΤ! 'DԔx^ĻT*EIm7nt911q=z ~nݺ$s̹sΥK.B8p@ǐ999o޼Qcdd}~~9a&Lh,3g 12hܢ"OСÈ#4FӚhRګca^ʺ7ǭQͬ"H~~~8߼y300@&y<ŋ c////((Hp+ZdddHbeddh)FZ' {]A!6-hVJjǓ=lDRi/^oYlyNnZ֎Ͷ9mp_ߏ"Ґ?yn=зo_D̈w}yT onn޷o߷o޿j$ yqAA/RnnnFFFAAALLLϞ=۵kY4ԃz*//_f͆ t:oUA,D2___د*%CըT=PBUUG*)))}yyy8޵kW&VJɓL{{}T K{c"һmhZcqH$ڥ]/_ԻBSӧM ȑ#/\޽cXƪuIwrss:w _E ,+//w흳n X HH$ՙ4+߯Xn$={@~Eq_٣D"4e&oll\w"[_”4_~?g,Dff&/??h΅STDd2 e-k]v0_~r^^^{UL&?~|Ϟ="h޼yjVաjT]( cddZꑊ\.>s SLo=<<\k/`ƍѓ'ODU[ƢIԥwW4WP]FsmHHɓ'b"#_,?E"H$u׬b1|+kB&UVV{(3]mrr.@ަM`savv'Orlll/]={TWWw۷]b/CL˗/=\IESSS ƢEBX[[[[[{xx888អGGG]+ Âl٢߼y d0ƍW\5j㞞$1c888oGGGsssBYօ9s椧OL&s ,P/ӧOjjڤUuPTRjUG*ݻw#,--g͚y<:tmۈe4U+cǎ-_02lcc)+E0zKiʯšZkWzcǎuzxx4Y9R,߾}QѣG_pS"Bm={߿?BYdӧu ڵkWcWIK7h rΝ;uuLFP8۷Lfǎ?VRwرkVgbs@L&Դ%%= ͂VG9wjd99~#}}mޤQ.})¥KomG itZJIM۾sWzFT*uqaڮnnJشe[eogݺtmP۞/u!dùcnbWYY5eXZP* Bqcc7ܺt ãhq4v޻w/ 77wɒ%7oeb )((8tСC`<԰֭ihh0cc~dFŘgΜyԩ9\Mh"((h<QiNNN ϸ8Fxyyq0QAɓ'srrBz$zΝ+f=~Y֎P(0eŊ+VHHH---UuMZuQ8IkR7nB022rܹ/^6mMqvvo7//////]jR)X u]44OZCvuWo޽ۥKbHMl5| .o߾{ӧ?@'6b֥KfVb1Q0D"ѣG&Mq˗u2VZ;"X"*YI1@Ww:'g_:dB{.\4;^55\nD5RxTLgXJ 9p g͘2#c?rrsIKB55,XH$/.q8oqrtn_.ϻ~~eK=ھs@PDJjkkcb_O4+](66VSaWʊio,VVVJ`2_h*-I{ќz{ر+VL<9?? **gϞaǫ3j(+++5ŞN={x5t4իWxx8˽pɓ']z(n $!p\յcǎ"hڴi!!! s΅cZЬwjU4U/cMpڝ%I}}W uD("nj$j%QH$222*..階d2>onn>---xB4M"㾺DryQQ\Z'R`=TwT[z4T/X,q\ryIIESսuo,j1SuɯP]RhNH$&&&M=V\\leeEc~d23YOnNoh!L&B.4Xէ_JNK\.r86b NR+<==ۚUґ׾>{t\j8 q'c@7/ uy/_8GюY|@JjӤ˖.Y ^X:vpk%'/tJ;[MMW"`y3l,Z7n6662Ȼnް~_;!&ѱ&魪Z"YYYUV^n@0W^1?v9Lcc: qK- ߰Ncaq*OC @ Z8$ ][t)\I"H$5ΤiG"rڵp8M|K$Ⓑl6seUUmm9׎R[[˯ibX,xMUffii)3i^G\.kkkպF @ BVVFh{}i3Ϥrd‡mK[Ϧ&&&p(d28;BhU璪Ztu 2µ5q @ ZT!"r bA/">Ufh@ fq)a # BŭHC >ݻ#~5T0ZkZ6T(mJɈO>(av$ ~ׁ*RX,FFI8q2 \dgvss<""s?ܹxb'1]ܹѣNJ+|rNo߮wZkrݻ}~I}hw \@%5=而4H`P:@ Z'Nr1112oΝ}1c̘1C𾾾۷oʚ5k֬Y o|||͛o*^+1vةS6'`GGǦDȩK(dذasA͡K E6R>I@xWhQ([hpCib@(999o޼iD1 0aBKodd$tH|:9p0jUenf'OOOM2kIQN텢-yA͡MKJ{mԴϲA}r*~ <==a2L*Bwwwnݺ!#Z>KR{[{x]PTpj XE"P(CE|tt;w*++kǏ$}ILL@ "g}͛7UQqDGG'&&jBZZܹs1 p8bTI씔<ZTT@&>}ZTTpR7?~LSɩ^*--%D"ͽuVAA)˥hjUsE^^^TTP(|H$4hE,Hl2c ''뤨(**ٳ2???k%߿/좣<OqJ4f!;;Yrss 9 Z)  ȈdǕgΜq<::zʔ)ٳg#00pƍ7oDFF&''x{{ܹS5N###**HL&l檪q<44?Yx"<-,BBBN<9|pwq7_'d2>{lS*))3f̭[6mD$Tj5339rd~RSPtɛ7o^xHҪl*R^6~ ѤՒR.TBǏ߳gH$7o^ffZTu{UFFFJ魨RMNG%נjOK7߃2Lqk1I;op 4 D >.NNN~捯/k>3f ~S;G~ر˗cF&mll4=Е+WF㸧gllZaT\vիW>>>oٲES\\\=<<T޽@`ii9k,>lСCmd2%Iee%7n<<55`,ZH5NGGGsssV:t2d 㣽,wرn:cccWWW:#o={߿?BYdӧՖg9h5(R訓j???łEZASEj~hV&$tɠR/kjj铚VU`kRrz+J~^)ZinET*:Qhs>㌌4ħ=AӔd*R azJܹӾ}{w۷Uqvv5 hzV)!'''Du GO,¸q]& ###Ν{EDB|ɓϞ=;|'Oΐ'Ox}JƯI EQݻ]t! zC'zCdð.]v/t{l4U-B5 єYՐhj0cǎ‚ZTuwUJ95JE 5(5Jڋ>rtre2$dv܉y^L8 ^vD\NWٳgptQG eC'B,-MPԉuO{(A{ЯkJVm_Szm { Bѻ*&̚Ժ%9JлA  ur\\ħ;LB3NX'$b-66V#F?\"5=j xqcc#3""B󃊱q88b~O:u۶m;vtssLHH/**剉[n}ٴiKKKS*X,1=NP#Fz_VVF^ 3HKVQQ/SRRƎ4[bkYU'׽Vn7kJtoZ/u[KR+@TTN45&t'A}P ؠ֨|3н3=8nY?ۻcd2\.DZx}EEEw^v_|011Q*MCyrS۷XI'Um4ӜׯEܻw/##C1O!}-ݗ *qÇzO>jkUu2y/BmUJBUJN6.SCUM֭[Tj+бAyyyjd`Ŗ<)|0T* qWjh0TjddT\\LuVr۷fff ?%liiY]]-HLLL>LL&+--T^-.:]Zy4=ZH$R@oYMI4n xP EkNs|{R=f0 5\RSDV.-fX,AөT?Fw}ed!>!#w/ah2bqmmmEE2@ -GVVɄg@~PF:!f}@ D!\k.މuL ptҫW/@+wDSnm$wa5m_gtIJ!T*2E(C̮pqtא)喸4*J)'͝Ǻ|;ȉ~gzk޵.u x< JMO`_Gž2t+/^ P #vPkףp:o**?y7+MEECEvv&>.*סYY|>_QAa?MWjbGho#dr8E OLw~򥥥)o+pJJKυw;O@$/`ELL<&Md9ѱko4jl!{=vEYY9 Cv&dI2hQ 4Fk/̌4Su_lӧLY?vvܘ1/ՉBp8<NC,k@+`Gc]'y$ݹг,྽JJׯ_655B#*DiT*C @ 2ٺOKAU6D-ZS\Sw3ySB #l֦ [w6tۄ4|>/`>l;M_PMJ&ܾdV{NJ,E340PPPxd?x</b]ݫW޽de!X:xYuq +.<[@OI|~l\<*-#c8˔ Vt52ڳcqM['icؙիںy  w1B>FIS'WW4yC=fxm|>B` fҀ*0IHe+1ܻW/cY3=B1q`|u->1igΝSmm]e3B9>oJ>ԩK999Фd-[ǻ/^dk_R;ubp8kqUUUvvebg?ϟ?|aڵ{nԹs:a>a޿>~Ĭ{hہu[Ą Hed}V\{PgVZVfh`0}ꔰ 3\ǎ>e*sȡGφ1*&];uԯo_PpG-[cDyy?tؚ~2]6C@GݻJJJ[(''$99YCCcРA>11VTZNNNee%QQQqtt,((XpqRR>)((ݻ7~3vh!ƍ555666=zPEY IDAT[hekk͛]]]x l0CJ~ю3BD^~Ig]Ƕf!TUUy"-)!.2bŲ%o*޸K"JJK< YF]ˬ\.ʄc@aڵ&&&fjnnFQ( .;v޽{ƍ;~ p={6ϟ2e͛7ZHyfNNȑ#݋h=zSVVRO>t͞?'Oʜ;wn=<<6oѣwPx dyCB;9 w5"RQAaСbu1416A)Ŀd{ܺicĥ t:=($̩xvu?B=)z$<{Vh4|5"tn߾233322:pBdذa/^pvv&Ǐ9D"͙3g->x ??ZQQqXkkkmll{!V&e2'O&LAQ"##ǍG&n߾ |~`!\.J>#~x&*((s.\`0ngdnۼBt145rDPpDdk ?q4jүڋ/Yn&&аdǫ~*95 tcIX[;xeIvyyyx5{;ys|dzd* qƍ7vJibbrܹk"H$1>///w@INN!CZ=eMMM++?Cl$!Ԛsݻw8*qV&>`p:!8BH;Ywt#~zջw] 'Դۑ;Xb FГAd2%#N.YаdB۶#'Ne !`ޟ:gH$z;Cc-=zIN#}cH$Ih"w;vݻwg̘JJJpBeeuuuϝ;W^^~9OO'N,ZãԴŻCR544B&L7oޥKibbB&Ϝ9ޭ[k׊jUZZjbbː~ŋ, 4?c'zI˗/f/K8ĵ 7~$3iȣGIS`_kjf*BhQ3|>b5440L;;;X ˵Eg[K+ Ql6[NNիW jjjy>_UU%L8Ns\ɓ'***]x>Bʞ#())QSSSSSSUUe0*** w&_ߏ@t )ftVj)1/vkqL&K@GE72_q\]j P(bW? -i7DBd@TWW557+] I0B94Al'd fҀaWquuo>h/а&ۀ`ҲgJJ>zC;<>wGLc[0Jg|x<>2\`& 8WҘ[OaOHڻJP莸#*4ܹslvsssSSS}}}}}}mmmMMMMM >xL&s8X|^(R(%:1Y,VSSSccc]]FW%ac av 2Q4iНU׀A˃d# V!<qS/p>/7Hknn~MCc#)UUVHwCAKrqwXq#"ҝ;'O<|TSS3zo~+w_f2 m3;w^1GIy3V̧_;G*Ҿߴ9&.˴4Y/K#AAA_Wȷ5H0'--MΝ=-^\o*r57hki ѫF8v h/*NW<{T0@@{/j2q8GӉ3l6hTeeedbJ^8{ƨK%+Y***ĥں֭in~h^\p[[^\`_UD!B>P~;Yy<=iD@I \~/Kƌ,/*ُ9"ׯBV` ܻQa!3nu}zv6.cBwضeMMM.nw^"6 v52>>Z]ciڣ{N FiYG~>&iآh3QQQC !<۷֭۷o.]4444--\޿hggf==ϴTSShhIh4O"@ x5g޽{d:I9|֝ZdžVǏx8Ufg A[H u ਿU!V,[2|Bhvm9}*BHUUu/u`͵uuW&f- ZvU^=ͅfv6b$_Vx܂$ |?77p:^SSs…𨨨ؤxmb_zUSSSWW'eAAAIIIgϞ pttL׭[W&4F Vݻ?`gg{vO2͛ }v6-[ #z퍏ׯ_<>|~Ϟ=sss/ũ8q?8$JbS wDd sLv1 *OoBG51Bv@?! ;$CMMMLXQ.&$6ԉp_\h!]'gΞRWܚpQ!%bxX!Kh˗e&{'oh`XJC0Ntˉmpy&7v޽{ӧOLbbb6mZIʕ+g͚5~Yf1 __߶I1bD׮]%Y`Avvv~Ν[ZZlٲٳG9ݻ¢ 7gҤI;vbr':r}}+֬Y~=rl6FP( rTV_Hjdzuk |Av{; >F0t:L:%Ŵ ױcOZ<>_(..F546`#MpQ>)o!!_AD̈́@0h2Qb&VNp8\yyAB.999--f;88 >=z7nP(K\|a̙\.ڵk .|arrRSSSfff&''766{„ 0///11Ȉ`XXXߺukL&Ӛ! /**T N7444iRNNq&55UAAaРAkY}ZZZ; @&&n-GjKKK544P)u.Z+ Bhٲe6lBɓ@6l100(_T?<k߃։bhxvuu5sP$yiHVwvb?agb,4oނEOL2vYY?gM𑡡pw ;nq\dbb544l˒pU&*ie0&+>L"##ˆ[OJJh'NFEϞ=iaaq9 cǎ9::v޽ 00!diiݧOGT &1!w֭ իWo߾=))`EFFH{8XKK4##W^***G8AkWX,MMMuuuEEEa zzz6իW_NHH͛7M:{򚚚>LIIWZ%DFF ttt455rrrZ =}'5jԳgʢE233"""nܸ!cjjjTT۷o#""(J~ ĭ(Aݻ=zTXl>??Θ1Nϛ7˹{nJJJzzK巓@w8) 'lWf_cS2UUUW{䴌տ{!d!EX={nݴ1:ON 7;{կ˗-Z>q4:"!uTLLÑ#GkFEE]xq֭C uss^Ҷz#F޹sʕ+ϟ?Ǘnݺu??YfܹK9sǯ_~1866G Fqڴi[l f0%n-G jΛ7OXlܹsK,qss1cFRRB?~\ԏ:8D:¥KvW0h%;>y]|˒7zN[YZ>~|:ĉ&NNBMM˗,Vs7| =קw/e%%oyՀϞ?!-hkiwՈH.dV765^|D"yLH"D^Qi,O1ix䫲z7eŎ^ .zjFFj޿zM.]TTT 0vJ2ӧ1!KrSKK !tФIBBB-Z;}Vpiĉ]ΝZ\\\ZZzɓ'O"cW?*|8:xq>ӻ(fuu}}bn e-g|f4ý;}}*mZ.VHk}wܢZzF6IW?D0U2e Bhĉ6l"Hg޼yGݶmUĉ3f Bآpׯ׳gO'''۱J _maI.|~@@B...w;qDxx޽{BQQQ555'Na:88رcƍ޽۳gϮ]ŋ766.\9;;[8IkB[l*‘0MehYh4ڴivܹuVsȑc" C V\I=s̩SN4 ?†e&b555566־K.Ag^u3 ῔QG$Ijhh`2vvvPm(}&WWW<*l2>>$i߾}W\~䉻6?[^^>vX N:߿ESRRV^-Vᠠ ɕs-[()))((477[XXa/_֭[ 󏁁3f555d٦M 0cƌ䚚`06l09s愅h7FGG߹ssׯ_x"^JGPQQ]XXf~W|ŋ,GΝ300#Nם^zUUUbsvXXذalvg͚vڶ^//*\灁GhYBo߾>}zmmmuuȑ#9"'<<988 X,Vv 'OĊ in)p%%%jjjjjj CEEEQQQAAA^^47o߾+a555a8__ߠΝ;x7o***1eXA[nnnQl@ ކ o?+cǎeggh4陛+CF:.\|6-''W[[KTIsPV eee)_U\\,D"x<)5h'' `& !*! vBw aY޽Hl6j`F('U&v)r9aJSj& ~dt:aH <}TGGGtUHYFx)^FtG!?7;:wƍ6x}YBV׭/ϟ;wӧO{--蛮 )5jԼyo6U %i*jQ̎@RRwqqٻwRǯ6(eKѮtP> lɰ}766R(yyyh4_d2;wLR[<}G<\299y֬YǏ5km#FtUr dggoܹ˖-{={d#:K;vLϟ?񧜜zjS %i*-fGDKKD"M:WEn_h?:f~(7Fádax<> ceee8s;rfi4mBry˨QhdNYqӁC,-}[i?;ҕZZZMIy/B fTTVt1_RP7n!'5b577S:$… VVV}ԩSMMMAA+ZSSPVV+Vݻjjjyyyݺu{ennNVXXXPP{ikk˓H}}A;88Xd2o޼Y]]'CwΝ/^TVVjhhhgϞXVVvGGGАD"MZbn).NHH/rNNN~~Ǐ+**t"qAA/B"TUU9zVVӧO\\\mm!kx޽z&%%q8ׯH$---ݻw322JJJ7bjjբPnܸd2 [)oa(u]]] ɸI$Ryyynn {]:jQy&..ZKx.񥥥jjjt: U!MmH b~RBijjjjtuuبhK|-Tj-&|aL&F# )in@|TSS@i4FR1:.!boߖ򖓁A޽&pi^?JJR!ӼJyLQ\oeK֬p?4d Jމ38P455ݿ?44 0`+W3hРj|>00pȐ!N211Yh333oܸqԩE:u9w\KKK'O Ojjj㌌ kk 6q8|~ѢE޷opttE155ԩSo߾8uԩS[KZҨMR/_yfNNȑ#+Z4Grrrt/rss=<<?~e={6nTjhhŋ]]]6n܈/]d֬Y͢ -U)ʅ ;v޽qK)oa(b>}СCl6{O<+vܹؼys\\hY={ rV#BHNNN^^*++&eUHS 7~Z6?͛7'&&Θ1f/X:IFT4 1u&<)Í9|CE%:6^ʻl6#/)-{^\u(| J^8{&%C(Ru[A>k{B\2y7Z7}ͬʕ+گ_?+++VN>}ԩ#Gk׮x֭[-,,RSS &Zz#LMMܹsʕϟKn:p߬Yv܉%9sׯ_WWW'\bccϟ?ȑp___mmmMjjje˖`Zr6󫫫/^,ZfffzzzzzzFFF]\\d}bb"B(::#G$Hsپ}XQ >|Ҏ;Nu欷o+JtY? 1-7v۟<y%! fc;vϙ !>|ԫgOUmZѽ{'Cq{enI3*{ Ν;!T\\\ZZzI/////l<͘566~Tѣqzuuu"=]777OKK=z4BuuuXԩSoݺ:th̙}={1ceRj 9X455mmmz311MMMd:1dȐ"<򖖖 7n^ngbbr)+WQi-SEҔD""p4 b߿E(RV"6ֆ4UZ1ͭ2&%%uC ٲeey|M#V67rho$!d%WTPp$O挩S%6-.vYl IׯMEEEGG'f׷|uNm}-BcOO x^\-;)FNkk-\dbl 7<*1U^=ͅm7l23$^YA Wۣpw|̙x/ s!U$iȑG2dHzzk>*Vx- s$XYY/UUU666۷G=\ tMU 9v+_ʄs婪8--^"PWWԜ8q"8Lcc bWЊ@AAAT` Z?Ϭ"R-Z;v :4666;;fc}h$TgV4ѪPDgSX`J5INӚJz/ˎ'IWIcX: 8ѻ urܿo_|YS&039|i7tș zK{4+:6IS|`G.4aѣ׼ojjfbl5f/s|!+Z/^,+/NVb $++o5̡>0`KDDcAAÇqҨ_~%77_~]UUaǎjϞ=ӧOǗ/^| ggÇ|TTyy9Bh˖-q%( DȬhhhxyyM8Bl^+3ᶈwwwX,gTTTk?> UTT<~x„ l۷gΜ)V1[h%|U4P9"*-b&6!!:!T^^.ݻWRRjEuԪ6>Z-fkMEbJ_6?1cƔVV.MVM#V֤399Y/`mX1!vt\\33&Y҇ ]ǎ`{4'pNO?!t7+~^3Q}=]"cfִ)?ȉ_ y-wϞ=Zd`0\~5"dvb M!ovo~+PlFMd"x/s|IWωH,n<]__/!|1v{;w677!F|Ǐ?|޽ ᄅٳ')))((ƍ=z՝1c˓SRR̙sܹD99gee]|9--իIIIք+fȑ7n_xٳSNlڴi׮]L&s Cl8?Dھ};No-Ūmmm-fy#jllիBw޹hkk|Z__G1b DJII9rHAAAmmcBTѪPSS-&J *Y RgϞIIIm{*** عsJFF:BUWW4ͰaZٳ֞h۷/''//w兣;xHZ|968f_f̘Ѯ[rU;-N.7~ k&OUU|*!tӷb4>]u6bՀۧSRbm]Ǧ cƴSQ؅1q$i? vx/JJ]LX _ "l+̣GAjzUAv _uiBhbC fPYY 7eHӱcDzi4͕9466ta!6-''W[[Kӥ r$'{ꕂo󫪪#E zJGG7od2uuu B@P^^8QLV-72"FXQNs\mF)BrmHYR*}j1eRF"ׯt?R 'OTTT qR۷ܞS#JJJTUU twKNM7%^&҉3$d2n4H~LN$dܽݻ[zuƈKtzPHB@PQ/R҉3eh/{y\@Ph?eW**{&//߫W/:.倜(**a`0cMR*'ӓ`!d45/p\.NoJdZlodREbK-dQ;wƣT*s>mF)BrmHYR*}j1eRF"pnU vjGR| c!7nqqc\Mѣ/\\IO=33Ҩ+++UU;xMZs}zRVR1lXkhiizy =Kӭ,- ?>rcDccшLSPSS{%]~4FDQs&+$cD&Z4J`?5==&.~dI޶)3iB(53EC;FYpgHHuUUUAAU`/F\\܃\+WݡBi#;xe`ū}pƌr踸=֭^|jKBfMqZ0!ǻE&zL8b~]XW[jddxd%<[u :+wc27oSSRSRNvھu?"]h릍n&{?<\A,įQUU)...**RRR۷l$H^kCѸ\4_wMGree:~~Y]]__M466l q%#4[Rf"F {jРA\vHYY gb5i^~*j,sD"w޹34>)QTTi̫W^4I# F>[D\Gٺ;oYY{LNM#^ #3&; 1{F"\.0 +Tb[ZOOWWGUF}6|_kHttBF~%!iNw>[ |oLPFL 46/vs Ev; Iwߺ4QY忭ޛBU6ϰ'~&0|3|':[&@ @@;¡Ź\ `& f4 }?ˍ'H“2QoVQ8XS PT6i@{7#\ ݀|7hiI;Y#pw!^z]\WGy#ЮFq0|3s`rj!=; hWZ̛9Zk0|3X[蔔g,3]cB p899$h6wr(%AF T1𭠧kcmmh` !q\۽h\vmƍ7o૰`GGE=xRd2$￷Y#FtڵI<)avZ}}… >|驤&%%UWW|T8RSSfff&''766{„ T*!hdd`0ƍWRRr円3gߺukL&ӚR8Ak‹$3!T*Ft|xx8 ++ׯ_?{AEET ko`~rky\ēH$h(+.^ZjBHQQ 00!diiݧO!{'$$˗b744DGGN0;ݺu+""BCCc۷oOJJ*))󋌌$H{---7nN/**:v옣iFFF^UTT8pքK.p8͛7o2eȑ#B!MMM??ܘ>#GXDTӧO555qFFQ={&''N-ZiggWVVnggqFJJJvv?%B(555**۷iii _~ Clb9J( B{>>>Gaʹs3fy#޽~ҥIm#Χ+i\y҅ $ tyy"V˭# LHcl6G!*!b_hC# gud_s3Kxu{ڿrLx 6$;9 wrBf"ݫ}pwGYѷoN:XGH&]]]B橩5k999!~ 6]d:֎=z4DJMMݿǍBׯ۾}{=rss||֨Q;ZXXlmmMMMI ߵkWke!_zϬ^/_!Hϟ?733{ݻ544JJJLLL!njjj*++;{lpp0n>>>gΜqppg>vҥKcccoܸѭ[7Ђ YFxyڴiӦM۲e $$ckeȶJfZYjjjΝ;jժ7o̘1#887 'i'Z#<~F@ 8hhhd؎5`g?Gl"΋~TUUBmՈ³bB .**,---88ۻL#pssF鏋8p ^E m(((}5q;(**b'x\peec8>(GUEDP,D"cb5[bC;v^BP J88ԫ?FwG1yߏ?웙7{vA&&&>|pΝr2++K Y8q(.mLS(bJظgϞNNNIIIw})))ӓ3DbA%=w ?~$O22姥A}3j~\6=ϝf;!d3 qq;z%L&Y:ٹ5BhP}&kS&~;u}}=}|oBBE9Lf` $99YTTf2~x--x'>8wmllfϞ}i嚚t벅w iWn߾xĉR\\\l"JKKo>uTТE:`0<==݉-!aÆ[n55GiӦ={4,^6eʔ!p7zaÆm ]||@&n)0|]{ΤuD~BNE%ԁK#>8;;!TS[޽DRߤ##|X254ڽh@2h{@ `!ի%%%Kjjj644dee}:֭[ _Y__v֭ Κ5sL&D"ŭ]vǎRQQY|o&ݻwG O9rdɻvJJJZd۷owE"=zcן9sxԩǏ555w%@pui2sĉM63,`̞=;"""""멩#G6l؉'|||U߾}G|Νgv!8z(V5^l?400غukCCCO>WVVH}ĊKϖ9ʨ b5i3---}𡊊Jhhȑ#ed*^>uTre˖"##y<^tt4yeEEń H3ҐߍDWf x\.l6]sj}&޸rY[I3U+,y~B~/]tݫל ߾2iOo޾yUN ;84 ?/߾eà{k B]t8hl4Rhgވ?+LZZ>H|$~eɩ..S>JDyyd"|UUU厎d^O\ZZJUTT_Or xq~/ /PhWVVjhhX>-"c"p[[[KӉZl%%*:$ #cGCZ]l?3;;0@LuuuF GT(ɩ //O[[[[[[KKKCC`(++stǕ?/%~V/n2FI>_&'?{b}y'p@>|@={0QcjZlā<$O>[a M 4o H&yiOV]Mma%t:::˳ss]?KXu/^"HƓH$ s3]QiM|ƭۓ'b;Y 7ՄWO-1&&$@`یD"QfYMvw036T|Ⱥտhhh;qphLdii߯_^=,Z|w݆Æ &YBunٶ=$C;[Y},*/w2kğ }>ilۚ \v12oz{g* 4ZXhl 5_vIk^|&-TF𸿌קtTFmm-nt46}^H"d2ϯ/-- ᓆ3>=幽5 l$`..7% h4ܮ BHUU]|Ty?Zd QbAW1ÇA9@kDcׁ|vhhUaanf #Zk/qxL& g"!C4_ L&4[m:6BH p\bw2L j`Hx\Ngg޽{ qrrڼy3nv&Mt=>IL޽{WTT$pxĈsi)pQ/m%Rߎ@ll,ڱc2+V!m[yvN9T7o^+EVoӹ"Q( LqB(J>T |F2&|ڝ xfXZZ٫KKK !>|XdIEEۛWÇwI$ݻ<[O#|FIIRkRQ@^^Dx< ?XJKK|fYlaf9eu'ke0ޕ욚sssP,H7n:99QTGGGkkT=='O*++w<|`>}zXȠAtuu]\\-[?,޽{&&&ׯ߿d2h4B^ӳRQQ)?~##>H$%(.dggGGGWUU!SRR222-,,DΝ;D"iiiq8]]]ӧOY,V^nݺUUUE< &&ɓ'Xo޼p8uuuw!HǏ'%%YYYO<"e.xD%.0333&&^EEݻ,K JXw)VQu_\\K" ^zemmbn޼c:QEEYQQѭ[ξ}tuutlD!X E4}OXc"i$f.޲".2F4$Qu555999l6M؁Ņ? !XXXHEN<;SXXxjXM!د_Ç;99S{/ ɓ'-Z=vذkKV*..>}z}}xلK.^0R(s8pɓ'cƌ!J.[ErޥXE]D>J=z={ly޾}+Ml```߾}}}}ׯ_-߿?x왏Oxxɓ'%D\x@YY媫/)!~???6`iҤZ\ci$f$^  ѣlyHT;6rHA,)x婦x\rݸϞ=KA<;ឣr +IL#U Qr>G"@~d2SBAT#T*;@aƍzڳgǏ˗>K.߿tRUUUVVB(--?xIHH͛7!ݻ-[6}8qwˊn޼y}EFFΟ?K?ɓ'P)S}ܹx #pϱo$*s9# ?8@SGIb ?|>Ϟ o6CuMȑ#qխEČ;/˱x=zx5BǏ>}rqqɓCBB~={L6JQĺf֬Y&M׷߸qeuG)++c#6>>NGFF󮮮DWĽkO>}… !t]qV"HDC%׌Z(yڅD"u!# H{رӧO?y$++X#R#Bʩf)$66k׮縺JVkaIL#-#aXXxS;Ċ4F$ݳ%H-Xwy)ٙ>~o߾JJJҖȓ5ܒ&-W-LCO4~w&:8:٭[ }TTT 3o!OO 'VUUp8dbڇܹ4 @Bfee Ν;K*-Gu Ɍ.--uV``ׯ%~E?~x'q Z]TUU/p(ФZ(u' (k˖-nnn7o|E.XϦy a0K.քƤp-a*iiK&]2#O5EL ߿ܸqcƌi^v7iȹ1Z˟#@$*v;3KKymG>E_IgI:,;vxⅴ^^^oNNNF8q#----[۷O:!hѢC1 OOOwww,M6ZZZ 6;șc߳'O|ROOV7Ox?qㆆիW-x.++ƍ}Y'..nڴi&I(U$] Tĺ(6&&gN IDATɓ'yyyM4}CNQF}d?Df͚O^xwvvvӧO߻woNNց>^lDɻt"R0z999 XrWaQrޥ@Eݿ_]憄ddd444 8!#.V[[ٳoߦP(.؛7oݛagg'\ D"ۗZUU5x`.sqqq`03$##li"T*544И4cǎReU*2zT.]x7fذa"%ݻ={455MLLL&Qu766]ഴ4}}}brNNرcKTr +I|=x/Mq؈f%>G"@X,^pBQTtGRPP68f_;w_kO>U_pr݌'雊)d2bikC !fI>Mq%޿{߲B]~qc:r ))-  r\g7w}r }L_^dQ^T s>Կ_FŤćI⹻ rQj甏B#G?|>r?}TZZ* /suuu/Gb6TUUE_rtɱBhkkKKKKKPZaa/b[nX~=266~' CCCS.6@QVFKc6tҩkO9uhi>~hhh(O䩵4BٛJ$FFF\.WGGG|ĺ7G={U͡( +_yt^X7ϧI\"Nrj#`0***'WTThTuuux1yo] 4䉾}&==࡬-7 عƭ?/ rrboݱJ$?-+x)܎ =eum~uk--,{vv~*:6nP=)q~BjjKXz;SUQ]8o^Nn-]SSk~S:!dme/nMS_WB8 ~}˽Fx"yݿG!؎4mZ9S& 'ihh077}B >ORy</ l3a;oK#>8;;!TS[rI?x4v&5Ih.\ܺcGyyůFL>%RB)4X7!;yb]J23߿C;q}{yŶ7oB6=g>~,BDk-\ }b O%%%Cփf6FǛ`a۷S&Mt0ӧ7oAHU?1Ο<q*m[]4!r(L^O Я݄q߈^!]rCC m9‚8ٵKgVy ̈́C + ݸ(^m J%B8(sSRxҠ% ?[m+IO6= 9LoޭL~81BwϞ]:[#I߅@jTk+kNCkg'E 3##<}p\eeeR!agF#%h#h HDI )lU}:񧚚Zn]B<}V+RJjj\|]9 l:ݫaÚQ}oW\Y|׬Y#-MiV*6hd2#*ߴu񧹙ٵ,Z|w݆૑QWaq9~f|BÇ50K/264u4h"o?oۺ_lvtꝭ>I4%Vqáad2}~mX6'$'$ZO[ilxڵ,-[{hl)5zb4*py>i@"<<|̙xĈswWSޯ_f7ewJyxޤhܸqɲt6)::T*oҋ-RԦ x\.l6]sWKLM+,X***m_*SbSe |& Ufkii54|0I˗8.ɩ..S>JDyy"|~CCCmmmYY8@VVDžg<ݻLx5ecǎjΤ uV.+>۴I:ڝLuuuѰF"nINMpyyyZZZ CUUUEEEYYM@l{{xPIIIKKKdVD"hijb'B`L"PlBшͬAii)>K4bf+ > XwABN캺:333xwNjjܹsI$E=}b֭[UUUDyIuuJccc5㤤<+++2S__r݊ 33[n[XXߕFH,ȍ,\b5͍annnHNNNII(..&J"\񌌌XTPP+kk뜜說*,!!!盛 BD dffǏիTHŊ.gmRRRP(H#F555^,F|TYYBӕi4FR0 A@~ѽ{w%%%uuu󜜜W^##)))eĉ/_?~|qqĊo[/r ս~zܸqrÇ+V*MEn+vy[=%\.j?-Fw#4;cg£('8N}}=Dw:VUU666OOOeXCѣǎ;h4-HD0 #))ROOd2̙3Ϗ͛7ZZZ{MKK(//o4Ͱaċ$Qݻ={455MLL\\\DNOOheee>>>OKK hhh8p B$VVV]tyAN _~N8M~~Z;:::00088xϞ=suu%&'ަ"#rm5;;;w&''cOE`X$ 'dEEwOD2Qd/痖ʳ@ (,,422ߥHGCCCа56&iHWȨ`4,lRaa7Zb###\z+W$'***""ڦ6v-TSS#NU\,{GK8 2,h!D"LMMe I$HdffJ[G6Z$ O&utt !Y`O3a MZ-q{׮h4'''ikئ6vo ^Q(Vp}.U"` CBB455:j D\.B!r'H0Ҁ.0@ZF =rD쓦@ AtG૆=Vi (2O4kS(l<O8l6AQ+] d2,<F ;-|̤_7"h D(2gfT `cD" ?Ĥ38>v|Kqf]z4@3KKyRfCCCeUU+eMR7@#FxTgZ|23^tnFc3ս[{>`w߽qMXU_pk99QW_gC |Ǯ]&Q#GKy>8}&~|qI BbUHpFDA_f &i 69pH~9fxb84,$,f=]]utΞ񪪪]"hjGMM-p,P}}}Nns/G] sW=]N@_WG*]j׋,500 EPN=rͯ =1j ʊʰ'~Zƕt:]!eölpqln8fq9ܖi[WTT|shl6< ϛ8ncNc#WTThTuuuq8'b*hjhM%fg1*AiY&FkIcY*z K ?.o`0ĥO+~YcӣǞ];NKHx"}Ee屓ff A,ni$D"q8xk@11wӜ\7?G>yv7/O0W RR|>;L>i@B"I&5˻  S: Q*)2OZZF$_>{ڲmǗ,Z(%/^[r022hx<ȉ~,###׮OCb]7!!?!LM1v/:Z  $|ڍn9| [h?fĘ{%.jM19fh`PUIdeeb`0&O7vx9߽wx.΃{w?><o߉dO|ӫlB.d<^Kfnn&5;~M===g'G 9zxicKBȰp1Ohm Md@ FZ׮\hӣ{L~AA"!$?SRxҠ% ?[.W{n tz҄~ pֽ[72 q5cP=;[[!=–]vii=lOZZZ"<$\|ysY]]_V 9kYEQ_2Lu4>gEKh7{~hsgܼuVcLkהghRBOV]Mma܅'|=yb߿WԸ>srs|Lէ/!rnݹ+ڡt}~G? !v9UUU7!l69^3B$¨uUbe˯<{ݻv}k܆bǹygee>qJ˭ckj_D"|''HfNF]N['O0\tYzFưj.]F)++3vLk<$d2JiJCXSdZ)™{;6i ~}Px_q3>!wrhE yPbN/20Drr(*ߴuBF4"tŋ /GEEF]573 Z[?|i5v8:x}w6m(6҈0ff._VfWT0jgs%LfeeQ&%5X7m&OHOH073ٶ56^vbdd'K֭3׫7ngd bzV:➉ ?+X \.al6 szV]]]ZVffj*l VyyuubE -MMŖS[[fw{ZZ>"| ֒9D#G6]]]bo߾e04 fVRR"ɩ /v6NRiQTUe2E}Ikm]]]gGR-B+%5R(z1'¶ >0U~h JkHnP*0444WWWgy<^S1 phG$/Fb+Baʹ@3PRRNs8<٭[HKKSNT^^nhh8}iӦ_ٳgCBBLfii)N۱cQziFOO3333##c„ YYYIII_0dBB I$VWC{ޤljjjF}Ÿ >z(%%%666&&\.Ctrr/,--gΜ 1eʔ{y{{߽{BYYYӧOoc;99ξsӧlv޽?| c]bL3i`_=xo&h!L&eڵ"n~JJJ )..v;J]v-Bĉ999m\qgر/_ܽ{ٳC2_1xAG@aii9c ٯ 6h`ФIO~ӦMl6`ܸq3gΤhj||3gjkkmll~'͛7O:EKJJ-[7ȁ6mTXXbBĞr|rŊՃ Ztipp0ɬ5kghhhZZڛ7o֬Y,-#$133۳g{eEN]FH-(p#iWlN hbddddd$;🩩6mBUWW'%%O>hkמ>}:))HMM?Bo߾7n\AAy|ЦM֮]Z__wmifϞmkk|6ɱ]ffhhիUUU{v#F۷o:::K.o"LMM%XhK"M'ЎF񈇠8?!pHcmm{Cܹh3f5wwwMMcǎK~@  ;vlvv  wMMMV%%%} {{{NF_2d M-u"<ha M @~d2g^oFFF!!!?^| B#F>|_|b|Op!Ct%(((((xʔ)֭qަ<""'+**BeffK=|Q9:u߿ 2ܹJKK%֭Ğ)M-u"<OC *4o$;LZ8ȅ 𙈈;w~ >~| ?OfB}#GM8ǏG%%%I,*dl M-u"<2\.aA8?"UHaa!BH__!~Fvϛ7o޼ygŊíGDʢF7&'Oܹ3qfˑs۷ݻw'NSkj/<8a@?h4>ISvP0b E'^LZrڵW+W"*++Bu^z/#,**ZnNCƌckkkgg7gΜG%$$` 2򵲲B RRR,,,z 9MBEEƍ;w^hޫW-[{n7PDP(i@C ҚH|$~e>HNMvqtQ"Bh\.}b999b;<bihhBdxg0E&5558`O>PN()))))255gUDHI¬_^Fv ̺u֯_zh4 frG&)ɩ /񨶆6CEAPSf*i*Tei3iW^=4C} D}1P(EMbgq ֤$ja`````BHI"4FĿjOZf xFS` /><noo<8=1ݻSĬ }~}%%hT\썛9rMl7KRBٽgﰑ^v?y d2,4 ǍbiOZ~ MZi$D  uEOcgxcbH#<=-QSS 5 !T__{QWիg֨(oZ[Yg.\mZ.;;}]ܦGwE]m a Vqu@"haq9ܖixK+<RQQ B&j%f4~'ysMtilJ.2pxkO+<VW@PZVI 2{Ͼw3(+)5(X aФºz K ?.o`0+f7'4e\5pQy=Jwr^&5:`Ok|E m7q/kdɚ8[܇7op)f88doJz֌>Ea_ty\|~{h8%L}v5U4K >{9^UUe$BXE24@:YZ"޼IQՖiāGxk 1SBGlf1קO^ﳲl~% 'q⋗#c֬\`0 %j!:&6MZڴSBZZZ αܾϠ߹~ӧ9/ s7ByUiY w^#?~lD߀{|PVvB;sY3WU}Bsf\qs_{N<ѷk.i$֢l9LfiekCW ɚJr8XB>ixϴv6Ҩ4y Bȡ)_&;;L~7mU|y>wr2ΟZ{d۷'Nf2K:[[理4p(jee,&yqcǮ^!4ӃL&9} gO?'IWWS[߹wL\yD|$BWWl9oB=z(jxw e FZ"^a)6]49-4,@J$6bɉ9te#CCS3S#x>ȧϟ,*Ft:yRĹ&=jIF2WUU!ttf|A})4X7FFF<]f~s.nݱ_VihlIM&M:BHZ䏖\m6c) Lx "Qx2پ`4yA94CqϨJCCC*`L;nXoxs{>c]\O;r:y&w}zB e1Quuu!9dʟM&BZz-ڒg?}L; hm£1Һv&*G3eg 2߽ot ܇ !yŋ-Yqݺѫo^pN?.MHaǐ0=]]aݻu#W?FٳBk[q1ʮEwԴ46 +o '*ZkiM[8{~hsgܼuVcLkהghRBOV]Mma܅'m=yb߿WԸ>srs|Lէ*ػ(s Jo QAJXAhDƊl1" XJP@Qޯ/MÒ'OcvnwvfF.MA_7D"ў_wX,;',4ɴ803+x)Oww<˙S(01BLYژQ#ۓͿ/]  .\P(%9k%3A$npQϷ ڟ)D]M|dn%$|(QSW^8j>}k^OLJ>]1ah(pސuqr$b._9|Pk>+6o!`0F>w^0PS]=WtuN6]]NYo۱ oN8/|-䟉IɉIz^?sD)t>FÍit:8@;&򃂂|>xƏfϞ]mmmiYSH$*USU wي ]}&؄d-ivVva2BhPW|p2kkk]$''GJJbh4ܟ Ç<5-U$WQb(l4ɐK3mrrrrrrͣ^eeeeN2GX@ n/III};rO0͟Eq{ER%8a/<ԂUkg9]]] mhheP\\k{m6PLLʕ+!3f JtuFF%`A^5I߇쎟͛޽SVV[z5B͛cƌyj\\܊+Biii O<v211N" S$Ip4Ho@ C6!ҷo_[[oddee Rd~ `Ki;(b|>IL;Q5IRqFR|> Hϟ_[[khhq^ׯ>}dXYY07nرf޼yB֭[JJJl6;77wrrr<۷ƍ1cžB=:tQSS "߿Ò%Ku<ޔ)SpZwwwHM,+Nf pGFg޼y(&AOOoӦM&'߼yڵkmmmܹ;dȐ)S:99Y~ĉk׮xխ[\]]vލjc'OΚ5k֭GURRLIIQUUuUVX^z;( gϞÇ2ew z mIv40Ϥ6w\%<O>>{;}tUU˗/Y<d[ hW(A# tRZ=]烞?|[2n(W Hjjjb;'>>/)).66!..?99666XAAaʔ)޽}ⅇLj#6mw𐐐^vmҥ%%%%%%W\1bB{ gΜyQrrreeI:dy>k˖-{&tHvv6ͦR!"=Jl]Q!/Kc,i4M;~&;:v02B4MUUBf3B;x𠪪ׯ9N\\&tL3ΑA讐e8o>*@Q(:RT,*akyt% 8+\nUu NIf!F5?cxxxffݻ GѺc-i99/FyyL.ӻ/pѫܸ?!Aֶ^Z;4ZA^^GGgnnL(CJSCcTtDEGzm0|D/O<|;mmxM(p_|k7rP;s7CI BH_OoH4Q$5T*zd{[ :_[Tg? [UYu,Ԓ+JmW#ٸc3v&/(** ;u]˄BUG4l#fϭAjm!>;:bdKeִ],JUW3nj<|XOt/Ӧh5{cs= gNV}|\/FO:s#O-]|>]\]et6v OED(+Pʖ,Z')-+/716Z2漓y˴⩧R{Z@R|>@#8Xit]G[YYZMdn~Dˏ]${[۔ w[VPXhnm+V9-;!h|rafvNi#@))& 0SQQAs8aƍz207W*zSvSQ:a9겲rPITBeOM Ag hNH@ub-Bpb?cT x8#$x]J$1 rAi(T5mVf2<<7_)B蘿>-~!??!TW_]_3Q0z555(!# mmUGOLKO b@2BSZ| QUG囘 1-=!$/H;^O6 e: Et:LxJgt:7H0bv1f⪪%[5l6{WӴA[=_cܕK=LԹ3ϜmC[+<)gSCb!lo訪vKLJxR1Vabp}J%uݽzng/Gc>9r޾%}*Ɩ8j/_>ylipТ=S|m_cM^:d2VȻw=MEŹOT*ރ!!vJ)-+۳o;qqV}znՓB_*Di&FZаl qU+i]> ·jx =vƌogKY~7nhUUUsU)));= Ba#LuvnVIyyb./$&7매.UTp!)(FH$Nb|'f2ffe;&'Q,a'ba1F2̩S&gdf|nkm---w떡Aבo~p<[ÇW9fHnݸ)tO?yoYk9 #N:'e@P^^QPE 9w2lc- rvte_FIKK=J#q_MM 钒eeT0oӾNdjj##8p+!CT;~}k^OLJ>]1ah(pސuqr$b._9|Yk>+6o!`0F>w^0PS]=WtuN6]]NYo۱ oNL&FnۼqȐOGiruu̝3q,EYEYy嚵 RRqcF/[H+*+K8Ip8UUp8-m&&%'&%zy+^Bݾs=x>vtgcVuk<>ڷ*7l$~(`S%(( @y<kh>>>o֖hk7>DZ5UU ~@ xW^^({ (pTU 7}Z _؄d-ivVva2BɕiWjڳ>,b7i999rrr IڇڳyjZ/*HXf(46ΒHӤTFr?NՑl4MSOVTT ͱDx&F6:F˜|P(|ŋ?s˗/8p~~~Eu"EH$=~crO8QQQ!##Ht.[__b5 .]T___YY9}tUUUF*@\ B~͚5ݻwt͛7׭[KtҲe˦Nf͚姤9sf֭pIJ-8#"¡~#o߾:a洩C6!]F͛7V_V\ioo_^^z 6DEEUWWoK,Ylٮ]̙m۶???2B;q׭;v/SSӼ<۷enn>u?ӟ}ͶS[[ۯ_?###rɶ̝;866CآgjiiW\b &iiiYWWZr%Jvvv8qbANd2 J[^R9/]]]G++ɓ'oٲ);;0nܸ)SV~YYYFFFGW;N 'ƽ$ ADOW+Bo>S В9JKKGMV)y1L \˩T{TTW;xI{Nrڐb``bJJJ***fΜQ\\|Сp9C޽{{IJJw:QBkgggߡOlљ3g ?}yrr2*JKK/^XSSsɑ#G"D"r{! K~"UTT~bf͚?>y|С.]P.t5ʮAO6dYA6 GCwT9 A{kk֞>[Çnnn⪪ܧOp|>ͶDo.--׷j1:?ABBv^Y*'''55011QMMIIIvv-6ϙ3֭[s8p_v/^d2i4ܵkW~222ufll0a4ޤ*99YFFwp8iiit:ʪӧrss TTTJJJ733C|^mG7RihhX8Fы/89OlB^RUU%>UUUÔoܸL1=zԽ{w믠?<dO?+|gϞ^WWPVV`0Zl===+++GSKZ@nFϚA@tZ~Z[ejjJNJJz3gfϞݽ{Hׯ믿›7o:::ܹS$M>](Nz-vd0}ͷhQQQxQ߿}'Oxxx8qV zQKKˠPEfffKdeeWUUs <`_xqǎ666gϞ9r}z\\ܑ#G,Xp#&M}۷o=zmK}ϑ#G95jƍme˖E=zm|bLj?ܜ|իWBϟ?5jԻwē95oc0QQQϟ%_V^^r?}s8SSS%cƌݰa?R3fr-^ׯ'͛7ūw *t&ޤkuC/Խٯ&7?4kk#Fxzz^x/,ˋRRR^|YQQb]JPf͚e˖[KKKKKkРA8[C _~FRmmm/_|0^%ɒ%KBMZ皐_zu|||uuucccyyr ޽{̙3+**]F ZC >iҤy|簉֎ř'w?\USSfo"''׷o͛7g„ viE(++6Y+ЀăLk͛_D/۷o e(o4||>0 *K244D/^0001bDhhן={T*É/--믿N7'_޽{xS{ttncc''L|n۶ w400X~y󂃃TYk]]]zɒlmm7mڴb ==NOr>>>t:ŋRRRNiprͺ:))֦oUTT0FFF8Ǔ'OkjjȵMeee+**+++CuC$~Z/I&%&&6 )) klE{1Nj6vV@ B ~yOQA* qD5%QQQ...oNNNoY SRRungg#rpѕ+Wr%+**Yܦ|+=iCޱcܹsǍס"::'!D]zԴ[n#FtpS[bH0vX}}OkQ}}رc###޿?hР !bʕ&Mj&j `ff7o4HJJ^~=j(Pbb۷B|8+++[Q9ŋ<444??_|Z>|X<|-++#C/^7I9/#F5eMv $`ZEq&:YIII׮]+))Ylfpp0BBp߾}B ''֭[ZZZT*ԩS***=z_r%N֭ȑ#:`OOҞ={R(h{7. 8DϞ=luΝ(sYMM͈p͛7aaaӦMk۷xΜ9K.m5fii^zKG3gΔP(,ܹscǎCFFF]]7>}z%%%cƌa2aaaθpĪ* OsYbE^TUUtn:eʔ466޿_FF{׮]-p̙7nhjjN6zzz-hfffbbBR8m[_OO=m\!ǏÆ ܷo_ll,NO111JJJϟ?yd/Z--ӧ&W;)$!D "B |?={Х222/RR0!4eBR mYY5Tׂ0L@#g'%%;PwihhE(M;ў5pr.deeʪkk; |A]]|WZ|>_(?YHc0aBD#GPN*++={fddrsssss{u׷y-\ii [<BÇM*++ _"X]]]2n~t)))ii" [F͔fYL4]A4Af ;MhP(ڮ T*3k{j93/<$<#y_t:]AANPk)B%K7n4Զd[bz|^AAI6׭[7/QP3,,,;;{ʕl6nEKP-^gQ@ hT*ƤO_Gl/o\.+2Ԙ~sxݻwO[ _CZiВWQ|>i|E "> 6-F8:::::eQ%٧ЎiA@2)CNB.|荍$X B76.]7f1c'4?[UnnܟWؐ sk[/?\e~ /3wp7NTs^S!1vĉjj]`ݼu.::+n#WWW&zyv"#\js_|k7rPג;%Ip!x}:r$ix WT*'D| pC9Bo>pcv mNYYi%KOrZs#f'>. \7}QȨsS|Mau뗮Z]_7SG[{ϾfsJK?y:8@0wڭeeQ%#|>BH.9@NZzMj| p_l!*++ ?Fx<FQly q^'OG ssűPeeA6 `2 |}?iSΜdŪsg*-+STPd[gxDLpqHc#f-qsgL=q*X7yr2k@kpfܞ6܉m|AQQaةnO ֶV9nӰCG=!DDKM[!<&q8Bh舑-Zv4*UA^!aK.c={^L2jGSh(ah8sHISY;8yN| @@|8h(;'+WPx*"REY9Dž⡣p7f1kB;|&2;< ћ׉xu c㎮soA [p9Oq}BwGeP(rI ,oO~yy?8(p/Zx!:&>ΚlzA v)&"040ڱkwВe7] `]4-6:R"\?pYj?p ^~Ӧgf;x(/??t/91A5STTTḏ#l.qqO>ih>3[FFnR_w`~{+p8e&FZlcfLݰ%%#'_/ ipOHlV,rZ0wBhтS#8FncCCCC RRR-*++p8N=zeanT*艓3Nut)ssee!5vSA?mN>wᏧ""Ok^'_(=3ڒN`fV/_FP3$zdG$*h?s. J J"$jL&SYUK35յtrB(ӧ?#O}&ܽFaFWWW#2sB5艓iA oVQF SZE`oc} 1-=ŵ _m\/7/o +/CMtI) M]M 1WUU.yl6{ѣ,-?B#w]KK}h;[2YtID [3c<&&Qx!3SSO+MQB@GGGU[bRr4V$ڥczng/Gc>9r޾%}*L8j/_>ylipТ=S|m_cM^:d2VȻw=MEŹOT*ރ!!vJ)-+۳o;qqV}zn)\ft;]'ed +.!sqrD-3{%fL%W-6AwGDJRT53fWLqGr8KWJIIϘޡOah ;aDNVvs{M:?07˻s /v'1Y?%%op|܅F.MA_7D"ў_wX,;',4ɴ803+x)OwwCS(01BLYژQ#L)323OEDLONKψuР7?"yy;<ܼ~&u ~ZɓէWR^耇 \vB[v܅ s;XLeegddfJ!H_Fk2۾NL!jj##8p+!CT[JgGcy=1)svh{CVVɑlӋ|cijx~F1 u5Q#O#jG_sv@>xƵk0\ m;v6ɑdҨm79rb3\s|&Ne?h &kIMK'LM~2L&D|> ;@ɑ$i!*Çl* l6ŒNNNNNNB "4܆& (twq@ Mcs3pqqIHH4iRUUU߾}TKruu4hPZZZxxP&mٲhic/ -i{EN(t@ G"255/]4sLOf2%%%VVV!!!L&!)++[__hlldУG:pjkknܸcǎy [n)))r8ݸqcΝzzzϞ=+.. ӧB7o~]yy#B޽{^^x9x;&%%(''l2}}}PJJkkkmll-Zᅲp8%K8995h|>`gQC6|x n޼yڵ w܉7n۷oeddB[l)**B|xϞ=455'NnݺJ6)o߾ EOO򍌌Lffffiiinڳɽ{\6dddd"wﮤ_د .]d. ޱ.]dE\. t³RP В֥pGG< /##cĈ,ѣG;vP(ܽ{ԩSq RWW^#|~}}}WtgQTw%-''(/ lOsC޽M|ἅ^y 0ߙ~/^ :::}'wsDE̜=eZ>)M !v'NTSSn_\rڵ?l9\UPXx*"%%!}=kVxIҽ{?|H7z&>, 5Hjj۷555̙4hBȈ|kkk>|XTT4gΜ9s˗۷ %++K|Foߪc ZÇ555r! ?~|ƍ7dbr +--e={ Og|Eo _4 c<1K;Ҳޮb钥'MrVweee. >بOd9)d&Y/@ Lv+!AEY!dlO>aW.Z0bɊMD|>BDi3ᡙd2&c]ׯ_6lX=^g<|0)) WVV~ݺuUUU!1j(mmŋ8qǧq]B;vB!K3 sssooz /x"ݺu2_7 N:Q8=iml]YYITT**ކx&gLƯ>y:b+*.''y>ODL >?gN:u%+VŜ;۞^O"LQA=vnBuLii[<H]SSCiO_"tzSzz 46rlZkg#?+N攖ꊵiD={S}O 711 TxS;7nkУGpE-^Xz۷oܹs{ꥩp/_ޫWOjjjgeel۶mڡnRWW8r䈴k6n`0nݺxb… #''חMNNnҥjjjyyyQQQ^^^x-[BCCg̘QSS7/ɓ۷o8qY}}}nnnddĉBO< f0EEEα~~~we0AAA+V ? M͟<%3 °SǧMٹ ֶ\LKW\8pl}rBCGD wsbiTRaKx ^L۶L zn*Ӿ}[,~?p0>E"хѯhki0|،8B:W[[+-%0d'w׉GzzFVN=[;;boqywv-ha,$ڒ *a@grqqqqq)XxŋpBE|&L@ST:\SSd2_4F5jԨ/!!r]]ǏS(_ܪU,YRSSןȬ[nݺu555dNHݻowۇ:[ fǞ,oO~yy?8(p/Zx!:&>ΚlzDPjkko'IȘ2i"BHQQqCv-Yvڕڀ ER?o#%B1|GO7mZzf澃C7n@۞gda^]]qz:d3uɬi@m׭;lyMJpJM ILqOح筂Bsk[i9E 3OpJ = ,JII'h~+++p8N=zeanT*艓3Nut)sme{%A-Ȼwűqq/1 !4{qNiRBGgf6,_8~ƴxII '0hq~/P(iFFP4|{@˗/# Ϟ={'|a| ~C"Gl6b pBP%L&(eLi uum--B蘿>-~!??!TW_]_3Q0z555(VVV 6*[k'Nkhh1Y6x 9BGO<},M/ĴL,kڰm-S\_ 7 IDAT_pqeV:r&O {_G ()>}Z|.' B!'jY#نV]]daUUU&Aj͞d!AdfgO|co0w%cG:u.<3gy O!dfj4*?F®bVGenC]{9#3CWWy0Pxpf iYY!;OED<7pƠP(x4r |k[ݻwP' [x Uɠ2f"YiĒFL#FN{ܘhlիEoߒmDEoޡOlmڶxɳg׬?n,BRPOW w̙͖7g*ۣI2Ӡt)S~ljGіvFh+w߸ѣUUU9ΥWgL'04D0k"'+;ٹ=[[]LK߬7oF\>V]S}EP#q"hϯ;Y,~dZ u<씧B)lrr da~!&Fجym̨m$hmk@tu=v2BXY̬l;C>/]  .\P() rvte_FIKK= !LeegddfJ;"IEgNxƵk0\ m;v6ɱ nYzSᇏR-QV^~ĤĤdcâ~A:$TDEEE,PDsuZc5V]Q BWB@lE% Pj$&f`p{=9yOltHPxAcRݤi"dvVlYM@[C9)J[.\\.al6 3fqub**+MMLb fU2?^5pҲrMMVv [bːQ`0t O-999̬LC>HG6|>aXڈ7ot BǏ?=3+STզjU4Օjj*4Ue2J֝UJ"(<;*jnfFbK0eB&)Gh0)$h4Eb X!@CшhJHTۯ94vD|>p4Tvj@;x#6ը GF?4<;!rGit\PDD)(~SשS';VVVQQQ .9P8xz@]P0Ҁ{D"aϧ`)WWWiDOOO⺴4== !O"233 á±0 p횚ggΝ;ːϞ=ҥK.]dDXǏ߼ycnnBd5gKKd;  ۷o333RSS \\\Ҍ=<<G%FيF kYZҢEQ!A^^GZo'"_6*gAA'Oe,濪OO>|XTT>p@ "gfd2BQRR՝9s#G^zջwz{{{Bw+))UTTdeeH$'''2Z\\m۶C(555骪nnn***D/_USSի100P( #++J<}ҲcǎyyyEEED?~tpppqqQWWG{(55Bxxxd`Lfzz3L);::yxxtB' !{I׮]o޼)|͛`!ii @n/F2Dt2Ç/^5111!*zųg"wFxڴi={5jڵkE$&&'$$[NF\A]6)))88fϖZ8%>]|ǏGeee5qFyhs5^PPM[&%% 6lʕ8͛7=p?iӦ3f'|0p@CdWWה,*xU #Ri,MEW#!ɓ'cǎRҚvB e6"CΜ}ʕ;wvrr1#4%%%##ךΝ;ik&44s߾}-[\|yϟ??L&BzǎSRR8pɓ섓277/))BBBN8qׯ{xxݻqƹs;k,CCCЯ斔k׮РAlllܹssν~L&Ϛ5+**ߟRZtiܹsիWc7'nݺ\F)S:un=pNݻ.]'ڰ^Ν7nG ~@h4ΧbOK# Q7#f{B +++| 4,,...]|5pDDӧO9ϟ?J-OSH+#;ϫLlRSSUTTbccccc߿Eȵ$4&[{!^.B5e9-{PFXª?~|v픕e)|!1ir޹sΎd_~֧۷o ouxGCC~@}Q=ib] gXQQqiӦ|wZoӦM7nx&ɲO;pϑH[`x`ݻ"j+-rY RwwwrSDַ m\]]kmm-MND"d8UUUO񧪪J޼&*f(ĉjhhpww_~eͅ+gdd\z͛7<07MMM2v9Z>ue#H$l3߁)s==#1ف\7BD q0IԞ0 "J,צMD %Q)))3.49eTHUD}UudݺuǏojj!x;NYb JS\9xׯ_3c>}{,֧QF={7%%KU=KkPWWg2W\ٺukCC-,,ʄ޽{ذazǏWZr劳gVV֞={py:tN8'33!4yŋ "##E?򢣣x<˃--кudlشi@ ضm[PP%e0B(55;v/BXQID5$į$hi7v%'-as845%|>^BQd+d_8iii׮]ҥKgPrrrLL 8w3gJJJΜ9cjjzY&@Rccc?\__'!t]9SNZ[[911qCMdCll """̔$ɱ7**4iҧOm~a}}}G1} .hhh:thܹF!H+** "##E266#55ٳ/^/%*6&&ŋ5.\iܿi!M%'"*++KIGGի$Gݺu{×,Y"QND8QFנ4Ilnnn?~|?x¢^zi6W)D"mݺuѢEC y𡓓SppMT\3" Y~}jjjvvvffaNN-ee;SԾ}:;;o޼y̙O<ٱcGcccnn.DZjUVV֠AB{%|K?~|…֪ٳglԹs3g ,XPUUegg>}:<<ӧO***CԐH{Ĺyfffvvvd2K4yʔ)K,ؽ{DN8fmmf-Z?uԳgϞ={ڵkYYYgϞׯ… ͛7 wɓ Hy&\"PUU՞={rss( p8sss&BT*6( _a/\q\flvf̘,m:t8vΝ:س[ ݾ~UFD>:p˗}U)/_evBE͘*h4%c#>Ǎ30Wx*Pob]c2WTV>{Ҳ2A_ }?}bl{?,ųp1zfV?B|+IB|>XJ:aJJJڭ%`J>>|>ǏFFFG_Q 9+** 襥FFF̒-Hx>_]]CQ544Dlm.$?aa'M]lEsR];y'e\_,o˚`SY$dcmu! gaaSQx.|Ū.+y.)HKZii L~2ظq[pX]==ŏ15'B!6d (ӐiА:Q2)S\(ԉЉa-|_eeerzھMS.1p\p^~>B[7m,Lnٮ!n ٖ uC|e\ש͚+MY[YM {`br?_@pr˗?o?w!xT:z,:}8,3s;zԔ}upNuH;Ai3*6ͷ0L][e)((v󦵥ukpKy붫so.ibn`;5#}"XZ\.|\Ҩ&fߖһI!''#_egtw"19w_i{ \݅*ﹳf"oޜ:}hljlhhtt襤$C"DJ&8yjİa+×" @&MK!c F ηd l%iE[wN::%%FTQR+;yJ}=9?.Y "rrcid; 98RQQ>dS~tutfMldhhҾm<>O|=BsAcǜ9/!ƌ166xmm-BHGG;[>>]]622x={ط^lcsoEx X߿\XTtc'#LLڏ (++GcD@D^;LChҤ6IYZa<HsNfMMbDs[;g}fܘ.{?|F-K6l賧Ϟ-^}<%w^f*L!mo<bK4Do133JUUsN+.MJ08E.zBD ojOnxrҴ͛ǷBE>ӭ)2>=rtpϿ{þFku/^B565޼u[ v55555QUTT{}DQV!o3bԼp16/6?t< _?m<Strtزm o6HkAU՟ ΐab0jjj~b0Qdݰ35-=5-ltHݴ/EOd`A+ǵqu]zbll kVaIܧ k`Bp8UQQ $ ۷o544( d2ǏDpɫ4m MSBW)U)-;GACCCCCCmT*\q|Bt:Ţm;Q h4b\m ^Hp/%Sz.2A^9IFB@uDqc ׎@[am1CFJ%ɄǶp 'L)*A!-|>>MxJ _#Y*Sv0Ҁl͚Hh#Ih؃R4p`7!T*}oE_(#̤?*ة#q q4M!}gD4࿎Sn [yyyyy9NFp8Ν;ϛ7;\P*UUUoƎ?~7o@};J@_64;FU" RWFjHFm^w s3ӯy7J-v䠠]&'''''?{ݻ>>>[lϟ8qͬ'O@X$!~+N$PS[۲mmm; ECCî(p1{{+V V\YYY!~sѢE/_@Fog;}¥сc:;sN9{wyy_9e_'$lWY餐@a3f;)MȨq tq'L4pw wYud>Nģgo޺]ZV240_K~y*N֖wLnib3͛7nnnߏ`7nڵ}8^P(ni"9G::|o]Օ\GG{ԩ<NRHᨫO C566~((99.~߮?uZKVD}vj`dVu,:5=}0>?bڤ55>U ža(..Fu֭[۶m={6Ͽs玶Mt:B(55JJJK.@ݺuk,o߾Ϟ=+++366^hQ߮nܸqiO>,ZHEEEZQQQ6l(--e2~~~v!??Μ9,*22RFXhuu.],^jO^h ;*Hrn"\jO`2YxfIi5ǎ3O1zL354UCCCdxUUznT*5) s,jll½pk g? Nb x< <ŋ˗/WSS;s挆F>}***&L`eeݥKUVyzz7?\t۷ڽ{۷݉X999N5k3f}BB7BhÆ WNNNjlltwwOIIIHHԩS켽ݣBJJJ!ss;;;?#F`#7n(l|>> HN+.>h@WYx!c^oԤ /w 7!;pMd$K!iF۸F­ٖ uC|e\ש͚+MY[YM {`br?_@pr˗?o?w!28ΡǢcγX,e%^}m$655Dxm n7FF+pGEEmll֮c݌ _ @(H"b2^e/짭8ZP(m <=z4+1444iRhhBHUU!z颢"2-+{,,Ǝ9s^aCcll$#q}绻]]622x={7Kl93f444ܳ۫C{:v2sQT\rEx X߿\XTtc'#LLڏr'ik : i0W^2a먢NHLǏuuuNNNJ[rET-ѣ[n]V䩌 o{7I3*04d”I))U;OHpPHp[133BڹSK"rr_7ik0D7*phcƌxsҥ͛7 ɩ;wDm۶D"um)--;r츞~,g2|"w튵S-Ӧ&&'q45,B***cF +,*B=|efvP< ѡO[Dp8];?~"%%|\R$صk~7vΝ~EGG㥌$)""b֭ƍˋ7npt %Kggg`%}Κ5cǎ #<y$dwDCG@𯝓&f !aSF `0\4mfhme<}[W; uu '|3k;N&;XX8ڲaێؽo^CC&M_%vFԴԴts3с#Bw_}.Z,O~~@#Mx##;AX婫7+;%%%])dUC_|ΧM .x\.l63fcX&&+b .[ZVIj׮|M 55ړMc]:/j.'uIi&ζO rrr+3+_?HG x܂x<UYY ߎ7oޜ={v͚5+VY jt:BǏrlAa mMUm]ES]BSU*ӨaihhhhhZ$PTs3SEF!$9Yڬϟ߼yjN8@ScG|d2';Ӱ*pOQ(|lb, Pgϟxѥs纺S.wZN*\tԩSN73>OPCPXTsbYYr]:.Oµ8755h4{҄'+M!YEY.``:J5'?B*p t&O4N88I(`?VXQ\\,O^555uuunnn[liQQQfff5'~0k֬.]$$$dXݻw{x1c_3-fڵ_ zY[(VD| IDAT|{qSl؊B#CQskn~HaFxt$: 0~l {`&M())^s_r&{ܹ޽{#h4Z K~[pAd#~{Oޱkx/Vv~.]nzCl\|ܵkLfՑ{;**+OGyviYB |/֟~YvC'R`\.Fk 秀0#GLNN>qJMMwAݹsgժUL&ĉ˗/QSSsРA={D^x&LN<}LnnnrrrUU_ Ė˗/-,,455C>y$55`XYY7͛7III\.wǏ755 ,...ӧOqR&LHKK+++ѣǠAd~BJxAjjj}}}׮]GAR߾}{U5gΜT}}ǫˣ܏?:88|`7tÇ9+BP(xa˗/E򊊊lmmuuu///ic0YYYT*ťӧ;vQLfzz3HLIOOWUUussSQQAIL\UUݻwEEE ÃL&}L&͛7d2ML&ZZZ۶m;tDI%CwYUIJ#JJJ^zeooOlm˗/sssԴzꥦ&ҥUIJHGD Nѱ,//ÃN /**SUUmRD'L&S-P4߿''w6LYYY\0oʕ$6[h">뾎xtH^=_?r+zb`Sy<^mm흤+Vi͖ᨫO C566~((99.~߮?u"n[S'Orݻӧ%%߭rDž0U]lɮNMO?̪CϬOX6)ƭv?32BvL $^'$8`hhD͜93999!!F,_vvv&&&DgO[[ݻwqtt<|ԩSUTT޾}{OOOq#Mb[ܹٳݺu,((Z[b-#H۷o/**Fښ5ks…={v!###<<ݻ)))cƌ|pAtݻw?~aÆݻ;ƍp8"JXhѝ;w\tҍ7&''eee;v !ԫWnݺ%&&FGGSqqqqGp8VVV3f̸z*tҩS;v,&&ݻݻwqcǎ2|gϞM`0*+++***+++++?~XVV aaa*++ӧϝ;w6I55z@rJ۷o#ڵ+22_[YY˗/#D+xb"euuC)khho߾/^X,~Q7w\rժUׯ_7oF:uf֭L&SDx"̣G}Iԏpܴ4#zmҥc6lЙ3g5""p=z<{LF`СC߼y?f-Y_~ {{{=)//.]'޽[Z"|>&%%;woFd*8!"^bbbXX>NG^X\.Jx<H畕bihhk9fgg2 @PPP@PQ%wjKԶIJh ⊒F2sL???ׯ9xӧO[͔ib7K!b|}}}\ew}5((hD7wSRRuNZ q{gD<<t""Ml|㉔EeI/))IY5<¥4MbvZ-4ׯnj -/?NDF.7W8/ _jY8N722hx>~/>$C"^v`yh׮]UU.hmm-LMM3 i`KcԩDp*1qaL@"ƏSܐ$>>WlIslhhpww_~e͉xBbDo喕L슊;vTTTL2嫕.CjU#vcXu"Cl".6D0`WFFǻO?o;zԁ?ww;94 p_#%%,߸ f )`E[wyڵkt2uh<7` d2f)_h &HԏHHWDGGx˗H$555lb77ɓ'/^_ECKKcӦMb۶mAAAr劳gVV֞={ćxDnݺ7o'MtWWǫV GIDp@╔]%6iU#F">?a„s{D5B (U"һ V]ڰk]kA)" HIΗ7T{||̝3{fs[|I[5,))5k˗/eӔ!RܯIA 5-+IO#\&.<`apʻ[pSfjrMZ~/]Ii,_29(ؽB@eN+{GvWVV.eMa7mv?58ԓϬF]1Lf-++w𐣻ۋ/%"ww{?VՄgr.]fex5 þ~:nQjjj0 khlsk[& e2,fX7oHZ#FG0p{^z;hР 3͛GUXXnÆ k׮=z_jjb߾}]ʒ"˗ӦM۴iN׮]+ڄwo޼yԩ aXvvŋL+WX[[+**:4)) &KOOǕ/++פ5jڵ3f̰%O<8qܹs?.߿쬨驩R2I1000224i|*>}jhhhnn޽{wSSS*f̘1‰kjjLMM555-Z%뫨t}}}|A[f]~~~ חԩT A޽[z+++Nj``н{www ä311Y[;nܸKsHHJֶr ~PIwܺui=  +nm)ECxǸ8ajjecc jxxxxxxy!,tI֖9(P;IPPZhh7JðF خk4B,HRhhh>ٳgttGI>)}4hMɄuϟ?( m&h">\.p8 ߘ5kV`` E'L8sJ`rr3N]]qS9vԽ['M~9Ri;sc?~KMvd\t+Dڽ}$Q#/m۹ku/ٱ/ XѮ⢤1WHI3wб׬\=tw^8¹sM=J=ں::xOR}}|3XUUUp.pGuCCp˳X,EE _h'<qfim۶UVeddXXX5x;(c}Y3g͌3pnW]]]|$nɌHRO uuu 6"q8 ׋/?~ [9+F\;x_r1 oKp84ZAAnЂBo3H*ٝb- 8x𠜜\cccVVք ^|ق|Z</̛7oTTT{nfqut9 2DU'+S-Y&^ 7n|(-5ׇG>)x?jd cfN֫W226 5b8˗/g--,6_7;xF'`#Mc'Nvݯ+L~o?~ mi kϞ? i4)D\|0 qoYl}]<~$!)yYtUU޽J+)d28 EE"#@dr a clF2|h4&<۲l>"PԶ]|,MP$kqE]z(ɝ4˞T*U>]VV[WWVP;Z_w3][#>)=-(f9Z$4WmY޽;|Ϟ=~ڂF$$t8 NkkY3nޙ4=hСL&4-xfɁkE쩢,K2!;[۷]NNIꭡQ}cct*}qql\yy01x{yE\TRRp|>JT/fؐ ~GZ[KMMw Iɪtct,.JCC0/k?y==wbE!+f_]aDib!׮G^@6ҕ$HTZVv6⼧)HSS?`ݻ@Sa; 5?W&&&:;;[n޽yko6o#UU &lk/%%%f200ؿ?z}~0aBXX=?$l'@ \0>BZWGKJ鳎jkk7KN#yvJj>2р)pG}'NYY۫oc8 -8gf0~]׶999]!~L^\`~]kQ1̟4߹[cg dOww{;m;wq8Aymll7955ctL(jPIy3 #gpLfUU5Lf+Wڌfdh8f(ԴKW7 ra\sm[Łfp=999**=8=zѣ*}||]^ѣGjjj^}A]]֭[o޼QVVj:$y&2D"&h#k: }}| ؕ:M,x<^YGUU sT0 rħ牋"&'7LUܢK-5i\.B] ݁@ h't:Dhp#GI(.jƠ@R dmHRrá?Á;T544@ ]o3Ĉ o 'ƒ@ DW5O8"L[S(|&@ ސH$./DҚ]e Ձ*ӁPTh$ QOG#iǎ3_lll-[V[i IDATѤ;ݻwmmm޽{s%WW޽{aÆVņ]K+{ݬE\MDzOn&P?!<|>Nؖȃ8Q8J+cZ"#G?~o|qɒ%4̙3hUUUuuuVVV=zoےsssὛEz PF\%%%uu>}[윜OOO6MR?nbbҽ{wIy铭mQQtrrRVVb(B!6SBvvvo߾uss]Ç4E"C%YUF7֖Rd%i,7i"i-p3I&f d^4n&P "iMYIIIN66!uOB4D~0`J\.04@H"::ZMM[x```o?zh„ ++++//OHHHKKsXQFQTkkׯϝ;&,,,66vʔ)nݲs&Ʉy>ve0]t5k֍7233%PHzz  [%''%:wtLIƮYf/^عs]!| b7.2Bɒ4i?74iMl K2${t7khh޽{PPСCksn`6hѢ ̝;788xʔ)#G򊈈vlt/?<Ū`2L&,///==Y&$$DCCTMMmΝ𠵵uFF |@Э[dx|޼y'C/^0VEEYb֭[E.2dHLL '_~m``d21 {=BUm&&&9s޽{?\Rn/,(ZʻHTj}}=XC6A DXpaHHȩSAl&L~]IIѣG= (,,ӓ"VUU5$$$!!ibw:thNFFF={$I7qZ;;;x[o333a˖-SWW6= ;w.˅;7ByyyMM|7رc;<;p@(YKKN]>|x^rwwoqvd)ָ^d߿ ؤtz7kVѴͤ{7={6zm"=%wh m3x=׀BPԙ3gqrra2jժ 7!nnn[l0bܹ3 ڻwСC?~}}˜q8C+=MdM=MӤYA``kֈ"gomy& AפUTToX|IA&GQQQ3g^>DR---\:uAKJJX===///ð[cذaG0, @__W__ȑ#555򚚚-rǸ8ajjecc\MLL<<< utt<<!_?mۍ@ 0 @n@[hsA[nY?W/o ?3]o6m.ٷ@?kO bUT=ppΞ^> Hhy [;8Mfck\. @ ѮmvGҸ\rG^sݽ,-$Ҙѣl4艓N}V.x'Md+-{6bPF׮5_ke3\u颂No|d5yr?q>Rmm?z|%;w7qd2y|nݴ6Ʈ\|Zb}=AL< >_{NUUzu~cog'rJx-]ymgGGuuu]{.Z0_YI Hx^@ FtІџ1pWddf~O~љW\tB4^fWF^2u93pw[xa\&O5r΂FDM"eBRr?pL&TCX۟L&8}fɦ C){[ۓ^~ݡun0VÎ=𷽝&3s%VCV,'Hٯs,|l!譁@ hWT*'m[Xhjjy[8q̈1Fhr$04076AGٷ#0>ocm[H$wPz7? &j)((p8ٯs"QC FF"ϝ3עuuu ,۶RFwq-M @ @P` ~)f-0iVz_o9rݻHU,>tȅK/pqm>uq0I$]c-z)0NNnHEEff/OLHn^l+ܸmy,0ď0>/K?)ekXsΒ^M DGyykQ;qV~ @AAah5Liiai#Nu:ʊ|EUU5!)a64ذs,{(+{yzhO~NAAOܼSagGdJ)_ʺKWH$Q#I$RiYوnn  OMݳu^^~+)*Moc<``0& СCӦMy$R_9JK5BٸvƵk# 'JDˑ45E2"LัC敖{[tYRsgۣBy[h(v! 'N\xիდb7$}}ݻ㫪{(,,|),|gόڇ0L&rt;ӧFFFNNNrrr_ζp8?-**ugwﮦ^zYZZDORE㒒eee___~Mff&`0))):urqq!̝%%%III}QSS,--H,-#PE.]G @7q%Keq@*T")@ @:0 YWWD"iij I }Nwt5bO~RZh>h |IC d˗/%%%M:U ;ݻǎѣFSQQ_6666lo+W\pA%"pС3g 8N߽{WV޽{733}ݵk`Æ gܹPSN۷٘:S:ɓ֭d_$V铿?%.y<'zс;0{,hM! 0<`mm͛7O"f̘yf333======{{{ccc fƌIl߾=$$DYYG*IJ&.ŋW^UVV*))͟??33ɓK.'<<<_zգGa\\\\]]lrGd_6 ^nllgׯ_QQ/LvuuMLLɝkMLLtttEB;˗/~~~7VR2sa 7x֢ B&ѣ@ p\_HF 62 {/H! fff))) QQQQQQ鞞 ;Ϝ9cǎ=}ׯR$ {nϞ=O#LFӟ>}󓒒wh<==7n%Hݺu+[G^^O> RߵkWO%Xʵͅ`He%"Y~w@Ry<^;ECo"~ сx}v(p! 'ORZZZ#GVWWmٲGҨ'N_QQ0L&3!!b/^XRQ&uuu"cY0 2illTRRoIʝkDX7LVV%9lpb^m+Ugpc ø _a鿸{Ǐo=zǏᩘ a۷D(--0ɓ'w.?&4ha2B _xѩSI&9ֶd4xE:nDTTT>}1b@$%'NKU$"h"Fq|I EE">@ ~o+ǃm3X)m% >y߰ݻ7*DbdIho%%nn[S<?é700@E iii۶m{iCCCQQQrrr\\ׯ] uuu=`aaqEyyR;wP(UUÇ暘55Դ=== aUt:a2777q ߿+''WQQ1uT[[ۭ[Ν;;v,//pBu떚E% IDATM&+++o_Y[[d2K9B&ϟ?ohh8gtС\---6 khhC;uDxmjjE"1hbaa!Feee–=zpA"ŝ۷"w|zmmsrrTUUCCC333;/fHb"@f (QQH#+(4YJiѢEar9iƬYQ ڕYefg99Q`>a\.dDs0sX@ `X»! 0Qkqw˗/<OSSpqd"9F+++STTVWWWm۶}eÆ l6K."D/aii.ᶐMڹJфB4Kx!B7ot2 ?RxT|-Ŋi4T*rUI(O#S@@P~d2V@#"d&!)t$IOOOX +`Jkex<ij/|׷Z)Bhf/;@p`6_֤!:p-a{2P! /^xիW5,|6\PtGDGpw@ -E`OowDM&H@ ]`3hzQ# Rp5@;Y#@  $aHCׁSBtG@ DXi @ Z(B;a; AtT pY՚" @  !"Ͷ6!:0p)@ RxO@ ]UPᆙ@ @#iz=oJno&@ ,_iڵ@M48m7Ҽafvx^s,,x6 ? EEQ17oٕttO**Ν_V^YlO~"|K>x`J1M` T6F %ٵ (+e嶔…-k|.4~xhkijٕ=VV~IIK1l(kךO^nC'%%%< a;Bw=|in޶-4;3P# p`VPPйsg:5'2sW1=OnCgiS)+p6|:0.@~==%x*5٘+;wlh` Rfʸ|>bGߧx¥S'Miц-4<?@!%>>~fffǏ?yϦ@ .((?nootҭ[?aׯ>|ҥK͛g``0u]vmܸqΜ9'N,qqqVVV+W$</],i?Rs*, w޵Ylׯ_777߶m[G) cu`֭[7\4 y۷4 }D*m'7Ҳ^eOɣ _egk7ڷ?a#RHOh ]_mb n;;:理ڳwтzzMG҄d<#IC ݶmۛ7o~6߮]`yիCCCWZfCBB6nY]]o߾iӦ-[l;uTHHH+rM{g0`̙|Q(Y|&%_?ͥgϖ`Ĉ'Nmh;w4_ztROgg͛7HPP丸8zp;ٖve͚59sXXXܹsYkٰan;ݻ4B$qET.]ᅲ.]<ABgΜ'HBBjA0@GFZuuav=aUTS7mNIKs gl._QZV&%=0 69aGԹ l9_󗇬9|شɓ^*)*NjL&STLC 80XGGD"7dXC{ ;;;x|Gǧk׮4B$q&ŋDځ%̄ 4(<^j+x~311IJJ޽;Ύttt>~ڥK777\q4 ?,ImYHɵH)Ș/•)| +,1 KJJ񣟟_FF?~ RRUYIfFF:E%qdFc嵰d]]] BcmmMR:sN@UUUjjj]]rssWS%Ô>|(((())IIIP(nnnQUU?z0??{ %??Mz} --ɓ***P Xb2NNNڄUTTdggST''ϟd,//'8D^^^]]}ʔ)>|عs?Ch)#͖۷oKJJͅ[>>}-** %lvZZ#L %ٕ} _eSPP&gϞYZZ NXhQs݅x^4юO ` ƍqs{//wěό3nĘq-MImЅ: 5bld~?)~}=O>s-:PWW`R:m+Jmp޾{G8r64v4@HBDFF>|ɓ'C 9rHddH 6$&&r8smll7l؀޽ٿ}ڵ ðS 8رc"bWZ'1y䆆&//TTT{pz-I^zillLHHs>K\[UуFxvDLwС;v<{lѧO+.PTTKRRW\ƒԖ%S K 0SVXN>f)$dy-XYY qssS {耀;v$&&:^7oӓ;K鍨ǏǏ?~xmm-l^zuΝ...`{ݰaxىwtty͛7/\ĉpiڄedd?~|ȑ+Vpww?q℃b.\àPI!007tkQǏ7o[GGG[PR&noo͵k6 .ZtQggg|`bbm?/_tpp9Nlvcc좄pMxE7Aw> c7x7tutkDVUUDZDzӮ./ s?%7I'YbA#ZONnk=V/_?|$7/wn|<|وNJoTxZ `ׯחL&&&&l%%1cU/^zRIIi7o߿?D1c͛&''?|pذa333cc={뛘۷ cLLӧO>]WWCGGGx\\[UEij#n!Cdggg????R044&0.M4KA|.a%$ٳg r֭StY$̝GuuWz!Q,*''ps=yDvLׂ߫tݻgϞKN/n@(E9s愇6L82}||\]] %Emq!={ȑ#qqqZZZ%wW^~SN^xACCd6w147{;ZqCi>9*:fL Yv`x|}Q#9>} ^7F* mkн)im~&޸vչ/0d~>~9=w)5!f ?)̠AJJJ) < PZZaؓ'O_xѩSI&9xuLLp |Krr2ZcK@$G$&&k Cºuuu:}-`1EfOʗR ) G%)YJP1BkgJJd1]IIɊ+~w&%c",.лߢIgee1Bv$'%9$+IBsa2Ç766.//'twfffKKK7nԩݳ/]@ 8qŋEipԉ'?Z* D"IQ[D=I []"~7a=}t͚5+VbIjKcs→Hmٲ0s΀322*))!r0%%7nܲoM>O|F%~IVh$aQOMij8zYZ݌aWVhk r]rL&SSC453~m6]wSSSn޼˗wepŋbX"ݝŵe0ª%((hĈ3gμ|2֭HvELWRR`0߿6eʔȗ/_dGX~RRR l;wD,OL% @D/qeEX"F/\ayyyIyh]v{+L2*)ؘ>MIIpBEEŕ+W 2lkkq3g BWiWZդO k.cYEk:88zÇ!!!K,ٷoٳg/^ح[ קW\ٽ{wmmm*ڷo_GGǭ[\pa۶m=z􈈈'Mb>|xĉS/ ? 8yELMMuuuϟ?/̙S\\lii8k,CCk׮ݺuk</##C8ÇϜ9c``0{쨨!Cdeeijj[YYٓL&{zz…RWܹs+Va' g^paeeeϞ=UUUϟ?/)k֬0`TpAIjQ*tkPmIBN:5}tSSStRtsƌ.\pB]]͛7x…~ 8P8bllljjjqq޽{={h"ƒK.566♪ܿnnnxx8B"/KWAa;GH-<r8Yf*]ɑ%YfvӿAx;d2p8uuu,08h[yy.ł}/8F+++STT/,++ܹ3ak JKKuuue_2DX,adG˗eO#TK͔$bbbV\I&\ntt .]ו%wM:nO>uYdPF6'e/ IYh[x<ׯ_UUUq@VPP}7B$p84k yyyY&TOF]}}HL%Dڄw9s̘1CP-PNAAAƶ͸q"/_۶۲/^|ӧL"uo޼QQQ5ðϟ?XŸXq) UE :]AUY$ (O!24H@h[Ah _}"~EH$\ IDATo|EuPU!"\!K ._:=S-.Bk47S͵u5999gggf))KtT)gş]tiJb哲,-T*P' cJ#^RHsZڄho/. &c+ ^l| =))i۹s-WG BuDlapXdffy;fhѢ;vLMMҋ@ ~66o#UUU9 gRO P# с <)5K.ݺu6o޼~Ç/]4..jʕ~ݻ666˖-<}MBoʥE@@)ZփU[mjmmE_m7ZC"@@m>ߏ?3lyCȑ#˗/] BHlATN6ڵk{nnn~tb߽V\i6@Jg}b.]̵E=hӢ/hs5~~t2hN#~  uŋ׮]hѢA℄e˖%''߿?&&f7^vݻ?59s;yNl۶o*~!cwBP2ܬ8tG-{а;ioJZzuM Bf Д>8~}?C =hFppAչNNNDݼy3??188!TPPPWW'L줧7770SjQQQaaa޽R{BAAA3uօ \\\Ú( oooPd2mmmuԥ@$Dl+++,M }wwLGG^zi-ӬZJJJn߾߭[sݾ}4::djdQmll޽cooMCvvv׮]+(( :͛/^薆>T͡Rii7LfffL&khhٳg``V֭P+6jL&+,,ի`>}zҖVJQN,mETlC:-z*Vz"=ё5zjj c¨͞63*ʄ%K?Yd\\wqrt\!qiu}616nL?dߚ|"3Ӳ{w?wccSvnkVEL&sK>|߬6B>^^k@E#ljjԧO|PQQqM6%''#X,ց݋:~xAAATTԐ!C֬YCUG#MַoKhf/_^*Μ9tʔ)JrܸqǏ߲eLo>l0@pq2υ [+ۇK.L&399yƍyyy#G$ 411133ZŚUTubbbprA-D&MjkkשEMLLo.\m6m5 ]vܹW[nU me5ɓ'kjjbccSSS-[9y4443p8fffݺuۿuk)-e&RMIX]v͞=͛FںuQi64D+mJϢ-*bBE(1D+BgQo!I}jts JG c } D Q7 y ~yFڮ=IGL_~Sߞ7+׭^U~} H{Ç:$$.Z8rp=sbw@3 ijj>|8A!!!!ggH|ҥKW^mllgϦ͡V,cjE<<<|\zڵkQQQ cԩ+VЖIqqULMM===It7n077G+k׮՜FSH$G@WWW=z(m]8::_)֭ш#Ԋz#GE[lѣY}ww(MVV[s޽;//Z}@ԤA;]8`rAG+RM4˦M8p`HHHddW_}ygjAiCSJu{fQieZC"zmԳFOA!c"hN!tgi)ʝ{,w?sU  י~?Ve%.'!De_ ><~|7'64z·S~xA}jMHq#JC/x%\]BEE>*ԆXS9k}?olGdЙ4}J%> !D"V"]}wΟ?omm7B=o߾=??˖-ϟ퇘={"LMM\C:t̙09F3'N~S,^!!!rܹs&&&}pww!V[]F0--MSDEݬ: C[1 A'C jW?V~Yq8'OvQtw+m򧭵{քVWcTSytuHj tt JmHsνB9C#B_5!t,Qmiiyu(В/Wd~;w{e Ià.:rB۰hRyԣʉG;:bذ7>4&RܽwWVƏutpXl yӄFJJ<>cT*ʃ}?s?3ڻɓ'޽;gΜiӦ555=uߏDӧONjsRf%ݍ,--G?fǎ 66%`0f͚xё#GJ>>}Zǽuёǣ'SlydQOXO|٠x}NW[ ]).=+c)UmH>|&1m9N UJoii53TEGVZ 1H5GG!j ?  >I,1BZ󒵕%BA,ճǟ)H=z,bphHuuMjz3f 1vQB?pޘ^1,F[i˭+6Of ڥS9ee55wBOxjY#-`f}/]CݻW7{G~&,`{{y0:#{T*j(e'Wvt钕[o5zZݙ>##C.#T*U^^^eeZa㸸8y^3޽{ݻG=qcǎUVVZZZ)(m~{i뢣 /^$kEF$WkN)b<*AB Drʕ^{G jK-UC[ٴVmH֖biA\=_?y$mGŞVTM7b""+BgtH/#1'6#c<8388/zS* BPcyבʤI]\.]),J;~"fP>}ۏ r1Ɔ ұԴk~=)iNCC>C"%HJ"Sj-?7o\.[l Y ߿?zhWWM6{14WTTdaa?iVV߿_(bٳZeibԨQgΜqss/^%zРAO>IMMJe***6o\VVfkk[SSCRaaaGVVVE+RM),,$qժU˗/ǭ-BW޽{ᆱMT)iW^y)uەVTmҼӚZD[xmEvHYVVV-$Oz"Bl6 Bd2qq=}Jkj5Wd8L 5arL`lb2ÆL&JR13f̘0aP*U)URsQtgɻwzzx4Q#FN|c}يSdқszG3>mrwj[_u7,Է`Ώ̤߭͞aEeHs^]Q>[`oGl辶Zqq>((, zB:l.B(&2)Y,Rd d[ AM*511xBЀZv.+·ODR555ݻs?ԩSxUT<1%m]t.1^TwZYYZZZjzjVV[*Z;;;mb4'k)U+WljjZtX,JL[ o߾_GMku{fQoGmZD1H !Ntc1Dy<pqJUWWV%SUf~.f, 3)Sg9䰉g$&LXϛKv==<Bݻ 9ѫ>)r!\~tis-7P>R.L}{ B(*2b,Yt374ߠ*@5P~~.?Nff}0s> :O~`X?K`8:: ^]b_@@ .G@[c1 {{{\ a|?oeX6 xjوg& (ʺBaW)Ҫjss]'2('T*LR`M`lpꚴ{9}~פ&Aill#|_/4HL&i!QK5tr@Ht@ۏ lc ]f*-b7>a 8r䈷_J]6==x&a H^`pD b`2 ;y繄۶mhk׮ݽ{xxJ n 7?4{ˇT*}>vƍ&۸q#4+!Y,bXwG0ҀBd21V(`6nݺuΝ}itt4١Ο?_VVf/_lggzڵkk배H$mll޽coo(JȨwuu Rj=33ѱW^!D<`OOOd,+??ёY#mO7F#c"[p ^Tk۷6L ?~NNN޸qc^^ȑ# .m۶m׮]kʔ)JrܸqǏ߲e]6mJNNƟZ<==MLLMPMַoKh&cXػwi{"t}8Jl-# x!]I;MPXxժU 믿bccB֭+((غu rttD#22E"QDDDEEEtt4A!!!9r$AYYYGFEE1SXB󮌌 \@WWW\.|رcl٢ٙ,mhˉ]GP`wGiR4lUj`N8C2$==͍L&{ꅿ l6[y9H$"% B(;;:t wᔴl߾}Ϟ=yyy7nxhѢEDsP(?8bA46%aुKD|@ x-iAKKKkkяٱc{ӧBߏDӧOT*>']#e@D ÌF]JMr4 P1bDii)9wt=E=8++kĉ#F}v]]>yaܧCqq1yIŝ;wycR",,,xuPFF\.GUUUTJddn5Q6Pvv6>`0Lұ E A.(JBP( 6J}}>jj]]u!SshXe2IDATD"qrrF _[n999vuuݴiAIII@ ׯ_-Μ9cgg988ٳի ͉%%%bxÆ EEE?CqqyDDך5kl3g_vWIIP(ݼy3rBp߾}&55d5ޞLVWWspww֬ĵkel?bĄ E-xC 9EJL9E\qFqpDZdzEoDÆL&JR13f̘0a`TIVPX(w\PLd y&ooooiiijj"q@;;&\޽{w8MRUUUڪڒ+ɻwZYYZZZ1yzuu5CZJe}} WcrMF}fb; =޳!T[[V%SUVV BPhaaann.|>p8bxQN.c' ppp@u]3X=Bf >|"A^d14㷕äv4E *b1H>8bF 0immm5w>xfB^D$IOo`Gj ~!ɨ <k2O/EEObİa P(L~ky>7lݾ#+=xOQT?#457o;3SӧY͛9|Xܸ%qÀI{SҫkjB66 >hhDP(Sv.B۶eAGwJ4l6Wp4Rd)~ϛkcc~V%uҗ?oݲuÿ[YZv?SR~ܸQCC&ǿ5ڲ{w˓z);7Q"7?mݶA߸.:j7yP#T*& HT0FLI})yRljjfYfffjd2Brnv^.B=?ў&馦&RIǤRT*4hˀz!a2._A-IXLmxr0,,+yNW9okkWֳפ=䟕%JVTRx/OOc 7>N@ ^]Z{4J-?;;;͙fƲ_KMH$!g˿rp嚵%% £W% D"թiR]CCtz5ja njssA o@ a| s\|\QQqiyyPBCBoOHTM%?<<`YTTf{DU3H'`& ^t##0 ZhHohhFb֌"w뾛iGN1K/74 o=ZsX򹫋]fmt\|+}߸ժտ1w͝sC'3>[@ j+-BTvNLqq\.%q܍'69u>A,Noݺ}4%eKKE%r|PdT*==b Ov`T!f/:)'KvSWW&Hza-hWWפ',txL4Bhw8>6})BmݶjQBhPHȥ'3"‡`HmeA8fA|r6^caE/#;߬]YR*$ټ~i豣#0$ԀSHssu(ʃ:_s͛Oufxc8{{;B?o۾{>Rіp\?h+CW䀐¢Z˙SooܼmG~dLLSf͙y*P_, 9 OrDDwfn윑H9C2Q(lA;XjǢO>~uȽw%ݽw߷V 7Fѳ'5Yoo/|\.w:΋E!.;.>Ow>]f#p'A7`$[w2<=?ռNffcHX945#Ad2қ!:p9ܸ)6nlx`7WWRynm- xӎ8g~ƁCLfe+ +njoo!85t c`PT&-)- 86=B;gc>}LMFDЖA=Ĵ!K.\uz_ !a >E͜=ƍ{vlҿؿ~X.K$ F z瞤=D 8|}#BMMMޝ`oRJJ_2d֌!!\5iSs!::Fj1Ҟɓl'.NC;'%o'/7ƍ; w,542|ȝ*ɡG6W!8h{ӧ>$a6 7W>J`RaޗLw9&&Ǝ2F4ˠ'rx'nT4Zr~=۫ ^Dcs1 cQh^Bx; *M\.711aX̚x `0Xڬ:c4dgH;MRJȓFPhKiiiW\r yL`0KR```zzzvv6>d2]]]hfe2Yjj*Bhƌ:IIIdUFl x<x<.pVϤa C'jZh`OH &&&---aaaԞ0rȌ޽{.P`0.^b<<БOxx'ݻGCLLifl6L#M5l{<~xLTboF( yG5 >i>n…+WHLiZ#4.>E OJ!C~S 4@gNse᠌AUgp5i jQ.RI @k# 44x5x>HSz@O zSTKX,8:zeHSsz$=b~,y2?ILBS FNijjtGNi 4mRczL6 ZIENDB`pasdoc/www/screenshots/latex_intro.png0000600000175000017500000064445713034465545020742 0ustar michalismichalisPNG  IHDRR8 pHYs+tIME  ̄tEXtCommentCreated with GIMPW IDATxw|e.ё6ݥ@PZ/*=qoT("*"F"ld{$mvr3~I.]<ۃ&Z`FS\S04RBZi%47ݞ(Iկs#`HhR,˺>tm4TOhyMF~hCkuk*c둗!n5i3A HD5ip'4R B`>SXEѭV_ȵg¿4ڸqnqL֭[VUgi\ f3]vG+GKHH(--jli$n!ބF,Kݑ<%55bvzt뚑sڵ&p+#GJp8\;~T(4'͵}x$I6My:~ڙCnë!xnWEL=i;Ԥx<ݓF gC& !&/9ьh+ӜN'AMVpsG;\ܛ;9K-y'fwK<֍v&NȈj41 #ِ&X-3:l!cS&^SWWW[[+4>/4[ncFVKs۫ÿvӳDMxOϫѿ<1Orڼb:K#wު[Qퟚ>JH98.;׍ƔWU[_A|}|juQY/fB4ju6_ 4y׫g3_ҙc ;D;go+6{(Kg?Nv5ʵϨ?wynj^qƝt;}rG*QTm iS8o8'ԟF ۼu_ڨ0CQqn޹",$8ߩWWAٴK+1׌#Ge}qY9!$KcGgrO0O/y*?_Vg;?}}ؘK8q*rD5'Ll-y5H$ XGS'_:A}ԪV@t{ʿjE裯VmecDS_o޹[RvM+,)[~ɼ0 `I54|Iy%n/G>TTiɼy=q\c5>Pg,t$DG~];kU[:y~5Srji5ZәlHs.,WXǶzOEE3 sg*k! 7ܭVLZ鑹/PVHn*rQ2CY$%F2gdX_a:!P />p(*"i!A߭;鷐ԤU!uԤQ[Ov0Crr!RCt6{''7ҧGjp`fӨٰe[N^~@۳{P,aDQJKI+,Yݻ&>$__-v5Qg- kcp8׭$Ij{rϜ<\stdxmrͷ⢣M&S (B[7$IDa%I~]FVS[wݲkO9}z>нM,K8V]up| Ju/W$W3miҾd9Vj,K/  9 <%)>r4dEuMXpkvJNL >]R^%W~i !# ޼cH$RXRm7f${z_~DymlFMSxȰ͞51ooBHc wAv~vx]JBBNgJb{Hr "x }ޛ[TڿWOZc&ޘiА']1w: !vS\tƿ/-@h pZ),$O 7h$0 #ߓq08H7o뮺RBHc4Vh }p&h4{ǏWym%!DRqDz($) JSRT*tYDXEpHR 0( @'VTs!d˜Nͻo,+IXRT*8<~:~NtZGR& ڛn r8j娈ۦNk>{bi4^B#"\! 9 .: $tjbka$@ i:5IB ii,l~f$Ihvap8vjX,fd2L޽{& ]Cرcxf2 ^5iDQE֘>9 ݰ4E5r8/8r G 49!'Vjyir0C[Gp:PHk#*CH!@! 7tCqp-}$IeeeeodDddx$0>΍- e  ?enk |BYE/C3jCi=%E鼴rs׸n;s!@RVQVYU Ѕh((X9vw?64sSNoO((2xUv螺P=fH隲c䀀\T].:2FNd7st+XEjf^JyEyxHxPPBhIjjj+;l9~8Iz1tN3 qq}֭ >jT*᥷K=RVksZaIύ l>zoeСXP|)Z+Xa !rsEAի<5!!' ռtCӅ|!E;^u0C} +pòB.tGILgY6Ѵ=&R^sGfpn4;e?B3C:`#k~^+IRtTӧswܝAӫ!~ju pQC:\M! j7鯭 -)(CՕ@s.\pC:ZLHcY133FY >"i ;5:G(>.rHm-~oUTv  T^**+W|;Z:$֛n  /ChrȓO?kzZ]iQy䉙 üd2ۖc׹4w( ndqiɎݻuy;y5Ҳ]{vWT_l5v}?#k׵[wK}n^[U]m4ymwݳg^^JNPӭ6[s[TNtX*ۿ~>1-否kϞ;{LŜrNEtڽP&Mn~S/'˓o 's"#t`:e%n)qq^d/.)ya%#]Z,֣Ǐkx&'Aŭ;Fuد?!Kd_N>dXbn m]FQQkjw5$#CR{c˟7bdrQ%+jמ=swDFz2_yy~XV}햕x񁃇NgLL>0|P2ů/;~"|;&^5KRRZw=pf٣o߷oc{QXT|]w_;e}w߅Z䭷_sD_YeWWW= oCdR*㚚f̘9ŋOkKsGIrN|hQQf2c%%UUkzat5n]N^ 3'f̥4Hז }~yy ^J{ Z*,4M8_ mw5aa:_Eds:w#~2nKsADGETF8t5h܊ݐ7r0K_]X?V5\윜Ǟګ?B)M<1]uzoJu.\USw:}{م/-/r i W0>MAQav<8!䒡ÕJ%!$k;>1|?e4sNt}nt#ǎC+9GVT*3 -]鍜5k߄[omni=;w>P eliDxOk!-w:^T. W^1-}ÕJYuFOu)!$!!~_[_?5]yÏ!{7@%r w{~>p}:+_|yo7L埮88-5eWWQQo&OJXLW2'NirHc.zǟSPX8wyۃ!m?xǧ;nyBϏW~VRZ7-Vk}s*>pTYU3 ~ʪTƒE=RSy|ŠJB=RS-^&M4$iLjj |&4$DKY[WGiݞX]So ?__m jgY C>C>RҺt{J j_ .{GgZА&LU'T*cfyv.!41!՗ЄʛkYc+dJ?_i'ܴDW#Ам|bDQi R !}AVnIݶڱuȈaFSYE!a !b95j ݅#܅A%HN5V!v,r N~E868+cP/}s:o%dBsGP5OBVu}Jxx!lЉ߭^ST\\^^t:šmhr-Cw?K/e?l!( BԬO͚)Is_t:Ι$H];WW^^Fʑ&))-\R)U*k $̜tI3DQ}{))SR^ރݻȞ:eV=W O).)ٽwOĤF;jL^Ehl %a@~A:ݰ:7?/B4$I\i=n6/⫷uCu[wnxsDr^g2DV{pnnfm//Z_Pt: ^Yd_[Y嗟p!% ^:ubIi)!;=9[꛵3?<Xg%=>¿vժVkRSR@H۰a݆=̯׏rŒO VS5\5)$8֡5?yZߝN$I|P쭷h t9}<1SEB Zq#!DGG=X|Ms$&$`JR).xY^o"h6':sʂ͚0/rG_g+*M]מV!Nn'stSR qu=ҞW_^YѧWoyZD 4X>EU)UUUtu7|-$%NK#8y'9B䔙3veݾ{fm߽l>i$i56g//ZiMYEq^PjNsh4YG\;e?_yn]dʞݻ?x߽t֔I8槟| ]J i={ڙuQ[&%Ƀd N९>[_yE// 7uuV$ے5en5WOBfu i--41QQ^2GuO?BǍ%~Ê/dqc6[tTTk(;>/~sN:āk]+tK-dGs΄h^%á7ۏ?dIW_E['V|Fkxsb|—^G1t9!L{w/~}Yف %I3ҍl鍕CWRZեˡ,BH^JJKKJK޷oЀm ir:n[Vb6M&d޽{+-'6\٢`Ɵ?s'0, +yv6t#Ǐ80$@8h.k!dQ]Ȭ6#Y'r !!!<}N8.[rJf|&l1DwPCgܳvuڀI`f?;dނ|m/C|нrBiH _Y?!1!ͥKff҅ff~zYVd+^2~N>3$~՗)w?ϝ6ڦPVև#uD[q5&-#}T׿E{c{owBuMJzvΓaanaW^|bE a\3FsGW9Br(mr9cy)Zg6xͧ7$IJINTki-K/P!M3\.UjuOkzw5i6f(c/2}:,,qAsQgIFֿ7.y _U9C~¼fv>gX8nx&}4 {˅ jma4;KO-FcK80? ma0:r9|~q.;;;>>lt5ZdDdYyY6{7*Vk7scx:tĮ?y;TT7(,.\9h45+*+<~heСDFD=-r@+';r9~8Q9NMM=DJKm67Ea7VhDt  xQ/#t(87NuskEСlpC:`EbXZZc} FFF ltFm@\99,WLpi(VTT#+++44}Y> lv^T pIh9X,8--7/e=zbEQ ynժR{HS 4BQWWWUUh\JÁJT*呢"##I3FHLHR*EaȲl\\he ֿO'vDju= !JepKJJhҠS8v؈!#\抢t:FcMMMff&xINN?q Di,6p8***zCZ35%kbG/sn}zLy ^!9uhKs[uDz5p֡V_ɿax50@}rsGZ[@o]iAbq8Vfl6Zp89ubANg8lDk]]}@VG4#kE+'\zɈ' !}{~ZBbyÏ T(A:}f[߷7tFxn+o>X#?隫?9yRI3g<=5Gh4պpkcF Nh4m4f05-j w(x<=1DI7ZVjXfl޽{֕sԤk37/oo|wOwݸG| }@ް7).O͉믟'%2R^/\yxW ϞW š,}o"3K^s|b@~yzeYe%Q"Dj˪h֧ѻD$P*[rr|}}}|||||T*JR*\VV sA3lĄ=T*U}0xg 4iB+ {3 !G]ֺ&7&n Z{l}tVKӚZd3>Vմw|BHZtB>]%GϒR:w{n1vh!QQS&M;ww٘W]9EOyYJh6m:ӻS s׎ڱ;::vi:|o[6ي&פѴF?:xvP(hģ^oFCÇϢCTs/gϳEp'bc_Ryy|ħOj~3;9mן;fי~q$42Rm٣{Z+VH/)mZ =z:fGx&-:*j?E۷6./W_K4h'9yjAI tRpw/m߹+gNWXTpؓq~tSL?qƌu+t\Ll8UރәB$IO?9so}WX_^QAg~񀀀oV}/Yק##"^쬧~ׯ2V~%=~8?.Z Iq4?qpy̘178NP85jUTAT* ,ø80LUUUNT*yEQVHaYVTH{P1֚АZ޶k!dqOZFOT]]#^rĉRڻ$Iy#%TPPy#!nΕ3EVN;CgI$?um('Iު"g3|m W,t:Ahᨭoϝi5J _l]렃Gvmr"2x2I`ڇ\{&\EHqlKZzkA}}m٪4QMBP),z jlB[YiUMht^4Op4 Krure ҠNV:@K*@HN=Л5=iJEAhAO^_PXd|4ؘtq|^rHuh88U,* B!zZ ?a2A0G_9jot+64h=9Ek}ZaQEͯL{1zѣG7mp8\g,^d\Ɣ8x`lt:J<~&@ch݀ͣ,춰biـB痖6eFCgT*wcahGԤɷ"[=AjU$_t!}3p衃49j4<;;@kՙ\s۷oZ{III!aaa8Z8$) I6U*qj#`0B􁏏;Z}6\)^4QxCϺM!{n_fYFfv}EI"5q,Q* YS0 yR0JcrCHWgx_+T̐;OVl??\upvelU }jRQ~:hx y$箊zl\:x럳 e'0ye­#TvHkNS6BZYõδ H] ͽ<-MQB12UQcoe6BHj澑] ɭanN88dB_uӦW~)udbU~jlGW`.?+o_gH2?>pub` nF>0*|DV`*372!,*]#ήӦ-KR*{=G$k/I.Z_VBz!ѳý4pV LhjԹs&4! $Oտ[zBHM|guaCQ}Iسn负Z䘂Ǽ5łDztٶ{FJ~@%ЗodVsV֡צ=dn[+#5"^_9\d({jԮ˪-ssXR&UNp.NۚcpۆG/bcʀ'Dݷ"l}Y*ğ[!WCm;i$E+ڧÆ`?J?{jsg iS~,+ߓRh IsiͩCҩ~|8Ys)ՄO3[RzҀ`Nͱ%[X8\lu 3Jsc{ٯBj5f`?nߏoS!(kӃ۫[+{OŮ6o!Ci󪾺k_-͞S&V[Ps*=T:_EmP^ߦ ڇWGj'8enp]|s=~ Bإ={Ls}<@{rƵ+;B[V9ށih_쪶b/s՞bry1aZ.6XEQzO W 烆 &+m`؏#-tz N{ϊjB!a hgZF i4Q ]X{6Q2/OI S=d8Ph;2UKyϊ꫻~֖5ƻIid(I7y]T+W(2%fLݹVۢ60m'J^w}fQc ??!HaZޑᇊ,?;ڎ"A3;@`F׃!5],4'5&5R+-lZUvUNm{Wyi`BdWOU+OK.* =Kw?A$XB%IHSEPXc'؝/kGφHVr u݂$KR -+%3F,P*.9vǏU4ID h'"쾮b2BHX߬bK\^gzOd$+Z c c) VP%GO6'r: IDATRVkz߲ji:qtU SuڤT0,.Fw$+(ل`Ր&ACӫ=]i?ΗIh?pM6l1N$T0]{-*ipO-\3Prf_Ket#>8ʞ3.;Ou &f|Un#_]e &4eN㽋wH˯v|!!#S)2Loc{\?8""/ >=],qil򭕕F縴qi[+WϺwdAAtsͮ!G8eOǩ6hmUt&VMNZ0)[eϫnmxsc&Nt`Q"EzGVUj|I$]MWMRc厪3}(B9NB &ğ;*B9RLN9}x|Z/Dĥ;T/=ڤc!pƌ !!"w5%m;v֟;lH&}pa,k!dqntL|pӱDQ$IT2 SVV̒ t:]@@VQv]4ݛI,pA^h5W(mh'`x;:6n(iz} Q#^%$I<ϫT*B˲c!NJnH+}( hlCH'=)@.hrovpȽ{MWr⮽;"ܮT@D5Z +^M.sJqiiprZ_$&Ζ9QyqGSW;vϕ$ɭ}T@;Eѭ qd+y()-H8y,+ߦI{W(8,QAQ|}ݧ!VV4DKJ% iq1n ן ydw׻6ѵ#OaXu!-((gTB߳G +kkkqM~isG h"(zR@PPPPPPVΚL&bhoFBuh(҂gKh8BxṲQ#Y~<8Btnrw|ڍ;DM! ."ZuFt:8,J%L#g[xyp,(48 :t qOost2 ֻc[ wnc#q`@@LLm78~ضYCN498Η}l֛C23lgmm;гGA=nBh;kގj(PlH{M!$@põ{뚩> DQ4jJ߿~lhjp8NA4 SrDvh0Q q[ 5z}hHϳG+pɧU* =O['z$H,zCFxܤKnuA4W 4 ^zuV+!$.6vi={FӦL>z؉p֑K^;v )ݞ^iiEQ9tec-)-% ْZB {ϾfM~\3ϳo}݆ =pפ$OtARШp8h:8U)H=DQ0dǎtuNw=w'%&.~}ٌO_}ʖl̴)5M]LJL|{ CU б'MܧwSOWx !~׷+s*,|o>tg/ r4p*9H+(,mK/%<+?*$$2b͐nZ&%_R N eOVBȠ"QBHUu_sM7+-5?y] !A?>פti=zskV}hXJ֍qy}~Iϝ덆((h}:@;}(imuj]{ 0߭nŬ#G6oAAAyvEƎt7  (***.)i)|={騨._9m+ߊF/d &I\=pw/뚔C{[7ґEō-ǟh9=@/h| Zk~h¢|kؐ! i ^>J%0<>^جzU1-<~p.z_S^o2|||cjͪoj>uAAAuhivq1?c0 P(hGC}54z*(@bEATAS@,g9=ذ ""(M:lc7)}?&N6aޝwe[O^MMMMM:e]ZZZE =• ȴ,8 r")quԎ=H>ELL6m ?.'ObiH<&Jq3DhB5ҘzLF'EEffiM@Hȣ44lӰAډᐯ $ Nb é#IZVTni@X,H$br]a h ܀FA < EJ\.l˫ |ߊ(E H@6Tqj@pCáA(5q=>dw %tzEQyzAhR)EQ= Ȼ ppvGzEFtuu455|"tw =#4j ppERw] 8?yH qpUP@CEZpSAO"7ݠwF2|/bWGɈ<֋ M Gf3WC(feeQ~Π= |<^dvxm.\C454s7wngHQH-\Џ&1q폟>H$*S'{wgdv3 q>d82Tk]vceYYٓ?|#\9Nbtaa+5-mԶYbځ[akĄ/{3Y)Y~ {N?ӫgP( E5gqI"!mhR.GI$>r|ib2 QpQ@mF5UUPFFFtLLii#;ww;!=T*%vbw |>%nI!BׯY%Jτ {߬<ƻs\ܹ9.D+K[6ڶ__Wq32B]ͷnܠGQB(++kԨVaQcDQq1EQj+fڵ7k%DQfb19 š! f{{NZnF 4\Y3왾goF^`>EؽP`Ш.&ڻ/9%e͊x;w⬤T^yܱC563!eNMn޹S;kAÇ O1cGDFm61xD"G@yBq8\\.c6jSAxyLM/cnFmo{'fee>2|ȐE!9eه<Ə716B},MV' ZX!sr 0nqcBΝO{c./^mkmHG&fŠQ@\GQi0 kL'Zޱe0/wwe%ohmzWwTRR ׯbqN:g{Mx҅<|h=]l6˥9̖ W89^`Y_5m;[6D .WX-%lNOA("( 3/-=}S<'7VEEL0aXނ6 7tbWB!BgM6[QQ#:M[B=~3%$E5nܘ֭ǰv57 ڶkwFJKKqj~PGwn޺؉,6i+.#lX,Z\3\Y3bH$ B)S Ri~AH$jהDR5qwaaٓcne+~/U_SDn5G?$Y \kkk(y ' |>v$#n>\ͣ_EKEҴ4------MMMuuu>gb454~1pl--℄mcw^b6br!6 q}11m۴),,f70MHE7 \dK;v% ]L,Vf=Ԏ@p:TmllCH-Z0-- JgD*r\233]fddԻwoOOOcccX,|88h@  aXwCC &jkkO8qΝ6l߿ݻw[n㓗7MIIv|RO3''G 4O$::zpq?*m޼ys?x"8h(p3=p3`ٳgpGh%KWXd۷KJJ/]!ԿׯD!!!cƌ) ܹ@Q]N~*@2zu ɓb1,, s8<#_ ҤcҘ8i$\[nݝ;wiiiԩSV3n@}@&\(b@4.fԁԎ s玷7^9s_+khh8q} 4Pddd=-Z=Z[[UVpq:a6#i=qciuGQN)W\MLMM'Lp}z{xݺu֭\@g!# hd[SGgϞ}%^9rZuhڢEbbbC@ W> QKX,/(Ԅ?Paå( x$w2 r^bիyӧ޽300رyD7nxӧObE6668?˗ ǎkddr[jeooAߪ,..nǎW zQŋ߿(UVmڴݻ7Ǔ(..믿BϞ={.srrׇk 4DيhnF<26V"((Z8>lo@&1q폟>H$*S'{wgrb1%KRHRw7n m۶V o߾bԗ/_|}}{著xbkHH}wرƍ333SSSYlEQ֭kѢYyԨQaf.\xծ]6mݻ~~~˖-SRR«>}zڴi7ݷo_@@^vrr ҞFsCU=XL OX˗/FS20W"~),,P( E5=nB"|C m6߯gw! JK˘nF3. )CEH:ڵk===D:R9sFfe/ ޽BqqqN]]̬q ,YB~@x<ށp'ɇΝ;G&X,Vpp yi֬YZӧOxR֭[}JKO5Ef8 ҕ?}bA!!s;uROW!W'%'YppLUor~}\]MMߧxoز.̞{&,f |==]Ў{9aB\|SR֬XۂB3vmp^&rc:; q6mb:hiix ۲s2 6HMQuҥKwB^I{X|//o{9@;ׯ_WۦX@}Ff35 -+;! n{W{7{7͟7#BhkoD? !dei9qBE@`pl\Bnj*6٣Y-fJ Gak":fvttBYYY 2dy~}l Mdv^ZZjbl\AAe_r"╫ٶ֍tF e YZZT&&&_jժU-&99ƍ999999o޼IћjrllLB(../|=P60c-B> ի-[BIoB8IN;RRR 5!DI$gŸ>3pU\RPc%5yP`Ы85703D 8յiS_ 9c3pRTT >zl]wY0w#(~835dEEE :N2ۻq_5J[RR}9$44?*jP($?::: 3ͮ,a#} ~&w'oAQ˖"okjhplڳ 04$[2fP[M(}F|BhבV>rze;E94hX6dS!O=qr󺵽z.ٴ۶Ϙ:eIƇ2 Yt2 eM4i8tҪU}.59`!g7_fje… ={QVV!###wO w GI$ϓq9%%s-{JB#\]ɿΝ:Uo26ٿ1N[Ӻ$ Iݦuk6 Y!cPӁmrsC 7!-B$C%%'Z[1{u]IBOO?ї/_V|>_~u|9sm$BCuELw^"hĈ_hxVrf '6{߶:ؿ<1cX7:X,++H&QvXM|>Bѓ'],,τ#/#koNMUաwon!Gǿys8QO^ݾ{SZZZRS2_M]5557m۞Ç m< z^G<1pݢE^򊊊jٲe{nٲe+W{+WA4C}v$?IM@  8m4ROP ,^WxbtIRcYw  ~Qs::],̗i+E (flѢy;&&3}fڻʵ몪}ۮӰ._{'hOS]ݰ_hn>֭?aQY[u=pwܼu'YlvkV>3\F81x풛!е.744tW\snN:Eڔd<{eȐ!3f̨[|8dzX,osРAnnnǏ6lXdoҥK?~سgOl_lS$0T(J,D"P( ˾2e[}(J"Ҫ"Y6)**1gpT*򥨨ILMܠo3H*NeF|-ѯ[K!ގl6H$$;;~8!H6o޼jժ|P߾}'NأGCCCӧ;v\|y+V?QQQ7A秫kii5k O>8p 9zX,VVV>uӧOp8˗/o׮]>}444B-[TTTwidd$Joݺz1cȜK &H"##5j쬯!@ :ujPPBh֬Y͛7GEGG_>""̙3$+W(ӂYC***}GPPPp$q߿?^nժU&>pN_'H_o~-IҴ455|l{X~}H$HTTTekk ˠ?zϟb:ttacdd$%YD"ѐ!C<8uTrl<ӧW(,,UVVZjՠA._x⤤6رC lݺ}%//Yfs̩fXXˣBNNN{'"""o~͢"njzj2B |RZ˖-I*СaٜhLŸj*P&11瓚 X͡ ҸPĠi#Yd>gΜ9s攔檪6k֬Ce\qFe;wlU$kȃw{;g``PkXF5j?\nqwGO'V0h( @AN+MPE }mU2 8qI @oM6D"!tռ<;;;H g'24ФR)s!44T$r\D'N4n4ȵ 4D"aXeNy'zFÅs<2x0C m6"222cbJK9pF4;P@NH70Ƿ5Y`ޛWVφ?˘HΣp?I:YZs1B+lz0`}5ӪUO;ױb_k;(*.(!$.^b֮]{v{GfPYT>Iv^/;wt歃ծo2ؽP`Ш.&ڻ/9%e͊g y{|>_OO!tOXaPHȜyN062ڵu y=$C\'b䘱N#"#y\M b1iFGS*dr3_4-]v"$XQAz*'Nn^WpyOZzmgL2~X̤ _y Tfl6EQ&?j,K,3،d ^t9giݚf?zD։z! !A◌BJJJ._Nfmۮ\P%%` ϩиqcLRrrZzoD3rZw % n:OuuE|gg4i>-8䨒Rs7oqqr262B#koNMUաw~}Y,P$F (}^ޥ exC ?ݺvܴm{jZ/\d]D"r$01i@p25: B=:; ?~<3קn/47q_miKܽweCotџAGB `-[bnb gmmdo߽sNd٭M[pl3i!J9D"( @~S v.ߟ(X,BP(,jʔ)nnn 2H&J_5iXYY.lׯ_ʿkΘWݭ!ގdk@ ())ζrp-ysu6~-IҴ455|",5?( w&d9PO4/}@CE0bX8iWsP%l6=}#oIBAElܲpxMHt0;U/iJby<ؔ438NC05?n&3U/J,!4% Ţ H)qFCK7p.B#0fGm lNJPĠik{>5㝹: /s\6gN4 oIB5fВ02;NǏF lT43jl6b2;L֌x 4 1(=}l6!Oz/M&6a3 y CXlkia=84ČaL+<1nj4w"H$H$8#37܁2ؘ& OΔywߙT!EQ,V:>ɳqInܨO2ղ{־˘[w̒GU'Kn=zc$7m^K0t0Z@Up88<ΐ|P 71[u C?HGյxyQUPPq+rޟYϱoMV$N4 !TVV.5x詰vmL'z5@ u e+3L]F8 KW,XĨQkV'0$iO&~bB>@MQ̫|>>A,ggg6iDUU y կBH --=6fa5=+w3//HH aZ) BQR竻rS't$I^^>USSD"Ojk!'M?~:)fe'}~+i7jii՟ߜ9]l۴Æ 2%F4/ H_~++**jkkv^CC>ڑ#Gv]TTT\\ۭ֭[ǔ{g>{\͛7:tB($$Ç7 ~ӹs_~ݬﻡlffֿA'4iRllM`` id^6o6fܩӡbK\.u䨚Fh>mamۯC쫸.[7nPWSeam;y_ 8vKJNF9 ~ͪ*va55BWrzii)BȰyVkzjM)jmj?+k(3164q={oF4T*=~:,]j~f;D}=UTT`׫熿T]<<`Ksshk\UxE9v|ߴt==Q#]Ǝ57\~C 6[`~?½}nnr9Gb i~jԱ'[@@j첲2رcW\W?O0)))''m!}DDĘ1cgΜٮ];MM7o޽{Æ DJffwUVV)9yͺ g̠0{𛑷/t+ɦ( XEEE"oǽ~=nhS7l?wK 062ڵu yS۹gу߱{ϡQ#]<'Lߵw_rJʚBm?}6l$], Q5}]SQVnkxk +;w"m{7lޒ7c:BhՏ>YtI Cà9懝:c!ӗ/_JKK5jl! Dr(zuxsx޽{2+S޽%%%} (\]]|HD~|CT1i8BsPW ظ8zھy]ec-miaiSB3gL'O'$9z,++LPVZZjbl\AAeתPGG!u8!Cؗ͟f ?N3M\7oRTTT/_*j!N|;9qBAA7͟7#BhkoD?^ݺ)*(,Yrؐ!JJRS#nBXucCD"Iӵk׀-[.]!?dȐc622j.&L 6mzС5jvZ ѣGY?={v̘1"!dccs {+((XM6 6~:,,GiZ IDATyxM~?ԩ~ PJ!8N;~7#4-E*E~OBa-N@G[{dE%E=]]f Dr6,> K[h1fSF 4pkӦU*((@ikk'$J$[k򒭵WqqzzzEuԱ|6}Y^470X66Q'8I_S}vn߽|F::::vd`x}zj-.++:uǏ6=AUdԨQ{+yq֤I7ÇvB]xq…6leK8qӧOZ:t\Q咔u8#ߐ3lb̍ۤIAA̓LF- ɋEo.Ν߇&%M8i9U_Oikk>y˗:taE8pY5A݉bWWW2̙34iͭ/^lܸ_~l!33SWW~,ё(EwYN¶I|&M- qY3gLwv޺4kv%N*))W3 hӷO6[QȫQ#:!=^c+(({<>~5V?|[6762F)))8;u"L$C.ϙ,SWWw҄fC@d}^/Tpݪ׷W;pMVN.Yczzz~8 ! 0`ݻ?)^W^s9|ȐƍgeexQAAa!|X{vj{Wg+ ѓ'],,τǾzuN;hiiKMLh p2 5-Rt******c݂C*))u17p''c##P{c'CUTT{ EEubq&<\RymA7nFCO@Q*0goF~hղǰAA,J(ƿIncXYYۡaÅ%//++NTVR>g2Ar"Li ?b(ݻw&N.""k׮%pС'NQQQp\b̎۷Oۤv9n[+ktv t{]F89T﯒Lrj{;Ҧ~C!emՍ#7˪p5HIOp߬~uOS]ݰ_hn53NJ%oܫG],nX~v^Ҵ?3z̥W8 Cjd={t/]zБlv-XI޷.Ge=ҲUB**NçMVctzV2;~p'AQTRRRjjjqqF- Ͽ\/^婪6mڴm۶l6;55U*lٲ 233)ש$PJJJ㳲D"Q&MZjU5BH(&$$dffiӦց=/׋/OnjjZPW dΝ;ˬ :m۶v%HJKK255UQQϿ}VYYr4''۷<iӦڵfZ_uJJJz5yheeUm;}]xQ~AZ c_]EU2N?tCOޖ-[|}}ɓ'O0a̘1NNN ?v옴!+,,Ly7$;']jjII o'Rҿq?X,صۊ5W2>}'333 +{(Woܾs7;PXjq_8Pyi_?u9+++o޼y0^5޽{kRE;YZZJ^MNNvuu8<5X,VǎnZVVV!((ܜᘘvQEEyGp83f̨p3fԤvEeggW7… P=&eaagϞʎ{~/ƫ2rZ|"ƻu6k֬׭['sPCC7G݉u,7˗E]533s#E* :ԵkWM4***))) ^uUro+CKf+((|>foܸAɖ-[\2WUUx-uAsd /\ suUX\?/_2cX7np8ꪪgǎdcƌx******\.wϞ=_ABBǏ333srrǎ[v}BCC_իO>}jjj-[RX,mr > Xf kܸ1Д(WmZճG-ϝK]X w}2\ !vZxkkk{ԩlܘvmwǏw;s̉'lݻwo߾~tttNNӧ)*(|׮][lyP(铟ߪUllly: :thDDGbbbnn. ^n]\\ޱcW^U@ ٳgxxv``bqYY… KJJN>mcc[#Ǐl2jԨ͛N4 W|?ASSSGGV;ʗI&⭭dzU̚5VBzjРA$z455[n^^^O>NOOsQQ7n| 7oCMMoq`dBHMMYfjiiϚ5ːM !ԹsgWWW|u...ֵ.}^~ڵkWuY\tttf͚# 񁕖zyy͞=O2ߟz<`777%%WW_~I0%gR-iYYYdǏВCZ^|iL<9{lDB^%ciBzo{RWsA {_ݻwдio~gffhvv62֒vEAC N? #!4Gٳgϲe;u'2008yƍ74h2ƍˏ=U5DK$˫||9{_ll,BHWWwWիא!CB...2*;vt^^|92~\1rQQQߜ]v' ~ bɤ,͛7/_iӦ_Qdٿ[]ÇxWN0!rʺ\uՔCXј2+L4kעiiiϧB c]xUL:,O2ܺu$"""pu lK;!!p8Ope 4&L>}5kbbb:w{, Q"} +Vx$UW}!שo1^d堡"f+AR49QUUϟ={gϞCVXp8o߾577ywdZn=ڤIN:AAdڪUHKmڴݸPr OPISs޹sӧOxؘ~vXo^"\ץKrssܹd{{[Ҵ ʃ9iQSS[f͙3g`+ӧOW}I~ż>[5X>wH]^g̘AǏ_|ٳ0k]P5rTsaSL0J 蟅P( Q'HQ]ƍ===2EQxaF c]R:A\;v/߾};!!t ͥGaaaYYYޒ_e& M Yll6߽I ?Ϸ0553fƍ_xQ&׮]I,Y‚:USFFYݫ1TyeddЏ|fccgϞk׮~Pl+Rzf%K*BOOF>ޭ#oV+ٳg^ll+W|||d.~u9HyX&MH␐o>mmKvܤ{%[ݻyk\4t\.tL&}T*:{ĉȫz(M$񃝝)!!!//Lo"#y̧s娨(2yO!dooO ϟ?/[sUrԮHoGGG0aBAAӧO\bkkkllLRSSm/-- /,,|A\\\Ϟ=IL&sʔ)/^ȸ~Jyї_~^z*RCq544$%%sν~ZGGBx"::zƌ^xbnݚ:aaayyyNNNGٽ{w\\\MMMYYYMMMeeerr/2Z .>IZXAөSsBggg--K.^BuԦMV\IYuM #G:99=~,++رcƺA\|yѢE{  .=[ ݺu;~8^N/(kю-)$BΝ;?sLLLRR  \nLLE [[HѣRLvzZ:~II {!žB!v{Un/!dX,d2  hhK.]pahh̙3L!V&#GG^=}tGN=}ҒR.[PPumjK&N3L---]]]]]]mmmE P=A@pq___ N1cFVVX,.));wy ʕ+bqhhݍ7gggr233?~ZZLuttQ> IRD&M<!si|4RSSΝkii)yՊ+\nZgP,?zhΜ9rڵkW}}ZXe˖1H$wohL&fiii1 *:mڴijj% Lc-Ѻ IDATO<9fAիի߾}ۼC4IP-ip3mmm===]]]MMM R^^ޒȂQǎ+*5k/3\.B\nqq1MSgOGDDl߾СCQQQ111wMMM}ջw)˗/dzg|>x̛7oԩ`( u;nGrj'oIB#;A<T~xEEE%%%l6Vr0*Rmmmr'[yyyAA344Re@ /--Դ˖޿A~?POn""ݻw̬ђK"\H$255555mrnݺIzYYYeeeI\ZRAHTVVrkjj,,,HիWUUUaiIIIqqq}}\7\-׺uwqz###ccݻK6t E ٪u255ZH˗/;uԪ 6?^N(JQQ*'&\}}}KGGfkjjX,D`O!IzA^  kkkIʑO&Hlmmhii3$@EP(333333ȐtZ YGGGG۠AI!ZO-REU5k 05%5FA}Bj] xy5^!':|KI.\{/wEEo|?WqAWcc՘mmRT v; T9^N;{@ XYjI'Yf>@] 4)Lc# S@P]]-EQ|-ihh|Ŋ?ځ.;!0MY(D"ݓ"4U>ƑĎni3iSR͚2xAMK귮9o|bm'fbYYg'jmebJF#B?5@ix#c!hIh1nOTgJ>u雭>زiq [(>ENOWW]YH~7f `; uOmӦM{ehڷo^~=77=Լ3ι__ «֬7g1o *7>Ip8o2o\rsFici@@9g@Ɠ9h_P( <}۷o-,,HI#Kk+)"޾sw)AAflcOE!'о_*2RGdghhI]Y@ ?9?{v⇴jkktR^^˴6IUUT`ee%>B[rȨ#OECV66]]tVSѷO¿sr 9S]F_ H0!N3;wŚ8qIUϱCVv|2m~~Vvc7276{ ;q!ı LfP`_޽>9Eū֭755 95: A4 ;# hUHXSrGX>oeef͙}!s?KCC#tV0B(%55!Vo^߼ih lFz;~Bnn rPX^Q$&%E9bbԛ@ P(>.6\ FJPf+**f̘Z]]ݖ[zLML~?E&&.K-466.\>|4 e8|ӆ:::O>FD'[[})_6!?~ZZb@ÎC` hm$ǜxMrŋoݺ511#???>>-khaa7[^٣G̥ccImm֭]f55mOwn{eccmiaA[oPT " Iz1'ބҶoߎzuVVxrR T@[`o`oz BXLR@@PT,(PFk;F ^%>4\(rA@tBa sJ`& >~!@ Aa40Ҁe&Cxi@ ]; ƟQu{Ҁ ^(Q,c_ЪP$-Þ4pn ȅ EH#"PTXL|ѻ#zH$v8ik rV ZH$9:UF3ˤwGIZņ @@Zhj0# ؐNOtHש8(Ex<^C6Av5ҥK FaaK^|u 8}򕩓'Y?7o.[ꫯܻAuuLt, dД4Wv;wB`͛]N#`!u~ rDqvB  ;wsСC۸bBdiC/>_*Y%!CFy{߹{/3+]?&7ø4kU>tHIBBoYCFx/bpoێ;UTV8zp9py b OIJ&O"&k++UZVAiiZG C\ ƙ4[nNj㊽}<ȃ!u{pOE]o%%UWWEmfkbRҖM#Oi58[rc Fy{D7q7Bq aMMQ@G!DP*//U/5ɥ06r uzw 5kU׭ !dbl,{!TZV`oߵK翯\Rt`«aޜ <6BybF(֧qf-K / !ݸbI%7>zW_orsWZ\Åx A=FZtt?6BHnI)BB}Q]]}֭>tzVN6B'N?qByoʕ$(J Q^wݯy{kkv BKHq Çy2 PSȳϗZvrRWg@}"HNՕ8gϞ)))mƔQ$xN ^3={/_ʱ|Ɂ66]]tD(Q'#NLu޽{קO͛]eUȑJۧo99Sg̜- Dxzl(H:tѣ\Swٻg˗JHL2`=B`Xk+]q ǎb2Aiʝd$RC՘'sf#۱'=]=]uST\jzSSӐ3Z3P(Ğ<h=H {T$m߾}BP ތigd8`0Rc_uv&28߱7o*))Y/pHaOP(7͍cInF)H(]:S(aO Fz@>]?\6q?(E(WTp%IIgΰ#X,u-T*LFZlCuizT7CNG74X[Y.^0IZdkkHRܴaᇏֹo_EMA%a#BĤw^ϟ_G\o"45/7W[KK0΀{i@^ER|rr&x̛7oԩ\:Bk?'ŋbkK )O-Iw^ps?S=\<>ļ9Æ@@@D"ϯ)--uuuDVVb2!*\.WۓS|qnndX / iL9Ԉie8hu3J%v8 tPV< @)ylZ!@@D3i@kC gjFЁ3B!oTShGiX >}\Hi Z>!y.iwGIghQaީbX  z H:0epH`2 hUx*/i 1>w Y4 ;BBM< `4 (T0kWp4?đbaC(`4̤4K Z v$,? zWrx?B{:wN_ndgߵK';X,hN#OND555CBBJJJ._3igϟٳ?_PES$UTT4mmm[|P(d2R( *oU}BHx<_.Ee@e2T*MSTUNhhh|Ŋ?ځ2w7bIJ^r&xZxki"gmlk:rj*_ovjL]]Bz[ztz} Phߵ˦ {$n;6xff֮$M}׈ԴBs߾?ܡ<5K1Q?lVn Ϡ̬,>~4qUЮHXVVIdmebJ7 % fV >O!(A@mFZϞ=SRR***~6{pէ>Λ˱ܱ+W\h1nOTgJJKBUUrBz-6_zgϰيNzffP`S9/_n~o'N,[˖/׮aff`fjxk׈&ikc[ILP SErhoikkB-//UW^Zw@ۊP('鳳lv/4ȪRu% $Yo j=:N.#=:tUƌs6nj3zEӧ p3ob.-̱sw2!(jly|Fz;vs7gv{Me37yD3SӔ4 wBhP}'2x/O?naeׁ:uR$2446~;;[ \%}[eb-_bw}7ylݺuӦMƍ[bELLڵkeoܵkWll4)$J :ю~-UUD=zl6j!&nFoHGV]:+k׮gʕD͒,Yҭ[П~\zx"͛7uTxD)qL$Q@۷oP(|>kL"qDž^zz_IAQgo߹;f ss3lcOE!}(~a2<O%Eeh2nWZknnvh/{?t344ݥB|>7͛ 6 .]:rȹsޘmbbb.M|رYfJ :~~~ϟ?W7UV=ZTE"Ν;." 6j!ՅFK#7KWOԕ_xNãwl6{޽3ٳ=oΜ9'Z-ȂcuZG5N~y^]k븄r3-p/^L2`/_2Zj8߱QgOG<ۇ ([D#ؐwYQ֨2d)C;o޿>ّ3ufp̙];FK()) &>dc1Lggg8z.G~ׯ%CIhhh׳lU֤&h*&&& eҤIF-mnb5JQu뉺lHUslpx jo(z~ŸkWXe+Va{!<%ѓ'0a8PEEqMΙ2#8 Ҹ q3(0@6;E@)**ˡ}RT\jzSSӐ3k+INkN`РBAAARRBիW?tuuE%''s\>f%¨955uѢEvvv񖖖]vUT qqq%%%...r͛GH|ܿ?//OKK[r2Ç/^qqqyg<<< p8Nbb˻wnݺennᡨxR7ɭr]]]llleeH6Te+%7;Ej uW222mmڵkW]]ٳ&Y!UEM%M"W9e+W1puz񊋋W*G2Qރv%E+u2UrE)ȟ,.ISTJRRR޿/ TI.RRY+RuL.ѓ'O1b)iAE]FdLn:::*x T=i4Yznn˗.IMO ˯uk6|:XǏ\y ޽vܼq 7]0[o'?P7) 5"}=~Nge(ιx5I8_]STUR$6yB=~{/Y=Ɨ[v[ׄBaIiizFa| IDATϨo8wRD *8i zRtgϞ~Q9k-<|ӆƏ;~2|p--m۶>|޽{ {+`O[J^%ß>}jdd4}t"%)7YOO&srr h=:33jX\\>ytؓ0m4?///b6MN%U$Ջ'7T'B(??_,?x 77WdUJQIʽHym)--?233ǏH۶mT~mbEĒ%UNEQE1*Մ de"S$$$$%%)金Wu6{)(S6Ez5QШ4UJYfxdERRYm_|6nA]FT>6PBo%<ī8 cCutX, |~mm5%ܺuرcΝ{uEEEJJ  CCò}edd뗗vvvt:=334 @uM#>|XSSd:::**СCusN:~]+++)`ٽzڳg[-,,lkk{A N>mmm` fw߱wZXXDDDt o{8{~eeTjjjݛ3l0)dϜ9`0MLL^JR}}}%IJUR rzޛ/VUUu&LEEEk#xA~m޽Br RydQn6J)\mEEEGlhh8p VB++|)ʎ;N:5{lE]۷WHe#^wwwC؊T/+ϫWJMJVOTQ*g\)!455={6|pfO9۷/==;u:lR"ձ]v%''-Lr?Ӈ`(z\҂rLuudBBB$s%;h[P2 <&DD%xdDbX,&`0 N4|r0k?ҌCIw^pI695ۤ{I!a8TWWWWWWVVFQPPb=P"D:bqAA3bqaaYEE@ 000bq~~IT[wkjj U_hTog2BKFQT,jSU a7o.++377إ  eGQ+l7QQ1*L{̙ɓ'7WʶڨȦDjT6%z4QDI'z&gTw 6) ]!$G* d0kq5D$&\}}}}}}===6b  D tP/ƏZUΚZPWd TаX* '=fp+++%%CBt:]a d%%R*LʅɔRBCĊ*%č*tTT J%) –lmյQIMAըlJD%i@4OJR.),lS5ZPIQ;ZBJQ4ؓ$HbJMm7\Ӭσ4P 'hxC?4P(x wү_? @\MgHDnDh4>OJ)jHh7&yH;tl; jBoK{<. RԊB5 ݀-4P(AL k FɴPHP" R(7SZG0Ҁy;>INGoF=qϟ1@<ۦRR633k_On"==o$% >x=NYwGcwulW"cbb֮]8qO>hGGoõH$ ѣGeee(3nAggg XT Hy# ^H~P @]9rܹ;vLɟMB TUUQ??3gv戏D>>>;wj?SԂ(›{Nm^:}4'bڴi7nܰ(b1vvZ;0*˗/_~Ϧ3rHUU)"77ĄBL4JIӷ^ @ K{v6dȐ[$t==mm.]@M `!d o!\.A⸸[[[* TNAAARRB(55uѢEvvv񖖖<OϮ]vUWW={ѣNL$I_RJ*I.66rr߼y#߿M>>| ErNVVֳg<<< ңGW\\MPdjW^eddWWWW6G)wj(6}52ur83f#6o7uTpBrVA'OĪ~0\~mϞ=<o/^N444 @ D6GٔB!!!eeecƌ1bv}}H$RT*5**<;v,r5G7+ȉNBشi˵ɠ\}B:ܧP(aRT>}R^^dɒK.effzyyQ(9slݺ!$7P9>>>A!-,,,,,okk+'>|p--m۶>|޽{]vٳG2Je*$A@PVV9qDl9H!oذAKK8ل;w,lmmwޝb (Ν; 켼Ⱥ 1`Ww7=dT[WG*xgQySR?$Ek pldcd]t7'sȐ^p1KeeG8W[Ló4 `ǖdlle˖D&y|uȐ!bXnu\=k㏼o߾7npqq177v֭3f(7ǏGDD騳\ӏ=?n\Q#z!!b0/V9~Ҿk(&Oibblh`PVVAjT#VSp7n\r%44tƌ*ahh(%۷o+V^RY `UU϶m<==/_WXX()ϟX,X,MMM6=ӗMGII.]ͤ$GeT*/_===TY7zdӫ҂iB!Ɓ(rJWWפ$%r|cr45W|,;KJKW֎x<$)IAӧNY4^TDSH$*++dz.N:e)!ݼ)o|o1U[RU5+OE"wɫM-9jhS'nfffme%5V~E7 lrǖS##ӧ{xxܿ/FEGG @] SOO999bJ?>233ǏJLL0SNTn'6 bm&)ѣGgffӀXף044mK!dmaJSK^WWWcbxx<^G͛'!37BS' [bV;wlbI#p#>˵kli''̮p Pjjj޺mڔ+Xz;Ҡc.EWW׌-]J>}̾klz?L?ˀS'M ܰf};>ib~22=j-_#?BCfwWUU<}z좢_mٿ;1kjWkW9~#.g,-,RMc}|ӛz5==HsW+!$#qXkjjJKK]]]ȳgϪejz܌B˗}}},mmm:.er{rj/aٚ,`T/mINk$.߯_ر)iiR?M~v#>aPE{r3q4se/^<7u9뫡Ѩ CCCPii֬F"f024\i 6r}ܼ˵nj nXg7Bhޜٗ^!j=2BݻukՖ@.t?I[[ IDATȧP( 6q|>_ 0L "##/_J >~~( $VVV"(g%`_)t:]ɚa5Lrs$##G D]]]#""ZrjzE-@@Ѥt Zbc;tF-4 AL1+d2[U`Pafjjiaa/qDž^zz_IAQgo߹;f ss3%WUU! 3^dD"wg]];fff& vjR;*37sNH&<+'!tSglj׼oXGS2B(B,3СrӧO /JULe;r䈮n}}}nnCZ5GE- F:Dt:]7XoFk351 455Utl gx19hˀ>|5!DP֭Z9wldӑ"!)J/s}p.xPش*GLco&3I%V66d]tncMHVDfCБ4hx۟7sGBJ>b,t:'G={*6f!B>i͸G9\믷 ȫI+!!++kРAQQQHB *;UnW Ѩkh``ojFX[}S LNY9nI'"\sÈ#B??y;vجYW ЪcNX==q 8+:*,3lv!̙'*~hFR/_|uђ{Zr̉D"@i _Ih-g/ZTݣG!t<---ooo*p8NbbB(55uѢEvvv񖖖]vMWRRbkk\.A!D"4mH$JTj: r&>4ovI*B|ur83fST]cǎ=x`TTBN;88hhhhkk㭒b888X$]vȑ#*{ڵd//Cܹiɒ%χ&S DBP(lA@z=,K hx^ђф;w!mmmwp kooo p ".]EP̙uV}iJJJyy%Kpavڵgh2>t:CH: $wm9i-۷>}+9pbbbB G1 E'&&2 .\pݻC vu<|Ņ^ennnii M'@PP40Ҁؗ^h0gΜK GX,G644hjj6do߾244466ȉ'p5z/˽qƻw.]ZQQ-'5''`N-[l),,xd`TT522>}QQB(11h{ ϡD"<U(*W\ >ܫW/hU)))?-#+X|tP(@@Rq? |> lt8g``?O>;w622=x AO^`ABB322 ۗ߫W/SSÇkjj2LGGGnݺܹN߽{*''G{\nFFN,-- P(vJNNڒRAR<RP(sqUVVX,d2 t:F7I 9}5{'O.Xo~~a𴾧'yoll,.&&<{>>>fff8MU;vFAAkwQQ]mt; 4 (Ůn,hIb]F4XP1*QŮHQlJ(_6\aWAx# J{BH%]mhOBb JJJC'H*d2x{ׇJ@Ѱ w"ݓAЁJ% lR`O 4H0Ϙz1N/..&ܵ@<- CQQqs^sH$v>i Dȱ[Whjh|ԃ=&Z55V}ſ 2ds:Y#G3gζmۈg„ ,FZdI^^gCAA o'!!fٳGQQ__kooμn/^颣qWL_^UUrww^Iq=dP?{ {=c:s9s/ \ry999bبƯX,"j[U]ګFoniP(֊5!MGgϞOlRXF>,WhkkHiӦzTuWz555Q-tF\@f8 a2PZ-ϛ{𑸄1>AN_z+BEF={srX,Vޖ֯Ö7qsMMM22Ç ݹ}T|gG?wq7y5,ΎiJJJuuuM42Ռ^!FAxym V.^|ҥ}>_ϙSwq52#3My9Bh=UT6jjbpػҒj``_/^2LSSbA&ﯤ$:œ҄;;^z333;33BAy&99Pӧ܁bNnnW(JBBB˗::: Q+,,$jADQ333{ݫWG IOOd0ʄ PV"ɓ'yyy4fkjjBg}סB.ɤ9b8BYz:BhӶI[7m ;sz@VykȪju&t'޹choo~7鞽ݠ_֬?v 늊ݿ?qܸU+߾ /kVڱ}tީ?oP7?ݸuq7;7w߉׭^ٳOʹUvϦ'Ywׯ_H$'̛7fO:566رc! ~Ǐ;ȑ##Sԓ'O8pN -Z4h ͛7GEE}0k׮}9slի8ǏX]l6J^x1,,L`)8… ϝ;G&gΜ/_,NB222L&SIIg~FWFFFIIۀVTTsu:uGYY966~vdeeqd%%% D] #K.-,,7n\HHƍ$666==}ԨQÇ߳ghq D͛g̘Aӿ[ҥK,Y $;JB͛11-^emwtz̝V svN.1lB693g|spO8͡n?/m7FOo,k@D"B3^f]!..LAʘܗ!3+!$/軝@ݩ C:ׯ'OlٲfРA/_NJJ|˗SRR FhffmmmE L",--BSN;vɓ'tcjjJ477Fyxx֦1L BR|;dXL߿~>(v^aYv/N%>--- R^^WUUhѢ/^(++.G%uAKڛ7Nhjh073GM# 8Ǵ޶i rrr!O#,BOSS;">PVV616BakC&<$BR=B ]ffgk[$>cٲe۷o/^XRReѣv~5|8F6l՞={h4ZJJQBB¡Crrr444jjjϜ55ÇDn8=== qq[;[TT&w-~ZHݻw/33L&ڵkh4Znnnuu@q :T`YWee唔]]]{ lJuu,B!d2];Frrr4FQTҲe˰b`0t:No{ŋg̘!͞EF&14vw2w,}}Դ׮hd֍H$xhmF-MMPccow36^2}߸c}lee 1{GEEr'f#.]ZR`رgΠt&Nc_TӬͧS]dgg ̕3ݜ!>ܳl6`455 C IDATUWWc@'inn~왼 i͛7ʼn=:1LE",++9 cYPR" 2,6]UU%Q,#)//խc2x@ckG/eΝuuu7o)Œy捼<9%,8׺] tXIB\fBIx=m۶.@-x ŢP(RҺ ýݟD"ikh!*jldA ൎ44DEEGFF4Bш8J4*z@WN@]`0~,&p/jH<xaUMKBIY/zHX؁$L&R(i---4M*@dR4QHPI,]!>ECO6H| J]!V6bϧng!l6[;n@ISd2pq#AXITh܃OɞJ]ᶛgɞPƢQP08<4b4@!ik&,w>>= _0LPH$EkO3 RXUQ2Lx% 0 BRdH&IB A/DI?~O^cAw wO>ng LdOyaPTb'6I,}1YfPW+N0ܞB8BpZ eBzwG&PC?> Y\xAWWPYYYdd244@ȜÝ:sVFf&ommݰep޾'&%&&~{> ӈ=Rpd2$\]zcCCcwߛBI{ڴmǣ'nhbl|*4tŪ՗"++) HʪꚚ~V۩9'Mj*:qHRZ[[-89:7ooĬ_ !x[cy.0> mrB:p|$ /wK U3<eXF"9W .iS#?H7fStB/ B':wyb^A "n!N+R`)ýt x!i_Inhh +'z.۵sPw<iblL U8Nfvv?+ܕ4>N?^fI-i.u{ǍҪr̢!223 VT\fan26252i4ٙΠ &0> %.]d2[[[kjj[Z[".FH$ɓCw%quDpN ef3 hk_8wÇ$$TvuvopWpqv&`ߴ~ʩ3'Bd`;;Ih|@Tl޾t/9^+L"L&6454AP!!}}_mxMk5MMMZZ-%% k׬[R]MMFF H u;vWh}\lG4 !..L?>%m4ß_J7$%]T1ЭNd2vljkkޒ377755%Ꟁ7oB@;cX4Mm@I+l6أ'0yְ-M_POCCCCTTBѣ!sss///xUZZZ{{zjMMMi '''gر+V@kpd&} Zֈ5ÞNRSSsշo>z(**u޼yT:bbbrBIstt?1UUUcǎݳgO\\\RRTE;f= |5qč{QĔH3477Θ1UOIMM˗#RSS7)amm}Ѝ7BpJo 4'0*G6f9lK$FFF7oFH)c``/>̬h޽D%''#*++Nj/N4 !dkk燻樨(??K.ikkGGG{{{\xq6l*ك֬YC(i;v8}?߿?ɼp႑3,t(z3 GAIz:xe#}lw=۷k999SSӋ/73g9ā!cc%KcMfo߾b >\SS{%w C***fΜCqHCC B(66!daa#҅ B@ׇB=#~hx pz֡hkkcիWyyyUUUo߾EtppZT޽{SLAYYY^8p࿝ ft:HUUU'RP-ඛ$>8+7/Gb&dp`0,,,Mchh%0*[֮]ۧOPNNNPP9aܹW^.]z]{{'@/Fz[(toJމppkhɋ/>t|]Z8͛7b>3a„b}}iӦyxxhkku&Wop8+W\r%4'Q6U5 JЍ QTp)yvŕ}R(KÇXUc04Mt o߾ݺu+$??_FFpC1 #"" MPdeenj >Nɺ % h'477[YYQ(#//:u*Vu?yԀHǏ2jjjJR ҊZfߤIdիWMv^zZɓ˖-[jU\\%皚3ݻw111555 jll?vXZZڱcϟ?ͼUV]xQNN!dootUV=*%%;ǏWQQ F]_IcytWb&EER%,))GFɓz---l:{1ažɑe0ouuu8p!G&.\A?zرc}˗/@Ұ@n>pbbD\_Pndd4)Ie:oku¢W]qء?Ŀ+VDiܲ |Ih:_YYYFBĻw&''8pߟ;|…yyyIII,೫0ܣP{w.lMW[:т<4wI id{A:j; !kXK_ [&$vxxxss3wxFFFjj @C2dJ6lI ={ƭ_M[b91N{+7lz( jjj[ZdeyY64chkkWVVnjaxo®D^.ׁk׮@k.x >f!Yl4nLja|n_zl#LBtH1vnmm mv:]OWwC\"Ʃ~YYٹΎ&&Sػk'rGQz!/_曀E.@t.N{wmĄdee; w? eUeU ~A0|] Ǐs8ot`5&WIQ<$vIϹCdedxnyD>8n,Bh~/9q¸qMv$%'oݴ1AmWZ]IfcD|lvݻ8N̝8P|??>~4\!TYYU]Sڪw; 5fu_~[tVVV校@` Бؙ해--M PuMM>}z[Z܌G7nVUUM혘/xv:+Qn?/4-eB_&N6qʴeB_'%,8R#>^R>jjnNy[I$R|b"ɌOHp2rp AojnۉπgqM b~=iZZItW8`Aw74z{CEed "457TUWjRmw~ I$ɤP( 9'B&Ϟ1c߁?yhŲjIIcbPWwwucldاwohnfǝ3Bmݺ,=}B<=vۯKg'h'3;qC~J*24Y VF@xJaɤR?33kfvNΙ2\]\dee3c173ݾym¸wݫZgbld=jdȩ$i3As2TSFXj--H$Wȩ!Q#B#==v_tlɓ8=KW2֚ږ֖$$@E24n wC|$x4@p>y%B&ܾmС"/}.ojmPwe斖1\7_rLh2ljb2N؋԰fcmm8`@=ܯcuM;I%MB ~lh^4J>/zTe˖X,&`0t:No{ŋg̘b+++dqR qnn|^zftzsssuu yyyT* J.U%'"?DMMMMMMUUUEEEYYYAAA^^^VVۯ֣ɺ::]35@44R Xs8pH*ʪ*ʪhO<rGAgvB#$f2@Jq- ;(i@B]U<[;I%{2x0b0[ "౛a5PҀn Mے̄`0`#z4|$lnF yd%%(1 ]  JmunO &Ywl͕4X,JvJJJ|r}@WWWYYg5Z9Dh f_AwG) S^^joo?zΝ;f"N``Çϟ?… .\xQX{[n!BRk׬oށgmmm׬Y}f/ΝRׯOKKC4(00S3uػwoLL 䜻-ZƦ+wb,BX'&~݉ ޽ &@4 ~b6~!_,XIvm_zJX"۷o}v3uXiT*f]vʔ)k֬stt$8W^=rȾ}ٳcǎ .l]޽#BRSSWMǏ;wG=_ oonJo޼ݻ%KXYY#FdɒOTħnq(((x~TR'"!!fٳGQQQt+aϟ?O&eddubb`;vbe Aqj Jгo+)+!BL& rΐbŊ4334x a[+,,|~Fijj*"?{ՀHPUUƍSRRRRR̙s!aC>}p8;;JlzcvA222N83 ?Ç̙#Tι)))&HӦM^*{.1,, +];1{0;1{( JTn5?@wrΰ|r999 "###''o>2lnn8`HMMMrriF!?~RTTtttD'''2 y_|7|JCC^[[ۣGl6kee+++333Ts}}}jjY޽BZZZ!s{jg???;w%S(޽{/?}zٲe񳲲233mlltzEEB(>>GkmmXG IDATwrr۷/xqqӧOLOOd0w}gff```%zMrr!C/?'<ѣG^^^ %??纺nnnZZZÆ XvɓgΜ62zB X͛7:~8ِťPRRիWDDj~,6B ?|ǏǎKJXE_46zwDDY,OE_ݢ[JxbXX"-H| hZk^"r.0? e2JJJ`ܻwȑ#ٳg6~i533F`фK[BiiiL&BPTu/aaV +0肋=ىĤׄ vO{%BړV[W //^**Mdr%`0𠼲RII˔ӧ{xxXXX #x###"2ހ!f[1cJTщchhh455q\pj̘1O< P)))>B(-- /r~j{7Z2dҤI'hhh 1bĭ[={Fi4҉ʸExk+uS`NDktoG{y&ʮ?^'(m2/~A nM^^^%H/>zرc}}}EK\B"J$69sA(3]{у &:5! qɺwgΛ>>aaaIII$6lXdIXXXtt0d2 E?{Ǐ;}Cx-+--8q"4BUDRGNNNhh(B;|8BXk׮X,55KZZZ=z$H...d2̙3qqqk׮ 1cFIIIiii\\J|rsssKK&mĉ.\^YYyy==gϖ={v̙9wM0L&Xb̘1=rpp1cٳgUUUBBB,XSv==Пy޼yx1lDl̕+W 񋪫/^ϟHxxϓx %L"%"Oz!Ex%-xLJ_/۷oskܽ{7,,>>><ϊnKK0 hZcƌAÓs .,;{۷ow滰P`G1;1Ý"#:1~I)@/$.[b1LAtz{/^,Õ /\ڵ{~[Ųwq;{֊~i4# b+™Lfcc#SZa!N'VUU\Uuuu,6[;xȱwn(ijniP(;v~bj}19|bMXz8K -"A nC\Ezf?1&#= ݑ`455UUU %H9991?`2t:]J1'>mڴ>V#S~zio/1͛78v ''d2s&8Nyyn]]TWWg222o޼b)UUU N)++ފp޾}Ԥ!lI.EgR#AE'SŠ/.1G8-DOn*<,h kZ xS.=N6-ey3ZNb=BE4eʵUUŝ6!!+))h43L@~39 NII紤q8N7b[vݺיܾզ_?Ћ̝{fX>-7_FDxkkkooGǴz׬*"8l{WQ#32ޔ#߳[EE/_B-h<`t_VVvn~c{{T+Bh)kW&ς vx9VkqI]$0%QJb'X=kh}o1[F"l`k'H$>] B&? VxE" ]@===F"(TY,F'<!N%Bq]k3M'%-aaM룚O|q ѥ@vd$Y =Bݻ;ΞXͰ9̺k~8̬~WE߸ffGPҞ?F544 Gmڶѓ[7m416>bK畕ܩ~|*hO?p帄_֬VVV]ݤ{ޣFN316>t/09|F夲8Iݷz/_QvؓS9" 0HOOJö5k,@4B@c4lnsH~;:'/g++Z[[-89sjM]}7ooĬ_ !x[cy.0G`\}_3Bi=F an?/#Ċ#C>WUfd#YYV^3|sHx҂P(6bW@OOUJZ[[B<']_b Ut B hxl XLML:+y B-ͦ&&ӧM eܘӧNE Y:שΣׯ0rrr~Ϧef x\ykÖ^#GزIJ)I 6MlcZ?k߃(\\F`Z@\ޟ_,a<=р IYw &(޼Jc b:4]s*iTTkkkيb>'/﫩S=yr?']8aذsa߮Æ ǃx&D--ŗFمA, M>#9FFFQ6|"p1IY"Q3_݇?=%IF_Jʇ%pqgy~tTR% M(Wf!99fЅI(bۺUX,Aٱ\)VLK,ۥKhlTPT>ԳR1t(sG 67#e҂xDj.%ĉ("B ~͡A^%ì?HmȐe?,=xx)# 551a%%o߽X0LOM}{GWGj>~ƚFQT]Ox`Z0b5q`0 55m{ <4/ʍ~Oɬ|VOE) }qD2D\?wP7c!'FQQQ6641o?wΡ+׮[jS~ZG޺9b2ׂO`8;}HtTTTN >B&MMLّHs8װ9:>m1|ؤ oܼt/ 'LuuL&!Dg+*+𭚚ڊJu>DuM;I%MvVNn.B(>n|]gTҰ - ORa---Y'<PQ"rʪU̙/tZoM7_rGŮZh JJJN640R7oѢo\mjj~Bml#6]nJu55ϬO._?-k  5Bٲ-~`xAmXf5!pw89q'q6TΟUb/ҞHWAڠ w>q*ի˗/( ދ Ub ҋPF+Q5Dy7Q_k0DQFEQQ@@QD Y@i[82,q>OfZlwoPz&oذaƍ:::Gqrrʂ]+W())VWW?J76ʗҽDĉ-\Pgd#pE'GwQUe2999;Ŵid"rei}qrMGh 3NtLM#1 8@ӟ0oJoIro gw>/]677b%%%AAAgΜ=r˗[[[򱱱f͚? }S<ϗ4hoLLEi%2>IB&''yFyŊ0:n1n8ss^ ???##rK,ill466n޼9///333333000<<${ҽArq"<*++i4Z@@kAno޼-66 pvv)ddNF-Sp{=i voe>wӤ?f0 l6;,,7 ¢"}}}///%==}ذazڲ2xAs($##CII Eihh(,,d2...---O<8>c066NKK6l>evv1=wؚ5k_xohhQZZkhhxjjj"(99Iq햖ggghIc^^eZZy$իlFIhٳs7oތ?=?RPP&lmm222 E{{'O]]]% RRR|}}srrfs!Kt% 222NH,l+ IDAT!ı=#rCCCd9#[J:::zzzHg[wHܹsgĈ )maax! 'mȐ B_xQUU=kaa+,,,RRR(5_ K-v[d|Q*'':1(Fh՗/_WUUۣ:СC=N!w;KN1pcb cI4^|ckk ?a<'1r4$)G7)I _E£zeff:::&$$lڴsxիWg>zH$"$8޾};::zʕшsFGGGGGGEEM<_ 'Iik׮ikk3yd2%$$=Hfcc nlllkk'-ถVCCƎN grss 8UJJJi4ŋmۆO󛚚gΜ ;aKK1cTTT?NccIVLEEE;wܸqj54hȑ#[[[ 0 C ٺukyy:ݻGͧNpss~… {2"O:q-Çp8 $8~111~~~˶v튉?]\\95 B>~8f*JOZڐ$3/>x0h 330[x*Lkॉ+l+ȄMF%oooDsٚBX;::$TN!>StkI Y,իO>  %0 I̔bM%ʑM `t:Q+i(cF|>26J 8pYYY/^ׯXՁ7nhmmmeeN{{;"˗UUU ,X`ANNXhh&}StcxƍK. ?? ⡪*0  Q=~XOOE ˗/_|933K$a%5hЀ|GCꠦfhhׯjkkzݻw0ǀ;;ܹ3qv$O{1077?>_paUUUBBJN ?>_ 'mȓ_oFu!T$T!6ae\ E8_I!iՏn>StkIqhvvvȲ8O9qs7=&k#.L1 `,~8E^^ގ;Ξ= lٲ|r8kp0Q:::כg74yN/^|LLL  {޴ipBxiT8%!pѻwGٙpĐ==ӧÿ4O>=uV__۷=ƍ999\.Nob30i5h˗O6Md6 ~ׯѣg͚C*++x<ȥt$9s3fG̮s2x8, /\`cc3i$@vvӭ&\!8IE2 ӧJJJ`t]]]:h*+%Rs 9TbHZMrSOnָ֒uKd $_,0Ggggqs"nZs](|rFùt]6d{ѢE---?544tttL:̬V~* 믿=== 8 ejjZUU#\"hĈ"4$ _466 B577Qniט\]] L>,dW^D4h|>DYYY(h,I'NXRR L?c M'ϿqFee%zɗUUU֭ {>%}vHظ{9s ]t]ddy:::%O:USSٳ uuupdRݻÆ HJJ*++CTTTU)-xRFZx_AbVKGHWMMM+EF5$UfE#9^%䟄%@UMK*w#B djjjFFn0l |i$3 I 붵' }s̘1S>tE otV(j0GGr2!  ,8 irD"Qmmass3ֆdxbpէO_Nx+W"=A{{;&YRXp{F[HM> b/^K"8ڐ)D"Quulc* Khs Hh24)2[MZKUUߗ:8@gI AGBa}}!4<'{BʑM 2D]]b!T{}+؄+DZZZZZZjjjJJJT=Qp }5ˡTt:>zD_#L&IhhE E RRRwd+>SA#jL `i 1$ IHA%\m6|piŃ<zFCT=V,]jҝijj?-pK~e 8ڐ)h4Ze=t:5h+ w4K&S4ΟohNxn v@AFl!)G7)`= 5Hop&Τ}pvvpzAx`` Y/vvv̈́'$c͚5쬬XJ;;;ٽ ˋ4)jX?~d˃8)PN/ D (|xp#uF{VwaU2/I|2bg )b˕ҝo߲@zSy_~Mmmu&6{Y0@HNKrT'O9.Q4 = |XXB0=z=*GZO P=_6eV 932sd[[E$y2P(I@qiǀ#49᠗F$nH@AXhGKzEc_,/i)vSCH.P.(QGhI YU /# )ҥW>2_=J >sojf2omm +IVjXZZjhh*ھk"EȾe+tfb^0k ߽(s+ǥ2k + xj Nc|ɸz֭[?{m”$%|?~.kYYYtt}04Y(/gϞe27n-/ CBBJKK ' ?!%>))髯 Ԓվܐ>}v˖-O>]dɠA-Z?~_u֭aÆ'sG#:rȎ;x 6 44qqq.\pŋS߿ƍ7`07oޤ:{]S9Cںvj% ^x|>_(R!???Ju&'N'!!^*̐nRF\HV\oTrrǏ_֭[._^__l2W^ɱ C[>%%E(ٳʂ 7_h˖-,@,QK8̟?Ŋ8vX'''o>mڴ &,YDݽ{?1dȐrq lݺV^Yf%%%qqqH?gÆ 3g\~=vrr+WDDDٳg۶m.\ $ttt,Y}yݧdD}Xh}b=޽ȣ ?aҜnTxYQq+ MMCN[ yr~"*RG <NS+irC>|y^^^^QQ@BT( GzLOr!SqWrɱ gXXؖ-[2rAAAEzhWVVh!ŏCHis :kT/j%חN'&&L^||<2}UPPdfµk~K,4iכ7o= 544^|)k7\F|9{;K,ٴiS||ĉ7o޼`Gl!3fPt{.:' oěÇ ]Z__իJ yXԱc7ۃrϟ}}=m&5e/ܩS&} XZȹ-.F;^zmjjC/%-J\,cnn~Νg«i>|k!,>Fr޾}kee(ٶ!\P=_|Y\\\UUbooAFmX}{*x~#K]]]zzz~<<<0dՄT<~禦..., Q OW :i4jT % Sj [[[-- aaamチI.\iYYY/޼yw0jjj222G޼l6`(((찰C{hjjsvvӸt:r nTQQˀ %%%7776]\\\__P[[[VV-++Avvv>zbhhhccC(PXXd2]\\ZZZ&?y򤏏d^x166bTUUlذ200:8wÇ&Oq9~P('Mzq~p`\F5o~Aa!`QǎNϿmc||=zO\JN(0/ffgϊef(Y,K;A|>jܹsƍ***֎;4hڑx~ IDATO<cƌ?~Ĥ,--ň"̱[̛7lԩ⊏WܼƎ%q6 SxЖ766+_&6E|hGR_ sʕɓ'tWWT ٺUC*̚ޱc֮]KјL1aCF1t&24 \&aÆm޼˗p.""ɓ'd<&MnݺLrt!Rss3!y{C>uTDDĭ[ttt0{A9KOO ,8~xtt=<<N.T! 4{{wﺸSɱ[<|966EEE'QZT[zƍͱ7"0S@dz7np\Ie6"+hooGz$8Q%[իWƍ׵mdl"B>i H{8UaGG9- *[!3%s9vdJt#GL<חPrqqGfΜjժ#GPHI%@YYyUUUeees3f̀t:}< AWWܹsLf||dJ @@[… 666&Mdgg;88^uu5!c+++߿ͅGBE޽{CW1  ďOԈb?! P+͆mIsf]0qjk%/Ư7u*Mp<ߊgLU+,;; x#KvDBg:'N,))Af:߼y@Ԅ݅2srrWRSSϟ]\5IKC,**"T!P3fx)իÍ111 ,>}z}}=Fd>TWWDJ)\r`pq),Adڴi\Esl͛7#QF+~c BhB!x 'R׶W !$aqJ(Թ ٦uʕ3fֆ@jjjCݿFzzzFFFZZQCCáC-,, "##l6Offft:ٳ&&&~-FKII /..ijj鵴-̽{ea;hddtsssxZZZ---V[[߿aaaTTTIIIWW3Tb}vƌhݴo޼`0TUU#""+Ѐ3!\ЖD*Sd,HOO/,,gΝ[n>|xbb":%^\Lx-d2;;;={6bWWWq4 T熆ϟ?700GQF޽{ӧ1D%TmN8&&&ȋp|r tuu%ٳg߿?p@QQzKK СCEEEzzzxULr-<Ԉ#eff:88[n>|8 'Q---H{_ )\M;v,'^2q{c~b{ql,Yҿ_j@f!i^]$999eff&$$X,tUsooCm޼СCVZp!`˖-[nMJJx #""cǎ522|5k"""?9s&99YAA_~yŋ-,,Νf͚C{xx+xO4iRiii||]##'O>Ā˫ܑ#GŅNڼy3`޽͛5554m௿.LNNFZ)H&`0 $yA}C=%%%%%%6bX,ɤYvmy<rtҹsj2sכ6}'uuV,\GvIܼ!KiSNPq&&cH˙<;qe=^rU7ߣIdĿa503N6=<ݻwMMMZCCf>f-  _600@vvv^GGG; D555s\BMM ~f[AxB|."vy|a%[ cǎ-[455OBQ ˗/GSN\U`H8O& ZIG 2r{:(N*N a577WVV 33vf.Kz xxBYYYAA.t^BxJ------MMMuuu555eee%%%EEO|OۚV<7chffBUee]}H}}sf;1 S҇UUWW'V?O2NUE|0bDYy#@__\vz\ hjwONњClmlDgYnj|yoTs3N'hqS2@B0~X,$d EF B7^7D,(`rC."$[ |>D9=,*OGBpI[kҪ-_!x{򐧫!3sۦBKIbRPPM^N-&)2H M=wnBw455I! 11F1#Z\axAp:v'73zP(d0?|+W._jxw~q򕫑GA?wuqvI|>f~ og=}ܘ1W<q[***cGz]]ݭp}}qiajb2sꚚƙ lwnr dF@"11177#w0 ])P Η%g咷P Eܗ{ow=5q8߿#<߾ol,T}i 3;Any펍R@ (͛4__e-\KKc퍂xⅪ*ŢHQ@D[ݱ@tum*PUUEd40z2̌̀WSf@ …^ , Lٛ~ee1H(@A2rV^)A_H\lt:^ ǻ)PSp1Bb54A >*44#x|"B>_L,7P4 1vGd CYώA/eKyLEEfVevtt P'QK\$|>Ν~KE"Qii!&SG q\\\[3mHAh4ɄUtG%F3It@@h4S {}v$%%}Wb[(_666;vS~$^4iu{!DΝ+..F?;vXdd$ϗ 7n())1D99,3nݺ5lذ}'S8qĠAV^=uTyjj꯿ZVVo>h)B0$$t---ȋW^ݺuxt+7 NV ٷo_XXƍGw )H|86RtjFዞ0L:@ w\ezm.#viϟ1{nbȐ!d{{{###FFEE5#M۷vZjٲemmm.Xd r׍RUUɳ}H&Lcm SNC enHmر!!!/^XprǏvvv֭MOO|SRRRB={TTT~~~"݊5 .<<(Q/ ]F%G\XXv\ ۷*++y9sȑ#/_nmmk\0`YfMVO>=u䳃Ãō ~bnn!))mrZ/s[LMMlff{]]]Hf7R__F`z (&Pdv㩫{yy]*R;ӑ4?Zޤt>>R{fllcccWW/^YZZZZZ뻸ե ={VXX8p@ G 2d, VFF000@'r߼y3~x8ONNnll433sqq+VXXXO =<DiiiPRRrssc L&ťɓ'zzzzW Ԑ\iiip~fBd/^|%0>ddd-Rݼ;y ^SЭ$>ƀdt쬩QSS{r;wΞ= ?|d||*%%^CCիlSSS| /P&"M5LLL x<퍿tK$444̞=nOAp\eeeXYr.NQ\/%t:2HJJ5jԞ={Lŋccc ܹsʚ,, V_\\?xse˖=\$-\P(Κ5+)) cX t:=&&ԩSPcǎJÔ(""ܹsx#UHHW_}eL[`t7lP__oiiى~%'''$$ׄFaY 6 PQQ:thKKڵkADDʕ+G^z ߚ3gή]LqFʕ+!!!|>!L#F޽͍DGGO>}ݺuGurr# hbbى4\.+?? `455W*?W'P?犊|pBcJA>D-@nNP$>ހdt #3}mٲ%88FS|*Xxxɓ'}||Ԓ P kPIk\6$''>}~ 4?4iҤqƩ[3R2OA% 1TP0Lᴞ 77(++ZdرOcƌ?~o޼Sxzzvtt)jjjEEE;wܸq#LE|qHzdD[C\e!C<=====aO:秡v J`|# N hF IDAT@ QVh4%HdCPPǏ\\\i4kpъbGGBdoo](www>ѣ.qTi4kNKKcٗ/_|rffau#0ZiRH6'O>y$**}9u-ٳgЀ; 'e!##<<++ŋ+V@w_ouu7Z[[[YYuvvAvq_|YUU` Ϗjjj1ûwn`0oܸqҥ~A> ϷRVV&|]UUUI>Uq"( `S NDBn{M#,ʆ;;;gffZ[[߿_B;w!CNIu[(|$BQRqFo @555CCCgK_X'@ z3i>{0L@ w2pĐOK@{{;~F-_<<<|ڴi'O:z?߿~oo8@wGqFNN˕mYII MAtuu!C~޽uԨQ `Byyy;v8{,b˖-˗/߶mArMMM1Xl6^>:N_x1U211ApD[[{ӦM… ]]]-..]\ BƁzxW%P[ƒS|i)E``d7N$ (_Dm )N (A7qxոqjkka^_5-JJJ ѣ$4-2o` 6mӧV`=zY'GiT~ :@֨=ALLLnn O^__Koo%%%𫃹\k7nܨż2c 8yUWMMM8\VVPSSC歋o^Xrr2=z4Z$eeeUVV3srrUSSSapHdhhhllw޼y]]]@,R\t v]hQhh(c?j SN533-_YXXx KSSӪ*D#F(,,# Ƨ ;AoIcD"P)!J^rP]&7ԛ;FSUu`1߿?eXp޽bURR[]]C[XX~:<|{:TTTi(**VTTL2E\}%&&FEEtuu9;;mllb233WW "##lљ3gIkiic`JT\\pF1cҊSTT׿y&PWW?|0,ccc# Zg]]]33:~Yo͛%%%755ݵkG9f*ݻO>,+䔙b`طׯ_gdd\tĉQQQUUUGQUUuvv.++ ٳg pSN988lڴISSgΜINNVPP_?~|Ç߿k֬(//߳gիW'MTZZ{{{d˖ɓ'ghiLaω'jjj*++Y,ݻw]\\ˣ"""f½{s)pD{7ohÇxIJJs W1mR+55U@izBcƌkB0NHH-f///|1e:F Δ)Snݺq%WAu&ٳ#F1r޽rСl///eee8Sd2 ɤh12:`AKKVTTTTTdX,d֬Yf<rXtܹs:Ы(**?2df<g<L; ܊  ߽{WWW7rHʰ*((())|zǎ[lijjׯŋK;$jjj 'dBacc>NWW:::!oxfE]i ծ600@ oeC\vmmm***pVEOOSu|>M]]3|>86e@@++@1=d)Tfbp⫉?WSKf?& OD2[@\$咊*$Fh._$D"Qmmass3F6K.>8QColիO>]~=NxW\=fٶm dh4xt:ɤhX,iCW76!M$ׁ @,0JTUU3 \a2$ZmpiX,3&-^~-nMj"UԒOE# a)H2S9QO, u rIEE#/UHaI @(!7eFOP\\-h4 "hL* t,:5HCEicggWQQ܌1Aroggg燝BPM@KK(?@`͚5쬬'(X5kPv胃4JC p`EEŔ[dbd?'W8QᇜH@5 `Q!4&5H@K^2= %>4\Q &)XZF &>P(7voSS'OHȣǢq/]A)6|hk75qlm-+N2\^##4>,Q!)P||z=ý"y};U(PGhHO [ǎy8M4. 5|>TmlEE'/]1N235ǵ]Sϊ̶{֘;y<fV _V3gd1~]ιPi)P@A<.\fN"BH-TV54m:iHҦZGD!ٕ?wߝj~>s9Y>!XI{ƦI7o555+(CeԩSΜ'''} 9o<'2/PNww7N27aC7p)@`>蕆X2UUކxx<,lh~[wJIJ::{1̻))WT*ht8[:d1.عw6L .&ha`?"+*9÷m8㛷mDz}9bc:I>-Zb:yqCi1V\Dӝƺs?kw侎M4<Bsιo-244\`/O>uwwwrrvW\ihhe Hi& |@{{{|||tt޽{#""8ίn/H)99dǎ_7n<|?s0ɼz<֭[uuuK,166s)Ǐ_h@ٳ >'C 9rO<_3 .`+/^ci,Yhee%:;;-ZTWW?ķoÿ2-ܖ,Y2@6uԁ>6`رAAA"g&!!XfJaÇsXq!tpp033c7>WC\|̜9}ۣ8uV]]]+++1LOOϽ{r974h}e'-=#_|몪(lgH$ܴV\Rd2_sJSCw7nN2-Hu1#j dE⠅s|f.?~]ڣ QQX>N4cgH$*))]rKPYY93pޒ}yŊ]]]:֝MIIy1¢4???++ Ebѣ///{<2իW︸Sn=Q:Kڵ+77WJJǏ񵵵ǏOJJjkkHBB&{GsժU6Buz Iaz122yk};ӳd>>>K,3f̍7x&7nСCPe˖999fee={L& \ ђӧ7nljjڷoߖ-[8?/**:u̙3/ꕆTUU)++pٳgyihG;~y``U_y*7q[[0P~.[bxfI 'KNHST\Bj))IY2bD b:N {&*&Nx%ooo/.\yO>da;vܾ}{˖-[DLL C}QII/_i4Lvrayyyطϟ?P(,,,\|NZZ[/xmmm[[[7o BZZFkll׷P+LY, TJw;^ZEEEBB@ KHHDEE)**lllfϞ~`0 aõfffvttʪ۷d2E>YYYD"ֶ˗:::ʔWd2Tu8Naε-;;ο׏߹s߁H_.,,455R?~twwcn)8XVV̝>ht,..]yubbÇ+++ţBCC /_ΞNGFF>~XBBb޼yGݸq#B(**B}!ob fii9h iB>| <[;X`pkΤ}z\%%%I3˥P(.]{.DԼqㆂ ??yҤI< <777{@HLL}T*uɒ%%%%n)< rJLL 0FӸT($pta9{nAf3fSԧOZ[[߼ysӦM^^^p=? HOO?y򤓓ʊkע?܇ ?Ӏi4ZWWWxx˗/gr!''K.}_5dr)ggh]]} }>|8%<,NWWW+++WVV2k.EEE޽#𣫫'Ov08D222x<[T/Dgp8v;5g?|@'MdW2.)116262|gň윜z9A0%ܓv\pa2\]4oٸsVoޜ>=mwW#UVvww õ 216b^;ebƆ'31E&NHݻ7eG"&O|%__ls !//ojjq…7_O>sKSSsر^uq+VY]]]WW+WRSSgϞɓ`hh~zCC!CyfXTT1###,͛7߼y) .[hСC544t:LfooSjŝx³---p;R-ZįJ}.L=Ϝ9Ν6m߽{7`2220}DDB{{jXe IDATXڵk+++oݺ455y^444dX;}3`ŊMƏoggOommIcR ;-/\<[aFzꕴ7Rzzzcǎ-,,踹 v=Ag\=*w?B> g(%W"BdggH$4k,<b:::.ѣGg~:y-[3||||||n K.]4<<4۶m;p@MM 6/ݻw(**VUUӧL ֯_= >}Z N0W;(oj}ȈSN]_߳m/5j` F]]]GGښJs۩0g_Y v"R"Ӿv]yy92ig7116u_.]`h%suq6YӧsTЪ+TT^t=YSC=ty~s%N|T 򤱩;YYZ3gLTh?}ML65vh_! FcQQA&=<<.]4tPF{) 6$''{ZFFtǎ622ºk k,0k,%%%++m۶ '߿ϾBWW7>>WǏ 6 8b222$$$}p0dȐC***BBBo߾s[nAvGIJ6lxa[[[WWWSSxxxBŕXQQAPN8q u k֬`~>}x !ݹs EVVVMM'x\FFFN<s}59ʑ?0 @ӟ?naa!...d^k??uqԲo7˷cKQkkk?};{'Ots7VW}K?~cG%w&p6ZZZÆ CMcD?xNc|UWW'%%1 +WRUUb890Fa"O;LکcG/Z,pӻ( $''ǮCa릍[7Rĝ~>~>Q癚޻ge%?28ѩaÎ:`0Bof!FQ$_,֏̙3WX1zh8<,tSqqgZ[[O6mҥ7oބ*((ddd@'ҥK'Ndgg[qN}}ÇܹTPPp?.%%%T*c >x`%%iӦw&NX)E@\Jdqyolٲ;w4#@ggõ8`C (++.\1AAl LAA99>z\ soR~X]] W< Piᣀ[}^>!E}'H:T^^y8nD;д45z"`$fDWgg'B򔖖0aɓ'96cYÜÇ߶mӧOwQ( yaggwRRRM `Yrss͛7m4Mk흓-IOOBuB0a›7oI?Lf̘slQrr2_pgɳ8~pT^RxV(H^fq`5kΞ= 7wvvN2E[[;yW(**zzz^vmԨQNNNp_GKKBo#G gիW%%%:DPtuu8PZZJBBB`"ۼy222 wE͝;BL:}jgG%$$455ݽ{H$&%%wtt(**r%&&_pAMM->>:>>oaaa'N|9[wLyn,CxJM`0R<ͭYYYrrr 111C ȍ_ ct/C ˗/Ed2y֬YTB%B)ݸqÍ1bSL9OE>}: @OOJyyy.\ȭ FFFXV _87nhت6}Ι3'##=f<텟iuԹs*͛79rh---ӧOU233?|έVߣi~ |F]s h4xą2 :NѨT*Jŋcbz+suY՝wlF`ԨaBRJJJ۷o߾5448T*U\\FRR=***u"544(++ ammjKK NWPPX,VMM{ieΑ xc+,Xviii8ΡoL&c!4NooogWNST~ؙ={v1%KCѲދwkggrn)EEŮϟ?T\Z8!R8NMM ֭]|ፎq `Ν#FRQQ渵^(Z SQBz)0%OEZLC577@wD" 6LBB+:i<Ϟ=KJJ3ֈ~ x<$ 1Ќ5*J"vww9R aÆ{Q@`,_jhh(,,_o\*ڦ~ȏ@8YEwD3ib133./SH7Jo ~(nݺUQQQZZ*--mnn'yh?8@ x:...t!L wǏOK! FGG˜@ 8= &&d2447잱fIC ر`%::""7,fRa @^YY@&)) ) H$!m' -IlTUUy*`Q ;! IJ=s&9GիW?>w\xx߻H4~C|O@ n,[ x0>"z|SbIIIXf }&22_NMLL~!(JWWUO?9200{Hd8} ///:ℼثLzWoH& B)!"rG&( ޜc@1w{0hnIKKc2{"dLYYهʝzyy4IHH066666`֬Y)))}Ç͸qㄱV333')Sԝ;w^^^? z*wVCtqqQWWWQQ z 666***fffwޅ FcccpeX̙3 W۷obr= --!Ccu>uV]]]++ktvGall ‹T@ES=x JJb'L/Q&q8ٳydXG?׺o1Onݺc2%K3ƍ<7/[)888777777++ٳgXkzz:U"`s熅=zҥ'OѩTTT\z$Z~9pchhO?-\k##9sl߾=77bneee?~ pttOJJ?Ν;) tؒ{ݷoӧ;GIMMmhhӍ7^KSSӾ}lƞ888xŊ ;;ٳСCEEEN9s6:;/^ !ES D7G=툧 /% 2hډmF\ TTTS(4KKA=BHKK%H\PPIӇZYY_z^__Kuuu;;Ҽ<]]]]]݌ EEEb>|陓S__]]RRekk U_+++8`H[[~Lb$Q__h~YFFFGGԩSDbii7>|ׯ_gdd())asڲ7nljj:}Ҍ38@xB[ bll5T\\\WWgeeU[[[GGG툭YYYp'bbb#DJJJIuuWͱ6w5zIEEEIIuYY'OL"x~{{;+S\\y{{[VZ'޼ycoo=| W^z9TrHkkk@@@xxxPPիWaaa/^jUyyyrr>`ذa};/2ׯYZZ8qٳ#G^reϞ=X>4+<<˗nnn29t萓ӥK޾}˯kr)ggh]]}񛾻}>|xoP*IJJ<8<<ӧiii𫬬QFܹ3$$8|WWWtttMM ٳ<<|pww'H%%% w ,,,| x8jee!C`k.Щ;w̜5kV2yLVWW]]]ҥK⼼=-k׮7nG\V^^-k޼yOu떣m۶Ç3f 6q1⢭]UUY[[[[[?xѣGpKII ѱw^GGH~Μ9tT*5""yرk׮ɜ^pAKKK\\WKQVVzګԔ=޼y3&&/aD[A F\\\hhhIIɱcbbb^~ L3n)IHH8p`ѢEݍZ`"zo3 5AkE7 ޻wgΜyŋ_rNDO1WJ"L& aÆq0-->(nʯ><6lfddHHH$%%%%%=}ٴSt IDATٙbaCGپ} H3mRVV}qpp!wMep]SEEB9qļy͛ [+++244Ijjɓkiilki`&...F79rHZZZQQQ02ǂ >s'M[AA֚,+***"".cvء`ddW REEEt@vp222+++}FaF;x𠁁A^^^ff?φ >}/Z>rHJJJIIrJ|弼<^eZWW}SQQ\\o_{AwYrpphll455 YxQjo"i=zǏ1b„ Ϟ=;i~n탛zbyY|9G7aNOOk׮5ɩСCYWW{(E <+}}?CQQQCCҥK۳g{hW^b\qq.:~ĉǏKJJ߿СC%%%>|3P4(--߆4vrr;ua2o޼V***Zj\p5lV9%%EYcƌSTT:r䈀C'(fX'N3fL2!H˖-۴iŢP(OQjt~핝=bĈk׮?^9x ;h 555)))-.H{+>`2=hwܑ?I$?gGL[JL&sΜ9<@ p[->:>>O\\|С$`=:**cZ\\ܪU`p---2dHLL̚5k̙SUUEP>|hii9cƌǏ{{{744p/vwwsAݻwoʕ...Fjll;1߿zyѳg8pdDD͛7KKKcbbp8ӧOCBBTTTJJJۇ|}}Ϟ=zAw<+>>~ƍ4 hh4dΜ98?ܴi:::n޼YXXᑐ')){MHHojj S"ܙΘ1ijjZXX'Nƒ%K.\ȳ&NNN$CII nٲْ^-ر uEc.]ܹs.\`> #pM>}ҥ.ǣGO⍍uÇkVUUutt̜9nݺsε1L [.\իbbbWԬ0a`ƍ744h222 .]ڰa\?ů]c2=z섭C"tuuYYY;uԹs眝CBB444`8fy怀SS#G9)|k/???pelرc/!EO <@)kkkw/?Fmii>}:z}#ָ6ǀgp Nh4*JR֋/i .cO/|W$ft:ӧOLfKKQFFϣNƜ~p3@7Z]]zmx۷o@*(wZZ+W{Wyelq! SJ^aIϲǎgoz&IR;;;PT]]jW{@x0䂂p<OѮ_pE֪`LB .ŪQUUU Ah4ǐN>%_pZWWH "~*ڟ3=sa11??|}fСO>UUUejqqq7׬Y&M`5pT*:7*''ގ|PUU$b8łۙoDc555 8L& Cl/جD"ϟ/ioi`'X,i;?iGLg_QQqF|yJKKeddp8U̾#TpϖEcUe'Kʑ%dId)$H#~͙4u)MM˖ H;Y3^.zSZjkcs]ܽwJUSUn`]ރ45#vl36lϜqw$]B"h fX_Y[Yq|u.7`0`Zp,Drp8U^}KQ\\-}W!C X]C~q/σx侤Z?>^ssD6lD{{4"8s ʛ{r'v$ ΁H|Na1z YX,hN\vNwvv655wtv\|yOZZZQSeX_l"xrNHێnj̬,-M͙3kj4՟>{&K&;/^ '0\]@ _;>*K}k\>@ @ \/;^Ӯo-wNt$@ ۢ%ک", !XhG"&@  ł;аrN8 /停d2DBYķmp!4 Ig@ b ;f\4ķ o1113@ ėDр,d@F HDbx!Ux<TO@ !&m-qĦ  @  `0rG!1ӈD4?@ @}>4rp-i_#@ } 04@ @\Ʌa_T+ Ʉ @ b-@3ioh1OY,jYF(( #KSy@r4 @ ~('D8[4ķ 29h#p شi@r^>/ցyfu+0`wr7E$@|@\ CrE 55GrE Z@wj6b0Ϟ-<;;;iaa?< Jp2VQIh-}/*++SUU%ɨх[aГhuPwm|G3i!++kŊAAA߷oڵkmll9~oLIIXf ϏM,+11=ϟϝ;wM=~III"X]]h`rrɎ;]A O!UPP %%%@EY,օ bbbN8AӅTQ/ _A$377b% LfPPPYYikkko~5cc㈈{CC)S|}ʕ+ }||bbbPϧNO!~tۀè!t:} {pttx捏Ohhիwޝ@YYهzے%K}={ÇavIR.\}x޿]]`رc̙gϞYuvv.Z~z}CC^^^?S}S]aTjii9dȐ#GΟ?ɓ5^pAYYG੢K,ioo  *J JKKE5A=s̗m9-Z%k+ --dzzzݻWZZ:uܹsرcJKKꃻ{DDDiii````` %&&`D'm^@ԙ@)#ll:N:sۋ6ϕ&M`0#ll5رN5c;؝lx.!W6_8z-\8 2E `O ѣC> 0,,,77WGGg׮]RRRNNN999gϞܰaWZBB>q֬YVn怀Ǐ'%%פ!@E bcc>>ƍx򥺺]iii^^nFF=Igg[[[G];z`gee,իUTT$$$DTTԈ#D#Ghmm077*P___XXH$mmm[[[_|c``RRRrrrz֬,III{{{ 9))) |陓S__^hffVTThbb={6D YYY־}ёL&է*ړ1d111Q]]=##\ৢ<E˗/IKKSWWB%nE****,,4004ػ(?WGG:H,DE) X!(F M41$v%;bC=* ,"pǕ[|g}g2N}G=++vȐ!&gpK$h_!233іmh` ٲ2DE; oooQZZZXXXQQjgg_%x񢶶V$9::2 tL]1nuѭ|RIIIn큌}R> !x(xob7wuuuttS|>E,G:7w$ 2NTt%e?A.|Qn ?R+ IDATfnR"&ȐTd2Μz}}}ccO >3;07jHV^&Hy yM|ߦM$zr߻w/;:t(zpuuHyΜ9vrSLA=z5}k׎=رc#GD˖- NKK;zѣ{1… wvvvnhhFrGA'O322a??ٙ7@ ĝ9}4vx֭[^^^{AAA"֭[p3D,q\UZ{'ON0ܺu `d2?K]Dty<ޤIƍ!Og}Դjժ_^^{5$Y-bllll*\֐LfLLLXXXii)S7l؀krXj6?DYYY^^"V "29֭[WSSgaa16 TUU%"xaž.AѣG^VO6eSVd ͜Td쁌}R]>]Fp6o9vhO~O/5}wf<}0gҰ|9gdD?ܼU- oܨ'/bKkw8q0}lD)q^pwt[F{z!6?n}xi陷~Bofx)z]ǴbYZX 9{B UUU>?ˡcǎ-++...\.xʳf`kke˖555 ௿ڻwUϟ}?wqDFFx<cbb믻w7n.]Zd ,Z,ϛ7QQQׯ_wuuߥQTWWWիW|>ᅬ}DxistKKKD)^^8ee尰k׮yyyh nݺKWV}Ν;ׯ_bccVz̘1͎ZiDtO>뫮| G |Y֭[7D\.w߾}III#05k֌7pBsssII nb_WGsl%brI4 *p\+7F3yXAAY>ydlllvvvII @ >|8͖iêH$ }LTSS[~}JJJsssGGB^Yz"##?{{{???QiiiEEő#G9444F[ t;;O$C^^֡*? m?SzzKnnnbX"4UJS}_5x`DL$n\ <L@Ɯppej/+V[n~zZZIE2 ڤ%2WTTYDq I&K趟ԭAJ%!!K@ vvv)))FȉK Bܾp1i5'(<҄`''']u֑d'O̝;wp۰4vJUX$Э.zFzc'5꣥$^Oڊe_!υϞ>[[[nian?Žf;gmKNn^JjXw3i**||M7oMKSVR^3iO6ek㽽t'̟v̝3`anM`0.]y(Q~ Cn$L+ed~wsup85b\ )B.:SC^`0 .+Jfm۶yxxܸqѣG|>:tL6m2U{ɒ%v9<<}YAYWWvΝ555:pBd(Av[ZZjffFѐN'F)TXXX^^rrr``-ݹ'oRWW:|]]ӧ_DǏÞ=*#$nwmmml!'iN:0o&**ߟ<;v8{,\9ܴiҥKnݪЀvkXľ0Q֏?i^(O o ݂ o߾"͖c3!+BHܾ1B\nCYlB+))wvv~}6wvrrrwwVVe.2 (t޸MF֓B_QNtGiD_X/.|*xN?M:}oo23agس'fe_k9sH%''@'/^}9=/N6+`ڬ*^Ǎ'!a.  \RNaM3,z93$m*}3|rPYY)%n?qFyy9q1jkkۧNjffV]]%aaaap8ޞ˗/;::=.Hj9`aÆ?Ə<&`ddtҶIS4&&&''GGGg޼yӧOwuuB ]zU,KA"RJڻ'N,**By9s&X!cNݚ.bڵ!!!_L_ن/"WO[[[ V^ o:uW_}EDɠ/LT,1pΝAAZ/MOz444 זpo555EEEӦM.5 ` ",i=zNZZ OpI _iC FFF7o;wnggg 2OKK$i0j4ƥi#:Lb@>)Ⱥ`  -Pr'1 EK>{6֨#߿tM}zq bƝe1eևz1m*Af:ɗa6qfpU,y 6𩉉d,8X̐4&zF9 ##ٳJJJ~XXֿ;..%%%)(($$$VVVƎ7N>}Z[[Ҳ5%%5..~~~'cu:r;w_o<}t||r vF d2o߮v7o***:ujر~ر&66҉^rٳgϜ9K0a„+WČ_+WTTTww]tiʔ)0,s:;;R [aaaLL DuuuJ:a„̦& h&yҥֶ6I&>|xٲe~~~uuuVVVpYG"V֭KMMUܹswW^X^^^QQbgg7sLl^* 555Șӝ;w.߿P(3f޽{)Lepp*FSVV>w`Ŋ VSSSQQKmL4+++.....ڵk&LPQQH;vlOL"k Ȉ:s ID|45$gggY-MBMhѢ?CUU`ee%aKIIIhCBWUU={(**ٳ&&&&KFIHܾ Zu0hnEp„ Y,qk׮UVM4)++!000###66;vŒuh'F6lǏN}vꥥ W yyyd,‚q\K\7"шȀ=`+/^oUTTPWrv0V\ ]]]|>wŋa; y x8*_t.iUeAV':v?/7AC\ D! _7͛ SNB~LYsg[i/^$_S(pr5sƏ7n⦦N|C;ܿ+^[_[+*^<}&wصm A/ bרpL)\sLzX –z]:3QlEEE@@3Zp6 V55n |6ܬ  ' ̠A;&FĒÇ-,,Qwt!CJuuCB.ů_hii+Hl6JII 9.F yzJZo-@KK n6^p:uʕ88"ikk  4L'K"oݚ:yUQa޾ ҲaKS0aƒS LT&Cf =ȫׯ2-رqӦM<^iH\O jɴ/l ɗ%İpTRYY>J^#2Ni&x#aB[ j7"k[isRϟ?WUUe2h'@ӱz.qyMKSRSap t%WҚ6VQQm?bċ.ß 3 LSSwG*é3CeA~9hogWXTtij.\rtphhh(}YF0$RLM{>yF9=suv`eIGv 4ot8?$tbIaacݗ.^$ً.Ĺ#q$ B][6^OOO۸L&a Kdp;wuMSSsܸqSYY9g6b `0yzJ"+vSaa!CȄb999!˪djC$g†j oݚ:y-;k<, &*!I|#$?RWW@ PTT$nҨK$Ӿ5$_V |'Sy18I~ez ; IX&j3NP޸YkҐ(F]@Shh55ee> kزc'򧉱ϯ[I7UTT<=_UV_/]zX4(%BaXwS}]7c=7 .^rUcg-?n۹hZW~*!߫<sX4NoffogGGzoӖ뚞ijb2k @eU{8!CKg8F00xಲF@' GGbX`3b[)sݕ+W߿ѣ_c>Œ7宮.MLL.\`IEnn.?F(` p/^Hzc##ěX,546p_eh!jkk45%g$1C(3%Ќ߾}[[[J9 3ϗ#v8~0ޚhhh͛J+{i ::ի͔)P³g8Ţd\o޼!ٳw3k)ir48j* eeESd~ $ShZZڽX,}7bq_%ُa؉B,Sۯ)|h4PHS @nk; dLT^&. &|`f(f3LP.OÁ< WP{)|0XZTI|tP(0d=ZdǍ A}=u ̢EPP#(y1Om 'ИLfWW0X, 2+}@pX\\\O&F_cG PW} 52; ---Сr$+ jKIP.Gt9i`E(*!^:hР-[֭[Ç_zu_'"""99ݡC  _|y;v 333o߾_~e͚5#G|jժ۷Ϟ={ȑ[nݸqԩSWZu͡C˾u*33sٲeAAA{ټy%K;&i ɿϊ}# .H$$$v۷oܸ HJJ{yi>m[Ð{\ +/cgqq뾉*|||كcWxڴie;fϞrov׮]qqqEokqIhMޱcCBB㵏 +++^|GDD[n<o7oNHHhnn?~E=522rW޸qcddׯ_Gߙ@YrPtT29yzݻw7lmmKJJߏ899mݺ/{̧3f 8pĈ|>?!!R'~֭[ 6g||A?ϝ;o߾UVz8E/RVV~:ڑBozP)|@x)|`ٲ~ ﻤ r>b_~4- @d0m2SB~,--mll*ą՚|{ Aw0552d),,$y.((q{j$lĉwڵ}8)fay,y9(4 IN^`ժUϟ1cƢE&M͛K>zhذa+Vhllܽ{Lϝ;gddrl^^[>nܸK$٨}8..ҥɓC>l"xZę3gĬ\ ޠ/ΤQOQ~ͭp8G\.lԨQ0n"䦦&GGG~˗/| ʪPQQf0ϟ?͵HOOqvvNŠT;;;EBpРA \MM[&|iiG %4]zubn NI&yqIhWz PWWʲ2dHqRũ_yQmmٳ$4;f̘*K899IُF 466FLW&@4666+\CC{lm/kHdJ'nh IDAT^L`mkkۼy3Z7@H4Gk-<'6In[===EEEfgt&b8iMMMmmmCE|qaa2?I4 dWWWx9Rŋjkk#d_zU\\\QQ^__`0\]]tzqq\<2dHbb"cl߾ɥ/  9K,P)| ^gq֭\///ww={⠠ Hwh=zJFhh6mڄ0@8pɓ&Lp8\ʛ6mr|>)jZ8&yH>_>{ 7Ųa٪wd2ϟ?)[b #!!ٓ'O>tPBBJl@ PUUXDk׮Ν'K$R]]뛔sU EP^^ Si :ąZxx޽{ax( &VZZ:eʔ 6,4cK988M4iܸq"MB? U3Q@mmmCYYY^^ˆLIIIJJpMN nmV_•?!ab'n,I aN׈#t\#ZpK$?7CFpD̙k..;edOe˂Ҏ=:zhh+Wم9r Ȑlٲ(T̨7o\|9*****rGozggg^^ȑ#?)((xN uD>QOO]c`cQrrr®]VTTE.\uVn")++Ϛ5 ӝ;w_^EEc)FGGZ Saa3fLssc~~> fhhhhh`ff011dܹ sݻbرeeet:ŅJE###ss~988H*:t JKKz:d``@/t $oggbVXq̙ltU(z^NpJ Y%5[[-[AaFDDY[[;;;xzzl۶ȑ##,4cKӾׯ_ ~:uttkm>>>hF ի'N8qD[[۝;w;h[(npkHXآĉ[K)\s3f/Ҕn,$h:XIZғy9ybiaP 믽{۷o;vxrrr"##y<ƍK,Y'b5k֌7pBsssII iɒ%111;gώڼysLLɓ'mTWWKY[[K|zP[{j#O(@ 4*oﯫkooO?+**^t &q^ɓ%%%#N ˌr GnnnnnnXjh4+++2im$>9`aan:fnnD|c6442 (|u+ ŅF <֭[nHT& @\pqqYYYÇg譕<]JJJcc#IfџabK~CC^uu;5+/XXXH0B^>>>$M͎W!(Tdjhآ,X 8nUq,I̵[eLAyĚ4'OF25=YD/B(8ۈ֯_񴴴"##?{{{???VtÙ0a|nkk߾}K~4YYY)++KˠL|8Zʠis~B!u5֦%&&Ο?_WWwWMDm67n|xɰL/@!;qm … 8I=h4ҥK80mڴɓ'Kp L̒8曨(xğ@ ##j|cGؑ*?V4 `)hhhHȟdEVUKS)bsE;"22l:D"uĪ{ɒ%v9<<9WWW א#""`W:U͛7WEEŞВXliiz o߾ Ɂ;񂃃CA9 =[0pǣGhHp nYh4 &&&''GGGg޼yӧOwuuB_zU,Ϝ9PrPYY)ѥL8} OEEʕ+,d۷$K˦/^@E??G!攖c٣)n='" ,?N|<~xڴiT"]233{/.>7nKt8kjjMfi\+**֮]_éVi y!==w\X&.K«J ,IӧOc$La͕IH^"7-[4C qUI`ΖFiSUWW#Çs8oooOO\sX\[[{U//QYY ؼy3|4Ni4ݻw9sFKOO5BYYٔ)Sm?##N744ܹs˖-Æ #^@rrZPPPWW$M{>x-11ѣhJCDDDnn.moo?jhh䔗oܸqΝ<_~'ǜ:o߾7?~…0.?p;88\2===##c***Q=]]%K߿FmݺUQQɓ3 11`Rxĉ[nUUU;880LD /а{*6l0p2x%(Ι3<fC7~W:NrmMm %KQf*,&Ť3tʕ+wXxq``  }Oɖ[:>g`x[oiixHt 쪪*%%%$hX,GMD{.4 7X,ollZZZDeSOOO 2I&'mROOO= =xCb Iȼ"jjj f NqӥbU\XEEE-\ݎ;7m ?n|Ǐ+Wŝ;wNzSn׫T4 'cH袥V>K);" :,YVk5DJ[(+Akk h$͊M[B{Nϟ0u*Cʳw6lUUUY, a޼yCg+gTS(ipT8 ʊ,%II AbBJmw HѰaqlFi{=27IF &4g =x'Wtq NBPZ YŅhm֭Æ ӓ¥u8'-/fUraa!C>rrroԧ[+*2*hiĻ*n)s%vDA`u2Y5iNXr@Yd2w3"FWϰ@P«WNKHg>11ȑ#TG^.W!e3hPHLҰP)PQx^0x`@B?rrr _5&_\rGUWW(//?|0eeH3W(`x>"аty]fr _' Ջ|gP`9B 457kjhGbB;/58ۯĥWx|Ob2kׅw[y! ೺qм{ _ql}1.sgOTvt|Hf,-gN6udx"BiY٥+W\5=qVW[^N_:/{** (P@'=7nwT%w'( G$t}AUeqZMr#ÿ>}e)79hii.^P(677M]4@-sԮ.`@GGG˗g]ru_l]|!GDy*挅+620yaNΩ3SLs/ p7+k]NN7o*3|W(P@ >$OƓBQL&A,X,9d !7B1tHqEf< i"bb BSj?i/\sdz unyƩ3SL:$s@ x-:ž4}XL8st:::%^iS|J%%%yip#ZnvG (P@W}BYw.gfrғA?WNb~pi"hxqOvvVS㠷;Μ0g`m[2tu5Fn$݄LMLvli;D<-, 6^BEp<6gX,>/,7248a`(Q&kiiQ`޾Q \.1CFvN_;Յ@hF'O:ۣ;;;o}Q..4S4 (P@七> c38l4yiQ̡پ()ٶsSV-Cgv/yB!ZZZiO>|lŋ,͛vݷr׮}۲ee09yyu5pG|&v'f|œni3 ?.\ ^`?- TOlyk6n035=jڋ탠j$(ພ'N,X (P@$8 gHhtHiXZPEEE>, UPT3244~.,.\t5ֶffsݾswʤs 7774 =D.NO.NNN,xD___(F2ffׯ's?{8wxp3qoSr&w<)D;wfLq^?_!A@/Qie} (P@6TQPtT@T@ @Xti$kn~+Ԥ'_p8Y~BpeϞ5jȬo$݄r\S&%9w&.;ƌF<]P[[Zd: dþkMMkljPWgp pQd=yklO 477 K ,9ޜQ!{҇999=<77"==]GGfͭp8_}yjjрMMM666j?{tԨQX,ruuufffu.(P@ HS,Hr\*-X$w9hJ$UeĀ58"=+}5s4k++C y$(**F:%HUUc:^cmt_fe>2C[zUk[۪50 ]H0(**D 65PX\$&o@>'7s.w.7`2ϟ0fggO<СC [nzyyٳbذlUUUd:|p??M6%&&PlڴKBUD"[n=zR  (P@"H ȭK&Si3HC[0FbҼiS^O6 H--,2n,.>\ҹm?bċ.aC?,{҇h~|@Ggěb8=9hogWXTti- nc.P`?K"IΣ]9k &&o3o߮?7x׸蓧h4Q.~a3Wgg i^|E x mm_h~3h4`xǑ6()ٱ'hyJߧz OO|رc/\p܀7o444hjjY[[@ xf:z4jeee0PڵkEEE^^^ :99-Z (P@H$`F>R^~RSԼeTXwS}]7c8r0+–?tFMOwdMҕGEC9:rDG `XzMżύ ,3ӻxʥ+WMV.77ӆv7)Hmh;v6^4s'Ǒ'OݹwZ#6+߫<sX4Noffoge=iVLSY3go^*<|KcƬ_#qZ'0!BB\A᳂\յ駟p_}$|Q[ (P@ z8?,5UUffˎ4M[K=Bx451#4A1'L Ч6ЎZh̛7o555p JX]^^Kmĉ+W3gfeeuvvīWt.K) (PtPvt:]̚|J-w\\KJJRPPHHH700e2.]jmmmkkѱfً-?TUUNNNt:ږ)))θΝ7yԔFYYY>|xٲe~~~uuuVVV4ܹscǎD (P"dihPnW\) AWWx@JO>%- u+|μ 9ƀ3999Q;|6]UU E"Q]]l(ݮ-bqUU>uԐ (PQXYYbEËFԐي49,MU*KMQf*+Е ='%x1H$bK-b@t D:haѻ)P@ >(.F) 65*> (P@.d?" A:B!tOjvuuQb@ (P:¾(5Hrnc2z (P@:xWW<#ώ.%b z=ibX (P@ (`^@cXBJOx,1L&FA~۷o)QP 0 R4HHO I#'`jP Ʈ0 2k 2cjs%5J8=Frr˭gϞ EZ\\Zm=(B#^<iSݭ"`x{{ر!!!!!!THgJD'NPB@ a- _~iJ1YKJebuh7Ii%KCI*ג!8 ="=RΤQxz>F 7Dhp%%%eee$oϓ mP$KI~)QޏdC5}d899H$ B?3Juuud֘ 92 bqWWW{{1%C lݺ/(--MJJTTTD痖*))effVUUX,UUU@VVݻwtSSSLMM\n]]r---JQQQAgҥ6FE`!GŅQ{ lSLO, Y;i򅑑y~8'[[-[v___޽{---===^^^]vˋF-\p֭CݰaCii:`zD6X֘1cmllД_755뇄ꪩ7nq644444tpp033VX$SVV5knSEEe۶mGwZ566>}W]]AAA666X`kbaa1vز2ooo:rʕɓ't''4ڢ766@"\.W^G`bbX z\.K D999 aaa=P:V4|h33t.;|{{{bv[\B%bmʊb~:w 4!BX`^OydnDt@D[yi>WzѫVhL&]1. 9*."""220#:X@ }Τ B)P}k*{@ >|8͆!99pllu5@'@zz"\c6442 & zI+++nYf޺uk.\7oץ1mܝdui3q!554>F{{;K]M W>Ԥ͐p^]un~hK.=pi&O |>]M/ںӧO"/>|ɓ6}ijMMM77+W+WK̝_۷oAss϶m<<gdֆ,]v[+7DEExxxr$&1dEovqq"A׉?⭀҄LVXbmmmJJJ]]]bbbhhǏ544ztbsjmm1cFDDԩSvH,Cz %+8ҧ  (}ڠiD*H KBT!XDGG z]xo@pqY=\-@Shh55eed?.${Nt ĥWxOm{Q?oA>Cӛ19u47g~TE#]xN8j[A_ O:mɾەQ˖]g\SמB B a}]]w^֎@P E쀀ҤF?\BPܽ2s̙;hߡ'OGKpBu$Ӥtkqoׯ_/++CN<}ӧO34gQQ!b/_3g_ze`` [n577>2*]TETUUעJt6x999eeeQ]]]RR2n8*//_zupp?Ll UdEi_ EQ80 $ !PGɨ9cƌWWWKxiӦYfO!~lw$#*Dٯ(BPkm܋X':T[jxn5(6Q%{s!š)//ҍLJJ'Ii8B ȭv*c;-+[ GEhjhYӧauTWg7h9艈K&%644ԉhanLLL; Zп JtŤ!v{Bٓ'z+=c.v7**"FxO pb8_<}lfp;]YYb=7̓4S$ -dG")۷MMMCN/'';___$qxx8L>{… I$3gz w;wNMMmРAk.* nTPP7P%'';v}422rӦM$YMMmOEUDGGѣ 4qqqrrr7nܐpYYYd2~6m0`R:thϞ=?vuu}@^Ԓ())khh:t窪(**RVV0`@`ee/Z]OO?۷oC &&&߿G/A|dT TT*ӧO<.IT::t($$D[[{џ?^v7otuu갨HKKOC_K WTM322 nΝ1110,Jwl'ϺJD{okkk% p@CCC73(hLDCŨH}}X"K"P}fnJ߿[ZZlM%oRoݻw$C]]YI#HX V%s\3\GԚe˖b2L&+ϟ/n- bh`42ƾGOQ},-'kW`~8\&Za""o%_CM0#(Kp&NRQV9r T*EIII`bq8x߼4WYY9\JOTUT7ǣʵ~8w̆_^`fYMM SixՅ_{8y::3זdTRTğyȈl,EEEx^WeA6`H~q܎:AoǏϝ;Wx<^EE?y<އ455ۛ544PwxJ]]]~.`ĢCNN:2,6/jE\nmm-2}$8Fc@m۶544lܸNOOȊ@._ٳ5k֐d{9JJ vU472LYYJyyyKKj &_ .aدk׮a]\\ܔ)S{ (fV/StJ <>>DX3<JGGUWRo88 :)߁^4ճxeّjjtyU:MYQ @Q-ڰYO53Hrv ^ WVU ڻk21'OXvoxc&eA2YEY-o܄zm5YA]9~gc*4h22Gxx _@_93gU/u皛de\ܺG]vpiබ-;v޸d[z3Ҿ#A=T]]kȾҢquk~6R;!ؼyuttN"!H2J) nkD j23@L%) z,jblR@BR ƙ3g$. N(uǟ6Dg, p-%:Y .aدpl!p8ϽHDAP[PlvA~)L{%Zxl"X GPwq2jĀY ?-ؽo!As55}Q>|(+/<1Dm~(7|tut(ۃ垍/--lfbߑ?zkiȠR(v8J >6'ݻw 99977f'$$w6e:t1#GZ# ۊp/z B@H(] lw!Cg 8ysCs22=Dm++/c8 /\XMxq:LMMm{G{[[ YYY!K+TWSSy8_uWF"'NF͙9SSC#3/5$ b2 _~n*#_q3VixQ{v|(2žr=֙P{eddT*b„ R2Pe˖jV%G .bggG? B\.Y uPd\4?*~h/"G17r.&>zC۷o--NGM4IOOCxSS@]]K.N ƉQϟr8lq1d}=;| pdTLl2L/^J.{;c'NF9vx&;sfCY\ZVЮ!i,[Ywd__M(_ALLH?D(ǂD"X,*ͤ vSg:::UN<1@!ÙhqS&Mt2Go܄\rX1}밡g߻`^$ː~z**&{gd646Ȑp p1G 4 eaޣ;4},-]*=vQq }/?k0ϠY3.?+mF.?ciHQQKS& >|'4= &H߲2C x< t/*ఈQ()^۹A%ˬIr}EwԃxVPӍ0n, l}ÂSgΎ8uJ ! IDAT؉M /O2|_T>x䉧^|a޾8\@& <{8S{;ZZZ__ySV^>wlOcjZOp8Vo\Lxy .[:tRqۿMMMeee}I- =R`2R)lkkSQ!ɵk.B[[[yyҝ^S]MCQ$vŒvN'o 뫥USSsYYِNLMbVRT' '7/wWSS{WZ~n:w!QZV|3{Œich4A%%Nojbtw?:dq8vBk~cFh4'G_!? >g߽[YY5sZ`/#Ñ^#NH$'GG&Y\Ԥ7F]{caiut By̩ZR$eEe3g]]\LIt;+kρtw8 {Ҳ2WysBp^gL111SLYjׯߟx!Cܿmmm+W޼ys޻v5JMM]|޽{M~Ϟ=+Wēm\xHt5w9[[۾}򧉏oiia_w6665 {ðaTݻwڎ:&-r6l022rss[n]``^|yʕSNݸqwToQ*,,e6ɓ!!!+VÎDK\^zeOZZZ7n~B{NSRR󉰷lnntSSS3fXW ɲU9L0H)DG[3#cOVuX׮0~81035]P7n***zJL|Dt GhuumPTm1>޳fL7;\LJJLldhlIi_.so;u Jv:tݶL`u`$33DDŤKv6_NG=A&{ۣ]ɏ55s& ǚ$E>w!lܗd(֬a޻LlL0_8`xwF9 Q#;vӧO>}ʕ+9dXf Juuu5ry敕}yyy-Xŋuqqq CII s'NR(IIIˇ]]]ϟӘ7F|ܹߑݎ 0ǏϚ5KTy߿oZ[)i#^znavZuuMbi~~~Ϟ=C=E-)Yrxذa6ǦMbbbI,XM=k׮[NCCȑ#C QTTLJJ}.kL&xB𮮮K. `pz'~~~+WĈc>ZdɁnaaaiiU]v J71/[CmOQO[$##XQo=krO e/qo^\W_ܬ]XQ6uʴ(wn~_+>(+UUT9YXZ"!C~_WQWSC\( g88E%tVQXXX9t.mI.Y 6=J>>>d2999?(VBB¬Y`Ҡ }^oKK ñRSSΖ111~(fmmm[ZZ޾}lllt@ϟ0̏?1Bۯ^B$~&###++Kf555C ׯ+޾}-))y捌LFF铹Q'5?~܋/T(*)D̓&ɦeggkii988@[ ɐ'---999EEE2/LKQ~uyyy߾}5ioo!HWWY.$6f@ O>)**"WcݺuNMMMXc744LNN'<غu+ rpL)a؂p^T[СCA*.d2BPTyyyKK˰0WWם;w JlGٳbUUA)((t[~af'Ǐ;vx 9T`o2L&s\@&TL8Gh$ę4`ĉW\{ .]*++{U5ׯǛ={6˝4iRjjcDz]~~~@@@xxx|ߐlܸ~\իܹs?pľEX?r:  |@8%Bܿ?Dݟ@<[ظ||xkkkݗ.]z޽ݻwSNݱcGzzuIII!!! >z([E=]BBΝ;O>=~W^=t'N 2w* ##vܘL֎|JsMMMrss۵kBpBll,@FF&>>999cƌ ۱cǏO< W(Jttthh۷o}}}#""6l؀: _JJJ***Νr(vEEEy{{T<|!$)C9T;99 ?߿?xW_ϏǞ+VL2ĉ<8rŋ?~?~cǎ3?FFFW\QWW8cƌW K)D*1 'Ě-&%T\sC;TW/^yرCb<4-++j޽7~S9K/vA*Ln'0cZd֖PN1zhuMn&''{y8;a%%%^^^$iܹ7o%tvvFα캺:' ޾}طjall|Ν3g޾}[8aÚ gd2'NYv-=iNNN{qj۶m/^ ݿ]]ݪUnnn~턄7oPx3fDFF?~ڵk...92::֭[ߏ+))惧"NNN}}1E M\\ܔ)SPԈ-((WPP 522255x݈# ƌC& Fff&lS'''gggOOOEE-[=z#RDl޽ ,hh֭STTӧ\m,EQIӅS'rI擃O>~M ݕ,++++<<JKQ^pattc++;vDGG:uJYYȑ#$% <_### E~E*E~5% [+L6KDuRqnݺgr֭]~=.. .zK<~=422rvv_#""޽9T< |(|O=g B"t{ 7̜9I$ҝ;wh4Zbb"La?c*rrr]QQQgΜy ҳ𨯯ׯ BTQ JLLL Q)I$9@x6gO}vҥ\v `oInݺ:8 ڊxG=zTk<$+V@Ik<INN>tPyy |sssdJlM4IKKYE&&&Q?#''7hР48ٕjmm xĠ(?٫nQUUgD"M<رc?3ҥ^j <شmݻwl6;((ի~޽A\nxxӧOwL@Q֭[89Uj^ XbP-8N߾}޽ M[DmO>> 궳K?(L5+Wq2G*8'o  !L8qbhha͛_5?˵O>&-[_~ӧL&1?#Gƌ_'-P !e„ w;vFJ؊۶mٳg&&&7n\h Ehkksvv믿֬YӫW/}xXBϕdܹscFFF ̄Sٳg3 9\dmOԤ&''<{ x[[[|0gN8zIb!H٩$wb jjj~SN033æ(n nP( p$-'ϟ?߷oѣG?~loo{ A'"„G5l <uUۂdę3gv E0bĈ q^[[z޽ݻww[)1DBT aqj4Qqm+0 BH~~~mmmPɊF:vCd[˗QϿ%f቎ 3͙3^200 Q%!>>~ӦMf駟x<؇{U^^/"]\ү_?{Μ9+Vhll:u꧟~]cWUUIESSҥKC-,,DWꩣVD<ήp=+++8H['O^>>>ݎdPfffvvpotttnn3Ə_]]-:Q| .)) [0g|||JJJ?oOQa~J)P.NHUUU-[xڝ;wN:󭭭=:mڴ6ăֱcǪ={VVVÇppaffҒvZF} % ۷ccc?}t…aڷoDZbDZ`p˗/s855Pay{{ xC )((w޺u~ bffD"Ν;/]ZYYYQQk͚5ZZZ mmmzjaawllltttll󈈈e˖@111W񣟟F;uꔇjEe˖h4daaޞuܹsGGGy ^Ͽs玀>/BILLliiimmClll]]ݍ7X^^mjj]ZZz)xDeeٳg ?~Y###B<\.wРA.]bXcǎADDĊ+  CѰ0T~2 7n'-sڴiMz 233c2˗/lܸ]SScaakll|uTZΝ;GsNcc#D:x,X{M===ccc[B:ZGyyqWHeee~,'<Y 6EiӦSYYYἃ  %=\(`O377G.Cu[nURRBmwmmm۶uttSK=<o߾rD___x<SEB|{PT$5mie˖q86bL&l @[QTT'Y^a 0s$ttt l" *++qlll*++uuu_sChp .I[DXLYl *8y䨨(c<EQQ 嶵 tlvKKrW!l68 PҨQ ,LTޯ_?q+LM^<7ݾL&SVVR^^5$Xl۶aƍuuu œxUUU l6[]]]n7@kk+FINѲ8?y4Ǡ#YCCCYY}"A=71e2OpLX [ÅmqF s==e->;?y9X(#F296(*!K%%% Q]]gcʲ#Քt]ANFQ)vG?*v""QH$zp0FP%EQDNM.\bE\\LzL>ROPTTT8~P(+VJvP ޼_/&@sps̑# dP(*p"]O /ǃ DGn:kѿ?]=+WӻE93||@JJH&.ـN@$o:(Q( #9@%4?*8w!@@tb's-בX?QcW\.= &_ǞV6īCtIz=6\.׈U%KXZZN2%""OݻwDTbR͛7mmm׬Y ve++M6u6x˖ 55u+V7UJbɓ'---;::.]:vp=lǁīc ~ .]HӤ`7p#È#m`䛍իW>|)Sּ]߭U5ry}3ᇟdΝ;WK/ %@eKW`c>mOOϐ/_Ξ=R+nY+! ?dv:AX_|q>!~dWzzciy>,}uʵ+9yk. ~VP(+Ξ1{ 4AAQT0iShkkuSӦed<RǍ;FNNGd*Yw yCuuXч}edx|Hs$ n VҺh݈yʚÇީRw1oWwksuvoP/1b0?}tߞ]iɖoV0Gի1N/..Up=l]q˝%bh Nxܿ*EZ0 r8 {{<ޝ}NsKV} ;zëדgMS]ݠ'".Y?~ .쥡N G s^ǝ`fbbffYEOӂ lTʥ+W/&% ֖z޷̞?_['y<]߼ ?+(>'H}(y"1鲧:+k{+fu6b/!Y͛7Ϛ5Դp$IUUbib~mZZZSSy^^^AAAIIIuuu^0|2==]^^>%%ÇHϟgddX7oH$~{|LLLd2LL"***MMM?.\ׯ?|Fijj SWWgdd$4BByJ㥧4775ףG뗜ԄTX!b.D4--ݻwL&UK=zب'##իf lD"^!$6Q ӎKٳRv ㊊ UU|ir>##իW鵵ƨ *N0Rɓ'?~y$׹jG۳KKKkjj$p\ $ 'l=ޱZ9dFrrr?҂g ],&+#'KBȐ:=c+'we#kk?}ߨL^v͘>d2, QtɓfNi3FFQ1g{]]ϟ®CeSgN ig"YL5 UZ%6kOEnjsz@O)wnr|<2ͮǣ3qqϞ1`mivtt|{-^8ȡ\.7mA vJT*O>JJJs~ … Լ#$$/Np]Q6N+ih3+ip-rF[I&YO7rΫ~]7z>}F_p qk6c> q\obde8{zx 0s`an&MlqiYU>edOSgbLv<$r^b<>kwϕkŮ'tuׯ]3lcd.d:yw'.Ҿ/nڵg߲%}wMP^^S]^I^\aii?x`8?-###OOO;77^AA!44;ǻwFA&ƌC& Fff&R'''gggOOOEE-[=zicii9lذ&>}f)((L8~ .A-p.DUJW^-))"Hsݼy3khh)B]TJ&FQQ׭[اOq"|rhUUUl$ &cN~4),]m7M:p8\ncSSbEEnh{lccVxMMڻXءÇcG?;mso\_0}O9-đ6oy`ՇeÆ`Ew}CS._Ҿ1J^Xc̜XA^Kk+,?׷H}q|=zHKK DB?ə"P/ һwo͛7LsssFEE=yرc=B$F8!Tb_3;wh4Zbbbbb]]]sUɨ -.҄q-kkkd>-JudY`a" BT2 '<*ĉ^Ғ:6MP`鲅RP*MX)o뿋nTT󑮏6#G ~fʭ([ǚe n*TȪo_ 9Y 5חF{WZz+- 2͆l$t޽yqVMMMZZZmmmrrrHHȳgϐQhmm\.|GGrlU,SSϖ-[ݯ_S& _QuiE bbhhhhii?>D~)K1HJ <t:FOEaVH9s& @l`ێDFMM5))d-[YV>#* I)@"ĉtGuq p;K8I({uu, yN 9B#< 84h4 {4׭^돆gvyyy=w!af͝w)2pIIW;~UUbB!755Պ_rN O /98 P5 3Bپy%W'M}VfffN>]@jl6 ''y& ӷnjnnnccSWWw}dClH!A}jbTӬ٨EE"|:( u︄Ap'qD)%$I(b%+%թT*[*tt^HI`L=&6VYYe¸<VVnÆ?Ɵh GOΞ1]TtGH6@ÙhםȼzzIjjj\] mljxlƽ(&8yk7nfݽ8y@$xIMUo)ƍubۿ߀]urtBͿH̬:~H tu͝3{F``K)&:sMp8͉?N!%%e߾}mmm 9zFuCTVVSԒO> ,l'~}XXXqqF]]ݡC?|"ee dr}}7m4`MMMccp2|Y## ޸qرc%%%_lʯ'''WQQ} %%pyyya]XaÄK%!Pw:UPWW۷]T Q /KK]]]뫧]wvAU2 CYYWQQξs玾(t;;[ɸ}66:[` r ~" "$$J cH%Lv!06m"Hjjj?sL޽ṝsΩ566[8ϟ*.**Ҳ޹sgLL rxRo>  ۻ5j^N9.ao,]XWb;G՝229QDIbPT3(莤e˖b2L&+ϟAQq~rk붤+W.'+*O0aڕ+/C7qJc:rDؑW.^0B :#(KuƍDw(,\8}EԙLO;*jFP0DpoX1cceddL8u/Q=x0t`;۷"</`/K  ]P`"Ji߅?o|0''-#steeѣDžKXlhԉ \]L< Ad2Yhjjwz֊dVVVcmаqƺ:===ǫ#h5Fc$ ç᩻@˜.\ WYYc(;;FHp8xUUU l6[]] @^GGG8*E}&XD%]J X,2.)Ç455ۛ5440v ' X7eM2w{O]Q_t.tD8ݲB.1H/^())q?:7tly,^Y5:UMDUV+Pr2rTrΤx*ƌqZZZ555\ 3So4359ZIQq\t: '7/wWSS{WZnf՚>7h(-+KKAAAAAaƴS14~Р⒒SƏ751xWPPpwd8`{ \;1i4/KwQFFMMޭ9-HQH$#,.ydjRs?>oO 'OsW[͛gNzۆT %/^(ˇ!;Z9N}CCMM3qq4c к8r@:fx5q,M x:c/ݷX,6Mф%H$ sw[UH%fhF]B"HK~ [G[3#cO:F7c^~'+;`htiCG߸)1P Ghuum^G[{ - ѹt`ْӾ,3:%:n]7yh4C"N{b% u {Afia}ݯQ ɽ ®r}Cǚxb~illBOj=/*۷ä+W7n PTP?nyJ"uv?Z!wVw 99977f'$$`܊ChH:<5 ntuc'CWW_ܬ%UͮLVy[SS3\XOCɋ{22ǘvGd0XO>1 w @&xN3i#ǂ(8PW=@P(^F? C&ciҲ[_$0 Ǔu @pB~K&TL#%N @VUdT&6 8dee鹸?^XXhaa~-&#FH$Z @WaԀPUʀN @^gضAPC Hw7d29::@jjj^^ۮ]x<ٳ\v[ IDATIRSS;EEEy{{TQAPPP]]ѣ.Q( .b>|8''g̘1b+ёvƍ'OBBBqdF@ 72Edy1 ,dڵ3glooWXX؎;?~hзoFDDlذA@?mAP"##d2HZ @34)l'i~ KL`ff xyy߹ W^-))"Hsݼy3h֭STTӧQ_ACCӧTTT]6{lbzxx{nĈd29==#˗O``aQ!ulSJRPX__/? B>fffj߾=܉Wp+**lpn߾maaaii)w}vmm7n\~/_OOK.p#VBBB```XX֭[|rܹ #))P ;vdffjii988ܸq#==dVUUmڴiݺuxAeO􈈈즦&=ڵkR1 Ձ@ WOEEÎdfw:`#[ 5x5cla8l&d,Y:f"H( O<UTT~nsʝ2 6oߖ"~ 2.[\\V\\lbb&+JJJLLLb4ʴO0LHt̙#G~z#|>_,3 % )PRRbll/9m'dEEE-q5kTVV*2LWR#'''G Xfe2ٛ7oD}Zj5_K'P9j<6F{mFcXD: p;a! mzzz deeVСC wj@BYZXX(H$|>UKBN@%a <J*p2'M"0iXG;MdɒmmƂݻw#(ŋ?~,AhU' DL>>@׆bδ;6oB~ammwl_pϯ?+'D"qtv7!3u欧i𳶖Eoz{+as? &&\8Ȱ6!)9@Ӵ4Tr:v7z(< 5PDф!*b"?ԙ3UVVE ۧn-?H$@  ~ES-ޓPA?MIq~c{yi}}tgϖH$$&-g` ji"HCC#pL@ccc˗Ş<U^mۣcX[xi7?>xh:h G芋gc~N722ӫY/0L昩6)@ A7໼9;"i0?;%R)惱LP( ErDi &Ox휠?x:iRakjj&XD"D"ZS'O9}ڴt*(NBWThk7 1GX '`6<:|9:}F22S&Mҙcjn?4669TW)w!qrG@ D-b0p#?lN{?Ua}ӧTOJήCgzsf--~}z{a,&S[Kv .suYZn\}׮iffeI$NWǹJHJ3T&8yɓ/ ̆ 2cT!D=|,t rʾヲ&&!sX644l}WBS!1t28N2d2YFFfo''N 0Z@ hm' N `?4Ւ=߯Gn6lڼ/:z_S I?,&&Ɣ>D" F}}}bRrFfI:::lkjj6ose};:ϭ,'r4WG}7jqO ۵;ŋ n~z;:FFEedn8IBR tK ]qns]9pPYYycScCCCk'^\.  ߊʲ}F\ 0ۋd?c4}cOL27(PRMBa_ط/KW\g7 x ._'a71'@ hhhs#Gn!8r]^!D3zj @ ><~'MAdq,+5|D_OonP 316673p$D*;yÇ%K_xxm{+I9{m&ojj"Gxmm-@OO7+'W*8c_:;ڟabb"Hz:PPVVׯۓ޴[>X (|JFS!yY3-\t:aazF@QC pt`@ @ ħxpbc{?QmmbMMjM#&'\H$AgL?_>w߿p2qXl#cF鄧ܺ ѭx?]Cbmo\t۷OLJf1p 'fVa:u&Z@ X8cefeZZZ6j{3CS|WA @ Z=J, p&eH:uUp]ιr_aW^>{Z:B4-G?~doƌ^u1>M'$boζL&;طt`c x-_w~Xc@d2D*X|x?_O/޻ !)yks33vk|X@ h'whqX9VA1x /M9kaYYg\n}P7 R$sNio8讫eSS#=hljzYPpL-Ss;ꕕ/16OCG{ ES鵑#|~}_h_a# :Ң.iLngi1kphүP$qsq_V{m[;w+wY0/š(C6it135dYY?4p xgbqCCCeeջw' 1'[?@ a& ?1?C;IJzSȵo(Anjy7Rǎ:,^0?l .khhxz N߳7Թ__|ʪu78ӧN173~p3gN0_po&ï~]l %q-y GLܷO[wGqvDSyvl6 LUYi X;[]0#|@ V?luldbD[p%`k@  + ZY@W-- uux<&21`07hC @ Ts\klն6wPgGZGx(PAPICaD"[ruر,œ̟?" `˖-k׮;w޽{x;;uֵ4a[RϫWsҥ_IUR6T* |왽}MM͗P T?>|f\5Lu+)p9Ii h#8dXp ک!0<=hh'66?^zx*77۷͘1cҥW޾}}V\#G>} gϞmmmݶ taUKTT*#>!C)ųg^~zzyy͙3˴<6WU:2IIIRg˖-W(B)KKK̙ӥK/_*x=L>^HNkĴR(Տ/#?3lD V(Ѧ_`9iUC?=Ǐ߿ Ur oJ# -M윟l\aUH^^^kۍ䬹\Uhym*JtnUe  Ƅ Z\Rȯ4[[[9&&Fsȑ8[#AVmWPVΎhsRzh؟pe02Nۥܜ`444\ro߾;wnHMM-++D/_>x]vQw-,, 999ڵׯy왖N:ikk߽{[n+JUB͛7Omc3,#?H0湡6JSSSBB¥Kb={YŋWzyy 8p˖-;w߿Сի+VL6^_fMbbɓByÇZlvLL̂ ^xj*l6{߾}۷o sٹs'AL& JǏzjDD!INND-*,Yߕcǎ߻woĈv:v|ӹsg.I~L(Hvv6A9v+#]O<4'['9B.Ν;EEEy9 MQtAY|%ɷKYr QZIry|555J-o=(;BBBn [ѣGֈ{AWFrr0ـRT~Sڡَ ?>~€A 8!'-ݻ[nVneeq_ǏUUU/X 33sӦM+Wܹ3f:99֭[#GZYYmݺ 677`㕴uqqquuذaÞ={ܹCjkk훖@|ܹl///1{^drJ4hP~~7tuuMLLokkkfffffֻwo+++(BA={Fѕ 2jd XZZzzzҕ̙3#F`2e''-I _^: 5'VR四[[[[ ~2]CV^^^{D-,,{ݷo_YARRRb```q"JKY#Gvqq9|@@K>xöE\֭ۺu2=z(/H΂Pkl;"O4QtT9iL&c|wT W9Xoo3f̙3FDDܿ۷ O"?]vŖm+WoC~e@RRRNSwwk4!ȧxb~x1zꕐ@*||wA|u>ԩSNݾ}niag̘!t o +eI)FWFE!hN/it96+1H]p IDAT6"811Q~/S2Jf gެx]("͵NMMMz)t@ 011Nc׮] WB=鹔ruuwmjjr%jtgAl( l`#_:٢_.=i6>OѦٰaDž =z$ LfYYYBBByyŋ,YByd>DSS:u?!)~w1-!K7443f @1]MME%jtt1n޼JV +eI)pZt>kt}gHXQpՀŧkr*HNQf)Pf[O)*7GG檯___/8jD[b}w1Vji"KS۹sѣGAΚB,(o4`OQmiͤ!*X0j"Z"<_N^B~jbPTT$ݻWPPcS31;;{ѣGk)S VXXXVV9s5A~ii)A 4;;{t B_eհaZTX/>w|8y@YRJS9kJ)S^~lcA(>] c%:Spś2t  r*~\5LL826W@v PvV-t(,,\|Y-ZDX%grKNO2… \rKnQt#'Aă C,v [-&H$NNNݻw-H!TR^^me,G{+,*t}T* Ȱ/FEE]zwthhhjj*\4O&544ɓ'JWWѣ<ҥK,ƍYYY';;" G۷o־qFJJ `eek.&yaKK˹s2 @o ۷ov\v /qFzz:ɬڴiӺuT|rDDDvvvSSS߾}ɒtesm t|kݻ+^X===|tIII;wׯ 4h|cc={|;;;B{%&O@.#A>!k:H_NkkW^$dddر#33SKK@9'HV,|РAϟ?,T ŧkuvv&irr2]r:wڕ:Dʖyƍ+== PQ١CڷoP*SUUcǎ={o<芣utxJKK[)Wmݺtݐ0TDa["w.zxcŋ/(vww'gk.J haa!]Pӆ RYYr5\, ~VpqiY)D5KsY<.ar f1K,H$ B'OƋ;u|ȱ* .5::HT~ǦI "^8{&*++Έ \.XMMMWW{AXRRbbbR]]-(Ɋ;+ɏ2J7n^fMee)~@VUA2D/]Kr###%KJi72$ fR ANPI'$ҒDfx3&2+\fL&{Accc}}GcG(&L~lgZQ\+JKqҥO0LHt̙#Gƶh>橥H߳gϖ3!M 3ڗ8z0ֆ2͛7 le"YA*]GW` <0['-77xܱq~Tϡ:چ؆8ogϟ_9VNBD:o/+BgYOgm-- V3礥pMML~3qa+UmBRrԁiiRtoQ#x<^jݣϙIL,(|d2OUUl6X,8fz&h |㋿N~ | H$|> Jf0X0EP|k6_|&xv+rYrT ŧ|+ѵ9(ތɽL(ٮ`0LMMPzQyXtѣGg̘`q׊ҒdkdeeßZ|Сֳ</N{Ҧ (t=;e\bTܱŁC^*)7ֱWOמΜ6Z1 =["짟1K__ 3/_>{L|؟t:# ݶ=:栍y胇Fh[ yދ&p6Ϸ]jg^[*k8 iJ8xǏbq\\\n@ ͛~%KEDDhkk766޽͙k׮>Fd@nk&?OjXjT`,&?& BQZ8zA'M*VWp8lMMMD"D"ZS'O9}ڴt*(NBWT|c͓'N ,uuu5]tFddeLg:Aܻ7w}}~ >p 4L&yYhѭ[>p,Ym8vϕa@6,0v t)_,zU}`i3ӤRi%%^ܲYKK_7q<`޿oX'G,Ү]¥00Q;Kˍ~4-}̬,Db۩?Mu0] I}d'O?y2eٰCfL 'E">[__r9e^S_V9^6+MBʐ\s:iY 9}SSk<=SHkd D4@X"+ /&jS*`<8Wb>gsTEfvxݻ=۰i o~'O%$%\ S<0IS&M ټ%K]>_WW|k?XOLw=JM3tQ'5}zFVVخy/^lu- tq'gX[[.+yp89{WzUvcb~XdQccELXK(xyZ0o.<#Ʀ& o'(=JfD"@ D @ JQ@r_#=vT )㤱9l sˏߖ֯OY#227wu}$!)y@}ή8c9.f8xc/.۷Oo£3***Er2o/&7ji ?0uܠ@EJ]V^҂6 }`/]r2!ٳ.\|埄iLVh>NNnn4;i]JJʂ t˖-ӧΝ;̟?" `˖-k׮;w޽{?reҭʕ+ .8qbddgil#jjj.]B?yԐW-~mQmmbMMj $&';AgL?_>w߿p2`q(G>r?6mtПWm@n MRpۛD"UPammkjtYL&1&O{ZkԱChjZT&llո\4 }_:aȐ!AAA䯢tWZ{/Ϟ=(//9s4{'ڪRckX=N2EMMmʔ)?zwill٧OsHHqwwWUۀ@ رcl?}VʽE9;;ܹsƌ BOO܍7~_رcС&=}NNN4Ѧb#O,̸ʜݩt}(s.[# !yѣ[x~cFvV:}ϏR\\7@_sPg[[&ywwmڴO*T@94|=0̋/?la\\v˗/ ܛ52\nաCΝ;^-=0\a?1꣒'H5^󋉉A?yhAP6v 8l;@s p=lLc|Ϟu⥩3g544,++;}, Т;fUSCc ;99:>;qr7ztʇƞ465,(xL&uuuuuL9z}kkǡ="DĩSR|K/^~ jiiQ[[rfqqɴo&58r4pO(fe縹#/=x׶;uz?{ t;,XPtJ_\UWWOhץL&ʺwqq}ܩ󼼍[B--gL*xB,V:ڼ|p̕+Wjjj Ljiiio߾H$vvv))),ښnr>55L$ C>11ʪ_~W8%%%==oNJJ277ԩH$JOOԩݻwuf '[YY)J oϞ=2.fdd $t6ܽ{PCC~NNNvGIKŋ;;;QR+O<111qss{Yjj;x(榦\~EVt]媫>pν{fϞjժ:@ Y:}ȹ5r6ݻ'<,rPlB͛7pdCSN`?CtV/k-8))>>>=*++8q"ABr##~~ƍnnn;/)HB9l:,ο C [IcQ@e3i1262:~K~$%m+쟤$~'244lQ5 #^(~05zoԙf89:}TVV۸iM up ~GڍK.Xb9U??3lܼJ& :pt;wş;gmȁViQ 3ogMY\ojjjr)+s*;ĝ:bv7l ldhV!pC~Kh=vܹC Wb{fl!$$d֭?z#G^z555k[l×T:~WFDD(p~~'Owu1ӹsg. ߅옘 x722rժU ̙3/f_#l4|Ŋ666ӦMÞ9k֬ILL~+3}ugLW^Qaanf׭Y _>_YUU__odh?^Y(lͤLH9qW^Sqk--6^J32:nZOe_SS!?-_VVV c^S틿3P+f*JYT%? ]֭s&C哙iӦ<չs޽mU,WVVknܸq>>>ݺu[nݢE=z9Ǐy󦪪JWWwsegg{yyfϞljjJԬDcWW &0mmm W\\\*++===6l1b+ %S#>_H6t6ONNuoںu+RSS###P8="ΖiiirT%:tLOOX[[{yy%''SZAmWX=cccCܮ*ɩÇD˗/5`x<__ǏO4t݁NAΞ=KVON抟={VXXإKʾDV:jmO>۷oZZt5dnn~- :+3ķ:VWW8p`Ϟ=\.k֬!?8l28q,x^x^z%$$?MMM nύ7.R $l:_r=\|ԩS'ڵkYSRB: ښP͖2]iEzC=~'Oz?<>݁Rw_9;3&44ڜRJdj`t],,j{ƌs<49Vg$)M*LLLbIII׮] KHN{ȩ2E$+`m*׳g0z6ցcNɯ!(:цz.g? IDATᏟ D*jjj)PZ 6xxx\pѣGBdyܹs#F#,!!ŋO>7443f a̘1;J-27otuu;EEEEfff,(/R`:<655CA:::rU%˝"-G,ٞܮTq-X`p"NIm߾ H@sn޼I] }cfϞMYF9=TNu2ſԳEKe6[,MMM=<<ƏA5]jV" )InLEI]]jc" & IkȾUXৈVeذa7owۉbme2ٽ{`)S\p'''%<~`ԩcƌ)--Spc4rkͱ:::Ѝy9ݕ 4;;{ׯ'&&b:4ydB)al#ln!99yʔ) 3gd2Lm VT.w(@L6Jʲ+2]d2Jt9rdCCCaa!|夡1lذ,]wԇ`J&Bz(tFh$zkR=ŭDY3RpfZh~>"PD" ) Tճ(&DNIRT( WIRD"Hprr޽;DR^^me,"+,*t;+PЀV Aݷo߮}ƍׯ=z]tb2L x5kAkײ8NvvvEE~.]lpn߾maa@biiIV@mmw\nRRΝ;+++²tuu٣+7nHOOg2UUU6mZnÇ5BCCSSSG ܷo,䋔uuuFAKK ڵk<|ܹs @ ptt۷MLL0v~:uǎ)U%244$EeffvСC۷OKKի׮]pvv&MNNǪ*V +)]8܊*ɩ\ϿuVPPԒH$|>+YMM]v޽;>w777zt?HKK+---((ٳ'уNYkMMM}ҒNLLLBCCx]]]ʕ+۶mKOO///ohh!$ѩ߱cGff]z x"6$'l$...ijjս{"ACôA'MDD ll&M,X,E Ñ-j<y\6Y6b2,Y3H$ Ba)!*$33SRSΑr'0s|o<uuuo޼!A|djXMUVV Şٳ1ѣpB*..611.,-Ԕ"+ƍ׬YSYYijjJɓ'III-jI$:;P\& V|Ue^~m``X__WOH%_e߆ e=bQ("!uE$e#kN%rlJHVRBf||ӧOCBBLH$:s̑#Gbcc{)4hx5)H(Mhmނ9rD(N>!:0-1 CL$+H٧+P4xu:c8l' ц9 N:=im Èc±D"ܛGP,!/B!a"b1'ȑ#䃃(/H0 v9WUS; )w" EbVDP1r\Y5mQltm@2ҩDΝ֚BiJJʲ#0|! > ~.)PMSI"v/^ܳgC|<Ʈ#21Mw=h_1]v|}}_"/>~8777..NmƚPٿz(VXdɋ/""";o߾ݻw4w7oޗPdn ͤ!<, gpb *;v,ck竡Q__С`%x}򩭭9s"%ІTmU(Vp8rfAQh={ԍ@hhhӧjWUæQOIzh*?L_FOOOVFWW%K6G`=bJ555!Q(' `qGN{h@ UC TsBY< _܋fG`0`@*x]1q@ A;dW:bru+lvccD"! TEz + 7oT)krl6d4@ Dk# L&UnAYD@ İl)PX4;GE|>L@ hm`DG|X6v @ `uY@  b2'tI}{eAZV:cdl6["`GZ6@ hUl6<>ap oݹ9㎍. ϡ:چ؆8ogϟ_9VK:o/+BgYOgm-- V3礥pMML~3qkt޽uu< _ZWdծ-ŪH$.MB!bQ{ץ;w{v+WA^~b#@  礽**TOScX^=_{FFDF^8s@_v==ٳ%Imm?I~CZH$9ؘc'ćG7{{xI(;n?=u$ϙӧM9{iOb+TyE6QIݴTBFV&`ʤ]:w&|Դ89m zp߱I׮I#l@  >I{什*>oiRuS^n٬%/w8y^`pPo7#djkiWWW֮p円@;Kˍ~4-}̬,Db۩?Mu0] I}d'O?y2eٰCfLf˴g܁6#+DNZF`c]|zee7'`s--,**+U~~A{@ I"-Z@W-- uux?3;{_ݞmشy_t7|xቓY.LL)0IS&M ټ%K]>_WW|k?XOWTc_cgިϚ>=#++l/6m񸓁3gvr Lw>R\\S% '-+S, ^̛x_cjhhVI `¾?@ U#*>e46man3+`:cdTtZFS$$%H'Vy̟;xŬ765644tvrr-_C}}}@EEeYYپ}}W._d2F1m'Nx٫7U *M 444ܹwEBq(__>? ~}U0 "$ nQ*ҝ_ػ TzW/KE 寲B}OD+%yh&h:/ SCc02@АI@>/w@[|ٯٳsnޤH'▯ygo߽4a熍utrrR33 =##;7W"t"[Y޻w r/ X`~p'̚;lsҵphejj;/33ӃGUTT뛙:衒I3%}zv޽qm۶}VT)))ϷزeڵkΝw^[n]KO2ܵ7=)n wHc11Di  {tطgͤgNx#G W{q ; JWX1nܸ>ߧO477۷͘1cҥW޾}}V\#G>} gϞmmmݶlٳׯzGбcGWC xŢPR9 x{{oܸ177w֬Yf͢T5ڏQP5gO |!/t/5jq'.Y[~3g>KEE>A-# "X@FopS'[W9u,UQvUQQv]:(GXf)Ӵݒ3ڶb UtBK"F{ylkd2o޾}{]@w{6U IX$7͛WdllqIU޴>2*/ JJ 9rZp! ?KE?{g]RwAE+@P( bW,1h-["*bA-PD, "JAe1~$}Y/sgy9sOG2 NCmmPDą]O1s׮)++ ^66;kjhٳ . [yG5EyUU$Xם3O;wJUUu!%%N 0H/ up3?ʹrȿ99ݷOV[ٳ tY351Ņr<</{,J(6444fdfƟ=} .FUD"r>I򑡧g```0^w<333ޞ''<544|3bsrr,1geeUWWkhhJV\<(--tvvfZZZ$KO>YYYwp*V`zח`ũVVVDoIPQQC333sZsTx08Uinn>|pd%!i +kk봴4333YVVgccccc/yZZZ]]_nnnCCÔ)SdnjjD1H}MFTHDwlR E~~wBnff5jKYYǏ ɵ%KIGď!&&&߿ǾHdbTIDT]|>>=?RrR* ՟ n߾mbbF$V5924`X,H UTͤQ324<:~_ii~+-xJp0>?8@/_'v!ҕ_/v9km(yGSS6mݶȻ9w!C_]rwss۷-Xz%~ 76as,Xx<`뎝07ڨ-C斖W ^54yӊAK5ff?vKk׶_ޕk7u'ƎM8} Y gc,kiڵk=z<~_|:::RRRnܸi<8$$dÆ 0Mrrr^^Ν;QQQǏ3f INNFr[zu}}}HHͬY\.|aÆiӦxŋǍG?v,...""" &&fݺuOXY,ֱc-ZTZZ_,Dhܷ2\p̙3Thii#ϱ<*++?~rs(Jk6ݷo_eeeMMMeeeI!Ν;wl$sܹsƍ7j(MMM.+diJ$4 -BXߠn "ZjpٳdwIŋ?p(Vqi(0x"hʕ$$$9rD(RX"cC3DT]t,5FHzԩ~VබTd(ց.P稨۷ɆRM Q@ذQ 'Ve˖,YxٳgO:u„ ~~~oVTV|ɇ"߿|斖n*ϋKJoeTTVx< t8ptD}}}mmmiiݻw4>Bqdz w;vW^mkk'O+ϟ? رojjIIIpX,^vRĪUl"=zdaa! bqzzuP _~o.kddt="l2m4X BU'''˗VVVoatRcÁFiTSSSSS;/ף^],¼/7vkkۥE B8o.=IgϞy慄㳳={D2wPC=2wԳgO$+իWmcw8'\UTT +0ݻ7@CCFFK`bwww ( 6OFJ]΂dp^|Ab=V&iiiRA\݉\ y +++D@HjGD,E*QQ \񼼼=zԿ%%%EQ ^WDPx000|2@  :wDEOehHYd"w R,h~itSD]H IDAT"%%%L&S rO:thgrkmm۲esssy<lhhHIIillLLL _l\⋂uCfErQ߿p܌֬Y&LE~[páDJ}ܹ*5s%%oȑ#&&&]矸"Q,Nc}H/ PEvrU * C] :t%QB*&r:b#HFij|u AAA'Ov+!7]rvJCnx>gϞ o޼X777,XK҂n. ^,uuǏ{{{apX&+++[ZZ8݋X:>p›t'F7r#M???m4^l'ĉi/t}& ߅2Ip)3i4hb4HhxϧɡA 4hРuhMʟэ/FDhaҠA 4hR&d 9r\!ghtcW?ҠA 4h4x5USlnƐS7}5.X,.++{mw. h띓Flht"K Wn3VrtT;Ts)p&=4b d07k׮r7ot#r^jggiӦϰX3`]|llmGGҥKǏ^|_~[njtDqq "?w?i.4yWZjki$[t'F@.##E~uiqiii"oΝ݈ٳg,Z+\B^/++ ݻ7lILKJ"ոI䟃ϝt:-*>]>{6z tǚ_CC5>e4;C陴={VYY]]bUU!IcL^(Pi:iB>:g$L&bq\dgn>pFhee =x𠴴ٙf|Wiiifff,Çfff...0}VVVuuRYYY^^MFFCPQQQ\\\]]6dmmm+IIIo޼qrr۷/Q΅}߿zˡ$%ϟXZZ"=~ͭmhhDNNN, >>;w0H ذaCjjix<ŋl6o߾ʚ,… gΜٮ^>$$f֬Y\.WIIܹs?xsH栬"455aÆD1+...""" &&fݺuc-ZTZZ+ .!EEE?~|̘1'99'O1/'.p hJ҂Mr B2+de:J!.Xttt%7nlܸ\wƨHjժݻw9{3gH \ɱEPyHԌھ}{NNNppplll\\}U&*GTOpsmjj7nܨQ455\.v\DU/^VDP .E4"WGzQʈjǏ *4du:2.++=~,E=\dup/Μ;o?Qސw܅ps:}^j s:ztodau0WV>/_X)$;Dl`)#]_t? nn@!_|Y]]3ydՅH*ERIFWS"UQ'IN"PV|V*@)PyA gO=)x_|6k=z~};urhGGk~,G|>_CCciD҈ya=}.!tO+$3ǽ S~ݻO]]cςs?=}V_ (66D3r#ns>xV).]tҽ{SSSq%ԳgO/͛7a>TQQioo58~Çqi"5kM7oܼ_\$y_0c<#=B (ec37l˺th:kgG">>c<_?ms_`PF$ͦۦϞ>wɷ?wvtt]5pl6MB5#R4>=z?s &Qgի~~~ / AcC(xvsssq֭b6]RR`==~ܹf߻w_~p8366􍌌>Y\\lmmbeeuA&yi /2===**XOO &Eo233V3tuuϞ=RSSchhx %%L&y۶m6m4hPbbbtttIIIGG$KH= 0`߾}ڷo055355ٳ'[__*n 777*uVdddQQ+CuQI611A\̪D\+ vvv([1{H#BϞ=kjjݻf͚AIZ^R/^2+ L$+Jeee@@*zǎN7ou៨y222H,,,ikkۿQQ֠Apb}+Oss3­ k"%59r$VܢiiiRӓJU+**TiPRQQb1e DM#5 [URa,%6Rb2-[;f|>x<,\pڴim۱b,ȗ;z/YZiҟׄBȢ1---"Qc%7 5s' Ժ{<5n70xVB21so.^-oxEF=J_OgK#hT֯]6~&`h,okkkllz:<OYYVMMMrX,566FjXK###:G$566aɽXpUUUx:Q u֖ 6455eJKo---G["\n[[ѭ;<DŔrp%$N+[ -HT__oll1u9rdT:{,DK-峯*K>"ϑ ^ɓUVF\r̙"Q%S@QI^jD]uTglל!iHEYY&͆udJ5Q/<-=~YaκŋO"(݉Aׯ]kS˺[NduޜKʐiC>4: 1055E ?Md2 УGIҪ UUUR%%7D0义 foI *Cd$. qZ,UGRpmAe˖¿I3d W!u( ϻxcyA ]SVV&Sll'NwЀuH=g.] 3n8@WWnMZ߶&\vt?g 8a>ec4ȃ߸ҕ@B]\Լi68`dh7ff$+W.]janlI; Æ:nݱ{Û4k;|4d:dn斖W n͛VDW ݵ7KZ5bO#׮kjkݿUqp.7 ]󕔔f4hРA 4P]5CŊ=__673܎) /weGG[+D =tuI6}}|444d=x`0Wl?Q X,tMe' !V\Vx={^s;Bs#\֪~)Vl-ASiC#TCCf+))!3bիW[;ie=IG+KK,¼zh%& ǎ7j/r#=}z3  1[(8r~Zt'4ȁo7(<445UHT0WwW,ZHַ꺝ѣG/X v3 ֬YeOOrr TgW{EPPLG)J#Y__hѢ~<3  1A((k R%'Ee?E: NNlHS"zJF7!K^3ir8p۩ٳN*@***jjj^z;#N!^ w~dUb.G2|[[[;.. 2ǤkO2 %夨짵H9y#CL&IK;%N v4C06.Ecc#d W]S i#y%t`>r;e-yDIIÇ^BSʺw^UU5҅/)) )))eee\.WMM-))çݻwݻYYYGIRXXo޼`0Dۯ_|T`<~W 2 >yhjj߿bbbkk<%շ@TTT6n[777xI>}tttҚ---SSSpmGSWk ,t+""55ϯTSS̬}F3ʠHf555 E[ZZ<䡁#yIIɟMMͲl. (;, ǏE}b#OJB%g\ҨZ#D(9pc(p'2$>#i\IpK?}Ą``B/ `.z]5;-[ oTت*,e f)YL0Fvc2G6lHMM6m[x1꯫W 5k$''xxxܹb]p̙3>> c7o&tذaȬOR?'J}$ؿRǂ 6mڤ| ЫW/$skkkraUnw*˧C quueK.=uTvv׭[WQQ ?x𠓓" QnD<6mz왖`v222N2\rߟdl{innnff6l0''']*J7x{{;JZlW?+ qI^kOTAP"r$\HML>IܑW&b8_|Y]]3y7n`Mܙ/ v@'#Н44d2ZBZZZ>}8(Gܼy~99#@:^Jn<U deeutt(++]d*+P74dLޢ2[+r|IBs'k-YW( n(uz IDN>][[[EEr)h`-ֺb}pn0$|>R) B^MpHjjj<gGG!%%1111<<ɓ'D-0JJJ~#GLLL<==CCC)J{O>~znn.c2,3000a'|\Ν;DɰyAcɑ+ QgggzcccdȖt"QA.V}"[ C|>Á… :l57grog0/ '"\jȠbD`Qxc$*T#:?$9w֒#IH #IQbcbS1I&&&;vpqqիRMfFϤƁ| u}~7رc?\"@HHHnn.2ȗ{葾̙3'LP__/9U]]ry}7c_?KJJRSS'F,gggWUU sW^EVbEсOHɓ(%ŒȠ|hϞ=HjxR cEEE"R~JJ -)W?y$((sΜ9ϟ///GVrJj"ɽ0cƌׯWUUm@%*\ q,RSuJ"iTj-"HEDZgffR%c7p(ROR?uZƍOсkb/ 9Qe\ ѧ;Đt^ֽMZ>ݱ8::/޽{ϟ?,**200pww:x <}ŗ_~`0nݺU\\fKJJ^~Y\\lmmŋb==&\WWw)))ᑑwqww¼}vAAlnn޶mۦM {YCC7n())ܼy3::ɩG۹s'͆ZXXsauuuUUU;;;d<+**$@E`ڵ+//n B]]]ff&cy={f̘055ٳ'ÐAٮ|v'zqmabb"[~xΝ={ݻw͚5 ?~y77"߾}v p}Jeee@@IG2{^aaN[[ P5(Occ#myyytttiiqeeÇKKK.՟e###8`===TY?Ĉ(I>}*5g///k-"HӉ"tǎN7on Ґ!CPDb޽{'યu$"Pb``@Y,VLLLIIܹ3rH///LMMMl6bM7P:ݑl21<q?`…ӦMm@KQTTD%Y^Ay?0f7C...4b˗FFF;jbqMM)++֪R)իOܙ`0^zEe+拫tuuuuuutt8 'FwP(H}  ^DW֒Eqq 6 UUUl=z?PGA`FSI&I 'r"wK `bbٓAn؝R\[PSVCP $=4܈x%j̓ :tyInr?w2XDR_>I:SkDzn L$>C-ZC5B@bR +;F7FP(җbٲe\.СCdP/Ӽ^9޾h[ njNO[Ɛ7 C36dM6P,*Jͤ;i4ql i4;h@f-[&58>ql1qďVֿ&4"٪ёh|Ũ5\L HiȖM4}H ! u4j"#|NP(}4h88'(4hc+4 4hȅ FO~ڧ]{PDF\;S%%%8&u- 4 hhАolٲM ,=fl_[J>\diӧI^#yQ(:N UR9wޓ[[KDnC>ۈcѣW|ݷS'vttǛIr544FD,6ۮ_BgDzn]:~渗5!tʯ{kY0 &NyZQ2q‚yו+\$ !>?WmڴImK.?~by˗u֮+{}}}7o8pժU'N <صkWRRRINNI]m߇6l˔)S͛7_~˗/df~aaa;wjժ_UR|ԋ7n/=څ-.ӠA- z.xJ2yK~4"HX"?\dJΡx<OGkP{тIOŏD7l6KSS5B!*m-Ӧ";{֬WZs),7R_hkzA!۷=i|>!颃khh011QgWG~vK eUK,_С{w퀶0.`bHڭ[}zwhut_C``'Ox1C%j>Rs΍ߵk4$_TVV;vFgxO8);iBQIIhH>{eێc'N,Z2wK\RJZVr8cc#\vB!`0R fLYp7ov޳l7mۂܳ[II ==~;p07/oߘQ<)dمő=F_=|aC[[Yq6g=y:+KqqX{Yc##@EKkkuνE=z0mۻ~amm}+AF.c䩵g7_-VWW{T&Zsss{{ep#ܓFɺ 飭տ IIIo޼qrr۷/|9Έ#ϟXZZ2ʪKzAii3.//"_>iab+____,666ZYY9;;ra=5kCYYǏ llllll222 n߾mbb&)"77N2$A"'.c>LssÇ +kk봴433>}|"755D"}}}]믿bENsEEÇ\\\HDŕtCb҉B>4%y"KŅ &aC3fo׬Y[---fff CzJI`2X$l*phRXlhb^aS&M262/,DWpjoTUW;::w<ݿr`_͜15`@q[޴8a tw'Wy؉AkW0gْgq= OrA0GGoOo/O$`u}y#)髅 Fp/~PljA3aaa"(444999::-I:::ZZZp\Lf\\ɓ'ŋcbbs8p ;;?**j999qqq/_޸qcƍHСL"'.cK? 9xsl6o߾ʚ͍zBb∈EI[eee5矃b.\pQq"*l#eUĔJ֋.kYِEKKKuuTOIIqFll| Ř?F4htPdP i &S Jb &jFʷCG+yO~;[Hpʵ?ΞwYOzcOؽo˗u䙷z-.-DPPXXRV& (=-=4irФV~ E'6Yu"(݉AO,Snۼi2n&&Ƈ"3559uLŋ_7陚 ݙp#r5]St>[CCc˖->@ 455O4 =zܬ(**ڶmڵk544;l0mzzݻwaVVVwC111˗/g0, Ϳ3ڎ9)??o߾㏒1͛7%)6u}D< mll*++}}}L+WLKzz:L6dWWW6tSNeggbce&X汥E???`jj*tذaVVV'$&޵k׾}$xbHH\矃laaxطJG@x(%K'ДJ\B}Qj&WƾݻNNN3cѠ!l0?$44*=4ak[7o) 3yRHP@_& _~{o\#߯?:%IޙEU̝U}Qp $M7p TP1JM-+S|cj&"("j"* þrg~9^P~5{9r?=C'9 9hj>/{i!4zGN=j5+?8nRMnJeop>/ϛOef{we'gKvNL3] ]&}||222B[l9|cc#B(::󶶶C Ύ;ֿ,"9ҳgOz:B(33OCv-}AʒH$))))))gΜ'aUBLo7xz"7A~oZ׿lv;ꬻ٥]zRkⓏ{1qq_޽-[clGjhhA:s,Bh5. h_hܣG/D"PyR˳#g-+/Uѳ 1JeO&33k:t(//O.fddTTT͛7/??ȈfyLI76RT#ncxX2?XhekkyH~ 0hܯ>c^~[B֜nkugЀ16myB ޘ+scd\H4o6kmOw Yܹ;w8 6g:UPXx)?_&k!TW_+yϮ=\(\_FΘ|~~[lDXG^nn#v&mشռ_E%ܘqkܣ˘Q#cb6lڜwٳmM=]==zkϞ/]ZlH*+*+ 5fZdTKlӏ?H@7HQӺmʊBCC?T*ےZ>wڵk/^hccVVV6vآ"uȈ#5N81sLرcR)NOMMe~Gȿ#sذagϞd.mj@m퀟$3K;PPxx8zĉ999tv˳K4igs|ySXܼyS[ BYYY8L#Ԝsk쫴Jhm%dK~p 8-cѣgϞu\y!}91x ͒{;݉ ?nx,3n%oekkۦ^xCY9F+.^aCMLLF-)RR5!y䪪/} vvCgEtvrG/Yho755%u%#g899ikZ ;vxxx$%%Iҝ;w:::&$${xx߾};..XZZ޽;66!ԧOj>|X:'%%]|9++Ky_C!0Stt1aǎ˖-3pΪ;ߦl:EUֿԧ}>j`Y!_Cp~x 4bbnS v7nٳjҥK8xb9 AhݿѰ"T*;cw@V Bb' D@:JO <+f!R(4(14cG WaM Ҁn/]^tj<dS$#q}: Dھ{A^VTZL& ̉CN+4Ii4*w{&O}ʟc6_f[Kyzקi_'룕Od+wssّ3GnGCD/XxAVBa3M5xFFϭoط;¿;%uUU[~KG˥3MMVV|l|Nq'BnnYAjk lt57R :yXONx{[cJgcmy7ޠiV!ޘѣZB011jiiĤ]{Sow ,;R9-rUUUụ/]ngg7on4%$LZ_vv-76xkmMmLܶ+?}^Db@iat**il60gERN|3555JE4gr\БSN=4JUSS+RVP4!z:YQQoX*eN}DZC(v5ꬣosws[{--2333rUkw&23"wكE+~CL$oVTdbfѰ4B#8"OL=iw:+*}:MR 3j䕂JKB||7fLwio޺2!w֭_k\ŋ'tIޔkV~hff`ϩhF<^CCW g> !daaւz~ o/k/_Q۸)ҥq!?qoS'G̝5k6m_k? !a [WWګ9g[u6RiEeUU~}2-/9;91ϔ&&rN~bB vK,i@@:g!(NVu\#\];,mK/͝= !47淸+WjС/]<NqP \BEokׯo۞ VZ{{#4`FUVVI_㶅NBcF[ecm;yv7`7sJl^+DP}ݒi#546d2WWB{Õ_3+ʀ.~xn!`I:܆i,J4[Qt箧BjiP#6)Hry;ZRM9[z쯿B565tw}IN>3aקLqttБy]]B*j+~P?\@/<3iiPpB5>B3ь Z=W~?>=rW}bUľZ7}ǚ v:(juj?QZi ή^#ް dff6urD C^zBosrr 8aW=߆cbY:29}!sϡ%k2hwmu~J(VŒY FP!æ-Ӱ&;RE$A ssgM(J~+:N^zݒrƟ75?Z_r!/˖.z;<,ԫO}v'I$8mܻWekA^^|>ԙ?3g"ۣBBnnXw}1B٧N䔔s/,Z:knn`M[?*qIDAT~YΒW}$0tdRR-t6X tj단@ `*4!5iXNbs:aT*wH$7gv!=MMLFs6q _ߛn%W Nde@KK˿oߖZp]{B-2;wҏ8rdϵ_Ey38\iz ˼6q8111䬳nVs.{{z]ppn%nM}JiW1)㹹rꁃBJbӿ:9bRk!Tx{׊MwًůMoAVQP(Ȇi:RIQӸVwGA+X|Ț464v'&qr;{Cmï6s"&KK/ڰi&&&#M/%u[c] yu_cMlog7>$xVLpŎ{SSSR8/[8rt|׬8o;`F¸؛:)JUKuvʥҎ(ʪOoVvNVvI8믾XHNI'O?VT:~'/ h@FZi/K!@j ҎPHpz4M4T*rB2L&EEEM>6\CCCEe3nUuuCCaf=zO9MMMr¢}sڥKÆ ÿsȑ%Mb=S( ~~~:ׯD"h`2}./Y\dnnnnnnfffjjjbbbdd$E"#gw355555HxVVVV!X RŅdY ѿw )D"¹ "H(RMjQGJLLv= t;]@D"4)"4 VhE%&&bGRP(J%vTTxO;vivBM2ECӧ lll~+W,,,F:zhuu4Y)&&&y| <<3 WXUQ%bD">hع41 4MKijĜ DHt`iii OR <ի䐷7>4x#Gdeet@>j("BB8|0Bht䓖VZZP<cccӦ" 4P($D"Ēx8'G D5"R$eee[XX{{{3g?2`lﲴxyyyEyyy20ɑL'00رc|>i̘1펡DiBP(bcjXq{b"x
pasdoc/www/snapshots/pasdoc_snapshot0000700000175000017500000000405713131363554020457 0ustar michalismichalis#!/bin/bash set -eu # Script run by Jenkins (Automatic Cloud Builds of Castle Game Engine projects) on # https://michalis.ii.uni.wroc.pl/jenkins/ to update PasDoc snapshots # visible on http://michalis.ii.uni.wroc.pl/pasdoc-snapshots/ . # Parts of this script are really specific to the Jenkins # and michalis.ii.uni.wroc.pl server configuration. . /usr/local/fpclazarus/bin/setup.sh default OUTPUT_BASE_PATH=/var/www/pasdoc-snapshots/ OUTPUT_PATH="${OUTPUT_BASE_PATH}"`date +%F`/ mkdir -p "$OUTPUT_PATH" PASDOC_VERSION=`make version` # build snapshots # make dist-src # useless, checks out the stable version make dist-linux-x86 make dist-win32 FPC_DEFAULT='fpc -Twin32' LAZBUILD_OPTIONS='--operating-system=win32 --widgetset=win32' echo '---- Snapshots build OK.' # Move archives to output dir mv -f pasdoc-"$PASDOC_VERSION"-linux-x86.tar.gz \ pasdoc-"$PASDOC_VERSION"-win32.zip \ "$OUTPUT_PATH" # Create "latest" link, comfortable for users. rm -f "${OUTPUT_BASE_PATH}"latest ln -s `date +%F` "${OUTPUT_BASE_PATH}"latest # Clean old snapshots, to conserve disk space. # Keep only snapshots from last couple of days. pushd . cd "${OUTPUT_BASE_PATH}" set +e find . -mindepth 1 -maxdepth 1 \ -type d -and \ -name '????-??-??' -and \ '(' -not -iname `date +%F` ')' -and \ '(' -not -iname `date --date='-1 day' +%F` ')' -and \ '(' -not -iname `date --date='-2 day' +%F` ')' -and \ '(' -not -iname `date --date='-3 day' +%F` ')' -and \ '(' -not -iname `date --date='-4 day' +%F` ')' -and \ '(' -not -iname `date --date='-5 day' +%F` ')' -and \ '(' -not -iname `date --date='-6 day' +%F` ')' -and \ '(' -not -iname `date --date='-7 day' +%F` ')' -and \ -exec rm -Rf '{}' ';' set -e popd echo '---------------------------------------------------------------' echo 'Setting snapshots permissions:' chmod a+rX "${OUTPUT_BASE_PATH}" echo '---------------------------------------------------------------' echo 'Building for current platform, to be used by dependent Jenkins jobs' make clean default build-tools echo '---- The end, everything finished Ok.' pasdoc/source/0000700000175000017500000000000013034465544013771 5ustar michalismichalispasdoc/source/tools/0000700000175000017500000000000013237143042015120 5ustar michalismichalispasdoc/source/tools/file_to_pascal_data.dpr0000600000175000017500000000427313237143042021574 0ustar michalismichalis{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { Reads file $1 and writes Pascal source file $2, such that $2 file contains type and value of Pascal constant, i.e. array[0 .. Xxx]of Byte = ( ... ) that has the contents of file $1. File is treated as binary file, so file contents are reflected exactly, byte by byte, in $2. Useful if you want to "embed" some binary file inside compiled Pascal program. } program file_to_pascal_data; {$apptype CONSOLE} {$ifdef FPC} {$mode objfpc} {$endif} {$H+} uses SysUtils, Classes; var Src: TFileStream; Dest: TextFile; SrcFileName, DestFileName: string; B: Byte; i: Integer; begin SrcFileName := ParamStr(1); DestFileName := ParamStr(2); Src := TFileStream.Create(SrcFileName, fmOpenRead); try Assign(Dest, DestFileName); Rewrite(Dest); try Writeln(Dest, '{ -*- buffer-read-only: t -*- }'); Writeln(Dest, '{ DON''T EDIT -- this file was automatically generated from "' + SrcFileName + '" }'); Writeln(Dest, 'array [0 .. ', Src.Size - 1, '] of Byte = ('); for i := 0 to Src.Size - 2 do begin Src.ReadBuffer(B, 1); Write(Dest, '$', IntToHex(B, 2), ', '); if ((i + 1) mod 15) = 0 then Writeln(Dest); end; Src.ReadBuffer(B, 1); Write(Dest, '$', IntToHex(B, 2)); Writeln(Dest, ')'); finally CloseFile(Dest) end; finally Src.Free end; end. pasdoc/source/tools/fpc_sources_parse_for_external_class_hierarchy.sh0000700000175000017500000000163113034465544027171 0ustar michalismichalis#!/bin/bash set -eu # Process some of the FPC RTL and FCL with PasDoc. For Linux i386 target. # You probably want to adjust paths below before running. # This may be used as a demo (that PasDoc can handle FPC sources). # # It was also used to make ../component/external_class_hierarchy.txt # Just take resulting GVClasses.dot, and process it with regexp. FPC_SOURCES=/home/michalis/sources/fpc/trunk/ OUTPUT_DIR=/tmp/ cd "$FPC_SOURCES" pasdoc --output="$OUTPUT_DIR" --graphviz-classes \ -I rtl/objpas/sysutils/ -I rtl/inc/ -I rtl/i386/ -I rtl/unix/ -I rtl/linux/ \ -I rtl/objpas/classes/ \ -D UNIX -D cpui386 \ rtl/unix/sysutils.pp rtl/objpas/objpas.pp rtl/unix/classes.pp \ rtl/inc/dynlibs.pas rtl/objpas/math.pp rtl/inc/matrix.pp \ rtl/objpas/typinfo.pp \ packages/fcl-base/src/contnrs.pp # System unit fails because of [INTERNPROC: xxx], which is special # for FPC system unit. # rtl/linux/system.pp pasdoc/source/tools/pascal_pre_proc.dpr0000600000175000017500000001717213237143042020775 0ustar michalismichalis{ -*- compile-command: "make -C ../../ build-pascal_pre_proc" -*- } { Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { A Pascal preprocessor. See [https://github.com/pasdoc/pasdoc/wiki/OtherTools] for documentation. TODO: should be made configurable to preserve some directives. Conditional compilation, macros, includes are handled fully by this preprocessor, so they should be stripped, but some directives should be usually left in the source for the actual compiler. Things like $mode, or $H+. } program pascal_pre_proc; uses SysUtils, Classes, PasDoc_OptionParser, PasDoc_StringVector, PasDoc_Base, PasDoc_Tokenizer, PasDoc_Scanner, PasDoc_Types, PasDoc_Versions; { TPascalPreProcessor -------------------------------------------------------- } type TPascalPreProcessor = class private procedure MessageEvent(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); public Verbosity: Cardinal; HandleMacros: boolean; Directives: TStringVector; IncludeDirectories: TStringVector; constructor Create; destructor Destroy; override; procedure Process(const InputFileName: string); end; constructor TPascalPreProcessor.Create; begin inherited; Directives := TStringVector.Create; IncludeDirectories := TStringVector.Create; end; destructor TPascalPreProcessor.Destroy; begin FreeAndNil(Directives); FreeAndNil(IncludeDirectories); inherited; end; procedure TPascalPreProcessor.MessageEvent( const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); begin if (AVerbosity <= Verbosity) then case MessageType of pmtInformation: WriteLn(ErrOutput, 'Info[', AVerbosity, ']: ', AMessage); pmtWarning: WriteLn(ErrOutput, 'Warning[', AVerbosity, ']: ', AMessage); pmtError: WriteLn(ErrOutput, 'Error[', AVerbosity, ']: ', AMessage); else WriteLn(ErrOutput, AMessage); end; end; procedure TPascalPreProcessor.Process(const InputFileName: string); var Scanner: TScanner; InputStream: TStream; T: TToken; begin InputStream := TFileStream.Create(InputFileName, fmOpenRead); { We do not free InputStream anywhere in this procedure, Scanner will take care of this. } Scanner := TScanner.Create(InputStream, {$ifdef FPC_OBJFPC}@{$endif} MessageEvent , Verbosity, InputFileName, ExtractFilePath(InputFileName), HandleMacros); try Scanner.IncludeFilePaths := IncludeDirectories; Scanner.AddSymbols(Directives); try repeat T := Scanner.GetToken; Write(T.Data); until false; except on ETokenizerStreamEnd do { silence exception, as this is the normal end }; end; finally FreeAndNil(Scanner) end; end; { TPascalPreProcessorOptions ------------------------------------------------- } type TPascalPreProcessorOptions = class(TOptionParser) OptionVerbosity: TIntegerOption; OptionDefine: TStringOptionList; OptionHelp: TBoolOption; OptionIncludePaths: TPathListOption; OptionConditionalFile: TStringOptionList; OptionNoMacro: TBoolOption; public constructor Create; override; procedure InterpretCommandline(PreProcessor: TPascalPreProcessor); end; constructor TPascalPreProcessorOptions.Create; begin inherited; OptionHelp := TBoolOption.Create('?', 'help'); OptionHelp.Explanation := 'Show this help'; AddOption(OptionHelp); OptionVerbosity := TIntegerOption.Create('v', 'verbosity'); OptionVerbosity.Value := DEFAULT_VERBOSITY_LEVEL; OptionVerbosity.Explanation := 'Set log verbosity (0-6) ['+IntToStr(DEFAULT_VERBOSITY_LEVEL)+']'; AddOption(OptionVerbosity); OptionDefine := TStringOptionList.Create('D', 'define'); OptionDefine.Explanation := 'Define conditional'; AddOption(OptionDefine); OptionConditionalFile := TStringOptionList.Create('d', 'conditionals'); OptionConditionalFile.Explanation := 'Read conditionals from this file'; AddOption(OptionConditionalFile); OptionIncludePaths := TPathListOption.Create('I', 'include'); OptionIncludePaths.Explanation := 'Includes search path'; AddOption(OptionIncludePaths); OptionNoMacro := TBoolOption.Create(#0, 'no-macro'); OptionNoMacro.Explanation := 'Turn FPC macro support off'; AddOption(OptionNoMacro); end; procedure TPascalPreProcessorOptions.InterpretCommandline( PreProcessor: TPascalPreProcessor); var I: Integer; begin PreProcessor.Directives.Assign(OptionDefine.Values); for I := 0 to OptionConditionalFile.Values.Count - 1 do PreProcessor.Directives.LoadFromTextFileAdd(OptionConditionalFile.Values[I]); PreProcessor.IncludeDirectories.Assign(OptionIncludePaths.Values); PreProcessor.Verbosity := OptionVerbosity.Value; PreProcessor.HandleMacros := not OptionNoMacro.TurnedOn; end; { Main program --------------------------------------------------------------- } { If CATCH_EXCEPTIONS then exceptions will be catched and displayed nicely using MessageEvent, which means that exceptions will be reported like other errors of pasdoc. This is what users most definitely want. For debug purposes, it's sometimes useful to undefine this, to let the default FPC exception handler do it's work and output nice backtrace of the exception. } {$define CATCH_EXCEPTIONS} var PreProcessor: TPascalPreProcessor; InputFileName: string; Options: TPascalPreProcessorOptions; begin PreProcessor := TPascalPreProcessor.Create; try {$ifdef CATCH_EXCEPTIONS} try {$endif} Options := TPascalPreProcessorOptions.Create; try Options.ParseOptions; if Options.OptionHelp.TurnedOn then begin Writeln('pascal_pre_proc: Pascal preprocessor.'); Writeln('Using PasDoc parser:'); Writeln(PASDOC_FULL_INFO); Writeln; WriteLn('Usage:'); WriteLn(' pascal_pre_proc [options] file-name'); Writeln('This will parse file-name, interpreting all compiler directives'); Writeln('(like $define, $ifdef, $include, handling also FPC macros)'); Writeln('and output the result on standard output.'); Writeln; WriteLn('Valid options are: '); Options.WriteExplanations; Exit; end; Options.InterpretCommandline(PreProcessor); if Options.LeftList.Count = 0 then raise Exception.Create('You must provide a filename to parse'); if Options.LeftList.Count > 1 then raise Exception.Create('You cannot provide more than one filename to parse'); InputFileName := Options.LeftList[0]; finally FreeAndNil(Options) end; PreProcessor.Process(InputFileName); {$ifdef CATCH_EXCEPTIONS} except on E: Exception do begin PreProcessor.MessageEvent(pmtError, E.Message, 1); ExitCode := 1; Exit; end; end; {$endif CATCH_EXCEPTIONS} finally FreeAndNil(PreProcessor) end; end.pasdoc/source/tools/adjust_copyrights.sh0000700000175000017500000000037213237143035021230 0ustar michalismichalis#!/bin/bash set -eu find ../../ '(' \ -iname '*.pas' -or \ -iname '*.inc' -or \ -iname '*.css' -or \ -iname '*.dpr' ')' \ -execdir sed --in-place -e 's|Copyright 1998-2016 PasDoc developers|Copyright 1998-2018 PasDoc developers|' '{}' ';' pasdoc/source/tools/file_to_pascal_string.dpr0000600000175000017500000000625513237143042022173 0ustar michalismichalis{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { Reads text file $1 and writes Pascal source file $2, such that $2 file contains Pascal string that has the contents of file $1. Useful if you want to "embed" some text file inside compiled Pascal program. Note it treats $1 as text file, so difference between various line endings is lost in $2 (line endings are always encoded using LineEnding constant). } program file_to_pascal_string; {$apptype CONSOLE} {$ifdef FPC} {$mode objfpc} {$endif} {$H+} uses Math, SysUtils; const { String constants are (at max) this long. This avoids http://sourceforge.net/p/pasdoc/bugs/82/ problem with Delphi XE compilation like [DCC Fatal Error] jquery-1.7.1.min.js.inc(4): F2069 Line too long (more than 1023 characters) } MaxStringLength = 1000; var Src, Dest: TextFile; SrcFileName, DestFileName, S, Next: string; LenProcessed, LenNext: Cardinal; begin SrcFileName := ParamStr(1); DestFileName := ParamStr(2); Assign(Src, SrcFileName); Reset(Src); try Assign(Dest, DestFileName); Rewrite(Dest); try Writeln(Dest, '{ -*- buffer-read-only: t -*- }'); Writeln(Dest, '{ DON''T EDIT -- this file was automatically generated from "' + SrcFileName + '" }'); while not Eof(Src) do begin Readln(Src, S); { Split S into MaxStringLength chunks } if Length(S) <= MaxStringLength then begin { Special case when S already fits in MaxStringLength. We could allow the loop below to handle any S with Length(S) <> 0, the output would be correct, but for humans it looks better when we output ' LineEnding + ' on the same line. } S := StringReplace(S, '''', '''''', [rfReplaceAll]); Writeln(Dest, '''' + S + ''' + LineEnding +'); end else begin LenProcessed := 0; while LenProcessed < Length(S) do begin LenNext := Min(Length(S) - LenProcessed, MaxStringLength); Next := Copy(S, LenProcessed + 1, LenNext); Next := StringReplace(Next, '''', '''''', [rfReplaceAll]); Writeln(Dest, '''' + Next + ''' + '); LenProcessed := LenProcessed + LenNext; end; Writeln(Dest, 'LineEnding +'); end; end; Writeln(Dest, ''''''); finally CloseFile(Dest) end; finally CloseFile(Src) end; end.pasdoc/source/console/0000700000175000017500000000000013237143042015422 5ustar michalismichalispasdoc/source/console/pasdoc.dof0000600000175000017500000000022213034465544017374 0ustar michalismichalis[Directories] SearchPath=..\component;..\component\images;..\component\tipue DebugSourceDirs=..\component;..\Console;..\component\tipue OutputDir=pasdoc/source/console/pasdoc.lpi0000600000175000017500000000466613034465544017430 0ustar michalismichalis </General> <BuildModes Count="1"> <Item1 Name="default" Default="True"/> </BuildModes> <PublishOptions> <Version Value="2"/> <IgnoreBinaries Value="False"/> <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> </PublishOptions> <RunParams> <local> <FormatVersion Value="1"/> <CommandLineParams Value="..\..\tests\ok_record_case_parsing.pas --output=\tmp\"/> <LaunchingApplication Use="True" PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/> </local> </RunParams> <RequiredPackages Count="1"> <Item1> <PackageName Value="pasdoc_package"/> </Item1> </RequiredPackages> <Units Count="1"> <Unit0> <Filename Value="pasdoc.dpr"/> <IsPartOfProject Value="True"/> <IsVisibleTab Value="True"/> <UsageCount Value="20"/> <Loaded Value="True"/> </Unit0> </Units> </ProjectOptions> <CompilerOptions> <Version Value="11"/> <PathDelim Value="\"/> <SearchPaths> <IncludeFiles Value="..\component"/> </SearchPaths> <Parsing> <SyntaxOptions> <IncludeAssertionCode Value="True"/> <CStyleMacros Value="True"/> </SyntaxOptions> </Parsing> <CodeGeneration> <Checks> <IOChecks Value="True"/> <RangeChecks Value="True"/> <OverflowChecks Value="True"/> <StackChecks Value="True"/> </Checks> <VerifyObjMethodCallValidity Value="True"/> </CodeGeneration> <Other> <Verbosity> <ShowHints Value="False"/> </Verbosity> </Other> </CompilerOptions> <Debugging> <Exceptions Count="2"> <Item1> <Name Value="ECodetoolError"/> </Item1> <Item2> <Name Value="EFOpenError"/> </Item2> </Exceptions> </Debugging> </CONFIG> ��������������������������������������������������������������������������pasdoc/source/console/pasdoc.dpr��������������������������������������������������������������������0000600�0001750�0001750�00000004234�13237143042�017407� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { PasDoc * generates documentation from comments in Pascal unit source code files * command line program (GUI version also available, see ../gui/, as well as components for Lazarus and Delphi) * written in ObjectPascal (can be compiled by FPC or Delphi) * output formats Html, HtmlHelp, LaTeX * try PasDoc on its own source code (see ../autodoc/) * copyright (C) 1998-2000 by Marco Schmidt * copyright (C) 2001-2003 by Ralf Junker <delphi@zeitungsjunge.de> * Copyright (C) 2003 by Johannes Berg <johannes@sipsolutions.de> * Copyright 2005-2010 by Michalis Kamburelis, Richard B. Winston and other contributors, see ../../ChangeLog file Hint: Whenever you use PasDoc for documentations, make sure the program file contains no code except for a call to a main routine in another unit or the instantiation of an object / class that does all the work (usually TApplication). Pasdoc is restricted to work on unit files only, that's why the program file should contain no actual program-specific code - it would not become part of the documentation. ------------------------------------------------------------------------------ } program pasdoc; {$IFNDEF VPASCAL} {$IFDEF MSWINDOWS} {$APPTYPE CONSOLE} {$ENDIF} {$ENDIF} uses {$ifdef USE_FASTMM} FastMM4, {$endif} PasDoc_Main; begin Main; end. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/console/pasdoc.kof��������������������������������������������������������������������0000600�0001750�0001750�00000001674�13034465544�017417� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[FileVersion] Version=6.0 [Compiler] A=8 B=0 C=1 D=1 E=0 F=0 G=1 H=1 I=1 J=0 K=0 L=1 M=0 N=1 O=0 P=1 Q=0 R=0 S=0 T=0 U=0 V=1 W=1 X=1 Y=1 Z=1 ShowHints=1 ShowWarnings=1 UnitAliases= [Linker] MapFile=3 OutputObjs=0 ConsoleApp=1 DebugInfo=0 RemoteSymbols=0 ResourceReserve=1048576 ImageBase=4194304 ExeDescription= DynamicLoader=/lib/ld-linux.so.2 [Directories] OutputDir= UnitOutputDir=lib PackageDLLOutputDir= PackageDCPOutputDir= SearchPath=../component:../component/tipue Packages=rtl:visualclx:visualdbclx:dataclx:xmlrtl:netdataclx:netclx:indy:soaprtl Conditionals= DebugSourceDirs= UsePackages=0 [Parameters] RunParams=--visible-members private,protected,public,published,automated --css ../component/cssfiles/ThomasMueller.css --include ../component ../component/*.pas --write-uses-list --auto-abstract --output ../autodoc/html HostApplication= Launcher=/usr/X11R6/bin/xterm -T KylixDebuggerOutput -e bash -i -c %debuggee% UseLauncher=1 DebugCWD= ��������������������������������������������������������������������pasdoc/source/console/PasDoc_Main.pas���������������������������������������������������������������0000600�0001750�0001750�00000061272�13237143042�020256� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ @abstract(Provides the Main procedure.) } unit PasDoc_Main; interface { This is the main procedure of PasDoc, it does everything. } procedure Main; implementation uses PasDoc_Base, PasDoc_Languages, SysUtils, PasDoc_Utils, PasDoc_GenHtml, PasDoc_GenSimpleXML, PasDoc_GenLatex, PasDoc_GenHtmlHelp, PasDoc_Gen, PasDoc_Items, PasDoc_OptionParser, PasDoc_Types, PasDoc_Tokenizer, PasDoc_Serialize, PasDoc_SortSettings, PasDoc_Versions; type TPasdocOptions = class(TOptionParser) public OptionVerbosity: TIntegerOption; OptionDefine: TStringOptionList; OptionHelp: TBoolOption; OptionVersion: TBoolOption; OptionIncludePaths: TPathListOption; OptionDescriptions, OptionConditionalFile, OptionSourceList, OptionAbbrevFiles: TStringOptionList; OptionHtmlHelpContents, OptionHeader, OptionFooter, OptionHtmlHead, OptionHtmlBodyBegin, OptionHtmlBodyEnd, OptionName, OptionTitle, OptionFormat, OptionOutputPath, OptionLanguage, OptionAspell: TStringOption; OptionSpellCheck: TBoolOption; OptionSpellCheckIgnoreWords: TStringOption; OptionStarOnly, OptionExcludeGenerator, OptionIncludeCreationTime, OptionNumericFilenames, OptionWriteUsesList, OptionWriteGVUses, OptionWriteGVClasses: TBoolOption; OptionLinkGVUses: TStringOption; OptionLinkGVClasses: TStringOption; OptionVisibleMembers: TSetOption; OptionCommentMarker: TStringOptionList; OptionMarkerOptional: TBoolOption; OptionIgnoreLeading: TStringOption; OptionCacheDir: TStringOption; OptionFullLink: TBoolOption; OptionCSS: TStringOption; {< Using external CSS file for HTML output } OptionAutoAbstract: TBoolOption; OptionLinkLook: TStringOption; OptionUseTipueSearch: TBoolOption; OptionSort: TSetOption; OptionIntroduction: TStringOption; OptionConclusion: TStringOption; OptionLatexHead: TStringOption; OptionImplicitVisibility: TStringOption; OptionNoMacro: TBoolOption; OptionAutoLink: TBoolOption; OptionAutoLinkExclude: TStringOption; OptionExternalClassHierarchy: TStringOption; public constructor Create; override; procedure InterpretCommandline(PasDoc: TPasDoc); end; type TPasdocMain = class private procedure WriteWarning(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); procedure PrintHeader; procedure PrintUsage(OptionParser: TOptionParser); procedure PrintVersion; public procedure Execute; end; { ---------------------------------------------------------------------------- } constructor TPasdocOptions.Create; var l: TLanguageID; begin inherited; OptionHelp := TBoolOption.Create('?', 'help'); OptionHelp.Explanation := 'Show this help'; AddOption(OptionHelp); OptionVersion := TBoolOption.Create(#0, 'version'); OptionVersion.Explanation := 'Show pasdoc version (and related info)'; AddOption(OptionVersion); OptionVerbosity := TIntegerOption.Create('v', 'verbosity'); OptionVerbosity.Value := DEFAULT_VERBOSITY_LEVEL; OptionVerbosity.Explanation := 'Set log verbosity (0-6) ['+IntToStr(DEFAULT_VERBOSITY_LEVEL)+']'; AddOption(OptionVerbosity); OptionDefine := TStringOptionList.Create('D', 'define'); OptionDefine.Explanation := 'Define conditional'; AddOption(OptionDefine); OptionDescriptions := TStringOptionList.Create('R', 'description'); OptionDescriptions.Explanation := 'Read description from this file'; AddOption(OptionDescriptions); OptionConditionalFile := TStringOptionList.Create('d', 'conditionals'); OptionConditionalFile.Explanation := 'Read conditionals from this file'; AddOption(OptionConditionalFile); OptionIncludePaths := TPathListOption.Create('I', 'include'); OptionIncludePaths.Explanation := 'Includes search path'; AddOption(OptionIncludePaths); OptionSourceList := TStringOptionList.Create('S', 'source'); OptionSourceList.Explanation := 'Read source filenames from file'; AddOption(OptionSourceList); OptionHtmlHelpContents := TStringOption.Create(#0, 'html-help-contents'); OptionHtmlHelpContents.Explanation := 'Read Contents for HtmlHelp from file'; AddOption(OptionHtmlHelpContents); OptionHeader := TStringOption.Create('H', 'header'); OptionHeader.Explanation := 'Include file as header for HTML output'; AddOption(OptionHeader); OptionFooter := TStringOption.Create('F', 'footer'); OptionFooter.Explanation := 'Include file as footer for HTML output'; AddOption(OptionFooter); OptionHtmlHead := TStringOption.Create(#0, 'html-head'); OptionHtmlHead.Explanation := 'Include file to use inside HTML <head>'; AddOption(OptionHtmlHead); OptionHtmlBodyBegin := TStringOption.Create(#0, 'html-body-begin'); OptionHtmlBodyBegin.Explanation := 'Include file to use right after HTML <body>'; AddOption(OptionHtmlBodyBegin); OptionHtmlBodyEnd := TStringOption.Create(#0, 'html-body-end'); OptionHtmlBodyEnd.Explanation := 'Include file to use right before HTML </body>'; AddOption(OptionHtmlBodyEnd); OptionName := TStringOption.Create('N', 'name'); OptionName.Explanation := 'Name for documentation'; AddOption(OptionName); OptionTitle := TStringOption.Create('T', 'title'); OptionTitle.Explanation := 'Documentation title'; AddOption(OptionTitle); OptionFormat := TStringOption.Create('O', 'format'); OptionFormat.Explanation := 'Output format: html, simplexml, latex, latex2rtf or htmlhelp'; OptionFormat.Value := 'html'; AddOption(OptionFormat); OptionOutputPath := TStringOption.Create('E', 'output'); OptionOutputPath.Explanation := 'Output path'; AddOption(OptionOutputPath); OptionExcludeGenerator := TBoolOption.Create('X', 'exclude-generator'); OptionExcludeGenerator.Explanation := 'Exclude generator information'; AddOption(OptionExcludeGenerator); OptionIncludeCreationTime := TBoolOption.Create(#0, 'include-creation-time'); OptionIncludeCreationTime.Explanation := 'Include creation time in the docs'; AddOption(OptionIncludeCreationTime); OptionLanguage := TStringOption.Create('L', 'language'); OptionLanguage.Explanation := 'Output language. Valid languages are: ' + LineEnding; for l := Low(l) to High(l) do OptionLanguage.Explanation := OptionLanguage.Explanation + ' ' + LanguageDescriptor(l)^.Syntax + ': ' + LanguageDescriptor(l)^.Name + LineEnding; AddOption(OptionLanguage); OptionStarOnly := TBoolOption.Create(#0, 'staronly'); OptionStarOnly.Explanation := 'Parse only {**, (*** and //** style comments'; AddOption(OptionStarOnly); OptionCommentMarker := TStringOptionList.Create(#0, 'marker'); OptionCommentMarker.Explanation := 'Parse only {<marker>, (*<marker> and //<marker> comments. Overrides the staronly option, which is a shortcut for ''--marker=**'''; AddOption(OptionCommentMarker); OptionMarkerOptional := TBoolOption.Create(#0, 'marker-optional'); OptionMarkerOptional.Explanation := 'Do not require the markers given in --marker but remove them from the comment if they exist.'; AddOption(OptionMarkerOptional); OptionIgnoreLeading := TStringOption.Create(#0, 'ignore-leading'); OptionIgnoreLeading.Explanation := 'Ignore leading <ignore-leading> characters in comments.'; AddOption(OptionIgnoreLeading); OptionNumericFilenames := TBoolOption.Create(#0, 'numericfilenames'); OptionNumericFilenames.Explanation := 'Causes the html generator to create numeric filenames'; AddOption(OptionNumericFilenames); OptionVisibleMembers := TSetOption.Create('M','visible-members'); OptionVisibleMembers.Explanation := 'Include / Exclude class Members by visiblity'; OptionVisibleMembers.PossibleValues := VisibilitiesToStr(AllVisibilities); OptionVisibleMembers.Values := VisibilitiesToStr(DefaultVisibilities); AddOption(OptionVisibleMembers); OptionWriteUsesList := TBoolOption.Create(#0, 'write-uses-list'); OptionWriteUsesList.Explanation := 'Put uses list into output'; AddOption(OptionWriteUsesList); OptionWriteGVUses := TBoolOption.Create(#0, 'graphviz-uses'); OptionWriteGVUses.Explanation := 'Write a GVUses.dot file that can be used for the `dot` program from GraphViz to generate a unit dependency graph'; AddOption(OptionWriteGVUses); OptionWriteGVClasses := TBoolOption.Create(#0, 'graphviz-classes'); OptionWriteGVClasses.Explanation := 'Write a GVClasses.dot file that can be used for the `dot` program from GraphViz to generate a class hierarchy graph'; AddOption(OptionWriteGVClasses); OptionLinkGVUses := TStringOption.Create(#0, 'link-gv-uses'); OptionLinkGVUses.Explanation := 'Add a link to a GVUses.<format> file generated by the `dot` program where <format> is any extension that `dot` can generate (e.g. jpg). (currently only for HTML output)'; AddOption(OptionLinkGVUses); OptionLinkGVClasses := TStringOption.Create(#0, 'link-gv-classes'); OptionLinkGVClasses.Explanation := 'Add a link to a GVClasses.<format> file generated by the `dot` program where <format> is any extension that `dot` can generate (e.g. jpg). (currently only for HTML output)'; AddOption(OptionLinkGVClasses); OptionAbbrevFiles := TStringOptionList.Create(#0, 'abbreviations'); OptionAbbrevFiles.Explanation := 'Abbreviation file, format is "[name] value", value is trimmed, lines that do not start with ''['' (or whitespace before that) are ignored'; AddOption(OptionAbbrevFiles); OptionSpellCheck := TBoolOption.Create(#0, 'spell-check'); OptionSpellCheck.Explanation := 'Enable spell-checking by Aspell, specify language by the --language option'; AddOption(OptionSpellCheck); OptionSpellCheckIgnoreWords := TStringOption.Create(#0, 'spell-check-ignore-words'); OptionSpellCheckIgnoreWords.Explanation := 'When spell-checking, ignore the words in that file. The file should contain one word on every line'; AddOption(OptionSpellCheckIgnoreWords); OptionASPELL := TStringOption.Create(#0, 'aspell'); OptionASPELL.Explanation := 'Deprecated, use --spell-check. Enable spell-checking by Aspell, giving language as parameter'; AddOption(OptionASPELL); OptionCacheDir := TStringOption.Create(#0, 'cache-dir'); OptionCacheDir.Explanation := 'Cache directory for parsed files (default not set)'; AddOption(OptionCacheDir); OptionLinkLook := TStringOption.Create(#0, 'link-look'); OptionLinkLook.Explanation := 'How links are displayed in documentation: "default" (show the complete link name, as specified by @link), "full" (show the complete link name, and try to make each part of it a link), or "stripped" (show only last part of the link)'; OptionLinkLook.Value := 'default'; { default value is 'default' } AddOption(OptionLinkLook); OptionFullLink := TBoolOption.Create(#0, 'full-link'); OptionFullLink.Explanation := 'Obsolete name for --link-look=full'; AddOption(OptionFullLink); { Using external CSS file for HTML output. } OptionCSS := TStringOption.Create(#0, 'css'); OptionCSS.Explanation := 'CSS file for HTML files (copied into output tree)'; AddOption(OptionCSS); OptionAutoAbstract := TBoolOption.Create(#0, 'auto-abstract'); OptionAutoAbstract.Explanation := 'If set, pasdoc will automatically make abstract description of every item from the first sentence of description of this item'; AddOption(OptionAutoAbstract); OptionUseTipueSearch := TBoolOption.Create(#0, 'use-tipue-search'); OptionUseTipueSearch.Explanation := 'Use tipue search engine in HTML output'; AddOption(OptionUseTipueSearch); OptionSort := TSetOption.Create(#0, 'sort'); OptionSort.Explanation := 'Specifies what groups of items are sorted (the rest is presented in the same order they were declared in your source files)'; OptionSort.PossibleValues := SortSettingsToName(AllSortSettings); OptionSort.Values := ''; AddOption(OptionSort); OptionIntroduction := TStringOption.Create(#0, 'introduction'); OptionIntroduction.Explanation := 'The name of a text file with introductory materials for the project'; OptionIntroduction.Value := ''; AddOption(OptionIntroduction); OptionConclusion := TStringOption.Create(#0, 'conclusion'); OptionConclusion.Explanation := 'The name of a text file with concluding materials for the project'; OptionConclusion.Value := ''; AddOption(OptionConclusion); OptionLatexHead := TStringOption.Create(#0, 'latex-head'); OptionLatexHead.Explanation := 'The name of a text file that includes lines to be inserted into the preamble of a LaTeX file'; OptionLatexHead.Value := ''; AddOption(OptionLatexHead); OptionImplicitVisibility := TStringOption.Create(#0, 'implicit-visibility'); OptionImplicitVisibility.Explanation := 'How pasdoc should handle class members within default class visibility'; OptionImplicitVisibility.Value := 'public'; AddOption(OptionImplicitVisibility); OptionNoMacro := TBoolOption.Create(#0, 'no-macro'); OptionNoMacro.Explanation := 'Turn FPC macro support off'; AddOption(OptionNoMacro); OptionAutoLink := TBoolOption.Create(#0, 'auto-link'); OptionAutoLink.Explanation := 'Automatically create links, without the need to explicitly use @link tags'; AddOption(OptionAutoLink); OptionAutoLinkExclude := TStringOption.Create(#0, 'auto-link-exclude'); OptionAutoLinkExclude.Explanation := 'Even when --auto-link is on, never automatically create links to identifiers in the specified file. The file should contain one identifier on every line'; AddOption(OptionAutoLinkExclude); OptionExternalClassHierarchy := TStringOption.Create(#0, 'external-class-hierarchy'); OptionExternalClassHierarchy.Explanation := 'File defining hierarchy of classes not included in your source code, for more complete class tree diagrams'; AddOption(OptionExternalClassHierarchy); end; procedure TPasdocMain.PrintHeader; begin WriteLn(PASDOC_FULL_INFO); WriteLn('Documentation generator for Pascal source'); WriteLn; WriteLn('This is free software; see the source for copying conditions. There is NO'); WriteLn('warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.'); WriteLn; end; procedure TPasdocMain.PrintUsage(OptionParser: TOptionParser); begin PrintHeader; WriteLn('Usage: ' + ExtractFileName(ParamStr(0)) + ' [options] [files]'); WriteLn('Valid options are: '); OptionParser.WriteExplanations; end; procedure TPasdocMain.PrintVersion; begin Writeln(PASDOC_FULL_INFO); end; type EInvalidCommandLine = class(Exception); procedure TPasdocOptions.InterpretCommandline(PasDoc: TPasDoc); { sets the html specific options and returns its parameter as TDocGenerator } function SetHtmlOptions(Generator: TGenericHTMLDocGenerator): TDocGenerator; begin if OptionHeader.WasSpecified then Generator.Header := FileToString(OptionHeader.Value); if OptionFooter.WasSpecified then Generator.Footer := FileToString(OptionFooter.Value); if OptionHtmlHead.WasSpecified then Generator.HtmlHead := FileToString(OptionHtmlHead.Value); if OptionHtmlBodyBegin.WasSpecified then Generator.HtmlBodyBegin := FileToString(OptionHtmlBodyBegin.Value); if OptionHtmlBodyEnd.WasSpecified then Generator.HtmlBodyEnd := FileToString(OptionHtmlBodyEnd.Value); if OptionCSS.WasSpecified then Generator.CSS := FileToString(OptionCSS.Value); Generator.NumericFilenames := OptionNumericFilenames.TurnedOn; Generator.UseTipueSearch := OptionUseTipueSearch.TurnedOn; Result := Generator; end; function SetSimpleXMLOptions(Generator: TSimpleXMLDocGenerator): TDocGenerator; begin Result := Generator; end; { Sets HTML-help specific options and returns its parameter as TDocGenerator } function SetHtmlHelpOptions(Generator: THTMLHelpDocGenerator): TDocGenerator; begin Generator.ContentsFile := OptionHtmlHelpContents.Value; Result := SetHtmlOptions(Generator); end; { Sets Latex specific options and returns its parameter as TDocGenerator } function SetLatexOptions(Generator: TTexDocGenerator): TDocGenerator; begin if OptionLatexHead.Value <> '' then try Generator.LatexHead.LoadFromFile(OptionLatexHead.Value); except on E: Exception do begin E.Message := 'Error when opening file for "--latex-head" option: ' + E.Message; raise; end; end; Result := Generator; end; { Sets Latex and Latex2rtf specific options and returns its parameter as TDocGenerator } function SetRtfOptions(Generator: TTexDocGenerator): TDocGenerator; begin Generator.Latex2rtf := True; Result := SetLatexOptions(Generator); end; function GetLanguageFromStr(S: string): TLanguageID; begin if not LanguageFromStr(S, Result) then raise EInvalidCommandLine.CreateFmt('Unknown language code "%s"', [S]); end; var i: Integer; SS: TSortSetting; Vis: TVisibility; begin OptionFormat.Value := LowerCase(OptionFormat.Value); if OptionFormat.Value = 'html' then begin PasDoc.Generator := SetHtmlOptions(THTMLDocGenerator.Create(PasDoc)); end else if OptionFormat.Value = 'simplexml' then begin PasDoc.Generator := SetSimpleXMLOptions(TSimpleXMLDocGenerator.Create(PasDoc)); end else if OptionFormat.Value = 'latex' then begin PasDoc.Generator := SetLatexOptions(TTexDocGenerator.Create(PasDoc)); end else if OptionFormat.Value = 'latex2rtf' then begin PasDoc.Generator := SetRtfOptions(TTexDocGenerator.Create(PasDoc)); end else if OptionFormat.Value = 'htmlhelp' then begin PasDoc.Generator := SetHtmlHelpOptions(THTMLHelpDocGenerator.Create(PasDoc)); end else begin raise EInvalidCommandLine.CreateFmt( 'Unknown output format "%s"', [OptionFormat.Value]); end; PasDoc.Directives.Assign(OptionDefine.Values); for i := 0 to OptionConditionalFile.Values.Count - 1 do begin PasDoc.Directives.LoadFromTextFileAdd(OptionConditionalFile.Values[i]); end; PasDoc.Generator.DestinationDirectory := OptionOutputPath.Value; PasDoc.IncludeDirectories.Assign(OptionIncludePaths.Values); if OptionLanguage.WasSpecified then PasDoc.Generator.Language := GetLanguageFromStr(OptionLanguage.Value); PasDoc.ProjectName := OptionName.Value; PasDoc.DescriptionFileNames.Assign(OptionDescriptions.Values); for i := 0 to OptionSourceList.Values.Count - 1 do begin PasDoc.AddSourceFileNamesFromFile(OptionSourceList.Values[i], true); end; PasDoc.Title := OptionTitle.Value; PasDoc.Verbosity := OptionVerbosity.Value; PasDoc.Generator.ExcludeGenerator := OptionExcludeGenerator.TurnedOn; PasDoc.Generator.IncludeCreationTime := OptionIncludeCreationTime.TurnedOn; PasDoc.Generator.WriteUsesClause := OptionWriteUsesList.TurnedOn; if OptionUseTipueSearch.TurnedOn then begin if not (PasDoc.Generator is TGenericHTMLDocGenerator) then begin raise EInvalidCommandLine.Create( 'You can''t specify --use-tipue-search option for non-html output formats'); end; end; if OptionHtmlHelpContents.Value <> '' then begin if not (PasDoc.Generator is THTMLHelpDocGenerator) then begin raise EInvalidCommandLine.Create('You can specify --html-help-contents' + ' option only for HTMLHelp output format'); end; end; if OptionCommentMarker.WasSpecified then begin PasDoc.CommentMarkers.Assign(OptionCommentMarker.Values); end; if OptionStarOnly.TurnedOn then PasDoc.StarOnly := true; PasDoc.MarkerOptional := OptionMarkerOptional.TurnedOn; PasDoc.IgnoreLeading := OptionIgnoreLeading.Value; PasDoc.AddSourceFileNames(LeftList); PasDoc.ShowVisibilities := []; for Vis := Low(Vis) to High(Vis) do if OptionVisibleMembers.HasValue(VisToStr(Vis)) then PasDoc.ShowVisibilities := PasDoc.ShowVisibilities + [Vis]; PasDoc.Generator.OutputGraphVizUses := OptionWriteGVUses.TurnedOn; PasDoc.Generator.OutputGraphVizClassHierarchy := OptionWriteGVClasses.TurnedOn; PasDoc.Generator.LinkGraphVizUses := OptionLinkGVUses.Value; PasDoc.Generator.LinkGraphVizClasses := OptionLinkGVClasses.Value; for i := 0 to OptionAbbrevFiles.Values.Count-1 do begin PasDoc.Generator.ParseAbbreviationsFile(OptionAbbrevFiles.Values[i]); end; PasDoc.Generator.CheckSpelling := OptionASPELL.WasSpecified or OptionSpellCheck.WasSpecified; if OptionSpellCheck.WasSpecified then PasDoc.Generator.AspellLanguage := LanguageCode(PasDoc.Generator.Language) else if OptionASPELL.Value = '' then PasDoc.Generator.AspellLanguage := LanguageCode(PasDoc.Generator.Language) else PasDoc.Generator.AspellLanguage := OptionASPELL.Value; if OptionSpellCheckIgnoreWords.Value <> '' then PasDoc.Generator.SpellCheckIgnoreWords.LoadFromFile( OptionSpellCheckIgnoreWords.Value); PasDoc.CacheDir := OptionCacheDir.Value; PasDoc.Generator.AutoAbstract := OptionAutoAbstract.TurnedOn; if SameText(OptionLinkLook.Value, 'default') then PasDoc.Generator.LinkLook := llDefault else if SameText(OptionLinkLook.Value, 'full') then PasDoc.Generator.LinkLook := llFull else if SameText(OptionLinkLook.Value, 'stripped') then PasDoc.Generator.LinkLook := llStripped else raise EInvalidCommandLine.CreateFmt( 'Invalid argument for "--link-look" option : "%s"', [OptionLinkLook.Value]); if OptionFullLink.TurnedOn then PasDoc.Generator.LinkLook := llFull; { interpret OptionSort value } PasDoc.SortSettings := []; for SS := Low(SS) to High(SS) do if OptionSort.HasValue(SortSettingNames[SS]) then PasDoc.SortSettings := PasDoc.SortSettings + [SS]; PasDoc.IntroductionFileName := OptionIntroduction.Value; PasDoc.ConclusionFileName := OptionConclusion.Value; if OptionLatexHead.Value <> '' then begin if not (PasDoc.Generator is TTexDocGenerator) then begin raise EInvalidCommandLine.Create( 'You can only use the "latex-head" option with LaTeX output.'); end; end; if SameText(OptionImplicitVisibility.Value, 'public') then PasDoc.ImplicitVisibility := ivPublic else if SameText(OptionImplicitVisibility.Value, 'published') then PasDoc.ImplicitVisibility := ivPublished else if SameText(OptionImplicitVisibility.Value, 'implicit') then PasDoc.ImplicitVisibility := ivImplicit else raise EInvalidCommandLine.CreateFmt( 'Invalid argument for "--implicit-visibility" option : "%s"', [OptionImplicitVisibility.Value]); PasDoc.HandleMacros := not OptionNoMacro.TurnedOn; PasDoc.AutoLink := OptionAutoLink.TurnedOn; if OptionAutoLinkExclude.Value <> '' then begin PasDoc.Generator.AutoLinkExclude.LoadFromFile(OptionAutoLinkExclude.Value); { Sorted makes searching AutoLinkExclude.IndexOf (used heavily when auto-linking to respect this option) obviously much faster. The speed improvement can be literally felt when you specified large file like /usr/share/dict/american-english for this option. } PasDoc.Generator.AutoLinkExclude.Sorted := true; end; if OptionExternalClassHierarchy.WasSpecified then PasDoc.Generator.ExternalClassHierarchy.LoadFromFile( OptionExternalClassHierarchy.Value); end; { ---------------------------------------------------------------------------- } procedure TPasdocMain.WriteWarning(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); begin case MessageType of pmtInformation: WriteLn('Info[', AVerbosity, ']: ', AMessage); pmtWarning: WriteLn('Warning[', AVerbosity, ']: ', AMessage); pmtError: WriteLn('Error[', AVerbosity, ']: ', AMessage); else WriteLn(AMessage); end; end; { ---------------------------------------------------------------------------- } procedure TPasdocMain.Execute; var PasDoc: TPasDoc; OptionParser: TPasdocOptions; begin OptionParser := TPasdocOptions.Create; try OptionParser.ParseOptions; if OptionParser.OptionHelp.TurnedOn then begin PrintUsage(OptionParser); Exit; end; if OptionParser.OptionVersion.TurnedOn then begin PrintVersion; Exit; end; if not OptionParser.OptionExcludeGenerator.TurnedOn then PrintHeader; try PasDoc := TPasDoc.Create(nil); try PasDoc.OnMessage := {$ifdef FPC}@{$endif} WriteWarning; OptionParser.InterpretCommandline(PasDoc); PasDoc.Execute; finally PasDoc.Free; end; except on e: Exception do with e do WriteLn('Fatal Error: ', Message); end; finally OptionParser.Free; end; end; procedure Main; var PasdocMain: TPasdocMain; begin {$IFNDEF FPC} {$IFDEF CONDITIONALEXPRESSIONS} {$IF CompilerVersion > 17} ReportMemoryLeaksOnShutdown := DebugHook <> 0; {$IFEND} {$ENDIF} {$ENDIF} try PasdocMain := TPasdocMain.Create; try PasdocMain.Execute; finally PasdocMain.Free; end; except on E: Exception do WriteLn(E.ClassName + ' :' + E.Message); end; {$IFNDEF FPC} {$IFDEF CONDITIONALEXPRESSIONS} {$IF CompilerVersion > 14} {$WARN SYMBOL_PLATFORM OFF} {$IFEND} {$ENDIF} if DebugHook <> 0 then ReadLn; {$ENDIF} end; end. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/console/pasdoc.bdsproj����������������������������������������������������������������0000600�0001750�0001750�00000021111�13034465544�020267� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <BorlandProject> <PersonalityInfo> <Option> <Option Name="Personality">Delphi.Personality</Option> <Option Name="ProjectType">VCLApplication</Option> <Option Name="Version">1.0</Option> <Option Name="GUID">{EF279D30-DF85-4096-B636-99517C7C1E58}</Option> </Option> </PersonalityInfo> <Delphi.Personality> <Source> <Source Name="MainSource">pasdoc.dpr</Source> </Source> <FileVersion> <FileVersion Name="Version">7.0</FileVersion> </FileVersion> <Compiler> <Compiler Name="A">8</Compiler> <Compiler Name="B">0</Compiler> <Compiler Name="C">1</Compiler> <Compiler Name="D">1</Compiler> <Compiler Name="E">0</Compiler> <Compiler Name="F">0</Compiler> <Compiler Name="G">1</Compiler> <Compiler Name="H">1</Compiler> <Compiler Name="I">1</Compiler> <Compiler Name="J">1</Compiler> <Compiler Name="K">0</Compiler> <Compiler Name="L">1</Compiler> <Compiler Name="M">0</Compiler> <Compiler Name="N">1</Compiler> <Compiler Name="O">0</Compiler> <Compiler Name="P">1</Compiler> <Compiler Name="Q">1</Compiler> <Compiler Name="R">1</Compiler> <Compiler Name="S">0</Compiler> <Compiler Name="T">0</Compiler> <Compiler Name="U">0</Compiler> <Compiler Name="V">1</Compiler> <Compiler Name="W">0</Compiler> <Compiler Name="X">1</Compiler> <Compiler Name="Y">1</Compiler> <Compiler Name="Z">1</Compiler> <Compiler Name="ShowHints">True</Compiler> <Compiler Name="ShowWarnings">True</Compiler> <Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler> <Compiler Name="NamespacePrefix"></Compiler> <Compiler Name="GenerateDocumentation">False</Compiler> <Compiler Name="DefaultNamespace"></Compiler> <Compiler Name="SymbolDeprecated">True</Compiler> <Compiler Name="SymbolLibrary">True</Compiler> <Compiler Name="SymbolPlatform">True</Compiler> <Compiler Name="SymbolExperimental">True</Compiler> <Compiler Name="UnitLibrary">True</Compiler> <Compiler Name="UnitPlatform">True</Compiler> <Compiler Name="UnitDeprecated">True</Compiler> <Compiler Name="UnitExperimental">True</Compiler> <Compiler Name="HResultCompat">True</Compiler> <Compiler Name="HidingMember">True</Compiler> <Compiler Name="HiddenVirtual">True</Compiler> <Compiler Name="Garbage">True</Compiler> <Compiler Name="BoundsError">True</Compiler> <Compiler Name="ZeroNilCompat">True</Compiler> <Compiler Name="StringConstTruncated">True</Compiler> <Compiler Name="ForLoopVarVarPar">True</Compiler> <Compiler Name="TypedConstVarPar">True</Compiler> <Compiler Name="AsgToTypedConst">True</Compiler> <Compiler Name="CaseLabelRange">True</Compiler> <Compiler Name="ForVariable">True</Compiler> <Compiler Name="ConstructingAbstract">True</Compiler> <Compiler Name="ComparisonFalse">True</Compiler> <Compiler Name="ComparisonTrue">True</Compiler> <Compiler Name="ComparingSignedUnsigned">True</Compiler> <Compiler Name="CombiningSignedUnsigned">True</Compiler> <Compiler Name="UnsupportedConstruct">True</Compiler> <Compiler Name="FileOpen">True</Compiler> <Compiler Name="FileOpenUnitSrc">True</Compiler> <Compiler Name="BadGlobalSymbol">True</Compiler> <Compiler Name="DuplicateConstructorDestructor">True</Compiler> <Compiler Name="InvalidDirective">True</Compiler> <Compiler Name="PackageNoLink">True</Compiler> <Compiler Name="PackageThreadVar">True</Compiler> <Compiler Name="ImplicitImport">True</Compiler> <Compiler Name="HPPEMITIgnored">True</Compiler> <Compiler Name="NoRetVal">True</Compiler> <Compiler Name="UseBeforeDef">True</Compiler> <Compiler Name="ForLoopVarUndef">True</Compiler> <Compiler Name="UnitNameMismatch">True</Compiler> <Compiler Name="NoCFGFileFound">True</Compiler> <Compiler Name="ImplicitVariants">True</Compiler> <Compiler Name="UnicodeToLocale">True</Compiler> <Compiler Name="LocaleToUnicode">True</Compiler> <Compiler Name="ImagebaseMultiple">True</Compiler> <Compiler Name="SuspiciousTypecast">True</Compiler> <Compiler Name="PrivatePropAccessor">True</Compiler> <Compiler Name="UnsafeType">False</Compiler> <Compiler Name="UnsafeCode">False</Compiler> <Compiler Name="UnsafeCast">False</Compiler> <Compiler Name="OptionTruncated">True</Compiler> <Compiler Name="WideCharReduced">True</Compiler> <Compiler Name="DuplicatesIgnored">True</Compiler> <Compiler Name="UnitInitSeq">True</Compiler> <Compiler Name="LocalPInvoke">True</Compiler> <Compiler Name="MessageDirective">True</Compiler> <Compiler Name="CodePage"></Compiler> </Compiler> <Linker> <Linker Name="MapFile">0</Linker> <Linker Name="OutputObjs">0</Linker> <Linker Name="GenerateHpps">False</Linker> <Linker Name="ConsoleApp">1</Linker> <Linker Name="DebugInfo">False</Linker> <Linker Name="RemoteSymbols">False</Linker> <Linker Name="GenerateDRC">False</Linker> <Linker Name="MinStackSize">16384</Linker> <Linker Name="MaxStackSize">1048576</Linker> <Linker Name="ImageBase">4194304</Linker> <Linker Name="ExeDescription"></Linker> </Linker> <Directories> <Directories Name="OutputDir"></Directories> <Directories Name="UnitOutputDir"></Directories> <Directories Name="PackageDLLOutputDir"></Directories> <Directories Name="PackageDCPOutputDir"></Directories> <Directories Name="SearchPath">..\component;..\component\tipue;..\component\images</Directories> <Directories Name="Packages">vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;dclOffice2k;DJcl;JVCL200_R70;qrpt</Directories> <Directories Name="Conditionals"></Directories> <Directories Name="DebugSourceDirs">..\component;..\Console;..\component\tipue</Directories> <Directories Name="UsePackages">False</Directories> </Directories> <Parameters> <Parameters Name="RunParams"></Parameters> <Parameters Name="HostApplication"></Parameters> <Parameters Name="Launcher"></Parameters> <Parameters Name="UseLauncher">False</Parameters> <Parameters Name="DebugCWD"></Parameters> <Parameters Name="Debug Symbols Search Path"></Parameters> <Parameters Name="LoadAllSymbols">True</Parameters> <Parameters Name="LoadUnspecifiedSymbols">False</Parameters> </Parameters> <Language> <Language Name="ActiveLang"></Language> <Language Name="ProjectLang">$00000000</Language> <Language Name="RootDir"></Language> </Language> <VersionInfo> <VersionInfo Name="IncludeVerInfo">False</VersionInfo> <VersionInfo Name="AutoIncBuild">False</VersionInfo> <VersionInfo Name="MajorVer">1</VersionInfo> <VersionInfo Name="MinorVer">0</VersionInfo> <VersionInfo Name="Release">0</VersionInfo> <VersionInfo Name="Build">0</VersionInfo> <VersionInfo Name="Debug">False</VersionInfo> <VersionInfo Name="PreRelease">False</VersionInfo> <VersionInfo Name="Special">False</VersionInfo> <VersionInfo Name="Private">False</VersionInfo> <VersionInfo Name="DLL">False</VersionInfo> <VersionInfo Name="Locale">1031</VersionInfo> <VersionInfo Name="CodePage">1252</VersionInfo> </VersionInfo> <VersionInfoKeys> <VersionInfoKeys Name="CompanyName"></VersionInfoKeys> <VersionInfoKeys Name="FileDescription"></VersionInfoKeys> <VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys> <VersionInfoKeys Name="InternalName"></VersionInfoKeys> <VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys> <VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys> <VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys> <VersionInfoKeys Name="ProductName"></VersionInfoKeys> <VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys> <VersionInfoKeys Name="Comments"></VersionInfoKeys> </VersionInfoKeys> </Delphi.Personality> </BorlandProject> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/���������������������������������������������������������������������������0000700�0001750�0001750�00000000000�13237143042�016071� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/pasdoc_gui.dof�������������������������������������������������������������0000600�0001750�0001750�00000003377�13034465544�020725� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[FileVersion] Version=7.0 [Compiler] A=8 B=0 C=1 D=1 E=0 F=0 G=1 H=1 I=1 J=0 K=0 L=1 M=0 N=1 O=1 P=1 Q=0 R=0 S=0 T=0 U=0 V=1 W=0 X=1 Y=1 Z=1 ShowHints=1 ShowWarnings=1 UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; NamespacePrefix= SymbolDeprecated=1 SymbolLibrary=1 SymbolPlatform=1 UnitLibrary=1 UnitPlatform=1 UnitDeprecated=1 HResultCompat=1 HidingMember=1 HiddenVirtual=1 Garbage=1 BoundsError=1 ZeroNilCompat=1 StringConstTruncated=1 ForLoopVarVarPar=1 TypedConstVarPar=1 AsgToTypedConst=1 CaseLabelRange=1 ForVariable=1 ConstructingAbstract=1 ComparisonFalse=1 ComparisonTrue=1 ComparingSignedUnsigned=1 CombiningSignedUnsigned=1 UnsupportedConstruct=1 FileOpen=1 FileOpenUnitSrc=1 BadGlobalSymbol=1 DuplicateConstructorDestructor=1 InvalidDirective=1 PackageNoLink=1 PackageThreadVar=1 ImplicitImport=1 HPPEMITIgnored=1 NoRetVal=1 UseBeforeDef=1 ForLoopVarUndef=1 UnitNameMismatch=1 NoCFGFileFound=1 MessageDirective=1 ImplicitVariants=1 UnicodeToLocale=1 LocaleToUnicode=1 ImagebaseMultiple=1 SuspiciousTypecast=1 PrivatePropAccessor=1 UnsafeType=0 UnsafeCode=0 UnsafeCast=0 [Linker] MapFile=0 OutputObjs=0 ConsoleApp=1 DebugInfo=0 RemoteSymbols=0 MinStackSize=16384 MaxStackSize=1048576 ImageBase=4194304 ExeDescription= [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath=..\component;..\component\images;..\component\tipue Packages= Conditionals= DebugSourceDirs=..\component;..\Console;..\component\tipue UsePackages=0 [Parameters] RunParams= HostApplication= Launcher= UseLauncher=0 DebugCWD= [Language] ActiveLang= ProjectLang= RootDir= [Version Info] IncludeVerInfo=0 AutoIncBuild=0 MajorVer=1 MinorVer=0 Release=0 Build=0 Debug=0 PreRelease=0 Special=0 Private=0 DLL=0 Locale=1031 CodePage=1252 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/pasdoc_gui.dproj�����������������������������������������������������������0000600�0001750�0001750�00000010656�13034465544�021271� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <ProjectGuid>{d6674a0e-9e27-4eb8-9b5f-d0b955f2e525}</ProjectGuid> <MainSource>pasdoc_gui.dpr</MainSource> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <DCC_DCCCompiler>DCC32</DCC_DCCCompiler> <DCC_DependencyCheckOutputName>pasdoc_gui.exe</DCC_DependencyCheckOutputName> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <Version>7.0</Version> <DCC_DebugInformation>False</DCC_DebugInformation> <DCC_LocalDebugSymbols>False</DCC_LocalDebugSymbols> <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> <DCC_UnitSearchPath>..\component;..\component\images;..\component\tipue</DCC_UnitSearchPath> <DCC_ResourcePath>..\component;..\component\images;..\component\tipue</DCC_ResourcePath> <DCC_ObjPath>..\component;..\component\images;..\component\tipue</DCC_ObjPath> <DCC_IncludePath>..\component;..\component\images;..\component\tipue</DCC_IncludePath> <DCC_Define>RELEASE</DCC_Define> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <Version>7.0</Version> <DCC_UnitSearchPath>..\component;..\component\images;..\component\tipue</DCC_UnitSearchPath> <DCC_ResourcePath>..\component;..\component\images;..\component\tipue</DCC_ResourcePath> <DCC_ObjPath>..\component;..\component\images;..\component\tipue</DCC_ObjPath> <DCC_IncludePath>..\component;..\component\images;..\component\tipue</DCC_IncludePath> <DCC_Define>DEBUG</DCC_Define> </PropertyGroup> <ProjectExtensions> <Borland.Personality>Delphi.Personality</Borland.Personality> <Borland.ProjectType>VCLApplication</Borland.ProjectType> <BorlandProject> <BorlandProject xmlns=""> <Delphi.Personality> <Parameters> <Parameters Name="DebugSourceDirs">..\component;..\Console;..\component\tipue</Parameters> <Parameters Name="UseLauncher">False</Parameters> <Parameters Name="LoadAllSymbols">True</Parameters> <Parameters Name="LoadUnspecifiedSymbols">False</Parameters> </Parameters> <VersionInfo> <VersionInfo Name="IncludeVerInfo">False</VersionInfo> <VersionInfo Name="AutoIncBuild">False</VersionInfo> <VersionInfo Name="MajorVer">1</VersionInfo> <VersionInfo Name="MinorVer">0</VersionInfo> <VersionInfo Name="Release">0</VersionInfo> <VersionInfo Name="Build">0</VersionInfo> <VersionInfo Name="Debug">False</VersionInfo> <VersionInfo Name="PreRelease">False</VersionInfo> <VersionInfo Name="Special">False</VersionInfo> <VersionInfo Name="Private">False</VersionInfo> <VersionInfo Name="DLL">False</VersionInfo> <VersionInfo Name="Locale">1031</VersionInfo> <VersionInfo Name="CodePage">1252</VersionInfo> </VersionInfo> <VersionInfoKeys> <VersionInfoKeys Name="CompanyName"></VersionInfoKeys> <VersionInfoKeys Name="FileDescription"></VersionInfoKeys> <VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys> <VersionInfoKeys Name="InternalName"></VersionInfoKeys> <VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys> <VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys> <VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys> <VersionInfoKeys Name="ProductName"></VersionInfoKeys> <VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys> <VersionInfoKeys Name="Comments"></VersionInfoKeys> </VersionInfoKeys> <Source> <Source Name="MainSource">pasdoc_gui.dpr</Source> </Source> </Delphi.Personality> </BorlandProject></BorlandProject> </ProjectExtensions> <ItemGroup /> <ItemGroup> <DelphiCompile Include="pasdoc_gui.dpr"> <MainSource>MainSource</MainSource> </DelphiCompile> <DCCReference Include="frmAboutUnit.pas"> <Form>frmAbout</Form> </DCCReference> <DCCReference Include="frmhelpgeneratorunit.pas"> <Form>frmHelpGenerator</Form> </DCCReference> <DCCReference Include="PasDocGuiSettings.pas" /> <DCCReference Include="preferencesfrm.pas"> <Form>preferencesfrm</Form> </DCCReference> <DCCReference Include="WWWBrowserRunnerDM.pas"> <Form>WWWBrowserRunner</Form> </DCCReference> </ItemGroup> <Import Project="$(MSBuildBinPath)\Borland.Delphi.Targets" /> </Project>����������������������������������������������������������������������������������pasdoc/source/delphi_gui/WWWBrowserRunnerDM.dfm�����������������������������������������������������0000600�0001750�0001750�00000000271�13034465544�022237� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������object WWWBrowserRunner: TWWWBrowserRunner OldCreateOrder = True OnCreate = DataModuleCreate OnDestroy = DataModuleDestroy Left = 15 Top = 15 Height = 161 Width = 278 end ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/PasDocGuiSettings.pas������������������������������������������������������0000600�0001750�0001750�00000013013�13237143042�022135� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "pasdoc_gui". "pasdoc_gui" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "pasdoc_gui" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "pasdoc_gui"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { This unit provides @link(IniFile) variable that can be used to store some user configuration. It also declares some global variables that are part of user configuration and don't fit anywhere else, like WWWHelpServer. @author(Michalis Kamburelis) } unit PasDocGuiSettings; interface {$IFDEF ConditionalExpressions} {$IF CompilerVersion >= 15} {$WARN UNSAFE_TYPE OFF} {$WARN UNSAFE_CAST OFF} {$WARN UNSAFE_CODE OFF} {$IFEND} {$IF CompilerVersion >= 20} {$DEFINE STRING_UNICODE} {$IFEND} {$ENDIF} uses {$IFDEF MSWINDOWS} Windows, {$ENDIF} Classes, SysUtils, IniFiles; var IniFile: TIniFile; const DefaultWWWHelpServer = 'https://github.com/pasdoc/pasdoc/wiki/'; var WWWHelpServer: string; AutoLoadLastProject: Boolean = TRUE; implementation {$ifdef UNIX} { Code below is copied from FPC 2.0.3 rtl/unix/sysutils.pp. It has fixed GetAppConfigDir and GetAppConfigFile, so that 1. config file is stored inside hidden dir 2. moreover it follows base-dir spec Michalis send this patch to FPC and it was applied during FPC 2.0.3 development. So for FPC 2.0.0 and 2.0.2, we need the workaround below. } Function GetHomeDir : String; begin Result:=GetEnvironmentVariable('HOME'); If (Result<>'') then Result:=IncludeTrailingPathDelimiter(Result); end; { Follows base-dir spec, see [http://freedesktop.org/Standards/basedir-spec]. Always ends with PathDelim. } Function XdgConfigHome : String; begin Result:=GetEnvironmentVariable('XDG_CONFIG_HOME'); if (Result='') then Result:=GetHomeDir + '.config/' else Result:=IncludeTrailingPathDelimiter(Result); end; Function GetAppConfigDir(Global : Boolean) : String; begin If Global then Result:=SysConfigDir else Result:=XdgConfigHome + ApplicationName; end; Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String; begin if Global then begin Result:=IncludeTrailingPathDelimiter(SysConfigDir); if SubDir then Result:=IncludeTrailingPathDelimiter(Result+ApplicationName); Result:=Result+ApplicationName+ConfigExtension; end else begin if SubDir then begin Result:=IncludeTrailingPathDelimiter(GetAppConfigDir(False)); Result:=Result+ApplicationName+ConfigExtension; end else begin Result:=XdgConfigHome + ApplicationName + ConfigExtension; end; end; end; {$endif} {$IFNDEF FPC} {$IFDEF MSWINDOWS} function GetCommonAppDataFolder(const SubPath: String): String; var hSHFolderDLL: HMODULE; f_SHGetFolderPath: function(hwndOwner: HWND; nFolder: Integer; hToken: THandle; dwFlags: DWORD; pszPath: PChar): HRESULT; stdcall; Buf: array[0..MAX_PATH - 1] of Char; const CSIDL_LOCAL_APPDATA = $001C; SHGFP_TYPE_CURRENT = 0; begin Result := ''; hSHFolderDLL := LoadLibrary('shfolder.dll'); if hSHFolderDLL = 0 then Exit; try {$IFDEF UNICODE} @f_SHGetFolderPath := GetProcAddress(hSHFolderDLL, 'SHGetFolderPathW'); {$ELSE} @f_SHGetFolderPath := GetProcAddress(hSHFolderDLL, 'SHGetFolderPathA'); {$ENDIF} if @f_SHGetFolderPath = nil then Exit; if Succeeded(f_SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, SHGFP_TYPE_CURRENT, Buf)) then begin Result := ExpandFileName(Buf); Result := IncludeTrailingPathDelimiter(Result) + SubPath; try if not ForceDirectories(Result) then Result := ''; except Result := ''; end; end; finally FreeLibrary(hSHFolderDLL); end; end; function GetAppConfigDir(Global: Boolean) : String; begin Result := GetCommonAppDataFolder(ChangeFileExt(ExtractFileName(ParamStr(0)), '')); if Result = '' then raise Exception.CreateFmt('Cannot create directory for config file: "%s"', [Result]); end; {$ENDIF} {$ENDIF} var ConfigDir: string; initialization { calculate ConfigDir } ConfigDir := GetAppConfigDir(false); if not ForceDirectories(ConfigDir) then raise Exception.CreateFmt('Cannot create directory for config file: "%s"', [ConfigDir]); ConfigDir := IncludeTrailingPathDelimiter(ConfigDir); { initialize IniFile } IniFile := TIniFile.Create(ConfigDir + 'prefs.ini'); WWWHelpServer := IniFile.ReadString('Main', 'WWWHelpServer', DefaultWWWHelpServer); AutoLoadLastProject := IniFile.ReadBool('Main', 'AutoLoadLastProject', TRUE); finalization if IniFile <> nil then begin IniFile.WriteString('Main', 'WWWHelpServer', WWWHelpServer); IniFile.WriteBool('Main', 'AutoLoadLastProject', AutoLoadLastProject); IniFile.UpdateFile; FreeAndNil(IniFile); end; end. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/WWWBrowserRunnerDM.pas�����������������������������������������������������0000644�0001750�0001750�00000004716�13237143042�022263� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "pasdoc_gui". "pasdoc_gui" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "pasdoc_gui" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "pasdoc_gui"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>) } unit WWWBrowserRunnerDM; interface {$IFDEF ConditionalExpressions} {$IF CompilerVersion >= 15} {$WARN UNSAFE_TYPE OFF} {$WARN UNSAFE_CAST OFF} {$WARN UNSAFE_CODE OFF} {$IFEND} {$IF CompilerVersion >= 20} {$DEFINE STRING_UNICODE} {$IFEND} {$ENDIF} uses Classes, SysUtils, Forms, Controls, Dialogs; type { TWWWBrowserRunner } TWWWBrowserRunner = class(TDataModule) procedure DataModuleCreate(Sender: TObject); procedure DataModuleDestroy(Sender: TObject); private { private declarations } public procedure RunBrowser(const URL: string); end; var WWWBrowserRunner: TWWWBrowserRunner; implementation uses {$ifdef WIN32} Windows, ShellAPI, {$endif} PasDocGuiSettings; {$R *.dfm} { TWWWBrowserRunner } procedure TWWWBrowserRunner.DataModuleCreate(Sender: TObject); begin end; procedure TWWWBrowserRunner.DataModuleDestroy(Sender: TObject); begin end; procedure TWWWBrowserRunner.RunBrowser(const URL: string); {$ifdef WIN32} procedure ShellExecuteURL; var ExecInfo: TShellExecuteInfo; const OpenCommand = 'open'; begin ExecInfo.cbSize := SizeOf(ExecInfo); ExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS; ExecInfo.Wnd := 0; // <= Might be "ExecInfo.hWnd" in older FPC ? ExecInfo.lpVerb := PChar(OpenCommand); ExecInfo.lpFile := PChar(URL); ExecInfo.lpParameters := nil; ExecInfo.lpDirectory := nil; ExecInfo.nShow := SW_SHOWNORMAL; ShellExecuteEx(@ExecInfo); end; {$endif} begin {$ifdef WIN32} ShellExecuteURL; {$endif} end; end. ��������������������������������������������������pasdoc/source/delphi_gui/frmhelpgeneratorunit.pas���������������������������������������������������0000600�0001750�0001750�00000155552�13237143042�023061� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Original version 2004-2005 Richard B. Winston, U.S. Geological Survey (USGS) Modifications copyright 2005 Michalis Kamburelis Additional modifications by Richard B. Winston, April 26, 2005. This file is part of pasdoc_gui. pasdoc_gui is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. pasdoc_gui is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with pasdoc_gui; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA } { @abstract(@name contains the main form of Help Generator.) @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>) @created(2004-11-28) } unit frmHelpGeneratorUnit; {$R *.dfm} interface {$IFDEF ConditionalExpressions} {$IF CompilerVersion >= 15} {$WARN UNSAFE_TYPE OFF} {$WARN UNSAFE_CAST OFF} {$WARN UNSAFE_CODE OFF} {$WARN UNIT_PLATFORM OFF} {$IFEND} {$IF CompilerVersion >= 20} {$DEFINE STRING_UNICODE} {$IFEND} {$ENDIF} uses Windows, Classes, SysUtils, Graphics, Controls, Forms, Dialogs, FileCtrl, ComCtrls, ExtCtrls, Menus, Buttons, Spin, CheckLst, PasDoc_Gen, PasDoc_GenHtml, PasDoc_Base, StdCtrls, PasDoc_Types, PasDoc_Languages, PasDoc_GenLatex, PasDoc_Serialize, IniFiles, PasDoc_GenHtmlHelp, PasDoc_Utils, PasDoc_Items; type EInvalidSpellingLanguage = class(Exception); // @abstract(TfrmHelpGenerator is the class of the main form of Help // Generator.) Its published fields are mainly components that are used to // save the project settings. { TfrmHelpGenerator } TfrmHelpGenerator = class(TForm) // Click @name to select a directory that may // have include directories. btnBrowseIncludeDirectory: TButton; // Click @name to select one or more sorce files for the // project. btnBrowseSourceFiles: TButton; // Click @name to generate output ButtonGenerateDocs: TButton; ButtonAspellURL: TButton; ButtonGraphVizURL: TButton; cbCheckSpelling: TCheckBox; cbVizGraphClasses: TCheckBox; cbVizGraphUses: TCheckBox; CheckAutoAbstract: TCheckBox; CheckAutoLink: TCheckBox; CheckStoreRelativePaths: TCheckBox; CheckHandleMacros: TCheckBox; CheckUseTipueSearch: TCheckBox; // @name controls what members (based on visibility) // will be included in generated output. CheckListVisibleMembers: TCheckListBox; CheckWriteUsesList: TCheckBox; clbSorting: TCheckListBox; // @name determines what sort of files will be created comboGenerateFormat: TComboBox; // comboLanguages is used to set the language in which the web page will // be written. Of course, this only affects tha language for the text // generated by the program, not the comments about the program. comboLanguages: TComboBox; comboLatexGraphicsPackage: TComboBox; // @name is used to set the name of the project. edProjectName: TEdit; edTitle: TEdit; Label1: TLabel; Label10: TLabel; Label11: TLabel; Label12: TLabel; Label17: TLabel; Label4: TLabel; LabelHeader: TLabel; LabelFooter: TLabel; LabelImplicitVisibility: TLabel; Label14: TLabel; Label15: TLabel; Label16: TLabel; Label18: TLabel; Label19: TLabel; Label2: TLabel; Label20: TLabel; LabelVisibleMembers: TLabel; Label22: TLabel; Label23: TLabel; Label24: TLabel; Label3: TLabel; Label6: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; lbNavigation: TListBox; memoCommentMarkers: TMemo; memoDefines: TMemo; // @name holds the complete paths of all the source files // in the project. memoFiles: TMemo; memoFooter: TMemo; memoHeader: TMemo; memoHyphenatedWords: TMemo; // The lines in @name are the paths of the files that // may have include files that are part of the project. memoIncludeDirectories: TMemo; // memoMessages displays compiler warnings. See also @link(seVerbosity); memoMessages: TMemo; memoSpellCheckingIgnore: TMemo; MenuAbout: TMenuItem; MenuContextHelp: TMenuItem; MenuEdit: TMenuItem; MenuGenerate: TMenuItem; MenuGenerateRun: TMenuItem; MenuSave: TMenuItem; MenuPreferences: TMenuItem; NotebookMain: TNotebook; PanelLatexHyphenation: TPanel; PanelFooterHidden: TPanel; PanelHeaderHidden: TPanel; pnlEditCommentInstructions: TPanel; PanelMarkers: TPanel; PanelDefinesTop: TPanel; PanelGenerateTop: TPanel; PanelIncludeDirectoriesTop: TPanel; PanelSourceFilesTop: TPanel; PanelSpellCheckingTop1: TPanel; OpenDialog1: TOpenDialog; RadioImplicitVisibility: TRadioGroup; rgCommentMarkers: TRadioGroup; rgLineBreakQuality: TRadioGroup; SaveDialog1: TSaveDialog; OpenDialog2: TOpenDialog; MainMenu1: TMainMenu; MenuFile: TMenuItem; MenuOpen: TMenuItem; MenuSaveAs: TMenuItem; MenuExit: TMenuItem; MenuNew: TMenuItem; seVerbosity: TSpinEdit; Splitter1: TSplitter; Splitter2: TSplitter; MenuHelp: TMenuItem; tvUnits: TTreeView; edOutPut: TEdit; EditCssFileName: TEdit; EditIntroductionFileName: TEdit; PasDoc1: TPasDoc; EditConclusionFileName: TEdit; HTMLDocGenerator: THTMLDocGenerator; HTMLHelpDocGenerator: THTMLHelpDocGenerator; TexDocGenerator: TTexDocGenerator; ButtonIntroFileName: TButton; ButtonConclusionFileName: TButton; ButtonCssFileName: TButton; ButtonOutPutPathName: TButton; OpenDialog3: TOpenDialog; seComment: TMemo; PanelLeft: TPanel; PanelLeftTop: TPanel; ButtonGenerate: TButton; PanelSort: TPanel; PanelSpellCheckingBottom: TPanel; PanelGenerateBottom: TPanel; PanelDisplayCommentsMid: TPanel; PanelDisplayCommentsBottom: TPanel; procedure ButtonURLClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure MenuContextHelpClick(Sender: TObject); procedure MenuGenerateRunClick(Sender: TObject); procedure MenuPreferencesClick(Sender: TObject); procedure MenuSaveClick(Sender: TObject); procedure SomethingChanged(Sender: TObject); procedure MenuAboutClick(Sender: TObject); procedure PasDoc1Warning(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); procedure btnBrowseSourceFilesClick(Sender: TObject); procedure cbCheckSpellingChange(Sender: TObject); procedure CheckListVisibleMembersClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ButtonGenerateDocsClick(Sender: TObject); procedure comboLanguagesChange(Sender: TObject); procedure btnBrowseIncludeDirectoryClick(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure MenuSaveAsClick(Sender: TObject); procedure Exit1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure MenuNewClick(Sender: TObject); procedure comboGenerateFormatChange(Sender: TObject); procedure lbNavigationClick(Sender: TObject); procedure rgCommentMarkersClick(Sender: TObject); // @name displays the comment associated with the selected node of // @link(tvUnits) in @link(seComment). procedure tvUnitsClick(Sender: TObject); procedure LocationsButtonsClick(Sender: TObject); private function GetCheckListVisibleMembersValue: TVisibilities; procedure SetCheckListVisibleMembersValue(const AValue: TVisibilities); private pageHeadFoot: TPage; pageLatexOptions: TPage; pageGenerate: TPage; FChanged: boolean; FSettingsFileName: string; MisspelledWords: TStringList; InsideCreateWnd: boolean; { If Changed then this offers user the chance to save the project. Returns @false when user chose to Cancel the whole operation (not only file saving, but also the parent operation -- you should always check the result of this function and cancel anything further if result is false). } function SaveChanges: boolean; procedure SetChanged(const AValue: boolean); procedure SetDefaults; procedure SetSettingsFileName(const AValue: string); procedure UpdateCaption; function LanguageIdToString(const LanguageID: TLanguageID): string; procedure CheckIfSpellCheckingAvailable; procedure FillNavigationListBox; procedure SetOutputDirectory(const FileName: string); // @name fills @link(tvUnits) with a heirarchical representation of the // TPasItems in PasDoc1. procedure FillTreeView; procedure PasDocMessages(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); procedure LoadSettings; { This property allows to get and set all CheckListVisibleMembers.Checked[] values as a simple TVisibilities type. } property CheckListVisibleMembersValue: TVisibilities read GetCheckListVisibleMembersValue write SetCheckListVisibleMembersValue; { Saves current settings to FileName. Additionally may also do some other things commonly done at saving time: if SetSettingsFileName then sets SettingsFileName property to FileName. if ClearChanged then sets Changed to false. } procedure SaveSettingsToFile(const FileName: string; SetSettingsFileName, ClearChanged: boolean); protected procedure CreateWnd; override; public DefaultDirectives: TStringList; // @name is @true when the user has changed the project settings. // Otherwise it is @false. property SChanged: boolean read FChanged write SetChanged; { This is the settings filename (.pds file) that is currently opened. You can look at pasdoc_gui as a "program to edit pds files". It is '' if current settings are not associated with any filename (because user did not opened any pds file, or he chose "New" menu item). } property SettingsFileName: string read FSettingsFileName write SetSettingsFileName; { If SettingsFileName <> '', this returns ExtractFileName(SettingsFileName), else it returns 'Unsaved PasDoc settings'. This is good when you want to nicely present the value of SettingsFileName to the user. This follows GNOME HIG standard for window caption. } function SettingsFileNameNice: string; end; var // @name is the main form of Help Generator frmHelpGenerator: TfrmHelpGenerator; implementation uses PasDoc_SortSettings, frmAboutUnit, HelpProcessor, WWWBrowserRunnerDM, PreferencesFrm, PasDocGuiSettings; procedure TfrmHelpGenerator.PasDoc1Warning(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); const MisText = 'Word misspelled "'; var MisspelledWord: string; begin memoMessages.Lines.Add(AMessage); if Pos(MisText, AMessage) =1 then begin MisspelledWord := Copy(AMessage, Length(MisText)+1, MAXINT); SetLength(MisspelledWord, Length(MisspelledWord) -1); MisspelledWords.Add(MisspelledWord) end; end; procedure TfrmHelpGenerator.MenuAboutClick(Sender: TObject); begin frmAbout.ShowModal; end; procedure TfrmHelpGenerator.SetOutputDirectory(const FileName: string); begin edOutput.Text := ExtractFileDir(FileName) + PathDelim + 'PasDoc'; end; procedure TfrmHelpGenerator.SomethingChanged(Sender: TObject); begin { Some components (in Lazarus 0.9.10, this concerns at least TMemo with GTK 1 interface) generate some OnChange event when creating their widget (yes, I made sure: it doesn't happen when reading their properties.) This is not good, because when we open pasdoc_gui, the default project should be left with Changed = false. Checking ComponentState and ControlState to safeguard against this is not possible. I'm using InsideCreateWnd to safeguard against this. } if InsideCreateWnd then Exit; SChanged := true; if (memoFiles.Lines.Count > 0) and (edOutput.Text = '') then begin SetOutputDirectory(memoFiles.Lines[0]); end; end; procedure TfrmHelpGenerator.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_F1 then begin MenuContextHelpClick(ActiveControl); end; end; procedure TfrmHelpGenerator.ButtonURLClick(Sender: TObject); begin WWWBrowserRunner.RunBrowser((Sender as TButton).Caption); end; procedure TfrmHelpGenerator.FormDestroy(Sender: TObject); begin DefaultDirectives.Free; MisspelledWords.Free; end; procedure TfrmHelpGenerator.btnBrowseSourceFilesClick(Sender: TObject); var Directory: string; FileIndex: integer; Files: TStringList; begin if OpenDialog1.Execute then begin Files := TStringList.Create; try if edOutput.Text = '' then begin SetOutputDirectory(OpenDialog1.FileName); end; Files.Sorted := True; Files.Duplicates := dupIgnore; Files.AddStrings(memoFiles.Lines); Files.AddStrings(OpenDialog1.Files); memoFiles.Lines := Files; for FileIndex := 0 to OpenDialog1.Files.Count - 1 do begin Directory := ExtractFileDir(OpenDialog1.Files[FileIndex]); if memoIncludeDirectories.Lines.IndexOf(Directory) < 0 then begin memoIncludeDirectories.Lines.Add(Directory); end; end; finally Files.Free; end; end; end; procedure TfrmHelpGenerator.CheckIfSpellCheckingAvailable; var CheckIfSpellCheckingAvailable: boolean; begin if not cbCheckSpelling.Enabled or not cbCheckSpelling.Checked then begin Exit; end; CheckIfSpellCheckingAvailable := comboGenerateFormat.ItemIndex in [0,1]; if CheckIfSpellCheckingAvailable then begin try LanguageIdToString(TLanguageID(comboLanguages.ItemIndex)); except on E: EInvalidSpellingLanguage do begin //CheckIfSpellCheckingAvailable := False; Beep; MessageDlg(E.Message, Dialogs.mtError, [mbOK], 0); end; end; end; end; procedure TfrmHelpGenerator.FillNavigationListBox; var Index: integer; page: TPage; begin { Under GTK interface, lbNavigation.OnClick event may occur when we change lbNavigation.Items. Our lbNavigationClick is not ready to handle this, so we turn him off. } lbNavigation.OnClick := nil; try lbNavigation.Items.Clear; for Index := 0 to NotebookMain.Pages.Count -1 do begin page := NotebookMain.Pages.Objects[Index] as TPage; if page.Tag = 1 then begin lbNavigation.Items.AddObject(page.Caption, page); end; end; finally lbNavigation.OnClick := lbNavigationClick; end; end; procedure TfrmHelpGenerator.cbCheckSpellingChange(Sender: TObject); begin SChanged := True; if cbCheckSpelling.Checked then begin CheckIfSpellCheckingAvailable; end; end; procedure TfrmHelpGenerator.CheckListVisibleMembersClick(Sender: TObject); var NewValue: TVisibilities; begin NewValue := CheckListVisibleMembersValue; if PasDoc1.ShowVisibilities <> NewValue then begin SChanged := True; PasDoc1.ShowVisibilities := NewValue; end; end; procedure TfrmHelpGenerator.SetDefaults; var SortIndex: TSortSetting; begin CheckListVisibleMembersValue := DefaultVisibilities; RadioImplicitVisibility.ItemIndex := 0; comboLanguages.ItemIndex := Ord(lgEnglish); comboLanguagesChange(nil); comboGenerateFormat.ItemIndex := 0; comboGenerateFormatChange(nil); edTitle.Text := ''; edProjectName.Text := ''; edOutput.Text := ''; seVerbosity.Value := 2; comboGenerateFormat.ItemIndex := 0; memoFiles.Clear; memoIncludeDirectories.Clear; memoMessages.Clear; memoCommentMarkers.Clear; rgCommentMarkers.ItemIndex := 1; memoDefines.Lines.Assign(DefaultDirectives); EditCssFileName.Text := ''; EditIntroductionFileName.Text := ''; EditConclusionFileName.Text := ''; CheckWriteUsesList.Checked := false; CheckAutoAbstract.Checked := false; CheckAutoLink.Checked := false; CheckHandleMacros.Checked := false; CheckUseTipueSearch.Checked := false; for SortIndex := Low(TSortSetting) to High(TSortSetting) do clbSorting.Checked[Ord(SortIndex)] := false; CheckStoreRelativePaths.Checked := true; SChanged := False; end; procedure TfrmHelpGenerator.UpdateCaption; var NewCaption: string; begin { Caption value follows GNOME HIG 2.0 standard } NewCaption := ''; if SChanged then NewCaption := NewCaption + '*'; NewCaption := NewCaption + SettingsFileNameNice; NewCaption := NewCaption + ' - PasDoc GUI'; Caption := NewCaption; end; function TfrmHelpGenerator.LanguageIdToString( const LanguageID: TLanguageID): string; begin try result := 'en'; case LanguageID of {$IFDEF STRING_UNICODE} lgBosnian: result := 'bs'; lgBrazilian: result := 'pt'; // Portuguese used for brazilian. lgCatalan: result := 'ca'; lgChinese: begin if cbCheckSpelling.Checked then raise EInvalidSpellingLanguage.Create( 'Sorry, that language is not supported for spell checking'); result := 'zh'; end; lgDanish: result := 'da'; lgDutch: result := 'nl'; lgEnglish: result := 'en'; lgFrench: result := 'fr'; lgGerman: result := 'de'; lgIndonesian: result := 'id'; lgItalian: result := 'it'; lgJavanese: result := 'jv'; lgPolish: result := 'pl'; lgRussian: result := 'ru'; lgSlovak: result := 'sk'; lgSpanish: result := 'es'; lgSwedish: result := 'sv'; lgHungarian: result := 'hu'; {$ELSE} lgBosnian: result := 'bs'; lgBrazilian_1252: result := 'pt'; // Portuguese used for brazilian. lgBrazilian_utf8: result := 'pt'; lgCatalan: result := 'ca'; lgDanish: result := 'da'; lgDutch: result := 'nl'; lgEnglish: result := 'en'; lgFrench_ISO_8859_15: result := 'fr'; lgFrench_UTF_8: result := 'fr'; lgGerman: result := 'de'; lgIndonesian: result := 'id'; lgItalian: result := 'it'; lgJavanese: result := 'jv'; lgPolish_CP1250: result := 'pl'; lgPolish_ISO_8859_2: result := 'pl'; lgRussian_1251: result := 'ru'; lgRussian_866: result := 'ru'; lgRussian_koi8: result := 'ru'; lgSlovak: result := 'sk'; lgSpanish: result := 'es'; lgSwedish: result := 'sv'; lgHungarian_1250: result := 'hu'; {$ENDIF} else raise EInvalidSpellingLanguage.Create( 'Sorry, that language is not supported for spell checking'); end; except on EInvalidSpellingLanguage do begin cbCheckSpelling.Checked := False; raise; end; end; end; procedure TfrmHelpGenerator.SetChanged(const AValue: boolean); begin if FChanged = AValue then Exit; FChanged := AValue; UpdateCaption; end; procedure TfrmHelpGenerator.SetSettingsFileName(const AValue: string); begin FSettingsFileName := AValue; UpdateCaption; end; procedure TfrmHelpGenerator.FormCreate(Sender: TObject); var LanguageIndex: TLanguageID; Index: integer; Vis: TVisibility; begin {$IFDEF CONDITIONALEXPRESSIONS} {$IF COMPILERVERSION > 17} ReportMemoryLeaksOnShutDown := DebugHook <> 0; {$IFEND} {$ENDIF} MisspelledWords:= TStringList.Create; MisspelledWords.Sorted := True; MisspelledWords.Duplicates := dupIgnore; pageHeadFoot := TPage(NotebookMain.Pages.Objects[NotebookMain.Pages.IndexOf('Header / Footer')]); pageLatexOptions := TPage(NotebookMain.Pages.Objects[NotebookMain.Pages.IndexOf('LaTeX Options')]); pageGenerate := TPage(NotebookMain.Pages.Objects[NotebookMain.Pages.IndexOf('Generate')]); comboLanguages.Items.Capacity := Ord(High(TLanguageID)) - Ord(Low(TLanguageID)) + 1; for LanguageIndex := Low(TLanguageID) to High(TLanguageID) do begin comboLanguages.Items.Add(LanguageDescriptor(LanguageIndex)^.Name); end; Constraints.MinWidth := Width; Constraints.MinHeight := Height; DefaultDirectives := TStringList.Create; { Original HelpGenerator did here DefaultDirectives.Assign(memoDefines.Lines) I like this solution, but unfortunately current Lazarus seems to sometimes "lose" value of TMemo.Lines... So I'm setting these values at runtime. } {$IFDEF FPC} DefaultDirectives.Append('FPC'); {$ENDIF} {$IFDEF UNIX} DefaultDirectives.Append('UNIX'); {$ENDIF} {$IFDEF LINUX} DefaultDirectives.Append('LINUX'); {$ENDIF} {$IFDEF DEBUG} //DefaultDirectives.Append('DEBUG'); {$ENDIF} {$IFDEF VER130} DefaultDirectives.Append('VER130'); {$ENDIF} {$IFDEF VER140} DefaultDirectives.Append('VER140'); {$ENDIF} {$IFDEF VER150} DefaultDirectives.Append('VER150'); {$ENDIF} {$IFDEF VER160} DefaultDirectives.Append('VER160'); {$ENDIF} {$IFDEF VER170} DefaultDirectives.Append('VER170'); {$ENDIF} {$IFDEF VER180} { Delphi 2006 and 2007 } {$IFDEF VER185} { Delphi 2007 } DefaultDirectives.Append('VER185'); {$ELSE} DefaultDirectives.Append('VER185'); {$ENDIF} {$ENDIF} {$IFDEF VER200} { Delphi 2009 } DefaultDirectives.Append('VER200'); {$ENDIF} {$IFDEF VER210} { Delphi 2010 } DefaultDirectives.Append('VER210'); {$ENDIF} {$IFDEF VER220} { Delphi XE } DefaultDirectives.Append('VER220'); {$ENDIF} {$IFDEF UNICODE} { Delphi 2009+ } DefaultDirectives.Append('UNICODE'); {$ENDIF} {$IFDEF MSWINDOWS} DefaultDirectives.Append('MSWINDOWS'); {$ENDIF} {$IFDEF WIN32} DefaultDirectives.Append('WIN32'); {$ENDIF} {$IFDEF CPU386} DefaultDirectives.Append('CPU386'); {$ENDIF} {$IFDEF CONDITIONALEXPRESSIONS} DefaultDirectives.Append('CONDITIONALEXPRESSIONS'); {$ENDIF} CheckListVisibleMembers.Items.Clear; for Vis := Low(TVisibility) to High(TVisibility) do begin CheckListVisibleMembers.Items.Add(string(VisibilityStr[Vis])); end; SetDefaults; { It's too easy to change it at design-time, so we set it at runtime. } NotebookMain.PageIndex := 0; Application.ProcessMessages; {$IFDEF WIN32} // Deal with bug in display of TSpinEdit in Win32. seVerbosity.Constraints.MinWidth := 60; seVerbosity.Width := seVerbosity.Constraints.MinWidth; {$ENDIF} { Workaround for Lazarus bug 0000713, [http://www.lazarus.freepascal.org/mantis/view.php?id=713]: we set menu shortcuts at runtime. (the bug is only for Win32, but we must do this workaround for every target). } //MenuOpen.ShortCut := ShortCut(VK_O, [ssCtrl]); //MenuSave.ShortCut := ShortCut(VK_S, [ssCtrl]); MenuOpen.ShortCut := ShortCut(Ord('O'), [ssCtrl]); MenuSave.ShortCut := ShortCut(Ord('S'), [ssCtrl]); MenuGenerateRun.ShortCut := ShortCut(VK_F9, []); // A Tag of 1 means the page should be visible. for Index := NotebookMain.Pages.Count -1 downto 0 do begin //NotebookMain.CustomPage(Index).Tag := 1; TPage(NotebookMain.Pages.Objects[Index]).Tag := 1; end; comboGenerateFormatChange(nil); FillNavigationListBox; SChanged := False; SettingsFileName := IniFile.ReadString('Main', 'LastProject', ''); if (SettingsFileName <> '') and (AutoLoadLastProject) then LoadSettings; end; procedure TfrmHelpGenerator.FillTreeView; var Lang: TPasDocLanguages; procedure TreeAddCio(const ALLCiosNode: TTreeNode); var LCio: TPasCio; LCios: TPasNestedCios; I, J: Integer; ClassNode: TTreeNode; FieldsNode: TTreeNode; MethodNode: TTreeNode; PropertiesNode: TTreeNode; TypesNode: TTreeNode; PasItem: TPasItem; begin LCios := TPasNestedCios(ALLCiosNode.Data); for J := 0 to LCios.Count - 1 do begin LCio := TPasCio(LCios.PasItemAt[J]); ClassNode := tvUnits.Items.AddChildObject(ALLCiosNode, LCio.Name, LCio); if LCio.Fields.Count > 0 then begin FieldsNode := tvUnits.Items.AddChildObject(ClassNode, Lang.Translation[trFields], LCio.Fields); for I := 0 to LCio.Fields.Count -1 do begin PasItem := LCio.Fields.PasItemAt[I]; tvUnits.Items.AddChildObject(FieldsNode, PasItem.Name, PasItem); end; end; if LCio.Methods.Count > 0 then begin MethodNode := tvUnits.Items.AddChildObject(ClassNode, Lang.Translation[trMethods], LCio.Methods); for I := 0 to LCio.Methods.Count -1 do begin PasItem := LCio.Methods.PasItemAt[I]; tvUnits.Items.AddChildObject(MethodNode, PasItem.Name, PasItem); end; end; if LCio.Properties.Count > 0 then begin PropertiesNode := tvUnits.Items.AddChildObject(ClassNode, Lang.Translation[trProperties], LCio.Properties); for I := 0 to LCio.Properties.Count -1 do begin PasItem := LCio.Properties.PasItemAt[I]; tvUnits.Items.AddChildObject(PropertiesNode, PasItem.Name, PasItem); end; end; if LCio.Types.Count > 0 then begin TypesNode := tvUnits.Items.AddChildObject(ClassNode, Lang.Translation[trInternalTypes], LCio.Types); for I := 0 to LCio.Types.Count -1 do begin PasItem := LCio.Types.PasItemAt[I]; tvUnits.Items.AddChildObject(TypesNode, PasItem.Name, PasItem); end; end; if LCio.Cios.Count > 0 then begin ClassNode := tvUnits.Items.AddChildObject(ClassNode, Lang.Translation[trInternalCR], LCio.CIOs); TreeAddCio(ClassNode); end; end; end; var UnitItem: TPasUnit; AllUnitsNode: TTreeNode; UnitIndex: integer; UnitNode: TTreeNode; AllTypesNode: TTreeNode; AllVariablesNode: TTreeNode; AllCIOs_Node: TTreeNode; AllConstantsNode: TTreeNode; AllProceduresNode: TTreeNode; UsesNode: TTreeNode; PasItemIndex: integer; PasItem: TPasItem; UsesIndex: integer; begin tvUnits.Items.Clear; Lang := TPasDocLanguages.Create; try Lang.Language := TLanguageID(comboLanguages.ItemIndex); if PasDoc1.IntroductionFileName <> '' then begin tvUnits.Items.AddObject(nil, PasDoc1.IntroductionFileName, PasDoc1.Introduction); end; AllUnitsNode := tvUnits.Items.AddObject(nil, Lang.Translation[trUnits], PasDoc1.Units); for UnitIndex := 0 to PasDoc1.Units.Count -1 do begin UnitItem := PasDoc1.Units.UnitAt[UnitIndex]; UnitNode := tvUnits.Items.AddChildObject(AllUnitsNode, UnitItem.SourceFileName, UnitItem); if UnitItem.Types.Count > 0 then begin AllTypesNode := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trTypes], UnitItem.Types); for PasItemIndex := 0 to UnitItem.Types.Count -1 do begin PasItem := UnitItem.Types.PasItemAt[PasItemIndex]; tvUnits.Items.AddChildObject(AllTypesNode, PasItem.Name, PasItem); end; end; if UnitItem.Variables.Count > 0 then begin AllVariablesNode := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trVariables], UnitItem.Variables); for PasItemIndex := 0 to UnitItem.Variables.Count -1 do begin PasItem := UnitItem.Variables.PasItemAt[PasItemIndex]; tvUnits.Items.AddChildObject(AllVariablesNode, PasItem.Name, PasItem); end; end; if UnitItem.CIOs.Count > 0 then begin AllCIOs_Node := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trCio], UnitItem.CIOs); TreeAddCio(AllCIOs_Node); end; if UnitItem.Constants.Count > 0 then begin AllConstantsNode := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trConstants], UnitItem.Constants); for PasItemIndex := 0 to UnitItem.Constants.Count -1 do begin PasItem := UnitItem.Constants.PasItemAt[PasItemIndex]; tvUnits.Items.AddChildObject(AllConstantsNode, PasItem.Name, PasItem); end; end; if UnitItem.FuncsProcs.Count > 0 then begin AllProceduresNode := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trFunctionsAndProcedures], UnitItem.FuncsProcs); for PasItemIndex := 0 to UnitItem.FuncsProcs.Count -1 do begin PasItem := UnitItem.FuncsProcs.PasItemAt[PasItemIndex]; tvUnits.Items.AddChildObject(AllProceduresNode, PasItem.Name, PasItem); end; end; if UnitItem.UsesUnits.Count > 0 then begin UsesNode := tvUnits.Items.AddChildObject(UnitNode, Lang.Translation[trUses], UnitItem.UsesUnits); for UsesIndex := 0 to UnitItem.UsesUnits.Count -1 do begin tvUnits.Items.AddChild(UsesNode, UnitItem.UsesUnits[UsesIndex]); end; end; end; if PasDoc1.ConclusionFileName <> '' then begin tvUnits.Items.AddObject(nil, PasDoc1.ConclusionFileName, PasDoc1.Conclusion); end; finally Lang.Free; end; end; procedure TfrmHelpGenerator.ButtonGenerateDocsClick(Sender: TObject); var Files: TStringList; index: integer; SortIndex: TSortSetting; const VizGraphImageExtension = 'png'; begin if edOutput.Text = '' then begin Beep; MessageDlg('You need to specify the output directory on the "Locations" tab.', Dialogs.mtWarning, [mbOK], 0); Exit; end; Screen.Cursor := crHourGlass; try memoMessages.Clear; Update; case comboGenerateFormat.ItemIndex of 0: PasDoc1.Generator := HtmlDocGenerator; 1: PasDoc1.Generator := HtmlHelpDocGenerator; 2, 3: begin PasDoc1.Generator := TexDocGenerator; TexDocGenerator.Latex2rtf := (comboGenerateFormat.ItemIndex = 3); TexDocGenerator.LatexHead.Clear; if rgLineBreakQuality.ItemIndex = 1 then begin TexDocGenerator.LatexHead.Add('\sloppy'); end; if memoHyphenatedWords.Lines.Count > 0 then begin TexDocGenerator.LatexHead.Add('\hyphenation{'); for Index := 0 to memoHyphenatedWords.Lines.Count -1 do begin TexDocGenerator.LatexHead.Add(memoHyphenatedWords.Lines[Index]); end; TexDocGenerator.LatexHead.Add('}'); end; case comboLatexGraphicsPackage.ItemIndex of 0: // none begin // do nothing end; 1: // PDF begin TexDocGenerator.LatexHead.Add('\usepackage[pdftex]{graphicx}'); end; 2: // DVI begin TexDocGenerator.LatexHead.Add('\usepackage[dvips]{graphicx}'); end; else Assert(False); end; end; else Assert(False); end; PasDoc1.Generator.Language := TLanguageID(comboLanguages.ItemIndex); if PasDoc1.Generator is TGenericHTMLDocGenerator then begin TGenericHTMLDocGenerator(PasDoc1.Generator).Header := memoHeader.Lines.Text; TGenericHTMLDocGenerator(PasDoc1.Generator).Footer := memoFooter.Lines.Text; if EditCssFileName.Text <> '' then TGenericHTMLDocGenerator(PasDoc1.Generator).CSS := FileToString(EditCssFileName.Text) else TGenericHTMLDocGenerator(PasDoc1.Generator).CSS := DefaultPasDocCss; TGenericHTMLDocGenerator(PasDoc1.Generator).UseTipueSearch := CheckUseTipueSearch.Checked; TGenericHTMLDocGenerator(PasDoc1.Generator).AspellLanguage := LanguageIdToString(TLanguageID(comboLanguages.ItemIndex)); TGenericHTMLDocGenerator(PasDoc1.Generator).CheckSpelling := cbCheckSpelling.Checked; if cbCheckSpelling.Checked then begin TGenericHTMLDocGenerator(PasDoc1.Generator).SpellCheckIgnoreWords.Assign(memoSpellCheckingIgnore.Lines); end; end; // Create the output directory if it does not exist. if not SysUtils.DirectoryExists(edOutput.Text) then begin CreateDir(edOutput.Text) end; PasDoc1.Generator.DestinationDirectory := edOutput.Text; PasDoc1.Generator.WriteUsesClause := CheckWriteUsesList.Checked; PasDoc1.Generator.AutoAbstract := CheckAutoAbstract.Checked; PasDoc1.AutoLink := CheckAutoLink.Checked; PasDoc1.HandleMacros := CheckHandleMacros.Checked; PasDoc1.ProjectName := edProjectName.Text; PasDoc1.IntroductionFileName := EditIntroductionFileName.Text; PasDoc1.ConclusionFileName := EditConclusionFileName.Text; { CheckListVisibleMembersClick event *should* already take care of setting PasDoc1.ShowVisibilities. Unfortunately CheckListVisibleMembersClick is not guarenteed to be fired on every change of state of CheckListVisibleMembersValue. See Lazarus bug [http://www.lazarus.freepascal.org/mantis/view.php?id=905]. So sometimes user will click on CheckListVisibleMembers and Changed will not be updated as it should. Below we at least make sure that PasDoc1.ShowVisibilities is always updated. } PasDoc1.ShowVisibilities := CheckListVisibleMembersValue; PasDoc1.ImplicitVisibility := TImplicitVisibility(RadioImplicitVisibility.ItemIndex); Files := TStringList.Create; try Files.AddStrings(memoFiles.Lines); PasDoc1.SourceFileNames.Clear; PasDoc1.AddSourceFileNames(Files); Files.Clear; Files.AddStrings(memoIncludeDirectories.Lines); PasDoc1.IncludeDirectories.Assign(Files); Files.Clear; Files.AddStrings(memoDefines.Lines); PasDoc1.Directives.Assign(Files); finally Files.Free; end; PasDoc1.Verbosity := seVerbosity.Value; case rgCommentMarkers.ItemIndex of 0: begin PasDoc1.CommentMarkers.Clear; PasDoc1.MarkerOptional := True; end; 1: begin PasDoc1.MarkerOptional := True; PasDoc1.CommentMarkers.Assign(memoCommentMarkers.Lines); end; 2: begin PasDoc1.MarkerOptional := False; PasDoc1.CommentMarkers.Assign(memoCommentMarkers.Lines); end; else Assert(False); end; if edTitle.Text = '' then begin PasDoc1.Title := edProjectName.Text; end else begin PasDoc1.Title := edTitle.Text; end; if cbVizGraphClasses.Checked then begin PasDoc1.Generator.OutputGraphVizClassHierarchy := True; PasDoc1.Generator.LinkGraphVizClasses := VizGraphImageExtension; end else begin PasDoc1.Generator.OutputGraphVizClassHierarchy := False; PasDoc1.Generator.LinkGraphVizClasses := ''; end; if cbVizGraphUses.Checked then begin PasDoc1.Generator.OutputGraphVizUses := True; PasDoc1.Generator.LinkGraphVizUses := VizGraphImageExtension; end else begin PasDoc1.Generator.OutputGraphVizUses := False; PasDoc1.Generator.LinkGraphVizUses := ''; end; Assert(Ord(High(TSortSetting)) = clbSorting.Items.Count -1); PasDoc1.SortSettings := []; for SortIndex := Low(TSortSetting) to High(TSortSetting) do begin if clbSorting.Checked[Ord(SortIndex)] then begin PasDoc1.SortSettings := PasDoc1.SortSettings + [SortIndex]; end; end; MisspelledWords.Clear; PasDoc1.OnMessage := PasDocMessages; PasDoc1.Execute; PasDoc1.OnMessage := nil; if MisspelledWords.Count > 0 then begin memoMessages.Lines.Add(''); memoMessages.Lines.Add('Misspelled Words'); memoMessages.Lines.AddStrings(MisspelledWords) end; FillTreeView; if cbVizGraphUses.Checked or cbVizGraphClasses.Checked then begin // To do: actually start dot here. MessageDlg('You will have to run the GraphViz "dot" program to generate ' + 'the images used in your documentation.', Dialogs.mtInformation, [mbOK], 0); end; if PasDoc1.Generator is TGenericHTMLDocGenerator then WWWBrowserRunner.RunBrowser( PasDoc1.Generator.DestinationDirectory + 'index.html'); finally Screen.Cursor := crDefault; end; end; procedure TfrmHelpGenerator.PasDocMessages(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); begin MemoMessages.Lines.Add(AMessage); end; procedure TfrmHelpGenerator.LocationsButtonsClick(Sender: TObject); var LEdit: TEdit; LDirectory: string; begin LEdit := nil; //OpenDialog3.Options := [ofHideReadOnly, ofFileMustExist, ofEnableSizing]; if Sender = ButtonIntroFileName then begin OpenDialog3.DefaultExt := '.html'; OpenDialog3.Filter := 'HTML files *.html|*.html,*.htm|All Files *.*|*.*'; OpenDialog3.Title := 'Select a Introduction HTML File'; LEdit := EditIntroductionFileName; end else if Sender = ButtonConclusionFileName then begin OpenDialog3.DefaultExt := '.html'; OpenDialog3.Filter := 'HTML files *.html|*.html,*.htm|All Files *.*|*.*'; OpenDialog3.Title := 'Select a Conclusion HTML File'; LEdit := EditConclusionFileName; end else if Sender = ButtonCssFileName then begin OpenDialog3.DefaultExt := '.css'; OpenDialog3.Filter := 'Css files *.css|*.css|All Files *.*|*.*'; OpenDialog3.Title := 'Select a Cascade Stylesheet File'; LEdit := EditCssFileName; end else if Sender = ButtonOutPutPathName then begin LDirectory := edOutPut.Text; if SelectDirectory('Select output directory', LDirectory, LDirectory) then edOutPut.Text := LDirectory; end; if Assigned(LEdit) and OpenDialog3.Execute then LEdit.Text := OpenDialog3.FileName; end; procedure TfrmHelpGenerator.comboLanguagesChange(Sender: TObject); begin CheckIfSpellCheckingAvailable; SChanged := True; end; procedure TfrmHelpGenerator.btnBrowseIncludeDirectoryClick(Sender: TObject); var directory: string; begin if memoIncludeDirectories.Lines.Count > 0 then begin directory := memoIncludeDirectories.Lines[ memoIncludeDirectories.Lines.Count - 1]; end else begin directory := ''; end; if SelectDirectory('Select directory to include', '', directory) then begin if memoIncludeDirectories.Lines.IndexOf(directory) < 0 then begin memoIncludeDirectories.Lines.Add(directory); end else begin MessageDlg('The directory you selected, (' + directory + ') is already included.', Dialogs.mtInformation, [mbOK], 0); end; end; end; procedure TfrmHelpGenerator.LoadSettings; var Ini: TIniFile; procedure ReadStrings(const Section: string; S: TStrings); var i: Integer; begin S.Clear; for i := 0 to Ini.ReadInteger(Section, 'Count', 0) - 1 do S.Append(Ini.ReadString(Section, 'Item_' + IntToStr(i), '')); end; { When reading any filename from Ini file, we make sure that it's an absolute filename. This is needed to properly handle the case when user choses "Save As" and stores the same project within a different directory. So it's safest to always keep absolute filenames when project is loaded in pasdoc_gui. Below are some helper wrappers around ExpandFileName that help us with this. } { This returns '' if FileName is '', else returns ExpandFileName(FileName). It's useful because often FileName = '' has special meaning: it means that "given filename was not chosen by user", so calling ExpandFileName is not wanted in this case. } function ExpandNotEmptyFileName(const FileName: string): string; begin if FileName = '' then Result := '' else Result := ExpandFileName(FileName); end; { Call ExpandNotEmptyFileName on each item. } procedure ExpandFileNames(List: TStrings); var I: Integer; begin for I := 0 to List.Count - 1 do List[I] := ExpandNotEmptyFileName(List[I]); end; var i: Integer; SettingsFileNamePath: string; LanguageSyntax: string; LanguageId: TLanguageID; begin if not SaveChanges then Exit; SaveDialog1.FileName := SettingsFileName; { Change current directory now to SettingsFileNamePath, this is needed to make all subsequent ExpandFileName operations work with respect to SettingsFileNamePath. } SettingsFileNamePath := ExtractFilePath(SettingsFileName); if not SetCurrentDir(SettingsFileNamePath) then raise Exception.CreateFmt('Cannot change current directory to "%s"', [SettingsFileNamePath]); Ini := TIniFile.Create(SettingsFileName); try { Default values for ReadXxx() methods here are not so important, don't even try to set them right. *Good* default values are set in SetDefaults method of this class. Here we can assume that values are always present in ini file. Well, OK, in case user will modify settings file by hand we should set here some sensible default values... also in case we will add in the future some new values to this file... so actually we should set here sensible "default values". We can think of them as "good default values for user opening a settings file written by older version of pasdoc_gui program". They need not necessarily be equal to default values set by SetDefaults method, and this is very good, as it may give us additional possibilities. } CheckStoreRelativePaths.Checked := Ini.ReadBool('Main', 'StoreRelativePaths', true); { Compatibility: in version < 0.11.0, we stored only the "id" (just an index to LANGUAGE_ARRAY) of the language. This was very wrong, as the id can change between pasdoc releases (items can get shifted and moved in the LANGUAGE_ARRAY). So now we store language "syntax" code (the same thing as is used for --language command-line option), as this is guaranteed to stay "stable". To do something mildly sensible when opening pds files from older versions, we set language to default (English) when language string is not recognized. } LanguageSyntax := Ini.ReadString('Main', 'Language', LanguageDescriptor(DEFAULT_LANGUAGE)^.Syntax); if not LanguageFromStr(LanguageSyntax, LanguageId) then LanguageId := DEFAULT_LANGUAGE; comboLanguages.ItemIndex := Ord(LanguageId); comboLanguagesChange(nil); edOutput.Text := ExpandNotEmptyFileName( Ini.ReadString('Main', 'OutputDir', '')); comboGenerateFormat.ItemIndex := Ini.ReadInteger('Main', 'GenerateFormat', 0); comboGenerateFormatChange(nil); edProjectName.Text := Ini.ReadString('Main', 'ProjectName', ''); seVerbosity.Value := Ini.ReadInteger('Main', 'Verbosity', 0); Assert(Ord(High(TVisibility)) = CheckListVisibleMembers.Items.Count -1); for i := Ord(Low(TVisibility)) to Ord(High(TVisibility)) do CheckListVisibleMembers.Checked[i] := Ini.ReadBool( 'Main', 'ClassMembers_' + IntToStr(i), true); CheckListVisibleMembersClick(nil); RadioImplicitVisibility.ItemIndex := Ini.ReadInteger('Main', 'ImplicitVisibility', 0); Assert(Ord(High(TSortSetting)) = clbSorting.Items.Count -1); for i := Ord(Low(TSortSetting)) to Ord(High(TSortSetting)) do begin clbSorting.Checked[i] := Ini.ReadBool( 'Main', 'Sorting_' + IntToStr(i), True); end; ReadStrings('Defines', memoDefines.Lines); ReadStrings('Header', memoHeader.Lines); ReadStrings('Footer', memoFooter.Lines); ReadStrings('IncludeDirectories', memoIncludeDirectories.Lines); ExpandFileNames(memoIncludeDirectories.Lines); ReadStrings('Files', memoFiles.Lines); ExpandFileNames(memoFiles.Lines); EditCssFileName.Text := ExpandNotEmptyFileName( Ini.ReadString('Main', 'CssFileName', '')); EditIntroductionFileName.Text := ExpandNotEmptyFileName( Ini.ReadString('Main', 'IntroductionFileName', '')); EditConclusionFileName.Text := ExpandNotEmptyFileName( Ini.ReadString('Main', 'ConclusionFileName', '')); CheckWriteUsesList.Checked := Ini.ReadBool('Main', 'WriteUsesList', false); CheckAutoAbstract.Checked := Ini.ReadBool('Main', 'AutoAbstract', false); CheckAutoLink.Checked := Ini.ReadBool('Main', 'AutoLink', false); CheckHandleMacros.Checked := Ini.ReadBool('Main', 'HandleMacros', true); CheckUseTipueSearch.Checked := Ini.ReadBool('Main', 'UseTipueSearch', false); rgLineBreakQuality.ItemIndex := Ini.ReadInteger('Main', 'LineBreakQuality', 0); ReadStrings('HyphenatedWords', memoHyphenatedWords.Lines); rgCommentMarkers.ItemIndex := Ini.ReadInteger('Main', 'SpecialMarkerTreatment', 1); ReadStrings('SpecialMarkers', memoCommentMarkers.Lines); edTitle.Text := Ini.ReadString('Main', 'Title', ''); cbVizGraphClasses.Checked := Ini.ReadBool('Main', 'VizGraphClasses', false); cbVizGraphUses.Checked := Ini.ReadBool('Main', 'VizGraphUses', false); cbCheckSpelling.Checked := Ini.ReadBool('Main', 'CheckSpelling', false); comboLatexGraphicsPackage.ItemIndex := Ini.ReadInteger('Main', 'LatexGraphicsPackage', 0); ReadStrings('IgnoreWords', memoSpellCheckingIgnore.Lines); finally Ini.Free end; SChanged := False; end; procedure TfrmHelpGenerator.btnOpenClick(Sender: TObject); begin if not SaveChanges then Exit; if OpenDialog2.Execute then begin SettingsFileName := OpenDialog2.FileName; LoadSettings; end; end; procedure TfrmHelpGenerator.SaveSettingsToFile(const FileName: string; SetSettingsFileName, ClearChanged: boolean); var Ini: TIniFile; procedure WriteStrings(const Section: string; S: TStrings); var i: Integer; begin { It's not really necessary for correctness but it's nice to protect user privacy by removing trash data from file (in case previous value of S had larger Count). } Ini.EraseSection(Section); Ini.WriteInteger(Section, 'Count', S.Count); for i := 0 to S.Count - 1 do Ini.WriteString(Section, 'Item_' + IntToStr(i), S[i]); end; { If CheckStoreRelativePaths.Checked and FileNameToCorrect <> '', this returns relative filename (with respect to directory where FileName is stored), else returns just FileNameToCorrect. } function CorrectFileName(const FileNameToCorrect: string): string; begin if CheckStoreRelativePaths.Checked and (FileNameToCorrect <> '') then Result := ExtractRelativepath(FileName, FileNameToCorrect) else Result := FileNameToCorrect; end; { Modified version of WriteStrings that always write CorrectFileName(S[I]) instead of just S[I]. } procedure WriteFileNames(const Section: string; S: TStrings); var i: Integer; begin { It's not really necessary for correctness but it's nice to protect user privacy by removing trash data from file (in case previous value of S had larger Count). } Ini.EraseSection(Section); Ini.WriteInteger(Section, 'Count', S.Count); for i := 0 to S.Count - 1 do Ini.WriteString(Section, 'Item_' + IntToStr(i), CorrectFileName(S[i])); end; var i: Integer; begin Ini := TIniFile.Create(FileName); try Ini.WriteBool('Main', 'StoreRelativePaths', CheckStoreRelativePaths.Checked); Ini.WriteString('Main', 'Language', LanguageDescriptor(TLanguageID(comboLanguages.ItemIndex))^.Syntax); Ini.WriteString('Main', 'OutputDir', CorrectFileName(edOutput.Text)); Ini.WriteInteger('Main', 'GenerateFormat', comboGenerateFormat.ItemIndex); Ini.WriteString('Main', 'ProjectName', edProjectName.Text); Ini.WriteInteger('Main', 'Verbosity', seVerbosity.Value); for i := Ord(Low(TVisibility)) to Ord(High(TVisibility)) do Ini.WriteBool('Main', 'ClassMembers_' + IntToStr(i), CheckListVisibleMembers.Checked[i]); Ini.WriteInteger('Main', 'ImplicitVisibility', RadioImplicitVisibility.ItemIndex); for i := Ord(Low(TSortSetting)) to Ord(High(TSortSetting)) do begin Ini.WriteBool('Main', 'Sorting_' + IntToStr(i), clbSorting.Checked[i]); end; WriteStrings('Defines', memoDefines.Lines); WriteStrings('Header', memoHeader.Lines); WriteStrings('Footer', memoFooter.Lines); WriteFileNames('IncludeDirectories', memoIncludeDirectories.Lines); WriteFileNames('Files', memoFiles.Lines); Ini.WriteString('Main', 'CssFileName', CorrectFileName( EditCssFileName.Text)); Ini.WriteString('Main', 'IntroductionFileName', CorrectFileName( EditIntroductionFileName.Text)); Ini.WriteString('Main', 'ConclusionFileName', CorrectFileName( EditConclusionFileName.Text)); Ini.WriteBool('Main', 'WriteUsesList', CheckWriteUsesList.Checked); Ini.WriteBool('Main', 'AutoAbstract', CheckAutoAbstract.Checked); Ini.WriteBool('Main', 'AutoLink', CheckAutoLink.Checked); Ini.WriteBool('Main', 'HandleMacros', CheckHandleMacros.Checked); Ini.WriteBool('Main', 'UseTipueSearch', CheckUseTipueSearch.Checked); Ini.WriteInteger('Main', 'LineBreakQuality', rgLineBreakQuality.ItemIndex); WriteStrings('HyphenatedWords', memoHyphenatedWords.Lines); Ini.WriteInteger('Main', 'SpecialMarkerTreatment', rgCommentMarkers.ItemIndex); WriteStrings('SpecialMarkers', memoCommentMarkers.Lines); Ini.WriteString('Main', 'Title', edTitle.Text); Ini.WriteBool('Main', 'VizGraphClasses', cbVizGraphClasses.Checked); Ini.WriteBool('Main', 'VizGraphUses', cbVizGraphUses.Checked); Ini.WriteBool('Main', 'CheckSpelling', cbCheckSpelling.Checked); Ini.WriteInteger('Main', 'LatexGraphicsPackage', comboLatexGraphicsPackage.ItemIndex); WriteStrings('IgnoreWords', memoSpellCheckingIgnore.Lines); Ini.UpdateFile; finally Ini.Free end; if SetSettingsFileName then begin SettingsFileName := FileName; IniFile.WriteString('Main', 'LastProject', SettingsFileName); end; if ClearChanged then SChanged := false; end; procedure TfrmHelpGenerator.MenuSaveAsClick(Sender: TObject); begin if SaveDialog1.Execute then SaveSettingsToFile(SaveDialog1.FileName, true, true); end; procedure TfrmHelpGenerator.Exit1Click(Sender: TObject); begin Close; end; function TfrmHelpGenerator.SaveChanges: boolean; var MessageResult: integer; begin Result := true; if SChanged then begin MessageResult := MessageDlg( Format('Project "%s" was modified. ' + 'Do you want to save it now ?', [SettingsFileNameNice]), Dialogs.mtInformation, [mbYes, mbNo, mbCancel], 0); case MessageResult of mrYes: begin MenuSaveClick(MenuSave); end; mrNo: begin // do nothing. end; else Result := false; end; end; end; procedure TfrmHelpGenerator.FormClose(Sender: TObject; var Action: TCloseAction); begin if not SaveChanges then Action := caNone; end; procedure TfrmHelpGenerator.MenuNewClick(Sender: TObject); begin if not SaveChanges then Exit; SetDefaults; SettingsFileName := ''; SChanged := False; end; procedure TfrmHelpGenerator.comboGenerateFormatChange(Sender: TObject); { With WinAPI interface, this is useful to give user indication of Edit.Enabled state. Other WinAPI programs also do this. With other widgetsets, like GTK, this is not needed, Lazarus + GTK already handle such things (e.g. edit boxes have automatically slightly dimmed background when they are disabled). } (* procedure SetColorFromEnabled(Edit: TFileNameEdit); overload; begin {$ifdef WIN32} if Edit.Enabled then Edit.Color := clWindow else Edit.Color := clBtnFace; {$endif} end; *) procedure SetColorFromEnabled(Edit: TEdit); overload; begin {$ifdef WIN32} if Edit.Enabled then Edit.Color := clWindow else Edit.Color := clBtnFace; {$endif} end; begin CheckUseTipueSearch.Enabled := comboGenerateFormat.ItemIndex = 0; PageHeadFoot.Tag := Ord(comboGenerateFormat.ItemIndex in [0,1]); PageLatexOptions.Tag := Ord(comboGenerateFormat.ItemIndex in [2,3]); edProjectName.Enabled := comboGenerateFormat.ItemIndex <> 0; SetColorFromEnabled(edProjectName); EditCssFileName.Enabled := comboGenerateFormat.ItemIndex in [0,1]; SetColorFromEnabled(EditCssFileName); comboLatexGraphicsPackage.Enabled := comboGenerateFormat.ItemIndex in [2,3]; FillNavigationListBox; SChanged := true; end; procedure TfrmHelpGenerator.lbNavigationClick(Sender: TObject); var Page: TPage; begin if lbNavigation.ItemIndex = -1 then Exit; Page := lbNavigation.Items.Objects[lbNavigation.ItemIndex] as TPage; NotebookMain.PageIndex := NotebookMain.Pages.IndexOfObject(Page); end; procedure TfrmHelpGenerator.MenuContextHelpClick(Sender: TObject); var HelpControl: TControl; begin HelpControl := nil; if (Sender is TMenuItem) or (Sender = lbNavigation) then begin HelpControl := TPage(NotebookMain.Pages.Objects[NotebookMain.PageIndex]); GetHelpControl(HelpControl, HelpControl); end else if (Sender is TControl) then begin GetHelpControl(TControl(Sender), HelpControl); end; if HelpControl <> nil then begin Assert(HelpControl.HelpType = htKeyword); WWWBrowserRunner.RunBrowser( WWWHelpServer + HelpControl.HelpKeyword); end; end; procedure TfrmHelpGenerator.MenuGenerateRunClick(Sender: TObject); begin { Switch to "Generate" page } lbNavigation.ItemIndex := lbNavigation.Items.IndexOfObject(pageGenerate); lbNavigationClick(nil); ButtonGenerateDocsClick(nil); end; procedure TfrmHelpGenerator.MenuPreferencesClick(Sender: TObject); begin TPreferences.Execute; end; procedure TfrmHelpGenerator.MenuSaveClick(Sender: TObject); begin if SettingsFileName = '' then MenuSaveAsClick(nil) else SaveSettingsToFile(SettingsFileName, true, true); end; procedure TfrmHelpGenerator.rgCommentMarkersClick(Sender: TObject); begin SChanged := True; memoCommentMarkers.Enabled := (rgCommentMarkers.ItemIndex >= 1); if memoCommentMarkers.Enabled then begin memoCommentMarkers.Color := clWindow; end else begin memoCommentMarkers.Color := clBtnFace; end; end; procedure TfrmHelpGenerator.tvUnitsClick(Sender: TObject); var Item: TBaseItem; begin seComment.Lines.Clear; seComment.Hint := ''; if (tvUnits.Selected <> nil) and (tvUnits.Selected.Data <> nil) then begin if TObject(tvUnits.Selected.Data) is TBaseItem then begin Item := TBaseItem(tvUnits.Selected.Data); seComment.Lines.Text := Item.RawDescription; seComment.Hint := Format( 'Comment in stream "%s", on position %d - %d', [ Item.RawDescriptionInfo.StreamName, Item.RawDescriptionInfo.BeginPosition, Item.RawDescriptionInfo.EndPosition ]); end; end; end; function TfrmHelpGenerator.GetCheckListVisibleMembersValue: TVisibilities; var V: TVisibility; begin Result := []; for V := Low(V) to High(V) do begin if CheckListVisibleMembers.Checked[Ord(V)] then Include(Result, V); end; end; procedure TfrmHelpGenerator.SetCheckListVisibleMembersValue( const AValue: TVisibilities); var V: TVisibility; begin for V := Low(V) to High(V) do CheckListVisibleMembers.Checked[Ord(V)] := V in AValue; end; procedure TfrmHelpGenerator.CreateWnd; begin InsideCreateWnd := true; try inherited; finally InsideCreateWnd := false; end; end; function TfrmHelpGenerator.SettingsFileNameNice: string; begin if SettingsFileName = '' then Result := 'Unsaved PasDoc settings' else Result := ExtractFileName(SettingsFileName); end; end. ������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/pasdoc_gui_manifest.rc�����������������������������������������������������0000600�0001750�0001750�00000000036�13034465544�022434� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1 24 "pasdoc_gui_manifest.xml"��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/frmAboutUnit.pas�����������������������������������������������������������0000600�0001750�0001750�00000004453�13237143042�021225� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 2004-2005 Richard B. Winston, U.S. Geological Survey (USGS) Copyright 2005 Michalis Kamburelis This file is part of pasdoc_gui. pasdoc_gui is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. pasdoc_gui is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with pasdoc_gui; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA } { @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Michalis Kamburelis) } unit frmAboutUnit; interface uses SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons; type { TfrmAbout } TfrmAbout = class(TForm) ButtonPasDocURL: TButton; LabelTitle: TLabel; MemoInformation: TMemo; ButtonClose: TButton; procedure ButtonPasDocURLClick(Sender: TObject); procedure frmAboutCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmAbout: TfrmAbout; implementation {$R *.dfm} uses PasDoc_Types, PasDoc_Base, WWWBrowserRunnerDM, PasDoc_Versions; { TfrmAbout } procedure TfrmAbout.frmAboutCreate(Sender: TObject); begin MemoInformation.Lines.Text := 'Original version Richard B. Winston (rbwinst@usgs.gov), ' + 'U.S. Geological Survey (USGS)' + LineEnding + LineEnding + 'Modifications copyright 2005 Michalis Kamburelis' + LineEnding + LineEnding + 'Additional modifications by Richard B. Winston' + LineEnding + LineEnding + 'pasdoc_gui and PasDoc component are free software. ' + 'You are welcome to further modify and redistribute them on terms ' + 'of GNU General Public License.' +LineEnding+ LineEnding+ 'PasDoc version information:' +LineEnding+ PASDOC_FULL_INFO; end; procedure TfrmAbout.ButtonPasDocURLClick(Sender: TObject); begin WWWBrowserRunner.RunBrowser((Sender as TButton).Caption); end; end. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/pasdoc_gui.dpr�������������������������������������������������������������0000600�0001750�0001750�00000001173�13237143042�020721� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������program pasdoc_gui; {$R 'pasdoc_gui_manifest.res' 'pasdoc_gui_manifest.rc'} uses Forms, frmAboutUnit in 'frmAboutUnit.pas' {frmAbout}, frmhelpgeneratorunit in 'frmhelpgeneratorunit.pas' {frmHelpGenerator}, WWWBrowserRunnerDM in 'WWWBrowserRunnerDM.pas' {WWWBrowserRunner}, PasDocGuiSettings in 'PasDocGuiSettings.pas', preferencesfrm in 'preferencesfrm.pas' {preferencesfrm}; {$R *.res} begin Application.Initialize; Application.CreateForm(TfrmHelpGenerator, frmHelpGenerator); Application.CreateForm(TfrmAbout, frmAbout); Application.CreateForm(TWWWBrowserRunner, WWWBrowserRunner); Application.Run; end. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/preferencesfrm.dfm���������������������������������������������������������0000644�0001750�0001750�00000003020�13215221657�021601� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������object Preferences: TPreferences Left = 287 Top = 206 Width = 432 Height = 226 Caption = 'Preferences' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = True Position = poMainFormCenter DesignSize = ( 424 192) PixelsPerInch = 96 TextHeight = 13 object LabelWWWHelpServer: TLabel Left = 8 Top = 104 Width = 151 Height = 13 Caption = '&URL of server with help pages :' Color = clBtnFace FocusControl = EditWWWHelpServer ParentColor = False end object EditWWWHelpServer: TEdit Left = 8 Top = 120 Width = 392 Height = 21 TabOrder = 1 Text = 'EditWWWHelpServer' end object BtnOK: TButton Left = 244 Top = 157 Width = 75 Height = 25 Anchors = [akRight, akBottom] Caption = '&OK' Default = True ModalResult = 1 TabOrder = 3 end object BtnCancel: TButton Left = 332 Top = 156 Width = 75 Height = 25 Anchors = [akRight, akBottom] Cancel = True Caption = '&Cancel' ModalResult = 2 TabOrder = 4 end object BtnResetDefaults: TButton Left = 8 Top = 156 Width = 139 Height = 25 Anchors = [akLeft, akBottom] Caption = '&Reset to defaults' TabOrder = 2 OnClick = BtnResetDefaultsClick end object cbLoadLastProject: TCheckBox Left = 8 Top = 74 Width = 345 Height = 17 Caption = 'Auto load last project' TabOrder = 5 end end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/preferencesfrm.pas���������������������������������������������������������0000644�0001750�0001750�00000004154�13237143042�021622� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "pasdoc_gui". "pasdoc_gui" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "pasdoc_gui" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "pasdoc_gui"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { This unit implements TPreferences form (run by TPreferences.Execute). @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>)} unit PreferencesFrm; interface {$R *.dfm} uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons; type { TPreferences } TPreferences = class(TForm) BtnOK: TButton; BtnCancel: TButton; BtnResetDefaults: TButton; EditWWWHelpServer: TEdit; LabelWWWHelpServer: TLabel; cbLoadLastProject: TCheckBox; procedure BtnResetDefaultsClick(Sender: TObject); private { private declarations } public class procedure Execute; end; implementation uses WWWBrowserRunnerDM, PasDocGuiSettings; procedure TPreferences.BtnResetDefaultsClick(Sender: TObject); begin EditWWWHelpServer.Text := DefaultWWWHelpServer; cbLoadLastProject.Checked := TRUE; end; class procedure TPreferences.Execute; var F: TPreferences; begin F := TPreferences.Create(nil); try F.EditWWWHelpServer.Text := WWWHelpServer; F.cbLoadLastProject.Checked := AutoLoadLastProject; if F.ShowModal = mrOK then begin WWWHelpServer := F.EditWWWHelpServer.Text; AutoLoadLastProject := F.cbLoadLastProject.Checked; end; finally F.Free; end; end; end. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/frmhelpgeneratorunit.dfm���������������������������������������������������0000600�0001750�0001750�00000134236�13034465544�023051� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������object frmHelpGenerator: TfrmHelpGenerator Left = 691 Top = 277 Width = 674 Height = 470 HelpType = htKeyword HelpKeyword = 'PasDocGui' Caption = 'pasdoc gui' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Shell Dlg 2' Font.Style = [] KeyPreview = True Menu = MainMenu1 OldCreateOrder = True Position = poScreenCenter ShowHint = True OnClose = FormClose OnCreate = FormCreate OnDestroy = FormDestroy OnKeyDown = FormKeyDown PixelsPerInch = 96 TextHeight = 13 object PanelLeft: TPanel Left = 0 Top = 0 Width = 165 Height = 416 Align = alLeft BevelOuter = bvNone Caption = 'PanelLeft' TabOrder = 0 object lbNavigation: TListBox Left = 0 Top = 38 Width = 165 Height = 378 Align = alClient ItemHeight = 13 TabOrder = 0 OnClick = lbNavigationClick end object PanelLeftTop: TPanel Left = 0 Top = 0 Width = 165 Height = 38 Align = alTop BevelOuter = bvNone TabOrder = 1 object ButtonGenerate: TButton Left = 10 Top = 7 Width = 147 Height = 25 Caption = 'Generate' TabOrder = 0 OnClick = MenuGenerateRunClick end end end object NotebookMain: TNotebook Left = 165 Top = 0 Width = 501 Height = 416 Align = alClient PageIndex = 7 TabOrder = 1 object pageOptions: TPage Left = 0 Top = 0 Caption = 'Options' DesignSize = ( 501 416) object Label2: TLabel Left = 10 Top = 14 Width = 27 Height = 13 HelpType = htKeyword Caption = 'Title :' Color = clBtnFace FocusControl = edTitle ParentColor = False end object Label6: TLabel Left = 10 Top = 102 Width = 68 Height = 13 HelpType = htKeyword Caption = 'Output Type :' Color = clBtnFace FocusControl = comboGenerateFormat ParentColor = False end object Label11: TLabel Left = 10 Top = 58 Width = 71 Height = 13 HelpType = htKeyword Caption = 'Project Name :' Color = clBtnFace FocusControl = edProjectName ParentColor = False end object Label19: TLabel Left = 10 Top = 146 Width = 218 Height = 13 HelpType = htKeyword Caption = 'Language used in generated documentation :' Color = clBtnFace FocusControl = comboLanguages ParentColor = False end object Label3: TLabel Left = 10 Top = 194 Width = 375 Height = 13 HelpType = htKeyword Caption = 'Output directory (This is the directory where the web pages will' + ' be created.) :' Color = clBtnFace ParentColor = False end object CheckAutoAbstract: TCheckBox Left = 10 Top = 294 Width = 605 Height = 24 Hint = 'If this is checked, the 1st sentence of each description'#10'will be' + ' treated as the abstract of that description'#10'(unless you overrid' + 'e it by using the @abstract tag).' HelpType = htKeyword HelpKeyword = 'AutoAbstractOption' Caption = 'Automatically deduce @abstract description from the 1st sentence' + ' of description' TabOrder = 8 end object CheckUseTipueSearch: TCheckBox Left = 10 Top = 270 Width = 316 Height = 24 Hint = 'Check this to get working "Search" button in your HTML documenta' + 'tion.' HelpType = htKeyword HelpKeyword = 'UseTipueSearchOption' Caption = 'Use tipue search engine in HTML output' TabOrder = 7 end object edTitle: TEdit Left = 10 Top = 30 Width = 177 Height = 21 Hint = 'Title for your documentation. In HTML output, this appears in th' + 'e web browser caption.' HelpType = htKeyword HelpKeyword = 'DocumentationTitle' Anchors = [akLeft, akTop, akRight] TabOrder = 0 OnChange = SomethingChanged end object comboGenerateFormat: TComboBox Left = 10 Top = 116 Width = 176 Height = 21 HelpType = htKeyword Style = csDropDownList Anchors = [akLeft, akTop, akRight] ItemHeight = 13 TabOrder = 2 OnChange = comboGenerateFormatChange Items.Strings = ( 'HTML' 'HTML Help Workshop' 'LaTeX' 'LaTeX for latex2rtf') end object edOutput: TEdit Left = 10 Top = 211 Width = 436 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 4 OnChange = SomethingChanged end object ButtonOutPutPathName: TButton Left = 451 Top = 211 Width = 21 Height = 21 Anchors = [akTop, akRight] Caption = '..' TabOrder = 5 OnClick = LocationsButtonsClick end object edProjectName: TEdit Left = 10 Top = 74 Width = 176 Height = 21 Hint = 'The project name is used to specify the main part of '#10'the output' + ' file name for HtmlHelp or LaTeX output.' HelpType = htKeyword HelpKeyword = 'NameOption' Anchors = [akLeft, akTop, akRight] TabOrder = 1 OnChange = SomethingChanged end object comboLanguages: TComboBox Left = 10 Top = 162 Width = 237 Height = 21 HelpType = htKeyword HelpKeyword = 'OutputLanguage' Style = csDropDownList Anchors = [akLeft, akTop, akRight] ItemHeight = 13 TabOrder = 3 OnChange = comboLanguagesChange end object CheckAutoLink: TCheckBox Left = 10 Top = 318 Width = 520 Height = 24 HelpType = htKeyword HelpKeyword = 'AutoLinkOption' Caption = 'Automatically turn identifiers into links, without the need for ' + '@link tag' TabOrder = 9 end object CheckHandleMacros: TCheckBox Left = 10 Top = 342 Width = 349 Height = 24 HelpType = htKeyword HelpKeyword = 'NoMacroOption' Caption = 'Recognize FPC macros syntax when parsing' Checked = True State = cbChecked TabOrder = 10 end object CheckStoreRelativePaths: TCheckBox Left = 10 Top = 374 Width = 294 Height = 24 HelpType = htKeyword HelpKeyword = 'PasDocGui/StoreRelativePaths' Caption = 'Store only relative paths in project file' Checked = True State = cbChecked TabOrder = 11 end object CheckWriteUsesList: TCheckBox Left = 10 Top = 246 Width = 167 Height = 24 HelpType = htKeyword HelpKeyword = 'WriteUsesList' Caption = 'Show units uses list' TabOrder = 6 end end object pageSourceFiles: TPage Left = 0 Top = 0 Caption = 'Source Files' object PanelSourceFilesTop: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 DesignSize = ( 501 416) object Label8: TLabel Left = 10 Top = 10 Width = 481 Height = 39 HelpType = htKeyword Align = alTop Caption = 'Add the filenames of source files you wish to include in your pr' + 'oject. The directories for each file will be automatically added' + ' to the "Include" directories if you use the "Browse" button to ' + 'add the source files.' Color = clBtnFace ParentColor = False WordWrap = True end object btnBrowseSourceFiles: TButton Left = 10 Top = 54 Width = 481 Height = 25 Anchors = [akLeft, akTop, akRight] Caption = 'Browse' TabOrder = 0 OnClick = btnBrowseSourceFilesClick end object memoFiles: TMemo Left = 10 Top = 86 Width = 481 Height = 320 HelpType = htKeyword Align = alBottom Anchors = [akLeft, akTop, akRight, akBottom] ScrollBars = ssBoth TabOrder = 1 WordWrap = False OnChange = SomethingChanged end end end object pageIncludeDirectories: TPage Left = 0 Top = 0 Caption = 'Include Directories' object PanelIncludeDirectoriesTop: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 DesignSize = ( 501 416) object Label9: TLabel Left = 10 Top = 10 Width = 481 Height = 26 HelpType = htKeyword Align = alTop Caption = 'The directories where PasDoc can find include files.'#10'(If you use' + ' $I, $INCLUDE compiler directives.)' Color = clBtnFace ParentColor = False WordWrap = True end object btnBrowseIncludeDirectory: TButton Left = 10 Top = 41 Width = 481 Height = 25 Anchors = [akLeft, akTop, akRight] Caption = 'Browse' TabOrder = 0 OnClick = btnBrowseIncludeDirectoryClick end object memoIncludeDirectories: TMemo Left = 10 Top = 72 Width = 481 Height = 334 HelpType = htKeyword HelpKeyword = 'IncludeInSearchPath' Anchors = [akLeft, akTop, akRight, akBottom] ScrollBars = ssBoth TabOrder = 1 WordWrap = False OnChange = SomethingChanged end end end object pageDefines: TPage Left = 0 Top = 0 Caption = 'Defines' object PanelDefinesTop: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 object Label12: TLabel Left = 10 Top = 10 Width = 472 Height = 26 Align = alTop Caption = 'Put here any symbols that you want to have defined at the start,' + ' just as if they would be defined by $DEFINE at the beginning of' + ' each unit.' Color = clBtnFace ParentColor = False WordWrap = True end object Label4: TLabel Left = 10 Top = 36 Width = 465 Height = 39 Align = alTop Caption = 'Note that your compiler may define some symbols by default (for ' + 'example, "FPC" by FreePascal, "VER150" by Delphi 7, target OS an' + 'd architecture like "UNIX", "MSWINDOWS" etc.) --- you may want t' + 'o define some of these for pasdoc too.' Color = clBtnFace ParentColor = False WordWrap = True end object MemoDefines: TMemo Left = 10 Top = 75 Width = 481 Height = 331 Align = alClient TabOrder = 0 end end end object PageVisibleMembers: TPage Left = 0 Top = 0 Caption = 'Visible members' object LabelImplicitVisibility: TLabel Left = 8 Top = 211 Width = 3 Height = 13 Color = clBtnFace ParentColor = False end object PanelVisibleMembers: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 0 object LabelVisibleMembers: TLabel Left = 10 Top = 10 Width = 481 Height = 13 HelpType = htKeyword Align = alTop Caption = 'Structures (classes etc.) members (properties, methods, events, ' + 'fields) to show in documentation :' Color = clBtnFace FocusControl = CheckListVisibleMembers ParentColor = False WordWrap = True end object RadioImplicitVisibility: TRadioGroup Left = 10 Top = 139 Width = 481 Height = 73 HelpType = htKeyword HelpKeyword = 'ImplicitVisibilityOption' Align = alTop Caption = 'Default visibility of members' ItemIndex = 0 Items.Strings = ( '"Public", unless the class is declared within {$M+} state, then ' + 'it'#39's "published"' 'Always "published"' 'Always "implicit"') TabOrder = 0 OnClick = SomethingChanged end object CheckListVisibleMembers: TCheckListBox Left = 10 Top = 23 Width = 481 Height = 116 HelpType = htKeyword HelpKeyword = 'IncludeByVisibility' Align = alTop ItemHeight = 13 Items.Strings = ( 'Published' 'Public' 'Protected' 'Private' 'Automated' 'Implicit') TabOrder = 1 OnClick = CheckListVisibleMembersClick end end end object TPage Left = 0 Top = 0 Caption = 'Sort' object PanelSort: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 0 object Label1: TLabel Left = 10 Top = 10 Width = 481 Height = 13 HelpType = htKeyword Align = alTop Caption = 'Items to sort alphabetically' Color = clBtnFace FocusControl = clbSorting ParentColor = False end object clbSorting: TCheckListBox Left = 10 Top = 23 Width = 481 Height = 146 Hint = 'Which items will be sorted alphabetically '#10'and which will be dis' + 'played in their declared order.' HelpType = htKeyword HelpKeyword = 'SortOption' Align = alTop ItemHeight = 13 Items.Strings = ( 'structures' 'constants' 'global functions' 'types' 'variables' 'uses-clauses' 'record-fields' 'non-record-fields' 'methods' 'properties') TabOrder = 0 OnClick = SomethingChanged end end end object pageMarkers: TPage Left = 0 Top = 0 Caption = 'Markers' object PanelMarkers: TPanel Left = 0 Top = 0 Width = 501 Height = 416 Align = alClient BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 object Label18: TLabel Left = 10 Top = 97 Width = 481 Height = 13 HelpType = htKeyword Align = alTop Caption = 'Special comment markers' Color = clBtnFace ParentColor = False end object rgCommentMarkers: TRadioGroup Left = 10 Top = 10 Width = 481 Height = 87 HelpType = htKeyword HelpKeyword = 'CommentMarker' Align = alTop Caption = 'Comment marker treatment' ItemIndex = 1 Items.Strings = ( 'Ignore special comment markers' 'Include all comments but remove special comment markers' 'Include only comments with special comment markers') TabOrder = 0 OnClick = rgCommentMarkersClick end object memoCommentMarkers: TMemo Left = 10 Top = 112 Width = 481 Height = 294 HelpType = htKeyword HelpKeyword = 'CommentMarker' Align = alBottom Anchors = [akLeft, akTop, akRight, akBottom] TabOrder = 1 OnChange = SomethingChanged end end end object pageLocations: TPage Left = 0 Top = 0 Caption = 'CustomFiles' DesignSize = ( 501 416) object Label14: TLabel Left = 8 Top = 121 Width = 75 Height = 13 HelpType = htKeyword Caption = 'Conclusion file :' Color = clBtnFace ParentColor = False end object Label15: TLabel Left = 8 Top = 75 Width = 83 Height = 13 HelpType = htKeyword Caption = 'Introduction file :' Color = clBtnFace ParentColor = False end object Label16: TLabel Left = 8 Top = 10 Width = 384 Height = 13 HelpType = htKeyword Caption = 'Use custom CSS file with HTML output (leave empty to use default' + ' pasdoc.css) :' Color = clBtnFace ParentColor = False end object EditCssFileName: TEdit Left = 8 Top = 25 Width = 436 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 0 Text = 'EditCssFileName' OnChange = SomethingChanged end object EditIntroductionFileName: TEdit Left = 8 Top = 90 Width = 436 Height = 21 Hint = 'Optional file used as an introduction to your project.' Anchors = [akLeft, akTop, akRight] TabOrder = 2 Text = 'EditIntroductionFileName' OnChange = SomethingChanged end object EditConclusionFileName: TEdit Left = 8 Top = 136 Width = 436 Height = 21 Hint = 'Optional file used as a conclusion to your project.' Anchors = [akLeft, akTop, akRight] TabOrder = 4 Text = 'EditConclusionFileName' OnChange = SomethingChanged end object ButtonIntroFileName: TButton Left = 449 Top = 90 Width = 21 Height = 21 Anchors = [akTop, akRight] Caption = '..' TabOrder = 3 OnClick = LocationsButtonsClick end object ButtonConclusionFileName: TButton Left = 449 Top = 136 Width = 21 Height = 21 Anchors = [akTop, akRight] Caption = '..' TabOrder = 5 OnClick = LocationsButtonsClick end object ButtonCssFileName: TButton Left = 449 Top = 25 Width = 21 Height = 21 Anchors = [akTop, akRight] Caption = '..' TabOrder = 1 OnClick = LocationsButtonsClick end end object pageHeadFoot: TPage Left = 0 Top = 0 Caption = 'Header / Footer' object Splitter2: TSplitter Left = 0 Top = 179 Width = 501 Height = 9 Cursor = crVSplit Align = alTop end object PanelHeaderHidden: TPanel Left = 0 Top = 0 Width = 501 Height = 179 Align = alTop BevelOuter = bvNone BorderWidth = 10 TabOrder = 0 object LabelHeader: TLabel Left = 10 Top = 10 Width = 275 Height = 13 HelpType = htKeyword Align = alTop Caption = '&Header (This text will appear at the top of the web page)' Color = clBtnFace FocusControl = memoHeader ParentColor = False end object memoHeader: TMemo Left = 10 Top = 23 Width = 481 Height = 146 HelpType = htKeyword HelpKeyword = 'FileAsHeaderOrFooter' Align = alClient TabOrder = 0 WordWrap = False OnChange = SomethingChanged end end object PanelFooterHidden: TPanel Left = 0 Top = 188 Width = 501 Height = 228 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 1 object LabelFooter: TLabel Left = 10 Top = 10 Width = 290 Height = 13 HelpType = htKeyword Align = alTop Caption = '&Footer (This text will appear at the bottom of the web page)' Color = clBtnFace FocusControl = memoFooter ParentColor = False end object memoFooter: TMemo Left = 10 Top = 23 Width = 481 Height = 195 HelpType = htKeyword HelpKeyword = 'FileAsHeaderOrFooter' Align = alClient TabOrder = 0 WordWrap = False OnChange = SomethingChanged end end end object pageLatexOptions: TPage Left = 0 Top = 0 Caption = 'LaTeX Options' object Label24: TLabel Left = 12 Top = 110 Width = 113 Height = 13 Caption = 'LateX graphics package' Color = clBtnFace FocusControl = comboLatexGraphicsPackage ParentColor = False end object rgLineBreakQuality: TRadioGroup Left = 12 Top = 7 Width = 95 Height = 81 HelpType = htKeyword HelpKeyword = 'PasDocGui/LatexLineBreaks' Caption = 'Line Breaks' ItemIndex = 0 Items.Strings = ( 'strict' 'sloppy') TabOrder = 1 OnClick = SomethingChanged end object comboLatexGraphicsPackage: TComboBox Left = 12 Top = 126 Width = 148 Height = 21 Hint = 'If you use graphics in LaTeX, you have to specify '#10'the graphics ' + 'package in the header for the LaTeX file.'#10'This option allows you' + ' to specify which one to use.' Style = csDropDownList Enabled = False ItemHeight = 13 ItemIndex = 0 TabOrder = 0 Text = 'None' OnChange = SomethingChanged Items.Strings = ( 'None' 'PDF' 'DVI') end object PanelLatexHyphenation: TPanel Left = 154 Top = 0 Width = 347 Height = 416 Align = alRight BevelOuter = bvNone BorderWidth = 10 TabOrder = 2 object Label17: TLabel Left = 10 Top = 10 Width = 322 Height = 39 HelpType = htKeyword Align = alTop Caption = 'You can specify how you want words to be hyphenated here. Just e' + 'nter the word (one per line) with hyphens in the correct places.' + ' Only English letters are allowed.' Color = clBtnFace ParentColor = False WordWrap = True end object memoHyphenatedWords: TMemo Left = 10 Top = 49 Width = 327 Height = 357 Align = alClient TabOrder = 0 OnChange = SomethingChanged end end end object pageGraphViz: TPage Left = 0 Top = 0 Caption = 'Graphs' object Label22: TLabel Left = 14 Top = 70 Width = 386 Height = 13 Caption = 'You will have to generate graphs yourself using the dot program ' + 'from GraphViz :' Color = clBtnFace ParentColor = False end object cbVizGraphUses: TCheckBox Left = 10 Top = 34 Width = 243 Height = 24 HelpType = htKeyword HelpKeyword = 'GraphVizSupport' Caption = 'Generate and use Uses graph' TabOrder = 1 end object cbVizGraphClasses: TCheckBox Left = 10 Top = 10 Width = 263 Height = 24 HelpType = htKeyword HelpKeyword = 'GraphVizSupport' Caption = 'Generate and use Classes graph' TabOrder = 0 end object ButtonGraphVizURL: TButton Left = 14 Top = 96 Width = 188 Height = 25 Caption = 'http://www.graphviz.org/' TabOrder = 2 OnClick = ButtonURLClick end end object pageSpellChecking: TPage Left = 0 Top = 0 Caption = 'Spell Checking' object PanelSpellCheckingTop1: TPanel Left = 0 Top = 0 Width = 501 Height = 133 Align = alTop BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 object Label20: TLabel Left = 10 Top = 97 Width = 302 Height = 26 HelpType = htKeyword Align = alBottom Caption = 'Enter words that should be ignored when spell-checking below.'#10'On' + 'e word per line.' Color = clBtnFace ParentColor = False end object Label23: TLabel Left = 10 Top = 40 Width = 343 Height = 13 Caption = 'GNU Aspell must be installed and available on $PATH for spell ch' + 'ecking :' Color = clBtnFace ParentColor = False end object cbCheckSpelling: TCheckBox Left = 10 Top = 10 Width = 131 Height = 24 HelpType = htKeyword HelpKeyword = 'SpellChecking' Caption = 'Check Spelling' TabOrder = 0 end object ButtonAspellURL: TButton Left = 10 Top = 64 Width = 218 Height = 25 Caption = 'http://aspell.sourceforge.net/' TabOrder = 1 OnClick = ButtonURLClick end end object PanelSpellCheckingBottom: TPanel Left = 0 Top = 133 Width = 501 Height = 283 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 1 object memoSpellCheckingIgnore: TMemo Left = 10 Top = 10 Width = 481 Height = 263 HelpType = htKeyword HelpKeyword = 'SpellChecking' Align = alClient TabOrder = 0 WordWrap = False end end end object pageGenerate: TPage Left = 0 Top = 0 Caption = 'Generate' object PanelGenerateTop: TPanel Left = 0 Top = 0 Width = 501 Height = 103 Align = alTop Alignment = taLeftJustify BevelOuter = bvNone BorderWidth = 10 FullRepaint = False TabOrder = 0 DesignSize = ( 501 103) object Label10: TLabel Left = 10 Top = 10 Width = 481 Height = 26 HelpType = htKeyword Align = alTop Caption = 'While generating documentation, messages describing what is happ' + 'ening will appear in the area below.' Color = clBtnFace ParentColor = False WordWrap = True end object Label7: TLabel Left = 80 Top = 49 Width = 134 Height = 13 HelpType = htKeyword Caption = 'Verbosity level (default is 2)' Color = clBtnFace ParentColor = False end object seVerbosity: TSpinEdit Left = 10 Top = 44 Width = 64 Height = 22 Hint = 'The higher the message level, the more messages will be shown.' HelpType = htKeyword MaxValue = 6 MinValue = 0 TabOrder = 0 Value = 2 OnChange = SomethingChanged end object ButtonGenerateDocs: TButton Left = 10 Top = 75 Width = 481 Height = 25 Anchors = [akLeft, akRight] Caption = 'Generate documentation' TabOrder = 1 OnClick = ButtonGenerateDocsClick end end object PanelGenerateBottom: TPanel Left = 0 Top = 103 Width = 501 Height = 313 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 1 object memoMessages: TMemo Left = 10 Top = 10 Width = 481 Height = 293 HelpType = htKeyword Align = alClient ScrollBars = ssBoth TabOrder = 0 end end end object pageEdit: TPage Left = 0 Top = 0 Caption = 'Display Comments' object Splitter1: TSplitter Left = 0 Top = 187 Width = 501 Height = 5 Cursor = crVSplit Align = alTop end object pnlEditCommentInstructions: TPanel Left = 0 Top = 0 Width = 501 Height = 28 Align = alTop BevelOuter = bvNone Caption = 'Click on an item in the tree view to see its comment.' FullRepaint = False TabOrder = 0 end object PanelDisplayCommentsMid: TPanel Left = 0 Top = 28 Width = 501 Height = 159 Align = alTop BevelOuter = bvNone BorderWidth = 10 TabOrder = 1 object tvUnits: TTreeView Left = 10 Top = 10 Width = 481 Height = 139 Align = alClient Indent = 19 TabOrder = 0 OnClick = tvUnitsClick end end object PanelDisplayCommentsBottom: TPanel Left = 0 Top = 192 Width = 501 Height = 224 Align = alClient BevelOuter = bvNone BorderWidth = 10 TabOrder = 2 object seComment: TMemo Left = 10 Top = 10 Width = 481 Height = 204 Align = alClient Lines.Strings = ( '') ScrollBars = ssBoth TabOrder = 0 WordWrap = False end end end end object OpenDialog1: TOpenDialog Filter = 'Delphi source files *.pas|*.pas|Free Pascal source files *.pp|*.' + 'pp|All Pascal source files *.pas, *.pp|*.pas;*.pp|All Files *.*|' + '*.*' FilterIndex = 3 Options = [ofHideReadOnly, ofAllowMultiSelect, ofFileMustExist, ofEnableSizing] Title = 'Open existing file' Top = 528 end object SaveDialog1: TSaveDialog DefaultExt = '.pds' Filter = 'PasDoc GUI Settings (*.pds)|*.pds' FilterIndex = 0 Title = 'Save file as' Left = 96 Top = 528 end object OpenDialog2: TOpenDialog DefaultExt = '.pds' Filter = 'PasDoc GUI Settings (*.pds)|*.pds' FilterIndex = 0 Title = 'Open existing file' Left = 64 Top = 528 end object MainMenu1: TMainMenu Left = 32 Top = 528 object MenuFile: TMenuItem Caption = '&File' object MenuNew: TMenuItem Caption = '&New' OnClick = MenuNewClick end object MenuOpen: TMenuItem Caption = '&Open ...' OnClick = btnOpenClick end object MenuSave: TMenuItem Caption = 'Save' OnClick = MenuSaveClick end object MenuSaveAs: TMenuItem Caption = '&Save as...' OnClick = MenuSaveAsClick end object MenuExit: TMenuItem Caption = '&Exit' OnClick = Exit1Click end end object MenuEdit: TMenuItem Caption = 'Edit' object MenuPreferences: TMenuItem Caption = 'Preferences' OnClick = MenuPreferencesClick end end object MenuGenerate: TMenuItem Caption = 'Generate' object MenuGenerateRun: TMenuItem Caption = 'Generate documentation' OnClick = MenuGenerateRunClick end end object MenuHelp: TMenuItem Caption = '&Help' object MenuContextHelp: TMenuItem Caption = 'Help' OnClick = MenuContextHelpClick end object MenuAbout: TMenuItem Caption = '&About' OnClick = MenuAboutClick end end end object OpenDialog3: TOpenDialog Options = [ofHideReadOnly, ofFileMustExist, ofEnableSizing] Left = 48 Top = 288 end object PasDoc1: TPasDoc ShowVisibilities = [] Left = 48 Top = 100 end object HTMLDocGenerator: THTMLDocGenerator CSS = 'body { font-family: Verdana,Arial; '#13#10' color: black; background-' + 'color: white; '#13#10' font-size: 12px; }'#13#10'body.navigationframe { fon' + 't-family: Verdana,Arial; '#13#10' color: white; background-color: #78' + '7878; '#13#10' font-size: 12px; }'#13#10#13#10'img { border:0px; }'#13#10#13#10'a:link {c' + 'olor:#C91E0C; text-decoration: none; }'#13#10'a:visited {color:#7E5C31' + '; text-decoration: none; }'#13#10'a:hover {text-decoration: underline;' + ' }'#13#10'a:active {text-decoration: underline; }'#13#10#13#10'a.navigation:link' + ' { color: white; text-decoration: none; font-size: 12px;}'#13#10'a.nav' + 'igation:visited { color: white; text-decoration: none; font-size' + ': 12px;}'#13#10'a.navigation:hover { color: white; font-weight: bold; ' + #13#10' text-decoration: none; font-size: 12px; }'#13#10'a.navigation:acti' + 've { color: white; text-decoration: none; font-size: 12px;}'#13#10#13#10'a' + '.bold:link {color:#C91E0C; text-decoration: none; font-weight:bo' + 'ld; }'#13#10'a.bold:visited {color:#7E5C31; text-decoration: none; fon' + 't-weight:bold; }'#13#10'a.bold:hover {text-decoration: underline; font' + '-weight:bold; }'#13#10'a.bold:active {text-decoration: underline; font' + '-weight:bold; }'#13#10#13#10'a.section {color: green; text-decoration: non' + 'e; font-weight: bold; }'#13#10'a.section:hover {color: green; text-dec' + 'oration: underline; font-weight: bold; }'#13#10#13#10'ul.useslist a:link {' + 'color:#C91E0C; text-decoration: none; font-weight:bold; }'#13#10'ul.us' + 'eslist a:visited {color:#7E5C31; text-decoration: none; font-wei' + 'ght:bold; }'#13#10'ul.useslist a:hover {text-decoration: underline; fo' + 'nt-weight:bold; }'#13#10'ul.useslist a:active {text-decoration: underl' + 'ine; font-weight:bold; }'#13#10#13#10'ul.hierarchy { list-style-type:none;' + ' }'#13#10'ul.hierarchylevel { list-style-type:none; }'#13#10#13#10'p.unitlink a:' + 'link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#13 + #10'p.unitlink a:visited {color:#7E5C31; text-decoration: none; fon' + 't-weight:bold; }'#13#10'p.unitlink a:hover {text-decoration: underline' + '; font-weight:bold; }'#13#10'p.unitlink a:active {text-decoration: und' + 'erline; font-weight:bold; }'#13#10#13#10'tr.list { background: #FFBF44; }'#13 + #10'tr.list2 { background: #FFC982; }'#13#10'tr.listheader { background: ' + '#C91E0C; color: white; }'#13#10#13#10'table.wide_list { border-spacing:2px' + '; width:100%; }'#13#10'table.wide_list td { vertical-align:top; paddin' + 'g:4px; }'#13#10#13#10'table.markerlegend { width:auto; }'#13#10'table.markerlege' + 'nd td.legendmarker { text-align:center; }'#13#10#13#10'table.sections { ba' + 'ckground:white; }'#13#10'table.sections td {background:lightgray; }'#13#10#13 + #10'table.summary td.itemcode { width:100%; }'#13#10'table.detail td.item' + 'code { width:100%; }'#13#10#13#10'td.itemname {white-space:nowrap; }'#13#10'td.i' + 'temunit {white-space:nowrap; }'#13#10'td.itemdesc { width:100%; }'#13#10#13#10'd' + 'iv.nodescription { color:red; }'#13#10'dl.parameters dt { color:blue; ' + '}'#13#10#13#10'/* Various browsers have various default styles for <h6>,'#13#10 + ' sometimes ugly for our purposes, so it'#39's best to set things'#13#10 + ' like font-size and font-weight in out pasdoc.css explicitly. ' + '*/'#13#10'h6.description_section { '#13#10' /* font-size 100% means that it' + ' has the same font size as the '#13#10' parent element, i.e. norma' + 'l description text */'#13#10' font-size: 100%;'#13#10' font-weight: bold; ' + #13#10' /* By default browsers usually have some large margin-bottom' + ' and '#13#10' margin-top for <h1-6> tags. In our case, margin-bott' + 'om is'#13#10' unnecessary, we want to visually show that descripti' + 'on_section'#13#10' is closely related to content below. In this si' + 'tuation'#13#10' (where the font size is just as a normal text), sm' + 'aller bottom'#13#10' margin seems to look good. */'#13#10' margin-botto' + 'm: 0em;'#13#10'}'#13#10#13#10'/* Style applied to Pascal code in documentation '#13 + #10' (e.g. produced by @longcode tag) } */'#13#10'span.pascal_string { ' + 'color: #000080; }'#13#10'span.pascal_keyword { font-weight: bolder; }'#13 + #10'span.pascal_comment { color: #000080; font-style: italic; }'#13#10'sp' + 'an.pascal_compiler_comment { color: #008000; }'#13#10'span.pascal_nume' + 'ric { }'#13#10'span.pascal_hex { }'#13#10#13#10'p.hint_directive { color: red; }' + #13#10#13#10'input#search_text { }'#13#10'input#search_submit_button { }'#13#10#13#10'acr' + 'onym.mispelling { background-color: #ffa; }'#13#10#13#10'/* Actually this ' + 'reduces vertical space between *every* paragraph'#13#10' inside list' + ' with @itemSpacing(compact). '#13#10' While we would like to reduce ' + 'this space only for the'#13#10' top of 1st and bottom of last paragr' + 'aph within each list item.'#13#10' But, well, user probably will not' + ' do any paragraph breaks'#13#10' within a list with @itemSpacing(com' + 'pact) anyway, so it'#39's'#13#10' acceptable solution. */'#13#10'ul.compact_sp' + 'acing p { margin-top: 0em; margin-bottom: 0em; }'#13#10'ol.compact_spa' + 'cing p { margin-top: 0em; margin-bottom: 0em; }'#13#10'dl.compact_spac' + 'ing p { margin-top: 0em; margin-bottom: 0em; }'#13#10#13#10'/* Style for t' + 'able created by @table tags:'#13#10' just some thin border.'#13#10' '#13#10' ' + ' This way we have some borders around the cells'#13#10' (so cells ar' + 'e visibly separated), but the border '#13#10' "blends with the backg' + 'round" so it doesn'#39't look too ugly.'#13#10' Hopefully it looks satis' + 'factory in most cases and for most'#13#10' people. '#13#10' '#13#10' We add ' + 'padding for cells, otherwise they look too close.'#13#10' This is no' + 'rmal thing to do when border-collapse is set to'#13#10' collapse (be' + 'cause this eliminates spacing between cells). '#13#10'*/'#13#10'table.table_' + 'tag { border-collapse: collapse; }'#13#10'table.table_tag td { border:' + ' 1pt solid gray; padding: 0.3em; }'#13#10'table.table_tag th { border:' + ' 1pt solid gray; padding: 0.3em; }'#13#10#13#10'table.detail {'#13#10' border: ' + '1pt solid gray;'#13#10' margin-top: 0.3em;'#13#10' margin-bottom: 0.3em;'#13#10 + '}'#13#10 Left = 48 Top = 148 end object TexDocGenerator: TTexDocGenerator Left = 48 Top = 190 end object HTMLHelpDocGenerator: THTMLHelpDocGenerator CSS = 'body { font-family: Verdana,Arial; '#13#10' color: black; background-' + 'color: white; '#13#10' font-size: 12px; }'#13#10'body.navigationframe { fon' + 't-family: Verdana,Arial; '#13#10' color: white; background-color: #78' + '7878; '#13#10' font-size: 12px; }'#13#10#13#10'img { border:0px; }'#13#10#13#10'a:link {c' + 'olor:#C91E0C; text-decoration: none; }'#13#10'a:visited {color:#7E5C31' + '; text-decoration: none; }'#13#10'a:hover {text-decoration: underline;' + ' }'#13#10'a:active {text-decoration: underline; }'#13#10#13#10'a.navigation:link' + ' { color: white; text-decoration: none; font-size: 12px;}'#13#10'a.nav' + 'igation:visited { color: white; text-decoration: none; font-size' + ': 12px;}'#13#10'a.navigation:hover { color: white; font-weight: bold; ' + #13#10' text-decoration: none; font-size: 12px; }'#13#10'a.navigation:acti' + 've { color: white; text-decoration: none; font-size: 12px;}'#13#10#13#10'a' + '.bold:link {color:#C91E0C; text-decoration: none; font-weight:bo' + 'ld; }'#13#10'a.bold:visited {color:#7E5C31; text-decoration: none; fon' + 't-weight:bold; }'#13#10'a.bold:hover {text-decoration: underline; font' + '-weight:bold; }'#13#10'a.bold:active {text-decoration: underline; font' + '-weight:bold; }'#13#10#13#10'a.section {color: green; text-decoration: non' + 'e; font-weight: bold; }'#13#10'a.section:hover {color: green; text-dec' + 'oration: underline; font-weight: bold; }'#13#10#13#10'ul.useslist a:link {' + 'color:#C91E0C; text-decoration: none; font-weight:bold; }'#13#10'ul.us' + 'eslist a:visited {color:#7E5C31; text-decoration: none; font-wei' + 'ght:bold; }'#13#10'ul.useslist a:hover {text-decoration: underline; fo' + 'nt-weight:bold; }'#13#10'ul.useslist a:active {text-decoration: underl' + 'ine; font-weight:bold; }'#13#10#13#10'ul.hierarchy { list-style-type:none;' + ' }'#13#10'ul.hierarchylevel { list-style-type:none; }'#13#10#13#10'p.unitlink a:' + 'link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#13 + #10'p.unitlink a:visited {color:#7E5C31; text-decoration: none; fon' + 't-weight:bold; }'#13#10'p.unitlink a:hover {text-decoration: underline' + '; font-weight:bold; }'#13#10'p.unitlink a:active {text-decoration: und' + 'erline; font-weight:bold; }'#13#10#13#10'tr.list { background: #FFBF44; }'#13 + #10'tr.list2 { background: #FFC982; }'#13#10'tr.listheader { background: ' + '#C91E0C; color: white; }'#13#10#13#10'table.wide_list { border-spacing:2px' + '; width:100%; }'#13#10'table.wide_list td { vertical-align:top; paddin' + 'g:4px; }'#13#10#13#10'table.markerlegend { width:auto; }'#13#10'table.markerlege' + 'nd td.legendmarker { text-align:center; }'#13#10#13#10'table.sections { ba' + 'ckground:white; }'#13#10'table.sections td {background:lightgray; }'#13#10#13 + #10'table.summary td.itemcode { width:100%; }'#13#10'table.detail td.item' + 'code { width:100%; }'#13#10#13#10'td.itemname {white-space:nowrap; }'#13#10'td.i' + 'temunit {white-space:nowrap; }'#13#10'td.itemdesc { width:100%; }'#13#10#13#10'd' + 'iv.nodescription { color:red; }'#13#10'dl.parameters dt { color:blue; ' + '}'#13#10#13#10'/* Various browsers have various default styles for <h6>,'#13#10 + ' sometimes ugly for our purposes, so it'#39's best to set things'#13#10 + ' like font-size and font-weight in out pasdoc.css explicitly. ' + '*/'#13#10'h6.description_section { '#13#10' /* font-size 100% means that it' + ' has the same font size as the '#13#10' parent element, i.e. norma' + 'l description text */'#13#10' font-size: 100%;'#13#10' font-weight: bold; ' + #13#10' /* By default browsers usually have some large margin-bottom' + ' and '#13#10' margin-top for <h1-6> tags. In our case, margin-bott' + 'om is'#13#10' unnecessary, we want to visually show that descripti' + 'on_section'#13#10' is closely related to content below. In this si' + 'tuation'#13#10' (where the font size is just as a normal text), sm' + 'aller bottom'#13#10' margin seems to look good. */'#13#10' margin-botto' + 'm: 0em;'#13#10'}'#13#10#13#10'/* Style applied to Pascal code in documentation '#13 + #10' (e.g. produced by @longcode tag) } */'#13#10'span.pascal_string { ' + 'color: #000080; }'#13#10'span.pascal_keyword { font-weight: bolder; }'#13 + #10'span.pascal_comment { color: #000080; font-style: italic; }'#13#10'sp' + 'an.pascal_compiler_comment { color: #008000; }'#13#10'span.pascal_nume' + 'ric { }'#13#10'span.pascal_hex { }'#13#10#13#10'p.hint_directive { color: red; }' + #13#10#13#10'input#search_text { }'#13#10'input#search_submit_button { }'#13#10#13#10'acr' + 'onym.mispelling { background-color: #ffa; }'#13#10#13#10'/* Actually this ' + 'reduces vertical space between *every* paragraph'#13#10' inside list' + ' with @itemSpacing(compact). '#13#10' While we would like to reduce ' + 'this space only for the'#13#10' top of 1st and bottom of last paragr' + 'aph within each list item.'#13#10' But, well, user probably will not' + ' do any paragraph breaks'#13#10' within a list with @itemSpacing(com' + 'pact) anyway, so it'#39's'#13#10' acceptable solution. */'#13#10'ul.compact_sp' + 'acing p { margin-top: 0em; margin-bottom: 0em; }'#13#10'ol.compact_spa' + 'cing p { margin-top: 0em; margin-bottom: 0em; }'#13#10'dl.compact_spac' + 'ing p { margin-top: 0em; margin-bottom: 0em; }'#13#10#13#10'/* Style for t' + 'able created by @table tags:'#13#10' just some thin border.'#13#10' '#13#10' ' + ' This way we have some borders around the cells'#13#10' (so cells ar' + 'e visibly separated), but the border '#13#10' "blends with the backg' + 'round" so it doesn'#39't look too ugly.'#13#10' Hopefully it looks satis' + 'factory in most cases and for most'#13#10' people. '#13#10' '#13#10' We add ' + 'padding for cells, otherwise they look too close.'#13#10' This is no' + 'rmal thing to do when border-collapse is set to'#13#10' collapse (be' + 'cause this eliminates spacing between cells). '#13#10'*/'#13#10'table.table_' + 'tag { border-collapse: collapse; }'#13#10'table.table_tag td { border:' + ' 1pt solid gray; padding: 0.3em; }'#13#10'table.table_tag th { border:' + ' 1pt solid gray; padding: 0.3em; }'#13#10#13#10'table.detail {'#13#10' border: ' + '1pt solid gray;'#13#10' margin-top: 0.3em;'#13#10' margin-bottom: 0.3em;'#13#10 + '}'#13#10 Left = 48 Top = 242 end end ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/frmAboutUnit.dfm�����������������������������������������������������������0000600�0001750�0001750�00000002603�13034465544�021214� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������object frmAbout: TfrmAbout Left = 167 Top = 62 Caption = 'About' ClientHeight = 347 ClientWidth = 408 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Shell Dlg 2' Font.Style = [] OldCreateOrder = True Position = poMainFormCenter OnCreate = frmAboutCreate DesignSize = ( 408 347) PixelsPerInch = 96 TextHeight = 13 object LabelTitle: TLabel Left = 13 Top = 8 Width = 109 Height = 24 Alignment = taCenter Anchors = [akLeft, akTop, akRight] Caption = 'pasdoc_gui' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -19 Font.Name = 'MS Sans Serif' Font.Style = [fsBold] ParentColor = False ParentFont = False end object MemoInformation: TMemo Left = 13 Top = 38 Width = 387 Height = 270 Anchors = [akLeft, akTop, akRight, akBottom] Color = clBtnFace ReadOnly = True TabOrder = 0 end object ButtonPasDocURL: TButton Left = 13 Top = 314 Width = 225 Height = 25 Anchors = [akLeft, akBottom] Caption = 'http://pasdoc.sourceforge.net/' TabOrder = 1 OnClick = ButtonPasDocURLClick end object ButtonClose: TButton Left = 318 Top = 314 Width = 75 Height = 25 Caption = 'Close' ModalResult = 1 TabOrder = 2 end end �����������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/HelpProcessor.pas����������������������������������������������������������0000600�0001750�0001750�00000006154�13237143042�021376� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ @author(Richard B. Winston <rbwinst@usgs.gov>) The main purpose of @name is to define GetHelpControl which is used to find a control that has help for a control. Contributions to this unit by Richard B. Winston are in the public domain. As of Nov. 2, 2005, this entire unit is by Richard B. Winston. } unit HelpProcessor; interface uses Classes, SysUtils, Controls, StdCtrls, Forms; { @abstract(@name returns @true if it can find a control that has help starting its search with HelpRequestControl. The control that it finds is returned in HasHelpControl.) In its search, the function checks the FocusControl property of TCustomStaticText and TCustomLabel, the Parent property of TControl, and finally Application.MainForm. @name works for both HelpType = htKeyword and HelpType = htContext.} function GetHelpControl(const HelpRequestControl: TControl; out HasHelpControl: TControl): boolean; implementation type TCustomLabelCracker = class(TCustomLabel); function GetHelpControl(const HelpRequestControl: TControl; out HasHelpControl: TControl): boolean; var AControl: TControl; AlreadyTried: TList; begin AControl := HelpRequestControl; HasHelpControl := nil; Result := FALSE; AlreadyTried := TList.Create; try while AControl <> nil do begin // Test if AControl has help. If it does, set HasHelpControl // and exit; case AControl.HelpType of htKeyword: begin if AControl.HelpKeyword <> '' then begin HasHelpControl := AControl; Exit; end; end; htContext: begin if AControl.HelpContext <> 0 then begin HasHelpControl := AControl; Exit; end; end; else Assert(False); end; // AControl does not have help, find the next one to test. { if (AControl is TCustomStaticText) and (TCustomStaticText(AControl).FocusControl <> nil) then begin AControl := TCustomStaticText(AControl).FocusControl; end else } if (AControl is TCustomLabel) and (TCustomLabelCracker(AControl).FocusControl <> nil) then begin AControl := TCustomLabelCracker(AControl).FocusControl; end else if AControl.Parent <> nil then begin AControl := AControl.Parent; end else if (Application <> nil) and (AControl <> Application.MainForm) and (Application.MainForm <> nil) then begin AControl := Application.MainForm; end else begin // nothing left to test so quit. Exit; end; // If the FocusControl of a TCustomStaticText or TCustomLabel // refers back to itself either directly or indirectly the // while loop might never exit. The following prevents that // from happening. if AlreadyTried.IndexOf(AControl) >= 0 then begin Exit; end else begin AlreadyTried.Add(AControl); end; end; finally AlreadyTried.Free; result := HasHelpControl <> nil; end; end; end. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/delphi_gui/pasdoc_gui_manifest.xml����������������������������������������������������0000600�0001750�0001750�00000001172�13034465544�022632� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="PasDoc.delphi_gui" processorArchitecture="x86" version="1.0.0.0" type="win32"/> <description>Windows Shell</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/����������������������������������������������������������������������������0000700�0001750�0001750�00000000000�13237143042�015762� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_StringVector.pas�����������������������������������������������������0000600�0001750�0001750�00000011136�13237143042�022355� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) @author(Michalis Kamburelis) @abstract(String vector based on TStringList.) The string vector is based on TStringList and simply exports a few extra functions - I did this so I didn't have to change so much old code, this has only little additional functionality } unit PasDoc_StringVector; {$I pasdoc_defines.inc} interface uses Classes; type TStringVector = class(TStringList) public { This is the same thing as Items[0] } function FirstName: string; procedure LoadFromTextFileAdd(const AFilename: string); overload; procedure LoadFromTextFileAdd(var ATextFile: TextFile); overload; procedure RemoveAllNamesCI(const AName: string); function ExistsNameCI(const AName: string): boolean; function IsEmpty: boolean; function AddNotExisting(const AString: string): Integer; { Load from a stream using the binary format. The binary format is @unorderedList( @item Count @item(followed by each string, loaded using @link(TSerializable.LoadStringFromStream).) ) Note that you should never use our Text value to load/save this object from/into a stream, like @code(Text := TSerializable.LoadStringFromStream(Stream)). Using and assigning to the Text value breaks when some strings have newlines inside that should be preserved. } procedure LoadFromBinaryStream(Stream: TStream); { Save to a stream, in a format readable by @link(LoadFromBinaryStream). } procedure SaveToBinaryStream(Stream: TStream); end; function NewStringVector: TStringVector; function IsEmpty(const AOV: TStringVector): boolean; overload; implementation uses SysUtils, PasDoc_Serialize; function IsEmpty(const AOV: TStringVector): boolean; begin Result := (not Assigned(AOV)) or (AOV.Count = 0); end; function NewStringVector: TStringVector; begin Result := TStringVector.Create; Result.Duplicates := dupIgnore; end; { TStringVector } function TStringVector.AddNotExisting(const AString: string): integer; begin Result := IndexOf(AString); if Result < 0 then begin Result := Add(AString); end; end; function TStringVector.ExistsNameCI(const AName: string): boolean; var i: Integer; LName: string; begin LName := LowerCase(AName); Result := false; for i := Count - 1 downto 0 do begin if LowerCase(Get(i)) = LName then begin Result := True; break; end; end; end; function TStringVector.FirstName: string; begin if Count > 0 then begin Result := Get(0); end else begin Result := ''; end end; function TStringVector.IsEmpty: boolean; begin Result := Count = 0; end; procedure TStringVector.LoadFromTextFileAdd( const AFilename: string); var LCurrent: string; begin LCurrent := Text; LoadFromFile(AFilename); Add(LCurrent); end; procedure TStringVector.LoadFromTextFileAdd(var ATextFile: TextFile); var S: string; begin while not Eof(ATextFile) do begin Readln(ATextFile, S); S := Trim(S); if S <> '' then Append(S); end; end; procedure TStringVector.RemoveAllNamesCI(const AName: string); var i: Integer; LName: string; begin LName := LowerCase(AName); for i := Count - 1 downto 0 do begin if LowerCase(Get(i)) = LName then begin Delete(i); end; end; end; procedure TStringVector.LoadFromBinaryStream(Stream: TStream); var i, n: Integer; begin Clear; n := TSerializable.LoadIntegerFromStream(Stream); Capacity := n; for i := 0 to n - 1 do Append(TSerializable.LoadStringFromStream(Stream)); end; procedure TStringVector.SaveToBinaryStream(Stream: TStream); var i: Integer; begin TSerializable.SaveIntegerToStream(Count, Stream); for i := 0 to Count - 1 do TSerializable.SaveStringToStream(Strings[i], Stream); end; end. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Gen.pas��������������������������������������������������������������0000600�0001750�0001750�00000377177�13237143042�020461� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(basic doc generator object) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Ivan Montes Velencoso (senbei@teleline.es)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Philippe Jean Dit Bailleul (jdb@abacom.com)) @author(Rodrigo Urubatan Ferreira Jardim (rodrigo@netscape.net)) @author(Grzegorz Skoczylas <gskoczylas@rekord.pl>) @author(Pierre Woestyn <pwoestyn@users.sourceforge.net>) @author(Michalis Kamburelis) @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Ascanio Pressato) @author(Arno Garrels <first name.name@nospamgmx.de>) @created(30 Aug 1998) @name contains the basic documentation generator object @link(TDocGenerator). It is not sufficient by itself but the basis for all generators that produce documentation in a specific format like HTML or LaTex. They override @link(TDocGenerator)'s virtual methods. } unit PasDoc_Gen; {$I pasdoc_defines.inc} interface uses PasDoc_Items, PasDoc_Languages, PasDoc_StringVector, PasDoc_ObjectVector, PasDoc_HierarchyTree, PasDoc_Types, Classes, PasDoc_TagManager, PasDoc_Aspell, PasDoc_StreamUtils, PasDoc_StringPairVector; type { Overview files that pasdoc generates for multiple-document-formats like HTML (see @link(TGenericHTMLDocGenerator)). But not all of them are supposed to be generated by pasdoc, some must be generated by external programs by user, e.g. uses and class diagrams must be made by user using programs such as GraphViz. See type TCreatedOverviewFile for subrange type of TOverviewFile that specifies only overview files that are really supposed to be made by pasdoc. } TOverviewFile = ( ofUnits, ofClassHierarchy, ofCios, ofTypes, ofVariables, ofConstants, ofFunctionsAndProcedures, ofIdentifiers, ofGraphVizUses, ofGraphVizClasses ); TCreatedOverviewFile = Low(TOverviewFile) .. ofIdentifiers; TOverviewFileInfo = record BaseFileName: string; TranslationId: TTranslationId; TranslationHeadlineId: TTranslationId; NoItemsTranslationId: TTranslationId; end; const OverviewFilesInfo: array[TOverviewFile] of TOverviewFileInfo = ( (BaseFileName: 'AllUnits' ; TranslationId: trUnits ; TranslationHeadlineId: trHeadlineUnits ; NoItemsTranslationId: trNone { unused } ; ), (BaseFileName: 'ClassHierarchy'; TranslationId: trClassHierarchy ; TranslationHeadlineId: trClassHierarchy { no headline }; NoItemsTranslationId: trNoCIOs ; ), (BaseFileName: 'AllClasses' ; TranslationId: trCio ; TranslationHeadlineId: trHeadlineCio ; NoItemsTranslationId: trNoCIOs ; ), (BaseFileName: 'AllTypes' ; TranslationId: trTypes ; TranslationHeadlineId: trHeadlineTypes ; NoItemsTranslationId: trNoTypes ; ), (BaseFileName: 'AllVariables' ; TranslationId: trVariables ; TranslationHeadlineId: trHeadlineVariables ; NoItemsTranslationId: trNoVariables ; ), (BaseFileName: 'AllConstants' ; TranslationId: trConstants ; TranslationHeadlineId: trHeadlineConstants ; NoItemsTranslationId: trNoConstants ; ), (BaseFileName: 'AllFunctions' ; TranslationId: trFunctionsAndProcedures; TranslationHeadlineId: trHeadlineFunctionsAndProcedures; NoItemsTranslationId: trNoFunctions ; ), (BaseFileName: 'AllIdentifiers'; TranslationId: trIdentifiers ; TranslationHeadlineId: trHeadlineIdentifiers ; NoItemsTranslationId: trNoIdentifiers ; ), (BaseFileName: 'GVUses' ; TranslationId: trGvUses ; TranslationHeadlineId: trGvUses { no headline } ; NoItemsTranslationId: trNone { unused } ; ), (BaseFileName: 'GVClasses' ; TranslationId: trGvClasses ; TranslationHeadlineId: trGvClasses { no headline } ; NoItemsTranslationId: trNoCIOs { unused }; ) ); { Using High(TCreatedOverviewFile) or High(Overview) where Overview: TCreatedOverviewFile in PasDoc_GenHtml produces internal error in FPC 2.0.0. Same for Low(TCreatedOverviewFile). This is submitted as FPC bug 4140, [http://www.freepascal.org/bugs/showrec.php3?ID=4140]. Fixed in FPC 2.0.1 and FPC 2.1.1. } LowCreatedOverviewFile = Low(TCreatedOverviewFile); HighCreatedOverviewFile = High(TCreatedOverviewFile); type TLinkLook = (llDefault, llFull, llStripped); { This is used by @link(TDocGenerator.MakeItemLink) } TLinkContext = ( { This means that link is inside some larger code piece, e.g. within FullDeclaration of some item etc. This means that we @italic(may) be inside a context where used font has constant width. } lcCode, { This means that link is inside some "normal" description text. } lcNormal); TListType = (ltUnordered, ltOrdered, ltDefinition); TListItemSpacing = (lisCompact, lisParagraph); { Collected information about @@xxxList item. } TListItemData = class private FItemLabel: string; FText: string; FIndex: Integer; public constructor Create(AItemLabel, AText: string; AIndex: Integer); { This is only for @@definitionList: label for this list item, taken from @@itemLabel. Already in the processed form. For other lists this will always be ''. } property ItemLabel: string read FItemLabel; { This is content of this item, taken from @@item. Already in the processed form, after @link(TDocGenerator.ConvertString) etc. Ready to be included in final documentation. } property Text: string read FText; { Number of this item. This should be used for @@orderedList. When you iterate over @code(TListData.Items), you should be aware that Index of list item is @italic(not) necessarily equal to the position of item inside @code(TListData.Items). That's because of @@itemSetNumber tag. Normal list numbering (when no @@itemSetNumber tag was used) starts from 1. Using @@itemSetNumber user is able to change following item's Index. For unordered and definition lists this is simpler: Index is always equal to the position within @code(TListData.Items) (because @@itemSetNumber is not allowed there). And usually you will just ignore Index of items on unordered and definition lists. } property Index: Integer read FIndex; end; { Collected information about @@xxxList content. Passed to @link(TDocGenerator.FormatList). Every item of this list should be non-nil instance of @link(TListItemData). } TListData = class(TObjectVector) private { This is used inside list tags' handlers to calculate TListItemData.Index fields. } NextItemIndex: Integer; { This is only for @@definitionList. This is already expanded (by TTagManager.Execute) parameter of @@itemLabel tag, or '' if there is no pending (pending = not included in some @link(TListItemData)) @@itemLabel content. } LastItemLabel: string; FItemSpacing: TListItemSpacing; FListType: TListType; public property ItemSpacing: TListItemSpacing read FItemSpacing; property ListType: TListType read FListType; constructor Create(const AOwnsObject: boolean); override; end; { Collected information about @@row (or @@rowHead). } TRowData = class public { @true if this is for @@rowHead tag. } Head: boolean; { Each item on this list is already converted (with @@-tags parsed, converted by ConvertString etc.) content of given cell tag. } Cells: TStringList; constructor Create; destructor Destroy; override; end; { Collected information about @@table. Passed to @link(TDocGenerator.FormatTable). Every item of this list should be non-nil instance of @link(TRowData). } TTableData = class(TObjectVector) private FMaxCellCount: Cardinal; FMinCellCount: Cardinal; procedure CalculateCellCount; public { Maximum Cells.Count, considering all rows. } property MaxCellCount: Cardinal read FMaxCellCount; { Minimum Cells.Count, considering all rows. } property MinCellCount: Cardinal read FMinCellCount; end; { @abstract(basic documentation generator object) This abstract object will do the complete process of writing documentation files. It will be given the collection of units that was the result of the parsing process and a configuration object that was created from default values and program parameters. Depending on the output format, one or more files may be created (HTML will create several, Tex only one). } TDocGenerator = class(TComponent) private { Things related to spell checking } FCheckSpelling: boolean; FAspellLanguage: string; FAspellProcess: TAspellProcess; FSpellCheckIgnoreWords: TStringList; FLinkGraphVizUses: string; FLinkGraphVizClasses: string; FAutoAbstract: boolean; FLinkLook: TLinkLook; FConclusion: TExternalItem; FIntroduction: TExternalItem; FAbbreviations: TStringList; FGraphVizClasses: boolean; FGraphVizUses: boolean; FWriteUsesClause: boolean; FAutoLink: boolean; FAutoLinkExclude: TStringList; { Name of the project to create. } FProjectName: string; { if true, no link to pasdoc homepage will be included at the bottom of HTML files; default is false } FExcludeGenerator: boolean; FIncludeCreationTime: boolean; { the output stream that is currently written to; depending on the output format, more than one output stream will be necessary to store all documentation } {$IFDEF STRING_UNICODE} FCurrentStream: TStreamWriter; {$ELSE} FCurrentStream: TStream; {$ENDIF} { Title of documentation. } FTitle: string; { destination directory for documentation; must include terminating forward slash or backslash so that valid file names can be created by concatenating DestinationDirectory and a pathless file name } FDestDir: string; FOnMessage: TPasDocMessageEvent; { These fields are available only for tags OnExecute handlers. They are set in ExpandDescription. } FCurrentItem: TBaseItem; OrderedListTag, UnorderedListTag, DefinitionListTag, TableTag, RowTag, RowHeadTag: TTag; FExternalClassHierarchy: TStrings; procedure SetAbbreviations(const Value: TStringList); function GetLanguage: TLanguageID; procedure SetLanguage(const Value: TLanguageID); procedure SetDestDir(const Value: string); { This just calls OnMessage (if assigned), but it appends to AMessage FCurrentItem.QualifiedName. } procedure DoMessageFromExpandDescription( const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); procedure TryAutoLink(TagManager: TTagManager; const QualifiedIdentifier: TNameParts; out QualifiedIdentifierReplacement: string; var AutoLinked: boolean); function SplitSectionTagParameters( ThisTag: TTag; const TagParameter: string; DoMessages: boolean; out HeadingLevel: integer; out AnchorName: string; out Caption: string): boolean; procedure HandleLinkTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleLongCodeTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleClassnameTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleHtmlTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleLatexTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleInheritedClassTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleInheritedTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleNameTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleCodeTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleLiteralTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleBrTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleGroupTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure PreHandleSectionTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleSectionTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure PreHandleAnchorTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleAnchorTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleBoldTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleItalicTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandlePreformattedTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleImageTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleIncludeTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleIncludeCodeTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleOrderedListTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleUnorderedListTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleDefinitionListTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleItemTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleItemLabelTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleItemSpacingTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleItemSetNumberTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleTableTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleSomeRowTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleCellTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleNoAutoLinkTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleTableOfContentsTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure SetSpellCheckIgnoreWords(Value: TStringList); procedure TagAllowedInsideLists( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); procedure ItemLabelTagAllowedInside( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); procedure TagAllowedInsideTable( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); procedure TagAllowedInsideRows( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); procedure SetExternalClassHierarchy(const Value: TStrings); function StoredExternalClassHierarchy: boolean; protected { the (human) output language of the documentation file(s) } FLanguage: TPasDocLanguages; FClassHierarchy: TStringCardinalTree; procedure DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); procedure DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); {$IFDEF STRING_UNICODE} property CurrentStream: TStreamWriter read FCurrentStream; {$ELSE} property CurrentStream: TStream read FCurrentStream; {$ENDIF} procedure CreateClassHierarchy; { Return a link to item Item which will be displayed as LinkCaption. Returned string may be directly inserted inside output documentation. LinkCaption will be always converted using ConvertString before writing, so don't worry about doing this yourself when calling this method. LinkContext may be used in some descendants to present the link differently, see @link(TLinkContext) for it's meaning. If some output format doesn't support this feature, it can return simply ConvertString(LinkCaption). This is the default implementation of this method in this class. } function MakeItemLink(const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; virtual; { This writes Code as a Pascal code. Links inside the code are resolved from Item. If WriteItemLink then Item.Name is made a link. Item.Name is printed between NameLinkBegin and NameLinkEnd. } procedure WriteCodeWithLinksCommon(const Item: TPasItem; const Code: string; WriteItemLink: boolean; const NameLinkBegin, NameLinkEnd: string); protected { list of all units that were successfully parsed } FUnits: TPasUnits; { If field @link(CurrentStream) is assigned, it is disposed and set to nil. } procedure CloseStream; { @abstract(Makes a String look like a coded String, i.e. <CODE>TheString</CODE> in Html.) @param(s is the string to format) @returns(the formatted string) } function CodeString(const s: string): string; virtual; abstract; { Converts for each character in S, thus assembling a String that is returned and can be written to the documentation file. The @@ character should not be converted, this will be done later on. } function ConvertString(const s: string): string; virtual; abstract; { Converts a character to its converted form. This method should always be called to add characters to a string. @@ should also be converted by this routine. } function ConvertChar(c: char): string; virtual; abstract; { This function is supposed to return a reference to an item, that is the name combined with some linking information like a hyperlink element in HTML or a page number in Tex. } function CreateLink(const Item: TBaseItem): string; virtual; { Open output stream in the destination directory. If @link(CurrentStream) still exists (<> nil), it is closed. Then, a new output stream in the destination directory is created and assigned to @link(CurrentStream). The file is overwritten if exists. Use this only for text files that you want to write using WriteXxx methods of this class (like WriteConverted). There's no point to use if for other files. Returns @true if creation was successful, @false otherwise. When it returns @false, the error message was already shown by DoMessage. } function CreateStream(const AName: string): Boolean; { Searches for an email address in String S. Searches for first appearance of the @@ character} function ExtractEmailAddress(s: string; out S1, S2, EmailAddress: string): Boolean; { Searches for a web address in String S. It must either contain a http:// or start with www. } function ExtractWebAddress(s: string; out S1, S2, WebAddress: string): Boolean; { Searches all items in all units (given by field @link(Units)) for item with NameParts. Returns a pointer to the item on success, nil otherwise. } function FindGlobal(const NameParts: TNameParts): TBaseItem; {@name returns ' abstract', or ' sealed' for classes that abstract or sealed respectively. @name is used by @link(TTexDocGenerator) and @link(TGenericHTMLDocGenerator) in writing the declaration of the class.} function GetClassDirectiveName(Directive: TClassDirective): string; {@name writes a translation of MyType based on the current language. However, 'record' and 'packed record' are not translated.} function GetCIOTypeName(MyType: TCIOType): string; { Loads descriptions from file N and replaces or fills the corresponding comment sections of items. } procedure LoadDescriptionFile(n: string); { Searches for item with name S. If S is not splittable by SplitNameParts, returns nil. If WarningIfNotSplittable, additionally does DoMessage with appropriate warning. Else (if S is "splittable"), seeks for S (first trying Item.FindName, if Item is not nil, then trying FindGlobal). Returns nil if not found. } function SearchItem(s: string; const Item: TBaseItem; WarningIfNotSplittable: boolean): TBaseItem; { Searches for an item of name S which was linked in the description of Item. Starts search within item, then does a search on all items in all units using @link(FindGlobal). Returns a link as String on success. If S is not splittable by SplitNameParts, it always does DoMessage with appropriate warning and returns something like 'UNKNOWN' (no matter what is the value of WarningIfLinkNotFound). FoundItem will be set to nil in this case. When item will not be found then: @unorderedList( @item( if WarningIfLinkNotFound is true then it returns CodeString(ConvertString(S)) and makes DoMessage with appropriate warning.) @item(else it returns '' (and does not do any DoMessage)) ) If LinkDisplay is not '', then it specifies explicite the display text for link. Else how exactly link does look like is controlled by @link(LinkLook) property. @param(FoundItem is the found item instance or nil if not found.) } function SearchLink(s: string; const Item: TBaseItem; const LinkDisplay: string; const WarningIfLinkNotFound: boolean; out FoundItem: TBaseItem): string; overload; { Just like previous overloaded version, but this doesn't return FoundItem (in case you don't need it). } function SearchLink(s: string; const Item: TBaseItem; const LinkDisplay: string; const WarningIfLinkNotFound: boolean): string; overload; procedure StoreDescription(ItemName: string; var t: string); { Writes S to CurrentStream, converting it using @link(ConvertString). Then optionally writes LineEnding. } procedure WriteConverted(const s: string; Newline: boolean); overload; { Writes S to CurrentStream, converting it using @link(ConvertString). No LineEnding at the end. } procedure WriteConverted(const s: string); overload; { Writes S to CurrentStream, converting it using @link(ConvertString). Then writes LineEnding. } procedure WriteConvertedLine(const s: string); { Simply writes T to CurrentStream, with optional LineEnding. } procedure WriteDirect(const t: string; Newline: boolean); overload; { Simply writes T to CurrentStream. } procedure WriteDirect(const t: string); overload; { Simply writes T followed by LineEnding to CurrentStream. } procedure WriteDirectLine(const t: string); { Abstract method that writes all documentation for a single unit U to output, starting at heading level HL. Implementation must be provided by descendant objects and is dependent on output format. } procedure WriteUnit(const HL: integer; const U: TPasUnit); virtual; abstract; { Writes documentation for all units, calling @link(WriteUnit) for each unit. } procedure WriteUnits(const HL: integer); procedure WriteStartOfCode; virtual; procedure WriteEndOfCode; virtual; { output graphviz uses tree } procedure WriteGVUses; { output graphviz class tree } procedure WriteGVClasses; { starts the spell checker } procedure StartSpellChecking(const AMode: string); { If CheckSpelling and spell checking was successfully started, this will run @link(TAspellProcess.CheckString FAspellProcess.CheckString) and will report all errors using DoMessage with mtWarning. Otherwise this just clears AErrors, which means that no errors were found. } procedure CheckString(const AString: string; const AErrors: TObjectVector); { closes the spellchecker } procedure EndSpellChecking; { FormatPascalCode will cause Line to be formatted in the way that Pascal code is formatted in Delphi. Note that given Line is taken directly from what user put inside @longcode(), it is not even processed by ConvertString. You should process it with ConvertString if you want. } function FormatPascalCode(const Line: string): string; virtual; { This will cause AString to be formatted in the way that normal Pascal statements (not keywords, strings, comments, etc.) look in Delphi. } function FormatNormalCode(AString: string): string; virtual; // FormatComment will cause AString to be formatted in // the way that comments other than compiler directives are // formatted in Delphi. See: @link(FormatCompilerComment). function FormatComment(AString: string): string; virtual; // FormatHex will cause AString to be formatted in // the way that Hex are formatted in Delphi. function FormatHex(AString: string): string; virtual; // FormatNumeric will cause AString to be formatted in // the way that Numeric are formatted in Delphi. function FormatNumeric(AString: string): string; virtual; // FormatFloat will cause AString to be formatted in // the way that Float are formatted in Delphi. function FormatFloat(AString: string): string; virtual; // FormatString will cause AString to be formatted in // the way that strings are formatted in Delphi. function FormatString(AString: string): string; virtual; // FormatKeyWord will cause AString to be formatted in // the way that reserved words are formatted in Delphi. function FormatKeyWord(AString: string): string; virtual; // FormatCompilerComment will cause AString to be formatted in // the way that compiler directives are formatted in Delphi. function FormatCompilerComment(AString: string): string; virtual; { This is paragraph marker in output documentation. Default implementation in this class simply returns ' ' (one space). } function Paragraph: string; virtual; { See @link(TTagManager.ShortDash). Default implementation in this class returns '-'. } function ShortDash: string; virtual; { See @link(TTagManager.EnDash). Default implementation in this class returns '@--'. } function EnDash: string; virtual; { See @link(TTagManager.EmDash). Default implementation in this class returns '@-@--'. } function EmDash: string; virtual; { S is guaranteed (guaranteed by the user) to be correct html content, this is taken directly from parameters of @html tag. Override this function to decide what to put in output on such thing. Note that S is not processed in any way, even with ConvertString. So you're able to copy user's input inside @@html() verbatim to the output. The default implementation is this class simply discards it, i.e. returns always ''. Generators that know what to do with HTML can override this with simple "Result := S". } function HtmlString(const S: string): string; virtual; { This is equivalent of @link(HtmlString) for @@latex tag. The default implementation is this class simply discards it, i.e. returns always ''. Generators that know what to do with raw LaTeX markup can override this with simple "Result := S". } function LatexString(const S: string): string; virtual; { @abstract(This returns markup that forces line break in given output format (e.g. '<br>' in html or '\\' in LaTeX).) It is used on @br tag (but may also be used on other occasions in the future). In this class it returns '', because it's valid for an output generator to simply ignore @br tags if linebreaks can't be expressed in given output format. } function LineBreak: string; virtual; { This should return markup upon finding URL in description. E.g. HTML generator will want to wrap this in <a href="...">...</a>. Note that passed here URL is @italic(not) processed by @link(ConvertString) (because sometimes it could be undesirable). If you want you can process URL with ConvertString when overriding this method. Default implementation in this class simply returns ConvertString(URL). This is good if your documentation format does not support anything like URL links. } function URLLink(const URL: string): string; virtual; {@name is used to write the introduction and conclusion of the project.} procedure WriteExternal(const ExternalItem: TExternalItem; const Id: TTranslationID); { This is called from @link(WriteExternal) when ExternalItem.Title and ShortTitle are already set, message about generating appropriate item is printed etc. This should write ExternalItem, including ExternalItem.DetailedDescription, ExternalItem.Authors, ExternalItem.Created, ExternalItem.LastMod. } procedure WriteExternalCore(const ExternalItem: TExternalItem; const Id: TTranslationID); virtual; abstract; {@name writes a conclusion for the project. See @link(WriteExternal).} procedure WriteConclusion; {@name writes an introduction for the project. See @link(WriteExternal).} procedure WriteIntroduction; // @name writes a section heading and a link-anchor; function FormatSection(HL: integer; const Anchor: string; const Caption: string): string; virtual; abstract; // @name writes a link-anchor; function FormatAnchor(const Anchor: string): string; virtual; abstract; { This returns Text formatted using bold font. Given Text is already in the final output format (with characters converted using @link(ConvertString), @@-tags expanded etc.). Implementation of this method in this class simply returns @code(Result := Text). Output generators that can somehow express bold formatting (or at least emphasis of some text) should override this. @seealso(FormatItalic) } function FormatBold(const Text: string): string; virtual; { This returns Text formatted using italic font. Analogous to @link(FormatBold). } function FormatItalic(const Text: string): string; virtual; { This returns Text preserving spaces and line breaks. Note that Text passed here is not yet converted with ConvertString. The implementation of this method in this class just returns ConvertString(Text). } function FormatPreformatted(const Text: string): string; virtual; { This should return markup upon including specified image in description. FileNames is a list of alternative filenames of an image, it always contains at least one item (i.e. FileNames.Count >= 1), never contains empty lines (i.e. Trim(FileNames[I]) <> ''), and contains only absolute filenames (already expanded to take description's unit's path into account). E.g. HTML generator will want to choose the best format for HTML, then somehow copy the image from FileNames[Chosen] and wrap this in <img src="...">. Implementation of this method in this class simply returns @code(Result := ExpandFileName(FileNames[0])). Output generators should override this. } function FormatImage(FileNames: TStringList): string; virtual; { Format a list from given ListData. } function FormatList(ListData: TListData): string; virtual; abstract; { This should return appropriate content for given Table. It's guaranteed that the Table passed here will have at least one row and in each row there will be at least one cell, so you don't have to check it within descendants. } function FormatTable(Table: TTableData): string; virtual; abstract; { Override this if you want to insert something on @@tableOfContents tag. As a parameter you get already prepared tree of sections that your table of contents should show. Each item of Sections is a section on the level 1. Item's Name is section name, item's Value is section caption, item's Data is a TStringPairVector instance that describes subsections (on level 2) below this section. And so on, recursively. Sections given here are never nil, and item's Data is never nil. But of course they may contain 0 items, and this should be a signal to you that given section doesn't have any subsections. Default implementation of this method in this class just returns empty string. } function FormatTableOfContents(Sections: TStringPairVector): string; virtual; public { Creates anchors and links for all items in all units. } procedure BuildLinks; virtual; { Expands description for each item in each unit of @link(Units). "Expands description" means that TTagManager.Execute is called, and item's DetailedDescription, AbstractDescription, AbstractDescriptionWasAutomatic (and many others, set by @@-tags handlers) properties are calculated. } procedure ExpandDescriptions; { Abstract function that provides file extension for documentation format. Must be overwritten by descendants. } function GetFileExtension: string; virtual; abstract; { Assumes C contains file names as PString variables. Calls @link(LoadDescriptionFile) with each file name. } procedure LoadDescriptionFiles(const c: TStringVector); { Must be overwritten, writes all documentation. Will create either a single file or one file for each unit and each class, interface or object, depending on output format. } procedure WriteDocumentation; virtual; property Units: TPasUnits read FUnits write FUnits; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ParseAbbreviationsFile(const AFileName: string); property Introduction: TExternalItem read FIntroduction write FIntroduction; property Conclusion: TExternalItem read FConclusion write FConclusion; { Callback receiving messages from generator. This is usually used internally by TPasDoc class, that assigns it's internal callback here when using this generator. Also, for the above reason, do not make this published. See TPasDoc.OnMessage for something more useful for final programs. } property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; published { the (human) output language of the documentation file(s) } property Language: TLanguageID read GetLanguage write SetLanguage default DEFAULT_LANGUAGE; { Name of the project to create. } property ProjectName: string read FProjectName write FProjectName; { "Generator info" are things that can change with each invocation of pasdoc, with different pasdoc binary etc. This includes @unorderedList( @item(pasdoc's compiler name and version,) @item(pasdoc's version and time of compilation) ) See [https://github.com/pasdoc/pasdoc/wiki/ExcludeGeneratorOption]. Default value is false (i.e. show them), as this information is generally considered useful. Setting this to true is useful for automatically comparing two versions of pasdoc's output (e.g. when trying to automate pasdoc's tests). } property ExcludeGenerator: Boolean read FExcludeGenerator write FExcludeGenerator default false; { Show creation time in the output. } property IncludeCreationTime: Boolean read FIncludeCreationTime write FIncludeCreationTime default false; { Title of the documentation, supplied by user. May be empty. See @link(TPasDoc.Title). } property Title: string read FTitle write FTitle; { Destination directory for documentation. Must include terminating forward slash or backslash so that valid file names can be created by concatenating DestinationDirectory and a pathless file name. } property DestinationDirectory: string read FDestDir write SetDestDir; { generate a GraphViz diagram for the units dependencies } property OutputGraphVizUses: boolean read FGraphVizUses write FGraphVizUses default false; { generate a GraphViz diagram for the Class hierarchy } property OutputGraphVizClassHierarchy: boolean read FGraphVizClasses write FGraphVizClasses default false; { link the GraphViz uses diagram } property LinkGraphVizUses: string read FLinkGraphVizUses write FLinkGraphVizUses; { link the GraphViz classes diagram } property LinkGraphVizClasses: string read FLinkGraphVizClasses write FLinkGraphVizClasses; property Abbreviations: TStringList read FAbbreviations write SetAbbreviations; property CheckSpelling: boolean read FCheckSpelling write FCheckSpelling default false; property AspellLanguage: string read FAspellLanguage write FAspellLanguage; property SpellCheckIgnoreWords: TStringList read FSpellCheckIgnoreWords write SetSpellCheckIgnoreWords; { The meaning of this is just like @--auto-abstract command-line option. It is used in @link(ExpandDescriptions). } property AutoAbstract: boolean read FAutoAbstract write FAutoAbstract default false; { This controls @link(SearchLink) behavior, as described in [https://github.com/pasdoc/pasdoc/wiki/LinkLookOption]. } property LinkLook: TLinkLook read FLinkLook write FLinkLook default llDefault; property WriteUsesClause: boolean read FWriteUsesClause write FWriteUsesClause default false; { This controls auto-linking, see [https://github.com/pasdoc/pasdoc/wiki/AutoLinkOption] } property AutoLink: boolean read FAutoLink write FAutoLink default false; property AutoLinkExclude: TStringList read FAutoLinkExclude; property ExternalClassHierarchy: TStrings read FExternalClassHierarchy write SetExternalClassHierarchy stored StoredExternalClassHierarchy; end; implementation uses SysUtils, PasDoc_Utils, PasDoc_Tokenizer; { TListItemData ------------------------------------------------------------- } constructor TListItemData.Create(AItemLabel, AText: string; AIndex: Integer); begin inherited Create; FItemLabel := AItemLabel; FText := AText; FIndex := AIndex; end; { TListData ----------------------------------------------------------------- } constructor TListData.Create(const AOwnsObject: boolean); begin inherited; FItemSpacing := lisParagraph; NextItemIndex := 1; end; { TRowData ------------------------------------------------------------------- } constructor TRowData.Create; begin inherited; Cells := TStringList.Create; end; destructor TRowData.Destroy; begin FreeAndNil(Cells); inherited; end; { TTableData ----------------------------------------------------------------- } procedure TTableData.CalculateCellCount; var i: Integer; CC: Cardinal; begin FMinCellCount := MaxInt; FMaxCellCount := 0; for i := 0 to Count - 1 do begin CC := TRowData(Items[i]).Cells.Count; if CC < FMinCellCount then FMinCellCount := CC; if CC > FMaxCellCount then FMaxCellCount := CC; end; end; { ---------------------------------------------------------------------------- } { TDocGenerator } { ---------------------------------------------------------------------------- } procedure TDocGenerator.BuildLinks; { Assign Cio.Ancestors.Objects[i] for every i } procedure AssignCioAncestorLinks(Cio: TPasCio); var i: Integer; begin for i := 0 to Cio.Ancestors.Count - 1 do Cio.Ancestors[i].Data := SearchItem(Cio.Ancestors[i].Name, Cio, true); end; { Assign MyXxx properties (MyUnit, MyObject, MyEnum) and FullLink for all items on the list. } procedure AssignLinks(MyUnit: TPasUnit; MyObject: TPasCio; MyEnum: TPasEnum; c: TPasItems); var i: Integer; p: TPasItem; begin if (not Assigned(c)) or (c.Count < 1) then Exit; for i := 0 to c.Count - 1 do begin p := c.PasItemAt[i]; p.MyObject := MyObject; p.MyUnit := MyUnit; p.MyEnum := MyEnum; p.FullLink := CreateLink(p); end; end; var U: TPasUnit; { Assign MyXxx properties (MyUnit, MyObject, MyEnum), FullLink, OutputFileName and ansestor links for this Cio (classs / interface / object). } procedure CiosAssignLinks(ACios: TPasItems); var ACio : TPasCio; I : Integer; begin for I := 0 to ACios.Count -1 do begin ACio := TPasCio(ACios.PasItemAt[I]); ACio.MyUnit := U; ACio.FullLink := CreateLink(ACio); ACio.OutputFileName := ACio.FullLink; AssignCioAncestorLinks(ACio); AssignLinks(U, ACio, nil, ACio.Fields); AssignLinks(U, ACio, nil, ACio.Methods); AssignLinks(U, ACio, nil, ACio.Properties); AssignLinks(U, ACio, nil, ACio.Types); AssignLinks(U, ACio, nil, ACio.Cios); if ACio.Cios.Count > 0 then CiosAssignLinks(ACio.Cios); end; end; { Assign MyXxx properties (MyUnit, MyObject, MyEnum) and FullLink for all members of the enumerated types on this list. } procedure EnumsAssignLinks(ATypes: TPasTypes); var Enum: TPasEnum; I: Integer; begin for I := 0 to ATypes.Count - 1 do if ATypes.PasItemAt[I] is TPasEnum then begin Enum := TPasEnum(ATypes.PasItemAt[I]); AssignLinks(U, nil, Enum, Enum.Members); end; end; var i: Integer; j: Integer; begin DoMessage(2, pmtInformation, 'Creating links ...', []); if ObjectVectorIsNilOrEmpty(Units) then Exit; if Introduction <> nil then begin Introduction.FullLink := CreateLink(Introduction); Introduction.OutputFileName := Introduction.FullLink; end; if Conclusion <> nil then begin Conclusion.FullLink := CreateLink(Conclusion); Conclusion.OutputFileName := Conclusion.FullLink; end; for i := 0 to Units.Count - 1 do begin U := Units.UnitAt[i]; U.FullLink := CreateLink(U); U.OutputFileName := U.FullLink; for j := 0 to U.UsesUnits.Count - 1 do begin { Yes, this will also set U.UsesUnits.Objects[i] to nil if no such unit exists in Units table. } U.UsesUnits.Objects[j] := Units.FindListItem(U.UsesUnits[j]); end; AssignLinks(U, nil, nil, U.Constants); AssignLinks(U, nil, nil, U.Variables); AssignLinks(U, nil, nil, U.Types); AssignLinks(U, nil, nil, U.FuncsProcs); if not ObjectVectorIsNilOrEmpty(U.Types) then EnumsAssignLinks(U.Types); if not ObjectVectorIsNilOrEmpty(U.CIOs) then CiosAssignLinks(U.CIOs); end; DoMessage(2, pmtInformation, '... ' + ' links created', []); end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.CloseStream; begin if Assigned(FCurrentStream) then begin FCurrentStream.Free; FCurrentStream := nil; end; end; { ---------------------------------------------------------------------------- } function TDocGenerator.CreateLink(const Item: TBaseItem): string; begin Result := Item.Name; end; { ---------------------------------------------------------------------------- } function TDocGenerator.CreateStream(const AName: string): Boolean; var S: string; begin CloseStream; DoMessage(4, pmtInformation, 'Creating output stream "' + AName + '".', []); Result := false; S := DestinationDirectory + AName; try FCurrentStream := {$IFDEF STRING_UNICODE} TStreamWriter.Create(S, false, false, FLanguage.CodePage); {$ELSE} {$IFDEF USE_BUFFERED_STREAM} TBufferedStream.Create(S, fmCreate); {$ELSE} TFileStream.Create(S, fmCreate); {$ENDIF} {$ENDIF} Result := true; except on E: Exception do DoMessage(1, pmtError, 'Could not create file "%s": %s', [S, E.Message]); end; end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.HandleLongCodeTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if TagParameter = '' then exit; // Trim off "marker" characters at the beginning and end of TagParameter. // Do this only if they are the same character -- this way we are backward // compatible (in the past, matching characters were required), but were // not insisting on them being present in new code. if (Length(TagParameter) >= 2) and (TagParameter[1] = TagParameter[Length(TagParameter)]) then ReplaceStr := Copy(TagParameter, 2, Length(TagParameter) - 2); ReplaceStr := RemoveIndentation(ReplaceStr); // Then format pascal code. ReplaceStr := FormatPascalCode(ReplaceStr); end; procedure TDocGenerator.HandleHtmlTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := HtmlString(TagParameter); end; procedure TDocGenerator.HandleLatexTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := LatexString(TagParameter); end; procedure TDocGenerator.HandleNameTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := CodeString(ConvertString(FCurrentItem.Name)); end; procedure TDocGenerator.HandleClassnameTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ItemClassName: string; begin { TODO: this should be moved to TPasItem handler, so that @classname is registered only for TPasItem (or, even better, for TPasCio and TPasItem with MyObject <> nil). } ItemClassName := ''; if FCurrentItem is TPasItem then begin if Assigned(TPasItem(fCurrentItem).MyObject) then ItemClassName := TPasItem(fCurrentItem).MyObject.Name else if fCurrentItem is TPasCio then ItemClassName := fCurrentItem.Name; end; if ItemClassName <> '' then ReplaceStr := CodeString(ConvertString(ItemClassName)) else ThisTag.TagManager.DoMessage(1, pmtWarning, '@classname not available here', []); end; // handles @true, @false, @nil (Who uses these tags anyway?) procedure TDocGenerator.HandleLiteralTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := CodeString(UpCase(ThisTag.Name[1]) + Copy(ThisTag.Name, 2, MaxInt)); end; procedure TDocGenerator.HandleInheritedClassTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure InheritedClassCannotResolve(const Msg: string); begin ThisTag.TagManager.DoMessage(2, pmtWarning, 'Can''t resolve @inheritedClass: ' + Msg, []); ReplaceStr := CodeString(ConvertString(FCurrentItem.Name)); end; procedure HandleFromClass(TheObject: TPasCio); begin if TheObject.FirstAncestorName = '' then InheritedClassCannotResolve('No ancestor class') else if TheObject.FirstAncestor = nil then ReplaceStr := CodeString(ConvertString(TheObject.FirstAncestorName)) else ReplaceStr := MakeItemLink(TheObject.FirstAncestor, TheObject.FirstAncestorName, lcNormal); end; begin if FCurrentItem is TPasCio then HandleFromClass(TPasCio(FCurrentItem)) else if FCurrentItem is TPasItem then begin if Assigned(TPasItem(FCurrentItem).MyObject) then HandleFromClass(TPasItem(FCurrentItem).MyObject) else InheritedClassCannotResolve('This item is not a member of a class/interface/etc.'); end else InheritedClassCannotResolve('You can''t use @inheritedClass here'); end; procedure TDocGenerator.HandleInheritedTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure InheritedCannotResolve(const Msg: string); begin ThisTag.TagManager.DoMessage(2, pmtWarning, 'Can''t resolve @inherited: ' + Msg, []); ReplaceStr := CodeString(ConvertString(FCurrentItem.Name)); end; var TheObject: TPasCio; InheritedItem: TPasItem; begin { TODO: this should be moved to TPasItem handler, so that @inherited is registered only for TPasItem (or, even better, for TPasCio and TPasItem with MyObject <> nil). } if FCurrentItem is TPasCio then begin TheObject := TPasCio(FCurrentItem); if TheObject.FirstAncestorName = '' then InheritedCannotResolve('No ancestor class') else if TheObject.FirstAncestor = nil then ReplaceStr := CodeString(ConvertString(TheObject.FirstAncestorName)) else ReplaceStr := MakeItemLink(TheObject.FirstAncestor, TheObject.FirstAncestorName, lcNormal); end else if FCurrentItem is TPasItem then begin if Assigned(TPasItem(FCurrentItem).MyObject) then begin InheritedItem := TPasItem(FCurrentItem).MyObject.FindItemInAncestors( FCurrentItem.Name); if InheritedItem = nil then InheritedCannotResolve(Format('Member "%s" not found in ancestors', [FCurrentItem.Name])) else ReplaceStr := MakeItemLink(InheritedItem, InheritedItem.MyObject.Name + '.' + InheritedItem.Name, lcNormal); end else InheritedCannotResolve('This item is not a member of a class/interface/etc.'); end else InheritedCannotResolve('You can''t use @inherited here'); end; procedure TDocGenerator.HandleLinkTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var LinkTarget, LinkDisplay: string; begin ExtractFirstWord(TagParameter, LinkTarget, LinkDisplay); ReplaceStr := SearchLink(LinkTarget, FCurrentItem, LinkDisplay, true); end; procedure TDocGenerator.HandleCodeTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := CodeString(TagParameter); end; procedure TDocGenerator.HandleBrTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := LineBreak; end; procedure TDocGenerator.HandleGroupTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ''; ThisTag.TagManager.DoMessage(1, pmtWarning, 'Tag "%s" is not implemented yet, ignoring', [ThisTag.Name]); end; procedure TDocGenerator.HandleBoldTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := FormatBold(TagParameter); end; procedure TDocGenerator.HandleItalicTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := FormatItalic(TagParameter); end; procedure TDocGenerator.HandlePreformattedTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := FormatPreformatted(RemoveIndentation(TagParameter)); end; type { For @@orderedList, @@unorderedList and @@definitionList tags. } TListTag = class(TTag) function CreateOccurenceData: TObject; override; end; function TListTag.CreateOccurenceData: TObject; begin Result := TListData.Create(true); end; procedure TDocGenerator.HandleOrderedListTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; begin ListData := ThisTagData as TListData; ListData.FListType := ltOrdered; ReplaceStr := FormatList(ListData); end; procedure TDocGenerator.HandleUnorderedListTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; begin ListData := ThisTagData as TListData; ListData.FListType := ltUnordered; ReplaceStr := FormatList(ListData); end; procedure TDocGenerator.HandleDefinitionListTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; begin ListData := ThisTagData as TListData; ListData.FListType := ltDefinition; if ListData.LastItemLabel <> '' then begin ListData.Add(TListItemData.Create( ListData.LastItemLabel, '', ListData.NextItemIndex)); Inc(ListData.NextItemIndex); ListData.LastItemLabel := ''; end; ReplaceStr := FormatList(ListData); end; procedure TDocGenerator.HandleItemTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; begin ListData := EnclosingTagData as TListData; ListData.Add(TListItemData.Create( ListData.LastItemLabel, TagParameter, ListData.NextItemIndex)); Inc(ListData.NextItemIndex); ListData.LastItemLabel := ''; ReplaceStr := ''; end; procedure TDocGenerator.HandleItemLabelTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; begin ListData := EnclosingTagData as TListData; { If last tag was also @@itemLabel, not @@item, then make new item from ListData.LastItemLabel with empty Text. } if ListData.LastItemLabel <> '' then begin ListData.Add(TListItemData.Create( ListData.LastItemLabel, '', ListData.NextItemIndex)); Inc(ListData.NextItemIndex); end; { This @@itemLabel is stored inside ListData.LastItemLabel. Will be added later to ListData.Items wrapped inside some TListItemData. } ListData.LastItemLabel := TagParameter; ReplaceStr := ''; end; procedure TDocGenerator.HandleItemSpacingTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ListData: TListData; LTagParameter: string; begin ListData := EnclosingTagData as TListData; LTagParameter := LowerCase(TagParameter); if LTagParameter = 'compact' then ListData.FItemSpacing := lisCompact else if LTagParameter = 'paragraph' then ListData.FItemSpacing := lisParagraph else ThisTag.TagManager.DoMessage(1, pmtWarning, 'Invalid parameter for @itemSpacing tag: "%s"', [TagParameter]); { @itemSpacing does not generate any output to ReplaceStr. It only sets ListData.ItemSpacing } ReplaceStr := ''; end; procedure TDocGenerator.HandleItemSetNumberTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var NewNextItemIndex: Integer; begin ReplaceStr := ''; try NewNextItemIndex := StrToInt(TagParameter); (EnclosingTagData as TListData).NextItemIndex := NewNextItemIndex; except on E: EConvertError do ThisTag.TagManager.DoMessage(1, pmtWarning, 'Cannot convert parameter of @itemSetNumber tag ("%s") to a number: %s', [TagParameter, E.Message]); end; end; type { For @@row and @@rowHead tags. } TRowTag = class(TTag) function CreateOccurenceData: TObject; override; end; TTableTag = class(TTag) function CreateOccurenceData: TObject; override; end; function TRowTag.CreateOccurenceData: TObject; begin Result := TRowData.Create; end; function TTableTag.CreateOccurenceData: TObject; begin Result := TTableData.Create(true); end; procedure TDocGenerator.HandleTableTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure Error(const S: string); begin ThisTag.TagManager.DoMessage(1, pmtWarning, S, []); ReplaceStr := ConvertString(S); end; var TableData: TTableData; begin TableData := ThisTagData as TTableData; if TableData.Count = 0 then begin Error('Invalid @table: no rows'); Exit; end; TableData.CalculateCellCount; if TableData.MinCellCount = 0 then begin Error('Invalid table @row: no cells'); Exit; end; ReplaceStr := FormatTable(TableData); end; procedure TDocGenerator.HandleSomeRowTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ''; (ThisTagData as TRowData).Head := ThisTag = RowHeadTag; (EnclosingTagData as TTableData).Add(ThisTagData); { Since we just added ThisTagData to EnclosingTagData, it should no longer be freed by DestroyOccurenceData. It will be freed when EnclosingTagData will be freed. } ThisTagData := nil; end; procedure TDocGenerator.HandleCellTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ''; (EnclosingTagData as TRowData).Cells.Append(TagParameter); end; procedure TDocGenerator.HandleNoAutoLinkTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ThisTag.TagManager.CoreExecute(TagParameter, false, ThisTag, ThisTagData); end; procedure TDocGenerator.HandleTableOfContentsTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var MaxLevel: Integer; AnchorIndex: Integer; ItemAnchors: TBaseItems; function CollectSections(MinLevel: Integer): TStringPairVector; var Anchor: TAnchorItem; SectionEntry: TStringPair; begin Result := TStringPairVector.Create(true); repeat if AnchorIndex = ItemAnchors.Count then Exit; Anchor := ItemAnchors[AnchorIndex] as TAnchorItem; if Anchor.SectionLevel = 0 then begin Inc(AnchorIndex); end else if Anchor.SectionLevel = MinLevel then begin Inc(AnchorIndex); SectionEntry := TStringPair.Create(Anchor.Name, Anchor.SectionCaption); SectionEntry.Data := CollectSections(MinLevel + 1); if MinLevel <= MaxLevel then Result.Add(SectionEntry) else begin TStringPairVector(SectionEntry.Data).Free; SectionEntry.Free; end; end else if Anchor.SectionLevel > MinLevel then begin { This is for the case of malformed sections, i.e. user suddenly specified section with level greater than the "last section level + 1". In the future we may just give a warning to the user and refuse to work in such case ? For now, we just try to go on and produce something sensible. } SectionEntry := TStringPair.Create('', ''); SectionEntry.Data := CollectSections(MinLevel + 1); if MinLevel <= MaxLevel then Result.Add(SectionEntry) else begin TStringPairVector(SectionEntry.Data).Free; SectionEntry.Free; end; end else { So Anchor.SectionLevel < MinLevel, so we have to return from recursive call. } Exit; until false; end; procedure FreeSectionsList(List: TStringPairVector); var i: Integer; begin for i := 0 to List.Count - 1 do FreeSectionsList(TStringPairVector(List[i].Data)); List.Free; end; var TopLevelSections: TStringPairVector; begin { calculate MaxLevel } if Trim(TagParameter) = '' then MaxLevel := MaxInt else try MaxLevel := StrToInt(TagParameter); except on E: EConvertError do begin ThisTag.TagManager.DoMessage(1, pmtWarning, 'Invalid parameter of @tableOfContents tag: "%s". %s', [TagParameter, E.Message]); Exit; end; end; { calculate ItemAnchors } ItemAnchors := (FCurrentItem as TExternalItem).Anchors; { calculate TopLevelSections } AnchorIndex := 0; TopLevelSections := CollectSections(1); { now make use of TopLevelSections -- call FormatTableOfContents } ReplaceStr := FormatTableOfContents(TopLevelSections); { free TopLevelSections } FreeSectionsList(TopLevelSections); end; procedure TDocGenerator.DoMessageFromExpandDescription( const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); begin if Assigned(OnMessage) then OnMessage(MessageType, AMessage + ' (in description of "' + FCurrentItem.QualifiedName + '")', AVerbosity); end; procedure TDocGenerator.TryAutoLink(TagManager: TTagManager; const QualifiedIdentifier: TNameParts; out QualifiedIdentifierReplacement: string; var AutoLinked: boolean); var FoundItem: TBaseItem; QualifiedIdentifierGlued: string; begin QualifiedIdentifierGlued := GlueNameParts(QualifiedIdentifier); { first, check that we're not on AutoLinkExclude list } AutoLinked := AutoLinkExclude.IndexOf(QualifiedIdentifierGlued) = -1; if AutoLinked then begin FoundItem := FCurrentItem.FindName(QualifiedIdentifier); if FoundItem = nil then FoundItem := FindGlobal(QualifiedIdentifier); AutoLinked := (FoundItem <> nil) and FoundItem.AutoLinkHereAllowed; if AutoLinked then begin if FCurrentItem <> FoundItem then QualifiedIdentifierReplacement := MakeItemLink(FoundItem, QualifiedIdentifierGlued, lcNormal) else QualifiedIdentifierReplacement := CodeString(ConvertString(QualifiedIdentifierGlued)); end; end; end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.ExpandDescriptions; (*Takes description D of the Item, expands links (using Item), converts output-specific characters. Note that you can't process with this function more than once the same Description (i.e. like @longcode(# { BAD EXAMPLE } Description := ExpandDescription(Item, Description); Description := ExpandDescription(Item, Description); #)) because output of this function is already something ready to be included in final doc output, it shouldn't be processed once more, moreover this function initializes some properties of Item to make them also in the "already-processed" form (ready to be included in final docs). Meaning of WantFirstSentenceEnd and FirstSentenceEnd: see @link(TTagManager.Execute). *) function ExpandDescription(PreExpand: boolean; Item: TBaseItem; const Description: string; WantFirstSentenceEnd: boolean; out FirstSentenceEnd: Integer): string; overload; var TagManager: TTagManager; ItemTag, ItemLabelTag, ItemSpacingTag, ItemSetNumberTag, CellTag: TTag; begin // make it available to the handlers FCurrentItem := Item; TagManager := TTagManager.Create; try TagManager.PreExecute := PreExpand; TagManager.Abbreviations := Abbreviations; TagManager.ConvertString := {$IFDEF FPC}@{$ENDIF} ConvertString; TagManager.URLLink := {$IFDEF FPC}@{$ENDIF} URLLink; TagManager.OnMessage := {$IFDEF FPC}@{$ENDIF} DoMessageFromExpandDescription; TagManager.OnTryAutoLink := {$IFDEF FPC}@{$ENDIF} TryAutoLink; TagManager.Paragraph := Paragraph; TagManager.ShortDash := ShortDash; TagManager.EnDash := EnDash; TagManager.EmDash := EmDash; Item.RegisterTags(TagManager); { Tags without params } TTag.Create(TagManager, 'classname', nil, {$IFDEF FPC}@{$ENDIF} HandleClassnameTag, []); TTag.Create(TagManager, 'true', nil, {$IFDEF FPC}@{$ENDIF} HandleLiteralTag, []); TTag.Create(TagManager, 'false', nil, {$IFDEF FPC}@{$ENDIF} HandleLiteralTag, []); TTag.Create(TagManager, 'nil', nil, {$IFDEF FPC}@{$ENDIF} HandleLiteralTag, []); TTag.Create(TagManager, 'inheritedclass', nil, {$IFDEF FPC}@{$ENDIF} HandleInheritedClassTag, []); TTag.Create(TagManager, 'inherited', nil, {$IFDEF FPC}@{$ENDIF} HandleInheritedTag, []); TTag.Create(TagManager, 'name', nil, {$IFDEF FPC}@{$ENDIF} HandleNameTag, []); TTag.Create(TagManager, 'br', nil, {$IFDEF FPC}@{$ENDIF} HandleBrTag, []); TTag.Create(TagManager, 'groupbegin', nil, {$IFDEF FPC}@{$ENDIF} HandleGroupTag, []); TTag.Create(TagManager, 'groupend', nil, {$IFDEF FPC}@{$ENDIF} HandleGroupTag, []); { Tags with non-recursive params } TTag.Create(TagManager, 'longcode', nil, {$IFDEF FPC}@{$ENDIF} HandleLongCodeTag, [toParameterRequired]); TTag.Create(TagManager, 'html', nil, {$IFDEF FPC}@{$ENDIF} HandleHtmlTag, [toParameterRequired]); TTag.Create(TagManager, 'latex', nil, {$IFDEF FPC}@{$ENDIF} HandleLatexTag, [toParameterRequired]); TTag.Create(TagManager, 'link', nil, {$IFDEF FPC}@{$ENDIF} HandleLinkTag, [toParameterRequired]); TTag.Create(TagManager, 'preformatted', nil, {$IFDEF FPC}@{$ENDIF} HandlePreformattedTag, [toParameterRequired]); TTag.Create(TagManager, 'image', nil, {$IFDEF FPC}@{$ENDIF} HandleImageTag, [toParameterRequired]); TTag.Create(TagManager, 'include', { @include tag works the same way in both expanding passes. } {$IFDEF FPC}@{$ENDIF} HandleIncludeTag, {$IFDEF FPC}@{$ENDIF} HandleIncludeTag, [toParameterRequired]); TTag.Create(TagManager, 'includeCode', nil, {$IFDEF FPC}@{$ENDIF} HandleIncludeCodeTag, [toParameterRequired]); { Tags with recursive params } TTag.Create(TagManager, 'code', nil, {$IFDEF FPC}@{$ENDIF} HandleCodeTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); TTag.Create(TagManager, 'bold', nil, {$IFDEF FPC}@{$ENDIF} HandleBoldTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); TTag.Create(TagManager, 'italic', nil, {$IFDEF FPC}@{$ENDIF} HandleItalicTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); TTag.Create(TagManager, 'noautolink', nil, {$IFDEF FPC}@{$ENDIF} HandleNoAutoLinkTag, [toParameterRequired, toRecursiveTagsManually, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); OrderedListTag := TListTag.Create(TagManager, 'orderedlist', nil, {$IFDEF FPC}@{$ENDIF} HandleOrderedListTag, [toParameterRequired, toRecursiveTags]); UnorderedListTag := TListTag.Create(TagManager, 'unorderedlist', nil, {$IFDEF FPC}@{$ENDIF} HandleUnorderedListTag, [toParameterRequired, toRecursiveTags]); DefinitionListTag := TListTag.Create(TagManager, 'definitionlist', nil, {$IFDEF FPC}@{$ENDIF} HandleDefinitionListTag, [toParameterRequired, toRecursiveTags]); ItemTag := TTag.Create(TagManager, 'item', nil, {$IFDEF FPC}@{$ENDIF} HandleItemTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); ItemTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideLists; ItemLabelTag := TTag.Create(TagManager, 'itemlabel', nil, {$IFDEF FPC}@{$ENDIF} HandleItemLabelTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); ItemLabelTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} ItemLabelTagAllowedInside; ItemSpacingTag := TTag.Create(TagManager, 'itemspacing', nil, {$IFDEF FPC}@{$ENDIF} HandleItemSpacingTag, [toParameterRequired]); ItemSpacingTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideLists; ItemSetNumberTag := TTag.Create(TagManager, 'itemsetnumber', nil, {$IFDEF FPC}@{$ENDIF} HandleItemSetNumberTag, [toParameterRequired, toAllowNormalTextInside]); ItemSetNumberTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideLists; TableTag := TTableTag.Create(TagManager, 'table', nil, {$IFDEF FPC}@{$ENDIF} HandleTableTag, [toParameterRequired, toRecursiveTags]); RowTag := TRowTag.Create(TagManager, 'row', nil, {$IFDEF FPC}@{$ENDIF} HandleSomeRowTag, [toParameterRequired, toRecursiveTags]); RowTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideTable; RowHeadTag := TRowTag.Create(TagManager, 'rowhead', nil, {$IFDEF FPC}@{$ENDIF} HandleSomeRowTag, [toParameterRequired, toRecursiveTags]); RowHeadTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideTable; CellTag := TTag.Create(TagManager, 'cell', nil, {$IFDEF FPC}@{$ENDIF} HandleCellTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); CellTag.OnAllowedInside := {$IFDEF FPC}@{$ENDIF} TagAllowedInsideRows; if FCurrentItem is TExternalItem then begin TTopLevelTag.Create(TagManager, 'section', {$IFDEF FPC}@{$ENDIF} PreHandleSectionTag, {$IFDEF FPC}@{$ENDIF} HandleSectionTag, [toParameterRequired]); TTopLevelTag.Create(TagManager, 'anchor', {$IFDEF FPC}@{$ENDIF} PreHandleAnchorTag, {$IFDEF FPC}@{$ENDIF} HandleAnchorTag, [toParameterRequired]); TTopLevelTag.Create(TagManager, 'tableofcontents', nil, {$IFDEF FPC}@{$ENDIF} HandleTableOfContentsTag, [toParameterRequired]); end; Result := TagManager.Execute(Description, AutoLink, WantFirstSentenceEnd, FirstSentenceEnd); finally TagManager.Free; end; end; { Same thing as ExpandDescription(PreExpand, Item, Description, false, Dummy) } function ExpandDescription(PreExpand: boolean; Item: TBaseItem; const Description: string): string; overload; var Dummy: Integer; begin Result := ExpandDescription(PreExpand, Item, Description, false, Dummy); end; procedure ExpandCollection(PreExpand: boolean; c: TPasItems); forward; { expands RawDescription of Item } procedure ExpandPasItem(PreExpand: boolean; Item: TPasItem); var FirstSentenceEnd: Integer; Expanded: string; begin if Item = nil then Exit; { Note: don't just Trim or TrimCompress here resulting Item.DetailedDescription (because whitespaces, including leading and trailing, may be important for final doc format; moreover, you would break the value of FirstSentenceEnd by such thing). } Expanded := ExpandDescription(PreExpand, Item, Trim(Item.RawDescription), true, FirstSentenceEnd); if not PreExpand then begin Item.DetailedDescription := Expanded; Item.AbstractDescriptionWasAutomatic := AutoAbstract and (Trim(Item.AbstractDescription) = ''); if Item.AbstractDescriptionWasAutomatic then begin Item.AbstractDescription := Copy(Item.DetailedDescription, 1, FirstSentenceEnd); Item.DetailedDescription := Copy(Item.DetailedDescription, FirstSentenceEnd + 1, MaxInt); end; end; if Item is TPasEnum then ExpandCollection(PreExpand, TPasEnum(Item).Members); end; procedure ExpandExternalItem(PreExpand: boolean; Item: TExternalItem); var Expanded: string; begin Expanded := ExpandDescription(PreExpand, Item, Trim(Item.RawDescription)); if not PreExpand then Item.DetailedDescription := Expanded; end; { for all items in collection C, expands descriptions } procedure ExpandCollection(PreExpand: boolean; c: TPasItems); var i: Integer; begin if c = nil then Exit; for i := 0 to c.Count - 1 do ExpandPasItem(PreExpand, c.PasItemAt[i]); end; procedure ExpandEverything(PreExpand: boolean); procedure CiosExpand(const ACios: TPasItems); procedure CioExpand(const ACio: TPasCio); begin ExpandPasItem(PreExpand, ACio); ExpandCollection(PreExpand, ACio.Fields); ExpandCollection(PreExpand, ACio.Methods); ExpandCollection(PreExpand, ACio.Properties); ExpandCollection(PreExpand, ACio.Types); if ACio.Cios.Count > 0 then CiosExpand(ACio.Cios); end; var I: Integer; LCio: TPasCio; begin for I := 0 to ACios.Count - 1 do begin LCio := TPasCio(ACios.PasItemAt[I]); CioExpand(LCio); end; end; var i: Integer; U: TPasUnit; begin if Introduction <> nil then begin ExpandExternalItem(PreExpand, Introduction); end; if Conclusion <> nil then begin ExpandExternalItem(PreExpand, Conclusion); end; for i := 0 to Units.Count - 1 do begin U := Units.UnitAt[i]; ExpandPasItem(PreExpand, U); ExpandCollection(PreExpand, U.Constants); ExpandCollection(PreExpand, U.Variables); ExpandCollection(PreExpand, U.Types); ExpandCollection(PreExpand, U.FuncsProcs); if not ObjectVectorIsNilOrEmpty(U.CIOs) then CiosExpand(U.CIOs); end; end; begin DoMessage(2, pmtInformation, 'Expanding descriptions (pass 1) ...', []); ExpandEverything(true); DoMessage(2, pmtInformation, 'Expanding descriptions (pass 2) ...', []); ExpandEverything(false); DoMessage(2, pmtInformation, '... Descriptions expanded', []); end; { ---------------------------------------------------------------------------- } function TDocGenerator.ExtractEmailAddress(s: string; out S1, S2, EmailAddress: string): Boolean; const ALLOWED_CHARS = ['a'..'z', 'A'..'Z', '-', '.', '_', '0'..'9']; Letters = ['a'..'z', 'A'..'Z']; var atPos: Integer; i: Integer; begin Result := False; if (Length(s) < 6) { minimum length of email address: a@b.cd } then Exit; atPos := Pos('@', s); if (atPos < 2) or (atPos > Length(s) - 3) then Exit; { assemble address left of @ } i := atPos - 1; while (i >= 1) and IsCharInSet(s[i], ALLOWED_CHARS) do Dec(i); EmailAddress := System.Copy(s, i + 1, atPos - i - 1) + '@'; S1 := ''; if (i > 1) then S1 := System.Copy(s, 1, i); { assemble address right of @ } i := atPos + 1; while (i <= Length(s)) and IsCharInSet(s[i], ALLOWED_CHARS) do Inc(i); EmailAddress := EmailAddress + System.Copy(s, atPos + 1, i - atPos - 1); if (Length(EmailAddress) < 6) or (not IsCharInSet(EmailAddress[Length(EmailAddress)], Letters)) or (not IsCharInSet(EmailAddress[Length(EmailAddress) - 1], Letters)) then Exit; S2 := ''; if (i <= Length(s)) then S2 := System.Copy(s, i, Length(s) - i + 1); Result := True; end; function TDocGenerator.ExtractWebAddress(s: string; out S1, S2, WebAddress: string): Boolean; const ALLOWED_CHARS = ['a'..'z', 'A'..'Z', '-', '.', '_', '0'..'9']; var p: integer; begin Result := false; p := Pos('http://', s); if p > 0 then begin { if it starts with "http://" it is at least meant to be a web address } S1 := Copy(s, 1, p - 1); WebAddress := Copy(s, p + 7, 255); p := 1; while (p < Length(WebAddress)) and IsCharInSet(WebAddress[p], ALLOWED_CHARS) do Inc(p); S2 := Copy(WebAddress, p, 255); WebAddress := Copy(WebAddress, 1, p - 1); Result := true; end else begin p := Pos('www.', s); if p = 0 then exit; { if it starts with "www.", its most likely a web address, we could probably add more checks here (like: does it contain an additional dot for the TLD?) } S1 := Copy(s, 1, p - 1); WebAddress := Copy(s, p, 255); p := 1; while (p < Length(WebAddress)) and IsCharInSet(WebAddress[p], ALLOWED_CHARS) do Inc(p); S2 := Copy(WebAddress, p, 255); WebAddress := Copy(WebAddress, 1, p - 1); Result := true; end; end; { ---------------------------------------------------------------------------- } function TDocGenerator.FindGlobal( const NameParts: TNameParts): TBaseItem; var i: Integer; Item: TBaseItem; U: TPasUnit; begin Result := nil; if ObjectVectorIsNilOrEmpty(Units) then Exit; case Length(NameParts) of 1: begin if (Introduction <> nil) then begin if SameText(Introduction.Name, NameParts[0]) then begin Result := Introduction; Exit; end; Result := Introduction.FindItem(NameParts[0]); if Result <> nil then Exit; end; if (Conclusion <> nil) then begin if SameText(Conclusion.Name, NameParts[0]) then begin Result := Conclusion; Exit; end; Result := Conclusion.FindItem(NameParts[0]); if Result <> nil then Exit; end; for i := 0 to Units.Count - 1 do begin U := Units.UnitAt[i]; if SameText(U.Name, NameParts[0]) then begin Result := U; Exit; end; Result := U.FindItem(NameParts[0]); if Result <> nil then Exit; end; end; 2: begin { object.field_method_property } for i := 0 to Units.Count - 1 do begin Result := Units.UnitAt[i].FindInsideSomeClass(NameParts[0], NameParts[1]); if Assigned(Result) then Exit; end; { unit.cio_var_const_type } U := TPasUnit(Units.FindListItem(NameParts[0])); if Assigned(U) then Result := U.FindItem(NameParts[1]); end; 3: begin { unit.objectorclassorinterface.fieldormethodorproperty } U := TPasUnit(Units.FindListItem(NameParts[0])); if (not Assigned(U)) then Exit; Item := U.FindItem(NameParts[1]); if (not Assigned(Item)) then Exit; Item := Item.FindItem(NameParts[2]); if (not Assigned(Item)) then Exit; Result := Item; Exit; end; end; end; { ---------------------------------------------------------------------------- } function TDocGenerator.GetClassDirectiveName(Directive: TClassDirective): string; begin case Directive of CT_NONE: begin result := ''; end; CT_ABSTRACT: begin result := ' abstract'; end; CT_SEALED: begin result := ' sealed'; end; CT_HELPER: begin result := ' helper'; end; else Assert(False); end; end; function TDocGenerator.GetCIOTypeName(MyType: TCIOType): string; begin case MyType of CIO_CLASS: Result := FLanguage.Translation[trClass]; CIO_PACKEDCLASS: Result := FLanguage.Translation[trPacked] + ' ' + FLanguage.Translation[trClass]; CIO_DISPINTERFACE: Result := FLanguage.Translation[trDispInterface]; CIO_INTERFACE: Result := FLanguage.Translation[trInterface]; CIO_OBJECT: Result := FLanguage.Translation[trObject]; CIO_PACKEDOBJECT: Result := FLanguage.Translation[trPacked] + ' ' + FLanguage.Translation[trObject]; CIO_RECORD: Result := FLanguage.Translation[trRecord]; CIO_PACKEDRECORD: Result := FLanguage.Translation[trPacked] + ' ' + FLanguage.Translation[trRecord]; else Result := ''; end; end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.LoadDescriptionFile(n: string); var {$IFDEF STRING_UNICODE} f : TStreamReader; {$ELSE} f : TStream; {$ENDIF} ItemName : string; Description : string; i : Integer; s : string; const IdentChars = ['A'..'Z', 'a'..'z', '_', '.', '0'..'9']; begin ItemName := ''; if n = '' then Exit; try {$IFDEF STRING_UNICODE} f := TStreamReader.Create(n); {$ELSE} {$IFDEF USE_BUFFERED_STREAM} f := TBufferedStream.Create(n, fmOpenRead or fmShareDenyWrite); {$ELSE} f := TFileStream.Create(n, fmOpenRead or fmShareDenyWrite); {$ENDIF} {$ENDIF} // Assert(Assigned(f)); useless here try {$IFDEF STRING_UNICODE} while f.ReadLine(S) do begin {$ELSE} while f.Position < f.Size do begin s := StreamReadLine(f); {$ENDIF} if s[1] = '#' then begin i := 2; while IsCharInSet(s[i], [' ', #9]) do Inc(i); { Make sure we read a valid name - the user might have used # in his description. } if IsCharInSet(s[i], IdentChars) then begin if ItemName <> '' then StoreDescription(ItemName, Description); { Read item name and beginning of the description } ItemName := ''; repeat ItemName := ItemName + s[i]; Inc(i); until not IsCharInSet(s[i], IdentChars); while IsCharInSet(s[i], [' ', #9]) do Inc(i); Description := Copy(s, i, MaxInt); Continue; end; end; Description := Description + s; end; if ItemName = '' then DoMessage(2, pmtWarning, 'No descriptions read from "%s" -- invalid or empty file', [n]) else StoreDescription(ItemName, Description); finally f.Free; end; except on E: Exception do DoError('Could not open description file "%s". Reason: "%s"', [n, E.Message], 0); end; end; {TDocGenerator.LoadDescriptionFile} { ---------------------------------------------------------------------------- } procedure TDocGenerator.LoadDescriptionFiles(const c: TStringVector); var i: Integer; begin if c <> nil then begin DoMessage(3, pmtInformation, 'Loading description files ...', []); for i := 0 to c.Count - 1 do LoadDescriptionFile(c[i]); end; end; { ---------------------------------------------------------------------------- } function TDocGenerator.SearchItem(s: string; const Item: TBaseItem; WarningIfNotSplittable: boolean): TBaseItem; var NameParts: TNameParts; begin if not SplitNameParts(s, NameParts) then begin if WarningIfNotSplittable then DoMessage(2, pmtWarning, 'The link "' + s + '" is invalid', []); Result := nil; Exit; end; { first try to find link starting at Item } if Assigned(Item) then Result := Item.FindName(NameParts) else Result := nil; if not Assigned(Result) then Result := FindGlobal(NameParts); end; { ---------------------------------------------------------------------------- } function TDocGenerator.SearchLink(s: string; const Item: TBaseItem; const LinkDisplay: string; const WarningIfLinkNotFound: boolean; out FoundItem: TBaseItem): string; var NameParts: TNameParts; begin FoundItem := nil; if (not SplitNameParts(s, NameParts)) then begin DoMessage(2, pmtWarning, 'Invalid Link "' + s + '" (' + Item.QualifiedName + ')', []); Result := 'UNKNOWN'; Exit; end; { first try to find link starting at Item } if Assigned(Item) then begin FoundItem := Item.FindName(NameParts); end; { Find Global } if FoundItem = nil then FoundItem := FindGlobal(NameParts); if Assigned(FoundItem) then begin if LinkDisplay <> '' then Result := MakeItemLink(FoundItem, LinkDisplay, lcNormal) else case LinkLook of llDefault: Result := MakeItemLink(FoundItem, S, lcNormal); llStripped: Result := MakeItemLink(FoundItem, FoundItem.Name, lcNormal); llFull: begin Result := MakeItemLink(FoundItem, FoundItem.Name, lcNormal); if Length(NameParts) = 3 then begin SetLength(NameParts, 2); FoundItem := FindGlobal(NameParts); Result := MakeItemLink(FoundItem, FoundItem.Name, lcNormal) + '.' + Result; end; if Length(NameParts) = 2 then begin SetLength(NameParts, 1); FoundItem := FindGlobal(NameParts); Result := MakeItemLink(FoundItem, FoundItem.Name, lcNormal) + '.' + Result; end; end; else Assert(false, 'LinkLook = ??'); end; end else if WarningIfLinkNotFound then begin DoMessage(1, pmtWarning, 'Could not resolve link "%s" (from description of "%s")', [S, Item.QualifiedName]); Result := CodeString(ConvertString(S)); end else Result := ''; end; function TDocGenerator.SearchLink(s: string; const Item: TBaseItem; const LinkDisplay: string; const WarningIfLinkNotFound: boolean): string; var Dummy: TBaseItem; begin Result := SearchLink(S, Item, LinkDisplay, WarningIfLinkNotFound, Dummy); end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.StoreDescription(ItemName: string; var t: string); var Item: TBaseItem; NameParts: TNameParts; begin if t = '' then Exit; DoMessage(5, pmtInformation, 'Storing description for ' + ItemName, []); if SplitNameParts(ItemName, NameParts) then begin Item := FindGlobal(NameParts); if Assigned(Item) then begin if Item.RawDescription <> '' then { Delimit previous contents of Item.RawDescription with a paragraph } Item.RawDescription := Item.RawDescription + LineEnding + LineEnding; Item.RawDescription := Item.RawDescription + t; end else DoMessage(2, pmtWarning, 'Could not find item ' + ItemName, []); end else DoMessage(2, pmtWarning, 'Could not split item "' + ItemName + '"', []); t := ''; end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.WriteConverted(const s: string; Newline: boolean); begin WriteDirect(ConvertString(s), Newline); end; procedure TDocGenerator.WriteConverted(const s: string); begin WriteDirect(ConvertString(s)); end; procedure TDocGenerator.WriteConvertedLine(const s: string); begin WriteDirectLine(ConvertString(s)); end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.WriteDirect(const t: string; Newline: boolean); begin if NewLine then WriteDirectLine(T) else WriteDirect(T); end; procedure TDocGenerator.WriteDirect(const t: string); begin {$IFDEF STRING_UNICODE} CurrentStream.Write(t); {$ELSE} StreamWriteString(CurrentStream, AnsiString(t)); {$ENDIF} end; procedure TDocGenerator.WriteDirectLine(const t: string); begin {$IFDEF STRING_UNICODE} CurrentStream.WriteLine(t); {$ELSE} StreamWriteLine(CurrentStream, AnsiString(t)); {$ENDIF} end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.WriteUnits(const HL: integer); var i: Integer; begin if ObjectVectorIsNilOrEmpty(Units) then Exit; for i := 0 to Units.Count - 1 do begin WriteUnit(HL, Units.UnitAt[i]); end; end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); begin raise EPasDoc.Create(AMessage, AArguments, AExitCode); end; { ---------------------------------------------------------------------------- } procedure TDocGenerator.DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if Assigned(FOnMessage) then begin FOnMessage(MessageType, Format(AMessage, AArguments), AVerbosity); end; end; const DefaultExternalClassHierarchy = {$I external_class_hierarchy.txt.inc}; constructor TDocGenerator.Create(AOwner: TComponent); begin inherited; FClassHierarchy := nil; FExcludeGenerator := false; FIncludeCreationTime := false; FLanguage := TPasDocLanguages.Create; FAbbreviations := TStringList.Create; FAbbreviations.Duplicates := dupIgnore; FSpellCheckIgnoreWords := TStringList.Create; FAutoLinkExclude := TStringList.Create; FAutoLinkExclude.CaseSensitive := false; FExternalClassHierarchy := TStringList.Create; FExternalClassHierarchy.Text := DefaultExternalClassHierarchy; TStringList(FExternalClassHierarchy).CaseSensitive := false; end; destructor TDocGenerator.Destroy; begin FreeAndNil(FExternalClassHierarchy); FreeAndNil(FAutoLinkExclude); FSpellCheckIgnoreWords.Free; FLanguage.Free; FClassHierarchy.Free; FAbbreviations.Free; FCurrentStream.Free; inherited; end; procedure TDocGenerator.CreateClassHierarchy; function FindGlobalPasItem(const NameParts: TNameParts): TPasItem; var BaseResult: TBaseItem; begin BaseResult := FindGlobal(NameParts); if (BaseResult <> nil) and (BaseResult is TPasItem) then Result := TPasItem(BaseResult) else Result := nil; end; { Insert a parent->child relation into the tree. ParentItem may be nil, then only ParentName (not linked) will be used. When ParentName is '', this child has no parent (for example, maybe it's TObject class). ChildItem also may be nil, then only ChildName (not linked) will be used. ChildName must not be empty. } procedure Insert(const ParentName: string; ParentItem: TPasItem; const ChildName: string; ChildItem: TPasItem); var Parent, Child: TPasItemNode; GrandParentName: string; GrandParentItem: TPasItem; begin if Assigned(ParentItem) then begin Parent := FClassHierarchy.ItemOfName(ParentItem.Name); // Add parent if not already there. if Parent = nil then Parent := FClassHierarchy.InsertItem(ParentItem); end else if Length(ParentName) <> 0 then begin Parent := FClassHierarchy.ItemOfName(ParentName); if Parent = nil then begin Parent := FClassHierarchy.InsertName(ParentName); { We add a new item to the tree that is not a TPasItem. So look for it's parents using ExternalClassHierarchy. } GrandParentName := ExternalClassHierarchy.Values[ParentName]; if GrandParentName <> '' then begin { Although we found GrandParentName using ExternalClassHierarchy, it's possible that it's actually present in parsed files. This may happen when you have classes A -> B -> C (descending like this), and your source code includes classes A and C, but not B. So we have to use here FindGlobalPasItem. } GrandParentItem := FindGlobalPasItem(OneNamePart(GrandParentName)); Insert(GrandParentName, GrandParentItem, ParentName, nil); end; end; end else Parent := nil; Child := FClassHierarchy.ItemOfName(ChildName); if Child = nil then begin if ChildItem <> nil then FClassHierarchy.InsertParented(Parent, ChildItem) else FClassHierarchy.InsertParented(Parent, ChildName); end else begin if Parent <> nil then FClassHierarchy.MoveChildLast(Child, Parent); end; end; var ParentItem: TPasItem; ParentName: string; procedure CioClassHierarchy(const ACio: TPasCio); begin if ACio.MyType in CIONonHierarchy then Exit; { calculate ParentName and ParentItem for current ACIO. } if Assigned(ACio.Ancestors) and (ACio.Ancestors.Count > 0) then begin ParentName := ACio.Ancestors.FirstName; ParentItem := FindGlobalPasItem(OneNamePart(ParentName)); end else begin ParentName := ''; ParentItem := nil; end; Insert(ParentName, ParentItem, ACio.Name, ACio); end; procedure CiosClassHierarchy(const ACios: TPasNestedCios); var I: Integer; LCio: TPasCio; begin for I := 0 to ACios.Count - 1 do begin LCio := TPasCio(ACios.PasItemAt[I]); CioClassHierarchy(LCio); end; end; var unitLoop: Integer; classLoop: Integer; PU: TPasUnit; LCio: TPasCio; begin FClassHierarchy.Free; FClassHierarchy := TStringCardinalTree.Create; for unitLoop := 0 to Units.Count - 1 do begin PU := Units.UnitAt[unitLoop]; if PU.CIOs = nil then Continue; for classLoop := 0 to PU.CIOs.Count - 1 do begin LCio := TPasCio(PU.CIOs.PasItemAt[classLoop]); CioClassHierarchy(LCio); if LCio.Cios.Count > 0 then CiosClassHierarchy(LCio.Cios); end; end; FClassHierarchy.Sort; end; procedure TDocGenerator.WriteEndOfCode; begin // nothing - for some output this is irrelevant end; procedure TDocGenerator.WriteStartOfCode; begin // nothing - for some output this is irrelevant end; procedure TDocGenerator.WriteDocumentation; begin if OutputGraphVizUses then WriteGVUses; if OutputGraphVizClassHierarchy then WriteGVClasses; end; procedure TDocGenerator.SetLanguage(const Value: TLanguageID); begin FLanguage.Language := Value; end; procedure TDocGenerator.SetDestDir(const Value: string); begin if Value <> '' then begin FDestDir := IncludeTrailingPathDelimiter(Value); end else begin FDestDir := ''; end; end; function TDocGenerator.GetLanguage: TLanguageID; begin Result := FLanguage.Language; end; procedure TDocGenerator.WriteGVClasses; var LNode: TPasItemNode; OverviewFileName: string; begin CreateClassHierarchy; LNode := FClassHierarchy.FirstItem; if Assigned(LNode) then begin OverviewFileName := OverviewFilesInfo[ofGraphVizClasses].BaseFileName + '.dot'; if not CreateStream(OverviewFileName) then Exit; WriteDirect('DiGraph Classes {', true); while Assigned(LNode) do begin if Assigned(LNode.Parent) and (LNode.Parent.Name <> '') then begin WriteDirectLine(' ' + LNode.Name + ' -> '+LNode.Parent.Name); end; if Assigned(LNode.Item) and (LNode.Item is TPasCio) then begin WriteDirectLine(' ' + LNode.Name + ' [href="' + TPasCio(LNode.Item).OutputFileName + '"]'); end; LNode := FClassHierarchy.NextItem(LNode); end; WriteDirect('}', true); CloseStream; end; end; procedure TDocGenerator.WriteGVUses; var i, j: Integer; U: TPasUnit; OverviewFileName: string; begin if not ObjectVectorIsNilOrEmpty(FUnits) then begin OverviewFileName := OverviewFilesInfo[ofGraphVizUses].BaseFileName + '.dot'; if not CreateStream(OverviewFileName) then Exit; WriteDirect('DiGraph Uses {', true); for i := 0 to FUnits.Count-1 do begin if FUnits.PasItemAt[i] is TPasUnit then begin U := TPasUnit(FUnits.PasItemAt[i]); if not IsEmpty(U.UsesUnits) then begin for j := 0 to U.UsesUnits.Count-1 do begin WriteDirectLine(' "' + U.Name + '" -> "' + U.UsesUnits[j] + '"'); end; end; WriteDirectLine(' "' + U.Name + '" [href="' + U.OutputFileName + '"]'); end; end; WriteDirect('}', true); CloseStream; end; end; procedure TDocGenerator.SetAbbreviations(const Value: TStringList); begin FAbbreviations.Assign(Value); end; procedure TDocGenerator.ParseAbbreviationsFile(const AFileName: string); var L: TStringList; i, p: Integer; s, lname, value: string; begin if FileExists(AFileName) then begin L := TStringList.Create; try L.LoadFromFile(AFileName); for i := 0 to L.Count-1 do begin s := Trim(L[i]); if length(s)>0 then begin if s[1] = '[' then begin p := pos(']', s); if p>=0 then begin lname := Trim(copy(s, 2, p-2)); value := Trim(copy(s,p+1,MaxInt)); FAbbreviations.Values[lname] := value; end; end; end; end; finally L.Free; end; end; end; procedure TDocGenerator.CheckString(const AString: string; const AErrors: TObjectVector); var i: Integer; begin if FCheckSpelling and (FAspellProcess <> nil) then begin FAspellProcess.CheckString(AString, AErrors); for i := 0 to AErrors.Count - 1 do DoMessage(2, pmtWarning, 'Word misspelled "%s"', [TSpellingError(AErrors[i]).Word]); end else AErrors.Clear; end; procedure TDocGenerator.EndSpellChecking; begin { If CheckSpelling was false or StartSpellChecking failed then FAspellProcess will be nil, so it's safe to just always call FreeAndNil here. } FreeAndNil(FAspellProcess); end; procedure TDocGenerator.StartSpellChecking(const AMode: string); var WordsToIgnore: TStringList; procedure AddSubItems(Items: TBaseItems); var SubItem: TBaseItem; Index: integer; AName: string; NewName: string; begin for Index := 0 to Items.Count -1 do begin SubItem := Items[Index] as TBaseItem; AName := Trim(SCharsReplace(SubItem.Name, ['0'..'9', '_'], ' ')); if AName = SubItem.Name then begin if (SubItem.Name <> '') then begin WordsToIgnore.Add(SubItem.Name); end; end else begin While AName <> '' do begin NewName := ExtractFirstWord(AName); WordsToIgnore.Add(NewName); end; end; if SubItem is TExternalItem then begin AddSubItems(TExternalItem(SubItem).Anchors); end else if SubItem is TPasEnum then begin AddSubItems(TPasEnum(SubItem).Members); end else if SubItem is TPasCio then begin AddSubItems(TPasCio(SubItem).Fields); AddSubItems(TPasCio(SubItem).Methods); AddSubItems(TPasCio(SubItem).Properties); AddSubItems(TPasCio(SubItem).Fields); end else if SubItem is TPasUnit then begin AddSubItems(TPasUnit(SubItem).CIOs); AddSubItems(TPasUnit(SubItem).Constants); AddSubItems(TPasUnit(SubItem).FuncsProcs); AddSubItems(TPasUnit(SubItem).Types); AddSubItems(TPasUnit(SubItem).Variables); AddSubItems(TPasUnit(SubItem).Types); AddSubItems(TPasUnit(SubItem).Types); end; end; end; begin { Make sure that previous aspell process is closed } FreeAndNil(FAspellProcess); if CheckSpelling then begin try FAspellProcess := TAspellProcess.Create(AMode, FAspellLanguage, OnMessage); except on E: Exception do begin DoMessage(1, pmtWarning, 'Executing aspell failed, ' + 'disabling spell checking: "%s"', [E.Message]); Exit; end; end; WordsToIgnore := TStringList.Create; try WordsToIgnore.Sorted := True; WordsToIgnore.Duplicates := dupIgnore; WordsToIgnore.AddStrings(SpellCheckIgnoreWords); if Introduction <> nil then begin WordsToIgnore.Add(Introduction.Name); AddSubItems(Introduction.Anchors); end; if Conclusion <> nil then begin WordsToIgnore.Add(Conclusion.Name); AddSubItems(Conclusion.Anchors); end; AddSubItems(Units); FAspellProcess.SetIgnoreWords(WordsToIgnore); finally WordsToIgnore.Free; end; end; end; procedure TDocGenerator.SetSpellCheckIgnoreWords(Value: TStringList); begin SpellCheckIgnoreWords.Assign(Value); end; function TDocGenerator.FormatPascalCode(const Line: string): string; { Calls FormatKeyWord or FormatNormalCode, depending on whether AString is keyword. } function FormatCode(const AString: string): string; begin if (KeyWordByName(AString) <> KEY_INVALIDKEYWORD) or (StandardDirectiveByName(AString) <> SD_INVALIDSTANDARDDIRECTIVE) then Result := FormatKeyWord(AString) else Result := FormatNormalCode(AString); end; type TCodeType = (ctWhiteSpace, ctString, ctCode, ctEndString, ctChar, ctParenComment, ctBracketComment, ctSlashComment, ctCompilerComment, ctHex, ctEndHex, ctNumeric, ctEndNumeric); var CharIndex: integer; CodeType: TCodeType; CommentBegining: integer; StringBeginning: integer; CodeBeginning: integer; HexBeginning: Integer; NumBeginning: Integer; EndOfCode: boolean; WhiteSpaceBeginning: integer; NumberSubBlock: String; NumberRange: Integer; const Separators = [' ', ',', '(', ')', #9, #10, #13, ';', '[', ']', '{', '}', '''', ':', '<', '>', '=', '+', '-', '*', '/', '@', '.']; LineEnd = [#10, #13]; AlphaNumeric = ['0'..'9', 'a'..'z', 'A'..'Z', '_']; Numeric = ['0'..'9','.']; Hexadec = ['0'..'9', 'a'..'f', 'A'..'F', '$']; function TestCommentStart: boolean; begin result := False; if Line[CharIndex] = '(' then begin if (CharIndex < Length(Line)) and (Line[CharIndex + 1] = '*') then begin CodeType := ctParenComment; result := True; end end else if Line[CharIndex] = '{' then begin if (CharIndex < Length(Line)) and (Line[CharIndex + 1] = '$') then begin CodeType := ctCompilerComment; end else begin CodeType := ctBracketComment; end; result := True; end else if Line[CharIndex] = '/' then begin if (CharIndex < Length(Line)) and (Line[CharIndex + 1] = '/') then begin CodeType := ctSlashComment; result := True; end end; if result then begin CommentBegining := CharIndex; end; end; function TestStringBeginning: boolean; begin result := False; if Line[CharIndex] = '''' then begin if CodeType <> ctChar then begin StringBeginning := CharIndex; end; CodeType := ctString; result := True; end end; begin CommentBegining := 1; StringBeginning := 1; HexBeginning := 1; NumBeginning := 1; result := ''; CodeType := ctWhiteSpace; WhiteSpaceBeginning := 1; CodeBeginning := 1; for CharIndex := 1 to Length(Line) do begin case CodeType of ctWhiteSpace: begin EndOfCode := False; if TestStringBeginning then begin EndOfCode := True; end else if Line[CharIndex] = '#' then begin StringBeginning := CharIndex; CodeType := ctChar; EndOfCode := True; end else if TestCommentStart then begin EndOfCode := True; end else if Line[CharIndex] = '$' Then begin CodeType := ctHex; HexBeginning := CharIndex; EndOfCode := True; end else if IsCharInSet(Line[CharIndex], Numeric) then begin CodeType := ctNumeric; NumBeginning := CharIndex; EndOfCode := True; end else if IsCharInSet(Line[CharIndex], AlphaNumeric) then begin CodeType := ctCode; CodeBeginning := CharIndex; EndOfCode := True; end; if EndOfCode then begin result := result + ConvertString(Copy(Line, WhiteSpaceBeginning, CharIndex - WhiteSpaceBeginning)); end; end; ctString: begin if Line[CharIndex] = '''' then begin if (CharIndex = Length(Line)) or (Line[CharIndex + 1] <> '''') then begin CodeType := ctEndString; result := result + FormatString(Copy(Line, StringBeginning, CharIndex - StringBeginning + 1)); end; end; end; ctCode: begin EndOfCode := False; if TestStringBeginning then begin EndOfCode := True; end else if Line[CharIndex] = '#' then begin EndOfCode := True; CodeType := ctChar; StringBeginning := CharIndex; end else if TestCommentStart then begin EndOfCode := True; end else if not IsCharInSet(Line[CharIndex], AlphaNumeric) then begin EndOfCode := True; CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex; end; if EndOfCode then begin result := result + FormatCode(Copy(Line, CodeBeginning, CharIndex - CodeBeginning)); end; end; ctEndString: begin if Line[CharIndex] = '#' then begin CodeType := ctChar; end else if TestCommentStart then begin // do nothing end else if Line[CharIndex] = '$' Then Begin CodeType := ctHex; HexBeginning := CharIndex; End else if IsCharInSet(Line[CharIndex], Numeric) then begin CodeType := ctNumeric; NumBeginning := CharIndex; end else if IsCharInSet(Line[CharIndex], AlphaNumeric) then begin CodeType := ctCode; CodeBeginning := CharIndex; end else begin CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex; end; end; ctChar: begin if Line[CharIndex] = '''' then begin CodeType := ctString; end else if TestCommentStart then begin // do nothing end else if IsCharInSet(Line[CharIndex], Separators) then begin result := result + FormatString(Copy(Line, StringBeginning, CharIndex - StringBeginning)); CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex; end; end; ctParenComment: begin if (Line[CharIndex] = ')') and (CharIndex > 1) and (Line[CharIndex - 1] = '*') then begin result := result + FormatComment(Copy(Line, CommentBegining, CharIndex - CommentBegining + 1)); // behave like whitespace starts right after the comment CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex + 1; end; end; ctBracketComment: begin if Line[CharIndex] = '}' then begin result := result + FormatComment(Copy(Line, CommentBegining, CharIndex - CommentBegining + 1)); // behave like whitespace starts right after the comment CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex + 1; end; end; ctCompilerComment: begin if Line[CharIndex] = '}' then begin result := result + FormatCompilerComment(Copy(Line, CommentBegining, CharIndex - CommentBegining + 1)); // behave like whitespace starts right after the comment CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex + 1; end; end; ctSlashComment: begin if IsCharInSet(Line[CharIndex], LineEnd) then begin CodeType := ctWhiteSpace; result := result + FormatComment(Copy(Line, CommentBegining, CharIndex - CommentBegining)); WhiteSpaceBeginning := CharIndex; end; end; ctHex: Begin If IsCharInSet(Line[CharIndex], Separators) Or Not IsCharInSet(Line[CharIndex], Hexadec) then begin CodeType := ctEndHex; result := result + FormatHex(Copy(Line, HexBeginning, CharIndex - HexBeginning)); result := result + FormatCode(Copy(Line, CharIndex, 1)); end; End; ctNumeric: Begin If IsCharInSet(Line[CharIndex], (Separators - ['.'])) Or Not IsCharInSet(Line[CharIndex], Numeric) then begin CodeType := ctEndNumeric; If Pos('.', Copy(Line, NumBeginning, CharIndex - NumBeginning)) > 0 Then Begin NumberSubBlock := Copy(Line, NumBeginning, CharIndex - NumBeginning); NumberRange := Pos('..', NumberSubBlock); If NumberRange > 0 Then Begin result := result + FormatNumeric( Copy(NumberSubBlock, 1, NumberRange - 1)); result := result + FormatCode( Copy(NumberSubBlock, NumberRange, Length(NumberSubBlock))); End Else result := result + FormatFloat(NumberSubBlock); End Else result := result + FormatNumeric(Copy(Line, NumBeginning, CharIndex - NumBeginning)); result := result + FormatCode(Copy(Line, CharIndex, 1)); end; End; ctEndHex: begin if Line[CharIndex] = '#' then begin CodeType := ctChar; end else if TestCommentStart then begin // do nothing end else if IsCharInSet(Line[CharIndex], Numeric) then begin CodeType := ctNumeric; NumBeginning := CharIndex; end else if IsCharInSet(Line[CharIndex], AlphaNumeric) then begin CodeType := ctCode; CodeBeginning := CharIndex; end else begin CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex; end; end; ctEndNumeric: begin if Line[CharIndex] = '#' then begin CodeType := ctChar; end else if TestCommentStart then begin // do nothing end else if Line[CharIndex] = '$' Then Begin CodeType := ctHex; HexBeginning := CharIndex; End else if IsCharInSet(Line[CharIndex], AlphaNumeric) then begin CodeType := ctCode; CodeBeginning := CharIndex; end else begin CodeType := ctWhiteSpace; WhiteSpaceBeginning := CharIndex; end; end; else Assert(False); end; end; CharIndex := Length(Line) + 1; case CodeType of ctWhiteSpace: begin result := result + (Copy(Line, WhiteSpaceBeginning, CharIndex - WhiteSpaceBeginning)); end; ctString: begin end; ctCode: begin result := result + FormatCode(Copy(Line, CodeBeginning, CharIndex - CodeBeginning)); end; ctEndString: begin end; ctChar: begin result := result + FormatString(Copy(Line, StringBeginning, CharIndex - StringBeginning)); end; ctParenComment, ctSlashComment, ctBracketComment: begin { add an unterminated comment at the end } result := result + FormatComment(Copy(Line, CommentBegining, CharIndex - CommentBegining)); end; ctCompilerComment: begin result := result + FormatCompilerComment(Copy(Line, CommentBegining, CharIndex - CommentBegining)); end; ctHex: begin end; ctEndHex: begin end; ctNumeric: begin end; ctEndNumeric: begin end; else Assert(False); end; end; function TDocGenerator.FormatNormalCode(AString: string): string; begin Result := ConvertString(AString); end; function TDocGenerator.FormatComment(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatHex(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatNumeric(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatFloat(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatCompilerComment(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatKeyWord(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.FormatString(AString: string): string; begin result := ConvertString(AString); end; function TDocGenerator.Paragraph: string; begin Result := ' '; end; function TDocGenerator.ShortDash: string; begin Result := '-'; end; function TDocGenerator.EnDash: string; begin Result := '--'; end; function TDocGenerator.EmDash: string; begin Result := '---'; end; function TDocGenerator.HtmlString(const S: string): string; begin Result := ''; end; function TDocGenerator.LatexString(const S: string): string; begin Result := ''; end; function TDocGenerator.LineBreak: string; begin Result := ''; end; function TDocGenerator.URLLink(const URL: string): string; begin Result := ConvertString(URL); end; function TDocGenerator.FormatBold(const Text: string): string; begin Result := Text; end; function TDocGenerator.FormatItalic(const Text: string): string; begin Result := Text; end; function TDocGenerator.FormatPreformatted(const Text: string): string; begin Result := ConvertString(Text); end; function TDocGenerator.FormatTableOfContents(Sections: TStringPairVector): string; begin Result := ''; end; function TDocGenerator.MakeItemLink(const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; begin Result := ConvertString(LinkCaption); end; procedure TDocGenerator.WriteCodeWithLinksCommon(const Item: TPasItem; const Code: string; WriteItemLink: boolean; const NameLinkBegin, NameLinkEnd: string); var NameFound, SearchForLink: Boolean; FoundItem: TBaseItem; i, j, l: Integer; s: string; pl: TStandardDirective; { ncstart marks what part of Code was already written: Code[1..ncstart - 1] is already written to output stream. } ncstart: Integer; begin WriteStartOfCode; i := 1; NameFound := false; SearchForLink := False; l := Length(Code); ncstart := i; while i <= l do begin case Code[i] of '_', 'A'..'Z', 'a'..'z': begin WriteConverted(Copy(Code, ncstart, i - ncstart)); { assemble item } j := i; repeat Inc(i); until (i > l) or (not IsCharInSet(Code[i], ['.', '_', '0'..'9', 'A'..'Z', 'a'..'z'])); s := Copy(Code, j, i - j); if not NameFound and (s = Item.Name) then begin WriteDirect(NameLinkBegin); if WriteItemLink then WriteDirect(MakeItemLink(Item, s, lcCode)) else WriteConverted(s); WriteDirect(NameLinkEnd); NameFound := True; end else begin { Special processing for standard directives. Note that we check whether S is standard directive *after* we checked whether S matches P.Name, otherwise we would mistakenly think that 'register' is a standard directive in Code 'procedure Register;' This shouldn't cause another problem (accidentally making standard directive a link, e.g. in code like 'procedure Foo; register' or even 'procedure Register; register;' ) because we safeguard against it using NameFound and SearchForLink state variables. That said, WriteCodeWithLinksCommon still remains a hackish excuse to not cooperate better with PasDoc_Parser when generating FullDeclaration of every item. } pl := StandardDirectiveByName(s); case pl of SD_ABSTRACT, SD_ASSEMBLER, SD_CDECL, SD_DYNAMIC, SD_EXPORT, SD_FAR, SD_FORWARD, SD_NAME, SD_NEAR, SD_OVERLOAD, SD_OVERRIDE, SD_PASCAL, SD_REGISTER, SD_SAFECALL, SD_STATIC, SD_STDCALL, SD_REINTRODUCE, SD_VIRTUAL: begin WriteConverted(s); SearchForLink := False; end; SD_EXTERNAL: begin WriteConverted(s); SearchForLink := true; end; else begin if SearchForLink then FoundItem := SearchItem(S, Item, false) else FoundItem := nil; if Assigned(FoundItem) then WriteDirect(MakeItemLink(FoundItem, s, lcCode)) else WriteConverted(s); end; end; end; ncstart := i; end; ':', '=': begin SearchForLink := True; Inc(i); end; ';': begin SearchForLink := False; Inc(i); end; '''': begin { No need to worry here about the fact that 'foo''bar' is actually one string, "foo'bar". We will parse it in this procedure as two strings, 'foo', then 'bar' (missing the fact that ' is a part of string), but this doesn't harm us (as we don't need here the value of parsed string). } repeat Inc(i); until (i > l) or (Code[i] = ''''); Inc(i); end; else Inc(i); end; end; WriteConverted(Copy(Code, ncstart, i - ncstart)); WriteEndOfCode; end; procedure TDocGenerator.WriteExternal( const ExternalItem: TExternalItem; const Id: TTranslationID); begin if not Assigned(ExternalItem) then begin Exit; end; DoMessage(2, pmtInformation, 'Writing Docs for %s, "%s"', [FLanguage.Translation[Id], ExternalItem.Name]); If ExternalItem.Title = '' then begin ExternalItem.Title := FLanguage.Translation[Id]; end; If ExternalItem.ShortTitle = '' then begin ExternalItem.ShortTitle := ExternalItem.Title; end; WriteExternalCore(ExternalItem, Id); end; procedure TDocGenerator.WriteIntroduction; begin WriteExternal(Introduction, trIntroduction); end; procedure TDocGenerator.WriteConclusion; begin WriteExternal(Conclusion, trConclusion); end; procedure TDocGenerator.PreHandleAnchorTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var AnchorName: string; AnchorItem: TAnchorItem; begin { We add AnchorName to FCurrentItem.Anchors in the 1st pass of expanding descriptions (i.e. in PreHandleAnchorTag instead of HandleAnchorTag), this way creating @links in the 2nd pass of expanding descriptions works good. } ReplaceStr := ''; AnchorName := Trim(TagParameter); if not IsValidIdent(AnchorName) then begin ThisTag.TagManager.DoMessage(1, pmtWarning, 'Invalid anchor name: "%s"', [AnchorName]); Exit; end; AnchorItem := (FCurrentItem as TExternalItem).AddAnchor(AnchorName); AnchorItem.FullLink := CreateLink(AnchorItem); end; procedure TDocGenerator.HandleAnchorTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var AnchorName: string; begin { AnchorName is already added to FCurrentItem.Anchors, thanks to PreHandleAnchorTag. All we do here is to generate correct ReplaceStr. } AnchorName := Trim(TagParameter); if not IsValidIdent(AnchorName) then { Warning for this case was already printed by PreHandleAnchorTag. That's why here we do only Exit. } Exit; ReplaceStr := FormatAnchor(AnchorName); end; function TDocGenerator.SplitSectionTagParameters( ThisTag: TTag; const TagParameter: string; DoMessages: boolean; out HeadingLevel: integer; out AnchorName: string; out Caption: string): boolean; var HeadingLevelString: string; Remainder: string; begin Result := false; ExtractFirstWord(TagParameter, HeadingLevelString, Remainder); ExtractFirstWord(Remainder, AnchorName, Caption); try HeadingLevel := StrToInt(HeadingLevelString); except on E: EConvertError do begin if DoMessages then ThisTag.TagManager.DoMessage(1, pmtWarning, 'Invalid heading level in @section tag: "%s". %s', [HeadingLevelString, E.Message]); Exit; end; end; if HeadingLevel < 1 then begin if DoMessages then ThisTag.TagManager.DoMessage(1, pmtWarning, 'Invalid heading level in @section tag: %d. Heading level must be >= 1', [HeadingLevel]); Exit; end; Result := true; end; procedure TDocGenerator.PreHandleSectionTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var AnchorName: string; Caption: string; AnchorItem: TAnchorItem; HeadingLevel: integer; begin { We add AnchorName to FCurrentItem.Anchors in the 1st pass of expanding descriptions (i.e. in PreHandleSectionTag instead of HandleSectionTag), this way creating @links in the 2nd pass of expanding descriptions works good. Also, we can handle @tableOfContents in the 2nd pass. } ReplaceStr := ''; if SplitSectionTagParameters(ThisTag, TagParameter, false, HeadingLevel, AnchorName, Caption) then begin AnchorItem := (FCurrentItem as TExternalItem).AddAnchor(AnchorName); AnchorItem.FullLink := CreateLink(AnchorItem); AnchorItem.SectionLevel := HeadingLevel; AnchorItem.SectionCaption := Caption; end; end; procedure TDocGenerator.HandleSectionTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var AnchorName: string; Caption: string; HeadingLevel: integer; begin if SplitSectionTagParameters(ThisTag, TagParameter, true, HeadingLevel, AnchorName, Caption) then begin ReplaceStr := FormatSection(HeadingLevel, AnchorName, Caption); end; { Section is already added to FCurrentItem.Anchors, thanks to PreHandleSectionTag. } end; procedure TDocGenerator.TagAllowedInsideLists( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); begin Allowed := (EnclosingTag = OrderedListTag) or (EnclosingTag = UnorderedListTag) or (EnclosingTag = DefinitionListTag); end; procedure TDocGenerator.ItemLabelTagAllowedInside( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); begin Allowed := EnclosingTag = DefinitionListTag; end; procedure TDocGenerator.TagAllowedInsideTable( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); begin Allowed := EnclosingTag = TableTag; end; procedure TDocGenerator.TagAllowedInsideRows( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean); begin Allowed := (EnclosingTag = RowTag) or (EnclosingTag = RowHeadTag); end; procedure TDocGenerator.HandleImageTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var I: Integer; FileNames: TStringList; begin FileNames := TStringList.Create; try FileNames.Text := TagParameter; { Trim, remove empty lines, and expand paths on FileNames } I := 0; while I < FileNames.Count do begin FileNames[I] := Trim(FileNames[I]); if FileNames[I] = '' then FileNames.Delete(I) else begin FileNames[I] := CombinePaths(FCurrentItem.BasePath, FileNames[I]); Inc(I); end; end; if FileNames.Count = 0 then begin ThisTag.TagManager.DoMessage(1, pmtWarning, 'No parameters for @image tag', []); end else ReplaceStr := FormatImage(FileNames); finally FileNames.Free end; end; function TDocGenerator.FormatImage(FileNames: TStringList): string; begin Result := ExpandFileName(FileNames[0]); end; procedure TDocGenerator.HandleIncludeTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var IncludedText: string; begin IncludedText := FileToString(CombinePaths(FCurrentItem.BasePath, Trim(TagParameter))); ReplaceStr := ThisTag.TagManager.Execute(IncludedText, { Note that this means that we reset auto-linking state inside the include file to what was chosen by --auto-link command-line option. I.e., @noAutoLink(@include(file.txt)) does NOT turn auto-linking off inside file.txt. } AutoLink); end; procedure TDocGenerator.HandleIncludeCodeTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var I: Integer; FileName: string; FileNames: TStringList; begin FileNames := TStringList.Create; try FileNames.Text := TagParameter; ReplaceStr := ''; for I := 0 to Pred(FileNames.Count) do begin FileName := Trim(FileNames[I]); if Length(FileName) > 0 then begin FileName := CombinePaths(FCurrentItem.BasePath, FileName); ReplaceStr := ReplaceStr + FormatPascalCode(FileToString(FileName)); end; end; if ReplaceStr = '' then ThisTag.TagManager.DoMessage(1, pmtWarning, 'No parameters for @includeCode tag', []); finally FileNames.Free end; end; procedure TDocGenerator.SetExternalClassHierarchy(const Value: TStrings); begin FExternalClassHierarchy.Assign(Value); end; function TDocGenerator.StoredExternalClassHierarchy: boolean; begin Result := Trim(FExternalClassHierarchy.Text) <> Trim(DefaultExternalClassHierarchy); end; end. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/pasdoc.css������������������������������������������������������������������0000600�0001750�0001750�00000015446�13237143042�017761� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- */ body, html, table.container { margin: 0; padding: 0; } body { font-family: Verdana,Arial; color: black; background-color: white; } table.container { width: 100%; border-spacing: 0; } table.container td { vertical-align: top; } td.navigation { width: 200px; color: white; background-color: #787878; margin: 0; /* padding-bottom is a little larger, to make navigation column have some nice height even when td.content column is very small. */ padding: 1em 1em 100px 1em; } td.navigation p { padding: 0; } td.navigation h2 { margin-top: 0; } td.content { padding: 1em; } td.content h1 { margin-top: 0; } img { border:0px; } hr { border-bottom: medium none; border-top: thin solid #888; } a:link {color:#C91E0C; text-decoration: none; } a:visited {color:#7E5C31; text-decoration: none; } a:hover {text-decoration: underline; } a:active {text-decoration: underline; } a.navigation:link { color: white; text-decoration: none; } a.navigation:visited { color: white; text-decoration: none; } a.navigation:hover { color: white; font-weight: bold; text-decoration: none; } a.navigation:active { color: white; text-decoration: none; } a.bold:link {color:#C91E0C; text-decoration: none; font-weight:bold; } a.bold:visited {color:#7E5C31; text-decoration: none; font-weight:bold; } a.bold:hover {text-decoration: underline; font-weight:bold; } a.bold:active {text-decoration: underline; font-weight:bold; } a.section {color: green; text-decoration: none; font-weight: bold; } a.section:hover {color: green; text-decoration: underline; font-weight: bold; } ul.useslist a:link {color:#C91E0C; text-decoration: none; font-weight:bold; } ul.useslist a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; } ul.useslist a:hover {text-decoration: underline; font-weight:bold; } ul.useslist a:active {text-decoration: underline; font-weight:bold; } ul.hierarchy { list-style-type:none; } ul.hierarchylevel { list-style-type:none; } p.unitlink a:link {color:#C91E0C; text-decoration: none; font-weight:bold; } p.unitlink a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; } p.unitlink a:hover {text-decoration: underline; font-weight:bold; } p.unitlink a:active {text-decoration: underline; font-weight:bold; } tr.list { background: #FFBF44; } tr.list2 { background: #FFC982; } tr.listheader { background: #C91E0C; color: white; } table.wide_list { border-spacing:2px; width:100%; } table.wide_list td { vertical-align:top; padding:4px; } table.markerlegend { width:auto; } table.markerlegend td.legendmarker { text-align:center; } .sections { background:white; } .sections .one_section { background:lightgray; display: inline-block; margin: 0.2em; padding: 0.5em 1em; } table.summary td.itemcode { width:100%; } table.detail td.itemcode { width:100%; } td.itemname {white-space:nowrap; } td.itemunit {white-space:nowrap; } td.itemdesc { width:100%; } div.nodescription { color:red; } dl.parameters dt { color:blue; } /* Various browsers have various default styles for <h6>, sometimes ugly for our purposes, so it's best to set things like font-size and font-weight in out pasdoc.css explicitly. */ h6.description_section { /* font-size 100% means that it has the same font size as the parent element, i.e. normal description text */ font-size: 100%; font-weight: bold; /* By default browsers usually have some large margin-bottom and margin-top for <h1-6> tags. In our case, margin-bottom is unnecessary, we want to visually show that description_section is closely related to content below. In this situation (where the font size is just as a normal text), smaller bottom margin seems to look good. */ margin-top: 1.4em; margin-bottom: 0em; } /* Style applied to Pascal code in documentation (e.g. produced by @longcode tag) } */ span.pascal_string { color: #000080; } span.pascal_keyword { font-weight: bolder; } span.pascal_comment { color: #000080; font-style: italic; } span.pascal_compiler_comment { color: #008000; } span.pascal_numeric { } span.pascal_hex { } p.hint_directive { color: red; } input#search_text { } input#search_submit_button { } acronym.mispelling { background-color: #ffa; } /* Actually this reduces vertical space between *every* paragraph inside list with @itemSpacing(compact). While we would like to reduce this space only for the top of 1st and bottom of last paragraph within each list item. But, well, user probably will not do any paragraph breaks within a list with @itemSpacing(compact) anyway, so it's acceptable solution. */ ul.compact_spacing p { margin-top: 0em; margin-bottom: 0em; } ol.compact_spacing p { margin-top: 0em; margin-bottom: 0em; } dl.compact_spacing p { margin-top: 0em; margin-bottom: 0em; } /* Style for table created by @table tags: just some thin border. This way we have some borders around the cells (so cells are visibly separated), but the border "blends with the background" so it doesn't look too ugly. Hopefully it looks satisfactory in most cases and for most people. We add padding for cells, otherwise they look too close. This is normal thing to do when border-collapse is set to collapse (because this eliminates spacing between cells). */ table.table_tag { border-collapse: collapse; } table.table_tag td { border: 1pt solid gray; padding: 0.3em; } table.table_tag th { border: 1pt solid gray; padding: 0.3em; } table.detail { border: 1pt solid gray; margin-top: 0.3em; margin-bottom: 0.3em; } .search-form { white-space: nowrap; } .search-input, .search-button { display: inline-block; vertical-align: middle; } /* Do not make extra vertical space at the beginning/end of table cells. We need ">" selector, to not change paragraphs inside lists inside table cells. */ table.table_tag td > p:first-child, table.table_tag th > p:first-child, td.itemdesc > p:first-child { margin-top: 0em; } table.table_tag td > p:last-child, table.table_tag th > p:last-child, td.itemdesc > p:last-child { margin-bottom: 0em; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/pasdoc_kylixversions.inc����������������������������������������������������0000600�0001750�0001750�00000002426�13237143042�022745� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } {$IFDEF LINUX} {$IF RTLVersion = 14.0} {$DEFINE KYLIX_1} {$DEFINE KYLIX_1_UP} {$DEFINE KYLIX} {$IFEND} {$IF RTLVersion = 14.2} {$DEFINE KYLIX_2} {$DEFINE KYLIX_1_UP} {$DEFINE KYLIX_2_UP} {$DEFINE KYLIX} {$IFEND} {$IF RTLVersion = 14.5} {$DEFINE KYLIX_3} {$DEFINE KYLIX_1_UP} {$DEFINE KYLIX_2_UP} {$DEFINE KYLIX_3_UP} {$DEFINE KYLIX} {$IFEND} {$ENDIF} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/���������������������������������������������������������������������0000700�0001750�0001750�00000000000�13237143042�017227� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/published.gif��������������������������������������������������������0000600�0001750�0001750�00000000215�13034465544�021706� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL8���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/automated.gif��������������������������������������������������������0000600�0001750�0001750�00000000215�13034465544�021712� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL?���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/automated.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�13237143042�022455� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "automated.gif" } array [0 .. 140] of Byte = ( $47, $49, $46, $38, $39, $61, $0B, $00, $0B, $00, $F1, $02, $00, $66, $4C, $1B, $8D, $ED, $3F, $FF, $FF, $FF, $00, $00, $00, $21, $F9, $04, $00, $00, $00, $00, $00, $21, $FE, $15, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $54, $68, $65, $20, $47, $49, $4D, $50, $00, $2C, $00, $00, $00, $00, $0B, $00, $0B, $00, $00, $02, $45, $04, $08, $10, $20, $40, $80, $00, $25, $4A, $94, $28, $51, $20, $C4, $84, $09, $13, $46, $04, $A8, $30, $61, $C2, $84, $02, $21, $26, $4C, $98, $30, $22, $40, $85, $09, $13, $26, $14, $08, $31, $61, $C2, $84, $11, $01, $2A, $4C, $98, $30, $A1, $40, $88, $09, $13, $26, $8C, $08, $50, $A2, $44, $89, $12, $05, $02, $04, $08, $10, $20, $40, $14, $00, $3B) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/protected.gif��������������������������������������������������������0000600�0001750�0001750�00000000215�13034465544�021720� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL'���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/private.gif.inc������������������������������������������������������0000600�0001750�0001750�00000001522�13237143042�022142� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "private.gif" } array [0 .. 140] of Byte = ( $47, $49, $46, $38, $39, $61, $0B, $00, $0B, $00, $F1, $02, $00, $66, $4C, $1B, $E0, $01, $01, $FF, $FF, $FF, $00, $00, $00, $21, $F9, $04, $00, $00, $00, $00, $00, $21, $FE, $15, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $54, $68, $65, $20, $47, $49, $4D, $50, $00, $2C, $00, $00, $00, $00, $0B, $00, $0B, $00, $00, $02, $45, $04, $08, $10, $20, $40, $80, $00, $25, $4A, $94, $28, $51, $20, $C4, $84, $09, $13, $46, $04, $A8, $30, $61, $C2, $84, $02, $21, $26, $4C, $98, $30, $22, $40, $85, $09, $13, $26, $14, $08, $31, $61, $C2, $84, $11, $01, $2A, $4C, $98, $30, $A1, $40, $88, $09, $13, $26, $8C, $08, $50, $A2, $44, $89, $12, $05, $02, $04, $08, $10, $20, $40, $14, $00, $3B) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/public.gif.inc�������������������������������������������������������0000600�0001750�0001750�00000001521�13237143042�021745� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "public.gif" } array [0 .. 140] of Byte = ( $47, $49, $46, $38, $39, $61, $0B, $00, $0B, $00, $F1, $02, $00, $66, $4C, $1B, $38, $A4, $23, $FF, $FF, $FF, $00, $00, $00, $21, $F9, $04, $00, $00, $00, $00, $00, $21, $FE, $15, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $54, $68, $65, $20, $47, $49, $4D, $50, $00, $2C, $00, $00, $00, $00, $0B, $00, $0B, $00, $00, $02, $45, $04, $08, $10, $20, $40, $80, $00, $25, $4A, $94, $28, $51, $20, $C4, $84, $09, $13, $46, $04, $A8, $30, $61, $C2, $84, $02, $21, $26, $4C, $98, $30, $22, $40, $85, $09, $13, $26, $14, $08, $31, $61, $C2, $84, $11, $01, $2A, $4C, $98, $30, $A1, $40, $88, $09, $13, $26, $8C, $08, $50, $A2, $44, $89, $12, $05, $02, $04, $08, $10, $20, $40, $14, $00, $3B) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/protected.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�13237143042�022463� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "protected.gif" } array [0 .. 140] of Byte = ( $47, $49, $46, $38, $39, $61, $0B, $00, $0B, $00, $F1, $02, $00, $66, $4C, $1B, $FF, $CF, $27, $FF, $FF, $FF, $00, $00, $00, $21, $F9, $04, $00, $00, $00, $00, $00, $21, $FE, $15, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $54, $68, $65, $20, $47, $49, $4D, $50, $00, $2C, $00, $00, $00, $00, $0B, $00, $0B, $00, $00, $02, $45, $04, $08, $10, $20, $40, $80, $00, $25, $4A, $94, $28, $51, $20, $C4, $84, $09, $13, $46, $04, $A8, $30, $61, $C2, $84, $02, $21, $26, $4C, $98, $30, $22, $40, $85, $09, $13, $26, $14, $08, $31, $61, $C2, $84, $11, $01, $2A, $4C, $98, $30, $A1, $40, $88, $09, $13, $26, $8C, $08, $50, $A2, $44, $89, $12, $05, $02, $04, $08, $10, $20, $40, $14, $00, $3B) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/Makefile�������������������������������������������������������������0000600�0001750�0001750�00000000605�13034465544�020703� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Generate all *.gif.inc files from *.gif files in this directory. # Uses ../../tools/file_to_pascal_data program, so be sure that it's # compiled. ALL_OUTPUT := automated.gif.inc \ private.gif.inc \ protected.gif.inc \ public.gif.inc \ published.gif.inc .PHONY: all clean all: $(ALL_OUTPUT) clean: rm -f $(ALL_OUTPUT) %.gif.inc: %.gif ../../tools/file_to_pascal_data $< $@ ���������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/private.gif����������������������������������������������������������0000600�0001750�0001750�00000000215�13034465544�021401� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/published.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�13237143042�022451� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "published.gif" } array [0 .. 140] of Byte = ( $47, $49, $46, $38, $39, $61, $0B, $00, $0B, $00, $F1, $02, $00, $66, $4C, $1B, $1E, $38, $BA, $FF, $FF, $FF, $00, $00, $00, $21, $F9, $04, $00, $00, $00, $00, $00, $21, $FE, $15, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $54, $68, $65, $20, $47, $49, $4D, $50, $00, $2C, $00, $00, $00, $00, $0B, $00, $0B, $00, $00, $02, $45, $04, $08, $10, $20, $40, $80, $00, $25, $4A, $94, $28, $51, $20, $C4, $84, $09, $13, $46, $04, $A8, $30, $61, $C2, $84, $02, $21, $26, $4C, $98, $30, $22, $40, $85, $09, $13, $26, $14, $08, $31, $61, $C2, $84, $11, $01, $2A, $4C, $98, $30, $A1, $40, $88, $09, $13, $26, $8C, $08, $50, $A2, $44, $89, $12, $05, $02, $04, $08, $10, $20, $40, $14, $00, $3B) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/public.gif�����������������������������������������������������������0000600�0001750�0001750�00000000215�13034465544�021205� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL8#���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_GenHtmlHelp.pas������������������������������������������������������0000600�0001750�0001750�00000046747�13237143042�022113� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Generate HtmlHelp output.) } unit PasDoc_GenHtmlHelp; {$I pasdoc_defines.inc} interface uses PasDoc_GenHtml, PasDoc_Utils, PasDoc_SortSettings; type THTMLHelpDocGenerator = class(TGenericHTMLDocGenerator) private FContentsFile: string; { Writes the topic files for Html Help Generation } procedure WriteHtmlHelpProject; public procedure WriteDocumentation; override; published { Contains Name of a file to read HtmlHelp Contents from. If empty, create default contents file. } property ContentsFile: string read FContentsFile write FContentsFile; end; implementation uses SysUtils, PasDoc_Types, PasDoc_StringVector, PasDoc_Base, PasDoc_Items, PasDoc_Languages, PasDoc_Gen, PasDoc_Versions; { HtmlHelp Content Generation inspired by Wim van der Vegt <wvd_vegt@knoware.nl> } function BeforeEqualChar(const s: string): string; var i: Cardinal; begin Result := s; i := Pos('=', Result); if i <> 0 then SetLength(Result, i - 1); end; function AfterEqualChar(const s: string): string; var i: Cardinal; begin Result := s; i := Pos('=', Result); if i <> 0 then Delete(Result, 1, i) else Result := ''; end; function GetLevel(var s: string): Integer; var l: Cardinal; p: PChar; begin Result := 0; p := Pointer(s); l := Length(s); while (l > 0) and IsCharInSet(p^, [' ', #9]) do begin Inc(Result); Inc(p); Dec(l); end; Delete(s, 1, Result); end; { THTMLHelpDocGenerator ------------------------------------------------------ } procedure THTMLHelpDocGenerator.WriteDocumentation; begin inherited; WriteHtmlHelpProject; end; procedure THTMLHelpDocGenerator.WriteHtmlHelpProject; var DefaultContentsWritten: Boolean; DefaultTopic: string; procedure WriteLiObject(const Name, Local: string); begin WriteDirectLine('<li><object type="text/sitemap">'); WriteDirectLine('<param name="Name" value="' + Name + '">'); if Local <> '' then begin WriteDirectLine('<param name="Local" value="' + Local + '">'); if DefaultTopic = '' then DefaultTopic := Local; end; WriteDirectLine('</object>'); end; { ---------- } procedure WriteItemCollection(const _Filename: string; const c: TPasItems); var i: Integer; Item: TPasItem; begin if Assigned(c) then begin WriteDirectLine('<ul>'); for i := 0 to c.Count - 1 do begin Item := c.PasItemAt[i]; WriteLiObject(Item.Name, _Filename + '#' + Item.Name); end; WriteDirectLine('</ul>'); end; end; { ---------- } procedure WriteItemHeadingCollection(const Title, ParentLink, Anchor: string; const c: TPasItems); begin if Assigned(c) and (c.Count > 0) then begin WriteLiObject(Title, ParentLink + '#' + Anchor); WriteItemCollection(ParentLink, c); end; end; { ---------- } procedure InternalWriteCIO(const ClassItem: TPasCio); var I: Integer; begin WriteLiObject(ClassItem.Name, ClassItem.FullLink); WriteDirectLine('<ul>'); if ClassItem.Cios.Count > 0 then begin WriteLiObject(FLanguage.Translation[trInternalCR], ClassItem.FullLink + '#@InternalCRs'); ClassItem.Cios.SortShallow; WriteDirectLine('<ul>'); for I := 0 to ClassItem.Cios.Count - 1 do begin TPasCio(ClassItem.Cios.PasItemAt[I]).Sort([ssRecordFields, ssNonRecordFields, ssMethods, ssProperties]); InternalWriteCIO(TPasCio(ClassItem.Cios.PasItemAt[I])); end; WriteDirectLine('</ul>'); end; WriteItemHeadingCollection(fLanguage.Translation[trInternalTypes], ClassItem.FullLink, '@InternalTypes', ClassItem.Types); WriteItemHeadingCollection(fLanguage.Translation[trFields], ClassItem.FullLink, '@Fields', ClassItem.Fields); WriteItemHeadingCollection(fLanguage.Translation[trProperties], ClassItem.FullLink, '@Properties', ClassItem.Properties); WriteItemHeadingCollection(fLanguage.Translation[trMethods], ClassItem.FullLink, '@Methods', ClassItem.Methods); WriteDirectLine('</ul>'); end; { ---------- } procedure ContentWriteUnits(const Text: string); var c: TPasItems; j, k: Integer; PU: TPasUnit; begin if Text <> '' then WriteLiObject(Text, OverviewFilesInfo[ofUnits].BaseFileName + GetFileExtension) else WriteLiObject(FLanguage.Translation[trUnits], OverviewFilesInfo[ofUnits].BaseFileName + GetFileExtension); WriteDirectLine('<ul>'); // Iterate all Units for j := 0 to Units.Count - 1 do begin PU := Units.UnitAt[j]; WriteLiObject(PU.Name, PU.FullLink); WriteDirectLine('<ul>'); // For each unit, write classes (if there are any). c := PU.CIOs; if Assigned(c) then begin WriteLiObject(FLanguage.Translation[trClasses], PU.FullLink + '#@Classes'); WriteDirectLine('<ul>'); for k := 0 to c.Count - 1 do InternalWriteCIO(TPasCio(c.PasItemAt[k])); WriteDirectLine('</ul>'); end; // For each unit, write Functions & Procedures. WriteItemHeadingCollection(FLanguage.Translation[trFunctionsAndProcedures], PU.FullLink, '@FuncsProcs', PU.FuncsProcs); // For each unit, write Types. WriteItemHeadingCollection(FLanguage.Translation[trTypes], PU.FullLink, '@Types', PU.Types); // For each unit, write Constants. WriteItemHeadingCollection(FLanguage.Translation[trConstants], PU.FullLink, '@Constants', PU.Constants); WriteDirectLine('</ul>'); end; WriteDirectLine('</ul>'); end; { ---------- } procedure ContentWriteClasses(const Text: string); var c: TPasItems; j: Integer; PU: TPasUnit; FileName: string; begin FileName := OverviewFilesInfo[ofCios].BaseFileName + GetFileExtension; // Write Classes to Contents if Text <> '' then WriteLiObject(Text, FileName) else WriteLiObject(FLanguage.Translation[trClasses], FileName); WriteDirectLine('<ul>'); c := TPasItems.Create(False); // First collect classes for j := 0 to Units.Count - 1 do begin PU := Units.UnitAt[j]; c.CopyItems(PU.CIOs); end; // Output sorted classes // TODO: Sort by sort settings rather than const values c.SortShallow; for j := 0 to c.Count - 1 do begin TPasCio(c.PasItemAt[j]).Sort([ssRecordFields, ssNonRecordFields, ssMethods, ssProperties]); InternalWriteCIO(TPasCio(c.PasItemAt[j])); end; c.Free; WriteDirectLine('</ul>'); end; { ---------- } procedure ContentWriteClassHierarchy(const Text: string); var FileName: string; begin FileName := OverviewFilesInfo[ofClassHierarchy].BaseFileName + GetFileExtension; if Text <> '' then WriteLiObject(Text, FileName) else WriteLiObject(FLanguage.Translation[trClassHierarchy], FileName); end; { ---------- } procedure ContentWriteOverview(const Text: string); procedure WriteParam(Id: TTranslationId); begin WriteDirect('<param name="Name" value="'); WriteConverted(FLanguage.Translation[Id]); WriteDirectLine('">'); end; var Overview: TCreatedOverviewFile; begin if Text <> '' then WriteLiObject(Text, '') else WriteLiObject(FLanguage.Translation[trOverview], ''); WriteDirectLine('<ul>'); for Overview := LowCreatedOverviewFile to HighCreatedOverviewFile do begin WriteDirectLine('<li><object type="text/sitemap">'); WriteParam(OverviewFilesInfo[Overview].TranslationHeadlineId); WriteDirect('<param name="Local" value="'); WriteConverted(OverviewFilesInfo[Overview].BaseFileName + GetFileExtension); WriteDirectLine('">'); WriteDirectLine('</object>'); end; WriteDirectLine('</ul>'); end; { ---------- } procedure ContentWriteLegend(const Text: string); var FileName: string; begin FileName := 'Legend' + GetFileExtension; if Text <> '' then WriteLiObject(Text, FileName) else WriteLiObject(FLanguage.Translation[trLegend], FileName); end; { ---------- } procedure ContentWriteGVUses(); var FileName: string; begin FileName := OverviewFilesInfo[ofGraphVizUses].BaseFileName + '.' + LinkGraphVizUses; if LinkGraphVizUses <> '' then WriteLiObject(FLanguage.Translation[trGvUses], FileName); end; { ---------- } procedure ContentWriteGVClasses(); var FileName: string; begin FileName := OverviewFilesInfo[ofGraphVizClasses].BaseFileName + '.' + LinkGraphVizClasses; if LinkGraphVizClasses <> '' then WriteLiObject(FLanguage.Translation[trGvClasses], FileName); end; { ---------- } procedure ContentWriteCustom(const Text, Link: string); begin if CompareText('@Classes', Link) = 0 then begin DefaultContentsWritten := True; ContentWriteClasses(Text); end else if CompareText('@ClassHierarchy', Link) = 0 then begin DefaultContentsWritten := True; ContentWriteClassHierarchy(Text); end else if CompareText('@Units', Link) = 0 then begin DefaultContentsWritten := True; ContentWriteUnits(Text); end else if CompareText('@Overview', Link) = 0 then begin DefaultContentsWritten := True; ContentWriteOverview(Text); end else if CompareText('@Legend', Link) = 0 then begin DefaultContentsWritten := True; ContentWriteLegend(Text); end else WriteLiObject(Text, Link); end; { ---------- } Procedure ContentWriteIntroduction; begin if Introduction <> nil then begin WriteLiObject(Introduction.ShortTitle, Introduction.FullLink); end; end; { ---------- } Procedure ContentWriteConclusion; begin if Conclusion <> nil then begin WriteLiObject(Conclusion.ShortTitle, Conclusion.FullLink); end; end; procedure IndexWriteItem(const Item, PreviousItem, NextItem: TPasItem); { Item is guaranteed to be assigned, i.e. not to be nil. } begin if Assigned(Item.MyObject) then begin if (Assigned(NextItem) and Assigned(NextItem.MyObject) and (CompareText(Item.MyObject.Name, NextItem.MyObject.Name) = 0)) or (Assigned(PreviousItem) and Assigned(PreviousItem.MyObject) and (CompareText(Item.MyObject.Name, PreviousItem.MyObject.Name) = 0)) then WriteLiObject(Item.MyObject.Name + ' - ' + Item.MyUnit.Name + #32 + FLanguage.Translation[trUnit], Item.FullLink) else WriteLiObject(Item.MyObject.Name, Item.FullLink); end else begin WriteLiObject(Item.MyUnit.Name + #32 + FLanguage.Translation[trUnit], Item.FullLink); end; end; { ---------- } procedure CopyCiosRecursively(ADst: TPasItems; ACios: TPasItems); procedure AddRecursive(ACio: TPasCio); begin ADst.Add(ACio); ADst.CopyItems(ACio.Fields); ADst.CopyItems(ACio.Properties); ADst.CopyItems(ACio.Methods); ADst.CopyItems(ACio.Types); if ACio.Cios.Count > 0 then CopyCiosRecursively(ADst, ACio.Cios); end; var I: Integer; begin for I := 0 to ACios.Count - 1 do AddRecursive(TPasCio(ACios.PasItemAt[I])); end; { -------------------------------------------------------------------------- } var j, k, l: Integer; CurrentLevel, Level: Integer; PU: TPasUnit; c: TPasItems; Item, NextItem, PreviousItem: TPasItem; Item2: TPasCio; s, Text, Link: string; SL: TStringVector; Overview: TCreatedOverviewFile; begin { At this point, at least one unit has been parsed: Units is assigned and Units.Count > 0 No need to test this again. } if not CreateStream(ProjectName + '.hhc') then Exit; DoMessage(2, pmtInformation, 'Writing HtmlHelp Content file "' + ProjectName + '"...', []); // File Header WriteDirectLine('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">'); WriteDirectLine('<html>'); WriteDirectLine('<head>'); if not ExcludeGenerator then WriteDirect('<meta name="GENERATOR" content="' + PASDOC_NAME_AND_VERSION + '">', true); WriteDirectLine('</head><body>'); WriteDirectLine('<ul>'); DefaultContentsWritten := False; DefaultTopic := ''; if ContentsFile <> '' then begin SL := NewStringVector; try SL.LoadFromTextFileAdd(ContentsFile); except on e: Exception do DoMessage(1, pmtError, e.Message + '. Writing default HtmlHelp contents.', []); end; CurrentLevel := 0; for j := 0 to SL.Count - 1 do begin s := SL[j]; Text := BeforeEqualChar(s); Level := GetLevel(Text); Link := AfterEqualChar(s); if Level = CurrentLevel then ContentWriteCustom(Text, Link) else if CurrentLevel = (Level - 1) then begin WriteDirectLine('<ul>'); Inc(CurrentLevel); ContentWriteCustom(Text, Link) end else if CurrentLevel > Level then begin WriteDirectLine('</ul>'); Dec(CurrentLevel); while CurrentLevel > Level do begin WriteDirectLine('</ul>'); Dec(CurrentLevel); end; ContentWriteCustom(Text, Link) end else begin DoMessage(1, pmtError, 'Invalid level ' + IntToStr(Level) + 'in Content file (line ' + IntToStr(j) + ').', []); Exit; end; end; SL.Free; end; if not DefaultContentsWritten then begin ContentWriteIntroduction; ContentWriteUnits(''); ContentWriteClassHierarchy(FLanguage.Translation[trClassHierarchy]); ContentWriteClasses(''); ContentWriteOverview(''); ContentWriteLegend(''); ContentWriteGVClasses(); ContentWriteGVUses(); ContentWriteConclusion; end; // End of File WriteDirectLine('</ul>'); WriteDirectLine('</body></html>'); CloseStream; // Create Keyword Index // First collect all Items c := TPasItems.Create(False); // Don't free Items when freeing the container for j := 0 to Units.Count - 1 do begin PU := Units.UnitAt[j]; if Assigned(PU.CIOs) then CopyCiosRecursively(c, PU.CIOs); c.CopyItems(PU.Types); c.CopyItems(PU.Variables); c.CopyItems(PU.Constants); c.CopyItems(PU.FuncsProcs); end; if not CreateStream(ProjectName + '.hhk') then Exit; DoMessage(2, pmtInformation, 'Writing HtmlHelp Index file "%s"...', [ProjectName]); WriteDirectLine('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">'); WriteDirectLine('<html>'); WriteDirectLine('<head>'); if not ExcludeGenerator then WriteDirectLine('<meta name="GENERATOR" content="' + PASDOC_NAME_AND_VERSION + '">'); WriteDirectLine('</head><body>'); WriteDirectLine('<ul>'); // Write all Items to KeyWord Index c.SortShallow; if c.Count > 0 then begin Item := c.PasItemAt[0]; j := 1; while j < c.Count do begin NextItem := c.PasItemAt[j]; // Does the next Item have a different name? if CompareText(Item.Name, NextItem.Name) <> 0 then begin WriteLiObject(Item.Name, Item.FullLink); Item := NextItem; end else begin // Write the Item. It acts as a header for the subitems to follow. WriteLiObject(Item.Name, Item.FullLink); // Indent by one. WriteDirectLine('<ul>'); // No previous Item as we start. PreviousItem := nil; // Keep on writing Items with the same name as subitems. repeat IndexWriteItem(Item, PreviousItem, NextItem); PreviousItem := Item; Item := NextItem; Inc(j); if j >= c.Count then Break; NextItem := c.PasItemAt[j]; // Break as soon Items' names are different. until CompareText(Item.Name, NextItem.Name) <> 0; // No NextItem as we write the last one of the same Items. IndexWriteItem(Item, PreviousItem, nil); Item := NextItem; WriteDirectLine('</ul>'); end; Inc(j); end; // Don't forget to write the last item. Can it ever by nil? WriteLiObject(Item.Name, Item.FullLink); end; c.Free; WriteDirectLine('</ul>'); WriteDirectLine('</body></html>'); CloseStream; // Create a HTML Help Project File if not CreateStream(ProjectName + '.hhp') then Exit; DoMessage(3, pmtInformation, 'Writing Html Help Project file "%s"...', [ProjectName]); WriteDirectLine('[OPTIONS]'); WriteDirectLine('Binary TOC=Yes'); WriteDirectLine('Compatibility=1.1 or later'); WriteDirectLine('Compiled file=' + ProjectName + '.chm'); WriteDirectLine('Contents file=' + ProjectName + '.hhc'); WriteDirectLine('Default Window=Default'); WriteDirectLine('Default topic=' + DefaultTopic); WriteDirectLine('Display compile progress=Yes'); WriteDirectLine('Error log file=' + ProjectName + '.log'); WriteDirectLine('Full-text search=Yes'); WriteDirectLine('Index file=' + ProjectName + '.hhk'); if Title <> '' then WriteDirectLine('Title=' + Title) else WriteDirectLine('Title=' + ProjectName); WriteDirectLine(''); WriteDirectLine('[WINDOWS]'); if Title <> '' then WriteDirect('Default="' + Title + '","' + ProjectName + '.hhc","' + ProjectName + '.hhk",,,,,,,0x23520,,0x300e,,,,,,,,0', true) else WriteDirect('Default="' + ProjectName + '","' + ProjectName + '.hhc","' + ProjectName + '.hhk",,,,,,,0x23520,,0x300e,,,,,,,,0', true); WriteDirectLine(''); WriteDirectLine('[FILES]'); { HHC seems to know about the files by reading the Content and Index. So there is no need to specify them in the FILES section. } WriteDirectLine('Legend.html'); If Introduction <> nil then begin WriteDirectLine(Introduction.FullLink); end; if (LinkGraphVizClasses <> '') then WriteDirectLine(OverviewFilesInfo[ofGraphVizClasses].BaseFileName + '.' + LinkGraphVizClasses); if LinkGraphVizUses <> '' then WriteDirectLine(OverviewFilesInfo[ofGraphVizUses].BaseFileName + '.' + LinkGraphVizUses); for Overview := LowCreatedOverviewFile to HighCreatedOverviewFile do WriteDirectLine(OverviewFilesInfo[Overview].BaseFileName + '.html'); if Assigned(Units) then for k := 0 to units.Count - 1 do begin Item := units.PasItemAt[k]; PU := TPasUnit(units.PasItemAt[k]); WriteDirectLine(Item.FullLink); c := PU.CIOs; if Assigned(c) then for l := 0 to c.Count - 1 do begin Item2 := TPasCio(c.PasItemAt[l]); WriteDirectLine(Item2.OutputFilename); end; end; If Conclusion <> nil then begin WriteDirectLine(Conclusion.FullLink); end; WriteDirectLine(''); WriteDirectLine('[INFOTYPES]'); WriteDirectLine(''); WriteDirectLine('[MERGE FILES]'); CloseStream; end; end.�������������������������pasdoc/source/component/PasDoc_Reg.pas��������������������������������������������������������������0000600�0001750�0001750�00000003007�13237143042�020437� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Registers the PasDoc components into the IDE. ) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Michalis Kamburelis) TODO: We have some properties in TPasDoc and generators components that should be registered with filename editors. } unit PasDoc_Reg; {$I pasdoc_defines.inc} interface { Registers the PasDoc components into the IDE. } procedure Register; implementation uses Classes, PasDoc_Base, PasDoc_GenHtml, PasDoc_GenLatex, PasDoc_GenHtmlHelp; procedure Register; begin RegisterComponents('PasDoc', [TPasDoc, THTMLDocGenerator, TTexDocGenerator, THTMLHelpDocGenerator]); end; end. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Tokenizer.pas��������������������������������������������������������0000644�0001750�0001750�00000104225�13237143042�021710� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>) @abstract(Simple Pascal tokenizer.) The @link(TTokenizer) object creates @link(TToken) objects (tokens) for the Pascal programming language from a character input stream. The @link(PasDoc_Scanner) unit does the same (it actually uses this unit's tokenizer), with the exception that it evaluates compiler directives, which are comments that start with a dollar sign. } unit PasDoc_Tokenizer; {$I pasdoc_defines.inc} interface uses {$IFDEF MSWINDOWS} Windows, {$ENDIF} Classes, PasDoc_Utils, PasDoc_Types, PasDoc_StreamUtils; type { enumeration type that provides all types of tokens; each token's name starts with TOK_. TOK_DIRECTIVE is a compiler directive (like $ifdef, $define). Note that tokenizer is not able to tell whether you used standard directive (e.g. 'Register') as an identifier (e.g. you're declaring procedure named 'Register') or as a real standard directive (e.g. a calling specifier 'register'). So there is @italic(no) value like TOK_STANDARD_DIRECTIVE here, standard directives are always reported as TOK_IDENTIFIER. You can check TToken.Info.StandardDirective to know whether this identifier is @italic(maybe) used as real standard directive. } TTokenType = (TOK_WHITESPACE, TOK_COMMENT_PAS, TOK_COMMENT_EXT, TOK_COMMENT_HELPINSIGHT, TOK_COMMENT_CSTYLE, TOK_IDENTIFIER, TOK_NUMBER, TOK_STRING, TOK_SYMBOL, TOK_DIRECTIVE, TOK_KEYWORD, TOK_ATT_ASSEMBLER_REGISTER); type TKeyword = ( KEY_INVALIDKEYWORD, KEY_AND, KEY_ARRAY, KEY_AS, KEY_ASM, KEY_BEGIN, KEY_CASE, KEY_CLASS, KEY_CONST, KEY_CONSTRUCTOR, KEY_DESTRUCTOR, KEY_DISPINTERFACE, KEY_DIV, KEY_DO, KEY_DOWNTO, KEY_ELSE, KEY_END, KEY_EXCEPT, KEY_EXPORTS, KEY_FILE, KEY_FINALIZATION, KEY_FINALLY, KEY_FOR, KEY_FUNCTION, KEY_GOTO, KEY_IF, KEY_IMPLEMENTATION, KEY_IN, KEY_INHERITED, KEY_INITIALIZATION, KEY_INLINE, KEY_INTERFACE, KEY_IS, KEY_LABEL, KEY_LIBRARY, KEY_MOD, KEY_NIL, KEY_NOT, KEY_OBJECT, KEY_OF, KEY_ON, KEY_OR, KEY_PACKED, KEY_PROCEDURE, KEY_PROGRAM, KEY_PROPERTY, KEY_RAISE, KEY_RECORD, KEY_REPEAT, KEY_RESOURCESTRING, KEY_SET, KEY_SHL, KEY_SHR, KEY_STRING, KEY_THEN, KEY_THREADVAR, KEY_TO, KEY_TRY, KEY_TYPE, KEY_UNIT, KEY_UNTIL, KEY_USES, KEY_VAR, KEY_WHILE, KEY_WITH, KEY_XOR); TStandardDirective = ( SD_INVALIDSTANDARDDIRECTIVE, SD_ABSOLUTE, SD_ABSTRACT, SD_APIENTRY, SD_ASSEMBLER, SD_AUTOMATED, SD_CDECL, SD_CVAR, SD_DEFAULT, SD_DISPID, SD_DYNAMIC, SD_EXPERIMENTAL, SD_EXPORT, SD_EXTERNAL, SD_FAR, SD_FORWARD, SD_GENERIC, SD_HELPER, SD_INDEX, SD_INLINE, SD_MESSAGE, SD_NAME, SD_NEAR, SD_NODEFAULT, SD_OPERATOR, SD_OUT, SD_OVERLOAD, SD_OVERRIDE, SD_PASCAL, SD_PRIVATE, SD_PROTECTED, SD_PUBLIC, SD_PUBLISHED, SD_READ, SD_REFERENCE, SD_REGISTER, SD_REINTRODUCE, SD_RESIDENT, SD_SEALED, SD_SPECIALIZE, SD_STATIC, SD_STDCALL, SD_STORED, SD_STRICT, SD_VIRTUAL, SD_WRITE, SD_DEPRECATED, SD_SAFECALL, SD_PLATFORM, SD_VARARGS, SD_FINAL); const { Names of the token types. All start with lower letter. They should somehow describe (in a few short words) given TTokenType. } TOKEN_TYPE_NAMES: array[TTokenType] of string = ( 'whitespace', 'comment ((**)-style)', 'comment ({}-style)', 'comment (///-style)', 'comment (//-style)', 'identifier', 'number', 'string', 'symbol', 'directive', 'reserved word', 'AT&T assembler register name'); TokenCommentTypes: set of TTokenType = [ TOK_COMMENT_PAS, TOK_COMMENT_EXT, TOK_COMMENT_HELPINSIGHT, TOK_COMMENT_CSTYLE ]; type { enumeration type that provides all types of symbols; each symbol's name starts with SYM_ } TSymbolType = (SYM_PLUS, SYM_MINUS, SYM_ASTERISK, SYM_SLASH, SYM_EQUAL, SYM_LESS_THAN, SYM_LESS_THAN_EQUAL, SYM_GREATER_THAN, SYM_GREATER_THAN_EQUAL, SYM_LEFT_BRACKET, SYM_RIGHT_BRACKET, SYM_COMMA, SYM_LEFT_PARENTHESIS, SYM_RIGHT_PARENTHESIS, SYM_COLON, SYM_SEMICOLON, SYM_ROOF, SYM_PERIOD, SYM_AT, SYM_DOLLAR, SYM_ASSIGN, SYM_RANGE, SYM_POWER, { SYM_BACKSLASH may occur when writing char constant "^\", see ../../tests/ok_caret_character.pas } SYM_BACKSLASH); const { Symbols as strings. They can be useful to have some mapping TSymbolType -> string, but remember that actually some symbols in tokenizer have multiple possible representations, e.g. "right bracket" is usually given as "]" but can also be written as ".)". } SymbolNames: array[TSymbolType] of string = ( '+', '-', '*', '/', '=', '<', '<=', '>', '>=', '[', ']', ',', '(', ')', ':', ';', '^', '.', '@', '$', ':=', '..', '**', '\' ); type { Stores the exact type and additional information on one token. } TToken = class(TObject) private FEndPosition: Int64; FBeginPosition: Int64; FStreamName: string; public { the exact character representation of this token as it was found in the input file } Data: string; { the type of this token as @link(TTokenType) } MyType: TTokenType; { additional information on this token as a variant record depending on the token's MyType } Info: record case TTokenType of TOK_SYMBOL: (SymbolType: TSymbolType); TOK_KEYWORD: (KeyWord: TKeyWord); TOK_IDENTIFIER: (StandardDirective: TStandardDirective); end; { Contents of a comment token. This is defined only when MyType is in TokenCommentTypes or is TOK_DIRECTIVE. This is the text within the comment @italic(without) comment delimiters. For TOK_DIRECTIVE you can safely assume that CommentContent[1] = '$'. } CommentContent: string; { Contents of the string token, that is: the value of the string literal. D only when MyType is TOK_STRING. } StringContent: string; { Create a token of and assign the argument token type to @link(MyType) } constructor Create(const TT: TTokenType); function GetTypeName: string; { Does @link(MyType) is TOK_SYMBOL and Info.SymbolType is ASymbolType ? } function IsSymbol(const ASymbolType: TSymbolType): Boolean; { Does @link(MyType) is TOK_KEYWORD and Info.KeyWord is AKeyWord ? } function IsKeyWord(const AKeyWord: TKeyWord): Boolean; { Does @link(MyType) is TOK_IDENTIFIER and Info.StandardDirective is AStandardDirective ? } function IsStandardDirective( const AStandardDirective: TStandardDirective): Boolean; { Few words long description of this token. Describes MyType and Data (for those tokens that tend to have short Data). Starts with lower letter. } function Description: string; // @name is the name of the TStream from which this @classname was read. // It is currently used to set @link(TRawDescriptionInfo.StreamName). property StreamName: string read FStreamName; // @name is the position in the stream of the start of the token. // It is currently used to set @link(TRawDescriptionInfo.BeginPosition). property BeginPosition: Int64 read FBeginPosition; // @name is the position in the stream of the character immediately // after the end of the token. // It is currently used to set @link(TRawDescriptionInfo.EndPosition). property EndPosition: Int64 read FEndPosition; end; { @abstract(Converts an input TStream to a sequence of @link(TToken) objects.) } TTokenizer = class(TObject) private FBufferedCharSize : Integer; function StreamPosition: Int64; protected FOnMessage: TPasDocMessageEvent; FVerbosity: Cardinal; { if @link(IsCharBuffered) is true, this field contains the buffered character } BufferedChar: Char; { true if end of stream @link(Stream) has been reached, false otherwise } EOS: Boolean; { if this is true, @link(BufferedChar) contains a buffered character; the next call to @link(GetChar) or @link(PeekChar) will return this character, not the next in the associated stream @link(Stream) } IsCharBuffered: Boolean; { current row in stream @link(Stream); useful when giving error messages } Row: Integer; { the input stream this tokenizer is working on } Stream: TStream; FStreamName: string; FStreamPath: string; procedure DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); procedure DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); procedure CheckForDirective(const t: TToken); procedure ConsumeChar; function CreateSymbolToken(const st: TSymbolType; const s: string): TToken; overload; { Uses default symbol representation, from SymbolNames[st] } function CreateSymbolToken(const st: TSymbolType): TToken; overload; {$IFDEF STRING_UNICODE} { Returns source codepoint size in bytes on success or 0 on failure. } { Supports ANSI, UTF-8, UCS2 and UCS2 big endian sources. } { Note that only Unicode codepoints from the BMP are supported. } function GetChar(out c: WideChar): Integer; {$ELSE} { Returns 1 on success or 0 on failure } function GetChar(out c: AnsiChar): Integer; {$ENDIF} function PeekChar(out c: Char): Boolean; function ReadCommentType1: TToken; function ReadCommentType2: TToken; function ReadCommentType3: TToken; function ReadAttAssemblerRegister: TToken; function ReadLiteralString(var t: TToken): Boolean; function ReadToken(c: Char; const s: TCharSet; const TT: TTokenType; var t: TToken): Boolean; public { Creates a TTokenizer and associates it with given input TStream. Note that AStream will be freed when this object will be freed. } constructor Create( const AStream: TStream; const OnMessageEvent: TPasDocMessageEvent; const VerbosityLevel: Cardinal; const AStreamName, AStreamPath: string); { Releases all dynamically allocated memory. } destructor Destroy; override; function HasData: Boolean; function GetStreamInfo: string; function GetToken: TToken; { Skips all chars until it encounters either $ELSE or $ENDIF compiler defines. } function SkipUntilCompilerDirective: TToken; property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; property Verbosity: Cardinal read FVerbosity write FVerbosity; property StreamName: string read FStreamName; { This is the path where the underlying file of this stream is located. It may be an absolute path or a relative path. Relative paths are always resolved vs pasdoc current directory. This way user can give relative paths in command-line when writing Pascal source filenames to parse. In particular, this may be '' to indicate current dir. It's always specified like it was processed by IncludeTrailingPathDelimiter, so it has trailing PathDelim included (unless it was '', in which case it remains empty). } property StreamPath: string read FStreamPath; end; const { all Object Pascal keywords } KeyWordArray: array[Low(TKeyword)..High(TKeyword)] of string = ('x', // lowercase never matches 'AND', 'ARRAY', 'AS', 'ASM', 'BEGIN', 'CASE', 'CLASS', 'CONST', 'CONSTRUCTOR', 'DESTRUCTOR', 'DISPINTERFACE', 'DIV', 'DO', 'DOWNTO', 'ELSE', 'END', 'EXCEPT', 'EXPORTS', 'FILE', 'FINALIZATION', 'FINALLY', 'FOR', 'FUNCTION', 'GOTO', 'IF', 'IMPLEMENTATION', 'IN', 'INHERITED', 'INITIALIZATION', 'INLINE', 'INTERFACE', 'IS', 'LABEL', 'LIBRARY', 'MOD', 'NIL', 'NOT', 'OBJECT', 'OF', 'ON', 'OR', 'PACKED', 'PROCEDURE', 'PROGRAM', 'PROPERTY', 'RAISE', 'RECORD', 'REPEAT', 'RESOURCESTRING', 'SET', 'SHL', 'SHR', 'STRING', 'THEN', 'THREADVAR', 'TO', 'TRY', 'TYPE', 'UNIT', 'UNTIL', 'USES', 'VAR', 'WHILE', 'WITH', 'XOR'); { Object Pascal directives } StandardDirectiveArray: array[Low(TStandardDirective)..High(TStandardDirective)] of PChar = ('x', // lowercase letters never match 'ABSOLUTE', 'ABSTRACT', 'APIENTRY', 'ASSEMBLER', 'AUTOMATED', 'CDECL', 'CVAR', 'DEFAULT', 'DISPID', 'DYNAMIC', 'EXPERIMENTAL', 'EXPORT', 'EXTERNAL', 'FAR', 'FORWARD', 'GENERIC', 'HELPER', 'INDEX', 'INLINE', 'MESSAGE', 'NAME', 'NEAR', 'NODEFAULT', 'OPERATOR', 'OUT', 'OVERLOAD', 'OVERRIDE', 'PASCAL', 'PRIVATE', 'PROTECTED', 'PUBLIC', 'PUBLISHED', 'READ', 'REFERENCE', 'REGISTER', 'REINTRODUCE', 'RESIDENT', 'SEALED', 'SPECIALIZE', 'STATIC', 'STDCALL', 'STORED', 'STRICT', 'VIRTUAL', 'WRITE', 'DEPRECATED', 'SAFECALL', 'PLATFORM', 'VARARGS', 'FINAL'); { Checks is Name (case ignored) some Pascal keyword. Returns SD_INVALIDSTANDARDDIRECTIVE if not. } function StandardDirectiveByName(const Name: string): TStandardDirective; { Checks is Name (case ignored) some Pascal standard directive. Returns KEY_INVALIDKEYWORD if not. } function KeyWordByName(const Name: string): TKeyword; implementation uses SysUtils; function KeyWordByName(const Name: string): TKeyword; var LName: string; i: TKeyword; begin LName := UpperCase(Name); Result := KEY_INVALIDKEYWORD; for i := Low(TKeyword) to High(TKeyword) do begin if LName = KeyWordArray[i] then begin Result := i; break; end; end; end; function StandardDirectiveByName(const Name: string): TStandardDirective; var LName: string; i: TStandardDirective; begin LName := UpperCase(Name); Result := SD_INVALIDSTANDARDDIRECTIVE; for i := Low(TStandardDirective) to High(TStandardDirective) do begin if LName = StandardDirectiveArray[i] then begin Result := i; break; end; end; end; const Whitespace = [#9, #10, #13, ' ']; Letters = ['A'..'Z', 'a'..'z']; DecimalDigits = ['0'..'9']; HexadecimalDigits = DecimalDigits + ['A'..'F', 'a'..'f']; IdentifierStart = ['_'] + Letters; IdentifierOther = IdentifierStart + DecimalDigits; CharOther = HexadecimalDigits + ['$']; NumberStart = DecimalDigits + ['$']; NumberOther = HexadecimalDigits + ['.', '+', '-']; QuoteChar = ''''; NUM_SINGLE_CHAR_SYMBOLS = 10; SingleCharSymbols: array[0..NUM_SINGLE_CHAR_SYMBOLS - 1] of record c: Char; s: TSymbolType; end = ((c: ';'; s: SYM_SEMICOLON), (c: ','; s: SYM_COMMA), (c: '['; s: SYM_LEFT_BRACKET), (c: ']'; s: SYM_RIGHT_BRACKET), (c: '+'; s: SYM_PLUS), (c: '-'; s: SYM_MINUS), (c: '*'; s: SYM_ASTERISK), (c: '='; s: SYM_EQUAL), (c: '^'; s: SYM_ROOF), (c: '@'; s: SYM_AT)); { ---------------------------------------------------------------------------- } { TToken } { ---------------------------------------------------------------------------- } constructor TToken.Create(const TT: TTokenType); begin inherited Create; MyType := TT; end; { ---------------------------------------------------------------------------- } function TToken.GetTypeName: string; begin GetTypeName := TOKEN_TYPE_NAMES[MyType]; end; { ---------------------------------------------------------------------------- } function TToken.IsSymbol(const ASymbolType: TSymbolType): Boolean; begin Result := (MyType = TOK_SYMBOL) and (Info.SymbolType = ASymbolType); end; function TToken.IsKeyWord(const AKeyWord: TKeyWord): Boolean; begin Result := (MyType = TOK_KEYWORD) and (Info.KeyWord = AKeyWord); end; function TToken.IsStandardDirective( const AStandardDirective: TStandardDirective): Boolean; begin Result := (MyType = TOK_IDENTIFIER) and (Info.StandardDirective = AStandardDirective); end; function TToken.Description: string; begin Result := TOKEN_TYPE_NAMES[MyType]; if MyType in [TOK_SYMBOL, TOK_KEYWORD, TOK_IDENTIFIER] then Result := Result + ' "' + Data + '"'; end; { ---------------------------------------------------------------------------- } { TTokenizer } { ---------------------------------------------------------------------------- } constructor TTokenizer.Create( const AStream: TStream; const OnMessageEvent: TPasDocMessageEvent; const VerbosityLevel: Cardinal; const AStreamName, AStreamPath: string); begin inherited Create; FOnMessage := OnMessageEvent; FVerbosity := VerbosityLevel; Row := 1; Stream := AStream; FStreamName := AStreamName; FStreamPath := AStreamPath; end; { ---------------------------------------------------------------------------- } destructor TTokenizer.Destroy; begin Stream.Free; inherited; end; { ---------------------------------------------------------------------------- } procedure TTokenizer.CheckForDirective(const t: TToken); begin if SCharIs(T.CommentContent, 1, '$') then t.MyType := TOK_DIRECTIVE; end; { ---------------------------------------------------------------------------- } procedure TTokenizer.ConsumeChar; begin IsCharBuffered := False; end; { ---------------------------------------------------------------------------- } function TTokenizer.CreateSymbolToken(const st: TSymbolType; const s: string): TToken; begin Result := TToken.Create(TOK_SYMBOL); with Result do begin Info.SymbolType := st; Data := s; end; end; function TTokenizer.CreateSymbolToken(const st: TSymbolType): TToken; begin Result := CreateSymbolToken(st, SymbolNames[st]); end; { ---------------------------------------------------------------------------- } procedure TTokenizer.DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); begin raise EPasDoc.Create(AMessage + Format(' (at %s)', [GetStreamInfo]), AArguments, AExitCode); end; { ---------------------------------------------------------------------------- } procedure TTokenizer.DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if (AVerbosity < FVerbosity) and Assigned(FOnMessage) then FOnMessage(MessageType, Format(AMessage, AArguments), AVerbosity); end; { ---------------------------------------------------------------------------- } {$IFDEF STRING_UNICODE} function TTokenizer.GetChar(out c: WideChar): Integer; const LDefaultFailChar = '?'; var Buf : array [0..7] of Byte; LInt: Integer; begin if IsCharBuffered then begin c := BufferedChar; IsCharBuffered := False; Result := FBufferedCharSize; end else begin // Actually only UCS2 and UCS2Be case TStreamReader(Stream).CurrentCodePage of CP_UTF16 : begin Result := Stream.Read(c, 2); Exit; end; CP_UTF16BE : begin Result := Stream.Read(c, 2); Swap16Buf(@c, @c, 1); Exit; end; end; // case { MBCS text } Result := 0; Buf[0] := 0; Result := Stream.Read(Buf[Result], 1); if Result = 0 then Exit; if TStreamReader(Stream).CurrentCodePage = CP_UTF8 then begin LInt := Utf8Size(Buf[0]); // Read number of bytes if LInt > 1 then begin Inc(Result, Stream.Read(Buf[Result], LInt -1)); if Result <> LInt then begin c := LDefaultFailChar; // return the default fail char. Exit; end; end; end else begin { Only DBCS have constant LeadBytes so we actually do not support } { some rarely used MBCS, such as euc-jp or UTF-7, with a maximum } { codepoint size > 2 bytes. }{ AG } if AnsiChar(Buf[0]) in TStreamReader(Stream).LeadBytes then begin if Stream.Read(Buf[Result], 1) = 1 then Inc(Result) else begin Result := 0; Exit; end; end end; if (Result = 1) and (Buf[0] < 128) then c := WideChar(Buf[0]) // Plain ASCII, no need to call MbToWc (speed) else if MultiByteToWideChar(TStreamReader(Stream).CurrentCodePage, 0, @Buf[0], Result, @c, 1) <> 1 then c := LDefaultFailChar; // return the default fail char. end; end; {$ELSE} function TTokenizer.GetChar(out c: AnsiChar): Integer; begin if IsCharBuffered then begin c := BufferedChar; IsCharBuffered := False; Result := FBufferedCharSize; end else Result := Stream.Read(c, 1); end; {$ENDIF} { ---------------------------------------------------------------------------- } function TTokenizer.GetStreamInfo: string; begin GetStreamInfo := FStreamName + '(' + IntToStr(Row) + ')'; end; { ---------------------------------------------------------------------------- } function TTokenizer.HasData: Boolean; begin HasData := IsCharBuffered or (Stream.Position < Stream.Size); end; { ---------------------------------------------------------------------------- } function TTokenizer.StreamPosition: Int64; begin if IsCharBuffered then Result := Stream.Position - FBufferedCharSize else Result := Stream.Position; end; { ---------------------------------------------------------------------------- } function TTokenizer.GetToken: TToken; var c: Char; MaybeKeyword: TKeyword; s: string; J: Integer; BeginPosition: integer; begin Result := nil; BeginPosition := StreamPosition; //used in finally try if GetChar(c) = 0 then DoError('Tokenizer: could not read character', [], 0); if IsCharInSet(c, Whitespace) then begin if ReadToken(c, Whitespace, TOK_WHITESPACE, Result) then { after successful reading all whitespace characters, update internal row counter to be able to state current row on errors; TODO: will fail on Mac files (row is 13) } Inc(Row, StrCountCharA(Result.Data, #10)) else DoError('Tokenizer: could not read character', [], 0); end else if IsCharInSet(c, IdentifierStart) then begin if ReadToken(c, IdentifierOther, TOK_IDENTIFIER, Result) then begin s := Result.Data; { check if identifier is a keyword } MaybeKeyword := KeyWordByName(s); if (MaybeKeyword <> KEY_INVALIDKEYWORD) then begin Result.MyType := TOK_KEYWORD; Result.Info.KeyWord := MaybeKeyword; end else begin { calculate Result.Info.StandardDirective } Result.Info.StandardDirective := StandardDirectiveByName(s); end; end; end else if IsCharInSet(c, NumberStart) then ReadToken(c, NumberOther, TOK_NUMBER, Result) else case c of QuoteChar: ReadLiteralString(Result); '#': if ReadToken(c, CharOther, TOK_STRING, Result) then begin try { Note that StrToInt automatically handles hex characters when number starts from $. So below will automatically work for them. } Result.StringContent := Chr(StrToInt(SEnding(Result.Data, 2))); except { In case of EConvertError, make a warning and continue. Result.StringContent will remain empty, which isn't a real problem. } on E: EConvertError do DoMessage(2, pmtWarning, 'Cannot convert string character code to int: %s', [Result.Data]); end; end; '{': begin Result := ReadCommentType1; CheckForDirective(Result); end; '(': begin c := ' '; if HasData and not PeekChar(c) then DoError('Tokenizer: could not read character', [], 0); case c of '*': begin ConsumeChar; Result := ReadCommentType2; CheckForDirective(Result); end; '.': begin ConsumeChar; Result := CreateSymbolToken(SYM_LEFT_BRACKET, '(.'); end; else Result := CreateSymbolToken(SYM_LEFT_PARENTHESIS); end; end; ')': begin c := ' '; Result := CreateSymbolToken(SYM_RIGHT_PARENTHESIS); end; '.': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '.': begin ConsumeChar; Result := CreateSymbolToken(SYM_RANGE); end; ')': begin ConsumeChar; Result := CreateSymbolToken(SYM_RIGHT_BRACKET, '.)'); end; else Result := CreateSymbolToken(SYM_PERIOD); end; end; '/': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '/': begin ConsumeChar; Result := ReadCommentType3; end; else Result := CreateSymbolToken(SYM_SLASH); end; end; ':': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '=': begin ConsumeChar; Result := CreateSymbolToken(SYM_ASSIGN); end; else Result := CreateSymbolToken(SYM_COLON); end; end; '<': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '=': begin ConsumeChar; Result := CreateSymbolToken(SYM_LESS_THAN_EQUAL); end; else Result := CreateSymbolToken(SYM_LESS_THAN); end; end; '>': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '=': begin ConsumeChar; Result := CreateSymbolToken(SYM_GREATER_THAN_EQUAL); end; else Result := CreateSymbolToken(SYM_GREATER_THAN); end; end; '*': begin c := ' '; if HasData and (not PeekChar(c)) then Exit; case c of '*': begin ConsumeChar; Result := CreateSymbolToken(SYM_POWER); end; else Result := CreateSymbolToken(SYM_ASTERISK); end; end; '\': Result := CreateSymbolToken(SYM_BACKSLASH); '%': Result := ReadAttAssemblerRegister; else begin for J := 0 to NUM_SINGLE_CHAR_SYMBOLS - 1 do begin if (c = SingleCharSymbols[J].c) then begin Result := CreateSymbolToken(SingleCharSymbols[J].s, c); exit; end; end; DoError('Invalid character (code %d) in Pascal input stream', [Ord(C)], 0); end; end; finally if Result <> nil then begin Result.FStreamName := StreamName; Result.FBeginPosition := BeginPosition; Result.FEndPosition := StreamPosition; end; end; end; { ---------------------------------------------------------------------------- } function TTokenizer.PeekChar(out c: Char): Boolean; begin if IsCharBuffered then begin c := BufferedChar; Result := True; end else begin FBufferedCharSize := GetChar(c); if FBufferedCharSize > 0 then begin BufferedChar := c; IsCharBuffered := True; Result := True; end else begin EOS := True; PeekChar := False; end; end; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadCommentType1: TToken; var c: Char; begin Result := TToken.Create(TOK_COMMENT_EXT); with Result do begin CommentContent := ''; repeat if not HasData or (GetChar(c) = 0) then Exit; if c = #10 then Inc(Row); CommentContent := CommentContent + c; // TODO: Speed up! until c = '}'; Data := '{' + CommentContent; (* Remove last '}' from CommentContent *) SetLength(CommentContent, Length(CommentContent) - 1); end; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadCommentType2: TToken; var c: Char; begin Result := TToken.Create(TOK_COMMENT_PAS); Result.CommentContent := ''; if not HasData or (GetChar(c) = 0) then Exit; repeat Result.CommentContent := Result.CommentContent + c; if c <> '*' then begin if c = #10 then Inc(Row); if not HasData or (GetChar(c) = 0) then Exit; end else begin if not HasData or (GetChar(c) = 0) then Exit; if c = ')' then begin ConsumeChar; Result.Data := '(*' + Result.CommentContent + ')'; { Remove last '*' from Result.CommentContent } SetLength(Result.CommentContent, Length(Result.CommentContent) - 1); Break; end; end; until False; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadCommentType3: TToken; var c: Char; pos: Integer; Prefix: string; begin Result := TToken.Create(TOK_COMMENT_CSTYLE); with Result do begin CommentContent := ''; pos := 0; Prefix := '//'; while HasData and (GetChar(c) > 0) do begin case c of #10: begin Inc(Row); break end; #13: break; else if (c = '/') and (pos = 0) then begin MyType := TOK_COMMENT_HELPINSIGHT; Prefix := '///'; end else CommentContent := CommentContent + c; end; Inc(pos); end; Data := Prefix + CommentContent; end; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadAttAssemblerRegister: TToken; var C: char; begin Result := TToken.Create(TOK_ATT_ASSEMBLER_REGISTER); Result.Data := '%'; repeat if (not HasData) or (not PeekChar(C)) then Exit; if IsCharInSet(C, ['a'..'z', 'A'..'Z', '0'..'9']) then begin GetChar(C); Result.Data := Result.Data + C; end else Break; until false; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadLiteralString(var t: TToken): Boolean; procedure ReleaseToken; begin t.Free; t := nil; end; var c: Char; Finished: Boolean; begin Finished := False; t := TToken.Create(TOK_STRING); t.Data := ''''; repeat if not (Stream.Position < Stream.Size) then begin ReleaseToken; DoError('Tokenizer: unexpected end of stream', [], 0); end; if GetChar(c) = 0 then begin ReleaseToken; DoError('Tokenizer: could not read character', [], 0); end; if c = QuoteChar then begin if not PeekChar(c) then begin ReleaseToken; DoError('Tokenizer: could not peek character', [], 0) end; if c = QuoteChar then { escaped single quote within string } begin ConsumeChar; t.Data := t.Data + QuoteChar; end else { end of string } begin Finished := True; end; t.Data := t.Data + QuoteChar; end else begin t.Data := t.Data + c; end; { Note that, because of logic above, this will append only ONE apostrophe when reading two apostrophes in source code. Checking Finished prevents adding the ending apostrophe. } if not Finished then T.StringContent := T.StringContent + c; until Finished; ReadLiteralString := True; end; { ---------------------------------------------------------------------------- } function TTokenizer.ReadToken(c: Char; const s: TCharSet; const TT: TTokenType; var t: TToken): Boolean; begin Assert(t=nil); Result := False; t := TToken.Create(TT); t.Data := c; repeat if not PeekChar(c) then begin if EOS then Result := True else begin t.Free; t := nil; end; break; end; if IsCharInSet(c, s) then begin t.Data := t.Data + c; ConsumeChar; end else begin Result := True; break; end; until False; if Result then begin Assert(Assigned(t)); end else begin Assert(not Assigned(t)); end; end; function TTokenizer.SkipUntilCompilerDirective: TToken; var c: Char; begin Result := nil; repeat if GetChar(c) > 0 then case c of '{': begin Result := ReadCommentType1; CheckForDirective(Result); if Result.MyType = TOK_DIRECTIVE then break; FreeAndNil(Result); end; '(': begin if PeekChar(c) and (c = '*') then begin ConsumeChar; Result := ReadCommentType2; CheckForDirective(Result); if Result.MyType = TOK_DIRECTIVE then break; FreeAndNil(Result); end; (* If C was not a '*', then we don't consume it here. This is important, because C could be #10 (indicates newline, so we must Inc(Row)) or even '{' (which could indicate compiler directive). And sequences like '('#10 and '({$ifdef ...' should work, see ../../tests/error_line_number_3.pas and ../../tests/ok_not_defined_omit.pas *) end; #10: Inc(Row); end else DoError('Could not read character', [], 0); until False; end; end. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Languages.pas��������������������������������������������������������0000644�0001750�0001750�00000050207�13237143042�021644� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(PasDoc language definitions and translations.) @author(Johannes Berg <johannes AT sipsolutions.de>) @author(Ralf Junker <delphi AT zeitungsjunge.de>) @author(Andrew Andreev <andrew AT alteragate.net> (Bulgarian translation)) @author(Alexander Lisnevsky <alisnevsky AT yandex.ru> (Russian translation)) @author(Hendy Irawan <ceefour AT gauldong.net> (Indonesian and Javanese translation)) @author(Ivan Montes Velencoso (Catalan and Spanish translations)) @author(Javi (Spanish translation)) @author(Jean Dit Bailleul (Frensh translation)) @author(Marc Weustinks (Dutch translation)) @author(Martin Hansen <mh AT geus.dk> (Danish translation)) @author(Michele Bersini <michele.bersini AT smartit.it> (Italian translation)) @author(Peter imkovi <simkovic_jr AT manal.sk> (Slovak translation)) @author(Peter Thrnqvist <pt AT timemetrics.se> (Swedish translation)) @author(Rodrigo Urubatan Ferreira Jardim <rodrigo AT netscape.net> (Brasilian translation)) @author(Alexandre da Silva <simpsomboy AT gmail.com> (Brasilian translation - Update)) @author(Alexsander da Rosa <alex AT rednaxel.com> (Brasilian translation - UTF8)) @author(Vitaly Kovalenko <v_l_kovalenko AT alsy.by> (Russian translation)) @author(Grzegorz Skoczylas <gskoczylas AT rekord.pl> (corrected Polish translation)) @author(Jns Gerg <jonas.gergo AT ch...> (Hungarian translation)) @author(Michalis Kamburelis) @author(Ascanio Pressato (Some Italian translation)) @author(JBarbero Quiter (updated Spanish translation)) @author(Liu Chuanjun <1000copy AT gmail.com> (Chinese gb2312 translation)) @author(Liu Da <xmacmail AT gmail.com> (Chinese gb2312 translation)) @author(DoDi) @author(Ren Mihula <rene.mihula@gmail.com> (Czech translation)) @author(Yann Merignac (French translation)) @author(Arno Garrels <first name.name@nospamgmx.de>) } unit PasDoc_Languages; {$I pasdoc_defines.inc} interface type { An enumeration type of all supported languages } {$IFDEF STRING_UNICODE} TLanguageID = ( lgBosnian, lgBrazilian, lgBulgarian, lgCatalan, lgChinese, lgCroatian, lgDanish, lgDutch, lgEnglish, lgFrench, lgGerman, lgIndonesian, lgItalian, lgJavanese, lgPolish, lgRussian, lgSlovak, lgSpanish, lgSwedish, lgHungarian, lgCzech ); {$ELSE} TLanguageID = ( lgBosnian, lgBrazilian_1252, lgBrazilian_utf8, lgBulgarian, lgCatalan, lgChinese_gb2312, lgCroatian, lgDanish, lgDutch, lgEnglish, lgFrench_ISO_8859_15, lgFrench_UTF_8, lgGerman, lgIndonesian, lgItalian, lgJavanese, lgPolish_CP1250, lgPolish_ISO_8859_2, lgRussian_1251, lgRussian_utf8, lgRussian_866, lgRussian_koi8, lgSlovak, lgSpanish, lgSwedish, lgHungarian_1250, lgCzech_CP1250, lgCzech_ISO_8859_2 ); {$ENDIF} { An enumeration type of all static output texts. Warning: count and order changed! } TTranslationID = ( //no translation ID assigned, so far trNoTrans, //the language name (English, ASCII), e.g. for file names. trLanguage, //map trUnits, trClassHierarchy, trCio, trInternalCR, trInternalTypes, trIdentifiers, trGvUses, trGvClasses, //tables and members trClasses, trClass, trDispInterface, trInterface, trObjects, trObject, trRecord, trPacked, trHierarchy, trFields, trMethods, trProperties, trLibrary, trPackage, trProgram, trUnit, trUses, trConstants, trFunctionsAndProcedures, trTypes, trType, trVariables, trAuthors, trAuthor, trCreated, trLastModified, trSubroutine, trParameters, trReturns, trExceptionsRaised, trExceptions, trException, trEnum, //visibilities trVisibility, trPrivate, trStrictPrivate, trProtected, trStrictProtected, trPublic, trPublished, trAutomated, trImplicit, //hints trDeprecated, trPlatformSpecific, trLibrarySpecific, trExperimental, //headings trOverview, trIntroduction, trConclusion, trEnclosingClass, trHeadlineCio, trHeadlineConstants, trHeadlineFunctionsAndProcedures, trHeadlineIdentifiers, trHeadlineTypes, trHeadlineUnits, trHeadlineVariables, trSummaryCio, //column headings trDeclaration, trDescription, //<as column OR section heading! trDescriptions, //<section heading for detailed descriptions trName, trValues, //empty tables trNone, trNoCIOs, trNoCIOsForHierarchy, trNoTypes, trNoVariables, trNoConstants, trNoFunctions, trNoIdentifiers, //misc trHelp, trLegend, trMarker, trWarningOverwrite, trWarning, trGeneratedBy, trGeneratedOn, trOnDateTime, trSearch, trSeeAlso, trInternal, //add more here trAttributes, trDummy ); //array holding the translated strings, or empty for default (English) text. RTransTable = array[TTranslationID] of string; PTransTable = ^RTransTable; //language descriptor PLanguageRecord = ^TLanguageRecord; TLanguageRecord = record {$IFDEF STRING_UNICODE} Table: PTransTable; Name: string; Syntax: string; AspellLanguage: string; {$ELSE} Table: PTransTable; Name: string; Syntax: string; CharSet: string; { Name of this language as used by Aspell, see http://aspell.net/man-html/Supported.html . Set this to empty string if it's the same as our Syntax up to a dot. So a Syntax = 'pl' or Syntax = 'pl.iso-8859-2' already indicates AspellLanguage = 'pl'. TODO: In the future, it would be nice if all language names used by PasDoc and Aspell matched. Aspell language naming follows the standard http://en.wikipedia.org/wiki/ISO_639-1 as far as I see, and we should probably follow it too (currently, we deviate for some languages). So in the future, we'll probably replace Syntax and AspellLanguage by LanguageCode and CharsetCode. LanguageCode = code (suitable for both PasDoc and Aspell command-line; the thing currently up to a dot in Syntax), CharsetCode = the short representation of CharSet (the thing currently after a dot in Syntax). } AspellLanguage: string; {$ENDIF} end; const DEFAULT_LANGUAGE = lgEnglish; lgDefault = lgEnglish; type { Language class to hold all translated strings } TPasDocLanguages = class private FLanguage: TLanguageID; {$IFDEF STRING_UNICODE} FCodePage: LongWord; {$ENDIF} procedure SetLanguage(const Value: TLanguageID); protected FCharSet: string; { @abstract(gets a translation token) } function GetTranslation(ATranslationID: TTranslationID): string; public { Charset for current language } property CharSet: string read FCharSet; {$IFDEF STRING_UNICODE} property CodePage: LongWord read FCodePage; {$ENDIF} property Translation[ATranslationID: TTranslationID]: string read GetTranslation; constructor Create; property Language: TLanguageID read FLanguage write SetLanguage default DEFAULT_LANGUAGE; end; //Some GUI helpers {} //Full language name function LanguageFromIndex(i: integer): string; function LanguageFromID(i: TLanguageID): string; //Language abbreviation function SyntaxFromIndex(i: integer): string; function SyntaxFromID(i: TLanguageID): string; //Search for language by short or long name function IDfromLanguage(const s: string): TLanguageID; //Manual translation of id into lang function Translation(id: TTranslationID; lang: TLanguageID): string; { Find a language with Syntax = S (case ignored). Returns @true and sets LanguageId if found, otherwise returns @false. } function LanguageFromStr(S: string; out LanguageId: TLanguageID): boolean; //access LANGUAGE_ARRAY function LanguageDescriptor(id: TLanguageID): PLanguageRecord; { Language code, using an official standardardized language names, suitable for Aspell or HTML. } function LanguageCode(const Language: TLanguageID): string; implementation {$IFDEF fpc} {$ELSE} //Delphi uses SysUtils; {$ENDIF} const { Translation markers. For ease of finding missing translations, special markers can be used: strToDo should be obvious ;-) strKeep means to keep the English (default language) wording. } strKeep = {$IFDEF debug} '=' {$else} '' {$endif}; strToDo = {$IFDEF debug} '?' {$else} '' {$endif}; { NewLanguageTemplate value is not actually used. We include it just to force developers to keep PasDoc_Languages_Template_New_Language.inc in compileable state. } NewLanguageTemplate: {$I lang\PasDoc_Languages_Template_New_Language.inc} {$IFDEF STRING_UNICODE} aEnglish : {$I lang\PasDoc_Languages_English_utf8_bom.inc} aBosnian : {$I lang\PasDoc_Languages_Bosnia_utf8_bom.inc} aBrazilian : {$I lang\PasDoc_Languages_Brasilian_utf8_bom.inc} aBulgarian : {$I lang\PasDoc_Languages_Bulgarian_utf8_bom.inc} aCatalan : {$I lang\PasDoc_Languages_Catalan_utf8_bom.inc} aChinese : {$I lang\PasDoc_Languages_Chinese_utf8_bom.inc} aCroatian : {$I lang\PasDoc_Languages_Croatia_utf8_bom.inc} aDanish : {$I lang\PasDoc_Languages_Danish_utf8_bom.inc} aDutch : {$I lang\PasDoc_Languages_Dutch_utf8_bom.inc} aFrench : {$I lang\PasDoc_Languages_French_utf8_bom.inc} aGerman : {$I lang\PasDoc_Languages_German_utf8_bom.inc} aIndonesian : {$I lang\PasDoc_Languages_Indonesian_utf8_bom.inc} aItalian : {$I lang\PasDoc_Languages_Italian_utf8_bom.inc} aJavanese : {$I lang\PasDoc_Languages_Javanese_utf8_bom.inc} aPolish : {$I lang\PasDoc_Languages_Polish_utf8_bom.inc} aRussian : {$I lang\PasDoc_Languages_Russian_utf8_bom.inc} aSlovak : {$I lang\PasDoc_Languages_Slovak_utf8_bom.inc} aSpanish : {$I lang\PasDoc_Languages_Spanish_utf8_bom.inc} aSwedish : {$I lang\PasDoc_Languages_Swedish_utf8_bom.inc} aHungarian : {$I lang\PasDoc_Languages_Hungarian_utf8_bom.inc} aCzech : {$I lang\PasDoc_Languages_Czech_utf8_bom.inc} {$ELSE} aEnglish : {$I lang\PasDoc_Languages_English_utf8.inc} aBosnian : {$I lang\PasDoc_Languages_Bosnia_1250.inc} aBrazilian_1252 : {$I lang\PasDoc_Languages_Brasilian_1252.inc} aBrazilian_utf8 : {$I lang\PasDoc_Languages_Brasilian_utf8.inc} aBulgarian : {$I lang\PasDoc_Languages_Bulgarian_utf8.inc} aCatalan : {$I lang\PasDoc_Languages_Catalan_1252.inc} aChinese_gb2312 : {$I lang\PasDoc_Languages_Chinese_gb2312.inc} aCroatian : {$I lang\PasDoc_Languages_Croatia_1250.inc} aDanish : {$I lang\PasDoc_Languages_Danish_1252.inc} aDutch : {$I lang\PasDoc_Languages_Dutch_1252.inc} aFrench_ISO_8859_15 : {$I lang\PasDoc_Languages_French_ISO_8859_15.inc} aFrench_UTF_8 : {$I lang\PasDoc_Languages_French_utf8.inc} aGerman : {$I lang\PasDoc_Languages_German_1252.inc} aIndonesian : {$I lang\PasDoc_Languages_Indonesian_1252.inc} aItalian : {$I lang\PasDoc_Languages_Italian_1252.inc} aJavanese : {$I lang\PasDoc_Languages_Javanese_1250.inc} aPolish1250 : {$I lang\PasDoc_Languages_Polish_1250.inc} aPolish_ISO_8859_2 : {$I lang\PasDoc_Languages_Polish_iso_8859_2.inc} aRussian_1251 : {$I lang\PasDoc_Languages_Russian_1251.inc} aRussian_utf8 : {$I lang\PasDoc_Languages_Russian_utf8.inc} aRussian_866 : {$I lang\PasDoc_Languages_Russian_866.inc} aRussian_koi8 : {$I lang\PasDoc_Languages_Russian_koi8r.inc} aSlovak : {$I lang\PasDoc_Languages_Slovak_1250.inc} aSpanish : {$I lang\PasDoc_Languages_Spanish_1252.inc} aSwedish : {$I lang\PasDoc_Languages_Swedish_1252.inc} aHungarian_1250 : {$I lang\PasDoc_Languages_Hungarian_1250.inc} aCzech_ISO_8859_2 : {$I lang\PasDoc_Languages_Czech_iso_8859_2.inc} aCzech_CP1250 : {$I lang\PasDoc_Languages_Czech_1250.inc} {$ENDIF} {$IFDEF STRING_UNICODE} LANGUAGE_ARRAY: array[TLanguageID] of TLanguageRecord = ( (Table: @aBosnian; Name: 'Bosnian'; Syntax: 'ba'; AspellLanguage: 'bs'), (Table: @aBrazilian; Name: 'Brazilian'; Syntax: 'br'; AspellLanguage: 'pt'), (Table: @aBulgarian; Name: 'Bulgarian'; Syntax: 'bg'; AspellLanguage: ''), (Table: @aCatalan; Name: 'Catalan'; Syntax: 'ct'; AspellLanguage: 'ca'), (Table: @aChinese; Name: 'Chinese'; Syntax: 'zh'; AspellLanguage: 'zh'), (Table: @aCroatian; Name: 'Croatian'; Syntax: 'hr'; AspellLanguage: 'hr'), (Table: @aDanish; Name: 'Danish'; Syntax: 'dk'; AspellLanguage: 'da'), (Table: @aDutch; Name: 'Dutch'; Syntax: 'nl'; AspellLanguage: ''), (Table: @aEnglish; Name: 'English'; Syntax: 'en'; AspellLanguage: ''), (Table: @aFrench; Name: 'French'; Syntax: 'fr'; AspellLanguage: ''), (Table: @aGerman; Name: 'German'; Syntax: 'de'; AspellLanguage: ''), (Table: @aIndonesian; Name: 'Indonesian'; Syntax: 'id'; AspellLanguage: ''), (Table: @aItalian; Name: 'Italian'; Syntax: 'it'; AspellLanguage: ''), (Table: @aJavanese; Name: 'Javanese'; Syntax: 'jv'; AspellLanguage: ''), (Table: @aPolish; Name: 'Polish'; Syntax: 'pl'; AspellLanguage: ''), (Table: @aRussian; Name: 'Russian'; Syntax: 'ru'; AspellLanguage: ''), (Table: @aSlovak; Name: 'Slovak'; Syntax: 'sk'; AspellLanguage: ''), (Table: @aSpanish; Name: 'Spanish'; Syntax: 'es'; AspellLanguage: ''), (Table: @aSwedish; Name: 'Swedish'; Syntax: 'se'; AspellLanguage: 'sv'), (Table: @aHungarian; Name: 'Hungarian'; Syntax: 'hu'; AspellLanguage: ''), (Table: @aCzech; Name: 'Czech'; Syntax: 'cz'; AspellLanguage: 'cs') ); {$ELSE} LANGUAGE_ARRAY: array[TLanguageID] of TLanguageRecord = ( (Table: @aBosnian; Name: 'Bosnian (Codepage 1250)'; Syntax: 'ba'; CharSet: 'windows-1250'; AspellLanguage: 'bs'), (Table: @aBrazilian_1252; Name: 'Brazilian (Codepage 1252)'; Syntax: 'br.1252'; CharSet: 'windows-1252'; AspellLanguage: 'pt'), (Table: @aBrazilian_utf8; Name: 'Brazilian (Codepage UTF-8)'; Syntax: 'br.utf8'; CharSet: 'utf-8'; AspellLanguage: 'pt'), (Table: @aBulgarian; Name: 'Bulgarian (Codepage UTF-8)'; Syntax: 'bg'; CharSet: 'utf-8'; AspellLanguage: ''), (Table: @aCatalan; Name: 'Catalan'; Syntax: 'ct'; CharSet: 'windows-1252'; AspellLanguage: 'ca'), (Table: @aChinese_gb2312; Name: 'Chinese (Simple, gb2312)'; Syntax: 'gb2312'; CharSet: 'gb2312'; AspellLanguage: 'zh'), (Table: @aCroatian; Name: 'Croatian'; Syntax: 'hr'; CharSet: 'windows-1250'; AspellLanguage: 'hr'), (Table: @aDanish; Name: 'Danish'; Syntax: 'dk'; CharSet: 'iso-8859-15'; AspellLanguage: 'da'), (Table: @aDutch; Name: 'Dutch'; Syntax: 'nl'; CharSet: 'iso-8859-15'; AspellLanguage: ''), (Table: @aEnglish; Name: 'English'; Syntax: 'en'; CharSet: 'utf-8'; AspellLanguage: ''), (Table: @aFrench_ISO_8859_15; Name: 'French (iso-8859-15)'; Syntax: 'fr'; CharSet: 'iso-8859-15'; AspellLanguage: ''), (Table: @aFrench_UTF_8; Name: 'French (UTF-8)'; Syntax: 'fr.utf8'; CharSet: 'utf-8'; AspellLanguage: ''), (Table: @aGerman; Name: 'German'; Syntax: 'de'; CharSet: 'iso-8859-15'; AspellLanguage: ''), (Table: @aIndonesian; Name: 'Indonesian'; Syntax: 'id'; CharSet: 'windows-1252'; AspellLanguage: ''), (Table: @aItalian; Name: 'Italian'; Syntax: 'it'; CharSet: 'iso-8859-15'; AspellLanguage: ''), (Table: @aJavanese; Name: 'Javanese'; Syntax: 'jv'; CharSet: 'windows-1252'; AspellLanguage: ''), (Table: @aPolish1250; Name: 'Polish (Codepage CP1250)'; Syntax: 'pl.cp1250'; CharSet: 'windows-1250'; AspellLanguage: ''), (Table: @aPolish_ISO_8859_2; Name: 'Polish (Codepage ISO 8859-2)'; Syntax: 'pl.iso-8859-2'; CharSet: 'iso-8859-2'; AspellLanguage: ''), (Table: @aRussian_1251; Name: 'Russian (Codepage 1251)'; Syntax: 'ru.1251'; CharSet: 'windows-1251'; AspellLanguage: ''), (Table: @aRussian_utf8; Name: 'Russian (Codepage UTF-8)'; Syntax: 'ru.utf8'; CharSet: 'utf-8'; AspellLanguage: ''), (Table: @aRussian_866; Name: 'Russian (Codepage 866)'; Syntax: 'ru.866'; CharSet: 'IBM866'; AspellLanguage: ''), (Table: @aRussian_koi8; Name: 'Russian (KOI-8)'; Syntax: 'ru.koi8r'; CharSet: 'koi8-r'; AspellLanguage: ''), (Table: @aSlovak; Name: 'Slovak (Codepage 1250)'; Syntax: 'sk'; CharSet: 'windows-1250'; AspellLanguage: ''), (Table: @aSpanish; Name: 'Spanish'; Syntax: 'es'; CharSet: 'iso-8859-15'; AspellLanguage: ''), (Table: @aSwedish; Name: 'Swedish'; Syntax: 'se'; CharSet: 'iso-8859-15'; AspellLanguage: 'sv'), (Table: @aHungarian_1250; Name: 'Hungarian (Codepage 1250)'; Syntax: 'hu.1250'; CharSet: 'windows-1250'; AspellLanguage: ''), (Table: @aCzech_CP1250; Name: 'Czech (Codepage 1250)'; Syntax: 'cz'; CharSet: 'windows-1250'; AspellLanguage: ''), (Table: @aCzech_ISO_8859_2; Name: 'Czech (Codepage ISO 8859-2)'; Syntax: 'cz.iso-8859-2'; CharSet: 'iso-8859-2'; AspellLanguage: 'cs') ); {$ENDIF} function TPasDocLanguages.GetTranslation( ATranslationID: TTranslationID): string; begin Result := LANGUAGE_ARRAY[FLanguage].Table^[ATranslationID]; if Result <= strKeep then Result := aEnglish[ATranslationID]; end; constructor TPasDocLanguages.Create; begin inherited; SetLanguage(DEFAULT_LANGUAGE); end; procedure TPasDocLanguages.SetLanguage(const Value: TLanguageID); begin inherited Create; FLanguage := Value; {$IFNDEF STRING_UNICODE} FCharSet := LANGUAGE_ARRAY[Value].Charset; {$ELSE} // String is UTF-16 so get rid of this ANSI stuff. FCharSet := 'UTF-8'; FCodePage := 65001; {$ENDIF} end; function LanguageFromStr(S: string; out LanguageId: TLanguageID): boolean; var I: TLanguageID; begin S := LowerCase(S); for I := Low(LANGUAGE_ARRAY) to High(LANGUAGE_ARRAY) do begin if LowerCase(LANGUAGE_ARRAY[I].Syntax) = S then begin Result := true; LanguageId := I; Exit; end; end; Result := false; end; //------------- language helpers, for PasDoc_gui ----------------- function LanguageFromIndex(i: integer): string; begin Result := language_array[TLanguageID(i)].Name; end; function LanguageFromID(i: TLanguageID): string; begin Result := language_array[i].Name; end; function SyntaxFromIndex(i: integer): string; var l: TLanguageID absolute i; begin Result := Language_array[l].Syntax; end; function SyntaxFromID(i: TLanguageID): string; begin Result := Language_array[i].Syntax; end; function IDfromLanguage(const s: string): TLanguageID; var i: TLanguageID; begin for i := low(i) to high(i) do begin if (LANGUAGE_ARRAY[i].Name = s) or (LANGUAGE_ARRAY[i].Syntax = s) then begin Result := i; exit; end; end; Result := DEFAULT_LANGUAGE; end; function LanguageDescriptor(id: TLanguageID): PLanguageRecord; begin Result := @Language_array[id]; end; function Translation(id: TTranslationID; lang: TLanguageID): string; var tbl: PTransTable; begin tbl := LANGUAGE_ARRAY[lang].Table; if not assigned(tbl) then tbl := @aEnglish; Result := tbl^[id]; end; function LanguageCode(const Language: TLanguageID): string; var Dot: Integer; begin Result := LANGUAGE_ARRAY[Language].AspellLanguage; if Result = '' then begin Result := LANGUAGE_ARRAY[Language].Syntax; Dot := Pos('.', Result); if Dot <> 0 then SetLength(Result, Dot - 1); { cut stuff after '.' } end; end; end. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/pasdoc_versions.inc���������������������������������������������������������0000600�0001750�0001750�00000017137�13237143042�021671� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { ---------------------------------------------------------------------------- } { Compiler Version Information } { ---------------------------------------------------------------------------- } {$IFDEF WIN32} {$IFNDEF FPC} {$DEFINE VERSION_UNKNOWN} {$ENDIF} {$IFDEF VER80} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_1} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_1} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER90} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_2} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_2} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER100} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_3} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_3} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER120} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_4} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_4} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER130} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_5} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_5} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER140} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_6} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_6} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER150} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_7} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_7} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} // VER160 was Delphi 8 .NET only, unsupported. {$IFDEF VER170} {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_9} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_9} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER180} { Delphi 2006 and 2007 } {$UNDEF VERSION_UNKNOWN} {$IFDEF VER185} { Delphi 2007 } {$DEFINE DELPHI_11} {$DEFINE COMPILER_11} {$DEFINE DELPHI_11_UP} {$DEFINE COMPILER_11_UP} {$ELSE} {$DEFINE DELPHI_10} {$DEFINE COMPILER_10} {$ENDIF} {$DEFINE DELPHI_10_UP} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_10_UP} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} // VER190 is Delphi 2007 for .NET, unsupported {$IFDEF VER200} { Delphi 2009 } {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_12} {$DEFINE DELPHI_12_UP} {$DEFINE DELPHI_11_UP} {$DEFINE DELPHI_10_UP} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_12} {$DEFINE COMPILER_12_UP} {$DEFINE COMPILER_11_UP} {$DEFINE COMPILER_10_UP} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} // Number 13 was skipped. {$IFDEF VER210} { Delphi 2010 } {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_14} {$DEFINE DELPHI_14_UP} {$DEFINE DELPHI_12_UP} {$DEFINE DELPHI_11_UP} {$DEFINE DELPHI_10_UP} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_14} {$DEFINE COMPILER_14_UP} {$DEFINE COMPILER_12_UP} {$DEFINE COMPILER_11_UP} {$DEFINE COMPILER_10_UP} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VER220} { Delphi XE } {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_15} {$DEFINE DELPHI_15_UP} {$DEFINE DELPHI_14_UP} {$DEFINE DELPHI_12_UP} {$DEFINE DELPHI_11_UP} {$DEFINE DELPHI_10_UP} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_15} {$DEFINE COMPILER_15_UP} {$DEFINE COMPILER_14_UP} {$DEFINE COMPILER_12_UP} {$DEFINE COMPILER_11_UP} {$DEFINE COMPILER_10_UP} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFDEF VERSION_UNKNOWN} // Assume this pasdoc version builds with newer compilers as well. {$UNDEF VERSION_UNKNOWN} {$DEFINE DELPHI_15} {$DEFINE DELPHI_15_UP} {$DEFINE DELPHI_14_UP} {$DEFINE DELPHI_12_UP} {$DEFINE DELPHI_11_UP} {$DEFINE DELPHI_10_UP} {$DEFINE DELPHI_9_UP} {$DEFINE DELPHI_7_UP} {$DEFINE DELPHI_6_UP} {$DEFINE DELPHI_5_UP} {$DEFINE DELPHI_4_UP} {$DEFINE DELPHI_3_UP} {$DEFINE DELPHI_2_UP} {$DEFINE DELPHI_1_UP} {$DEFINE COMPILER_15} {$DEFINE COMPILER_15_UP} {$DEFINE COMPILER_14_UP} {$DEFINE COMPILER_12_UP} {$DEFINE COMPILER_11_UP} {$DEFINE COMPILER_10_UP} {$DEFINE COMPILER_9_UP} {$DEFINE COMPILER_7_UP} {$DEFINE COMPILER_6_UP} {$DEFINE COMPILER_5_UP} {$DEFINE COMPILER_4_UP} {$DEFINE COMPILER_3_UP} {$DEFINE COMPILER_2_UP} {$DEFINE COMPILER_1_UP} {$ENDIF} {$IFNDEF MSWINDOWS} {$DEFINE MSWINDOWS} {$ENDIF} {$ENDIF} // WIN32 {$IFNDEF FPC} {$IFDEF LINUX} {$I pasdoc_kylixversions.inc} {$ENDIF} {$ELSE} {$ENDIF} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_ObjectVector.pas�����������������������������������������������������0000600�0001750�0001750�00000003536�13237143042�022322� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) @author(Michalis Kamburelis) a simple object vector } unit PasDoc_ObjectVector; {$I pasdoc_defines.inc} interface uses Contnrs, Classes; type TObjectVector = class(TObjectList) public { This is only to make constructor virtual, while original TObjectList has a static constructor. } constructor Create(const AOwnsObject: boolean); virtual; {$IFNDEF FPC} // Fix bug in D7 TList.Sort. procedure Sort(Compare: TListSortCompare); reintroduce; {$ENDIF} end; function ObjectVectorIsNilOrEmpty(const AOV: TObjectVector): boolean; implementation function ObjectVectorIsNilOrEmpty(const AOV: TObjectVector): boolean; begin Result := (not Assigned(AOV)) or (AOV.Count = 0); end; { TObjectVector } constructor TObjectVector.Create(const AOwnsObject: boolean); begin inherited Create(AOwnsObject); end; {$IFNDEF FPC} procedure TObjectVector.Sort(Compare: TListSortCompare); begin if Count <= 1 then exit; inherited; end; {$ENDIF} end. ������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_GenLatex.pas���������������������������������������������������������0000644�0001750�0001750�00000152722�13237143042�021452� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Provides Latex document generator object.) Implements an object to generate latex documentation, overriding many of @link(TDocGenerator)'s virtual methods. } unit PasDoc_GenLatex; {$I pasdoc_defines.inc} interface uses PasDoc_Gen, PasDoc_Items, PasDoc_Languages, PasDoc_StringVector, PasDoc_Types, Classes; type { @abstract(generates latex documentation) Extends @link(TDocGenerator) and overwrites many of its methods to generate output in LaTex format. } TTexDocGenerator = class(TDocGenerator) private {$IFDEF unused} FOddTableRow: Integer; { number of cells (= columns) per table row } NumCells: Integer; { number of cells we've already written in current table row } CellCounter: LongInt; {$ELSE} {$ENDIF} FLatex2Rtf: Boolean; FLatexHead: TStrings; FImages: TStringList; { Writes information on doc generator to current output stream, including link to pasdoc homepage. } procedure WriteAppInfo; { Writes authors to output, at heading level HL. Will not write anything if collection of authors is not assigned or empty. } procedure WriteAuthors(HL: integer; Authors: TStringVector); procedure WriteCodeWithLinks(const p: TPasItem; const Code: string; WriteItemLink: boolean); procedure WriteEndOfDocument; { Finishes a LaTeX paragraph by writing a blank line. } procedure WriteEndOfParagraph; {$IFDEF unused} { Finishes an Latex table cell by writing ' & '. } procedure WriteEndOfTableCell; { Finishes an HTML table by writing a closing TABLE tag. } procedure WriteEndOfTable; { Finishes a LaTeX table row by writing '\\'. } procedure WriteEndOfTableRow; {$ELSE} {$ENDIF} (* Writes the Item's AbstractDescription and DetailedDescription. TODO: this should be fixed to write @longcode(# WriteDirect('\item[\textbf{'+FLanguage.Translation[trDescription]+'}]',true); #) inside it, and to take care of writing paragraph markers inside it. Right now this is messy --- to many paragraphs may be written around (which does not hurt, but is unclean) and FLanguage.Translation[trDescription] header may be written when there is actually no description (only e.g. Params or Raises or Returns information). *) procedure WriteItemLongDescription(const AItem: TPasItem; AlreadyWithinAList: boolean); { @name writes the preamble of a LaTeX document and the begining of the document itself up through the table of contents.} procedure WriteStartOfDocument(AName: string); { Starts an LaTeX paragraph element by writing '\par'. } procedure WriteStartOfParagraph; {$IFDEF unused} procedure WriteStartOfTable1Column(t: string); procedure WriteStartOfTable2Columns(t1, t2: string); procedure WriteStartOfTable3Columns(t1, t2, T3: string); procedure WriteStartOfTableRow; {$ELSE} {$ENDIF} procedure WriteItemsSummary(const Items: TPasItems); { Writes information about all Items. If ShowVisibility then their Visibility will also be shown. } procedure WriteItemsDetailed(const HL: integer; const Items: TPasItems; ShowVisibility: boolean; SectionName: TTranslationId); procedure WriteFieldsProperties(HL: integer; const Items: TPasItems; ShowVisibility: boolean; SectionName: TTranslationId); procedure WriteAnchor(ItemName, Link: string); { Writes a single class, interface or object CIO to output, at heading level HL. } procedure WriteCIO(HL: integer; const CIO: TPasCio); { Calls @link(WriteCIO) with each element in the argument collection C, using heading level HL. } procedure WriteCIOs(HL: integer; c: TPasItems); procedure WriteSpellChecked(const AString: string); { PDF Conditional support routines } procedure WriteStartFlushLeft; procedure WritePDFIfdef; procedure WriteEndFlushLeft; procedure WritePDFDocInfo(LocalTitle: string); procedure WriteStartList(s: string); procedure WriteEndList; function HasDescriptions(c: TPasItems):boolean; procedure WriteDeclarationItem(p: TPasItem; itemname: string; itemdesc: string); {** Returns @true if this item or its ancestor has a description, otherwise returns @false. } function HasDescription(const AItem: TPasItem): boolean; { Writes heading S to output, at heading level I. For HTML, only levels 1 to 6 are valid, so that values smaller than 1 will be set to 1 and arguments larger than 6 are set to 6. The String S will then be enclosed in an element from H1 to H6, according to the level. } procedure WriteHeading(HL: integer; const s: string); { Writes dates Created and LastMod at heading level HL to output (if at least one the two has a value assigned). } procedure WriteDates(const HL: integer; const Created, LastMod: string); procedure SetLatexHead(const Value: TStrings); function FormatHeading(HL: integer; const s: string): string; protected function ConvertString(const s: string): string; override; { Called by @link(ConvertString) to convert a character. Will convert special characters to their html escape sequence -> test } function ConvertChar(c: char): String; override; procedure WriteUnit(const HL: integer; const U: TPasUnit); override; function LatexString(const S: string): string; override; // Makes a String look like a coded String, i.e. // '\begin{ttfamily}TheString\end{ttfamily}' // in LaTeX. } function CodeString(const s: string): string; override; { Returns a link to an anchor within a document. LaTeX simply concatenates the strings with either a "-" or "." character between them. } function CreateLink(const Item: TBaseItem): string; override; procedure WriteStartOfCode; override; procedure WriteEndOfCode; override; function Paragraph: string; override; function ShortDash: string; override; function LineBreak: string; override; function URLLink(const URL: string): string; override; procedure WriteExternalCore(const ExternalItem: TExternalItem; const Id: TTranslationID); override; { TODO : FormatKeyWord, FormatCompilerComment, FormatComment, FormatString and FormatPascalCode are all closely related. Maybe they should be extracted into an abstract base class. There could be descendents of the abstract ancestor associated with the HTML and Latex DocGenerators.} // @name is called from within @link(FormatPascalCode) // to return AString in a bold font. function FormatKeyWord(AString: string): string; override; // @name is called from within @link(FormatPascalCode) to // return AString in italics. function FormatCompilerComment(AString: string): string; override; // @name is called from within @link(FormatPascalCode) to // return AString in italics. function FormatComment(AString: string): string; override; function FormatAnchor(const Anchor: string): string; override; function MakeItemLink(const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; override; function FormatBold(const Text: string): string; override; function FormatItalic(const Text: string): string; override; function FormatPreformatted(const Text: string): string; override; function FormatImage(FileNames: TStringList): string; override; function FormatList(ListData: TListData): string; override; function FormatTable(Table: TTableData): string; override; public // @name is intended to format Line as if it were Object Pascal // code in Delphi or Lazarus. However, unlike Lazarus and Delphi, // colored text is not used because printing colored text tends to // be much more expensive than printing all black text. function FormatPascalCode(const Line: string): string; override; { Returns Latex file extension ".tex". } function GetFileExtension: string; override; { The method that does everything --- writes documentation for all units and creates overview files. } procedure WriteDocumentation; override; constructor Create(AOwner: TComponent); override; destructor Destroy; override; function EscapeURL(const AString: string): string; virtual; function FormatSection(HL: integer; const Anchor: string; const Caption: string): string; override; published { Indicate if the output must be simplified for latex2rtf } property Latex2rtf: boolean read FLatex2rtf write FLatex2rtf default false; // The strings in @name are inserted directly into the preamble of // the LaTeX document. Therefore they must be valid LaTeX code. property LatexHead: TStrings read FLatexHead write SetLatexHead; end; implementation uses SysUtils, PasDoc_Base, PasDoc_ObjectVector, PasDoc_Utils, PasDoc_StringPairVector, StrUtils, PasDoc_Versions; function TTexDocGenerator.LatexString(const S: string): string; begin Result := S; end; function TTexDocGenerator.FormatPascalCode(const Line: string): string; var AStringList: TStringList; LineIndex: integer; ALine: string; begin AStringList := TStringList.Create; try AStringList.Text := inherited FormatPascalCode(Line); for LineIndex := 0 to AStringList.Count -1 do begin ALine := AStringList[LineIndex]; ALine := SCharsReplace(ALine, [' '], '~') + '\\'; if LineIndex < AStringList.Count -1 then begin ALine := ALine + '\nopagebreak[3]' end; AStringList[LineIndex] := ALine; end; result := '\texttt{' + AStringList.Text + '}'; finally AStringList.Free; end; end; function TTexDocGenerator.CodeString(const s: string): string; begin Result := '\begin{ttfamily}' + s + '\end{ttfamily}'; end; function TTexDocGenerator.CreateLink(const Item: TBaseItem): string; begin Result := ''; if (not Assigned(Item)) then Exit; if (Item is TPasItem) and Assigned(TPasItem(Item).MyUnit) then begin if Assigned(TPasItem(Item).MyObject) then begin { it's a method, a field or a property - only those have MyObject initialized } Result := TPasItem(Item).MyObject.FullLink + '-' + Item.Name; end else begin if Item is TPasCio then begin { it's an object / a class } Result := TPasItem(Item).MyUnit.Name + '.' + Item.Name; end else begin { it's a constant, a variable, a type or a function / procedure } Result := TPasItem(Item).MyUnit.FullLink + '-' + Item.Name; end; end; end else begin Result := Item.Name; end; end; function TTexDocGenerator.MakeItemLink(const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; begin if LinkContext = lcCode then { Links inside lcCode context look bad... } Result := ConvertString(LinkCaption) else Result := '\begin{ttfamily}' + ConvertString(LinkCaption) + '\end{ttfamily}(\ref{' + EscapeURL(Item.FullLink) + '})'; end; function TTexDocGenerator.GetFileExtension: string; begin Result := '.tex'; end; procedure TTexDocGenerator.WriteAppInfo; begin if not ExcludeGenerator then WriteDirectLine('% '+ FLanguage.Translation[trGeneratedBy] + ' ' + PASDOC_HOMEPAGE + PASDOC_NAME_AND_VERSION); if IncludeCreationTime then WriteDirectLine('% ' + FLanguage.Translation[trGeneratedOn] + ' ' + FormatDateTime('yyyy-mm-dd hh:mm:ss', Now)); end; procedure TTexDocGenerator.WriteAuthors(HL: integer; Authors: TStringVector); var i: Integer; s, S1, S2: string; EmailAddress: string; begin if IsEmpty(Authors) then Exit; if (Authors.Count = 1) then WriteHeading(HL, FLanguage.Translation[trAuthor]) else WriteHeading(HL, FLanguage.Translation[trAuthors]); for i := 0 to Authors.Count - 1 do begin s := Authors[i]; WriteStartOfParagraph; if ExtractEmailAddress(s, S1, S2, EmailAddress) then begin WriteConverted(S1); WriteConverted(EmailAddress); WriteConverted(S2); end else begin WriteConverted(s); end; WriteEndOfParagraph; end; end; { Returns TRUE if one of the subentries has a description otherwise returns FALSE } function TTexDocGenerator.HasDescriptions(c: TPasItems):boolean; var j :integer; Item: TPasItem; begin HasDescriptions := false; for j := 0 to c.Count - 1 do begin Item := TPasItem(c.PasItemAt[j]); if HasDescription(Item) then begin HasDescriptions:=true; exit; end; end; end; procedure TTexDocGenerator.WriteCIO(HL: integer; const CIO: TPasCio); type TSections = (dsDescription, dsHierarchy, dsFields, dsMethods, dsProperties); TSectionSet = set of TSections; var s: string; Item: TBaseItem; SectionsAvailable: TSectionSet; SectionHeads: array[TSections] of string; begin if not Assigned(CIO) then Exit; SectionHeads[dsDescription] := FLanguage.Translation[trDescription]; SectionHeads[dsHierarchy] := FLanguage.Translation[trHierarchy]; SectionHeads[dsFields ]:= FLanguage.Translation[trFields]; SectionHeads[dsMethods ]:= FLanguage.Translation[trMethods]; SectionHeads[dsProperties ]:= FLanguage.Translation[trProperties]; SectionsAvailable := []; if HasDescription(CIO) then Include(SectionsAvailable, dsDescription); if Assigned(CIO.Ancestors) and (CIO.Ancestors.Count > 0) then Include(SectionsAvailable, dsHierarchy); if not ObjectVectorIsNilOrEmpty(CIO.Fields) then Include(SectionsAvailable, dsFields); if not ObjectVectorIsNilOrEmpty(CIO.Methods) then Include(SectionsAvailable, dsMethods); if not ObjectVectorIsNilOrEmpty(CIO.Properties) then Include(SectionsAvailable, dsProperties); if SectionsAvailable = [] then exit; if CIO.ClassDirective = CT_HELPER then s := ' for ' + CIO.HelperTypeIdentifier else s := ''; WriteHeading(HL+1,CIO.Name+' '+ConvertString(GETCIOTypeName(CIO.MyType)) + ConvertString(GetClassDirectiveName(CIO.ClassDirective)) + ConvertString(s)); WriteAnchor(CIO.Name,CIO.FullLink); if dsHierarchy in SectionsAvailable then begin { Write Hierarchy } if Assigned(CIO.Ancestors) and (CIO.Ancestors.Count > 0) then begin WriteHeading(HL + 2, SectionHeads[dsHierarchy]); WriteConverted(CIO.Name); WriteConverted(' > '); s := CIO.Ancestors.FirstName; Item := CIO.FirstAncestor; if Assigned(Item) and (Item is TPasCio) then begin repeat s := MakeItemLink(Item, Item.Name, lcNormal); WriteDirect(s); if TPasCio(Item).Ancestors.Count <> 0 then begin s := TPasCio(Item).Ancestors.FirstName; Item := TPasCio(Item).FirstAncestor; WriteConverted(' > '); if (Item <> nil) and (Item is TPasCio) then begin Continue; end; end; WriteDirect('',true); Break; until False; end; if Item = nil then begin WriteDirect(s,true); end; end; end; if dsDescription in SectionsAvailable then begin WriteHeading(HL + 2, SectionHeads[dsDescription]); WriteItemLongDescription(CIO, false); end else WriteDirect('%%%%' + SectionHeads[dsDescription],true); WriteFieldsProperties(HL + 2, CIO.Properties, CIO.ShowVisibility, trProperties); WriteFieldsProperties(HL + 2, CIO.Fields, CIO.ShowVisibility, trFields); WriteItemsDetailed(HL + 2, CIO.Methods, CIO.ShowVisibility, trMethods); WriteAuthors(HL + 2, CIO.Authors); WriteDates(HL + 2, CIO.Created, CIO.LastMod); end; procedure TTexDocGenerator.WriteCIOs(HL: integer; c: TPasItems); var j: Integer; CIO: TPasCio; begin if c = nil then Exit; if c.Count = 0 then Exit; WriteHeading(HL, FLanguage.Translation[trCio]); for j := 0 to c.Count - 1 do begin CIO := TPasCio(c.PasItemAt[j]); WriteCIO(HL,CIO); end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteCodeWithLinks(const p: TPasItem; const Code: string; WriteItemLink: boolean); begin WriteCodeWithLinksCommon(p, Code, WriteItemLink, '', ''); WriteDirect('',true); end; { ---------------------------------------------------------------------------- } { PDF SUPPORT ROUTINES } { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteStartFlushLeft; begin if not FLatex2rtf then begin WriteDirect('\ifpdf',true); WriteDirect('\begin{flushleft}',true); WriteDirect('\fi',true); end else WriteDirect('\begin{flushleft}',true); end; procedure TTexDocGenerator.WritePDFIfdef; begin { PDF output support, create ifpdf macro to be able to support extended PDF features. } if not FLatex2Rtf then begin WriteDirect('',true); WriteDirect('% Conditional define to determine if pdf output is used',true); WriteDirect('\newif\ifpdf',true); WriteDirect('\ifx\pdfoutput\undefined',true); WriteDirect('\pdffalse',true); WriteDirect('\else',true); WriteDirect('\pdfoutput=1',true); WriteDirect('\pdftrue',true); WriteDirect('\fi',true); WriteDirect('',true); end; end; procedure TTexDocGenerator.WriteEndFlushLeft; begin if not FLatex2Rtf then begin WriteDirect('\ifpdf',true); WriteDirect('\end{flushleft}',true); WriteDirect('\fi',true); end else WriteDirect('\end{flushleft}',true); end; procedure TTexDocGenerator.WritePDFDocInfo(Localtitle: string); begin if not FLatex2RTF then begin WriteDirect('',true); WriteDirect('% Write Document information for pdflatex/pdftex',true); WriteDirect('\ifpdf',true); WriteDirect('\pdfinfo{',true); WriteDirect(' /Author (Pasdoc)',true); WriteDirect(' /Title ('+LocalTitle+')',true); if IncludeCreationTime then WriteDirect(' /CreationDate ('+ FormatDateTime('yyyymmddhhmmss', Now)+')',true); WriteDirect('}',true); WriteDirect('\fi',true); WriteDirect('',true); end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteDates(const HL: integer; const Created, LastMod: string); begin if Created <> '' then begin WriteHeading(HL, FLanguage.Translation[trCreated]); WriteStartOfParagraph; WriteDirectLine(Created); WriteEndOfParagraph; end; if LastMod <> '' then begin WriteHeading(HL, FLanguage.Translation[trLastModified]); WriteStartOfParagraph; WriteDirectLine(LastMod); WriteEndOfParagraph; end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteDocumentation; var OutputFileName: string; begin StartSpellChecking('tex'); inherited; if ProjectName <> '' then OutputFileName := ProjectName + '.tex' else OutputFileName := 'docs.tex'; if not CreateStream(OutputFileName) then Exit; WriteStartOfDocument(''); WriteIntroduction; WriteUnits(1); WriteConclusion; WriteEndOfDocument; CloseStream; EndSpellChecking; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteEndOfDocument; begin WriteDirect('\end{document}',true); end; procedure TTexDocGenerator.WriteEndOfCode; begin WriteDirect('\end{ttfamily}',true); end; procedure TTexDocGenerator.WriteEndOfParagraph; begin WriteDirectLine(''); WriteDirect('',true); end; {$IFDEF unused} procedure TTexDocGenerator.WriteEndOfTableCell; begin Inc(CellCounter); if (CellCounter < NumCells) then WriteDirect(' & '); end; procedure TTexDocGenerator.WriteEndOfTable; begin WriteDirect('\end{tabular}',true); end; procedure TTexDocGenerator.WriteEndOfTableRow; begin WriteDirect('\\',true); end; {$ELSE} {$ENDIF} { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteStartList(s: string); begin if FLatex2rtf then begin WriteDirect('\begin{list}{}{',true); WriteDirect('\settowidth{\tmplength}{\textbf{'+convertstring(s)+'}}',true); WriteDirect('\setlength{\itemindent}{0cm}',true); WriteDirect('\setlength{\listparindent}{0cm}',true); WriteDirect('\setlength{\leftmargin}{\evensidemargin}',true); WriteDirect('\addtolength{\leftmargin}{\tmplength}',true); WriteDirect('\settowidth{\labelsep}{X}',true); WriteDirect('\addtolength{\leftmargin}{\labelsep}',true); WriteDirect('\setlength{\labelwidth}{\tmplength}',true); WriteDirect('}',true); end else begin WriteDirect('\begin{list}{}{',true); WriteDirect('\settowidth{\tmplength}{\textbf{'+convertstring(s)+'}}',true); WriteDirect('\setlength{\itemindent}{0cm}',true); WriteDirect('\setlength{\listparindent}{0cm}',true); WriteDirect('\setlength{\leftmargin}{\evensidemargin}',true); WriteDirect('\addtolength{\leftmargin}{\tmplength}',true); WriteDirect('\settowidth{\labelsep}{X}',true); WriteDirect('\addtolength{\leftmargin}{\labelsep}',true); WriteDirect('\setlength{\labelwidth}{\tmplength}',true); WriteDirect('}',true); end; end; procedure TTexDocGenerator.WriteEndList; begin WriteDirect('\end{list}',true); end; procedure TTexDocGenerator.WriteDeclarationItem(p: TPasItem; itemname: string; itemdesc: string); begin if FLatex2rtf then begin WriteStartFlushLeft; WriteDirect('\item[\textbf{'+convertstring(itemname)+'}\hfill]',true); WriteCodeWithLinks(p, itemdesc, false); WriteDirect('',true); WriteEndFlushLeft; end else begin WriteDirect('\item[\textbf{'+convertstring(itemname)+'}\hfill]',true); WriteStartFlushLeft; WriteCodeWithLinks(p, itemdesc, false); WriteEndFlushLeft; WriteDirect('',true); end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteItemsDetailed(const HL: integer; const Items: TPasItems; ShowVisibility: boolean; SectionName: TTranslationId); var j: Integer; Item: TPasItem; s: string; Visibility: string; begin if ObjectVectorIsNilOrEmpty(Items) then Exit; WriteHeading(HL, FLanguage.Translation[SectionName]); { Determine the longest string used. This is the one we will use for determining the label width. } s:=FLanguage.Translation[trDescription]; if length(s) < length(FLanguage.Translation[trDeclaration]) then s:= FLanguage.Translation[trDeclaration]; if length(s) < length(FLanguage.Translation[trReturns]) then s:=FLanguage.Translation[trReturns]; if length(s) < length(FLanguage.Translation[trParameters]) then s:=FLanguage.Translation[trParameters]; if length(s) < length(FLanguage.Translation[trExceptions]) then s:=FLanguage.Translation[trExceptions]; for j := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[j]; WriteHeading(HL+1, Item.Name); WriteAnchor(Item.Name, Item.FullLink); WriteStartList(s); if ShowVisibility then Visibility := string(VisibilityStr[Item.Visibility]) + ' ' else Visibility := ''; WriteDeclarationItem(Item, FLanguage.Translation[trDeclaration], Visibility + Item.FullDeclaration); if HasDescription(Item) then begin WriteStartOfParagraph; WriteDirect('\item[\textbf{'+FLanguage.Translation[trDescription]+'}]',true); WriteItemLongDescription(Item, true); WriteEndOfParagraph; end; WriteEndList; end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteItemsSummary(const Items: TPasItems); var i: Integer; Item: TPasItem; begin if ObjectVectorIsNilOrEmpty(Items) then Exit; WriteDirect('\begin{description}',true); for i := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[i]; WriteDirect('\item[\texttt{'); if Item is TPasCio then begin WriteDirect(CodeString(ConvertString(Item.Name))); WriteDirect(' '); WriteConverted(GETCIOTypeName(TPasCio(Item).MyType)); end else begin WriteConverted(Item.Name); end; WriteDirect('}]'); WriteSpellChecked(Item.AbstractDescription); WriteDirectLine(''); end; WriteDirect('\end{description}', true); end; { ---------------------------------------------------------------------------- } function TTexDocGenerator.FormatHeading(HL: integer; const s: string): string; begin if (HL < 1) then HL := 1; if HL > 5 then begin DoMessage(2, pmtWarning, 'LaTeX generator cannot write headlines of ' + 'level 5 or greater; will create a new paragraph instead.', []); HL := 5; end; case HL of 1: begin result := '\chapter{' + ConvertString(s) + '}' + LineEnding; end; 2: begin result := '\section{' + ConvertString(s) + '}' + LineEnding; end; 3: begin if latex2rtf then begin result := '\subsection*{' + ConvertString(s) + '}' + LineEnding; end else begin result := '\ifpdf' + LineEnding + '\subsection*{' +'\large{\textbf{'+ConvertString(s)+'}}\normalsize\hspace{1ex}'+ '\hrulefill' + '}' + '\else'+ LineEnding + '\subsection*{' + ConvertString(s) + '}'+ LineEnding + '\fi'+ LineEnding; end; end; 4: begin result := '\subsubsection*{' + '\large{\textbf{'+ConvertString(s)+'}}\normalsize\hspace{1ex}'+ '\hfill' + '}'+ LineEnding; end; 5: begin result := '\paragraph*{' + ConvertString(s) + '}\hspace*{\fill}'+ LineEnding + ''+ LineEnding; end; end; end; procedure TTexDocGenerator.WriteHeading(HL: integer; const s: string); begin if (HL < 1) then HL := 1; if HL > 5 then begin DoMessage(2, pmtWarning, 'LaTeX generator cannot write headlines of ' + 'level 5 or greater; will a new paragraph instead.', []); HL := 5; end; case HL of 1: begin WriteDirect('\chapter{'); WriteConverted(s); WriteDirectLine('}'); end; 2: begin WriteDirect('\section{'); WriteConverted(s); WriteDirectLine('}'); end; 3: begin if latex2rtf then begin WriteDirect('\subsection*{'); WriteConverted(s); WriteDirectLine('}'); end else begin WriteDirect('\ifpdf',true); WriteDirect('\subsection*{'); WriteDirect('\large{\textbf{'+ConvertString(s)+'}}\normalsize\hspace{1ex}'+ '\hrulefill'); WriteDirectLine('}'); WriteDirect('\else',true); WriteDirect('\subsection*{'); WriteConverted(s); WriteDirectLine('}'); WriteDirect('\fi',true); end; end; 4: begin WriteDirect('\subsubsection*{'); WriteDirect('\large{\textbf{'+ConvertString(s)+'}}\normalsize\hspace{1ex}'+ '\hfill'); WriteDirect('}',true); end; 5: begin WriteDirect('\paragraph*{'); WriteConverted(s); WriteDirectLine('}\hspace*{\fill}'); WriteDirect('',true); end; end; end; { ---------- } function TTexDocGenerator.HasDescription(const AItem: TPasItem): boolean; var Ancestor: TBaseItem; begin Result := false; if not Assigned(AItem) then Exit; Result := AItem.HasDescription or { TPasEnum always has some description: list of it's members } (AItem is TPasEnum) or { Some hint directive ? } (AItem.HintDirectives <> []) or { Some TPasMethod optional info ? } ( (AItem is TPasMethod) and TPasMethod(AItem).HasMethodOptionalInfo ) or { Seealso section ? } (AItem.SeeAlso.Count <> 0); if Result then Exit; if (AItem is TPasCio) and (TPasCio(AItem).Ancestors.Count <> 0) then begin Ancestor := TPasCio(AItem).FirstAncestor; if Assigned(Ancestor) and (Ancestor is TPasItem) then begin HasDescription := HasDescription(TPasItem(Ancestor)); exit; end; end; end; procedure TTexDocGenerator.WriteItemLongDescription(const AItem: TPasItem; AlreadyWithinAList: boolean); { writes the parameters or exceptions list } procedure WriteParamsOrRaises(Func: TPasMethod; const Caption: string; List: TStringPairVector; LinkToParamNames: boolean); procedure WriteParameter(const ParamName: string; const Desc: string); begin WriteDirect('\item['); WriteDirect(ParamName); WriteDirect('] '); WriteSpellChecked(Desc); WriteDirect('',true); end; var i: integer; ParamName: string; begin if objectVectorIsNilOrEmpty(List) then Exit; WriteDirect('\item[\textbf{'+Caption+'}]',true); WriteDirect('\begin{description}',true); { Terrible hack : To fix and replace by a clean solution, we need to add an empty item so that the list starts at the correct margin. } { WriteDirect('\item',true);} for i := 0 to List.Count - 1 do begin ParamName := List[i].Name; if LinkToParamNames then ParamName := SearchLink(ParamName, Func, '', true); WriteParameter(ParamName, List[i].Value); end; WriteDirect('\end{description}',true); end; procedure WriteSeeAlso(SeeAlso: TStringPairVector); var i: integer; SeeAlsoItem: TBaseItem; SeeAlsoLink: string; begin if ObjectVectorIsNilOrEmpty(SeeAlso) then Exit; if not AlreadyWithinAList then WriteStartList(FLanguage.Translation[trSeeAlso]); WriteDirect('\item[\textbf{' + FLanguage.Translation[trSeeAlso] + '}]',true); WriteDirect('\begin{description}',true); for i := 0 to SeeAlso.Count - 1 do begin SeeAlsoLink := SearchLink(SeeAlso[i].Name, AItem, SeeAlso[i].Value, true, SeeAlsoItem); WriteDirect('\item['); if SeeAlsoItem <> nil then WriteDirect(SeeAlsoLink) else WriteConverted(SeeAlso[i].Name); WriteDirectLine('] '); if (SeeAlsoItem <> nil) and (SeeAlsoItem is TPasItem) then WriteDirect(TPasItem(SeeAlsoItem).AbstractDescription); WriteDirectLine(''); end; WriteDirect('\end{description}',true); if not AlreadyWithinAList then WriteEndList; end; procedure WriteReturnDesc(Func: TPasMethod; ReturnDesc: string); begin if ReturnDesc = '' then exit; WriteDirect('\item[\textbf{'+FLanguage.Translation[trReturns]+'}]'); WriteSpellChecked(ReturnDesc); WriteDirect('',true); end; procedure WriteHintDirective(const S: string; const Note: string = ''); var Text: string; begin Text := FLanguage.Translation[trWarning] + ': ' + S; if Note <> '' then Text := Text + ': ' + Note else Text := Text + '.'; Text := Text + LineEnding + LineEnding; WriteConverted(Text); end; var Ancestor: TBaseItem; AncestorName: string; AItemMethod: TPasMethod; EnumMember: TPasItem; i: Integer; begin if not Assigned(AItem) then Exit; if hdDeprecated in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trDeprecated], AItem.DeprecatedNote); if hdPlatform in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trPlatformSpecific]); if hdLibrary in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trLibrarySpecific]); if hdExperimental in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trExperimental]); if AItem.AbstractDescription <> '' then begin WriteSpellChecked(AItem.AbstractDescription); if AItem.DetailedDescription <> '' then begin if not AItem.AbstractDescriptionWasAutomatic then begin WriteDirect('\hfill\vspace*{1ex}',true); WriteDirect('',true); end; WriteSpellChecked(AItem.DetailedDescription); end; end else begin if AItem.DetailedDescription <> '' then begin WriteSpellChecked(AItem.DetailedDescription); end else begin if (AItem is TPasCio) and (TPasCio(AItem).Ancestors.Count <> 0) then begin AncestorName := TPasCio(AItem).Ancestors.FirstName; Ancestor := TPasCio(AItem).FirstAncestor; if Assigned(Ancestor) and (Ancestor is TPasItem) then begin WriteConverted(Format('no description available, %s description follows', [AncestorName])); WriteItemLongDescription(TPasItem(Ancestor), AlreadyWithinAList); end; end else begin WriteDirect(' '); end; end; end; if (AItem is TPasMethod) and TPasMethod(AItem).HasMethodOptionalInfo then begin WriteStartOfParagraph; AItemMethod := TPasMethod(AItem); WriteParamsOrRaises(AItemMethod, FLanguage.Translation[trParameters], AItemMethod.Params, false); WriteReturnDesc(AItemMethod, AItemMethod.Returns); { In LaTeX generator I use trExceptions, not trExceptionsRaised, because trExceptionsRaised is just too long and so everything would look too ugly. However it's preferred to use trExceptionsRaised in the future (then trExceptions can be simply removed from PasDoc_Languages), because trExceptionsRaised is just more understandable to the reader of documentation. } WriteParamsOrRaises(AItemMethod, FLanguage.Translation[trExceptions], AItemMethod.Raises, true); end; WriteSeeAlso(AItem.SeeAlso); if AItem is TPasEnum then begin WriteDirect('\item[\textbf{' + FLanguage.Translation[trValues] + '}]',true); WriteDirectLine('\begin{description}'); for i := 0 to TPasEnum(AItem).Members.Count - 1 do begin EnumMember := TPasEnum(AItem).Members.PasItemAt[i]; WriteDirect('\item[\texttt{'); { Use EnumMember.FullDeclaration, not just EnumMember.Name. This is important for enums with explicit numeric value, like "me1 := 1". } WriteConverted(EnumMember.FullDeclaration); WriteDirect('}] '); { We have to place anchor outside of the \item[], otherwise it doesn't work... } WriteAnchor('', EnumMember.FullLink); WriteItemLongDescription(EnumMember, false); WriteDirectLine(''); end; WriteDirectLine('\end{description}'); end; end; procedure TTexDocGenerator.WriteFieldsProperties(HL: integer; const Items: TPasItems; ShowVisibility: boolean; SectionName: TTranslationId); var j: Integer; Item: TPasItem; s, Visibility: string; begin if FLatex2Rtf then WriteItemsDetailed(HL, Items, ShowVisibility, SectionName) else begin if ObjectVectorIsNilOrEmpty(Items) then Exit; WriteHeading(HL, FLanguage.Translation[SectionName]); { Determine the longest string used. This is the one we will use for determining the label width. } s:=''; for j := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[j]; if length(s) < length(Item.Name) then s := Item.Name; end; WriteStartList(s); for j := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[j]; WriteAnchor(Item.Name, Item.FullLink); if ShowVisibility then Visibility := string(VisibilityStr[Item.Visibility]) + ' ' else Visibility := ''; WriteDeclarationItem(Item, Item.Name, Visibility + Item.FullDeclaration); WriteDirectLine(''); WriteDirect('\par '); WriteItemLongDescription(Item, true); end; WriteEndList; end; end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteAnchor(ItemName, Link: string); begin { No links in RTF documentation -- latex2rtf can't really handle them. docs.aux must be generated by user using some normal latex program (like latex or pdflatex), and then passed to latex2rtf. See Latex2RtfOutput page on pasdoc wiki. } if FLatex2rtf then exit; if Link <> '' then WriteDirect('\label{'+Link+'}',true) else WriteDirect('\label{'+ItemName+'}',true); WriteDirect('\index{'+ConvertString(ItemName)+'}',true); end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteStartOfCode; begin WriteDirect('\begin{ttfamily}',true); end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteStartOfDocument(AName: string); var Index: integer; begin { write basic header } WriteAppInfo; WriteDirect('\documentclass{report}',true); WriteDirect('\usepackage{hyperref}',true); WriteDirect('% WARNING: THIS SHOULD BE MODIFIED DEPENDING ON THE LETTER/A4 SIZE',true); WriteDirect('\oddsidemargin 0cm',true); WriteDirect('\evensidemargin 0cm',true); WriteDirect('\marginparsep 0cm',true); WriteDirect('\marginparwidth 0cm',true); WriteDirect('\parindent 0cm',true); for Index := 0 to LatexHead.Count -1 do begin WriteDirect(LatexHead[Index], true); end; if not FLatex2Rtf then begin WriteDirect('\setlength{\textwidth}{\paperwidth}',true); WriteDirect('\addtolength{\textwidth}{-2in}',true); end else WriteDirect('\textwidth 16.5cm',true); WriteDirect('',true); WritePDFIfDef; { Use graphicx package (for @image tag) } WriteDirectLine( '\ifpdf' + LineEnding + ' \usepackage[pdftex]{graphicx}' + LineEnding + '\else' + LineEnding + ' \usepackage[dvips]{graphicx}' + LineEnding + '\fi'); Title := ConvertString(Title); WritePDFDocInfo(Title); WriteDirect('',true); WriteDirect('\begin{document}',true); if not Flatex2rtf then begin if Title <> '' then begin WriteDirect('\title{'+Title+'}',true); WriteDirect('\author{Pasdoc}',true); WriteDirect('\maketitle',true); WriteDirect('\newpage',true); end; WriteDirect('\label{toc}'); WriteDirect('\tableofcontents',true); WriteDirect('\newpage',true); end; WriteDirect('% special variable used for calculating some widths.',true); WriteDirect('\newlength{\tmplength}',true); end; procedure TTexDocGenerator.WriteStartOfParagraph; begin WriteDirect('\par',true); end; {$IFDEF unused} procedure TTexDocGenerator.WriteStartOfTable1Column(T: String); begin FOddTableRow := 0; NumCells := 1; WriteDirect('\begin{tabular}{|l|}',true); WriteDirect('\hline',true); if t <> '' then begin WriteConverted(t); WriteDirect(' \\',true); WriteDirect('\hline',true); end; end; procedure TTexDocGenerator.WriteStartOfTable2Columns(T1, T2: String); begin WriteDirect('\begin{tabular}{|ll|}',true); WriteDirect('\hline',true); if t1 <> '' then Begin WriteConverted(t1); WriteDirect(' & '); WriteConverted(t2); WriteDirect(' \\',true); WriteDirect('\hline',true); end; NumCells := 2; end; procedure TTexDocGenerator.WriteStartOfTable3Columns(T1, T2, T3: String); begin WriteDirect('\begin{tabular}{|lll|}',true); WriteDirect('\hline',true); WriteConverted(T1); WriteDirect(' & '); WriteConverted(T2); WriteDirect(' & '); WriteConverted(T3); WriteDirect(' \\',true); WriteDirect('\hline',true); NumCells := 3; end; procedure TTexDocGenerator.WriteStartOfTableRow; begin CellCounter := 0; end; {$ELSE} {$ENDIF} { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteUnit(const HL: integer; const U: TPasUnit); procedure WriteUnitDescription(HL: integer; U: TPasUnit); begin WriteHeading(HL, FLanguage.Translation[trDescription]); WriteItemLongDescription(U, false); WriteDirect('',true); end; procedure WriteUnitUses(const HL: integer; U: TPasUnit); var i: Integer; ULink: TPasItem; begin if WriteUsesClause and not IsEmpty(U.UsesUnits) then begin WriteHeading(HL, FLanguage.Translation[trUses]); WriteDirect('\begin{itemize}',true); for i := 0 to U.UsesUnits.Count-1 do begin WriteDirect('\item '); ULink := TPasUnit(U.UsesUnits.Objects[i]); if ULink <> nil then begin WriteDirect(MakeItemLink(ULink, U.UsesUnits[i], lcNormal)); end else begin { MakeItemLink writes link names in tt font, so we follow the convention here and also use tt font. } WriteDirect('\begin{ttfamily}' + ConvertString(U.UsesUnits[i]) + '\end{ttfamily}'); end; end; WriteDirect('\end{itemize}',true); end; end; type TSections = (dsDescription, dsUses, dsClasses, dsFuncsProcs, dsTypes, dsConstants, dsVariables); TSectionSet = set of TSections; var SectionsAvailable: TSectionSet; procedure ConditionallyAddSection(Section: TSections; Condition: boolean); begin if Condition then Include(SectionsAvailable, Section); end; begin SectionsAvailable := [dsDescription]; ConditionallyAddSection(dsUses, WriteUsesClause and not IsEmpty(U.UsesUnits)); ConditionallyAddSection(dsClasses, not ObjectVectorIsNilOrEmpty(U.CIOs)); ConditionallyAddSection(dsFuncsProcs, not ObjectVectorIsNilOrEmpty(U.FuncsProcs)); ConditionallyAddSection(dsTypes, not ObjectVectorIsNilOrEmpty(U.Types)); ConditionallyAddSection(dsConstants, not ObjectVectorIsNilOrEmpty(U.Constants)); ConditionallyAddSection(dsVariables, not ObjectVectorIsNilOrEmpty(U.Variables)); DoMessage(2, pmtInformation, 'Writing Docs for unit "%s"', [U.Name]); if U.IsUnit then WriteHeading(HL, FLanguage.Translation[trUnit] + ' ' + U.Name) else if U.IsProgram then WriteHeading(HL, FLanguage.Translation[trProgram] + ' ' + U.Name) else WriteHeading(HL, FLanguage.Translation[trLibrary] + ' ' + U.Name); WriteAnchor(U.Name, U.FullLink); if HasDescription(U) then WriteUnitDescription(HL + 1, U); WriteUnitUses(HL + 1, U); if (U.CIOs.count <> 0) or (U.FuncsProcs.count <> 0) then WriteHeading(HL + 1, FLanguage.Translation[trOverview]); WriteItemsSummary(U.CIOs); WriteItemsSummary(U.FuncsProcs); WriteCIOs(HL + 1, U.CIOs); WriteItemsDetailed(HL + 1, U.FuncsProcs, false, trFunctionsAndProcedures); WriteItemsDetailed(HL + 1, U.Types, false, trTypes); WriteItemsDetailed(HL + 1, U.Constants, false, trConstants); WriteItemsDetailed(HL + 1, U.Variables, false, trVariables); WriteAuthors(HL + 1, U.Authors); WriteDates(HL + 1, U.Created, U.LastMod); end; { ---------------------------------------------------------------------------- } procedure TTexDocGenerator.WriteSpellChecked(const AString: string); var LErrors: TObjectVector; begin LErrors := TObjectVector.Create(True); try CheckString(AString, LErrors); WriteDirect(AString); { TODO: write here LErrors, like in TGenericHTMLDocGenerator.WriteSpellChecked } finally LErrors.Free end; end; function TTexDocGenerator.ConvertString(const S: String): String; const ReplacementArray: array[0..10] of TCharReplacement = ( (cChar: '$'; sSpec: '{\$}'), (cChar: '&'; sSpec: '{\&}'), (cChar: '%'; sSpec: '{\%}'), (cChar: '#'; sSpec: '{\#}'), (cChar: '{'; sSpec: '{\{}'), (cChar: '}'; sSpec: '{\}}'), (cChar: '>'; sSpec: '{$>$}'), (cChar: '<'; sSpec: '{$<$}'), (cChar: '^'; sSpec: '{\^{}}'), (cChar: '\'; sSpec: '{\textbackslash}'), (cChar: '_'; sSpec: '{\_}') ); begin Result := StringReplaceChars(S, ReplacementArray); end; function TTexDocGenerator.ConvertChar(c: char): String; begin ConvertChar := ConvertString(c); end; function TTexDocGenerator.EscapeURL(const AString: string): string; begin EscapeURL := AString; end; function TTexDocGenerator.Paragraph: string; begin Result := LineEnding + LineEnding; end; function TTexDocGenerator.ShortDash: string; begin Result := '{-}'; end; function TTexDocGenerator.LineBreak: string; begin (* We add '{}' at the end. Otherwise there would be LaTeX errors if user will put "[" character right after @br, producing LaTeX code that looks like: "...\\ [...". In such case (even if you put newline between \\ and [) LaTeX would think that you want to use optional \\ argument, "\\[extra-space]". Putting '{}' tells LaTeX explicitly that this "\\" command doesn't take the "extra-space" argument. *) Result := '\\{}'; end; function TTexDocGenerator.URLLink(const URL: string): string; begin if Latex2Rtf then (* latex2rtf doesn't understand \href (well, actually it doesn't understand \usepackage{hyperref} at all) *) Result := ConvertString(URL) else Result := '\href{' + EscapeURL(URL) + '}{' + ConvertString(URL) + '}'; end; procedure TTexDocGenerator.WriteExternalCore( const ExternalItem: TExternalItem; const Id: TTranslationID); var HL: integer; begin HL := 1; WriteHeading(HL, ExternalItem.Title); WriteAnchor(ExternalItem.Name, ExternalItem.FullLink); WriteSpellChecked(ExternalItem.DetailedDescription); WriteAuthors(HL + 1, ExternalItem.Authors); WriteDates(HL + 1, ExternalItem.Created, ExternalItem.LastMod); end; constructor TTexDocGenerator.Create(AOwner: TComponent); begin inherited; FLatexHead := TStringList.Create; FImages := TStringList.Create; end; destructor TTexDocGenerator.Destroy; begin FImages.Free; FLatexHead.Free; inherited; end; procedure TTexDocGenerator.SetLatexHead(const Value: TStrings); begin FLatexHead.Assign(Value); end; function TTexDocGenerator.FormatKeyWord(AString: string): string; begin result := '}\textbf{' + ConvertString(AString) + '}\texttt{'; end; function TTexDocGenerator.FormatCompilerComment(AString: string): string; begin result := '\textit{' + ConvertString(AString) + '}'; end; function TTexDocGenerator.FormatComment(AString: string): string; begin result := '\textit{' + ConvertString(AString) + '}'; end; function TTexDocGenerator.FormatAnchor(const Anchor: string): string; begin { No links in RTF documentation -- latex2rtf can't really handle them. docs.aux must be generated by user using some normal latex program (like latex or pdflatex), and then passed to latex2rtf. See Latex2RtfOutput page on pasdoc wiki. } if not FLatex2rtf then begin result := '\label{'+Anchor+'}' + LineEnding end else begin result := ''; end; end; function TTexDocGenerator.FormatSection(HL: integer; const Anchor, Caption: string): string; begin { We use `HL + 1' because user is allowed to use levels >= 1, and heading level 1 is reserved for section title. } result := FormatAnchor(Anchor) + FormatHeading(HL + 1, Caption); end; function TTexDocGenerator.FormatBold(const Text: string): string; begin Result := '\textbf{' + Text + '}'; end; function TTexDocGenerator.FormatItalic(const Text: string): string; begin Result := '\textit{' + Text + '}'; end; function TTexDocGenerator.FormatPreformatted(const Text: string): string; begin Result := '\begin{verbatim}' + Text + '\end{verbatim}'; end; function TTexDocGenerator.FormatList(ListData: TListData): string; const ListEnvironment: array[TListType]of string = ( 'itemize', 'enumerate', 'description' ); var ListItem: TListItemData; i: Integer; begin { LaTeX doesn't allow empty lists } if ListData.Count <> 0 then begin Result := Format('\begin{%s}', [ListEnvironment[ListData.ListType]]) + LineEnding; for i := 0 to ListData.Count - 1 do begin ListItem := ListData.Items[i] as TListItemData; if ListData.ListType = ltDefinition then begin Result := Result + '\item[' + ListItem.ItemLabel + '] ' + ListItem.Text + LineEnding; end else begin if ListData.ListType = ltOrdered then Result := Result + { We don't know here which counter we should set to Index. So we just set *all* four counters. Simple, and works. } Format( '\setcounter{enumi}{%d} ' + '\setcounter{enumii}{%0:d} ' + '\setcounter{enumiii}{%0:d} ' + '\setcounter{enumiv}{%0:d} ' + LineEnding, [ { Note that we set ListItem.Index - 1, so that resulting document will correctly display ListItem.Index. That's how LaTeX works. } ListItem.Index - 1 ]); Result := Result + '\item ' + ListItem.Text + LineEnding; end; end; Result := Result + Format('\end{%s}', [ListEnvironment[ListData.ListType]]); end; end; function TTexDocGenerator.FormatTable(Table: TTableData): string; var RowNum, ColNum: Integer; Row: TRowData; function CellContent(Row: TRowData; ColNum: Integer): string; begin Result := Row.Cells[ColNum]; if Row.Head then Result := FormatBold(Result); end; begin Result := Paragraph + '\begin{tabular}{' + DupeString('|l', Table.MaxCellCount) + '|}' + LineEnding + '\hline' + LineEnding; for RowNum := 0 to Table.Count - 1 do begin Row := Table.Items[RowNum] as TRowData; for ColNum := 0 to Row.Cells.Count - 2 do Result := Result + CellContent(Row, ColNum) + ' & '; { No '&' after the last cell of a row. } Result := Result + CellContent(Row, Row.Cells.Count - 1) + ' \\ \hline' + LineEnding; end; Result := Result + '\end{tabular}' + Paragraph; end; function TTexDocGenerator.FormatImage(FileNames: TStringList): string; { This behaves like FormatImage would behave if we would take only pdflatex into account. Returns the filename that you should insert into the output. } function FormatImagePdf: string; var ChosenFileName: string; ImageId, I: Integer; CopyNeeded: boolean; begin { Calculate ChosenFileName, i.e. choose right image format for pdf. pdf extension is preferred, otherwise png or jpg. } ChosenFileName := ''; for I := 0 to FileNames.Count - 1 do if LowerCase(ExtractFileExt(FileNames[I])) = '.pdf' then begin ChosenFileName := FileNames[I]; Break; end; if ChosenFileName = '' then begin for I := 0 to FileNames.Count - 1 do if (LowerCase(ExtractFileExt(FileNames[I])) = '.jpg') or (LowerCase(ExtractFileExt(FileNames[I])) = '.jpeg') or (LowerCase(ExtractFileExt(FileNames[I])) = '.png') then begin ChosenFileName := FileNames[I]; Break; end; if ChosenFileName = '' then ChosenFileName := FileNames[0]; end; { Calculate ImageId and CopyNeeded } ImageId := FImages.IndexOf(ChosenFileName); CopyNeeded := ImageId = -1; if CopyNeeded then ImageId := FImages.Add(ChosenFileName); Result := 'image_' + IntToStr(ImageId) + ExtractFileExt(ChosenFileName); if CopyNeeded then CopyFile(ChosenFileName, DestinationDirectory + Result); end; { This behaves like FormatImage would behave if we would take only dvi output (i.e. normal latex) into account. Returns the filename that you should insert into the output. } function FormatImageDvi: string; var ChosenFileName: string; ImageId, I: Integer; CopyNeeded: boolean; begin { Calculate ChosenFileName, i.e. choose right image format for dvi. eps extension is preferred. } ChosenFileName := ''; for I := 0 to FileNames.Count - 1 do if LowerCase(ExtractFileExt(FileNames[I])) = '.eps' then begin ChosenFileName := FileNames[I]; Break; end; if ChosenFileName = '' then ChosenFileName := FileNames[0]; { Calculate ImageId and CopyNeeded } ImageId := FImages.IndexOf(ChosenFileName); CopyNeeded := ImageId = -1; if CopyNeeded then ImageId := FImages.Add(ChosenFileName); Result := 'image_' + IntToStr(ImageId) + ExtractFileExt(ChosenFileName); if CopyNeeded then CopyFile(ChosenFileName, DestinationDirectory + Result); end; var SImagePdf, SImageDvi: string; begin { I call FormatImageXxx funcs first, before calculating Result, to make sure that FormatImageXxx are called in determined order. Otherwise e.g. FPC 2.0.4 calculated S := S1 + S2 by calling S2 function first, while FPC 2.1.3 (fixes_2_2 branch) and 2.3.1 (trunk) call S1 first. The determined order is not needed for pasdoc correctness (they actually *can* be called in any order), but it's needed to make results determined --- e.g. for comparing two test results, like with our ../../tests/. } SImageDvi := FormatImageDvi; SImagePdf := FormatImagePdf; Result := '\begin{figure}' + LineEnding + ' \ifpdf' + LineEnding + ' \includegraphics{' + EscapeURL(SImagePdf) + '}' + LineEnding + ' \else' + LineEnding + ' \includegraphics{' + EscapeURL(SImageDvi) + '}' + LineEnding + ' \fi' + LineEnding + '\end{figure}' + LineEnding; end; end. ����������������������������������������������pasdoc/source/component/PasDoc_Items.pas������������������������������������������������������������0000644�0001750�0001750�00000247471�13237143042�021032� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(defines all items that can appear within a Pascal unit's interface) @created(11 Mar 1999) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Michalis Kamburelis) @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Damien Honeyford) @author(Arno Garrels <first name.name@nospamgmx.de>) For each item (type, variable, class etc.) that may appear in a Pascal source code file and can thus be taken into the documentation, this unit provides an object type which will store name, unit, description and more on this item. } unit PasDoc_Items; {$I PasDoc_Defines.inc} interface uses SysUtils, PasDoc_Types, PasDoc_StringVector, PasDoc_ObjectVector, PasDoc_Hashes, Classes, PasDoc_TagManager, PasDoc_Serialize, PasDoc_SortSettings, PasDoc_StringPairVector; type { Visibility of a field/method. } TVisibility = ( { indicates field or method is published } viPublished, { indicates field or method is public } viPublic, { indicates field or method is protected } viProtected, { indicates field or method is strict protected } viStrictProtected, { indicates field or method is private } viPrivate, { indicates field or method is strict private } viStrictPrivate, { indicates field or method is automated } viAutomated, { implicit visibility, marks the implicit members if user used @--implicit-visibility=implicit command-line option. } viImplicit ); TVisibilities = set of TVisibility; const VisibilityStr: array[TVisibility] of string[16] = ( 'published', 'public', 'protected', 'strict protected', 'private', 'strict private', 'automated', 'implicit' ); AllVisibilities: TVisibilities = [Low(TVisibility) .. High(TVisibility)]; DefaultVisibilities: TVisibilities = [viProtected, viPublic, viPublished, viAutomated]; type TPasCio = class; TPasMethod = class; TPasProperty = class; TPasUnit = class; TAnchorItem = class; TBaseItems = class; TPasItems = class; TPasMethods = class; TPasProperties = class; TPasNestedCios = class; TPasTypes = class; TPasEnum = class; { Raw description, in other words: the contents of comment before given item. Besides the content, this also specifies filename, begin and end positions of given comment. } TRawDescriptionInfo = record { This is the actual content the comment. } Content: string; // @name is the name of the TStream from which this comment was read. // Will be '' if no comment was found. It will be ' ' if // the comment was somehow read from more than one stream. StreamName: string; // @name is the position in the stream of the start of the comment. BeginPosition: Int64; // @name is the position in the stream of the character immediately // after the end of the comment describing the item. EndPosition: Int64; end; PRawDescriptionInfo = ^TRawDescriptionInfo; { This is a basic item class, that is linkable, and has some @link(RawDescription). } TBaseItem = class(TSerializable) private FDetailedDescription: string; FFullLink: string; FLastMod: string; FName: string; FAuthors: TStringVector; FCreated: string; FAutoLinkHereAllowed: boolean; FRawDescriptionInfo: TRawDescriptionInfo; procedure SetAuthors(const Value: TStringVector); function GetRawDescription: string; procedure WriteRawDescription(const Value: string); procedure StoreAuthorTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure StoreCreatedTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure StoreLastModTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure StoreCVSTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure PreHandleNoAutoLinkTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleNoAutoLinkTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); protected { Serialization of TPasItem need to store in stream only data that is generated by parser. That's because current approach treats "loading from cache" as equivalent to parsing a unit and stores to cache right after parsing a unit. So what is generated by parser must be written to cache. That said, @orderedList( @item( It will not break anything if you will accidentally store in cache something that is not generated by parser. That's because saving to cache will be done anyway right after doing parsing, so properties not initialized by parser will have their initial values anyway. You're just wasting memory for cache, and some cache saving/loading time.) @item( For now, in implementation of serialize/deserialize we try to add even things not generated by parser in a commented out code. This way if approach to cache will change some day, we will be able to use this code.) ) } procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; public constructor Create; override; destructor Destroy; override; { It registers @link(TTag)s that init @link(Authors), @link(Created), @link(LastMod) and remove relevant tags from description. You can override it to add more handlers. } procedure RegisterTags(TagManager: TTagManager); virtual; { Search for an item called ItemName @italic(inside this Pascal item). For units, it searches for items declared @italic(inside this unit) (like a procedure, or a class in this unit). For classes it searches for items declared @italic(within this class) (like a method or a property). For an enumerated type, it searches for members of this enumerated type. All normal rules of ObjectPascal scope apply, which means that e.g. if this item is a unit, @name searches for a class named ItemName but it @italic(doesn't) search for a method named ItemName inside some class of this unit. Just like in ObjectPascal the scope of identifiers declared within the class always stays within the class. Of course, in ObjectPascal you can qualify a method name with a class name, and you can also do such qualified links in pasdoc, but this is not handled by this routine (see @link(FindName) instead). Returns nil if not found. Note that it never compares ItemName with Self.Name. You may want to check this yourself if you want. Note that for TPasItem descendants, it always returns also some TPasItem descendant (so if you use this method with some TPasItem instance, you can safely cast result of this method to TPasItem). Implementation in this class always returns nil. Override as necessary. } function FindItem(const ItemName: string): TBaseItem; virtual; { This is just like @link(FindItem), but in case of classes or such it should also search within ancestors. In this class, the default implementation just calls FindItem. } function FindItemMaybeInAncestors(const ItemName: string): TBaseItem; virtual; { Do all you can to find link specified by NameParts. While searching this tries to mimic ObjectPascal identifier scope as much as it can. It seaches within this item, but also within class enclosing this item, within ancestors of this class, within unit enclosing this item, then within units used by unit of this item. } function FindName(const NameParts: TNameParts): TBaseItem; virtual; { Detailed description of this item. In case of TPasItem, this is something more elaborate than @link(TPasItem.AbstractDescription). This is already in the form suitable for final output, ready to be put inside final documentation. } property DetailedDescription: string read FDetailedDescription write FDetailedDescription; { This stores unexpanded version (as specified in user's comment in source code of parsed units) of description of this item. Actually, this is just a shortcut to @code(@link(RawDescriptionInfo).Content) } property RawDescription: string read GetRawDescription write WriteRawDescription; { Full info about @link(RawDescription) of this item, including it's filename and position. This is intended to be initialized by parser. This returns @link(PRawDescriptionInfo) instead of just @link(TRawDescriptionInfo) to allow natural setting of properties of this record (otherwise @longCode(# Item.RawDescriptionInfo.StreamName := 'foo'; #) would not work as expected) . } function RawDescriptionInfo: PRawDescriptionInfo; { a full link that should be enough to link this item from anywhere else } property FullLink: string read FFullLink write FFullLink; { Contains '' or string with date of last modification. This string is already in the form suitable for final output format (i.e. already processed by TDocGenerator.ConvertString). } property LastMod: string read FLastMod write FLastMod; { name of the item } property Name: string read FName write FName; { Returns the qualified name of the item. This is intended to return a concise and not ambigous name. E.g. in case of TPasItem it is overridden to return Name qualified by class name and unit name. In this class this simply returns Name. } function QualifiedName: String; virtual; { list of strings, each representing one author of this item } property Authors: TStringVector read FAuthors write SetAuthors; { Contains '' or string with date of creation. This string is already in the form suitable for final output format (i.e. already processed by TDocGenerator.ConvertString). } property Created: string read FCreated; { Is auto-link mechanism allowed to create link to this item ? This may be set to @false by @@noAutoLinkHere tag in item's description. } property AutoLinkHereAllowed: boolean read FAutoLinkHereAllowed write FAutoLinkHereAllowed default true; { The full (absolute) path used to resolve filenames in this item's descriptions. Must always end with PathDelim. In this class, this simply returns GetCurrentDir (with PathDelim added if needed). } function BasePath: string; virtual; end; THintDirective = (hdDeprecated, hdPlatform, hdLibrary, hdExperimental); THintDirectives = set of THintDirective; { This is a @link(TBaseItem) descendant that is always declared inside some Pascal source file. Parser creates only items of this class (e.g. never some basic @link(TBaseItem) instance). This class introduces properties and methods pointing to parent unit (@link(MyUnit)) and parent class/interface/object/record (@link(MyObject)). Also many other things not needed at @link(TBaseItem) level are introduced here: things related to handling @@abstract tag, @@seealso tag, used to sorting items inside (@link(Sort)) and some more. } TPasItem = class(TBaseItem) private FAbstractDescription: string; FAbstractDescriptionWasAutomatic: boolean; FVisibility: TVisibility; FMyEnum: TPasEnum; FMyObject: TPasCio; FMyUnit: TPasUnit; FHintDirectives: THintDirectives; FDeprecatedNote: string; FFullDeclaration: string; FSeeAlso: TStringPairVector; FCachedUnitRelativeQualifiedName: string; //< do not serialize FAttributes: TStringPairVector; procedure StoreAbstractTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleDeprecatedTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleSeeAlsoTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); protected procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; { This does the same thing as @link(FindName) but it @italic(doesn't) scan other units. If this item is a unit, it searches only inside this unit, else it searches only inside @link(MyUnit) unit. Actually @link(FindName) uses this function. } function FindNameWithinUnit(const NameParts: TNameParts): TBaseItem; virtual; public constructor Create; override; destructor Destroy; override; function FindName(const NameParts: TNameParts): TBaseItem; override; procedure RegisterTags(TagManager: TTagManager); override; { Abstract description of this item. This is intended to be short (e.g. one sentence) description of this object. This will be inited from @@abstract tag in RawDescription, or cutted out from first sentence in RawDescription if @--auto-abstract was used. Note that this is already in the form suitable for final output, with tags expanded, chars converted etc. } property AbstractDescription: string read FAbstractDescription write FAbstractDescription; (* TDocGenerator.ExpandDescriptions sets this property to true if AutoAbstract was used and AbstractDescription of this item was automatically deduced from the 1st sentence of RawDescription. Otherwise (if @@abstract was specified explicitly, or there was no @@abstract and AutoAbstract was false) this is set to false. This is a useful hint for generators: it tells them that when they are printing @italic(both) AbstractDescription and DetailedDescription of the item in one place (e.g. TTexDocGenerator.WriteItemLongDescription and TGenericHTMLDocGenerator.WriteItemLongDescription both do this) then they should @italic(not) put any additional space between AbstractDescription and DetailedDescription. This way when user will specify description like @longcode(# { First sentence. Second sentence. } procedure Foo; #) and @--auto-abstract was on, then "First sentence." is the AbstractDescription, " Second sentence." is DetailedDescription, AbstractDescriptionWasAutomatic is true and and TGenericHTMLDocGenerator.WriteItemLongDescription can print them as "First sentence. Second sentence." Without this property, TGenericHTMLDocGenerator.WriteItemLongDescription would not be able to say that this abstract was deduced automatically and would print additional paragraph break that was not present in desscription, i.e. "First sentence.<p> Second sentence." *) property AbstractDescriptionWasAutomatic: boolean read FAbstractDescriptionWasAutomatic write FAbstractDescriptionWasAutomatic; { Returns true if there is a DetailledDescription or AbstractDescription available. } function HasDescription: Boolean; function QualifiedName: String; override; function UnitRelativeQualifiedName: string; virtual; { Unit of this item. } property MyUnit: TPasUnit read FMyUnit write FMyUnit; { If this item is part of a class (or record, object., interface...), the corresponding class is stored here. @nil otherwise. } property MyObject: TPasCio read FMyObject write FMyObject; { If this item is a member of an enumerated type, then the enclosing enumerated type is stored here. @nil otherwise. } property MyEnum: TPasEnum read FMyEnum write FMyEnum; property Visibility: TVisibility read FVisibility write FVisibility; { Hint directives specify is this item deprecated, platform-specific, library-specific, or experimental. } property HintDirectives: THintDirectives read FHintDirectives write FHintDirectives; { Deprecation note, specified as a string after "deprecated" directive. Empty if none, always empty if @link(HintDirectives) does not contain hdDeprecated. } property DeprecatedNote: string read FDeprecatedNote write FDeprecatedNote; { This recursively sorts all items inside this item, and all items inside these items, etc. E.g. in case of TPasUnit, this method sorts all variables, consts, CIOs etc. inside (honouring SortSettings), and also recursively calls Sort(SortSettings) for every CIO. Note that this does not guarantee that absolutely everything inside will be really sorted. Some items may be deliberately left unsorted, e.g. Members of TPasEnum are never sorted (their declared order always matters, so we shouldn't sort them when displaying their documentation --- reader of such documentation would be seriously misleaded). Sorting of other things depends on SortSettings --- e.g. without ssMethods, CIOs methods will not be sorted. So actually this method @italic(makes sure that all things that should be sorted are really sorted). } procedure Sort(const SortSettings: TSortSettings); virtual; { Full declaration of the item. This is full parsed declaration of the given item. Note that that this is not used for some descendants. Right now it's used only with @unorderedList( @item TPasConstant @item TPasFieldVariable (includes type, default values, etc.) @item TPasType @item TPasMethod (includes parameter list, procedural directives, etc.) @item TPasProperty (includes read/write and storage specifiers, etc.) @item(TPasEnum But in this special case, '...' is used instead of listing individual members, e.g. 'TEnumName = (...)'. You can get list of Members using TPasEnum.Members. Eventual specifics of each member should be also specified somewhere inside Members items, e.g. @longcode# TMyEnum = (meOne, meTwo = 3); # and @longcode# TMyEnum = (meOne, meTwo); # will both result in TPasEnum with equal FullDeclaration (just @code('TMyEnum = (...)')) but this @code('= 3') should be marked somewhere inside Members[1] properties.) @item TPasItem when it's a CIO's field. ) The intention is that in the future all TPasItem descendants will always have approprtate FullDeclaration set. It all requires adjusting appropriate places in PasDoc_Parser to generate appropriate FullDeclaration. } property FullDeclaration: string read FFullDeclaration write FFullDeclaration; { Items here are collected from @@seealso tags. Name of each item is the 1st part of @@seealso parameter. Value is the 2nd part of @@seealso parameter. } property SeeAlso: TStringPairVector read FSeeAlso; { List of attributes defined for this item } property Attributes: TStringPairVector read FAttributes; procedure SetAttributes(var Value: TStringPairVector); function BasePath: string; override; end; { @abstract(Pascal constant.) Precise definition of "constant" for pasdoc purposes is "a name associated with a value". Optionally, constant type may also be specified in declararion. Well, Pascal constant always has some type, but pasdoc is too weak to determine the implicit type of a constant, i.e. to unserstand that constand @code(const A = 1) is of type Integer. } TPasConstant = class(TPasItem) end; { @abstract(Pascal global variable or field or nested constant of CIO.) Precise definition is "a name with some type". And Optionally with some initial value, for global variables. It also holds a nested constant of extended classes and records. In the future we may introduce here some property like Type: TPasType. } TPasFieldVariable = class(TPasItem) private FIsConstant: Boolean; protected procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; public { @abstract(Set if this is a nested constant field) } property IsConstant: Boolean read FIsConstant write FIsConstant; end; { @abstract(Pascal type (but not a procedural type --- these are expressed as @link(TPasMethod).)) } TPasType = class(TPasItem) end; { @abstract(Enumerated type.) } TPasEnum = class(TPasType) protected FMembers: TPasItems; procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; procedure StoreValueTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); public procedure RegisterTags(TagManager: TTagManager); override; { Searches for a member of this enumerated type. } function FindItem(const ItemName: string): TBaseItem; override; destructor Destroy; override; constructor Create; override; property Members: TPasItems read FMembers; end; { Methodtype for @link(TPasMethod) } TMethodType = (METHOD_CONSTRUCTOR, METHOD_DESTRUCTOR, METHOD_FUNCTION, METHOD_PROCEDURE, METHOD_OPERATOR); { This represents: @orderedList( @item global function/procedure, @item method (function/procedure of a class/interface/object), @item pointer type to one of the above (in this case Name is the type name). ) } TPasMethod = class(TPasItem) protected FParams: TStringPairVector; FReturns: string; FRaises: TStringPairVector; FWhat: TMethodType; procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; procedure StoreRaisesTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure StoreParamTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure StoreReturnsTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); public constructor Create; override; destructor Destroy; override; { In addition to inherited, this also registers @link(TTag)s that init @link(Params), @link(Returns) and @link(Raises) and remove according tags from description. } procedure RegisterTags(TagManager: TTagManager); override; { } property What: TMethodType read FWhat write FWhat; { Note that Params, Returns, Raises are already in the form processed by @link(TTagManager.Execute), i.e. with links resolved, html characters escaped etc. So @italic(don't) convert them (e.g. before writing to the final docs) once again (by some ExpandDescription or ConvertString or anything like that). } { } { Name of each item is the name of parameter (without any surrounding whitespace), Value of each item is users description for this item (in already-expanded form). } property Params: TStringPairVector read FParams; property Returns: string read FReturns; { Name of each item is the name of exception class (without any surrounding whitespace), Value of each item is users description for this item (in already-expanded form). } property Raises: TStringPairVector read FRaises; { Are some optional properties (i.e. the ones that may be empty for TPasMethod after parsing unit and expanding tags --- currently this means @link(Params), @link(Returns) and @link(Raises)) specified ? } function HasMethodOptionalInfo: boolean; end; TPasProperty = class(TPasItem) protected FDefault: Boolean; FNoDefault: Boolean; FIndexDecl: string; FStoredID: string; FDefaultID: string; FWriter: string; FPropType: string; FReader: string; procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; public { contains the optional index declaration, including brackets } property IndexDecl: string read FIndexDecl write FIndexDecl; { contains the type of the property } property Proptype: string read FPropType write FPropType; { read specifier } property Reader: string read FReader write FReader; { write specifier } property Writer: string read FWriter write FWriter; { true if the property is the default property } property Default: Boolean read FDefault write FDefault; { keeps default value specifier } property DefaultID: string read FDefaultID write FDefaultID; { true if Nodefault property } property NoDefault: Boolean read FNoDefault write FNoDefault; { keeps Stored specifier } property StoredId: string read FStoredID write FStoredID; end; { enumeration type to determine type of @link(TPasCio) item } TCIOType = (CIO_CLASS, CIO_PACKEDCLASS, CIO_DISPINTERFACE, CIO_INTERFACE, CIO_OBJECT, CIO_PACKEDOBJECT, CIO_RECORD, CIO_PACKEDRECORD ); TClassDirective = (CT_NONE, CT_ABSTRACT, CT_SEALED, CT_HELPER); { @abstract(Extends @link(TPasItem) to store all items in a class / an object, e.g. fields.) } TPasCio = class(TPasType) protected FClassDirective: TClassDirective; FFields: TPasItems; FMethods: TPasMethods; FProperties: TPasProperties; FAncestors: TStringPairVector; FOutputFileName: string; FMyType: TCIOType; FHelperTypeIdentifier: string; FCios: TPasNestedCios; FTypes: TPasTypes; FNameWithGeneric: string; procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; protected procedure StoreMemberTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); public constructor Create; override; destructor Destroy; override; { If this class (or interface or object) contains a field, method or property with the name of ItemName, the corresponding item pointer is returned. } function FindItem(const ItemName: string): TBaseItem; override; function FindItemMaybeInAncestors(const ItemName: string): TBaseItem; override; { This searches for item (field, method or property) defined in ancestor of this cio. I.e. searches within the FirstAncestor, then within FirstAncestor.FirstAncestor, and so on. Returns nil if not found. } function FindItemInAncestors(const ItemName: string): TPasItem; procedure Sort(const SortSettings: TSortSettings); override; procedure RegisterTags(TagManager: TTagManager); override; public { Name of the ancestor (class, object, interface). Each item is a TStringPair, with @unorderedList( @item @code(Name) is the name (single Pascal identifier) of this ancestor, @item(@code(Value) is the full declaration of this ancestor. For example, in addition to Name, this may include "specialize" directive (for FPC generic specialization) at the beginning. And "<foo,bar>" section at the end (for FPC or Delphi generic specialization).) @item(@code(Data) is a TPasItem reference to this ancestor, or @nil if not found. This is assigned only in TDocGenerator.BuildLinks.) ) Note that each ancestor is a TPasItem, @italic(not necessarily) TPasCio. Consider e.g. the case @longcode(# TMyStringList = Classes.TStringList; TMyExtendedStringList = class(TMyStringList) ... end; #) At least for now, such declaration will result in TPasType (not TPasCio!) with Name = 'TMyStringList', which means that ancestor of TMyExtendedStringList will be a TPasType instance. Note that the PasDoc_Parser already takes care of correctly setting Ancestors when user didn't specify any ancestor name at cio declaration. E.g. if this cio is a class, and user didn't specify ancestor name at class declaration, and this class name is not 'TObject' (in case pasdoc parses the RTL), the Ancestors[0] will be set to 'TObject'. } property Ancestors: TStringPairVector read FAncestors; { Nested classes (and records, interfaces...). } property Cios: TPasNestedCios read FCios; {@name is used to indicate whether a class is sealed or abstract.} property ClassDirective: TClassDirective read FClassDirective write FClassDirective; { This returns Ancestors[0].Data, i.e. instance of the first ancestor of this Cio (or nil if it couldn't be found), or nil if Ancestors.Count = 0. } function FirstAncestor: TPasItem; { This returns the name of first ancestor of this Cio. If Ancestor.Count > 0 then it simply returns Ancestors[0], i.e. the name of the first ancestor as was specified at class declaration, else it returns ''. So this method is @italic(roughly) something like @code(FirstAncestor.Name), but with a few notable differences: @unorderedList( @item( FirstAncestor is nil if the ancestor was not found in items parsed by pasdoc. But this method will still return in this case name of ancestor.) @item(@code(FirstAncestor.Name) is the name of ancestor as specified at declaration of an ancestor. But this method is the name of ancestor as specified at declaration of this cio --- with the same letter case, with optional unit specifier.) ) If this function returns '', then you can be sure that FirstAncestor returns nil. The other way around is not necessarily true --- FirstAncestor may be nil, but still this function may return something <> ''. } function FirstAncestorName: string; { list of all fields } property Fields: TPasItems read FFields; { Class or record helper type identifier } property HelperTypeIdentifier: string read FHelperTypeIdentifier write FHelperTypeIdentifier; { list of all methods } property Methods: TPasMethods read FMethods; { list of properties } property Properties: TPasProperties read FProperties; { determines if this is a class, an interface or an object } property MyType: TCIOType read FMyType write FMyType; { name of documentation output file (if each class / object gets its own file, that's the case for HTML, but not for TeX) } property OutputFileName: string read FOutputFileName write FOutputFileName; //function QualifiedName: String; override; { Is Visibility of items (Fields, Methods, Properties) important ? } function ShowVisibility: boolean; { Simple nested types (that don't fall into @link(Cios)). } property Types: TPasTypes read FTypes; { Name, with optional "generic" directive before (for FPC generics) and generic type identifiers list "<foo,bar>" after (for FPC and Delphi generics). } property NameWithGeneric: string read FNameWithGeneric write FNameWithGeneric; end; EAnchorAlreadyExists = class(Exception); { @name extends @link(TBaseItem) to store extra information about a project. @name is used to hold an introduction and conclusion to the project. } TExternalItem = class(TBaseItem) private FSourceFilename: string; FTitle: string; FShortTitle: string; FOutputFileName: string; // See @link(Anchors). FAnchors: TBaseItems; procedure SetOutputFileName(const Value: string); protected procedure HandleTitleTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); procedure HandleShortTitleTag(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); public Constructor Create; override; destructor Destroy; override; procedure RegisterTags(TagManager: TTagManager); override; { name of documentation output file } property OutputFileName: string read FOutputFileName write SetOutputFileName; property ShortTitle: string read FShortTitle write FShortTitle; property SourceFileName: string read FSourceFilename write FSourceFilename; property Title: string read FTitle write FTitle; function FindItem(const ItemName: string): TBaseItem; override; procedure AddAnchor(const AnchorItem: TAnchorItem); overload; { If item with Name (case ignored) already exists, this raises exception EAnchorAlreadyExists. Otherwise it adds TAnchorItem with given name to Anchors. It also returns created TAnchorItem. } function AddAnchor(const AnchorName: string): TAnchorItem; overload; // @name holds a list of @link(TAnchorItem)s that represent anchors and // sections within the @classname. The @link(TAnchorItem)s have no content // so, they should not be indexed separately. property Anchors: TBaseItems read FAnchors; function BasePath: string; override; end; TAnchorItem = class(TBaseItem) private FExternalItem: TExternalItem; FSectionLevel: Integer; FSectionCaption: string; public property ExternalItem: TExternalItem read FExternalItem write FExternalItem; { If this is an anchor for a section, this tells section level (as was specified in the @@section tag). Otherwise this is 0. } property SectionLevel: Integer read FSectionLevel write FSectionLevel default 0; { If this is an anchor for a section, this tells section caption (as was specified in the @@section tag). } property SectionCaption: string read FSectionCaption write FSectionCaption; end; { extends @link(TPasItem) to store anything about a unit, its constants, types etc.; also provides methods for parsing a complete unit. Note: Remember to always set @link(CacheDateTime) after deserializing this unit. } TPasUnit = class(TPasItem) protected FTypes: TPasTypes; FVariables: TPasItems; FCIOs: TPasItems; FConstants: TPasItems; FFuncsProcs: TPasMethods; FUsesUnits: TStringVector; FSourceFilename: string; FOutputFileName: string; FCacheDateTime: TDateTime; FSourceFileDateTime: TDateTime; FIsUnit: boolean; FIsProgram: boolean; procedure Serialize(const ADestination: TStream); override; procedure Deserialize(const ASource: TStream); override; public constructor Create; override; destructor Destroy; override; procedure AddCIO(const i: TPasCio); procedure AddConstant(const i: TPasItem); procedure AddType(const i: TPasItem); procedure AddVariable(const i: TPasItem); function FindInsideSomeClass(const AClassName, ItemInsideClass: string): TPasItem; function FindInsideSomeEnum(const EnumName, EnumMember: string): TPasItem; function FindItem(const ItemName: string): TBaseItem; override; procedure Sort(const SortSettings: TSortSettings); override; public { list of classes, interfaces, objects, and records defined in this unit } property CIOs: TPasItems read FCIOs; { list of constants defined in this unit } property Constants: TPasItems read FConstants; { list of functions and procedures defined in this unit } property FuncsProcs: TPasMethods read FFuncsProcs; { The names of all units mentioned in a uses clause in the interface section of this unit. This is never nil. After @link(TDocGenerator.BuildLinks), for every i: UsesUnits.Objects[i] will point to TPasUnit object with Name = UsesUnits[i] (or nil, if pasdoc's didn't parse such unit). In other words, you will be able to use UsesUnits.Objects[i] to obtain given unit's instance, as parsed by pasdoc. } property UsesUnits: TStringVector read FUsesUnits; { list of types defined in this unit } property Types: TPasTypes read FTypes; { list of variables defined in this unit } property Variables: TPasItems read FVariables; { name of documentation output file THIS SHOULD NOT BE HERE! } property OutputFileName: string read FOutputFileName write FOutputFileName; property SourceFileName: string read FSourceFilename write FSourceFilename; property SourceFileDateTime: TDateTime read FSourceFileDateTime write FSourceFileDateTime; { If WasDeserialized then this specifies the datetime of a cache data of this unit, i.e. when cache data was generated. If cache was obtained from a file then this is just the cache file modification date/time. If not WasDeserialized then this property has undefined value -- don't use it. } property CacheDateTime: TDateTime read FCacheDateTime write FCacheDateTime; { If @false, then this is a program or library file, not a regular unit (though it's treated by pasdoc almost like a unit, so we use TPasUnit class for this). } property IsUnit: boolean read FIsUnit write FIsUnit; property IsProgram: boolean read FIsProgram write FIsProgram; { Returns if unit WasDeserialized, and file FileName exists, and file FileName is newer than CacheDateTime. So if FileName contains some info generated from information of this unit, then we can somehow assume that FileName still contains valid information and we don't have to write it once again. Sure, we're not really 100% sure that FileName still contains valid information, but that's how current approach to cache works. } function FileNewerThanCache(const FileName: string): boolean; function BasePath: string; override; end; { Container class to store a list of @link(TBaseItem)s. } TBaseItems = class(TObjectVector) private FHash: TObjectHash; procedure Serialize(const ADestination: TStream); procedure Deserialize(const ASource: TStream); public constructor Create(const AOwnsObject: Boolean); override; destructor Destroy; override; { Find a given item name on a list. In the base class (TBaseItems), this simply searches the items (not recursively). In some cases, it may look within the items (recursively), when the identifiers inside the item are in same namespace as the items themselves. Example: it will look also inside enumerated types members, because (when "scoped enums" are off) the enumerated members are in the same namespace as the enumerated type name. Returns @nil if nothing can be found. } function FindListItem(const AName: string): TBaseItem; { Inserts all items of C into this collection. Disposes C and sets it to nil. } procedure InsertItems(const c: TBaseItems); { During Add, AObject is associated with AObject.Name using hash table, so remember to set AObject.Name @italic(before) calling Add(AObject). } procedure Add(const AObject: TBaseItem); { This is a shortcut for doing @link(Clear) and then @link(Add Add(AObject)). Useful when you want the list to contain exactly the one given AObject. } procedure ClearAndAdd(const AObject: TBaseItem); procedure Delete(const AIndex: Integer); procedure Clear; override; end; { Container class to store a list of @link(TPasItem)s. } TPasItems = class(TBaseItems) private function GetPasItemAt(const AIndex: Integer): TPasItem; procedure SetPasItemAt(const AIndex: Integer; const Value: TPasItem); public { A comfortable routine that just calls inherited and casts result to TPasItem, since every item on this list must be always TPasItem. } function FindListItem(const AName: string): TPasItem; { Copies all Items from c to this object, not changing c at all. } procedure CopyItems(const c: TPasItems); { Counts classes, interfaces and objects within this collection. } procedure CountCIO(var c, i, o: Integer); { Checks each element's Visibility field and removes all elements with a value of viPrivate. } procedure RemovePrivateItems; property PasItemAt[const AIndex: Integer]: TPasItem read GetPasItemAt write SetPasItemAt; { This sorts all items on this list by their name, and also calls @link(TPasItem.Sort Sort(SortSettings)) for each of these items. This way it sorts recursively everything in this list. This is equivalent to doing both @link(SortShallow) and @link(SortOnlyInsideItems). } procedure SortDeep(const SortSettings: TSortSettings); { This calls @link(TPasItem.Sort Sort(SortSettings)) for each of items on the list. It does @italic(not) sort the items on this list. } procedure SortOnlyInsideItems(const SortSettings: TSortSettings); { This sorts all items on this list by their name. Unlike @link(SortDeep), it does @italic(not) call @link(TPasItem.Sort Sort) for each of these items. So "items inside items" (e.g. class methods, if this list contains TPasCio objects) remain unsorted. } procedure SortShallow; { Sets FullDeclaration of every item to @orderedList( @item Name of this item (only if PrefixName) @item + Suffix. ) Very useful if you have a couple of items that share a common declaration in source file, e.g. variables or fields declared like @longcode(# A, B: Integer; #) } procedure SetFullDeclaration(PrefixName: boolean; const Suffix: string); end; { Collection of methods. } TPasMethods = class(TPasItems) end; { Collection of properties. } TPasProperties = class(TPasItems) end; { Collection of classes / records / interfaces. } TPasNestedCios = class(TPasItems) public constructor Create; reintroduce; end; { Collection of types. } TPasTypes = class(TPasItems) function FindListItem(const AName: string): TPasItem; end; { Collection of units. } TPasUnits = class(TPasItems) private function GetUnitAt(const AIndex: Integer): TPasUnit; procedure SetUnitAt(const AIndex: Integer; const Value: TPasUnit); public property UnitAt[const AIndex: Integer]: TPasUnit read GetUnitAt write SetUnitAt; function ExistsUnit(const AUnit: TPasUnit): Boolean; end; const CIORecordType = [CIO_RECORD, CIO_PACKEDRECORD]; CIONonHierarchy = CIORecordType; EmptyRawDescriptionInfo: TRawDescriptionInfo = ( Content: ''; StreamName: ''; BeginPosition: -1; EndPosition: -1; ); { Returns lowercased keyword associated with given method type. } function MethodTypeToString(const MethodType: TMethodType): string; { Returns VisibilityStr for each value in Visibilities, delimited by commas. } function VisibilitiesToStr(const Visibilities: TVisibilities): string; function VisToStr(const Vis: TVisibility): string; implementation uses PasDoc_Utils, PasDoc_Tokenizer; function ComparePasItemsByName(PItem1, PItem2: Pointer): Integer; begin Result := CompareText(TPasItem(PItem1).UnitRelativeQualifiedName, TPasItem(PItem2).UnitRelativeQualifiedName); // Sort duplicate class names by unit name if available. if (Result = 0) and (TObject(PItem1).ClassType = TPasCio) and (TObject(PItem2).ClassType = TPasCio) then if TPasCio(PItem1).MyUnit = nil then begin Result := -1 end else begin if TPasCio(PItem2).MyUnit = nil then begin Result := 1 end else begin Result := CompareText(TPasCio(PItem1).MyUnit.Name, TPasCio(PItem2).MyUnit.Name); end; end; end; function ComparePasMethods(PItem1, PItem2: Pointer): Integer; var P1: TPasMethod; P2: TPasMethod; begin P1 := TPasMethod(PItem1); P2 := TPasMethod(PItem2); { compare 'method type', order is constructor > destructor > visibility > function, procedure } if P1.What = P2.What then begin { if 'method type' is equal, compare names } if P1.Visibility = P2.Visibility then begin Result := CompareText(P1.Name, P2.Name) end else begin if P1.Visibility < P2.Visibility then begin Result := -1 end else begin Result := 1; end; end; end else begin if P1.What < P2.What then begin Result := -1 end else begin Result := 1; end; end; end; { TBaseItem ------------------------------------------------------------------- } constructor TBaseItem.Create; begin inherited Create; FAuthors := TStringVector.Create; AutoLinkHereAllowed := true; end; destructor TBaseItem.Destroy; begin Authors.Free; inherited; end; function TBaseItem.FindItem(const ItemName: string): TBaseItem; begin Result := nil; end; function TBaseItem.FindItemMaybeInAncestors(const ItemName: string): TBaseItem; begin Result := FindItem(ItemName); end; function TBaseItem.FindName(const NameParts: TNameParts): TBaseItem; begin Result := nil; end; procedure TBaseItem.StoreAuthorTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if TagParameter = '' then exit; if Authors = nil then FAuthors := NewStringVector; Authors.Add(TagParameter); ReplaceStr := ''; end; procedure TBaseItem.StoreCreatedTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if TagParameter = '' then exit; FCreated := TagParameter; ReplaceStr := ''; end; procedure TBaseItem.StoreLastModTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if TagParameter = '' then exit; FLastMod := TagParameter; ReplaceStr := ''; end; procedure TBaseItem.StoreCVSTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var s: string; begin if Length(TagParameter)>1 then begin case TagParameter[2] of 'D': begin if Copy(TagParameter,1,7) = '$Date: ' then begin LastMod := Trim(Copy(TagParameter, 7, Length(TagParameter)-7-1)) + ' UTC'; ReplaceStr := ''; end; end; 'A': begin if Copy(TagParameter,1,9) = '$Author: ' then begin s := Trim(Copy(TagParameter, 9, Length(TagParameter)-9-1)); if Length(s) > 0 then begin if not Assigned(Authors) then FAuthors := NewStringVector; Authors.AddNotExisting(s); ReplaceStr := ''; end; end; end; else begin end; end; end; end; procedure TBaseItem.PreHandleNoAutoLinkTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ''; { We set AutoLinkHereAllowed in the 1st pass of expanding descriptions (i.e. in PreHandleNoAutoLinkTag, not in HandleNoAutoLinkTag) because all information about AutoLinkHereAllowed must be collected before auto-linking happens in the 2nd pass of expanding descriptions. } AutoLinkHereAllowed := false; end; procedure TBaseItem.HandleNoAutoLinkTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin ReplaceStr := ''; end; procedure TBaseItem.RegisterTags(TagManager: TTagManager); begin inherited; TTag.Create(TagManager, 'author', nil, {$IFDEF FPC}@{$ENDIF} StoreAuthorTag, [toParameterRequired]); TTag.Create(TagManager, 'created', nil, {$IFDEF FPC}@{$ENDIF} StoreCreatedTag, [toParameterRequired, toRecursiveTags, toAllowNormalTextInside]); TTag.Create(TagManager, 'lastmod', nil, {$IFDEF FPC}@{$ENDIF} StoreLastModTag, [toParameterRequired, toRecursiveTags, toAllowNormalTextInside]); TTag.Create(TagManager, 'cvs', nil, {$IFDEF FPC}@{$ENDIF} StoreCVSTag, [toParameterRequired]); TTopLevelTag.Create(TagManager, 'noautolinkhere', {$IFDEF FPC}@{$ENDIF} PreHandleNoAutoLinkTag, {$IFDEF FPC}@{$ENDIF} HandleNoAutoLinkTag, []); end; procedure TBaseItem.SetAuthors(const Value: TStringVector); begin FAuthors.Assign(Value); end; function TBaseItem.QualifiedName: String; begin Result := Name; end; procedure TBaseItem.Deserialize(const ASource: TStream); begin inherited; Name := LoadStringFromStream(ASource); RawDescription := LoadStringFromStream(ASource); { No need to serialize, because it's not generated by parser: DetailedDescription := LoadStringFromStream(ASource); FullLink := LoadStringFromStream(ASource); LastMod := LoadStringFromStream(ASource); Authors.LoadFromBinaryStream(ASource); FCreated := LoadStringFromStream(ASource); AutoLinkHereAllowed } end; procedure TBaseItem.Serialize(const ADestination: TStream); begin inherited; SaveStringToStream(Name, ADestination); SaveStringToStream(RawDescription, ADestination); { No need to serialize, because it's not generated by parser: SaveStringToStream(DetailedDescription, ADestination); SaveStringToStream(FullLink, ADestination); SaveStringToStream(LastMod, ADestination); Authors.SaveToBinaryStream(ADestination); SaveStringToStream(Created, ADestination); AutoLinkHereAllowed } end; function TBaseItem.RawDescriptionInfo: PRawDescriptionInfo; begin Result := @FRawDescriptionInfo; end; function TBaseItem.GetRawDescription: string; begin Result := FRawDescriptionInfo.Content; end; procedure TBaseItem.WriteRawDescription(const Value: string); begin FRawDescriptionInfo.Content := Value; end; function TBaseItem.BasePath: string; begin Result := IncludeTrailingPathDelimiter(GetCurrentDir); end; { TPasItem ------------------------------------------------------------------- } constructor TPasItem.Create; begin inherited; FSeeAlso := TStringPairVector.Create(true); FAttributes := TStringPairVector.Create(true); end; destructor TPasItem.Destroy; begin FreeAndNil(FSeeAlso); FreeAndNil(FAttributes); inherited; end; function TPasItem.FindNameWithinUnit(const NameParts: TNameParts): TBaseItem; var p: TBaseItem; LNameParts0: string; begin Result := nil; LNameParts0 := LowerCase(NameParts[0]); case Length(NameParts) of 1: begin Result := FindItemMaybeInAncestors(NameParts[0]); if Result <> nil then Exit; if Assigned(MyObject) then begin { this item is a method or field } p := MyObject.FindItemMaybeInAncestors(NameParts[0]); if Assigned(p) then begin Result := p; Exit; end; end; if Assigned(MyUnit) then begin p := MyUnit.FindItem(NameParts[0]); if Assigned(p) then begin Result := p; Exit; end; end; if Assigned(MyUnit) and (LNameParts0 = LowerCase(MyUnit.Name)) then begin Result := MyUnit; Exit; end; end; 2: begin if Assigned(MyObject) then begin if LowerCase(MyObject.Name) = LNameParts0 then begin p := MyObject.FindItem(NameParts[1]); if Assigned(p) then begin Result := p; Exit; end; end; end; if Assigned(MyUnit) then begin // To find links inside classes p := MyUnit.FindInsideSomeClass(NameParts[0], NameParts[1]); if Assigned(p) then begin Result := p; Exit; end; // To find links inside enums p := MyUnit.FindInsideSomeEnum(NameParts[0], NameParts[1]); if Assigned(p) then begin Result := p; Exit; end; end; end; end; end; function TPasItem.FindName(const NameParts: TNameParts): TBaseItem; procedure SearchUsedUnits(UsesUnits: TStringVector); var U: TPasUnit; i: Integer; begin for i := 0 to UsesUnits.Count - 1 do begin U := TPasUnit(UsesUnits.Objects[i]); if U <> nil then begin Result := U.FindNameWithinUnit(NameParts); if Result <> nil then Exit; end; end; Result := nil; end; begin Result := FindNameWithinUnit(NameParts); if Result = nil then begin { Dirty code: checking for "Self is some class". This could be organized better by virtual methods. } if Self is TPasUnit then SearchUsedUnits(TPasUnit(Self).UsesUnits) else if MyUnit <> nil then SearchUsedUnits(MyUnit.UsesUnits); end; end; procedure TPasItem.StoreAbstractTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if AbstractDescription <> '' then ThisTag.TagManager.DoMessage(1, pmtWarning, '@abstract tag was already specified for this item. ' + 'It was specified as "%s"', [AbstractDescription]); AbstractDescription := TagParameter; ReplaceStr := ''; end; procedure TPasItem.HandleDeprecatedTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin HintDirectives := HintDirectives + [hdDeprecated]; ReplaceStr := ''; end; procedure TPasItem.HandleSeeAlsoTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var Pair: TStringPair; begin Pair := TStringPair.CreateExtractFirstWord(TagParameter); if Pair.Name = '' then begin FreeAndNil(Pair); ThisTag.TagManager.DoMessage(2, pmtWarning, '@seealso tag doesn''t specify any name to link to, skipped', []); end else begin SeeAlso.Add(Pair); end; ReplaceStr := ''; end; procedure TPasItem.RegisterTags(TagManager: TTagManager); begin inherited; TTopLevelTag.Create(TagManager, 'abstract', nil, {$IFDEF FPC}@{$ENDIF} StoreAbstractTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); TTag.Create(TagManager, 'deprecated', nil, {$ifdef FPC}@{$endif} HandleDeprecatedTag, []); TTopLevelTag.Create(TagManager, 'seealso', nil, {$ifdef FPC}@{$endif} HandleSeeAlsoTag, [toParameterRequired, toFirstWordVerbatim]); end; function TPasItem.HasDescription: Boolean; begin HasDescription := (AbstractDescription <> '') or (DetailedDescription <> ''); end; procedure TPasItem.Sort(const SortSettings: TSortSettings); begin { Nothing to sort in TPasItem } end; function TPasItem.QualifiedName: String; begin Result := UnitRelativeQualifiedName; if MyUnit <> nil then Result := MyUnit.Name + '.' + Result; end; function TPasItem.UnitRelativeQualifiedName: String; var LItem: TPasItem; begin if FCachedUnitRelativeQualifiedName <> '' then Result := FCachedUnitRelativeQualifiedName else begin Result := FName; LItem := Self; while LItem.MyObject <> nil do begin Result := LItem.MyObject.Name + '.' + Result; LItem := LItem.MyObject; end; FCachedUnitRelativeQualifiedName := Result; end; end; procedure TPasItem.Deserialize(const ASource: TStream); begin inherited; ASource.Read(FVisibility, SizeOf(Visibility)); ASource.Read(FHintDirectives, SizeOf(FHintDirectives)); DeprecatedNote := LoadStringFromStream(ASource); FullDeclaration := LoadStringFromStream(ASource); Attributes.LoadFromBinaryStream(ASource); { No need to serialize, because it's not generated by parser: AbstractDescription := LoadStringFromStream(ASource); ASource.Read(FAbstractDescriptionWasAutomatic, SizeOf(FAbstractDescriptionWasAutomatic)); SeeAlso } end; procedure TPasItem.Serialize(const ADestination: TStream); begin inherited; ADestination.Write(FVisibility, SizeOf(Visibility)); ADestination.Write(FHintDirectives, SizeOf(FHintDirectives)); SaveStringToStream(DeprecatedNote, ADestination); SaveStringToStream(FullDeclaration, ADestination); FAttributes.SaveToBinaryStream(ADestination); { No need to serialize, because it's not generated by parser: SaveStringToStream(AbstractDescription, ADestination); ADestination.Write(FAbstractDescriptionWasAutomatic, SizeOf(FAbstractDescriptionWasAutomatic)); SeeAlso } end; procedure TPasItem.SetAttributes(var Value: TStringPairVector); begin if Value.Count > 0 then begin FreeAndNil(FAttributes); FAttributes := Value; Value := TStringPairVector.Create(true); end; end; function TPasItem.BasePath: string; begin if MyUnit <> nil then Result := MyUnit.BasePath else Result := inherited BasePath; //required by D7 end; { TPasEnum ------------------------------------------------------------------- } constructor TPasEnum.Create; begin inherited Create; FMembers := TPasItems.Create(True); end; procedure TPasEnum.Deserialize(const ASource: TStream); begin inherited; Members.Deserialize(ASource); end; destructor TPasEnum.Destroy; begin FMembers.Free; inherited; end; procedure TPasEnum.RegisterTags(TagManager: TTagManager); begin inherited; { Note that @value tag does not have toRecursiveTags, and it shouldn't: parameters of this tag will be copied verbatim to appropriate member's RawDescription, and they will be expanded when this member will be expanded by TDocGenerator.ExpandDescriptions. This way they will be expanded exactly once, as they should be. } TTag.Create(TagManager, 'value', nil, {$IFDEF FPC}@{$ENDIF} StoreValueTag, [toParameterRequired]); end; procedure TPasEnum.Serialize(const ADestination: TStream); begin inherited; Members.Serialize(ADestination); end; procedure TPasEnum.StoreValueTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var ValueName: String; ValueDesc: String; Value: TPasItem; begin ReplaceStr := ''; ValueDesc := TagParameter; ValueName := ExtractFirstWord(ValueDesc); Value := Members.FindListItem(ValueName); if Assigned(Value) then begin if Value.RawDescription = '' then Value.RawDescription := ValueDesc else ThisTag.TagManager.DoMessage(1, pmtWarning, '@value tag specifies description for a value "%s" that already' + ' has one description.', [ValueName]); end else ThisTag.TagManager.DoMessage(1, pmtWarning, '@value tag specifies unknown value "%s"', [ValueName]); end; function TPasEnum.FindItem(const ItemName: string): TBaseItem; begin Result := FMembers.FindListItem(ItemName); end; { TPasFieldVariable ---------------------------------------------------------- } procedure TPasFieldVariable.Deserialize(const ASource: TStream); begin inherited; ASource.Read(FIsConstant, SizeOf(FIsConstant)); end; procedure TPasFieldVariable.Serialize(const ADestination: TStream); begin inherited; ADestination.Write(FIsConstant, SizeOf(FIsConstant)); end; { TBaseItems ----------------------------------------------------------------- } constructor TBaseItems.Create(const AOwnsObject: Boolean); begin inherited; FHash := TObjectHash.Create; end; destructor TBaseItems.Destroy; begin FHash.Free; FHash := nil; inherited; end; procedure TBaseItems.Delete(const AIndex: Integer); var LObj: TBaseItem; begin LObj := TBaseItem(Items[AIndex]); FHash.Delete(LowerCase(LObj.Name)); inherited Delete(AIndex); end; function TBaseItems.FindListItem(const AName: string): TBaseItem; begin Result := nil; if Length(AName) > 0 then begin result := TPasItem(FHash.Items[LowerCase(AName)]); end; end; procedure TBaseItems.Add(const AObject: TBaseItem); begin inherited Add(AObject); FHash.Items[LowerCase(AObject.Name)] := AObject; end; procedure TBaseItems.InsertItems(const c: TBaseItems); var i: Integer; begin if ObjectVectorIsNilOrEmpty(c) then Exit; for i := 0 to c.Count - 1 do Add(TBaseItem(c.Items[i])); end; procedure TBaseItems.Clear; begin if Assigned(FHash) then begin // not assigned if destroying FHash.Free; FHash := TObjectHash.Create; end; inherited; end; procedure TBaseItems.Deserialize(const ASource: TStream); var LCount, i: Integer; begin Clear; ASource.Read(LCount, SizeOf(LCount)); for i := 0 to LCount - 1 do Add(TBaseItem(TSerializable.DeserializeObject(ASource))); end; procedure TBaseItems.Serialize(const ADestination: TStream); var LCount, i: Integer; begin LCount := Count; ADestination.Write(LCount, SizeOf(LCount)); { Remember to always serialize and deserialize items in the same order -- this is e.g. checked by ../../tests/scripts/check_cache.sh } for i := 0 to Count - 1 do TSerializable.SerializeObject(TBaseItem(Items[i]), ADestination); end; procedure TBaseItems.ClearAndAdd(const AObject: TBaseItem); begin Clear; Add(AObject); end; { TPasItems ------------------------------------------------------------------ } function TPasItems.FindListItem(const AName: string): TPasItem; begin Result := TPasItem(inherited FindListItem(AName)); end; procedure TPasItems.CopyItems(const c: TPasItems); var i: Integer; begin if ObjectVectorIsNilOrEmpty(c) then Exit; for i := 0 to c.Count - 1 do Add(TPasItem(c.GetPasItemAt(i))); end; procedure TPasItems.CountCIO(var c, i, o: Integer); var j: Integer; begin c := 0; i := 0; o := 0; for j := 0 to Count - 1 do case TPasCio(GetPasItemAt(j)).MyType of CIO_CLASS, CIO_PACKEDCLASS: Inc(c); CIO_INTERFACE: Inc(i); CIO_OBJECT, CIO_PACKEDOBJECT: Inc(o); end; end; function TPasItems.GetPasItemAt(const AIndex: Integer): TPasItem; begin Result := TPasItem(Items[AIndex]); end; procedure TPasItems.RemovePrivateItems; var i: Integer; Item: TPasItem; begin i := 0; while (i < Count) do begin Item := PasItemAt[i]; if Assigned(Item) and (Item.Visibility = viPrivate) then Delete(i) else Inc(i); end; end; procedure TPasItems.SetPasItemAt(const AIndex: Integer; const Value: TPasItem); begin Items[AIndex] := Value; end; procedure TPasItems.SortShallow; begin Sort( {$IFDEF FPC}@{$ENDIF} ComparePasItemsByName); end; procedure TPasItems.SortOnlyInsideItems(const SortSettings: TSortSettings); var i: Integer; begin for i := 0 to Count - 1 do PasItemAt[i].Sort(SortSettings); end; procedure TPasItems.SortDeep(const SortSettings: TSortSettings); begin SortShallow; SortOnlyInsideItems(SortSettings); end; procedure TPasItems.SetFullDeclaration(PrefixName: boolean; const Suffix: string); var i: Integer; begin if PrefixName then begin for i := 0 to Count - 1 do PasItemAt[i].FullDeclaration := PasItemAt[i].Name + Suffix; end else begin for i := 0 to Count - 1 do PasItemAt[i].FullDeclaration := Suffix; end; end; { TPasNestedCios ------------------------------------------------------------- } constructor TPasNestedCios.Create; begin inherited Create(True); end; { TPasCio -------------------------------------------------------------------- } constructor TPasCio.Create; begin inherited; FClassDirective := CT_NONE; FFields := TPasItems.Create(True); FMethods := TPasMethods.Create(True); FProperties := TPasProperties.Create(True); FAncestors := TStringPairVector.Create(True); FCios := TPasNestedCios.Create; FTypes := TPasTypes.Create(True); end; destructor TPasCio.Destroy; begin Ancestors.Free; Fields.Free; Methods.Free; Properties.Free; FCios.Free; FTypes.Free; inherited; end; procedure TPasCio.Deserialize(const ASource: TStream); begin inherited; FFields.Deserialize(ASource); FMethods.Deserialize(ASource); FProperties.Deserialize(ASource); Ancestors.LoadFromBinaryStream(ASource); ASource.Read(FMyType, SizeOf(FMyType)); ASource.Read(FClassDirective, SizeOf(FClassDirective)); FHelperTypeIdentifier := LoadStringFromStream(ASource); FTypes.Deserialize(ASource); FCios.Deserialize(ASource); FNameWithGeneric := LoadStringFromStream(ASource); { No need to serialize, because it's not generated by parser: FOutputFileName := LoadStringFromStream(ASource); } end; procedure TPasCio.Serialize(const ADestination: TStream); begin inherited; FFields.Serialize(ADestination); FMethods.Serialize(ADestination); FProperties.Serialize(ADestination); Ancestors.SaveToBinaryStream(ADestination); ADestination.Write(FMyType, SizeOf(FMyType)); ADestination.Write(FClassDirective, SizeOf(FClassDirective)); SaveStringToStream(HelperTypeIdentifier, ADestination); FTypes.Serialize(ADestination); FCios.Serialize(ADestination); SaveStringToStream(NameWithGeneric, ADestination); { No need to serialize, because it's not generated by parser: SaveStringToStream(FOutputFileName, ADestination); } end; function TPasCio.FindItem(const ItemName: string): TBaseItem; begin if Fields <> nil then begin Result := Fields.FindListItem(ItemName); if Result <> nil then Exit; end; if Methods <> nil then begin Result := Methods.FindListItem(ItemName); if Result <> nil then Exit; end; if Properties <> nil then begin Result := Properties.FindListItem(ItemName); if Result <> nil then Exit; end; if FTypes <> nil then begin Result := FTypes.FindListItem(ItemName); if Result <> nil then Exit; end; if FCios <> nil then begin Result := FCios.FindListItem(ItemName); if Result <> nil then Exit; end; Result := inherited FindItem(ItemName); end; function TPasCio.FindItemMaybeInAncestors(const ItemName: string): TBaseItem; begin Result := inherited FindItemMaybeInAncestors(ItemName); if Result = nil then Result := FindItemInAncestors(ItemName); end; procedure TPasCio.Sort(const SortSettings: TSortSettings); begin inherited; if Fields <> nil then begin if MyType in CIORecordType then begin if ssRecordFields in SortSettings then Fields.SortShallow; end else begin if ssNonRecordFields in SortSettings then Fields.SortShallow; end; end; if (Methods <> nil) and (ssMethods in SortSettings) then Methods.Sort( {$IFDEF FPC}@{$ENDIF} ComparePasMethods); if (Properties <> nil) and (ssProperties in SortSettings) then Properties.SortShallow; if (FCios <> nil) then FCios.SortDeep(SortSettings); if (FTypes <> nil) then FTypes.SortDeep(SortSettings); end; procedure TPasCio.RegisterTags(TagManager: TTagManager); begin inherited; { Note that @member tag does not have toRecursiveTags, and it shouldn't: parameters of this tag will be copied verbatim to appropriate member's RawDescription, and they will be expanded when this member will be expanded by TDocGenerator.ExpandDescriptions. This way they will be expanded exactly once, as they should be. Moreover, this allows you to correctly use tags like @param and @raises inside @member for a method. } TTag.Create(TagManager, 'member', nil, {$IFDEF FPC}@{$ENDIF} StoreMemberTag, [toParameterRequired]); end; procedure TPasCio.StoreMemberTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var MemberName: String; MemberDesc: String; Member: TBaseItem; begin ReplaceStr := ''; MemberDesc := TagParameter; MemberName := ExtractFirstWord(MemberDesc); Member := FindItem(MemberName); if Assigned(Member) then begin { Only replace the description if one wasn't specified for it already } if Member.RawDescription = '' then Member.RawDescription := MemberDesc else ThisTag.TagManager.DoMessage(1, pmtWarning, '@member tag specifies description for member "%s" that already' + ' has one description.', [MemberName]); end else ThisTag.TagManager.DoMessage(1, pmtWarning, '@member tag specifies unknown member "%s".', [MemberName]); end; function TPasCio.ShowVisibility: boolean; begin Result := not (MyType in CIORecordType); end; function TPasCio.FirstAncestor: TPasItem; begin if Ancestors.Count <> 0 then Result := TObject(Ancestors[0].Data) as TPasItem else Result := nil; end; function TPasCio.FirstAncestorName: string; begin if Ancestors.Count <> 0 then Result := Ancestors[0].Name else Result := ''; end; function TPasCio.FindItemInAncestors(const ItemName: string): TPasItem; var Ancestor: TBaseItem; begin Ancestor := FirstAncestor; Result := nil; while (Result = nil) and (Ancestor <> nil) and (Ancestor is TPasCio) do begin { TPasCio.FindItem always returns some TPasItem, so the cast below of Ancestor.FindItem to TPasItem should always be OK. } Result := Ancestor.FindItem(ItemName) as TPasItem; Ancestor := TPasCio(Ancestor).FirstAncestor; end; end; { TPasUnit ------------------------------------------------------------------- } constructor TPasUnit.Create; begin inherited Create; FTypes := TPasTypes.Create(True); FVariables := TPasItems.Create(True); FCIOs := TPasItems.Create(True); FConstants := TPasItems.Create(True); FFuncsProcs := TPasMethods.Create(True); FUsesUnits := TStringVector.Create; end; destructor TPasUnit.Destroy; begin FCIOs.Free; FConstants.Free; FFuncsProcs.Free; FTypes.Free; FUsesUnits.Free; FVariables.Free; inherited; end; procedure TPasUnit.AddCIO(const i: TPasCio); begin CIOs.Add(i); end; procedure TPasUnit.AddConstant(const i: TPasItem); begin Constants.Add(i); end; procedure TPasUnit.AddType(const i: TPasItem); begin Types.Add(i); end; procedure TPasUnit.AddVariable(const i: TPasItem); begin Variables.Add(i); end; function TPasUnit.FindInsideSomeClass(const AClassName, ItemInsideClass: string): TPasItem; var po: TPasCio; begin Result := nil; if CIOs = nil then Exit; po := TPasCio(CIOs.FindListItem(AClassName)); if Assigned(po) then Result := TPasItem(po.FindItem(ItemInsideClass)); end; function TPasUnit.FindInsideSomeEnum(const EnumName, EnumMember: string): TPasItem; var TypeItem: TPasItem; begin Result := nil; if Types = nil then Exit; TypeItem := Types.FindListItem(EnumName); if Assigned(TypeItem) and (TypeItem is TPasEnum) then Result := TPasItem(TPasEnum(TypeItem).FindItem(EnumMember)); end; function TPasUnit.FindItem(const ItemName: string): TBaseItem; begin if Constants <> nil then begin Result := Constants.FindListItem(ItemName); if Result <> nil then Exit; end; if Types <> nil then begin Result := Types.FindListItem(ItemName); if Result <> nil then Exit; end; if Variables <> nil then begin Result := Variables.FindListItem(ItemName); if Result <> nil then Exit; end; if FuncsProcs <> nil then begin Result := FuncsProcs.FindListItem(ItemName); if Result <> nil then Exit; end; if CIOs <> nil then begin Result := CIOs.FindListItem(ItemName); if Result <> nil then Exit; end; Result := inherited FindItem(ItemName); end; function TPasUnit.FileNewerThanCache(const FileName: string): boolean; begin {$IFDEF COMPILER_10_UP} Result := WasDeserialized and FileExists(FileName) and (CacheDateTime < CheckGetFileDate(FileName)); {$ELSE} Result := WasDeserialized and FileExists(FileName) and (CacheDateTime < FileDateToDateTime(FileAge(FileName))); {$ENDIF} end; procedure TPasUnit.Sort(const SortSettings: TSortSettings); begin inherited; if CIOs <> nil then begin if ssCIOs in SortSettings then CIOs.SortShallow; CIOs.SortOnlyInsideItems(SortSettings); end; if (Constants <> nil) and (ssConstants in SortSettings) then Constants.SortShallow; if (FuncsProcs <> nil) and (ssFuncsProcs in SortSettings) then FuncsProcs.SortShallow; if (Types <> nil) and (ssTypes in SortSettings) then Types.SortShallow; if (Variables <> nil) and (ssVariables in SortSettings) then Variables.SortShallow; if (UsesUnits <> nil) and (ssUsesClauses in SortSettings) then UsesUnits.Sort; end; procedure TPasUnit.Deserialize(const ASource: TStream); begin inherited; FTypes.Deserialize(ASource); FVariables.Deserialize(ASource); FCIOs.Deserialize(ASource); FConstants.Deserialize(ASource); FFuncsProcs.Deserialize(ASource); FUsesUnits.LoadFromBinaryStream(ASource); ASource.Read(FIsUnit, SizeOf(FIsUnit)); ASource.Read(FIsProgram, SizeOf(FIsProgram)); { No need to serialize, because it's not generated by parser: FOutputFileName := LoadStringFromStream(ASource); FSourceFilename := LoadStringFromStream(ASource); SourceFileDateTime := LoadDoubleFromStream(ASource);} end; procedure TPasUnit.Serialize(const ADestination: TStream); begin inherited; FTypes.Serialize(ADestination); FVariables.Serialize(ADestination); FCIOs.Serialize(ADestination); FConstants.Serialize(ADestination); FFuncsProcs.Serialize(ADestination); FUsesUnits.SaveToBinaryStream(ADestination); ADestination.Write(FIsUnit, SizeOf(FIsUnit)); ADestination.Write(FIsProgram, SizeOf(FIsProgram)); { No need to serialize, because it's not generated by parser: SaveStringToStream(FOutputFileName, ADestination); SaveStringToStream(FSourceFilename, ADestination); SaveDoubleToStream(SourceFileDateTime, ADestination); } end; function TPasUnit.BasePath: string; begin Result := ExtractFilePath(ExpandFileName(SourceFileName)); end; { TPasTypes ------------------------------------------------------------------ } function TPasTypes.FindListItem(const AName: string): TPasItem; var I: Integer; begin Result := inherited; if Result = nil then begin for I := 0 to Count - 1 do if PasItemAt[I] is TPasEnum then begin Result := TPasEnum(PasItemAt[I]).FindItem(AName) as TPasItem; if Result <> nil then Exit; end; end; end; { TPasUnits ------------------------------------------------------------------ } function TPasUnits.ExistsUnit(const AUnit: TPasUnit): Boolean; begin Result := FindListItem(AUnit.Name) <> nil; end; function TPasUnits.GetUnitAt(const AIndex: Integer): TPasUnit; begin Result := TPasUnit(Items[AIndex]); end; procedure TPasUnits.SetUnitAt(const AIndex: Integer; const Value: TPasUnit); begin Items[AIndex] := Value; end; { TPasMethod ----------------------------------------------------------------- } constructor TPasMethod.Create; begin inherited; FParams := TStringPairVector.Create(true); FRaises := TStringPairVector.Create(true); end; destructor TPasMethod.Destroy; begin FParams.Free; FRaises.Free; inherited Destroy; end; { TODO for StoreRaisesTag and StoreParamTag: splitting TagParameter using ExtractFirstWord should be done inside TTagManager.Execute, working with raw text, instead of here, where the TagParameter is already expanded and converted. Actually, current approach works for now perfectly, but only because neighter html generator nor LaTeX generator change text in such way that first word of the text (assuming it's a normal valid Pascal identifier) is changed. E.g. '@raises(EFoo with some link @link(Blah))' is expanded to 'EFoo with some link <a href="...">Blah</a>' so the 1st word ('EFoo') is preserved. But this is obviously unclean approach. } procedure TPasMethod.StoreRaisesTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var Pair: TStringPair; begin Pair := TStringPair.CreateExtractFirstWord(TagParameter); if Pair.Name = '' then begin FreeAndNil(Pair); ThisTag.TagManager.DoMessage(2, pmtWarning, '@raises tag doesn''t specify exception name, skipped', []); end else begin FRaises.Add(Pair); end; ReplaceStr := ''; end; procedure TPasMethod.StoreParamTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); var Pair: TStringPair; begin Pair := TStringPair.CreateExtractFirstWord(TagParameter); if Name = '' then begin FreeAndNil(Pair); ThisTag.TagManager.DoMessage(2, pmtWarning, '@param tag doesn''t specify parameter name, skipped', []); end else begin FParams.Add(Pair); end; ReplaceStr := ''; end; procedure TPasMethod.StoreReturnsTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if TagParameter = '' then exit; FReturns := TagParameter; ReplaceStr := ''; end; function TPasMethod.HasMethodOptionalInfo: boolean; begin Result := (Returns <> '') or (not ObjectVectorIsNilOrEmpty(Params)) or (not ObjectVectorIsNilOrEmpty(Raises)); end; procedure TPasMethod.Deserialize(const ASource: TStream); begin inherited; ASource.Read(FWhat, SizeOf(FWhat)); { No need to serialize, because it's not generated by parser: Params.LoadFromBinaryStream(ASource); FReturns := LoadStringFromStream(ASource); FRaises.LoadFromBinaryStream(ASource); } end; procedure TPasMethod.Serialize(const ADestination: TStream); begin inherited; ADestination.Write(FWhat, SizeOf(FWhat)); { No need to serialize, because it's not generated by parser: Params.SaveToBinaryStream(ADestination); SaveStringToStream(FReturns, ADestination); FRaises.SaveToBinaryStream(ADestination); } end; procedure TPasMethod.RegisterTags(TagManager: TTagManager); begin inherited; TTopLevelTag.Create(TagManager, 'raises', nil, {$IFDEF FPC}@{$ENDIF} StoreRaisesTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside, toFirstWordVerbatim]); TTopLevelTag.Create(TagManager, 'param', nil, {$IFDEF FPC}@{$ENDIF} StoreParamTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside, toFirstWordVerbatim]); TTopLevelTag.Create(TagManager, 'returns', nil, {$IFDEF FPC}@{$ENDIF} StoreReturnsTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); TTopLevelTag.Create(TagManager, 'return', nil, {$IFDEF FPC}@{$ENDIF} StoreReturnsTag, [toParameterRequired, toRecursiveTags, toAllowOtherTagsInsideByDefault, toAllowNormalTextInside]); end; { TPasProperty --------------------------------------------------------------- } procedure TPasProperty.Deserialize(const ASource: TStream); begin inherited; ASource.Read(FDefault, SizeOf(FDefault)); ASource.Read(FNoDefault, SizeOf(FNoDefault)); FIndexDecl := LoadStringFromStream(ASource); FStoredID := LoadStringFromStream(ASource); FDefaultID := LoadStringFromStream(ASource); FWriter := LoadStringFromStream(ASource); FPropType := LoadStringFromStream(ASource); FReader := LoadStringFromStream(ASource); end; procedure TPasProperty.Serialize(const ADestination: TStream); begin inherited; ADestination.Write(FDefault, SizeOf(FDefault)); ADestination.Write(FNoDefault, SizeOf(FNoDefault)); SaveStringToStream(FIndexDecl, ADestination); SaveStringToStream(FStoredID, ADestination); SaveStringToStream(FDefaultID, ADestination); SaveStringToStream(FWriter, ADestination); SaveStringToStream(FPropType, ADestination); SaveStringToStream(FReader, ADestination); end; { TExternalItem ---------------------------------------------------------- } procedure TExternalItem.AddAnchor(const AnchorItem: TAnchorItem); begin FAnchors.Add(AnchorItem); end; function TExternalItem.AddAnchor(const AnchorName: string): TAnchorItem; begin if FindItem(AnchorName) = nil then begin Result := TAnchorItem.Create; Result.Name := AnchorName; Result.ExternalItem := Self; AddAnchor(Result); end else raise EAnchorAlreadyExists.CreateFmt( 'Within "%s" there already exists anchor "%s"', [Name, AnchorName]); end; constructor TExternalItem.Create; begin inherited; FAnchors := TBaseItems.Create(true); end; destructor TExternalItem.Destroy; begin FAnchors.Free; inherited; end; function TExternalItem.FindItem(const ItemName: string): TBaseItem; begin result := nil; if FAnchors <> nil then begin Result := FAnchors.FindListItem(ItemName); if Result <> nil then Exit; end; end; procedure TExternalItem.HandleShortTitleTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if ShortTitle <> '' then ThisTag.TagManager.DoMessage(1, pmtWarning, '@shorttitle tag was already specified for this item. ' + 'It was specified as "%s"', [ShortTitle]); ShortTitle := TagParameter; ReplaceStr := ''; end; procedure TExternalItem.HandleTitleTag( ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if Title <> '' then ThisTag.TagManager.DoMessage(1, pmtWarning, '@title tag was already specified for this item. ' + 'It was specified as "%s"', [Title]); Title := TagParameter; ReplaceStr := ''; end; procedure TExternalItem.RegisterTags(TagManager: TTagManager); begin inherited; TTopLevelTag.Create(TagManager, 'title', nil, {$IFDEF FPC}@{$ENDIF} HandleTitleTag, [toParameterRequired]); TTopLevelTag.Create(TagManager, 'shorttitle', nil, {$IFDEF FPC}@{$ENDIF} HandleShortTitleTag, [toParameterRequired]); end; procedure TExternalItem.SetOutputFileName(const Value: string); begin FOutputFileName := Value; end; function TExternalItem.BasePath: string; begin Result := ExtractFilePath(ExpandFileName(SourceFileName)); end; { global things ------------------------------------------------------------ } function MethodTypeToString(const MethodType: TMethodType): string; const { Maps @link(TMethodType) value to @link(TKeyWord) value. When given TMethodType value doesn't correspond to any keyword, it maps it to KEY_INVALIDKEYWORD. } MethodTypeToKeyWord: array[TMethodType] of TKeyWord = ( KEY_CONSTRUCTOR, KEY_DESTRUCTOR, KEY_FUNCTION, KEY_PROCEDURE, KEY_INVALIDKEYWORD ); begin if MethodType = METHOD_OPERATOR then Result := StandardDirectiveArray[SD_OPERATOR] else Result := KeyWordArray[MethodTypeToKeyWord[MethodType]]; Result := LowerCase(Result); end; function VisToStr(const Vis: TVisibility): string; begin result := StringReplace(string(VisibilityStr[Vis]), ' ', '', [rfReplaceAll]); end; function VisibilitiesToStr(const Visibilities: TVisibilities): string; var Vis: TVisibility; begin Result := ''; for Vis := Low(Vis) to High(Vis) do if Vis in Visibilities then begin if Result <> '' then Result := Result + ','; Result := Result + VisToStr(Vis); end; end; initialization TSerializable.Register(TPasItem); TSerializable.Register(TPasConstant); TSerializable.Register(TPasFieldVariable); TSerializable.Register(TPasType); TSerializable.Register(TPasEnum); TSerializable.Register(TPasMethod); TSerializable.Register(TPasProperty); TSerializable.Register(TPasCio); TSerializable.Register(TPasUnit); end. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_GenSimpleXML.pas�����������������������������������������������������0000600�0001750�0001750�00000027063�13237143042�022176� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(SimpleXML output generator.) } unit PasDoc_GenSimpleXML; {$I pasdoc_defines.inc} interface uses PasDoc_Utils, PasDoc_Gen, PasDoc_Items, PasDoc_Languages, PasDoc_StringVector, PasDoc_Types, Classes, PasDoc_StringPairVector; type TSimpleXMLDocGenerator = class(TDocGenerator) protected function CodeString(const s: string): string; override; function ConvertString(const s: string): string; override; function ConvertChar(c: char): string; override; procedure WriteUnit(const HL: integer; const U: TPasUnit); override; procedure WriteExternalCore(const ExternalItem: TExternalItem; const Id: TTranslationID); override; function FormatSection(HL: integer; const Anchor: string; const Caption: string): string; override; function FormatAnchor(const Anchor: string): string; override; function FormatTable(Table: TTableData): string; override; function FormatList(ListData: TListData): string; override; private space:string; { Returns XML <description> element with Item's AbstractDescription and DetailedDescription. Returns '' if Item doesn't have any description. } function ItemDescription(Item: TPasItem): string; procedure writefunction(const item:TPasItem); procedure writeconstant(const item:TPasItem); procedure writevariable(const item:TPasItem); procedure writetypes(const item:TPasItem); procedure writeclass(const item:TPasCIO); procedure writeproperty(const item:TPasItem); public procedure WriteDocumentation; override; function GetFileExtension: string; override; end; implementation uses PasDoc_ObjectVector, SysUtils; function TSimpleXMLDocGenerator.GetFileExtension:string; begin Result := '.xml'; end; procedure TSimpleXMLDocGenerator.WriteDocumentation; begin StartSpellChecking('sgml'); inherited; WriteUnits(1); WriteIntroduction; WriteConclusion; EndSpellChecking; end; function TSimpleXMLDocGenerator.CodeString(const s: string): string; begin Result := '<code>' + S + '</code>'; end; function TSimpleXMLDocGenerator.ConvertString(const S: String): String; const ReplacementArray: array[0..3] of TCharReplacement = ( (cChar: '<'; sSpec: '<'), (cChar: '>'; sSpec: '>'), (cChar: '&'; sSpec: '&'), (cChar: '"'; sSpec: '"') ); begin Result := StringReplaceChars(S, ReplacementArray); end; function TSimpleXMLDocGenerator.ConvertChar(c: char): String; begin ConvertChar := ConvertString(c); end; function TSimpleXMLDocGenerator.ItemDescription(Item: TPasItem): string; begin if Item.HasDescription then begin { Abstract and Detailed descriptions are somewhat siblings, for most normal uses you want to glue them together. That's why I (Michalis) decided it's most sensible to put them as sibling XML elements, not make <abstract> child of <detailed> of something like this. } Result := '<description>'; if Item.AbstractDescription <> '' then Result := Result + '<abstract>' + Item.AbstractDescription + '</abstract>'; if Item.DetailedDescription <> '' then Result := Result + '<detailed>' + Item.DetailedDescription + '</detailed>'; Result := Result + '</description>'; end else Result := ''; end; procedure TSimpleXMLDocGenerator.writefunction(const item:TPasItem); var I: Integer; meth: TPasMethod absolute item; begin if item is TPasMethod then begin WriteDirectLine(space + '<function name="' + ConvertString(item.name) + '" type="' + ConvertString(MethodTypeToString(TPasMethod(item).What)) + '" declaration="' + ConvertString(item.FullDeclaration) + '">'); for I := 0 to meth.params.count - 1 do WriteDirectLine(space + ' <param name="' + ConvertString(meth.params[i].name) + '">' + meth.params[i].value +'</param>'); if meth.returns <> '' then WriteDirectLine(space + ' <result>' + meth.returns + '</result>'); if item.HasDescription then WriteDirectLine(space + ' ' + ItemDescription(Item)); WriteDirectLine(space + '</function>'); end; end; procedure TSimpleXMLDocGenerator.writeproperty(const item:TPasItem); var prop: TPasProperty absolute item; begin Assert(item is TPasProperty); WriteDirectLine(space + '<property name="' + ConvertString(item.name) + '" indexdecl="' + ConvertString(prop.indexDecl) + '" type="' + ConvertString(prop.Proptype) + '" reader="' + ConvertString(prop.reader) + '" writer="' + ConvertString(prop.writer) + '" default="' + ConvertString(booltostr(prop.default)) + '" defaultid="' + ConvertString(prop.defaultid) + '" nodefault="' + ConvertString(booltostr(prop.nodefault)) + '" storedid="' + ConvertString(prop.storedid) +'">'); if item.HasDescription then WriteDirectLine(space + ' ' + ItemDescription(Item)); WriteDirectLine(space+'</property>'); end; procedure TSimpleXMLDocGenerator.writeconstant(const item:TPasItem); begin WriteDirectLine(space + '<constant name="' + ConvertString(item.FullDeclaration) + '">'); if item.HasDescription then WriteDirectLine(space + ' ' + ItemDescription(Item)); WriteDirectLine(space+'</constant>'); end; procedure TSimpleXMLDocGenerator.writevariable(const item:TPasItem); begin WriteDirectLine(space + '<variable name="' + ConvertString(item.FullDeclaration) + '">'); if item.HasDescription then WriteDirectLine(space + ' ' + ItemDescription(Item)); WriteDirectLine(space+'</variable>'); end; procedure TSimpleXMLDocGenerator.writetypes(const item:TPasItem); begin WriteDirectLine(space + '<type name="' + ConvertString(item.FullDeclaration) + '">'); if item.HasDescription then WriteDirectLine(space + ' ' + ItemDescription(Item)); WriteDirectLine(space+'</type>'); end; procedure TSimpleXMLDocGenerator.writeclass(const item:TPasCIO); function writetype(t:TCIOType):string; begin result:='unknown'; case t of CIO_CLASS:result:='class'; CIO_PACKEDCLASS:result:='packed class'; CIO_DISPINTERFACE:result:='dispinterface'; CIO_INTERFACE:result:='interface'; CIO_OBJECT:result:='object'; CIO_PACKEDOBJECT:result:='packed object'; CIO_RECORD:result:='record'; CIO_PACKEDRECORD:result:='packed record'; end; end; var i: Integer; begin WriteDirectLine(space + '<structure name="' + ConvertString(item.name) + '" name_with_generic="' + ConvertString(item.NameWithGeneric) + '" type="' + ConvertString(writetype(item.MyType)) + '">'); space:=space+' '; if item.HasDescription then WriteDirectLine(space + ItemDescription(Item)); for i:=0 to item.ancestors.count-1 do WriteDirectLine(space + '<ancestor name="' + ConvertString(item.ancestors[i].Name) + '" declaration="' + ConvertString(item.ancestors[i].Value) + '" />'); for i:=0 to item.Methods.count-1 do writefunction(item.Methods.PasItemAt[i]); for i:=0 to item.Fields.count-1 do writevariable(item.fields.PasItemAt[i]); for i:=0 to item.Properties.count-1 do writeproperty(item.Properties.PasItemAt[i]); space:=copy(space,0,length(space)-2); WriteDirectLine(space+'</structure>'); end; procedure TSimpleXMLDocGenerator.WriteUnit(const HL: integer; const U: TPasUnit); var i: Integer; begin U.OutputFileName:=U.OutputFileName+'.xml'; if not Assigned(U) then begin DoMessage(1, pmtError, 'TGenericXMLDocGenerator.WriteUnit: ' + 'Unit variable has not been initialized.', []); Exit; end; if U.FileNewerThanCache(DestinationDirectory + U.OutputFileName) then begin DoMessage(3, pmtInformation, 'Data for unit "%s" was loaded from cache, '+ 'and output file of this unit exists and is newer than cache, '+ 'skipped.', [U.Name]); Exit; end; if not CreateStream(U.OutputFileName) then Exit; DoMessage(2, pmtInformation, 'Writing Docs for unit "%s"', [U.Name]); WriteDirectLine('<unit name="' + ConvertString(U.SourceFileName) + '">'); space:=' '; if u.HasDescription then WriteDirectLine(space + ItemDescription(u)); //global uses if WriteUsesClause and not IsEmpty(U.UsesUnits) then for i:=0 to u.UsesUnits.count-1 do WriteDirectLine(space + '<uses name="' + ConvertString(u.UsesUnits[i]) + '"/>'); //global functions for i:=0 to u.FuncsProcs.count-1 do writefunction(u.FuncsProcs.PasItemAt[i]); //global constants for i:=0 to u.Constants.count-1 do writeconstant(u.Constants.PasItemAt[i]); //global vars for i:=0 to u.Variables.count-1 do writevariable(u.Variables.PasItemAt[i]); //global types for i:=0 to u.Types.count-1 do writetypes(u.types.PasItemAt[i]); //global classes for i:=0 to u.CIOs.count-1 do writeclass(TPasCIO(u.CIOs.PasItemAt[i])); WriteDirectLine('</unit>'); end; procedure TSimpleXMLDocGenerator.WriteExternalCore( const ExternalItem: TExternalItem; const Id: TTranslationID); begin { TODO } end; function TSimpleXMLDocGenerator.FormatSection(HL: integer; const Anchor: string; const Caption: string): string; begin Result := ''; { TODO } end; function TSimpleXMLDocGenerator.FormatAnchor(const Anchor: string): string; begin { TODO: untested, as this is used only by introduction-conclusion stuff and WriteExternalCore is not impl yet. } Result := Format('<anchor target="%s" />', [Anchor]); end; function TSimpleXMLDocGenerator.FormatTable(Table: TTableData): string; const RowElement: array [boolean] of string = ('row', 'rowhead'); var RowNum, ColNum: Integer; Row: TRowData; begin Result := LineEnding + LineEnding + '<table>' + LineEnding; for RowNum := 0 to Table.Count - 1 do begin Row := Table.Items[RowNum] as TRowData; Result := Result + ' <' + RowElement[Row.Head] + '>' + LineEnding; for ColNum := 0 to Row.Cells.Count - 1 do Result := Result + Format(' <cell>%s</cell>', [Row.Cells[ColNum]]) + LineEnding; Result := Result + ' </' + RowElement[Row.Head] + '>' + LineEnding; end; Result := Result + '</table>' + LineEnding + LineEnding; end; function TSimpleXMLDocGenerator.FormatList(ListData: TListData): string; const ListTag: array[TListType]of string = ( 'unorderedlist', 'orderedlist', 'definitionlist' ); var i: Integer; ListItem: TListItemData; begin Result := LineEnding + LineEnding + Format('<%s>', [ListTag[ListData.ListType]]) + LineEnding; for i := 0 to ListData.Count - 1 do begin ListItem := ListData.Items[i] as TListItemData; Result := Result + '<item'; if ListData.ListType = ltDefinition then Result := Result + ' label="' + ListItem.ItemLabel + '"'; Result := Result + '>' + ListItem.Text + '</item>' + LineEnding; end; Result := Result + Format('</%s>', [ListTag[ListData.ListType]]) + LineEnding + LineEnding; end; end.�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Hashes.pas�����������������������������������������������������������0000600�0001750�0001750�00000031313�13237143042�021136� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(* This unit implements an associative array. Before writing this unit, I've always missed Perl commands like @code($h{abc}='def') in Pascal. @author(Copyright (C) 2001-2014 Wolf Behrenhoff <wolf@behrenhoff.de> and PasDoc developers) Version 0.9.1 (works fine, don't know a bug, but 1.0? No, error checks are missing!) @italic( This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.) @italic( This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.) @italic( You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA) Thanks to: @unorderedList( @item(Larry Wall for perl! And because I found a way how to implement a hash in perl's source code (hv.c and hv.h). This is not a direct translation from C to Pascal, but the algortithms are more or less the same.)) Be warned: @unorderedList( @item(There is NOT a single ERROR CHECK in this unit. So expect anything! Especially there are NO checks on NEW and GETMEM functions --- this might be dangerous on machines with low memory.)) Programmer's information: @unorderedList( @item(you need Freepascal (http://www.freepascal.org) or Delphi (http://www.borland.com) to compile this unit) @item(I recommend that you use Ansistrings {$H+} to be able to use keys longer than 255 chars)) How to use this unit: @preformatted( Simply put this unit in your uses line. You can use a new class - THash. Initialize a hash (assuming "var h: THash;"): h:=THash.Create; Save a String: h.SetString('key','value'); //perl: $h{key}='value' Get the String back: string_var:=h.GetString('key'); //perl: $string_var=$h{key} returns '' if 'key' is not set Test if a key has been set: if h.KeyExists('key') then... //perl: if (exists $h{key}) ... returns a boolean Delete a key h.DeleteKey('key'); //perl: delete $h{key}; Which keys do exist? stringlist:=h.Keys; //perl: @list=keys %h; returns a TStringList Which keys do exist beginning with a special string? stinglist:=h.Keys('abc'); returns all keys beginning with 'abc' //perl: @list=grep /^abc/, keys %h; How many keys are there? number_of_keys:=h.Count; //perl: $number=scalar keys %hash; How many keys fit in memory allocated by THash? c:=h.Capacity; (property) THash automatically increases h.Capacity if needed. This property is similar to Delphi's TList.Capacity property. Note #1: You can't decrease h.Capacity. Note #2: Capacity must be 2**n -- Create sets Capacity:=8; The same: Capacity:=17; , Capacity:=32; I know there will be 4097 key/values in my hash. I don't want the hash's capacity to be 8192 (wasting 50% ram). What to do? h.MaxCapacity:=4096; => Capacity will never be > 4096. Note: You can store more than MaxCapacity key/values in the hash (as many as you want) but Count should be >= Capacity for best performance. MaxCapacity is -1 by default, meaning no limit. Delete the hash h.Free; OR h.Destroy; Instead of just strings you can also save objects in my hash - anything that is a pointer can be saved. Similar to SetString and GetString there are SetObject and GetObject. The latter returns nil if the key is unknown. You can use both Set/GetString and Set/GetObject for a single key string - no problem. But if DeleteKey is called, both the string and the pointer are lost. If you want to store a pointer and a string, it is faster to call SetStringObject(key,string,pointer) than SetString and SetObject. The same is true getting the data back - GetString and GetObject are significantly slower then a singe call to GetStringObject(key, var string, var pointer). Happy programming! ) *) unit PasDoc_Hashes; {$I pasdoc_defines.inc} {$Q-} // no integer overflow checks (I need overflow in THash.Hash) {$R-} // no range checks (because free bounds of TFakeArray[0..0]) interface uses SysUtils, Classes; type { } PPHashEntry=^PHashEntry; PHashEntry=^THashEntry; THashEntry=record next: PHashEntry; hash: Integer; key: String; value: String; data: Pointer; end; { in FPC, I can simply use PPHashEntry as an array of PHashEntry - Delphi doesn't allow that. I need this stupid array[0..0] definition! From Delphi4, I could use a dynamic array. } TFakeArray=array[0..0] of PHashEntry; PFakeArray=^TFakeArray; THash=class private Feld: PFakeArray; FeldMaxValue: Integer; FeldBelegt: Integer; FMaxCapacity: Integer; function Hash(key: String): Integer; procedure MakeHashLarger(power2: Integer); procedure SetCapacity(new_size: Integer); function GetCapacity: Integer; procedure SetMaxCapacity(newmc: Integer); procedure _SetStringObject(_key: String; s: String; set_s: Boolean; p: Pointer; set_p: Boolean); public property Count: Integer read FeldBelegt; property Capacity: Integer read GetCapacity write SetCapacity; property MaxCapacity: Integer read FMaxCapacity write SetMaxCapacity; constructor Create; destructor Destroy; override; procedure SetObject(_key: String; data: Pointer); procedure SetString(_key: String; data: String); procedure SetStringObject(_key: String; s: String; p: Pointer); function GetObject(_key: String): Pointer; function GetString(_key: String): String; procedure GetStringObject(_key: String; var s: String; var p: Pointer); function KeyExists(_key: String): Boolean; procedure DeleteKey(_key: String); function Keys: TStringList; overload; function Keys(beginning: String): TStringList; overload; end; TObjectHash = class(THash) public procedure Delete(_key: String); property Items[_key: string]: Pointer read GetObject write SetObject; end; implementation constructor THash.Create; begin FeldMaxValue:=7; //irgendein kleiner Wert der Eigenschaft 2**n-1 (English: any small value of the property 2**n-1) FeldBelegt:=0; FMaxCapacity:=-1; GetMem(Feld,sizeof(PHashEntry)*Succ(FeldMaxValue)); FillChar(Feld^,sizeof(PHashEntry)*Succ(FeldMaxValue),0); end; destructor THash.Destroy; var i: Integer; del: PHashEntry; begin for i:=0 to FeldMaxValue do begin while Assigned(Feld^[i]) do begin del:=Feld^[i]; Feld^[i]:=Feld^[i]^.next; dispose(del); end; end; FreeMem(Feld,sizeof(PHashEntry)*(Succ(FeldMaxValue))); Feld := nil; inherited Destroy; end; function THash.Hash(key: String): Integer; var i: Integer; begin Result:=0; for i:=1 to length(key) do Result:=33*Result+Ord(key[i]); Result:=Result+Result shr 5; end; function THash.KeyExists(_key: String): Boolean; var h: Integer; he: PHashEntry; begin h:=Hash(_key); he:=Feld^[h and FeldMaxValue]; while Assigned(he) do begin if he^.Hash=h then if he^.key=_key then begin //gefunden (English: found) Result:=True; Exit; end; he:=he^.next; end; Result:=False; end; function THash.GetCapacity: Integer; begin Result:=FeldMaxValue+1; end; procedure THash.SetCapacity(new_size: Integer); var power: Integer; begin if new_size>capacity then begin power:=1+Trunc(Ln(new_size-1)/Ln(2)-Ln(capacity)/Ln(2)+0.00001); { power:=Ceil(Ln(new_size)/Ln(2)-Ln(capacity)/Ln(2)-0.00001); but Ceiling needs unit Math... } if power>0 then MakeHashLarger(power); end; end; procedure THash.MakeHashLarger(power2: Integer); var i, oldsize, newsize, newpos: Integer; he: PHashEntry; oe: PPHashEntry; begin //zunchst Speicher reservieren (Enlish?: reserve additional memory) oldsize:=Succ(FeldMaxValue); newsize:=oldsize shl power2; if (newsize>MaxCapacity) and (MaxCapacity<>-1) then Exit; FeldMaxValue:=Pred(newsize); {$ifdef FPC} Feld:=ReAllocMem(Feld,newsize*sizeof(PHashEntry)); {$else} ReAllocMem(Feld,newsize*sizeof(PHashEntry)); {$endif} //neu dazureservierten Speicher leeren (English: initialize the newly allocated memory) FillChar(Feld^[oldsize],(newsize-oldsize)*sizeof(PHashEntry),0); //dann Daten neu einordnen (English: then rearrange the data) for i:=0 to oldsize-1 do begin oe:=@Feld^[i]; he:=oe^; while Assigned(he) do begin newpos:=he^.Hash and FeldMaxValue; if (i<>newpos) then begin oe^:=he^.next; he^.next:=Feld^[newpos]; Feld^[newpos]:=he; end else oe:=@he^.next; he:=oe^; end; end; end; procedure THash.SetMaxCapacity(newmc: Integer); begin if newmc<0 then FMaxCapacity:=-1 else if newmc<Capacity then FMaxCapacity:=Capacity else FMaxCapacity:=newmc; end; procedure THash._SetStringObject(_key: String; s: String; set_s: Boolean; p: Pointer; set_p: Boolean); var h: Integer; he, anker: PHashEntry; begin if FeldBelegt>FeldMaxValue then MakeHashLarger(1); h:=Hash(_key); he:=Feld^[h and FeldMaxValue]; anker:=he; while Assigned(he) do begin if he^.hash=h then if he^.key=_key then begin if set_s then he^.value:=s; if set_p then he^.data:=p; Exit; end; he:=he^.next; end; //nichts gefunden, key mu neu angelegt werden (English?: not found; a new key must be created.) New(he); Inc(FeldBelegt); with he^ do begin next:=anker; hash:=h; key:=_key; if set_s then value:=s else value:=''; if set_p then data:=p else data:=nil; end; Feld^[h and FeldMaxValue]:=he; end; procedure THash.SetStringObject(_key: String; s: String; p: Pointer); begin _SetStringObject(_key,s,true,p,true); end; procedure THash.SetObject(_key: String; data: Pointer); begin _SetStringObject(_key,'',false,data,true); end; procedure THash.SetString(_key: String; data: String); begin _SetStringObject(_key,data,true,nil,false); end; procedure THash.DeleteKey(_key: String); var he: PHashEntry; oe: PPHashEntry; h: Integer; begin h:=Hash(_key); oe:=@Feld^[h and FeldMaxValue]; he:=oe^; while Assigned(he) do begin if he^.hash=h then if he^.key=_key then begin oe^:=he^.next; Dec(FeldBelegt); Dispose(he); Exit; end; oe:=@he^.next; he:=oe^; end; end; procedure THash.GetStringObject(_key: String; var s: String; var p: Pointer); var h: Integer; he: PHashEntry; begin s:=''; p:=nil; h:=Hash(_key); he:=Feld^[h and FeldMaxValue]; while Assigned(he) do begin if he^.hash=h then if he^.key=_key then begin s:=he^.value; p:=he^.data; Exit; end; he:=he^.next; end; end; function THash.GetObject(_key: String): Pointer; var h: Integer; he: PHashEntry; begin Result:=nil; h:=Hash(_key); he:=Feld^[h and FeldMaxValue]; while Assigned(he) do begin if he^.hash=h then if he^.key=_key then begin Result:=he^.data; Exit; end; he:=he^.next; end; end; function THash.GetString(_key: String): String; var h: Integer; he: PHashEntry; begin Result:=''; h:=Hash(_key); he:=Feld^[h and FeldMaxValue]; while Assigned(he) do begin if he^.hash=h then if he^.key=_key then begin Result:=he^.value; Exit; end; he:=he^.next; end; end; function THash.Keys: TStringList; var i: Integer; he: PHashEntry; begin Result:=TStringList.Create; for i:=0 to FeldMaxValue do begin he:=Feld^[i]; while Assigned(he) do begin Result.Add(he^.key); he:=he^.next; end; end; end; function THash.Keys(beginning: String): TStringList; var i: Integer; he: PHashEntry; begin Result:=TStringList.Create; for i:=0 to FeldMaxValue do begin he:=Feld^[i]; while Assigned(he) do begin if Copy(he^.key,1,length(beginning))=beginning then Result.Add(he^.key); he:=he^.next; end; end; end; { $log: 2001-06-19 wolf: created this unit 2001-08-12 wolf: added overloaded Keys(String) Method 2001-08-14 wolf: bugfix: test if assigned 2001-09-12 wolf: completely rewritten (now using a real hashing algorithm) 2001-09-25 wolf: added Delphi compatibility 2001-12-21 wolf: added properties Count, Capacity, MaxCapacity 2001-12-23 wolf: MakeHashLarger fixed (now possible to set Capacity) } { TObjectHash } procedure TObjectHash.Delete(_key: String); begin DeleteKey(_key); end; end. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Scanner.pas����������������������������������������������������������0000600�0001750�0001750�00000073262�13237143042�021325� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>) @abstract(Simple Pascal scanner.) The scanner object @link(TScanner) returns tokens from a Pascal language character input stream. It uses the @link(PasDoc_Tokenizer) unit to get tokens, regarding conditional directives that might lead to including another files or will add or delete conditional symbols. Also handles FPC macros (when HandleMacros is true). So, this scanner is a combined tokenizer and pre-processor. } unit PasDoc_Scanner; {$I pasdoc_defines.inc} interface uses SysUtils, Classes, PasDoc_Types, PasDoc_Tokenizer, PasDoc_StringVector, PasDoc_StreamUtils, PasDoc_StringPairVector; const { maximum number of streams we can recurse into; first one is the unit stream, any other stream an include file; current value is 32, increase this if you have more include files recursively including others } MAX_TOKENIZERS = 32; type { subrange type that has the 26 lower case letters from a to z } TUpperCaseLetter = 'A'..'Z'; { an array of boolean values, index type is @link(TUpperCaseLetter) } TSwitchOptions = array[TUpperCaseLetter] of Boolean; ETokenizerStreamEnd = class(EPasDoc); { This class scans one unit using one or more @link(TTokenizer) objects to scan the unit and all nested include files. } TScanner = class(TObject) private FCurrentTokenizer: Integer; FDirectiveLevel: Integer; FTokenizers: array[0..MAX_TOKENIZERS - 1] of TTokenizer; FSwitchOptions: TSwitchOptions; FBufferedToken: TToken; { For each symbol: Name is the unique Name, Value is the string to be expanded into (in case of a macro), Data is SymbolIsMacro or SymbolIsNotMacro to say if this is a macro (i.e. should it be expanded). Note the important fact: we can't use Value <> '' to decide if symbol is a macro. A non-macro symbol is something different than a macro that expands to nothing. } FSymbols: TStringPairVector; FIncludeFilePaths: TStringVector; FOnMessage: TPasDocMessageEvent; FVerbosity: Cardinal; FHandleMacros: boolean; { Removes symbol Name from the internal list of symbols. If Name was not in that list, nothing is done. } procedure DeleteSymbol(const Name: string); { Returns if a given symbol Name is defined at the moment. } function IsSymbolDefined(const Name: string): Boolean; function IsSwitchDefined(n: string): Boolean; { This creates and adds new Tokenizer to FTokenizers list and makes it the current tokenizer. It also checks MAX_TOKENIZERS limit. After calling this procedure, don't free Stream -- it will be owned by created Tokenizer, and created Tokenizer will be managed as part of FTokenizers list. } procedure OpenNewTokenizer(Stream: TStream; const StreamName, StreamPath: string); procedure OpenIncludeFile(n: string); { Returns @true if $else was found. If $endif or $ifend was found then returns @false. Note that for pasdoc, $endif and $ifend directives are always exactly equivalent and interchangeable. For Delphi, $if/$elseif must be terminated with $ifend (to be able to nest $if...$ifend within $ifdef...$endif on older Delphi versions that don't support $if, see Borland Delphi docs about this). For FPC, $endif is valid terminator for $if. PasDoc way is, as usual, to leave the checking for compiler. We treat $endif and $ifend the same and therefore we can parse any valid Delphi or FPC code. } function SkipUntilElseOrEndif: Boolean; procedure ResolveSwitchDirectives(const Comment: String); procedure SetIncludeFilePaths(Value: TStringVector); protected procedure DoError(const AMessage: string; const AArguments: array of const); procedure DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); public { Creates a TScanner object that scans the given input stream. Note that the stream S will be freed by this object (at destruction or when we will read all it's tokens), so after creating TScanner you should leave the stream to be managed completely by this TScanner. } constructor Create( const s: TStream; const OnMessageEvent: TPasDocMessageEvent; const VerbosityLevel: Cardinal; const AStreamName, AStreamPath: string; const AHandleMacros: boolean); destructor Destroy; override; { Adds Name to the list of symbols (as a normal symbol, not macro). } procedure AddSymbol(const Name: string); { Adds all symbols in the NewSymbols collection by calling @link(AddSymbol) for each of the strings in that collection. } procedure AddSymbols(const NewSymbols: TStringVector); { Adds Name as a symbol that is a macro, that expands to Value. } procedure AddMacro(const Name, Value: string); { Gets next token and throws it away. } procedure ConsumeToken; { Returns next token. Always non-nil (will raise exception in case of any problem). } function GetToken: TToken; { Returns the name of the file that is currently processed and the line number. Good for meaningful error messages. } function GetStreamInfo: string; { Paths to search for include files. When you assign something to this property it causes Assign(Value) call, not a real reference copy. } property IncludeFilePaths: TStringVector read FIncludeFilePaths write SetIncludeFilePaths; function PeekToken: TToken; { Place T in the buffer. Next time you will call GetToken you will get T. This also sets T to nil (because you shouldn't free T anymore after ungetting it). Note that the buffer has room only for 1 token, so you have to make sure that you will never unget more than two tokens. Practically, always call UnGetToken right after some GetToken. } procedure UnGetToken(var t: TToken); property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; property Verbosity: Cardinal read FVerbosity write FVerbosity; property SwitchOptions: TSwitchOptions read FSwitchOptions; property HandleMacros: boolean read FHandleMacros; end; implementation uses PasDoc_Utils; type { all directives a scanner is going to regard } TDirectiveType = (DT_UNKNOWN, DT_DEFINE, DT_ELSE, DT_ENDIF, DT_IFDEF, DT_IFNDEF, DT_IFOPT, DT_INCLUDE_FILE, DT_UNDEF, DT_INCLUDE_FILE_2, DT_IF, DT_ELSEIF, DT_IFEND); const DirectiveNames: array[DT_DEFINE..High(TDirectiveType)] of string = ( 'DEFINE', 'ELSE', 'ENDIF', 'IFDEF', 'IFNDEF', 'IFOPT', 'I', 'UNDEF', 'INCLUDE', 'IF', 'ELSEIF', 'IFEND' ); SymbolIsNotMacro = nil; SymbolIsMacro = Pointer(1); { ---------------------------------------------------------------------------- } (*Assumes that CommentContent is taken from a Token.CommentContent where Token.MyType was TOK_DIRECTIVE. Extracts DirectiveName and DirectiveParam from CommentContent. DirectiveName is the thing right after $ sign, uppercased. DirectiveParam (in two versions: Black and White) is what followed after DirectiveName. E.g. for CommentContent = {$define My_Symbol} we get DirectiveName = 'DEFINE' and DirectiveParamBlack = 'My_Symbol' (and DirectiveParamWhite also = 'My_Symbol'). We get two versions of DirectiveParam: @orderedList( @item(DirectiveParamBlack is what followed DirectiveName and ended at the 1st whitespace. So DirectiveParamBlack never contains any white char.) @item(DirectiveParamWhite is what followed DirectiveName and ended at end of CommentContent. So DirectiveParamWhite may contain white characters.) ) So DirectiveParamBlack is always a prefix of DirectiveParamWhite. Some directives use DirectiveParamBlack and some use DirectiveParamWhite, that's why we return both. E.g. {$ifdef foo bar xyz} is equivalent to {$ifdef foo} (bar and xyz are simply ignored by Pascal compilers). When using FPC and macro is off, or when using other compilers, {$define foo := bar xyz} means just {$define foo}. So you use DirectiveParamBlack. However when using FPC and macro is on, then {$define foo := bar xyz} means "define foo as a macro that expands to ``bar xyz'', so in this case you will need to use DirectiveParamWhite. *) function SplitDirective(const CommentContent: string; out DirectiveName, DirectiveParamBlack, DirectiveParamWhite: string): Boolean; var i: Integer; l: Integer; begin Result := False; DirectiveName := ''; DirectiveParamBlack := ''; DirectiveParamWhite := ''; l := Length(CommentContent); { skip dollar sign from CommentContent } i := 2; if i > l then Exit; { get directive name } while (i <= l) and (CommentContent[i] <> ' ') do begin DirectiveName := DirectiveName + UpCase(CommentContent[i]); Inc(i); end; Result := True; { skip spaces } while (i <= l) and (CommentContent[i] = ' ') do Inc(i); if i > l then Exit; { get parameters - no conversion to uppercase here, it could be an include file name whose name need not be changed (platform.inc <> PLATFORM.INC) } while (i <= l) and (CommentContent[i] <> ' ') do begin DirectiveParamBlack := DirectiveParamBlack + CommentContent[i]; Inc(i); end; DirectiveParamWhite := DirectiveParamBlack; while (i <= l) do begin DirectiveParamWhite := DirectiveParamWhite + CommentContent[i]; Inc(i); end; end; { First, splits CommentContent like SplitDirective. Then returns true and sets Dt to appropriate directive type, if DirectiveName was something known (see array DirectiveNames). Else returns false. } function IdentifyDirective(const CommentContent: string; out dt: TDirectiveType; out DirectiveName, DirectiveParamBlack, DirectiveParamWhite: string): Boolean; var i: TDirectiveType; begin Result := false; if SplitDirective(CommentContent, DirectiveName, DirectiveParamBlack, DirectiveParamWhite) then begin for i := DT_DEFINE to High(TDirectiveType) do begin if UpperCase(DirectiveName) = DirectiveNames[i] then begin dt := i; Result := True; break; end; end; end; end; { ---------------------------------------------------------------------------- } { TScanner } { ---------------------------------------------------------------------------- } constructor TScanner.Create( const s: TStream; const OnMessageEvent: TPasDocMessageEvent; const VerbosityLevel: Cardinal; const AStreamName, AStreamPath: string; const AHandleMacros: boolean); var c: TUpperCaseLetter; begin inherited Create; FOnMessage := OnMessageEvent; FVerbosity := VerbosityLevel; FHandleMacros := AHandleMacros; { Set default switch directives (according to the Delphi 4 Help). } for c := Low(SwitchOptions) to High(SwitchOptions) do FSwitchOptions[c] := False; FSwitchOptions['A'] := True; FSwitchOptions['C'] := True; FSwitchOptions['D'] := True; FSwitchOptions['G'] := True; FSwitchOptions['H'] := True; FSwitchOptions['I'] := True; FSwitchOptions['J'] := True; FSwitchOptions['L'] := True; FSwitchOptions['P'] := True; FSwitchOptions['O'] := True; FSwitchOptions['V'] := True; FSwitchOptions['X'] := True; FSymbols := TStringPairVector.Create(true); FTokenizers[0] := TTokenizer.Create(s, OnMessageEvent, VerbosityLevel, AStreamName, AStreamPath); FCurrentTokenizer := 0; FBufferedToken := nil; FIncludeFilePaths := TStringVector.Create; end; { ---------------------------------------------------------------------------- } destructor TScanner.Destroy; var i: Integer; begin FSymbols.Free; for i := 0 to FCurrentTokenizer do begin FTokenizers[i].Free; end; FBufferedToken.Free; FIncludeFilePaths.Free; inherited; end; { ---------------------------------------------------------------------------- } procedure TScanner.SetIncludeFilePaths(Value: TStringVector); begin FIncludeFilePaths.Assign(Value); end; { ---------------------------------------------------------------------------- } procedure TScanner.AddSymbol(const Name: string); begin if not IsSymbolDefined(Name) then begin DoMessage(6, pmtInformation, 'Symbol "%s" defined', [Name]); FSymbols.Add(TStringPair.Create(Name, '', SymbolIsNotMacro)); end; end; { ---------------------------------------------------------------------------- } procedure TScanner.AddSymbols(const NewSymbols: TStringVector); var i: Integer; begin if NewSymbols <> nil then for i := 0 to NewSymbols.Count - 1 do AddSymbol(NewSymbols[i]) end; { ---------------------------------------------------------------------------- } procedure TScanner.AddMacro(const Name, Value: string); var i: Integer; begin i := FSymbols.FindName(Name); if i = -1 then begin DoMessage(6, pmtInformation, 'Macro "%s" defined as "%s"', [Name, Value]); FSymbols.Add(TStringPair.Create(Name, Value, SymbolIsMacro)); end else begin DoMessage(6, pmtInformation, 'Macro "%s" RE-defined as "%s"', [Name, Value]); { Redefine macro in this case. } FSymbols.Items[i].Value := Value; end; end; { ---------------------------------------------------------------------------- } procedure TScanner.ConsumeToken; begin FBufferedToken := nil; end; { ---------------------------------------------------------------------------- } procedure TScanner.DeleteSymbol(const Name: string); begin FSymbols.DeleteName(Name); end; { ---------------------------------------------------------------------------- } function TScanner.GetStreamInfo: string; begin if (FCurrentTokenizer >= 0) then begin Result := FTokenizers[FCurrentTokenizer].GetStreamInfo end else begin Result := ''; end; end; { ---------------------------------------------------------------------------- } function TScanner.GetToken: TToken; { Call this when you get $define directive } procedure HandleDefineDirective( const DirectiveParamBlack, DirectiveParamWhite: string); var i: Integer; SymbolName: string; begin if not HandleMacros then AddSymbol(DirectiveParamBlack) else begin i := 1; while SCharIs(DirectiveParamWhite, i, ['a'..'z', 'A'..'Z', '1'..'9', '_']) do Inc(i); SymbolName := Copy(DirectiveParamWhite, 1, i - 1); while SCharIs(DirectiveParamWhite, i, WhiteSpace) do Inc(i); if Copy(DirectiveParamWhite, i, 2) = ':=' then AddMacro(SymbolName, Copy(DirectiveParamWhite, i + 2, MaxInt)) else AddSymbol(SymbolName); end; end; { If T is an identifier that expands to a macro, then it handles it (i.e. opens a new tokenizer that expands a macro) and returns true. Else returns false. } function ExpandMacro(T: TToken): boolean; var SymbolIndex: Integer; begin Result := T.MyType = TOK_IDENTIFIER; if Result then begin SymbolIndex := FSymbols.FindName(T.Data); Result := (SymbolIndex <> -1) and (FSymbols[SymbolIndex].Data = SymbolIsMacro); if Result then OpenNewTokenizer(TStringStream.Create( FSymbols[SymbolIndex].Value), '<' + FSymbols[SymbolIndex].Name + ' macro>', { Expanded macro text inherits current StreamPath } FTokenizers[FCurrentTokenizer].StreamPath); end; end; { Call this on $ifdef, $ifndef, $ifopt, $if directives. @param(IsTrue says if condition is true (so we should parse the section up to $else or $elseif, and then skip to $endif or $ifend.)) @param(DirectiveName is used for debug messages.) @param(DirectiveParam is also used for debug messages.) } procedure HandleIfDirective(IsTrue: boolean; const DirectiveName, DirectiveParam: string); begin DoMessage(6, pmtInformation, '$%s encountered (%s), condition is %s, level %d', [DirectiveName, DirectiveParam, BoolToStr(IsTrue), FDirectiveLevel]); if IsTrue then begin Inc(FDirectiveLevel); end else begin if SkipUntilElseOrEndif then Inc(FDirectiveLevel); end; end; { This is supposed to evaluate boolean conditions allowed after $if and $elseif directives. TODO: For now, this is dummy, and just prints and warning and returns true. } function IsIfConditionTrue(const Condition: string): boolean; begin DoMessage(2, pmtWarning, 'Evaluating $if and $elseif conditions is not implemented, ' + 'I''m simply assuming that "%s" is true', [Condition]); Result := true; end; var dt: TDirectiveType; Finished: Boolean; DirectiveName, DirectiveParamBlack, DirectiveParamWhite: string; begin if Assigned(FBufferedToken) then begin { we have a token buffered, we'll return this one } Result := FBufferedToken; FBufferedToken := nil; Exit; end; Finished := False; repeat { check if we have a tokenizer left } if (FCurrentTokenizer = -1) then raise ETokenizerStreamEnd.Create('Unexpected end of stream', [], 1); if FTokenizers[FCurrentTokenizer].HasData then begin { get next token from tokenizer } Result := FTokenizers[FCurrentTokenizer].GetToken; try { if token is a directive, then we handle it } if Result.MyType = TOK_DIRECTIVE then begin if IdentifyDirective(Result.CommentContent, dt, DirectiveName, DirectiveParamBlack, DirectiveParamWhite) then begin case dt of DT_DEFINE: HandleDefineDirective(DirectiveParamBlack, DirectiveParamWhite); DT_ELSE: begin DoMessage(5, pmtInformation, 'ELSE encountered', []); if (FDirectiveLevel > 0) then begin if not SkipUntilElseOrEndif then Dec(FDirectiveLevel); end else DoError(GetStreamInfo + ': unexpected $ELSE directive', []); end; DT_ENDIF, DT_IFEND: begin DoMessage(5, pmtInformation, '$%s encountered', [DirectiveName]); if (FDirectiveLevel > 0) then begin Dec(FDirectiveLevel); DoMessage(6, pmtInformation, 'FDirectiveLevel = ' + IntToStr(FDirectiveLevel), []); end else DoError(GetStreamInfo + ': unexpected $%s directive', [DirectiveName]); end; DT_IFDEF: HandleIfDirective(IsSymbolDefined(DirectiveParamBlack), 'IFDEF', DirectiveParamBlack); DT_IFNDEF: HandleIfDirective(not IsSymbolDefined(DirectiveParamBlack), 'IFNDEF', DirectiveParamBlack); DT_IFOPT: HandleIfDirective(IsSwitchDefined(DirectiveParamBlack), 'IFOPT', DirectiveParamBlack); DT_IF: HandleIfDirective(IsIfConditionTrue(DirectiveParamWhite), 'IF', DirectiveParamWhite); DT_INCLUDE_FILE, DT_INCLUDE_FILE_2: begin if (Length(DirectiveParamBlack) >= 2) and (DirectiveParamBlack[1] = '%') and (DirectiveParamBlack[Length(DirectiveParamBlack)] = '%') then begin (* Then this is FPC's feature, see "$I or $INCLUDE : Include compiler info" on [http://www.freepascal.org/docs-html/prog/progsu30.html]. Unlike FPC, PasDoc will not expand the %variable% (for reasoning, see comments in ../../tests/ok_include_environment.pas file). We change Result to say that it's a string literal (but we leave Result.Data as it is, to show exact info to the user). We do *not* want to enclose it in quotes, because then real string literal '{$I %DATE%}' wouldn't be different than using {$I %DATE%} feature. *) Result.MyType := TOK_STRING; Break; end else begin OpenIncludeFile(DirectiveParamBlack); end; end; DT_UNDEF: begin DoMessage(6, pmtInformation, 'UNDEF encountered (%s)', [DirectiveParamBlack]); DeleteSymbol(DirectiveParamBlack); end; end; end else begin ResolveSwitchDirectives(Result.Data); end; FreeAndNil(Result); end else if ExpandMacro(Result) then begin FreeAndNil(Result); end else begin { If the token is not a directive, and not an identifier that expands to a macro, then we just return it. } Finished := True; end; except FreeAndNil(Result); raise; end; end else begin DoMessage(5, pmtInformation, 'Closing file "%s"', [FTokenizers[FCurrentTokenizer].GetStreamInfo]); FTokenizers[FCurrentTokenizer].Free; FTokenizers[FCurrentTokenizer] := nil; Dec(FCurrentTokenizer); end; until Finished; end; { ---------------------------------------------------------------------------- } function TScanner.IsSymbolDefined(const Name: string): Boolean; begin Result := FSymbols.FindName(Name) <> -1; end; { ---------------------------------------------------------------------------- } function TScanner.IsSwitchDefined(N: string): Boolean; begin { We expect a length 2 AnsiString like 'I+' or 'A-', first character a letter, second character plus or minus } if Length(N) >= 2 then begin; if (N[1] >= 'a') and (N[1] <= 'z') then N[1] := Char(Ord(N[1]) - 32); if (N[1] >= 'A') and (N[1] <= 'Z') and ((N[2] = '-') or (N[2] = '+')) then begin Result := FSwitchOptions[N[1]] = (N[2] = '+'); Exit; end; end; DoMessage(2, pmtInformation, GetStreamInfo + ': Invalid $IFOPT parameter (%s).', [N]); Result := False; end; { ---------------------------------------------------------------------------- } procedure TScanner.OpenNewTokenizer(Stream: TStream; const StreamName, StreamPath: string); var Tokenizer: TTokenizer; begin { check if maximum number of FTokenizers has been reached } if FCurrentTokenizer = MAX_TOKENIZERS - 1 then begin Stream.Free; DoError('%s: Maximum level of recursion (%d) reached when trying to ' + 'create new tokenizer "%s" (Probably you have recursive file inclusion ' + '(with $include directive) or macro expansion)', [GetStreamInfo, MAX_TOKENIZERS, StreamName]); end; Tokenizer := TTokenizer.Create(Stream, FOnMessage, FVerbosity, StreamName, StreamPath); { add new tokenizer } Inc(FCurrentTokenizer); FTokenizers[FCurrentTokenizer] := Tokenizer; end; { ---------------------------------------------------------------------------- } procedure TScanner.OpenIncludeFile(n: string); var NLowerCase: string; UseLowerCase: boolean; { Check for availability of file N inside given Path (that must be like after IncludeTrailingPathDelimiter --- either '' or ends with PathDelim). It yes, then returns @true and opens new tokenizer with appropriate stream, else returns false. Check both N and NLowerCase (on case-sensitive system, filename may be written in exact case (like for Kylix) or lowercase (like for FPC 1.0.x), FPC >= 2.x accepts both). } function TryOpen(const Path: string): boolean; var Name: string; begin Name := Path + N; DoMessage(5, pmtInformation, 'Trying to open include file "%s"...', [Name]); Result := FileExists(Name); if (not Result) and UseLowerCase then begin Name := Path + NLowerCase; DoMessage(5, pmtInformation, 'Trying to open include file "%s" (lowercased)...', [Name]); Result := FileExists(Name); end; if Result then { create new tokenizer with stream } {$IFDEF STRING_UNICODE} OpenNewTokenizer(TStreamReader.Create(Name), Name, ExtractFilePath(Name)); {$ELSE} {$IFDEF USE_BUFFERED_STREAM} OpenNewTokenizer(TBufferedStream.Create(Name, fmOpenRead or fmShareDenyWrite), Name, ExtractFilePath(Name)); {$ELSE} OpenNewTokenizer(TFileStream.Create(Name, fmOpenRead or fmShareDenyWrite), Name, ExtractFilePath(Name)); {$ENDIF} {$ENDIF} end; function TryOpenIncludeFilePaths: boolean; var I: Integer; begin for I := 0 to IncludeFilePaths.Count - 1 do if IncludeFilePaths[I] <> '' then begin Result := TryOpen(IncludeFilePaths[I]); if Result then Exit; end; Result := false; end; begin if (Length(N) > 2) and (N[1] = '''') and (N[Length(N)] = '''') then N := Copy(N, 2, Length(N) - 2); NLowerCase := LowerCase(N); { If NLowerCase = N, avoid calling FileExists twice (as FileExists may be costly when generating large docs from many files) } UseLowerCase := NLowerCase <> N; if not TryOpen(FTokenizers[FCurrentTokenizer].StreamPath) then if not TryOpenIncludeFilePaths then if not TryOpen('') then DoError('%s: could not open include file %s', [GetStreamInfo, n]); end; { ---------------------------------------------------------------------------- } function TScanner.PeekToken: TToken; begin FBufferedToken := GetToken; Result := FBufferedToken; end; { ---------------------------------------------------------------------------- } function TScanner.SkipUntilElseOrEndif: Boolean; var dt: TDirectiveType; Level: Integer; DirectiveName, DirectiveParamBlack, DirectiveParamWhite: string; t: TToken; TT: TTokenType; begin Level := 1; repeat t := FTokenizers[FCurrentTokenizer].SkipUntilCompilerDirective; if t = nil then begin DoError('SkipUntilElseOrEndif GetToken', []); end; if (t.MyType = TOK_DIRECTIVE) then begin if IdentifyDirective(t.CommentContent, dt, DirectiveName, DirectiveParamBlack, DirectiveParamWhite) then begin DoMessage(6, pmtInformation, 'SkipUntilElseOrFound: encountered directive %s', [DirectiveNames[dt]]); case dt of DT_IFDEF, DT_IFNDEF, DT_IFOPT, DT_IF: Inc(Level); DT_ELSE: { RJ: We must jump over all nested $IFDEFs until its $ENDIF is encountered, ignoring all $ELSEs. We must therefore not decrement Level at $ELSE if it is part of such a nested $IFDEF. $ELSE must decrement Level only for the initial $IFDEF. That's why we test Level for 1 (initial $IFDEF) here. } if Level = 1 then Dec(Level); DT_ENDIF, DT_IFEND: Dec(Level); end; end; end; TT := t.MyType; t.Free; until (Level = 0) and (TT = TOK_DIRECTIVE) and (dt in [DT_ELSE, DT_ENDIF, DT_IFEND]); Result := (dt = DT_ELSE); DoMessage(6, pmtInformation, 'Skipped code, last directive is %s', [DirectiveNames[dt]]); end; { ---------------------------------------------------------------------------- } procedure TScanner.UnGetToken(var t: TToken); begin if Assigned(FBufferedToken) then DoError('%s: FATAL ERROR - CANNOT UNGET MORE THAN ONE TOKEN.', [GetStreamInfo]); FBufferedToken := t; t := nil; end; { ---------------------------------------------------------------------------- } procedure TScanner.DoError(const AMessage: string; const AArguments: array of const); begin raise EPasDoc.Create(AMessage, AArguments, 1); end; { ---------------------------------------------------------------------------- } procedure TScanner.DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if Assigned(FOnMessage) then FOnMessage(MessageType, Format(AMessage, AArguments), AVerbosity); end; { ---------------------------------------------------------------------------- } procedure TScanner.ResolveSwitchDirectives(const Comment: String); var p: PChar; l: Cardinal; c: Char; procedure SkipWhiteSpace; begin while (l > 0) and (p^ <= #32) do begin Inc(p); Dec(l); end; end; begin p := Pointer(Comment); l := Length(Comment); if l < 4 then Exit; case p^ of '{': begin if p[1] <> '$' then Exit; Inc(p, 2); Dec(l, 2); end; '(': begin if (p[1] <> '*') or (p[2] <> '$') then Exit; Inc(p, 3); Dec(l, 3); end; else Exit; end; repeat SkipWhiteSpace; if l < 3 then Exit; c := p^; if IsCharInSet(c, ['a'..'z']) then Dec(c, 32); if not IsCharInSet(c, ['A'..'Z']) or not IsCharInSet(p[1], ['-', '+']) then Exit; FSwitchOptions[c] := p[1] = '+'; Inc(p, 2); Dec(l, 2); SkipWhiteSpace; // Skip comma if (l = 0) or (p^ <> ',') then Exit; Inc(p); Dec(l); until False; end; end. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_TagManager.pas�������������������������������������������������������0000600�0001750�0001750�00000132056�13237143042�021737� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Collects information about available @@-tags and can parse text with tags.) } unit PasDoc_TagManager; {$I pasdoc_defines.inc} interface uses SysUtils, Classes, PasDoc_Types, PasDoc_ObjectVector; type TTagManager = class; TTag = class; { @seealso TTag.Execute } TTagExecuteEvent = procedure(ThisTag: TTag; var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string) of object; { @seealso TTag.AllowedInside } TTagAllowedInsideEvent = procedure( ThisTag: TTag; EnclosingTag: TTag; var Allowed: boolean) of object; TStringConverter = function(const s: string): string of object; TTagOption = ( { This means that tag expects parameters. If this is not included in TagOptions then tag should not be given any parameters, i.e. TagParameter passed to @link(TTag.Execute) should be ''. We will display a warning if user will try to give some parameters for such tag. } toParameterRequired, { This means that parameters of this tag will be expanded before passing them to @link(TTag.Execute). This means that we will expand recursive tags inside parameters, that we will ConvertString inside parameters, that we will handle paragraphs inside parameters etc. --- all that does @link(TTagManager.Execute). If toParameterRequired is not present in TTagOptions then it's not important whether you included toRecursiveTags. It's useful for some tags to include toParameterRequired without including toRecursiveTags, e.g. @@longcode or @@html, that want to get their parameters "verbatim", not processed. @bold(If toRecursiveTags is not included in tag options:) Then @italic(everything) is allowed within parameter of this tag, but nothing is interpreted. E.g. you can freely use @@ char, and even write various @@-tags inside @@html tag --- this doesn't matter, because @@-tags will not be interpreted (they will not be even searched !) inside @@html tag. In other words, @@ character means literally "@@" inside @@html, nothing more. The only exception are double @@@@, @@( and @@): we still treat them specially, to allow escaping the default parenthesis matching rules. Unless toRecursiveTagsManually is present. } toRecursiveTags, { Use this, instead of toRecursiveTags, if the implementation of your tag calls (always!) TagManager.CoreExecute on given TagParameter. This means that your tag is expanded recursively (it handles @-tags inside), but you do it manually (instead of allowing toRecursiveTags to do the job). In this case, TagParameter given will be really absolutely unmodified (even the special @@@@, @@( and @@) will not be handled), because we know that it will be handled later by special CoreExecute call. Never use both flags toRecursiveTags and toRecursiveTagsManually. } toRecursiveTagsManually, { This is meaningful only if toRecursiveTags is included. Then toAllowOtherTagsInsideByDefault determines are other tags allowed by the default implementation of @link(TTag.AllowedInside). } toAllowOtherTagsInsideByDefault, { This is meaningful only if toRecursiveTags is included. Then @name says that normal text is allowed inside parameter of this tag. @italic("Normal text") is anything except other @@-tags: normal text, paragraph breaks, various dashes, URLs, and literal @@ character (expressed by @@@@ in descriptions). If @name will not be included, then normal text (not enclosed within other @@-tags) will not be allowed inside. Only whitespace will be allowed, and it will be ignored anyway (i.e. will not be passed to ConvertString, empty line will not produce any Paragraph etc.). This is useful for tags like @@orderedList that should only contain other @@item tags inside. } toAllowNormalTextInside, { This is useful for tags like @@raises and @@param that treat 1st word of their descriptions very specially (where "what exactly is the 1st word" is defined by the @link(ExtractFirstWord) function). This tells pasdoc to leave the beginning of tag parameter (the first word and the eventual whitespace before it) as it is in the parameter. Don't search there for @@-tags, URLs, @-- or other special dashes, don't insert paragraphs, don't try to auto-link it. This is meaningful only if toRecursiveTags is included (otherwise the whole tag parameters are always preserved "verbatim"). TODO: in the future TTagExecuteEvent should just get this "first word" as a separate parameter, separated from TagParameters. Also, this word should not be converted by ConvertString. } toFirstWordVerbatim); TTagOptions = set of TTagOption; TTag = class private FOnPreExecute: TTagExecuteEvent; FOnExecute: TTagExecuteEvent; FTagOptions: TTagOptions; FName: string; FTagManager: TTagManager; FOnAllowedInside: TTagAllowedInsideEvent; public { Note that AName will be converted to lowercase before assigning to Name. } constructor Create(ATagManager: TTagManager; const AName: string; AOnPreExecute: TTagExecuteEvent; AOnExecute: TTagExecuteEvent; const ATagOptions: TTagOptions); property TagOptions: TTagOptions read FTagOptions write FTagOptions; { TagManager that will recognize and handle this tag. Note that the tag instance is owned by this tag manager (i.e. it will be freed inside this tag manager). It can be nil if no tag manager currently owns this tag. Note that it's very useful in @link(Execute) or @link(OnExecute) implementations. E.g. you can use it to report a message by @code(TagManager.DoMessage(...)), this is e.g. used by implementation of TPasItem.StoreAbstractTag. You could also use this to manually force recursive behavior of a given tag. I.e let's suppose that you have a tag with TagOptions = [toParameterRequired], so the TagParameter parameter passed to handler was not recursively expanded. Then you can do inside your handler @longcode# NewTagParameter := TagManager.Execute(TagParameter, ...) # and this way you have explicitly recursively expanded the tag. Scenario above is actually used in implementation of @@noAutoLink tag. There I call TagManager.Execute with parameter @code(AutoLink) set to false thus preventing auto-linking inside text within @@noAutoLink. } property TagManager: TTagManager read FTagManager; { Name of the tag, that must be specified by user after the "@@" sign. Value of this property must always be lowercase. } property Name: string read FName write FName; property OnPreExecute: TTagExecuteEvent read FOnPreExecute write FOnPreExecute; property OnExecute: TTagExecuteEvent read FOnExecute write FOnExecute; { This is completely analogous to @link(Execute) but used when @link(TTagManager.PreExecute) is @true. In this class this simply calls @link(OnPreExecute). } procedure PreExecute(var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); virtual; { This will be used to do main work when this @@-tag occured in description. EnclosingTag parameter specifies enclosing tag. This is useful for tags that must behave differently in different contexts, e.g. in plain-text output @@item tag will behave differently inside @@orderedList and @@unorderedList. EnclosingTag is nil when the tag occured at top level of the description. ThisTagData and EnclosingTagData form a mechanism to pass arbitraty data between child tags enclosed within one parent tag. Example uses: @unorderedList( @item(This is the way for multiple @@item tags inside @@orderedList tag to count themselves (to provide list item numbers, for pasdoc output formats that can't automatically number list items).) @item(This is the way for @@itemSpacing tag to communicate with enclosing @@orderedList tag to specify list style. ) @item(And this is the way for @@cell tags to be collected inside rows data and then @@rows tags to be collected inside table data. Thanks to such collecting @link(TDocGenerator.FormatTable) receives at once all information about given table, and can use it to format table.) ) How does this XxxTagData mechanism work: When we start parsing parameter of some tag with toRecursiveTags, we create a new pointer inited to @link(CreateOccurenceData). When @@-tags occur inside this parameter, we pass them this pointer as EnclosingTagData (this way all @@-tags with the same parent can use this pointer to communicate with each other). At the end, when parameter was parsed, we call given tag's Execute method passing the resulting pointer as ThisTagData (this way @@-tags with the same parent can use this pointer to pass some data to their parent). In this class this method simply calls @link(OnExecute) (if assigned). } procedure Execute(var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); virtual; property OnAllowedInside: TTagAllowedInsideEvent read FOnAllowedInside write FOnAllowedInside; { This will be checked always when this tag occurs within description. Given EnclosingTag is enclosing tag, nil if we're in top level. If this returns false then this tag will not be allowed inside EnclosingTag. In this class this method @orderedList( @item( Assumes that Result = true if we're at top level or EnclosingTag.TagOptions contains toAllowOtherTagsInsideByDefault. Else it assumes Result = false.) @item( Then it calls @link(OnAllowedInside OnAllowedInside(Self, EnclosingTag, Result)) (if OnAllowedInside is assigned).) ) } function AllowedInside(EnclosingTag: TTag): boolean; virtual; { In this class this simply returns @nil. } function CreateOccurenceData: TObject; virtual; { In this class this simply does @code(Value.Free). } procedure DestroyOccurenceData(Value: TObject); virtual; end; TTopLevelTag = class(TTag) { This returns just @code(EnclosingTag = nil). Which means that this tag is allowed only at top level of description, never inside parameter of some tag. } function AllowedInside(EnclosingTag: TTag): boolean; override; end; TNonSelfTag = class(TTag) { This returns just @code(inherited and (EnclosingTag <> Self)). Which means that (assuming that @link(OnAllowedInside) is not assigned) this tag is allowed at top level of description and inside parameter of any tag @italic(but not within itself and not within tags without toAllowOtherTagsInsideByDefault). This is currently not used by any tag. } function AllowedInside(EnclosingTag: TTag): boolean; override; end; { All Items of this list must be non-nil TTag objects. } TTagVector = class(TObjectVector) { Case of Name does @italic(not) matter (so don't bother converting it to lowercase or something like that before using this method). Returns nil if not found. Maybe in the future it will use hashlist, for now it's not needed. } function FindByName(const Name: string): TTag; end; TTryAutoLinkEvent = procedure(TagManager: TTagManager; const QualifiedIdentifier: TNameParts; out QualifiedIdentifierReplacement: string; var AutoLinked: boolean) of object; TTagManager = class private FTags: TTagVector; FConvertString: TStringConverter; FAbbreviations: TStringList; FOnMessage: TPasDocMessageEvent; FParagraph: string; FSpace: string; FShortDash, FEnDash, FEmDash: string; FURLLink: TStringConverter; FOnTryAutoLink: TTryAutoLinkEvent; FPreExecute: boolean; function DoConvertString(const s: string): string; function DoURLLink(const s: string): string; procedure Unabbreviate(var s: string); function TryAutoLink(const QualifiedIdentifier: TNameParts; out QualifiedIdentifierReplacement: string): boolean; public constructor Create; destructor Destroy; override; { Call OnMessage (if assigned) with given params. } procedure DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); { Call @link(DoMessage) only if @link(PreExecute) is @false. } procedure DoMessageNonPre(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); { This will be used to print messages from within @link(Execute). Note that in this unit we essentialy "don't know" that parsed Description string is probably attached to some TPasItem. It's good that we don't know it (because it makes this class more flexible). But it also means that OnMessage that you assign here may want to add to passed AMessage something like + ' (Expanded_TPasItem_Name)', see e.g. TDocGenerator.DoMessageFromExpandDescription. Maybe in the future we will do some descendant of this class, like TTagManagerForPasItem. } property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; { This will be inserted on paragraph marker (two consecutive newlines, see wiki page WritingDocumentation) in the text. This should specify how paragraphs are marked in particular output format, e.g. html generator may set this to '<p>'. Default value is ' ' (one space). } property Paragraph: string read FParagraph write FParagraph; { This will be inserted on each whitespace sequence (but not on paragraph break). This is consistent with [https://github.com/pasdoc/pasdoc/wiki/WritingDocumentation] that clearly says that "amount of whitespace does not matter". Although in some pasdoc output formats amount of whitespace also does not matter (e.g. HTML and LaTeX) but in other (e.g. plain text) it matters, so such space compression is needed. In other output formats (no examples yet) it may need to be expressed by something else than simple space, that's why this property is exposed. Default value is ' ' (one space). } property Space: string read FSpace write FSpace; { This will be inserted on @code(@@@-) in description, and on a normal single dash in description that is not a part of en-dash or em-dash. This should produce just a short dash. Default value is '-'. You will never get any '-' character to be converted by ConvertString. Convertion of '-' is controlled solely by XxxDash properties of tag manager. @seealso EnDash @seealso EmDash } property ShortDash: string read FShortDash write FShortDash; { This will be inserted on @code(@--) in description. This should produce en-dash (as in LaTeX). Default value is '@--'. } property EnDash: string read FEnDash write FEnDash; { This will be inserted on @code(@-@--) in description. This should produce em-dash (as in LaTeX). Default value is '@-@--'. } property EmDash: string read FEmDash write FEmDash; { This will be called from @link(Execute) when URL will be found in Description. Note that passed here URL will @italic(not) be processed by @link(ConvertString). This tells what to put in result on URL. If this is not assigned, then ConvertString(URL) will be appended to Result in @link(Execute). } property URLLink: TStringConverter read FURLLink write FURLLink; { This should check does QualifiedIdentifier looks like a name of some existing identifier. If yes, sets AutoLinked to true and sets QualifiedIdentifierReplacement to a link to QualifiedIdentifier (QualifiedIdentifierReplacement should be ready to be put in final documentation, i.e. already in the final output format). By default AutoLinked is false. } property OnTryAutoLink: TTryAutoLinkEvent read FOnTryAutoLink write FOnTryAutoLink; { This method is the very essence of this class and this unit. It expands Description, which means that it processes Description (text supplied by user in some comment in parsed unit) into something ready to be included in output documentation. This means that this handles parsing @@-tags, inserting paragraph markers, recognizing URLs in Description and correctly translating it, and translating rest of the "normal" text via ConvertString. If WantFirstSentenceEnd then we will look for '.' char followed by any whitespace in Description. Moreover, this '.' must be outside of any @@-tags parameter. Under FirstSentenceEnd we will return the number of beginning characters @italic(in the output string) that will include correspong '.' character (note that this definition takes into account that ConvertString may translate '.' into something longer). If no such character exists in Description, FirstSentenceEnd will be set to Length(Result), so the whole Description will be treated as it's first sentence. If WantFirstSentenceEnd, FirstSentenceEnd will not be set. } function Execute(const Description: string; AutoLink: boolean; WantFirstSentenceEnd: boolean; out FirstSentenceEnd: Integer): string; overload; { This is equivalent to Execute(Description, AutoLink, false, Dummy) } function Execute(const Description: string; AutoLink: boolean): string; overload; { This is the underlying version of Execute. Use with caution! If EnclosingTag = nil then this is understood to be toplevel of description, which means that all tags are allowed inside. If EnclosingTag <> nil then this is not toplevel. EnclosingTagData returns collected data for given EnclosingTag. You should init it to EnclosingTag.CreateOccurenceData. It will be passed as EnclosingTagData to each of @@-tags found inside Description. } function CoreExecute(const Description: string; AutoLink: boolean; EnclosingTag: TTag; var EnclosingTagData: TObject; WantFirstSentenceEnd: boolean; out FirstSentenceEnd: Integer): string; overload; function CoreExecute(const Description: string; AutoLink: boolean; EnclosingTag: TTag; var EnclosingTagData: TObject): string; overload; property ConvertString: TStringConverter read FConvertString write FConvertString; property Abbreviations: TStringList read FAbbreviations write FAbbreviations; { When @name is @true, tag manager will work a little differently than usual: @unorderedList( @item(Instead of @link(TTag.Execute), @link(TTag.PreExecute) will be called.) @item(Various warnings will @italic(not) be reported. Assumption is that you will later process the same text with @name set to @false to get all the warnings.) @item(AutoLink will not be used (like it was always false). Also the result of @link(Execute) will be pretty much random and meaningless (so you should ignore it). Also this means that the TagParameter for tags with toRecursiveTags should be ignored, because it will be something incorrect. This means that only tags without toRecursiveTags should actually use TagParameter in their OnPreExecute handlers. Assumption is that you actually don't care about the result of @link(Execute) methods, and you will later process the same text with @name set to @false to get the proper output. The goal is to make execution with PreExecute set to @true as fast as possible.) ) } property PreExecute: boolean read FPreExecute write FPreExecute; end; implementation uses PasDoc_Utils, StrUtils; { TTag ------------------------------------------------------------ } constructor TTag.Create(ATagManager: TTagManager; const AName: string; AOnPreExecute: TTagExecuteEvent; AOnExecute: TTagExecuteEvent; const ATagOptions: TTagOptions); begin inherited Create; FName := LowerCase(AName); FOnPreExecute := AOnPreExecute; FOnExecute := AOnExecute; FTagOptions := ATagOptions; FTagManager := ATagManager; if TagManager <> nil then TagManager.FTags.Add(Self); end; procedure TTag.PreExecute(var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if Assigned(OnPreExecute) then OnPreExecute(Self, ThisTagData, EnclosingTag, EnclosingTagData, TagParameter, ReplaceStr); end; procedure TTag.Execute(var ThisTagData: TObject; EnclosingTag: TTag; var EnclosingTagData: TObject; const TagParameter: string; var ReplaceStr: string); begin if Assigned(OnExecute) then OnExecute(Self, ThisTagData, EnclosingTag, EnclosingTagData, TagParameter, ReplaceStr); end; function TTag.AllowedInside(EnclosingTag: TTag): boolean; begin Result := (EnclosingTag = nil) or (toAllowOtherTagsInsideByDefault in EnclosingTag.TagOptions); if Assigned(OnAllowedInside) then OnAllowedInside(Self, EnclosingTag, Result); end; function TTag.CreateOccurenceData: TObject; begin Result := nil; end; procedure TTag.DestroyOccurenceData(Value: TObject); begin Value.Free; end; { TTopLevelTag ---------------------------------------------------------- } function TTopLevelTag.AllowedInside(EnclosingTag: TTag): boolean; begin Result := EnclosingTag = nil; end; { TNonSelfTag ----------------------------------------------------------- } function TNonSelfTag.AllowedInside(EnclosingTag: TTag): boolean; begin Result := inherited AllowedInside(EnclosingTag) and (EnclosingTag <> Self); end; { TTagVector ------------------------------------------------------------ } function TTagVector.FindByName(const Name: string): TTag; var i: Integer; NameLower: string; begin NameLower := LowerCase(Name); for i := 0 to Count - 1 do begin Result := TTag(Items[i]); if Result.Name = NameLower then Exit; end; Result := nil; end; { TTagManager ------------------------------------------------------------ } constructor TTagManager.Create; begin inherited Create; FTags := TTagVector.Create(true); FParagraph := ' '; FSpace := ' '; FShortDash := '-'; FEnDash := '--'; FEmDash := '---'; end; destructor TTagManager.Destroy; begin FreeAndNil(FTags); inherited; end; function TTagManager.DoConvertString(const s: string): string; begin if Assigned(FConvertString) then Result := FConvertString(s) else Result := s; end; function TTagManager.DoURLLink(const s: string): string; begin if Assigned(FURLLink) then Result := FURLLink(s) else Result := DoConvertString(s); end; procedure TTagManager.Unabbreviate(var s: string); var idx: Integer; begin if Assigned(Abbreviations) then begin idx := Abbreviations.IndexOfName(s); if idx>=0 then begin s := Abbreviations.Values[s]; end; end; end; procedure TTagManager.DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if Assigned(FOnMessage) then FOnMessage(MessageType, Format(AMessage, AArguments), AVerbosity); end; procedure TTagManager.DoMessageNonPre(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if not PreExecute then DoMessage(AVerbosity, MessageType, AMessage, AArguments); end; function TTagManager.TryAutoLink(const QualifiedIdentifier: TNameParts; out QualifiedIdentifierReplacement: string): boolean; begin Result := false; if Assigned(OnTryAutoLink) then OnTryAutoLink(Self, QualifiedIdentifier, QualifiedIdentifierReplacement, Result); if Result then DoMessage(3, pmtInformation, 'Automatically linked identifier "%s"', [GlueNameParts(QualifiedIdentifier)]); end; function TTagManager.CoreExecute(const Description: string; AutoLink: boolean; EnclosingTag: TTag; var EnclosingTagData: TObject; WantFirstSentenceEnd: boolean; out FirstSentenceEnd: Integer): string; var { This is the position of next char in Description to work with, i.e. first FOffset-1 chars in Description are considered "done" ("done" means that their converted version is appended to Result) } FOffset: Integer; { This checks if some tag starts at Description[FOffset + 1]. If yes then it returns true and sets -- Tag to given tag object -- Parameters to params for this tag (text specified between '(' ')', parsed to the matching parenthesis) -- OffsetEnd to the index of *next* character in Description right after this tag (including it's parameters, if there were any) Note that it may also change it's out parameters even when it returns false; this doesn't harm anything for now, so I don't think there's a reason to correct this for now. In case some string looking as tag name (A-Za-z*) is here, but it's not a name of any existing tag, it not only returns false but also emits a warning for user. } function FindTag(out Tag: TTag; out Parameters: string; out OffsetEnd: Integer): Boolean; var i: Integer; BracketCount: integer; TagName: string; begin Result := False; Parameters := ''; i := FOffset + 1; while (i <= Length(Description)) and IsCharInSet(Description[i], ['A'..'Z', 'a'..'z']) do Inc(i); if i = FOffset + 1 then Exit; { exit with false } TagName := Copy(Description, FOffset + 1, i - FOffset - 1); Tag := FTags.FindByName(TagName); OffsetEnd := i; if Tag = nil then begin DoMessageNonPre(1, pmtWarning, 'Unknown tag name "%s"', [TagName]); Exit; end; Result := true; { OK, we found the correct tag, Tag variable is already set. Now lets get the parameters, setting Parameters and OffsetEnd. } if (i <= Length(Description)) and (Description[i] = '(') then begin { Read Parameters to a matching parenthesis. Note that we didn't check here whether toParameterRequired in Tag.TagOptions. Caller of FindTag will give a warning for user if it will receive some Parameters <> '' while toParameterRequired is *not* in Tag.TagOptions } Inc(i); BracketCount := 1; while not ((i > Length(Description)) or (BracketCount = 0)) do begin case Description[i] of '@': { Inc(I) here means that we will skip to next character when we will see @@, @( or @). This means that @( and @) will correctly *not* change BracketCount. And @@ will be properly avoided, so that e.g. "@@(" will correctly increase BracketCount (because "@@(" means one "at" character and then normal opening paren). } Inc(I); '(': Inc(BracketCount); ')': Dec(BracketCount); end; Inc(i); end; if (BracketCount = 0) then begin Parameters := Copy(Description, OffsetEnd + 1, i - OffsetEnd - 2); OffsetEnd := i; end else DoMessageNonPre(1, pmtWarning, 'No matching closing parenthesis for tag "%s"', [TagName]); end else if toParameterRequired in Tag.TagOptions then begin { Read Parameters to the end of Description or newline. } while (i <= Length(Description)) and (not IsCharInSet(Description[i], [#10, #13])) do Inc(i); Parameters := Trim(Copy(Description, OffsetEnd, i - OffsetEnd)); OffsetEnd := i; end; end; { This checks whether we are looking (i.e. Description[FOffset] starts with) at a pargraph marker (i.e. newline + optional whitespace + newline + some more optional whitespaces and newlines) and if it is so, returns true and sets OffsetEnd to the next index in Description after this paragraph marker. } function FindParagraph(out OffsetEnd: Integer): boolean; var i: Integer; begin Result := false; i := FOffset; while SCharIs(Description, i, WhiteSpaceNotNL) do Inc(i); if not SCharIs(Description, i, WhiteSpaceNL) then Exit; { In case newline is two-characters wide, read it to the end (to not accidentally take #13#10 as two newlines.) } Inc(i); if (i <= Length(Description)) and ( ((Description[i-1] = #10) and (Description[i] = #13)) or ((Description[i-1] = #13) and (Description[i] = #10)) ) then Inc(i); while SCharIs(Description, i, WhiteSpaceNotNL) do Inc(i); if not SCharIs(Description, i, WhiteSpaceNL) then Exit; { OK, so we found 2nd newline. So we got paragraph marker. Now read it to the end. } Result := true; while SCharIs(Description, i, WhiteSpace) do Inc(i); OffsetEnd := i; end; { This checks whether we are looking (i.e. Description[FOffset] starts with) at some whitespace. If true, then it also sets OffsetEnd to next index after whitespace. } function FindWhitespace(out OffsetEnd: Integer): boolean; begin Result := SCharIs(Description, FOffset, WhiteSpace); if Result then begin OffsetEnd := FOffset + 1; while SCharIs(Description, OffsetEnd, WhiteSpace) do Inc(OffsetEnd); end; end; { Checks does Description[FOffset] may be a beginning of some URL. (xxx://xxxx/.../). If yes, returns true and sets OffsetEnd to the next index in Description after this URL. For your comfort, returns also URL (this is *always* Copy(Description, FOffset, OffsetEnd - FOffset)). } function FindURL(out OffsetEnd: Integer; out URL: string): boolean; { Here's how it works, and what is the meaning of constants below: Include all continuous AlphaNum chars. Then must be '://'. Include all continuous FullLinkChars and HalfLinkChars chars after '://' but then strip all HalfLinkChars from the end. This means that HalfLinkChars are allowed in the middle of URL, but only as long as there is some char after FullLinkChars but not at the end. } const AlphaNum = ['A'..'Z', 'a'..'z', '0'..'9']; FullLinkChars = AlphaNum + ['_', '%', '/', '#', '~', '@']; HalfLinkChars = ['.', ',', '-', ':', ';', '?', '=', '&']; URLMiddle = '://'; var i: Integer; begin Result := False; i := FOffset; while SCharIs(Description, i, AlphaNum) do Inc(i); if not (Copy(Description, i, Length(URLMiddle)) = URLMiddle) then Exit; Result := true; i := i + Length(URLMiddle); while SCharIs(Description, i, FullLinkChars + HalfLinkChars) do Inc(i); Dec(i); while IsCharInSet(Description[i], HalfLinkChars) do Dec(i); Inc(i); OffsetEnd := i; URL := Copy(Description, FOffset, OffsetEnd - FOffset); end; { Checks does Description[FOffset] may be a beginning of some qualified identifier (identifier is [A-Za-z_]([A-Za-z_0-9])*, qualified identifier is a sequence of identifiers delimited by dots). If yes, returns true and sets OffsetEnd to the next index in Description after this qualified ident. For your comfort, returns also QualifiedIdentifier (this is *always* equal to SplitNameParts( Copy(Description, FOffset, OffsetEnd - FOffset))). } function FindQualifiedIdentifier(out OffsetEnd: Integer; out QualifiedIdentifier: TNameParts): boolean; const FirstIdentChar = ['a'..'z', 'A'..'Z', '_']; NonFirstIdentChar = FirstIdentChar + ['0'..'9']; AnyQualifiedIdentChar = NonFirstIdentChar + ['.']; var NamePartBegin: Integer; begin Result := ( (FOffset = 1) or not IsCharInSet(Description[FOffset - 1], AnyQualifiedIdentChar) ) and SCharIs(Description, FOffset, FirstIdentChar); if Result then begin NamePartBegin := FOffset; OffsetEnd := FOffset + 1; SetLength(QualifiedIdentifier, 0); repeat { skip a sequence of NonFirstIdentChar characters } while SCharIs(Description, OffsetEnd, NonFirstIdentChar) do Inc(OffsetEnd); if Length(QualifiedIdentifier) = MaxNameParts then begin { I can't add new item to QualifiedIdentifier. So Result is false. } Result := false; Exit; end; { Append next part to QualifiedIdentifier } SetLength(QualifiedIdentifier, Length(QualifiedIdentifier) + 1); QualifiedIdentifier[Length(QualifiedIdentifier) - 1] := Copy(Description, NamePartBegin, OffsetEnd - NamePartBegin); if SCharIs(Description, OffsetEnd, '.') and SCharIs(Description, OffsetEnd + 1, FirstIdentChar) then begin NamePartBegin := OffsetEnd + 1; { skip the dot and skip FirstIdentChar character } Inc(OffsetEnd, 2); end else break; until false; end; end; function FindFirstSentenceEnd: boolean; begin Result := (Description[FOffset] = '.') and SCharIs(Description, FOffset + 1, WhiteSpace); end; function IsNormalTextAllowed: boolean; begin Result := (EnclosingTag = nil) or (toAllowNormalTextInside in EnclosingTag.TagOptions); end; function CheckNormalTextAllowed(const NormalText: string): boolean; begin Result := IsNormalTextAllowed; if not Result then DoMessageNonPre(1, pmtWarning, 'Such content, "%s", is not allowed '+ 'directly within the tag @%s', [NormalText, EnclosingTag.Name]); end; { Strip initial @ from @( and @). Do not touch other @ occurences. This is only used for tags without toRecursiveTags (for toRecursiveTags, the recursive call to CoreExecute will already handle it). } function HandleAtChar(const S: string): string; var PosAt, HandledCount: Integer; begin Result := ''; HandledCount := 0; while HandledCount < Length(S) do begin PosAt := PosEx('@', S, HandledCount + 1); if PosAt = 0 then begin Result := Result + SEnding(S, HandledCount + 1); HandledCount := Length(S); end else if SCharIs(S, PosAt + 1, ['(', ')', '@']) then begin { strip @, add the next ( or ) or @ } Result := Result + Copy(S, HandledCount + 1, PosAt - HandledCount - 1) + S[PosAt + 1]; HandledCount := PosAt + 1; end else begin { do not strip @ } Result := Result + Copy(S, HandledCount + 1, PosAt - HandledCount); HandledCount := PosAt; end; end; end; var { Always ConvertBeginOffset <= FOffset. Description[ConvertBeginOffset ... FOffset - 1] is the string that should be filtered by DoConvertString. } ConvertBeginOffset: Integer; { This function increases ConvertBeginOffset to FOffset, appending converted version of Description[ConvertBeginOffset ... FOffset - 1] to Result. } procedure DoConvert; var ToAppend: string; begin ToAppend := Copy(Description, ConvertBeginOffset, FOffset - ConvertBeginOffset); if ToAppend <> '' then begin if (not PreExecute) and CheckNormalTextAllowed(ToAppend) then Result := Result + DoConvertString(ToAppend); ConvertBeginOffset := FOffset; end; end; var ReplaceStr: string; Params: string; OffsetEnd: Integer; FoundTag: TTag; URL: string; FoundTagData: TObject; QualifiedIdentifier: TNameParts; QualifiedIdentifierReplacement: string; begin Result := ''; FOffset := 1; ConvertBeginOffset := 1; if (EnclosingTag <> nil) and (toFirstWordVerbatim in EnclosingTag.TagOptions) then begin { Skip the first word in Description } while SCharIs(Description, FOffset, WhiteSpace) do Inc(FOffset); while SCharIs(Description, FOffset, AllChars - WhiteSpace) do Inc(FOffset); end; if WantFirstSentenceEnd then FirstSentenceEnd := 0; { Description[FOffset] is the next char that must be processed (we're "looking at it" right now). } while FOffset <= Length(Description) do begin if (Description[FOffset] = '@') and FindTag(FoundTag, Params, OffsetEnd) then begin DoConvert; { Check is it allowed for this tag to be here } if not FoundTag.AllowedInside(EnclosingTag) then begin if EnclosingTag = nil then DoMessageNonPre(1, pmtWarning, 'The tag "@%s" cannot be used at the ' + 'top level of description, it must be used within some other @-tag', [FoundTag.Name]) else DoMessageNonPre(1, pmtWarning, 'The tag "@%s" cannot be used inside ' + 'parameter of tag "@%s"', [FoundTag.Name, EnclosingTag.Name]); { Assign dummy value for ReplaceStr. We can't proceed with normal recursive expanding and calling FoundTag.[Pre]Execute, because tag methods (and callbacks, like TTag.On[Pre]Execute) may assume that the tag is always enclosed only within allowed tags (so e.g. EnclosingTag and EnclosingTagData values for On[Pre]Execute are of appropriate classes etc.) } ReplaceStr := ''; end else begin FoundTagData := FoundTag.CreateOccurenceData; try { Process Params } if Params <> '' then begin if toParameterRequired in FoundTag.TagOptions then begin Unabbreviate(Params); if toRecursiveTags in FoundTag.TagOptions then { recursively expand Params } Params := CoreExecute(Params, AutoLink, FoundTag, FoundTagData) else if not (toRecursiveTagsManually in FoundTag.TagOptions) then Params := HandleAtChar(Params); end else begin { Note that in this case we ignore whether toRecursiveTags is in Tag.TagOptions, we always behave like toRecursiveTags was not included. This is reported as a serious warning, because tag handler procedure will probably ignore passed value of Params and will set ReplaceStr to something unrelated to Params. This means that user input is completely discarded. So user should really correct it. I didn't mark this as an mtError only because some sensible output will be generated anyway. } DoMessageNonPre(1, pmtWarning, 'Tag "%s" is not allowed to have any parameters', [FoundTag.Name]); end; ReplaceStr := DoConvertString('@(' + FoundTag.Name) + Params + ConvertString(')'); end else ReplaceStr := DoConvertString('@' + FoundTag.Name); { execute tag handler } if PreExecute then FoundTag.PreExecute(FoundTagData, EnclosingTag, EnclosingTagData, Params, ReplaceStr) else FoundTag.Execute(FoundTagData, EnclosingTag, EnclosingTagData, Params, ReplaceStr); finally FoundTag.DestroyOccurenceData(FoundTagData) end; end; Result := Result + ReplaceStr; FOffset := OffsetEnd; ConvertBeginOffset := FOffset; end else if Copy(Description, FOffset, 2) = '@(' then begin DoConvert; { convert '@(' to '(' } if CheckNormalTextAllowed('@(') then Result := Result + '('; FOffset := FOffset + 2; ConvertBeginOffset := FOffset; end else if Copy(Description, FOffset, 2) = '@)' then begin DoConvert; { convert '@)' to '(' } if CheckNormalTextAllowed('@)') then Result := Result + ')'; FOffset := FOffset + 2; ConvertBeginOffset := FOffset; end else if Copy(Description, FOffset, 2) = '@@' then begin DoConvert; { convert '@@' to '@' } if CheckNormalTextAllowed('@@') then Result := Result + '@'; FOffset := FOffset + 2; ConvertBeginOffset := FOffset; end else if Copy(Description, FOffset, 2) = '@-' then begin DoConvert; { convert '@-' to ShortDash } if CheckNormalTextAllowed('@-') then Result := Result + ShortDash; FOffset := FOffset + 2; ConvertBeginOffset := FOffset; end else { Note that we must scan for '---' in Description before scanning for '--'. } if Copy(Description, FOffset, 3) = '---' then begin DoConvert; { convert '---' to EmDash } if CheckNormalTextAllowed('---') then Result := Result + EmDash; FOffset := FOffset + 3; ConvertBeginOffset := FOffset; end else if Copy(Description, FOffset, 2) = '--' then begin DoConvert; { convert '--' to EnDash } if CheckNormalTextAllowed('--') then Result := Result + EnDash; FOffset := FOffset + 2; ConvertBeginOffset := FOffset; end else if Description[FOffset] = '-' then begin DoConvert; { So '-' is just a normal ShortDash } if CheckNormalTextAllowed('-') then Result := Result + ShortDash; FOffset := FOffset + 1; ConvertBeginOffset := FOffset; end else if FindParagraph(OffsetEnd) then begin DoConvert; { If normal text is allowed then append Paragraph to Result. Otherwise just ignore any whitespace in Description. } if IsNormalTextAllowed then Result := Result + Paragraph; FOffset := OffsetEnd; ConvertBeginOffset := FOffset; end else { FindWhitespace must be checked after FindParagraph, otherwise we would take paragraph as just some whitespace. } if FindWhitespace(OffsetEnd) then begin DoConvert; { If normal text is allowed then append Space to Result. Otherwise just ignore any whitespace in Description. } if IsNormalTextAllowed then Result := Result + Space; FOffset := OffsetEnd; ConvertBeginOffset := FOffset; end else if (not PreExecute) and AutoLink and FindQualifiedIdentifier(OffsetEnd, QualifiedIdentifier) and TryAutoLink(QualifiedIdentifier, QualifiedIdentifierReplacement) then begin DoConvert; if CheckNormalTextAllowed(GlueNameParts(QualifiedIdentifier)) then Result := Result + QualifiedIdentifierReplacement; FOffset := OffsetEnd; ConvertBeginOffset := FOffset; end else if FindURL(OffsetEnd, URL) then begin DoConvert; if CheckNormalTextAllowed(URL) then Result := Result + DoURLLink(URL); FOffset := OffsetEnd; ConvertBeginOffset := FOffset; end else if WantFirstSentenceEnd and (FirstSentenceEnd = 0) and FindFirstSentenceEnd then begin DoConvert; if CheckNormalTextAllowed('.') then begin Result := Result + ConvertString('.'); FirstSentenceEnd := Length(Result); end; Inc(FOffset); ConvertBeginOffset := FOffset; end else Inc(FOffset); end; DoConvert; if WantFirstSentenceEnd and (FirstSentenceEnd = 0) then FirstSentenceEnd := Length(Result); { Only for testing: Writeln('----'); Writeln('Description was "', Description, '"'); Writeln('Result is "', Result, '"'); Writeln('----');} end; function TTagManager.CoreExecute(const Description: string; AutoLink: boolean; EnclosingTag: TTag; var EnclosingTagData: TObject): string; var Dummy: Integer; begin Result := CoreExecute(Description, AutoLink, EnclosingTag, EnclosingTagData, false, Dummy); end; function TTagManager.Execute(const Description: string; AutoLink: boolean; WantFirstSentenceEnd: boolean; out FirstSentenceEnd: Integer): string; var EnclosingTagData: TObject; begin EnclosingTagData := nil; Result := CoreExecute(Description, AutoLink, nil, EnclosingTagData, WantFirstSentenceEnd, FirstSentenceEnd); { Just ignore resulting EnclosingTagData } end; function TTagManager.Execute(const Description: string; AutoLink: boolean): string; var Dummy: Integer; begin Result := Execute(Description, AutoLink, false, Dummy); end; end. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_HierarchyTree.pas����������������������������������������������������0000600�0001750�0001750�00000020213�13237143042�022456� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) a n-ary tree for PasItems --- for use in Class Hierarchy } unit PasDoc_HierarchyTree; {$I pasdoc_defines.inc} interface uses Classes, PasDoc_Items; type TPasItemNode = class(TObject) protected FChildren: TList; FParent: TPasItemNode; FItem: TPasItem; FName: string; function GetName: string; protected procedure AddChild(const Child: TPasItemNode); overload; function AddChild(const AName: string): TPasItemNode; overload; function AddChild(const AItem: TPasItem): TPasItemNode; overload; function FindItem(const AName: string): TPasItemNode; procedure Adopt(const AChild: TPasItemNode); function Orphan(const AChild: TPasItemNode): boolean; procedure Sort; public constructor Create; destructor Destroy; override; function Level: Integer; property Name: string read GetName; property Item: TPasItem read FItem; property Parent: TPasItemNode read FParent; end; TStringCardinalTree = class protected FRoot: TPasItemNode; function GetIsEmpty: boolean; function GetFirstItem: TPasItemNode; procedure NeedRoot; public function ItemOfName(const AName: string): TPasItemNode; function InsertName(const AName: string): TPasItemNode; overload; function InsertItem(const AItem: TPasItem): TPasItemNode; overload; function InsertParented(const AParent: TPasItemNode; const AItem: TPasItem): TPasItemNode; overload; function InsertParented(const AParent: TPasItemNode; const AName: string): TPasItemNode; overload; procedure MoveChildLast(const Child, Parent: TPasItemNode); property IsEmpty: boolean read GetIsEmpty; property FirstItem: TPasItemNode read GetFirstItem; function Level(const ANode: TPasItemNode): Integer; function NextItem(const ANode: TPasItemNode): TPasItemNode; procedure Sort; constructor Create; destructor Destroy; override; end; function NewStringCardinalTree: TStringCardinalTree; implementation uses SysUtils; function SortProc(A, B: Pointer): Integer; begin Result := CompareText(TPasItemNode(A).Name, TPasItemNode(B).Name) end; function NewStringCardinalTree: TStringCardinalTree; begin Result := TStringCardinalTree.Create; end; { TStringCardinalTree } constructor TStringCardinalTree.Create; begin FRoot := nil; end; destructor TStringCardinalTree.Destroy; begin FRoot.Free; inherited; end; function TStringCardinalTree.GetFirstItem: TPasItemNode; begin Result := nil; if Assigned(FRoot) then begin if FRoot.FChildren.Count > 0 then begin Result := TPasItemNode(FRoot.FChildren[0]); end; end; end; function TStringCardinalTree.GetIsEmpty: boolean; begin Result := not Assigned(FRoot); end; function TStringCardinalTree.InsertName( const AName: string): TPasItemNode; begin NeedRoot; Result := FRoot.AddChild(AName); end; function TStringCardinalTree.InsertParented(const AParent: TPasItemNode; const AItem: TPasItem): TPasItemNode; begin if AParent = nil then begin NeedRoot; Result := FRoot.AddChild(AItem); end else begin Result := AParent.AddChild(AItem); end end; function TStringCardinalTree.InsertParented(const AParent: TPasItemNode; const AName: string): TPasItemNode; begin if AParent = nil then begin NeedRoot; Result := FRoot.AddChild(AName); end else begin Result := AParent.AddChild(AName); end end; function TStringCardinalTree.Level( const ANode: TPasItemNode): Integer; begin Result := ANode.Level; end; procedure TStringCardinalTree.MoveChildLast(const Child, Parent: TPasItemNode); begin NeedRoot; if FRoot.Orphan(Child) then begin Parent.Adopt(Child); end; end; procedure TStringCardinalTree.NeedRoot; begin if not Assigned(FRoot) then begin FRoot := TPasItemNode.Create; end; end; function TStringCardinalTree.ItemOfName( const AName: string): TPasItemNode; begin NeedRoot; Result := FRoot.FindItem(AName); end; function TStringCardinalTree.NextItem( const ANode: TPasItemNode): TPasItemNode; var idx: Integer; LNode: TPasItemNode; begin Result := nil; if ANode.FChildren.Count > 0 then begin Result := TPasItemNode(ANode.FChildren[0]); end; if Result = nil then begin if Assigned(ANode.FParent) then begin idx := ANode.FParent.FChildren.IndexOf(ANode); if idx + 1 < ANode.FParent.FChildren.Count then begin Result := TPasItemNode(ANode.FParent.FChildren[idx + 1]); end; end; end; if Result = nil then begin LNode := ANode.FParent; while Assigned(LNode) do begin if Assigned(LNode.FParent) then begin idx := LNode.FParent.FChildren.IndexOf(LNode); if LNode.FParent.FChildren.Count > idx + 1 then begin Result := TPasItemNode(LNode.FParent.FChildren[idx + 1]); break; end; end; LNode := LNode.FParent; end; end; end; procedure TStringCardinalTree.Sort; begin if Assigned(FRoot) then begin FRoot.Sort; end; end; function TStringCardinalTree.InsertItem( const AItem: TPasItem): TPasItemNode; begin Result := InsertParented(nil, AItem); end; { TPasItemNode } procedure TPasItemNode.AddChild(const Child: TPasItemNode); begin FChildren.Add(Child); end; function TPasItemNode.AddChild(const AName: string): TPasItemNode; begin Result := TPasItemNode.Create; Result.FItem := nil; Result.FName := AName; Result.FParent := Self; AddChild(Result); end; function TPasItemNode.AddChild(const AItem: TPasItem): TPasItemNode; begin Result := TPasItemNode.Create; Result.FItem := AItem; Result.FParent := Self; AddChild(Result); end; procedure TPasItemNode.Adopt(const AChild: TPasItemNode); begin FChildren.Add(AChild); AChild.FParent := Self; end; constructor TPasItemNode.Create; begin FParent := nil; FChildren := TList.Create; FItem := nil; end; destructor TPasItemNode.Destroy; var i: Integer; begin for i := 0 to FChildren.Count-1 do begin TObject(FChildren.Items[i]).Free; end; FChildren.Free; inherited; end; function TPasItemNode.FindItem( const AName: string): TPasItemNode; var i: Integer; LName: string; begin Result := nil; LName := LowerCase(AName); for i := 0 to FChildren.Count - 1 do begin if LowerCase(TPasItemNode(FChildren[i]).Name) = LName then begin Result := TPasItemNode(FChildren[i]); break; end; Result := TPasItemNode(FChildren[i]).FindItem(AName); if Assigned(Result) then break; end; end; function TPasItemNode.GetName: string; begin if Assigned(FItem) then begin Result := FItem.Name; end else begin Result := FName; end; end; function TPasItemNode.Level: Integer; begin if Assigned(FParent) then begin Result := FParent.Level + 1; end else begin Result := 0; end; end; function TPasItemNode.Orphan( const AChild: TPasItemNode): boolean; var i: Integer; begin i := FChildren.IndexOf(AChild); Result := false; if i >= 0 then begin FChildren.Delete(i); Result := true; end else begin for i := FChildren.Count - 1 downto 0 do begin Result := TPasItemNode(FChildren[i]).Orphan(AChild); if Result then break; end; end; end; procedure TPasItemNode.Sort; var i: Integer; begin FChildren.Sort( {$IFDEF FPC}@{$ENDIF} SortProc); for i := FChildren.Count-1 downto 0 do begin TPasItemNode(FChildren[i]).Sort; end; end; end. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_OptionParser.pas�����������������������������������������������������0000600�0001750�0001750�00000056511�13237143042�022357� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(The @name unit --- easing command line parsing) @author(Johannes Berg <johannes@sipsolutions.de>) To use this unit, create an object of @link(TOptionParser) and add options to it, each option descends from @link(TOption). Then, call your object's @link(TOptionParser.ParseOptions) method and options are parsed. After parsing, examine your option objects. } unit PasDoc_OptionParser; {$I pasdoc_defines.inc} interface uses Classes {$IFDEF USE_VARIANTS}, Variants {$ENDIF}; const { default short option character used } DefShortOptionChar = '-'; { default long option string used } DefLongOptionString = '--'; type TOptionParser = class; { @abstract(abstract base class for options) This class implements all the basic functionality and provides abstract methods for the @link(TOptionParser) class to call, which are overridden by descendants. It also provides function to write the explanation. } TOption = class protected FShort: char; FLong: string; FShortSens: boolean; FLongSens: boolean; FExplanation: string; FWasSpecified: boolean; FParser: TOptionParser; function ParseOption(const AWords: TStrings): boolean; virtual; abstract; {$IFDEF USE_VARIANTS} function GetValue: Variant; virtual; abstract; procedure SetValue(const AValue: Variant); virtual; abstract; {$ENDIF} public { Create a new Option. Set AShort to #0 in order to have no short option. Technically you can set ALong to '' to have no long option, but in practive *every* option should have long form. Don't override this in descendants (this always simply calls CreateEx). Override only CreateEx. } constructor Create(const AShort:char; const ALong: string); constructor CreateEx(const AShort:char; const ALong: string; const AShortCaseSensitive, ALongCaseSensitive: boolean); virtual; { returns the width of the string "-s, @--long-option" where s is the short option. Removes non-existant options (longoption = '' or shortoption = #0) } function GetOptionWidth: Integer; { writes the wrapped explanation including option format, AOptWidth determines how much it is indented & wrapped } procedure WriteExplanation(const AOptWidth: Integer); { Short form of the option --- single character --- if #0 then not used } property ShortForm: char read FShort write FShort; { long form of the option --- string --- if empty, then not used } property LongForm: string read FLong write FLong; { specified whether the short form should be case sensitive or not } property ShortCaseSensitive: boolean read FShortSens write FShortSens; { specifies whether the long form should be case sensitive or not } property LongCaseSensitive: boolean read FLongSens write FLongSens; { signifies if the option was specified at least once } property WasSpecified: boolean read FWasSpecified; { explanation for the option, see also @link(WriteExplanation) } property Explanation: string read FExplanation write FExplanation; {$IFDEF USE_VARIANTS} { Value as Variant --- for easier access through the @link(TOptionParser.ByName) property } property Value: Variant read GetValue write SetValue; {$ENDIF} end; { @abstract(simple boolean option) turned off when not specified, turned on when specified. Cannot handle @--option=false et al. } TBoolOption = class(TOption) protected function ParseOption(const AWords: TStrings): boolean; override; {$IFDEF USE_VARIANTS} function GetValue: Variant; override; procedure SetValue(const AValue: Variant); override; {$ENDIF} public property TurnedOn: boolean read FWasSpecified; end; { @abstract(base class for all options that values) base class for all options that take one or more values of the form @--option=value or @--option value etc } TValueOption = class(TOption) protected function CheckValue(const AString: String): boolean; virtual; abstract; function ParseOption(const AWords: TStrings): boolean; override; end; { @abstract(Integer option) accepts only integers } TIntegerOption = class(TValueOption) protected FValue: Integer; function CheckValue(const AString: String): boolean; override; {$IFDEF USE_VARIANTS} function GetValue: Variant; override; procedure SetValue(const AValue: Variant); override; {$ENDIF} public property Value: Integer read FValue write FValue; end; { @abstract(String option) accepts a single string } TStringOption = class(TValueOption) protected FValue: String; function CheckValue(const AString: String): boolean; override; {$IFDEF USE_VARIANTS} function GetValue: Variant; override; procedure SetValue(const AValue: Variant); override; {$ENDIF} public property Value: String read FValue write FValue; end; { @abstract(stringlist option) accepts multiple strings and collates them even if the option itself is specified more than one time } TStringOptionList = class(TValueOption) protected FValues: TStringList; function CheckValue(const AString: String): Boolean; override; {$IFDEF USE_VARIANTS} function GetValue: Variant; override; procedure SetValue(const AValue: Variant); override; {$ENDIF} public property Values: TStringList read FValues; constructor CreateEx(const AShort: Char; const ALong: String; const AShortCaseSensitive, ALongCaseSensitive: Boolean); override; destructor Destroy; override; end; { @abstract(pathlist option) accepts multiple strings paths and collates them even if the option itself is specified more than one time. Paths in a single option can be separated by the DirectorySeparator } TPathListOption = class(TStringOptionList) function CheckValue(const AString: String): Boolean; override; end; { @abstract(useful for making a choice of things) Values must not have a + or - sign as the last character as that can be used to add/remove items from the default set, specifying items without +/- at the end clears the default and uses only specified items } TSetOption = class(TValueOption) protected FPossibleValues, FValues: TStringList; function GetPossibleValues: string; procedure SetPossibleValues(const Value: string); function CheckValue(const AString: String): Boolean; override; {$IFDEF USE_VARIANTS} function GetValue: Variant; override; procedure SetValue(const AValue: Variant); override; {$ENDIF} function GetValues: string; procedure SetValues(const Value: string); public property PossibleValues: string read GetPossibleValues write SetPossibleValues; constructor CreateEx(const AShort: Char; const ALong: String; const AShortCaseSensitive, ALongCaseSensitive: Boolean); override; destructor Destroy; override; function HasValue(const AValue: string): boolean; property Values: string read GetValues write SetValues; end; { @abstract(OptionParser --- instantiate one of these for commandline parsing) This class is the main parsing class, although a lot of parsing is handled by @link(TOption) and its descendants instead. } TOptionParser = class protected FParams: TStringList; FOptions: TList; FLeftList: TStringList; FShortOptionChar: Char; FLongOptionString: string; function GetOption(const AIndex: Integer): TOption; function GetOptionsCount: Integer; function GetOptionByLongName(const AName: string): TOption; function GetOptionByShortname(const AName: char): TOption; public { Create without any options --- this will parse the current command line } constructor Create; virtual; { Create with parameters to be used instead of command line } constructor CreateParams(const AParams: TStrings); virtual; { destroy the option parser object and all associated @link(TOption) objects } destructor Destroy; override; { Add a @link(TOption) descendant to be included in parsing the command line } function AddOption(const AOption: TOption): TOption; { Parse the specified command line, see also @link(Create) } procedure ParseOptions; { output explanations for all options to stdout, will nicely format the output and wrap explanations } procedure WriteExplanations; { This StringList contains all the items from the command line that could not be parsed. Includes options that didn't accept their value and non-options like filenames specified on the command line } property LeftList: TStringList read FLeftList; { The number of option objects that were added to this parser } property OptionsCount: Integer read GetOptionsCount; { retrieve an option by index --- you can use this and @link(OptionsCount) to iterate through the options that this parser owns } property Options[const AIndex: Integer]: TOption read GetOption; { retrieve an option by its long form. Case sensitivity of the options is taken into account! } property ByName[const AName: string]: TOption read GetOptionByLongName; { retrieve an option by its short form. Case sensitivity of the options is taken into account! } property ByShortName[const AName: char]: TOption read GetOptionByShortname; { introductory character to be used for short options } property ShortOptionStart: Char read FShortOptionChar write FShortOptionChar default DefShortOptionChar; { introductory string to be used for long options } property LongOptionStart: String read FLongOptionString write FLongOptionString; end; implementation uses SysUtils; function TryStrToInt(const AString: string; var AValue: Integer): Boolean; var LError: Integer; begin Val(AString, AValue, LError); Result := LError = 0; end; { TOptionParser } constructor TOptionParser.Create; begin CreateParams(nil); end; function TOptionParser.AddOption(const AOption: TOption): TOption; begin FOptions.Add(AOption); Result := AOption; AOption.FParser := Self; end; constructor TOptionParser.CreateParams(const AParams: TStrings); var i: Integer; begin inherited Create; FParams := TStringList.Create; if Assigned(AParams) then begin FParams.Assign(AParams); end else begin for i := 1 to ParamCount do begin FParams.Add(ParamStr(i)); end; end; FLeftList := TStringList.Create; FOptions := TList.Create; FLongOptionString := DefLongOptionString; FShortOptionChar := DefShortOptionChar; end; destructor TOptionParser.Destroy; var i: Integer; begin for i := FOptions.Count-1 downto 0 do begin TOption(FOptions[i]).Free; end; FLeftList.Free; FParams.Free; FOptions.Free; inherited; end; procedure TOptionParser.ParseOptions; var LCopyList: TStringList; i: Integer; LFoundSomething: boolean; begin LCopyList := TStringList.Create; LCopyList.Assign(FParams); FLeftList.Clear; try while LCopyList.Count > 0 do begin LFoundSomething := false; for i := 0 to FOptions.Count-1 do begin if TOption(FOptions[i]).ParseOption(LCopyList) then begin LFoundSomething := true; break; end; end; if not LFoundSomething then begin FLeftList.Add(LCopyList[0]); LCopyList.Delete(0); end; end; finally LCopyList.Free; end; end; function TOptionParser.GetOptionsCount: Integer; begin Result := FOptions.Count; end; function TOptionParser.GetOption(const AIndex: Integer): TOption; begin Result := TOption(FOptions[AIndex]); end; procedure TOptionParser.WriteExplanations; function Max(const A,B: Integer): Integer; begin if A>B then Result := A else Result := B; end; var i: Integer; LMaxWidth: Integer; begin LMaxWidth := 0; for i := 0 to OptionsCount-1 do begin LMaxWidth := Max(LMaxWidth, Options[i].GetOptionWidth); end; for i := 0 to OptionsCount-1 do begin Options[i].WriteExplanation(LMaxWidth); end; end; function TOptionParser.GetOptionByLongName(const AName: string): TOption; var i: Integer; begin Result := nil; for i := GetOptionsCount-1 downto 0 do begin if (Options[i].LongForm = AName) OR (Options[i].LongCaseSensitive AND (LowerCase(Options[i].LongForm) = LowerCase(AName))) then begin Result := Options[i]; break; end; end; end; function TOptionParser.GetOptionByShortname(const AName: char): TOption; var i: Integer; begin Result := nil; for i := GetOptionsCount-1 downto 0 do begin if (Options[i].ShortForm = AName) OR (Options[i].LongCaseSensitive AND (LowerCase(Options[i].ShortForm) = LowerCase(AName))) then begin Result := Options[i]; break; end; end; end; { TOption } constructor TOption.CreateEx(const AShort: char; const ALong: string; const AShortCaseSensitive, ALongCaseSensitive: boolean); begin inherited Create; FShort := AShort; FLong := ALong; FShortSens := AShortCaseSensitive; FLongSens := ALongCaseSensitive; end; constructor TOption.Create(const AShort: char; const ALong: string); begin CreateEx(AShort, ALong, True, False); end; function TOption.GetOptionWidth: Integer; begin Result := 0; if ShortForm<>#0 then begin Inc(Result, 4); // "-x, " end; if Length(LongForm)>0 then begin Inc(Result, Length(LongForm)+Length(FParser.LongOptionStart)); end else begin Dec(Result, 2); end; end; procedure TOption.WriteExplanation(const AOptWidth: Integer); procedure WriteBlank(const ANumber: Integer); var j: Integer; begin for j := ANumber-1 downto 0 do begin Write(' '); end; end; var LLines: TStringList; i: Integer; LWritten: Integer; begin Write(' '); LWritten := 2; if ShortForm <> #0 then begin Write(FParser.ShortOptionStart, ShortForm); Inc(LWritten, 2); if Length(LongForm)>0 then begin Write(', '); Inc(LWritten, 2); end; end; if Length(LongForm)>0 then begin Write(FParser.LongOptionStart, LongForm); Inc(LWritten, Length(FParser.LongOptionStart) + Length(LongForm)); end; Write(' '); Inc(LWritten, 1); LLines := TStringList.Create; LLines.Text := WrapText(Explanation, 77 - AOptWidth); for i := 0 to LLines.Count-1 do begin if Length(LLines[i]) > 0 then begin // WrapText has a bug... if i = 0 then begin WriteBlank(AOptWidth + 4 - LWritten); end else begin WriteBlank(AOptWidth + 4); end; WriteLn(LLines[i]); end; end; LLines.Free; end; { TBoolOption } {$IFDEF USE_VARIANTS} function TBoolOption.GetValue: Variant; begin Result := WasSpecified; end; {$ENDIF} function TBoolOption.ParseOption(const AWords: TStrings): boolean; begin Result := False; if ShortForm <> #0 then begin if AWords[0] = FParser.ShortOptionStart+ShortForm then begin Result := True; AWords.Delete(0); FWasSpecified := True; end else begin if (not ShortCaseSensitive) and (LowerCase(AWords[0]) = FParser.ShortOptionStart+LowerCase(ShortForm)) then begin Result := True; AWords.Delete(0); FWasSpecified := True; end; end; end; if (not Result) and (Length(LongForm) > 0) then begin if AWords[0] = FParser.LongOptionStart+LongForm then begin Result := True; AWords.Delete(0); FWasSpecified := True; end else begin if (not LongCaseSensitive) and (LowerCase(AWords[0]) = FParser.LongOptionStart+LowerCase(LongForm)) then begin Result := True; AWords.Delete(0); FWasSpecified := True; end; end; end; end; {$IFDEF USE_VARIANTS} procedure TBoolOption.SetValue(const AValue: Variant); begin // do nothing, this option can either be specified or not end; {$ENDIF} { TValueOption } function TValueOption.ParseOption(const AWords: TStrings): boolean; var LValue: string; begin Result := False; if ShortForm <> #0 then begin if (Copy(AWords[0],1,Length(FParser.ShortOptionStart+ShortForm)) = FParser.ShortOptionStart+ShortForm) OR ((not ShortCaseSensitive) and (LowerCase(Copy(AWords[0],1,Length(FParser.ShortOptionStart+ShortForm))) = FParser.ShortOptionStart+LowerCase(ShortForm))) then begin LValue := Copy(AWords[0], Length(FParser.ShortOptionStart+ShortForm)+1, MaxInt); if LValue = '' then begin if AWords.Count>1 then begin LValue := AWords[1]; if CheckValue(LValue) then begin Result := True; AWords.Delete(0); AWords.Delete(0); end else begin Result := CheckValue(''); if Result then AWords.Delete(0); end; end else begin Result := CheckValue(LValue); if Result then AWords.Delete(0); end; end else begin Result := CheckValue(LValue); if Result then AWords.Delete(0); end; end; end; if Result then FWasSpecified := True; if (not Result) and (Length(LongForm) > 0) then begin if (Copy(AWords[0],1,Length(FParser.LongOptionStart+LongForm)) = FParser.LongOptionStart+LongForm) OR ((not LongCaseSensitive) AND (LowerCase(Copy(AWords[0],1,Length(FParser.LongOptionStart+LongForm))) = FParser.LongOptionStart+LowerCase(LongForm))) then begin if Length(AWords[0]) = Length(FParser.LongOptionStart+LongForm) then begin if AWords.Count>1 then begin LValue := AWords[1]; end else begin LValue := ''; end; Result := CheckValue(LValue); if Result then begin AWords.Delete(0); if AWords.Count>0 then AWords.Delete(0); end; end else begin if Copy(AWords[0], Length(FParser.LongOptionStart+LongForm)+1, 1) = '=' then begin LValue := Copy(AWords[0], Length(FParser.LongOptionStart+LongForm)+2, MaxInt); Result := CheckValue(LValue); if Result then AWords.Delete(0); end; end; end; end; if Result then FWasSpecified := True; end; { TIntegerOption } function TIntegerOption.CheckValue(const AString: String): boolean; var LValue: Integer; begin Result := TryStrToInt(AString, LValue); if Result then FValue := LValue; end; {$IFDEF USE_VARIANTS} function TIntegerOption.GetValue: Variant; begin Result := FValue; end; {$ENDIF} {$IFDEF USE_VARIANTS} procedure TIntegerOption.SetValue(const AValue: Variant); begin FValue := AValue; end; {$ENDIF} { TStringOption } function TStringOption.CheckValue(const AString: String): boolean; begin FValue := AString; Result := True; end; {$IFDEF USE_VARIANTS} function TStringOption.GetValue: Variant; begin Result := FValue; end; procedure TStringOption.SetValue(const AValue: Variant); begin FValue := AValue; end; {$ENDIF} { TStringOptionList } function TStringOptionList.CheckValue(const AString: String): Boolean; begin Result := True; FValues.Add(AString); end; constructor TStringOptionList.CreateEx(const AShort: Char; const ALong: String; const AShortCaseSensitive, ALongCaseSensitive: Boolean); begin inherited; FValues := TStringList.Create; end; destructor TStringOptionList.Destroy; begin FValues.Free; inherited; end; {$IFDEF USE_VARIANTS} function TStringOptionList.GetValue: Variant; begin Result := FValues.Text; end; procedure TStringOptionList.SetValue(const AValue: Variant); begin FValues.Text := AValue; end; {$ENDIF} { TSetOption } function TSetOption.CheckValue(const AString: String): Boolean; var LList, LResult: TStringList; i: Integer; s: string; si: Integer; LCleared: boolean; begin Result := True; LCleared := false; LList := TStringList.Create; LResult := TStringList.Create; try LList.Duplicates := dupIgnore; LList.CommaText := AString; LList.Sorted := True; LResult.Assign(FValues); // default values LResult.Duplicates := dupIgnore; LResult.Sorted := True; i := 0; while i < LList.Count do begin s := LList[i]; if Length(s) = 0 then continue; case s[length(s)] of '-': begin SetLength(s, Length(s)-1); if FPossibleValues.IndexOf(s) >= 0 then begin si := LResult.IndexOf(s); if si>=0 then begin LResult.Delete(si); end; end else begin Result := false; break; end; end; '+': begin SetLength(s, Length(s)-1); if FPossibleValues.IndexOf(s) >= 0 then begin LResult.Add(s); end else begin Result := false; break; end; end; else begin if FPossibleValues.IndexOf(s) >= 0 then begin LResult.Add(s); end else begin Result := false; break; end; if not LCleared then begin LCleared := True; LResult.Clear; i := -1; // restart from beginning end; end; end; Inc(i); end; finally LList.Free; FValues.Assign(LResult); LResult.Free; end; end; constructor TSetOption.CreateEx(const AShort: Char; const ALong: String; const AShortCaseSensitive, ALongCaseSensitive: Boolean); begin inherited; FPossibleValues := TStringList.Create; FPossibleValues.Duplicates := dupIgnore; FPossibleValues.Sorted := True; FValues := TStringList.Create; FValues.Duplicates := dupIgnore; FValues.Sorted := True; end; destructor TSetOption.Destroy; begin FPossibleValues.Free; FValues.Free; inherited; end; function TSetOption.GetPossibleValues: string; begin Result := FPossibleValues.CommaText; end; {$IFDEF USE_VARIANTS} function TSetOption.GetValue: Variant; begin Result := FValues.CommaText; end; {$ENDIF} function TSetOption.GetValues: string; begin Result := FValues.CommaText; end; function TSetOption.HasValue(const AValue: string): boolean; begin Result := FValues.IndexOf(AValue)>=0; end; procedure TSetOption.SetPossibleValues(const Value: string); begin FPossibleValues.CommaText := Value; end; {$IFDEF USE_VARIANTS} procedure TSetOption.SetValue(const AValue: Variant); begin FValues.CommaText := AValue; end; {$ENDIF} procedure TSetOption.SetValues(const Value: string); begin FValues.CommaText := Value; end; { TPathListOption } {$IFNDEF DELPHI_6_UP} {$IFDEF FPC} const sLineBreak = LineEnding; PathSep = PathSeparator; {$ELSE} {$IFNDEF KYLIX} const sLineBreak = #13#10; PathSep = ';'; {$ENDIF} {$ENDIF} {$ENDIF} function TPathListOption.CheckValue(const AString: String): Boolean; var LValues: TStringList; begin Result := true; LValues := TStringList.Create; LValues.Text := StringReplace(AString, PathSep, sLineBreak, [rfReplaceAll]); FValues.AddStrings(LValues); LValues.Free; end; end. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Types.pas������������������������������������������������������������0000600�0001750�0001750�00000012235�13237143042�021031� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @author(Johannes Berg <johannes@sipsolutions.de>) @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>) @abstract(Basic types.) } unit PasDoc_Types; {$I pasdoc_defines.inc} interface uses SysUtils; type {$IFNDEF COMPILER_11_UP} TBytes = array of Byte; {$ENDIF} {$IFNDEF COMPILER_12_UP} UnicodeString = WideString; RawByteString = AnsiString; {$ENDIF} { } TPasDocMessageType = (pmtPlainText, pmtInformation, pmtWarning, pmtError); { } TPasDocMessageEvent = procedure(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal) of object; TCharSet = set of AnsiChar; { } EPasDoc = class(Exception) public constructor Create(const AMessage: string; const AArguments: array of const; const AExitCode: Word); end; { This represents parts of a qualified name of some item. User supplies such name by separating each part with dot, e.g. 'UnitName.ClassName.ProcedureName', then @link(SplitNameParts) converts it to TNameParts like ['UnitName', 'ClassName', 'ProcedureName']. Length must be @italic(always) between 1 and @link(MaxNameParts). } TNameParts = array of string; const MaxNameParts = 3; { Windows Unicode code page ID } CP_UTF16 = 1200; CP_UTF16Be = 1201; CP_UTF32 = 12000; CP_UTF32Be = 12001; {$IFNDEF FPC} {$IFDEF MSWINDOWS} LineEnding = #13#10; {$ENDIF} {$ENDIF} { Splits S, which can be made of up to three parts, separated by dots. If S is not a valid identifier or if it has more than three parts, false is returned, otherwise true is returned and splitted name is returned as NameParts. } function SplitNameParts(S: string; out NameParts: TNameParts): Boolean; { Simply returns an array with Length = 1 and one item = S. } function OneNamePart(S: string): TNameParts; { Simply concatenates all NameParts with dot. } function GlueNameParts(const NameParts: TNameParts): string; type { See command-line option @--implicit-visibility documentation at [https://github.com/pasdoc/pasdoc/wiki/ImplicitVisibilityOption] } TImplicitVisibility = (ivPublic, ivPublished, ivImplicit); implementation { EPasDoc -------------------------------------------------------------------- } constructor EPasDoc.Create(const AMessage: string; const AArguments: array of const; const AExitCode: Word); begin ExitCode := AExitCode; CreateFmt(AMessage, AArguments); end; { global routines ------------------------------------------------------------ } function SplitNameParts(S: string; out NameParts: TNameParts): Boolean; const { set of characters, including all letters and the underscore } IdentifierStart : TCharSet = ['A'..'Z', 'a'..'z', '_']; { set of characters, including all characters from @link(IdentifierStart) plus the ten decimal digits } IdentifierOther : TCharSet = ['A'..'Z', 'a'..'z', '_', '0'..'9', '.']; procedure SplitInTwo(s: string; var S1, S2: string); var i: Integer; begin i := Pos('.', s); if (i = 0) then begin S1 := s; S2 := ''; end else begin S1 := System.Copy(s, 1, i - 1); S2 := System.Copy(s, i + 1, Length(s)); end; end; var i: Integer; t: string; begin Result := False; SetLength(NameParts, 3); S := Trim(S); { Check that S starts with IdentifierStart and then only IdentifierOther chars follow } if S = '' then Exit; {$IFNDEF COMPILER_12_UP} if (not (s[1] in IdentifierStart)) then Exit; {$ELSE} if not CharInSet(s[1], IdentifierStart) then Exit; {$ENDIF} i := 2; while (i <= Length(s)) do begin {$IFNDEF COMPILER_12_UP} if (not (s[i] in IdentifierOther)) then Exit; {$ELSE} if not CharInSet(s[i], IdentifierOther) then Exit; {$ENDIF} Inc(i); end; SplitInTwo(S, NameParts[0], NameParts[1]); if NameParts[1] = '' then begin SetLength(NameParts, 1); end else begin t := NameParts[1]; SplitInTwo(t, NameParts[1], NameParts[2]); if NameParts[2] = '' then SetLength(NameParts, 2) else SetLength(NameParts, 3); end; Result := True; end; function OneNamePart(S: string): TNameParts; begin SetLength(Result, 1); Result[0] := S; end; function GlueNameParts(const NameParts: TNameParts): string; var i: Integer; begin Result := NameParts[0]; for i := 1 to Length(NameParts) - 1 do Result := Result + '.' + NameParts[i]; end; end. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/cssfiles/�������������������������������������������������������������������0000700�0001750�0001750�00000000000�13237143042�017575� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/cssfiles/ThomasMueller.css��������������������������������������������������0000600�0001750�0001750�00000007074�13237143042�023102� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������body { font-family: Verdana,Arial; color: black; background-color: white; font-size: 12px; } body.navigationframe { font-family: Verdana,Arial; color: black; background-color: white; font-size: 12px; } img { border:0px; } body.navigationframe h2 { background:darkblue; color:white; text-align:center; padding:0; } h1 { border-color:black; border-top-style:solid; border-left-style:solid; color:darkblue; font-weight:normal; padding-left:4px; } h2 { font-weight:normal; } h3 { font-weight:bold; color:darkblue; } a { color:darkblue; text-decoration: none; border-bottom:dashed 1px; } ul.useslist { list-style-type:none; margin-left:10px; } ul.hierarchy { list-style-type:none; margin-left:10px; } ul.hierarchylevel { list-style-type:none; margin-left:20px; } ul.authors{ list-style-type:none; margin-left:10px; } p.unitlink { padding-left:10px; } p.declaration { padding-left:10px; color:darkblue; } table { border-spacing:2px; padding:4px; width:100%; } table.markerlegend { width:auto; } table.markerlegend td.legendmarker { text-align:center; } table.sections { border-collapse: collapse; background:white; width:auto; } table.sections tr { border-left: hidden; } table.sections td { border-left: solid 1px darkgray; } table.summary { border-collapse:collapse; border-top:double gray; border-bottom:double gray; } table.summary tr { background:transparent; padding:5px; border-top:solid 1px gray; } table.summary b { font-weight:normal; } table.summary td { border:none; } table.summary td.itemcode { width:100%; } table.detail td.itemcode { width:100%; } table.detail { border-collapse:collapse; border-top:solid 2px black; border-left:solid 2px black; } table.detail tr { background:transparent; font-weight:normal; color:black; } table.detail b { font-weight:normal; color:darkblue; } table.detail td.visibility img { display:none; } table.unitstable { border-collapse:collapse; border-top:double black; border-bottom:double black; } table.unitstable tr { background:transparent; border-top:solid 1px gray; } table.unitstable tr.listheader { color:darkblue; text-align:left; border-top:double black; border-bottom:double black; } table.classestable { border-collapse:collapse; border-top:double black; border-bottom:double black; } table.classestable tr { background:transparent; border-top:solid 1px gray; } table.classestable tr.listheader { color:darkblue; text-align:left; border-top:double black; border-bottom:double black; } table.itemstable { border-collapse:collapse; border-top:double black; border-bottom:double black; } table.itemstable tr { background:transparent; border-top:solid 1px gray; } table.itemstable tr.listheader { color:darkblue; text-align:left; border-top:double black; border-bottom:double black; } td { vertical-align:top; padding:4px; } td.itemname {white-space:nowrap; } td.itemunit {white-space:nowrap; } td.itemdesc { width:100%; } td.visibility a { border:none; } div.nodescription {color:red;} dl.parameters {;} dl.parameters dt {color:blue;} dl.parameters dd {;} /* Style applied to Pascal code in documentation (e.g. produced by @longcode tag) } */ span.pascal_string { color: #000080; } span.pascal_keyword { font-weight: bolder; } span.pascal_comment { color: #000080; font-style: italic; } span.pascal_compiler_comment { color: #008000; } p.hint_directive { color: red; } input#search_text { } input#search_submit_button { } acronym.mispelling { background-color: #ffa; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/�����������������������������������������������������������������������0000700�0001750�0001750�00000000000�13237143042�016703� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Bulgarian_utf8_bom.inc��������������������������������0000644�0001750�0001750�00000012775�13237143042�026352� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Bulgarian', //map {trUnits} 'Модули', {trClassHierarchy} 'Йерархия на класовете', {trCio} 'Класове, интерфейси и обекти', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Идентификатори', {trGvUses} 'Зависимости на модулите', {trGvClasses} 'Зависимости на класовете', //tables and members {trClasses} 'Класове', {trClass} 'Клас', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Интерфейс', {trObjects} 'Обекти', {trObject} 'Обект', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Йерархия', {trFields} 'Полета на класа', {trMethods} 'Методи на класа', {trProperties} 'Свойства на класа', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Програма', {trUnit} 'Модул', {trUses} 'Използвани модули', {trConstants} 'Константи', {trFunctionsAndProcedures} 'Процедури и функции', {trTypes} 'Типове', {trType} 'Тип', {trVariables} 'Променливи', {trAuthors} 'Автори', {trAuthor} 'Автор', {trCreated} 'Създадено', {trLastModified} 'Последна промяна', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Параметри', {trReturns} 'Резултат', {trExceptionsRaised} 'Изключения', {trExceptions} 'Изключения', {trException} strToDo, //'Exception', {trEnum} 'Изброим тип', //visibilities {trVisibility} 'Видимост', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'Този идентификатор е изваден от употреба! Моля, потърсете алтернатива', {trPlatformSpecific} 'Този идентификатор е платформено зависим', {trLibrarySpecific} 'Този идентификатор зависи от специфични библиотеки', {trExperimental} 'Този идентификатор е експериментален. Използвайте го внимателно', (* {trUnimplemented} 'Тази процедура/функция все още не е реализирана', *) //headings {trOverview} 'Съдържание', {trIntroduction} 'Въведение', {trConclusion} 'Заключение', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Всички класове, интерфейси и обекти', {trHeadlineConstants} 'Всички константи', {trHeadlineFunctionsAndProcedures} 'Всички процедури и функции', {trHeadlineIdentifiers} 'Всички идентификатори', {trHeadlineTypes} 'Всички типове', {trHeadlineUnits} 'Всички модули', {trHeadlineVariables} 'Всички променливи', {trSummaryCio} 'Списък на класовете, интерфейсите и обектите', //column headings {trDeclaration} 'Декларации', {trDescription} 'Описание', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Име', {trValues} 'Стойност(и)', //empty {trNone} 'Няма', {trNoCIOs} 'Модулите не съдържат класове, интерфейси, обекти и записи', {trNoCIOsForHierarchy} 'Модулите не съдържат класове, интерфейси и обекти', {trNoTypes} 'Модулите не съдържат типове', {trNoVariables} 'Модулите не съдържат променливи', {trNoConstants} 'Модулите не съдържат константи', {trNoFunctions} 'Модулите не съдържат функции и процедури', {trNoIdentifiers} 'Модулите не съдържат идентификатори', //misc {trHelp} strKeep, //'Help', // Untranslated to avoid Russian file name for css { TODO : how does "Help" interfere with file names? } {trLegend} 'Обозначения', {trMarker} 'Маркер', {trWarningOverwrite} 'Предупреждение: Не редактирайте този файл - той е автоматично създаден и може да бъде променен без предупреждение', {trWarning} 'Предупреждение', {trGeneratedBy} 'Документацията е създадена от', // + ' '? {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'на дата', //really??? {trSearch} 'Търсене', {trSeeAlso} 'Виж още', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���pasdoc/source/component/lang/PasDoc_Languages_Chinese_gb2312.inc������������������������������������0000644�0001750�0001750�00000006533�13237143042�025174� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Simplified Chinese (Codepage 936, GB2312) Translation by Liu Da <xmacmail AT gmail.com> } RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Chinese_gb2312', //map {trUnits} 'Ԫ', {trClassHierarchy} '̳', {trCio} 'ࡢӿڡͼ¼', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'ʶ', {trGvUses} 'Ԫϵͼ', {trGvClasses} '̳йϵͼ', //tables and members {trClasses} '', {trClass} '', {trDispInterface} 'Ƚӿ', {trInterface} 'ӿ', {trObjects} '', {trObject} '', {trRecord} '¼', {trPacked} strToDo, //'Packed', {trHierarchy} 'νṹ', {trFields} 'ֶ', {trMethods} '', {trProperties} '', {trLibrary} '', {trPackage} '', {trProgram} '', {trUnit} 'Ԫ', {trUses} '', {trConstants} '', {trFunctionsAndProcedures} '', {trTypes} '', {trType} '', {trVariables} '', {trAuthors} '', {trAuthor} '', {trCreated} '', {trLastModified} '', {trSubroutine} 'ӳ', {trParameters} '', {trReturns} 'ֵ', {trExceptionsRaised} '׳쳣', {trExceptions} '쳣', {trException} '쳣', {trEnum} 'ö', //visibilities {trVisibility} 'ɼ', {trPrivate} '˽', {trStrictPrivate} 'ϸ˽', {trProtected} '', {trStrictProtected} 'ϸ񱣻', {trPublic} '', {trPublished} '', {trAutomated} 'Զ', {trImplicit} 'ʽ', //hints {trDeprecated} 'Dzʹõ', {trPlatformSpecific} 'Žضƽ̨', {trLibrarySpecific} 'ŽضĿ', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} '', {trIntroduction} 'ǰ', {trConclusion} '', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'еࡢӿڡͼ¼', {trHeadlineConstants} 'г', {trHeadlineFunctionsAndProcedures} 'к͹', {trHeadlineIdentifiers} 'бʶ', {trHeadlineTypes} '', {trHeadlineUnits} 'еԪ', {trHeadlineVariables} 'б', {trSummaryCio} 'ࡢӿڡͼ¼ժҪ', //column headings {trDeclaration} '', {trDescription} '', {trDescriptions} '', {trName} '', {trValues} 'ֵ', //empty {trNone} '', {trNoCIOs} 'κࡢӿڡͼ¼ĵԪ.', {trNoCIOsForHierarchy} 'κࡢӿڡĵԪ.', {trNoTypes} 'κ͵ĵԪ.', {trNoVariables} 'καĵԪ.', {trNoConstants} 'κγĵԪ.', {trNoFunctions} 'κκ̵ĵԪ.', {trNoIdentifiers} 'καʶĵԪ.', //misc {trHelp} '', {trLegend} 'ͼ', {trMarker} '', {trWarningOverwrite} '棺Ҫ༭ļ - һԶɵļܱܿǵ', {trWarning} '', {trGeneratedBy} '', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} '', {trSearch} '', {trSeeAlso} 'μ', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Catalan_1252.inc��������������������������������������0000644�0001750�0001750�00000007703�13237143042�024652� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Catalan', //map {trUnits} 'Unitats', {trClassHierarchy} 'Jerarquia de classes', {trCio} 'Classes, interfcies i objectes', {trInternalCR} 'Registres i classes internes', {trInternalTypes} 'Tipus interns', {trIdentifiers} 'Identificadors', {trGvUses} 'Grfic de la dependncia d''unitats', {trGvClasses} 'Grfic de la jerarquia de classes', //tables and members {trClasses} 'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfcie', {trObjects} 'Objectes', {trObject} 'Objecte', {trRecord} 'Registre', {trPacked} strToDo, //'Packed', {trHierarchy} 'Jerarquia', {trFields} 'Camps', {trMethods} 'Mtodes', {trProperties} 'Propietats', {trLibrary} 'Biblioteca', {trPackage} 'Paquet', {trProgram} 'Programa', {trUnit} 'Unitat', {trUses} strToDo, //'Uses', {trConstants} 'Constants', {trFunctionsAndProcedures} 'Funcions i procediments', {trTypes} 'Tipus', {trType} 'Tipus', {trVariables} 'Variables', {trAuthors} 'Autors', {trAuthor} 'Autor', {trCreated} 'Creat', {trLastModified} 'ltima modificaci', {trSubroutine} 'Subrutina', {trParameters} 'Parmetres', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} 'Enumeraci', //visibilities {trVisibility} 'Visibilitat', {trPrivate} 'Privada', {trStrictPrivate} 'Estrictament privada', {trProtected} 'Protegida', {trStrictProtected} 'Estrictament protegida', {trPublic} 'Pblica', {trPublished} 'Publicada', {trAutomated} strToDo, //'Automated', {trImplicit} 'Implcita', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Resum', {trIntroduction} 'Introducci', {trConclusion} 'Conclusi', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Totes les classes, interfcies i objectes', {trHeadlineConstants} 'Totes les constants', {trHeadlineFunctionsAndProcedures} 'Totes les funcions i procediments', {trHeadlineIdentifiers} 'Tot els indentificadors', {trHeadlineTypes} 'Tots els tipus', {trHeadlineUnits} 'Totes les unitats', {trHeadlineVariables} 'Totes les variables', {trSummaryCio} 'Llista de classes, interfcies i objectes', //column headings {trDeclaration} 'Declaraci', {trDescription} 'Descripci', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nom', {trValues} 'Valors', //empty {trNone} 'Cap', {trNoCIOs} 'Les unitats no contenen cap classe, interfcie, objecte ni registre.', {trNoCIOsForHierarchy} 'Les unitats no contenen cap classe, interfcie ni objecte.', {trNoTypes} 'Les unitats no contenen cap tipus.', {trNoVariables} 'Les unitats no contenen cap variable.', {trNoConstants} 'Les unitats no contenen cap constant.', {trNoFunctions} 'Les unitats no contenen cap funci o procediment.', {trNoIdentifiers} 'Les unitats no contenen cap identificador.', //misc {trHelp} 'Ajuda', {trLegend} 'Llegenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Atenci, no editeu aquest fitxer. Ha estat creat automticament i ser sobrescrit', {trWarning} 'Atenci', {trGeneratedBy} 'Generat per', {trGeneratedOn} 'Generat el', {trOnDateTime} 'el', {trSearch} 'Cerca', {trSeeAlso} 'Veure tamb', {trInternal} 'intern', {trAttributes} 'Atributs', '' //dummy ); �������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Danish_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010571�13237143042�025644� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Danish', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Klasser, interfaces og objekter', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klasser', {trClass} 'Klasse', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objekter', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Herarki', {trFields} 'Felter', {trMethods} 'Metoder', {trProperties} 'Egenskaber', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanter', {trFunctionsAndProcedures} 'Funktioner og prosedurer', {trTypes} 'Typer', {trType} strToDo, //'Type', {trVariables} 'Variable', {trAuthors} 'Forfatre', {trAuthor} 'Forfatter', {trCreated} 'Udført', {trLastModified} 'Sidst Modificieret', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sammendrag', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alle Klasesr, Interfaces og Objekter', {trHeadlineConstants} 'Alle Konstanter', {trHeadlineFunctionsAndProcedures} 'Alle Functioner and Procedurer', {trHeadlineIdentifiers} 'Alle Identifiers', {trHeadlineTypes} 'Alle Typer', {trHeadlineUnits} 'Alle Units', {trHeadlineVariables} 'Alle Variable', {trSummaryCio} 'Oversigt over klasser, interfaces & objekter', //column headings {trDeclaration} strToDo, //'Declaration', {trDescription} 'Beskrivelse', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Navn', {trValues} strToDo, //'Values', //empty {trNone} 'Ingen', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Hjælp', {trLegend} 'Legende', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Advarsel: Editer ikke denne fil, den er autogeneret og vil sansylgvis blive overskret', {trWarning} strToDo, //'Warning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_German_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010223�13237143042�025641� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<häh?>', //no ID assigned, so far {trLanguage} 'German', //map {trUnits} strKeep, //'Units', {trClassHierarchy} 'Klassenhierarchie', {trCio} 'Klassen, Interfaces und Objekte', {trInternalCR} 'Interne Klassen and Records', {trInternalTypes} 'Interne Typen', {trIdentifiers} 'Bezeichner', {trGvUses} 'Graph der Unit-Abhängigkeiten', {trGvClasses} 'Graph der Klassenhierarchie', //tables and members {trClasses} 'Klassen', {trClass} 'Klasse', {trDispInterface} strKeep, //'DispInterface', {trInterface} strKeep, //'Interface', 'Schnittstelle'? {trObjects} strKeep, //'Objects', {trObject} strKeep, //'Object', {trRecord} strKeep, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Felder', {trMethods} 'Methoden', {trProperties} 'Eigenschaften', {trLibrary} 'Bibliothek', {trPackage} strKeep, //'Package', {trProgram} 'Programm', {trUnit} strKeep, //'Unit', {trUses} strKeep, //'Uses', {trConstants} 'Konstanten', {trFunctionsAndProcedures} 'Funktionen und Prozeduren', {trTypes} 'Datentypen', {trType} strKeep, //'Type', 'Typ'? {trVariables} 'Variablen', {trAuthors} 'Autoren', {trAuthor} 'Autor', {trCreated} 'Erstellt', {trLastModified} 'Letzte Änderung', {trSubroutine} 'Unterprogramm', {trParameters} 'Parameter', {trReturns} 'Result', {trExceptionsRaised} 'Wirft Ausnahmen', //'Exceptions raised', {trExceptions} 'Ausnahmen', {trException} strKeep, //'Exception', {trEnum} strKeep, //'Enumeration', //visibilities {trVisibility} 'Sichtbarkeit', {trPrivate} strKeep, //'Private', {trStrictPrivate} strKeep, //'Strict Private', {trProtected} strKeep, //'Protected', {trStrictProtected} strKeep, //'Strict Protected', {trPublic} strKeep, //'Public', {trPublished} strKeep, //'Published', {trAutomated} strKeep, //'Automated', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'Dieses Symbol sollte nicht (mehr) verwendet werden.', {trPlatformSpecific} 'Dieses Symbol ist plattformspezifisch.', {trLibrarySpecific} 'Dieses Symbol ist spezifisch für eine bestimmte Bibliothek.', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Übersicht', {trIntroduction} 'Einführung', {trConclusion} 'Fazit', {trEnclosingClass} 'Einschließende Klasse', {trHeadlineCio} 'Alle Klassen, Schnittstellen, Objekte und Records', {trHeadlineConstants} 'Alle Konstanten', {trHeadlineFunctionsAndProcedures} 'Alle Funktionen und Prozeduren', {trHeadlineIdentifiers} 'Alle Bezeichner', {trHeadlineTypes} 'Alle Typen', {trHeadlineUnits} 'Alle Units', {trHeadlineVariables} 'Alle Variablen', {trSummaryCio} 'Zusammenfassung aller Klassen, Schnittstellen, Objekte und Records', //column headings {trDeclaration} 'Deklaration', {trDescription} 'Beschreibung', {trDescriptions} 'Ausführliche Beschreibungen', {trName} strKeep, //'Name', {trValues} 'Werte', //empty {trNone} 'Keine', {trNoCIOs} 'Die Units enthalten keine Klassen, Interfaces, Objects oder Records.', {trNoCIOsForHierarchy} 'Die Units enthalten keine Klassen, Interfaces oder Objects.', {trNoTypes} 'Die Units enthalten keine Typen.', {trNoVariables} 'Die Units enthalten keine Variablen.', {trNoConstants} 'Die Units enthalten keine Konstanten.', {trNoFunctions} 'Die Units enthalten keine Funktionen oder Prozeduren.', {trNoIdentifiers} 'Die Units enthalten keine Bezeichner.', //misc {trHelp} 'Hilfe', {trLegend} 'Legende', {trMarker} 'Markierung', {trWarningOverwrite} 'Achtung: Nicht ändern - diese Datei wurde automatisch erstellt und wird möglicherweise überschrieben', {trWarning} 'Warnung', {trGeneratedBy} 'Erstellt mit', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'am', {trSearch} 'Suchen', {trSeeAlso} 'Siehe auch', {trInternal} 'intern', {trAttributes} strToDo, //'Attributes', '' //dummy ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Brasilian_utf8_bom.inc��������������������������������0000644�0001750�0001750�00000010563�13237143042�026343� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Brasilian', //map {trUnits} strToDo, //'Units', {trClassHierarchy} 'Hierarquia de Classes', {trCio} 'Classes, Interfaces, Objetos e Registros', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadores', {trGvUses} 'Diagrama de dependências de units', {trGvClasses} 'Diagrama de hierarquia de Classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objetos', {trObject} 'Objeto', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarquia', {trFields} 'Campos', {trMethods} 'Métodos', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Funções e Procedimentos', {trTypes} 'Tipos', {trType} 'Tipo', {trVariables} 'Variáveis', {trAuthors} 'Autores', {trAuthor} 'Autor', {trCreated} 'Criada', {trLastModified} 'Última modificação', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parâmetros', {trReturns} 'Retornos', //??? {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} 'Exceções', {trException} strToDo, //'Exception', {trEnum} 'Enumerações', //??? //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'este símbolo está depreciado', {trPlatformSpecific} 'este símbolo é específico para alguma plataforma', {trLibrarySpecific} 'este símbolo é específico para alguma biblioteca', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Visão Geral', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Todas as Classes, Interfaces, Objetos e Registros', {trHeadlineConstants} 'Todas as Constantes', {trHeadlineFunctionsAndProcedures} 'Todas as funções e procedimentos', {trHeadlineIdentifiers} 'Todos os Identificadores', {trHeadlineTypes} 'Todos os Tipos', {trHeadlineUnits} 'Todas as Units', {trHeadlineVariables} 'Todas as Variáveis', {trSummaryCio} 'Lista das Classes, Interfaces, Objetos e Registros', //column headings {trDeclaration} 'Declaração', {trDescription} 'Descrição', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nome', {trValues} strToDo, //'Values', //empty {trNone} 'Nenhum', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Ajuda', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Aviso, não altere - este arquivo foi gerado automaticamente e será sobrescrito', {trWarning} strToDo, //'Warning', {trGeneratedBy} 'Gerado por', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'as', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Polish_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010111�13237143042�025662� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Polish', //map {trUnits} 'Moduły', {trClassHierarchy} 'Hierarchia klas', {trCio} 'Klasy, interfejsy, obiekty i rekordy', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identyfikatory', {trGvUses} 'Graf zależności modułów', {trGvClasses} 'Graf dziedziczenia klas', //tables and members {trClasses} 'Klasy', {trClass} 'Klasa', {trDispInterface} 'DispInterface', //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Obiekty', {trObject} 'Obiekt', {trRecord} 'Rekord', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Pola', {trMethods} 'Metody', {trProperties} 'Właściwości', {trLibrary} 'Biblioteka', //'Library', {trPackage} 'Pakiet', //'Package', {trProgram} 'Program', //'Program', {trUnit} 'Moduł', {trUses} 'Używa', //'Uses', {trConstants} 'Stałe', {trFunctionsAndProcedures} 'Podprogramy', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Zmienne', {trAuthors} 'Autorzy', {trAuthor} 'Autor', {trCreated} 'Utworzony', {trLastModified} 'Ostatnia modyfikacja', {trSubroutine} 'Podprograma', //? {trParameters} 'Parametry', {trReturns} 'Wynik', {trExceptionsRaised} 'Generowane wyjątki', {trExceptions} 'Wyjątki', {trException} 'Wyjątek', //'Exception', {trEnum} 'Wyliczenie', //visibilities {trVisibility} 'Widoczność', {trPrivate} 'Prywatne', {trStrictPrivate} 'Ściśle prywatne', //'Strict Private', {trProtected} 'Chronione', {trStrictProtected} 'Ściśle chronione', //'Strict Protected', {trPublic} 'Publiczne', {trPublished} 'Publikowane', {trAutomated} 'Automated', //'Automated', {trImplicit} 'Domyślne', //hints {trDeprecated} 'odradza się używania tego identyfikatora', {trPlatformSpecific} 'ten identyfikator jest zależny od platformy', {trLibrarySpecific} 'ten identyfikator jest zależny od biblioteki', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Przegląd', {trIntroduction} 'Wstęp', {trConclusion} 'Podsumowanie', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Wszystkie klasy, interfejsy, obiekty i rekordy', {trHeadlineConstants} 'Wszystkie stałe', {trHeadlineFunctionsAndProcedures} 'Wszystkie podprogramy', {trHeadlineIdentifiers} 'Wszystkie identyfikatory', {trHeadlineTypes} 'Wszystkie typy', {trHeadlineUnits} 'Wszystkie moduły', {trHeadlineVariables} 'Wszystkie zmienne', {trSummaryCio} 'Podsumowanie klas, interfejsów, obiektów i rekordów', //column headings {trDeclaration} 'Deklaracja', {trDescription} 'Opis', {trDescriptions} 'Szczegóły', //'Descriptions', 'Detailed Descriptions'? {trName} 'Nazwa', {trValues} 'Wartości', //empty {trNone} 'Brak', {trNoCIOs} 'Moduł nie zawiera żadnych klas, interfejsów, obiektów ani rekordów.', {trNoCIOsForHierarchy} 'Moduł nie zawiera żadnych klas, interfejsów ani obiektów.', {trNoTypes} 'Moduł nie zawiera żadnych typów.', {trNoVariables} 'Moduł nie zawiera żadnych zmiennych.', {trNoConstants} 'Moduł nie zawiera żadnych stałych.', {trNoFunctions} 'Moduł nie zawiera żadnych funkcji ani podprogramów.', {trNoIdentifiers} 'Moduł nie zawiera żadnych identyfikatorów.', //misc {trHelp} 'Pomoc', {trLegend} 'Legenda', {trMarker} 'Kolor', {trWarningOverwrite} 'Uwaga, nie modyfikuj - ten plik został wygenerowany automatycznie i może zostać nadpisany', {trWarning} 'Uwaga', {trGeneratedBy} 'Wygenerowane przez', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} ' - ', {trSearch} 'Szukaj', {trSeeAlso} 'Zobacz także', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_French_utf8.inc���������������������������������������0000644�0001750�0001750�00000010471�13237143042�025005� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'French', //map {trUnits} 'Unités', {trClassHierarchy} 'Hiérarchie des classes', {trCio} 'Classes, interfaces, enregistrements et objets', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificateurs', {trGvUses} 'Graphe de dépendance d''unités', {trGvClasses} 'Graphe de hiérarchie des classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objets', {trObject} 'Objet', {trRecord} 'Enregistrement', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hiérarchie', {trFields} 'Champs', {trMethods} 'Méthodes', {trProperties} 'Propriétés', {trLibrary} 'Bibliothèque', //? {trPackage} 'Paquet', //'Package', {trProgram} 'Logiciel', //? 'Program', {trUnit} 'Unité', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Fonctions et procédures', {trTypes} strKeep, //'Types', {trType} strKeep, //'Type', {trVariables} strKeep, //'Variables', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Crée', {trLastModified} 'Dernière modification', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paramètres', {trReturns} 'Retourne', {trExceptionsRaised} 'Exception levées', //'Exceptions raised', {trExceptions} strKeep, //'Exceptions', {trException} strKeep, //'Exception', {trEnum} 'Énumération', //'Enumeration', //visibilities {trVisibility} 'Visibilité', {trPrivate} 'Privé', {trStrictPrivate} 'Strictement Privé', //? {trProtected} 'Protégé', {trStrictProtected} 'Strictement Protégé', //? {trPublic} strKeep, //'Public', {trPublished} 'Publiés', {trAutomated} 'Automatisé', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'ce symbole est désapprouvé', {trPlatformSpecific} 'ce symbole est spécifique à une plateforme d''exécution', {trLibrarySpecific} 'ce symbole est spécifique à une certaine bibliothèque', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Aperçu', {trIntroduction} strKeep, //'Introduction', {trConclusion} strKeep, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Toutes les classes, interfaces, objets et enregistrements', {trHeadlineConstants} 'Toutes les constantes', {trHeadlineFunctionsAndProcedures} 'Toutes les fonctions et procédures', {trHeadlineIdentifiers} 'Tous les identificateurs', {trHeadlineTypes} 'Tous les types', {trHeadlineUnits} 'Toutes les unités', {trHeadlineVariables} 'Toutes les variables', {trSummaryCio} 'Classes, interfaces, objets et enregistrements', //column headings {trDeclaration} 'Déclaration', {trDescription} strKeep, //'Description', {trDescriptions} strKeep, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nom', {trValues} 'Valeurs', //? //empty {trNone} 'Aucun(e)(s)', //'Rien'? {trNoCIOs} 'L''unité ne contient ni classe, ni interface, ni objets, ni enregistrement.', {trNoCIOsForHierarchy} 'L''unité ne contient ni classe, ni interface, ni objets.', {trNoTypes} 'L''unité ne contient aucun type.', {trNoVariables} 'L''unité ne contient aucune variable.', {trNoConstants} 'L''unité ne contient aucune constante.', {trNoFunctions} 'L''unité ne contient ni fonction ni procédure.', {trNoIdentifiers} 'L''unité ne contient aucun indentificateur.', //misc {trHelp} 'Aide', {trLegend} 'Légende', {trMarker} 'Marquage', {trWarningOverwrite} 'Attention, ne pas éditer - ce fichier est créé automatiquement et va être écrasé', {trWarning} 'Attention', {trGeneratedBy} 'Produit par', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'le', {trSearch} 'Cherche', //? 'Recherche' {trSeeAlso} 'Voir aussi', //? {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Italian_1252.inc��������������������������������������0000644�0001750�0001750�00000010404�13237143042�024660� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Italian', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Classi, Interfacce ed Oggetti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificatori', {trGvUses} 'Grafico dipendenze Unit', {trGvClasses} 'Grafico gerarchia Classi', //tables and members {trClasses} 'Classi', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfacce', {trObjects} 'Oggetti', {trObject} 'Oggetto', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Gerarchia', {trFields} 'Campi', {trMethods} 'Metodi', {trProperties} 'Propriet', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Costanti', {trFunctionsAndProcedures} 'Funzioni e Procedure', {trTypes} 'Tipi', {trType} 'Tipo', {trVariables} 'Variabili', {trAuthors} 'Autori', {trAuthor} 'Autore', {trCreated} 'Creato', {trLastModified} 'Ultima Variazione', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parametri', {trReturns} 'Ritorni', {trExceptionsRaised} 'Eccezioni sollevate', {trExceptions} 'Eccezione', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sommario', {trIntroduction} 'Introduczione', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Tutte le Classi, Interfacce ed Oggetti', {trHeadlineConstants} 'Tutte le Costanti', {trHeadlineFunctionsAndProcedures} 'Tutte le Funzioni e Procedure', {trHeadlineIdentifiers} 'Tutti gli Identificatori', {trHeadlineTypes} 'Tutti i Tipi', {trHeadlineUnits} 'Tutte le Units', {trHeadlineVariables} 'Tutte le Variabili', {trSummaryCio} 'Sommario di Classi, Interfacce ed Oggetti', //column headings {trDeclaration} 'Dichiarazione', {trDescription} 'Descrizione', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nome', {trValues} 'Valori', //empty {trNone} 'Nessuno', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Attenzione: Non modificare - questo file stato generato automaticamente e verr probabilmente sovrascritto', {trWarning} 'Attenzione', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} 'Cerca', {trSeeAlso} 'Vedere Anche', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Slovak_1250.inc���������������������������������������0000644�0001750�0001750�00000010474�13237143042�024543� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Slovak', //map {trUnits} 'Jednotky', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Triedy, interfejsy a objekty', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifiktory', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Triedy', {trClass} 'Trieda', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Objekty', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Poloky', {trMethods} 'Metdy', {trProperties} 'Monosti', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Jednotka', {trUses} strToDo, //'Uses', {trConstants} 'Kontanty', {trFunctionsAndProcedures} 'Funkcie a procedry', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Premenn', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Vytvoren', {trLastModified} 'Posledn zmena', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} strToDo, //'Overview', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Vetky triedy, interfejsy a objekty', {trHeadlineConstants} 'Vetky kontanty', {trHeadlineFunctionsAndProcedures} 'Vetky funkcie a procedry', {trHeadlineIdentifiers} 'Vetky identifiktory', {trHeadlineTypes} 'Vetky typy', {trHeadlineUnits} 'Vetky jednotky', {trHeadlineVariables} 'Vetky premenn', {trSummaryCio} 'Zoznam tried, interfejsov a objektov', //column headings {trDeclaration} 'Deklarcie', {trDescription} 'Popis', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Meno', {trValues} strToDo, //'Values', //empty {trNone} 'Ni', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozornenie: Needitujte - tento sbor bol vytvoren automaticky a je pravdepodobn, e bude prepsan', {trWarning} 'Upozornenie', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Russian_koi8r.inc�������������������������������������0000644�0001750�0001750�00000013115�13237143042�025370� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Russian', //<<<<<< replace with the name of the new language //map {trUnits} '', //'Units', {trClassHierarchy} ' ', //'Class Hierarchy', {trCio} ', ', //'Classes, Interfaces, Objects and Records', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} '', //'Identifiers', {trGvUses} ' ', //'Unit dependency graph', {trGvClasses} ' ', //'Classes hierarchy graph', //tables and members {trClasses} '', //'Classes', {trClass} '', //'Class', {trDispInterface} 'DispInterface', //'DispInterface', {trInterface} '', //'Interface', {trObjects} '', //'Objects', {trObject} '', //'Object', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} '', //'Hierarchy', {trFields} '', //'Fields', {trMethods} '', //'Methods', {trProperties} '', //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} '', //'Program', {trUnit} '', //'Unit', {trUses}' ', //'Uses', {trConstants} '', //'Constants', {trFunctionsAndProcedures} ' ', //'Functions and Procedures', {trTypes} '', //'Types', {trType} '', //'Type', {trVariables} '', //'Variables', {trAuthors} '', //'Authors', {trAuthor} '', //'Author', {trCreated} '', //'Created', {trLastModified} ' ', //'Last Modified', {trSubroutine} strToDo, //'Subroutine', {trParameters} '', //'Parameters', {trReturns} ' ', //'Returns', {trExceptionsRaised} ' ', //'Exceptions raised', {trExceptions} '', //'Exceptions', {trException} strToDo, //'Exception', {trEnum} '', //'Enumeration', //visibilities {trVisibility} ' ', //'Visibility', {trPrivate} 'Private', //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Protected', //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Public', //'Public', {trPublished} 'Published', //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} 'Implicit', //'Implicit', //hints {trDeprecated} ' ', //'this symbol is deprecated', {trPlatformSpecific} ' ', //'this symbol is specific to some platform', {trLibrarySpecific} ' ', //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} '', //'Overview', {trIntroduction} '', //'Introduction', {trConclusion} '', //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} ' , ', //'All Classes, Interfaces, Objects and Records', {trHeadlineConstants} ' ', //'All Constants', {trHeadlineFunctionsAndProcedures} ' ', //'All Functions and Procedures', {trHeadlineIdentifiers} ' ', //'All Identifiers', {trHeadlineTypes} ' ', //'All Types', {trHeadlineUnits} ' ', //'All Units', {trHeadlineVariables} ' ', //'All Variables', {trSummaryCio} ' , ', //'Summary of Classes, Interfaces, Objects and Records', //column headings {trDeclaration} '', //'Declaration', {trDescription} '', //'Description', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} '', //'Name', {trValues} '', //'Values', //empty {trNone} '', //'None', {trNoCIOs} ' , , .', //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} ' , .', //'The units do not contain any classes, interfaces or objects.', {trNoTypes} ' .', //'The units do not contain any types.', {trNoVariables} ' .', //'The units do not contain any variables.', {trNoConstants} ' .', //'The units do not contain any constants.', {trNoFunctions} ' .', //'The units do not contain any functions or procedures.', {trNoIdentifiers} ' .', //'The units do not contain any identifiers.', //misc {trHelp} 'Help', //'Help', {trLegend} '', //'Legend', {trMarker} '', //'Marker', {trWarningOverwrite} ': - Σ ', //'Warning: Do not edit - this file has been created automatically and is likely be overwritten', {trWarning} '', //'Warning', {trGeneratedBy} ' ', //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} '/', //'on', {trSearch} '', //'Search', {trSeeAlso} ' ', //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Russian_utf8.inc��������������������������������������0000644�0001750�0001750�00000012155�13237143042�025225� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Russian', //map {trUnits} 'Модули', {trClassHierarchy} 'Иерархия классов', {trCio} 'Классы, интерфейсы и объекты', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Идентификаторы', {trGvUses} 'График зависимости модулей', {trGvClasses} 'График иерархии классов', //tables and members {trClasses} 'Классы', {trClass} 'Класс', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Интерфейс', {trObjects} 'Объекты', {trObject} 'Объект', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Иерархия', {trFields} 'Поля', {trMethods} 'Методы', {trProperties} 'Свойства', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Программа', {trUnit} 'Модуль', {trUses} 'Используемые модули', {trConstants} 'Константы', {trFunctionsAndProcedures} 'Процедуры и функции', {trTypes} 'Типы', {trType} 'Тип', {trVariables} 'Переменные', {trAuthors} 'Авторы', {trAuthor} 'Автор', {trCreated} 'Создано', {trLastModified} 'Последнее изменение', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Параметры', {trReturns} 'Возвращаемые значения', {trExceptionsRaised} 'Вызывает исключения', {trExceptions} 'Исключения', {trException} strToDo, //'Exception', {trEnum} 'Перечисление', //visibilities {trVisibility} 'Зона видимости', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'этот символ больше не используется', {trPlatformSpecific} 'этот символ зависит от платформы', {trLibrarySpecific} 'этот символ зависит от библиотеки', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Обзор', {trIntroduction} 'Введение', {trConclusion} 'Заключение', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Все классы, интерфейсы и объекты', {trHeadlineConstants} 'Все константы', {trHeadlineFunctionsAndProcedures} 'Все процедуры и функции', {trHeadlineIdentifiers} 'Все идентификаторы', {trHeadlineTypes} 'Все типы', {trHeadlineUnits} 'Все модули', {trHeadlineVariables} 'Все переменные', {trSummaryCio} 'Список классов, интерфейсов и объектов', //column headings {trDeclaration} 'Объявления', {trDescription} 'Описание', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Имя', {trValues} 'Значение', //empty {trNone} 'Нет', {trNoCIOs} 'Модули не содержат классов, интерфейсов, объектов и записей.', {trNoCIOsForHierarchy} 'Модули не содержат классов, интерфейсов и объектов.', {trNoTypes} 'Модули не содержат типов.', {trNoVariables} 'Модули не содержат переменных.', {trNoConstants} 'Модули не содержат констант.', {trNoFunctions} 'Модули не содержат функции и процедуры.', {trNoIdentifiers} 'Модули не содержат ни одного идентификатора.', //misc {trHelp} strKeep, //'Help', // Untranslated to avoid Russian file name for css { TODO : how does "Help" interfere with file names? } {trLegend} 'Обозначения', {trMarker} 'Маркер', {trWarningOverwrite} 'Предупреждение: не редактировать - этот файл создан автоматически и может быть изменён без предупреждения', {trWarning} 'Предупреждение', {trGeneratedBy} 'Сгенерировал', // + ' '? {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'дата/время', //really??? {trSearch} 'Найти', {trSeeAlso} 'Материалы по теме', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Javanese_utf8_bom.inc���������������������������������0000644�0001750�0001750�00000010550�13237143042�026167� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Javanese', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Kelas, Interface, lan Objek', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Kelas', {trClass} 'Kelas', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objek', {trObject} 'Objek', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarki', {trFields} strToDo, //'Fields', {trMethods} strToDo, //'Methods', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanta', {trFunctionsAndProcedures} 'Fungsi lan Prosedur', {trTypes} 'Macem Gawean', {trType} 'Macem Gawean', {trVariables} 'Variabel', {trAuthors} 'Sing Nggawe', {trAuthor} 'Sing Nggawe', {trCreated} 'Digawe', {trLastModified} 'Terakhir Diowahi', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pambuka', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Kabeh Kelas, Interface, lan Objek', {trHeadlineConstants} 'Kabeh Konstanta', {trHeadlineFunctionsAndProcedures} 'Kabeh Fungsi lan Prosedur', {trHeadlineIdentifiers} 'Kabeh Identifier', {trHeadlineTypes} 'Kabeh Macem Gawean', {trHeadlineUnits} 'Kabeh Unit', {trHeadlineVariables} 'Kabeh Variabel', {trSummaryCio} 'Ringkesan Kelas, Interface, lan Objek', //column headings {trDeclaration} 'Deklarasi', {trDescription} 'Katrangan', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Jeneng', {trValues} strToDo, //'Values', //empty {trNone} 'Mboten Wonten', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Tulung', {trLegend} 'Katrangan', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Ati-ati: Ojo diowahi - ' + 'file iki digawe otomatis dadi iso ilang owahanmu', {trWarning} 'Ati-ati', //? {trGeneratedBy} 'Dihasilne karo', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'ing', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Slovak_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010533�13237143042�025673� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Slovak', //map {trUnits} 'Jednotky', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Triedy, interfejsy a objekty', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikátory', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Triedy', {trClass} 'Trieda', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Objekty', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Položky', {trMethods} 'Metódy', {trProperties} 'Možnosti', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Jednotka', {trUses} strToDo, //'Uses', {trConstants} 'Konštanty', {trFunctionsAndProcedures} 'Funkcie a procedúry', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Premenné', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Vytvorené', {trLastModified} 'Posledná zmena', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} strToDo, //'Overview', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Všetky triedy, interfejsy a objekty', {trHeadlineConstants} 'Všetky konštanty', {trHeadlineFunctionsAndProcedures} 'Všetky funkcie a procedúry', {trHeadlineIdentifiers} 'Všetky identifikátory', {trHeadlineTypes} 'Všetky typy', {trHeadlineUnits} 'Všetky jednotky', {trHeadlineVariables} 'Všetky premenné', {trSummaryCio} 'Zoznam tried, interfejsov a objektov', //column headings {trDeclaration} 'Deklarácie', {trDescription} 'Popis', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Meno', {trValues} strToDo, //'Values', //empty {trNone} 'Nič', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozornenie: Needitujte - tento súbor bol vytvorený automaticky a je pravdepodobné, že bude prepísaný', {trWarning} 'Upozornenie', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Hungarian_utf8_bom.inc��������������������������������0000644�0001750�0001750�00000010407�13237143042�026350� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Hungarian', //map {trUnits} 'Egységek', {trClassHierarchy} 'Osztály hierarchia', {trCio} 'Osztályok, Kapcsolódási felületek és Objektumok', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Azonosítók', {trGvUses} 'Egység függőségi gráf', {trGvClasses} 'Osztály hierarchia gráf', //tables and members {trClasses} 'Osztályok', {trClass} 'Osztály', {trDispInterface} 'Képernyő felületek', {trInterface} 'Kapcsolódási felület', {trObjects} 'Objektumok', {trObject} 'Objektum', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Mezők', {trMethods} 'Metódusok', {trProperties} 'Tulajdonságok', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Egység', {trUses} strToDo, //'Uses', {trConstants} 'Konstansok', {trFunctionsAndProcedures} 'Függvények és Eljárások', {trTypes} 'Típusok', {trType} 'Típus', {trVariables} 'Változók', {trAuthors} 'Szerzők', {trAuthor} 'Szerző', {trCreated} 'Készült', {trLastModified} 'Utolsó módosítás', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paraméterek', {trReturns} 'Visszatérési értékek', {trExceptionsRaised} 'Kivételek kiemelése', {trExceptions} 'Kivételek', {trException} strToDo, //'Exception', {trEnum} 'Felsorolások', //visibilities {trVisibility} 'Láthatóság', {trPrivate} 'Privát', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Védett', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Publikus', {trPublished} 'Publikált', {trAutomated} 'Automatikus', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'ez az azonosító érték nélküli', {trPlatformSpecific} 'ez az azonosító szükséges némely platform számára', {trLibrarySpecific} 'ez az azonosító szükséges némely library számára', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Áttekintés', {trIntroduction} 'Bevezető', {trConclusion} 'Összefoglaló', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Összes Osztály, Kapcsolódási felület és Objektumok', {trHeadlineConstants} 'Összes Kontans', {trHeadlineFunctionsAndProcedures} 'Összes Függvény és Eljárás', {trHeadlineIdentifiers} 'Összes Azonosító', {trHeadlineTypes} 'Összes Típus', {trHeadlineUnits} 'Összes Egység', {trHeadlineVariables} 'Összes Változó', {trSummaryCio} 'Öszefoglaló az Osztályokról, Kapcsoldási felületekről és Objektumokról', //column headings {trDeclaration} 'Deklaráció', {trDescription} 'Megjegyzés', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Név', {trValues} 'Értékek', //empty {trNone} 'Nincs', {trNoCIOs} 'Az egység nem tartalmaz osztályt, interfészt, objektumot, vagy rekordot.', {trNoCIOsForHierarchy} 'Az egység nem tartalmaz osztályt, interfészt vagy objektumot.', {trNoTypes} 'Az egység nem tartalmaz típusokat', {trNoVariables} 'Az egység nem tartalmaz változókat.', {trNoConstants} 'Az egység nem tartalmaz konstansokat.', {trNoFunctions} 'Az egység nem tartalmaz függvényeket vagy eljárásokat.', {trNoIdentifiers} 'Az egység nem tartalmaz azonosítókat.', //misc {trHelp} 'Súgó', {trLegend} 'Történet', {trMarker} 'Jelző', {trWarningOverwrite} 'Vigyázat: Nem szerkesztendő file - ez a file automatikusan készült, valószínűleg felülírásra kerülne', {trWarning} 'Vigyázat', {trGeneratedBy} 'Készítette', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} ' ', //none in Hungarian language {trSearch} 'Keresés', {trSeeAlso} 'Lásd még', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Swedish_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000010754�13237143042�026047� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Swedish', //map {trUnits} 'Enheter', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Klasser, interface och objekt', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klasser', {trClass} 'Klass', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objekt', //-er ??? {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarki', {trFields} 'Fält', //-er ??? {trMethods} 'Metoder', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Enhet', {trUses} strToDo, //'Uses', {trConstants} strToDo, //'Constants', {trFunctionsAndProcedures} strToDo, //'Functions and Procedures', {trTypes} 'Typer', {trType} 'Typer', {trVariables} 'Variabler', {trAuthors} 'Författare', {trAuthor} 'Författare', {trCreated} 'Skapad', {trLastModified} 'Senast ändrad', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Se parameter', {trReturns} 'Retur', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Översikt', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alla klasser, interface och objekt', {trHeadlineConstants} strToDo, //'All Constants', {trHeadlineFunctionsAndProcedures} 'Alla funktioner och procedurer', {trHeadlineIdentifiers} 'Alla identifierare', {trHeadlineTypes} 'Alla typer', {trHeadlineUnits} 'Alla enheter', {trHeadlineVariables} 'Alla variabler', {trSummaryCio} 'Sammanfattning av Klasser, Interface, Objekt', //column headings {trDeclaration} 'Deklarationer', {trDescription} 'Beskrivning', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Namn', {trValues} strToDo, //'Values', //empty {trNone} 'Ingen/inget.', //??? {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', // Untranslated to avoid Swedish file name for css {trLegend} 'Förklaring', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Varning: ändra inte denna fil manuellt - filen har skapats automatiskt och kommer troligen att skrivas över vid ett senare tilfälle', {trWarning} 'Varning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������pasdoc/source/component/lang/PasDoc_Languages_Bosnia_1250.inc���������������������������������������0000644�0001750�0001750�00000010356�13237143042�024516� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Bosnian', //map {trUnits} 'Fajlovi', {trClassHierarchy} 'Klasna hijerarhija', {trCio} 'Klase, Interfejsi i Objekti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikatori', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klase', {trClass} 'Klasa', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Objekti', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hijerarhija', {trFields} 'Polja', {trMethods} 'Metode', {trProperties} 'Osibine', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Fajl', {trUses} strToDo, //'Uses', {trConstants} 'Konstante', {trFunctionsAndProcedures} 'Funkcije i Procedure', {trTypes} 'Tipovi', {trType} 'Tip', {trVariables} 'Promjenjive', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Kreirano', {trLastModified} 'Zadnja promjena', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} 'Privatni', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Zatien', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Publikovan', {trPublished} 'Javan', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pregled', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Sve Klase, Interfejsi i Objekti', {trHeadlineConstants} 'Sve Konstante', {trHeadlineFunctionsAndProcedures} 'Sve Funkcije i Procedure', {trHeadlineIdentifiers} 'Svi Identifikatoti', {trHeadlineTypes} 'Svi Tipovi', {trHeadlineUnits} 'Svi Fajlovi', {trHeadlineVariables} 'Sve Varijable', {trSummaryCio} 'Zbirno od Klasa, Interfejsa i Objekata', //column headings {trDeclaration} 'Deklaracija', {trDescription} 'Opis', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Ime', {trValues} strToDo, //'Values', //empty {trNone} 'Nita', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Pomo', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozorenje: Ne mjenjajte fajl - ovaj fajl je kreiran automatski i velika je vjerovatnoa da e biti prepisan', {trWarning} strToDo, //'Warning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Russian_866.inc���������������������������������������0000644�0001750�0001750�00000013115�13237143042�024657� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Russian', //<<<<<< replace with the name of the new language //map {trUnits} '㫨', //'Units', {trClassHierarchy} ' ᮢ', //'Class Hierarchy', {trCio} ', 䥩 ꥪ', //'Classes, Interfaces, Objects and Records', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} '䨪', //'Identifiers', {trGvUses} '䨪 ᨬ 㫥', //'Unit dependency graph', {trGvClasses} '䨪 娨 ᮢ', //'Classes hierarchy graph', //tables and members {trClasses} '', //'Classes', {trClass} '', //'Class', {trDispInterface} 'DispInterface', //'DispInterface', {trInterface} '䥩', //'Interface', {trObjects} 'ꥪ', //'Objects', {trObject} 'ꥪ', //'Object', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} '', //'Hierarchy', {trFields} '', //'Fields', {trMethods} '⮤', //'Methods', {trProperties} '⢠', //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'ணࠬ', //'Program', {trUnit} '', //'Unit', {trUses}'ᯮ㥬 㫨', //'Uses', {trConstants} '⠭', //'Constants', {trFunctionsAndProcedures} '楤 㭪樨', //'Functions and Procedures', {trTypes} '', //'Types', {trType} '', //'Type', {trVariables} '६', //'Variables', {trAuthors} '', //'Authors', {trAuthor} '', //'Author', {trCreated} '', //'Created', {trLastModified} '᫥ ', //'Last Modified', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'ࠬ', //'Parameters', {trReturns} '頥 祭', //'Returns', {trExceptionsRaised} '뢠 ᪫祭', //'Exceptions raised', {trExceptions} '᪫祭', //'Exceptions', {trException} strToDo, //'Exception', {trEnum} '᫥', //'Enumeration', //visibilities {trVisibility} ' ', //'Visibility', {trPrivate} 'Private', //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Protected', //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Public', //'Public', {trPublished} 'Published', //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} 'Implicit', //'Implicit', //hints {trDeprecated} ' ᨬ ᯮ', //'this symbol is deprecated', {trPlatformSpecific} ' ᨬ ', //'this symbol is specific to some platform', {trLibrarySpecific} ' ᨬ ⥪', //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} '', //'Overview', {trIntroduction} '', //'Introduction', {trConclusion} '祭', //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} ' , 䥩 ꥪ', //'All Classes, Interfaces, Objects and Records', {trHeadlineConstants} ' ⠭', //'All Constants', {trHeadlineFunctionsAndProcedures} ' 楤 㭪樨', //'All Functions and Procedures', {trHeadlineIdentifiers} ' 䨪', //'All Identifiers', {trHeadlineTypes} ' ⨯', //'All Types', {trHeadlineUnits} ' 㫨', //'All Units', {trHeadlineVariables} ' ६', //'All Variables', {trSummaryCio} '᮪ ᮢ, 䥩ᮢ ꥪ⮢', //'Summary of Classes, Interfaces, Objects and Records', //column headings {trDeclaration} '', //'Declaration', {trDescription} 'ᠭ', //'Description', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} '', //'Name', {trValues} '祭', //'Values', //empty {trNone} '', //'None', {trNoCIOs} '㫨 ᮤঠ ᮢ, 䥩ᮢ, ꥪ⮢ ᥩ.', //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} '㫨 ᮤঠ ᮢ, 䥩ᮢ ꥪ⮢.', //'The units do not contain any classes, interfaces or objects.', {trNoTypes} '㫨 ᮤঠ ⨯.', //'The units do not contain any types.', {trNoVariables} '㫨 ᮤঠ ६.', //'The units do not contain any variables.', {trNoConstants} '㫨 ᮤঠ ⠭.', //'The units do not contain any constants.', {trNoFunctions} '㫨 ᮤঠ 㭪樨 楤.', //'The units do not contain any functions or procedures.', {trNoIdentifiers} '㫨 ᮤঠ 䨪.', //'The units do not contain any identifiers.', //misc {trHelp} 'Help', //'Help', {trLegend} '祭', //'Legend', {trMarker} 'થ', //'Marker', {trWarningOverwrite} '।०: ।஢ - 䠩 ᮧ ⮬᪨ ।०', //'Warning: Do not edit - this file has been created automatically and is likely be overwritten', {trWarning} '।०', //'Warning', {trGeneratedBy} '஢ ', //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} '/६', //'on', {trSearch} '', //'Search', {trSeeAlso} 'ਠ ⥬', //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Italian_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000010412�13237143042�026011� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Italian', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Classi, Interfacce ed Oggetti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificatori', {trGvUses} 'Grafico dipendenze Unit', {trGvClasses} 'Grafico gerarchia Classi', //tables and members {trClasses} 'Classi', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfacce', {trObjects} 'Oggetti', {trObject} 'Oggetto', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Gerarchia', {trFields} 'Campi', {trMethods} 'Metodi', {trProperties} 'Proprietà', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Costanti', {trFunctionsAndProcedures} 'Funzioni e Procedure', {trTypes} 'Tipi', {trType} 'Tipo', {trVariables} 'Variabili', {trAuthors} 'Autori', {trAuthor} 'Autore', {trCreated} 'Creato', {trLastModified} 'Ultima Variazione', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parametri', {trReturns} 'Ritorni', {trExceptionsRaised} 'Eccezioni sollevate', {trExceptions} 'Eccezione', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sommario', {trIntroduction} 'Introduczione', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Tutte le Classi, Interfacce ed Oggetti', {trHeadlineConstants} 'Tutte le Costanti', {trHeadlineFunctionsAndProcedures} 'Tutte le Funzioni e Procedure', {trHeadlineIdentifiers} 'Tutti gli Identificatori', {trHeadlineTypes} 'Tutti i Tipi', {trHeadlineUnits} 'Tutte le Units', {trHeadlineVariables} 'Tutte le Variabili', {trSummaryCio} 'Sommario di Classi, Interfacce ed Oggetti', //column headings {trDeclaration} 'Dichiarazione', {trDescription} 'Descrizione', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nome', {trValues} 'Valori', //empty {trNone} 'Nessuno', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Attenzione: Non modificare - questo file è stato generato automaticamente e verrà probabilmente sovrascritto', {trWarning} 'Attenzione', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} 'Cerca', {trSeeAlso} 'Vedere Anche', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_French_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010474�13237143042�025645� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'French', //map {trUnits} 'Unités', {trClassHierarchy} 'Hiérarchie des classes', {trCio} 'Classes, interfaces, enregistrements et objets', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificateurs', {trGvUses} 'Graphe de dépendance d''unités', {trGvClasses} 'Graphe de hiérarchie des classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objets', {trObject} 'Objet', {trRecord} 'Enregistrement', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hiérarchie', {trFields} 'Champs', {trMethods} 'Méthodes', {trProperties} 'Propriétés', {trLibrary} 'Bibliothèque', //? {trPackage} 'Paquet', //'Package', {trProgram} 'Logiciel', //? 'Program', {trUnit} 'Unité', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Fonctions et procédures', {trTypes} strKeep, //'Types', {trType} strKeep, //'Type', {trVariables} strKeep, //'Variables', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Crée', {trLastModified} 'Dernière modification', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paramètres', {trReturns} 'Retourne', {trExceptionsRaised} 'Exception levées', //'Exceptions raised', {trExceptions} strKeep, //'Exceptions', {trException} strKeep, //'Exception', {trEnum} 'Énumération', //'Enumeration', //visibilities {trVisibility} 'Visibilité', {trPrivate} 'Privé', {trStrictPrivate} 'Strictement Privé', //? {trProtected} 'Protégé', {trStrictProtected} 'Strictement Protégé', //? {trPublic} strKeep, //'Public', {trPublished} 'Publiés', {trAutomated} 'Automatisé', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'ce symbole est désapprouvé', {trPlatformSpecific} 'ce symbole est spécifique à une plateforme d''exécution', {trLibrarySpecific} 'ce symbole est spécifique à une certaine bibliothèque', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Aperçu', {trIntroduction} strKeep, //'Introduction', {trConclusion} strKeep, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Toutes les classes, interfaces, objets et enregistrements', {trHeadlineConstants} 'Toutes les constantes', {trHeadlineFunctionsAndProcedures} 'Toutes les fonctions et procédures', {trHeadlineIdentifiers} 'Tous les identificateurs', {trHeadlineTypes} 'Tous les types', {trHeadlineUnits} 'Toutes les unités', {trHeadlineVariables} 'Toutes les variables', {trSummaryCio} 'Classes, interfaces, objets et enregistrements', //column headings {trDeclaration} 'Déclaration', {trDescription} strKeep, //'Description', {trDescriptions} strKeep, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nom', {trValues} 'Valeurs', //? //empty {trNone} 'Aucun(e)(s)', //'Rien'? {trNoCIOs} 'L''unité ne contient ni classe, ni interface, ni objets, ni enregistrement.', {trNoCIOsForHierarchy} 'L''unité ne contient ni classe, ni interface, ni objets.', {trNoTypes} 'L''unité ne contient aucun type.', {trNoVariables} 'L''unité ne contient aucune variable.', {trNoConstants} 'L''unité ne contient aucune constante.', {trNoFunctions} 'L''unité ne contient ni fonction ni procédure.', {trNoIdentifiers} 'L''unité ne contient aucun indentificateur.', //misc {trHelp} 'Aide', {trLegend} 'Légende', {trMarker} 'Marquage', {trWarningOverwrite} 'Attention, ne pas éditer - ce fichier est créé automatiquement et va être écrasé', {trWarning} 'Attention', {trGeneratedBy} 'Produit par', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'le', {trSearch} 'Cherche', //? 'Recherche' {trSeeAlso} 'Voir aussi', //? {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Bulgarian_utf8.inc������������������������������������0000644�0001750�0001750�00000012772�13237143042�025512� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Bulgarian', //map {trUnits} 'Модули', {trClassHierarchy} 'Йерархия на класовете', {trCio} 'Класове, интерфейси и обекти', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Идентификатори', {trGvUses} 'Зависимости на модулите', {trGvClasses} 'Зависимости на класовете', //tables and members {trClasses} 'Класове', {trClass} 'Клас', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Интерфейс', {trObjects} 'Обекти', {trObject} 'Обект', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Йерархия', {trFields} 'Полета на класа', {trMethods} 'Методи на класа', {trProperties} 'Свойства на класа', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Програма', {trUnit} 'Модул', {trUses} 'Използвани модули', {trConstants} 'Константи', {trFunctionsAndProcedures} 'Процедури и функции', {trTypes} 'Типове', {trType} 'Тип', {trVariables} 'Променливи', {trAuthors} 'Автори', {trAuthor} 'Автор', {trCreated} 'Създадено', {trLastModified} 'Последна промяна', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Параметри', {trReturns} 'Резултат', {trExceptionsRaised} 'Изключения', {trExceptions} 'Изключения', {trException} strToDo, //'Exception', {trEnum} 'Изброим тип', //visibilities {trVisibility} 'Видимост', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'Този идентификатор е изваден от употреба! Моля, потърсете алтернатива', {trPlatformSpecific} 'Този идентификатор е платформено зависим', {trLibrarySpecific} 'Този идентификатор зависи от специфични библиотеки', {trExperimental} 'Този идентификатор е експериментален. Използвайте го внимателно', (* {trUnimplemented} 'Тази процедура/функция все още не е реализирана', *) //headings {trOverview} 'Съдържание', {trIntroduction} 'Въведение', {trConclusion} 'Заключение', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Всички класове, интерфейси и обекти', {trHeadlineConstants} 'Всички константи', {trHeadlineFunctionsAndProcedures} 'Всички процедури и функции', {trHeadlineIdentifiers} 'Всички идентификатори', {trHeadlineTypes} 'Всички типове', {trHeadlineUnits} 'Всички модули', {trHeadlineVariables} 'Всички променливи', {trSummaryCio} 'Списък на класовете, интерфейсите и обектите', //column headings {trDeclaration} 'Декларации', {trDescription} 'Описание', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Име', {trValues} 'Стойност(и)', //empty {trNone} 'Няма', {trNoCIOs} 'Модулите не съдържат класове, интерфейси, обекти и записи', {trNoCIOsForHierarchy} 'Модулите не съдържат класове, интерфейси и обекти', {trNoTypes} 'Модулите не съдържат типове', {trNoVariables} 'Модулите не съдържат променливи', {trNoConstants} 'Модулите не съдържат константи', {trNoFunctions} 'Модулите не съдържат функции и процедури', {trNoIdentifiers} 'Модулите не съдържат идентификатори', //misc {trHelp} strKeep, //'Help', // Untranslated to avoid Russian file name for css { TODO : how does "Help" interfere with file names? } {trLegend} 'Обозначения', {trMarker} 'Маркер', {trWarningOverwrite} 'Предупреждение: Не редактирайте този файл - той е автоматично създаден и може да бъде променен без предупреждение', {trWarning} 'Предупреждение', {trGeneratedBy} 'Документацията е създадена от', // + ' '? {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'на дата', //really??? {trSearch} 'Търсене', {trSeeAlso} 'Виж още', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������pasdoc/source/component/lang/PasDoc_Languages_Brasilian_utf8.inc������������������������������������0000644�0001750�0001750�00000010560�13237143042�025503� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Brasilian', //map {trUnits} strToDo, //'Units', {trClassHierarchy} 'Hierarquia de Classes', {trCio} 'Classes, Interfaces, Objetos e Registros', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadores', {trGvUses} 'Diagrama de dependências de units', {trGvClasses} 'Diagrama de hierarquia de Classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objetos', {trObject} 'Objeto', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarquia', {trFields} 'Campos', {trMethods} 'Métodos', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Funções e Procedimentos', {trTypes} 'Tipos', {trType} 'Tipo', {trVariables} 'Variáveis', {trAuthors} 'Autores', {trAuthor} 'Autor', {trCreated} 'Criada', {trLastModified} 'Última modificação', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parâmetros', {trReturns} 'Retornos', //??? {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} 'Exceções', {trException} strToDo, //'Exception', {trEnum} 'Enumerações', //??? //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'este símbolo está depreciado', {trPlatformSpecific} 'este símbolo é específico para alguma plataforma', {trLibrarySpecific} 'este símbolo é específico para alguma biblioteca', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Visão Geral', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Todas as Classes, Interfaces, Objetos e Registros', {trHeadlineConstants} 'Todas as Constantes', {trHeadlineFunctionsAndProcedures} 'Todas as funções e procedimentos', {trHeadlineIdentifiers} 'Todos os Identificadores', {trHeadlineTypes} 'Todos os Tipos', {trHeadlineUnits} 'Todas as Units', {trHeadlineVariables} 'Todas as Variáveis', {trSummaryCio} 'Lista das Classes, Interfaces, Objetos e Registros', //column headings {trDeclaration} 'Declaração', {trDescription} 'Descrição', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nome', {trValues} strToDo, //'Values', //empty {trNone} 'Nenhum', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Ajuda', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Aviso, não altere - este arquivo foi gerado automaticamente e será sobrescrito', {trWarning} strToDo, //'Warning', {trGeneratedBy} 'Gerado por', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'as', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_German_1252.inc���������������������������������������0000644�0001750�0001750�00000010205�13237143042�024507� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<hh?>', //no ID assigned, so far {trLanguage} 'German', //map {trUnits} strKeep, //'Units', {trClassHierarchy} 'Klassenhierarchie', {trCio} 'Klassen, Interfaces und Objects', {trInternalCR} 'Interne Klassen und Records', {trInternalTypes} 'Interne Typen', {trIdentifiers} 'Bezeichner', {trGvUses} 'Graph der Unit-Abhngigkeiten', {trGvClasses} 'Graph der Klassenhierarchie', //tables and members {trClasses} 'Klassen', {trClass} 'Klasse', {trDispInterface} strKeep, //'DispInterface', {trInterface} strKeep, //'Interface', 'Schnittstelle'? {trObjects} strKeep, //'Objects', {trObject} strKeep, //'Object', {trRecord} strKeep, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Felder', {trMethods} 'Methoden', {trProperties} 'Eigenschaften', {trLibrary} 'Bibliothek', {trPackage} strKeep, //'Package', {trProgram} 'Programm', {trUnit} strKeep, //'Unit', {trUses} strKeep, //'Uses', {trConstants} 'Konstanten', {trFunctionsAndProcedures} 'Funktionen und Prozeduren', {trTypes} 'Datentypen', {trType} strKeep, //'Type', 'Typ'? {trVariables} 'Variablen', {trAuthors} 'Autoren', {trAuthor} 'Autor', {trCreated} 'Erstellt', {trLastModified} 'Letzte nderung', {trSubroutine} 'Unterprogramm', {trParameters} 'Parameter', {trReturns} 'Result', {trExceptionsRaised} 'Wirft Ausnahmen', //'Exceptions raised', {trExceptions} 'Ausnahmen', {trException} strKeep, //'Exception', {trEnum} strKeep, //'Enumeration', //visibilities {trVisibility} 'Sichtbarkeit', {trPrivate} strKeep, //'Private', {trStrictPrivate} strKeep, //'Strict Private', {trProtected} strKeep, //'Protected', {trStrictProtected} strKeep, //'Strict Protected', {trPublic} strKeep, //'Public', {trPublished} strKeep, //'Published', {trAutomated} strKeep, //'Automated', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'Dieses Symbol sollte nicht (mehr) verwendet werden.', {trPlatformSpecific} 'Dieses Symbol ist plattformspezifisch.', {trLibrarySpecific} 'Dieses Symbol ist spezifisch fr eine bestimmte Bibliothek.', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'bersicht', {trIntroduction} 'Einfhrung', {trConclusion} 'Fazit', {trEnclosingClass} 'Einschlieende Klasse', {trHeadlineCio} 'Alle Klassen, Schnittstellen, Objekte und Records', {trHeadlineConstants} 'Alle Konstanten', {trHeadlineFunctionsAndProcedures} 'Alle Funktionen und Prozeduren', {trHeadlineIdentifiers} 'Alle Bezeichner', {trHeadlineTypes} 'Alle Typen', {trHeadlineUnits} 'Alle Units', {trHeadlineVariables} 'Alle Variablen', {trSummaryCio} 'Zusammenfassung aller Klassen, Schnittstellen, Objekte und Records', //column headings {trDeclaration} 'Deklaration', {trDescription} 'Beschreibung', {trDescriptions} 'Ausfhrliche Beschreibungen', {trName} strKeep, //'Name', {trValues} 'Werte', //empty {trNone} 'Keine', {trNoCIOs} 'Die Units enthalten keine Klassen, Interfaces, Objects oder Records.', {trNoCIOsForHierarchy} 'Die Units enthalten keine Klassen, Interfaces oder Objects.', {trNoTypes} 'Die Units enthalten keine Typen.', {trNoVariables} 'Die Units enthalten keine Variablen.', {trNoConstants} 'Die Units enthalten keine Konstanten.', {trNoFunctions} 'Die Units enthalten keine Funktionen oder Prozeduren.', {trNoIdentifiers} 'Die Units enthalten keine Bezeichner.', //misc {trHelp} 'Hilfe', {trLegend} 'Legende', {trMarker} 'Markierung', {trWarningOverwrite} 'Achtung: Nicht ndern - diese Datei wurde automatisch erstellt und wird mglicherweise berschrieben', {trWarning} 'Warnung', {trGeneratedBy} 'Erstellt mit', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'am', {trSearch} 'Suchen', {trSeeAlso} 'Siehe auch', {trInternal} 'intern', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Russian_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000012160�13237143042�026056� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Russian', //map {trUnits} 'Модули', {trClassHierarchy} 'Иерархия классов', {trCio} 'Классы, интерфейсы и объекты', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Идентификаторы', {trGvUses} 'График зависимости модулей', {trGvClasses} 'График иерархии классов', //tables and members {trClasses} 'Классы', {trClass} 'Класс', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Интерфейс', {trObjects} 'Объекты', {trObject} 'Объект', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Иерархия', {trFields} 'Поля', {trMethods} 'Методы', {trProperties} 'Свойства', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Программа', {trUnit} 'Модуль', {trUses} 'Используемые модули', {trConstants} 'Константы', {trFunctionsAndProcedures} 'Процедуры и функции', {trTypes} 'Типы', {trType} 'Тип', {trVariables} 'Переменные', {trAuthors} 'Авторы', {trAuthor} 'Автор', {trCreated} 'Создано', {trLastModified} 'Последнее изменение', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Параметры', {trReturns} 'Возвращаемые значения', {trExceptionsRaised} 'Вызывает исключения', {trExceptions} 'Исключения', {trException} strToDo, //'Exception', {trEnum} 'Перечисление', //visibilities {trVisibility} 'Зона видимости', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'этот символ больше не используется', {trPlatformSpecific} 'этот символ зависит от платформы', {trLibrarySpecific} 'этот символ зависит от библиотеки', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Обзор', {trIntroduction} 'Введение', {trConclusion} 'Заключение', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Все классы, интерфейсы и объекты', {trHeadlineConstants} 'Все константы', {trHeadlineFunctionsAndProcedures} 'Все процедуры и функции', {trHeadlineIdentifiers} 'Все идентификаторы', {trHeadlineTypes} 'Все типы', {trHeadlineUnits} 'Все модули', {trHeadlineVariables} 'Все переменные', {trSummaryCio} 'Список классов, интерфейсов и объектов', //column headings {trDeclaration} 'Объявления', {trDescription} 'Описание', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Имя', {trValues} 'Значение', //empty {trNone} 'Нет', {trNoCIOs} 'Модули не содержат классов, интерфейсов, объектов и записей.', {trNoCIOsForHierarchy} 'Модули не содержат классов, интерфейсов и объектов.', {trNoTypes} 'Модули не содержат типов.', {trNoVariables} 'Модули не содержат переменных.', {trNoConstants} 'Модули не содержат констант.', {trNoFunctions} 'Модули не содержат функции и процедуры.', {trNoIdentifiers} 'Модули не содержат ни одного идентификатора.', //misc {trHelp} strKeep, //'Help', // Untranslated to avoid Russian file name for css { TODO : how does "Help" interfere with file names? } {trLegend} 'Обозначения', {trMarker} 'Маркер', {trWarningOverwrite} 'Предупреждение: не редактировать - этот файл создан автоматически и может быть изменён без предупреждения', {trWarning} 'Предупреждение', {trGeneratedBy} 'Сгенерировал', // + ' '? {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'дата/время', //really??? {trSearch} 'Найти', {trSeeAlso} 'Материалы по теме', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Polish_1250.inc���������������������������������������0000644�0001750�0001750�00000010010�13237143042�024524� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Polish', //map {trUnits} 'Moduy', {trClassHierarchy} 'Hierarchia klas', {trCio} 'Klasy, interfejsy, obiekty i rekordy', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identyfikatory', {trGvUses} 'Graf zalenoci moduw', {trGvClasses} 'Graf dziedziczenia klas', //tables and members {trClasses} 'Klasy', {trClass} 'Klasa', {trDispInterface} 'DispInterface', //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Obiekty', {trObject} 'Obiekt', {trRecord} 'Rekord', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Pola', {trMethods} 'Metody', {trProperties} 'Waciwoci', {trLibrary} 'Biblioteka', //'Library', {trPackage} 'Pakiet', //'Package', {trProgram} 'Program', //'Program', {trUnit} 'Modu', {trUses} 'Uywa', //'Uses', {trConstants} 'Stae', {trFunctionsAndProcedures} 'Podprogramy', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Zmienne', {trAuthors} 'Autorzy', {trAuthor} 'Autor', {trCreated} 'Utworzony', {trLastModified} 'Ostatnia modyfikacja', {trSubroutine} 'Podprograma', //? {trParameters} 'Parametry', {trReturns} 'Wynik', {trExceptionsRaised} 'Generowane wyjtki', {trExceptions} 'Wyjtki', {trException} 'Wyjtek', //'Exception', {trEnum} 'Wyliczenie', //visibilities {trVisibility} 'Widoczno', {trPrivate} 'Prywatne', {trStrictPrivate} 'cile prywatne', //'Strict Private', {trProtected} 'Chronione', {trStrictProtected} 'cile chronione', //'Strict Protected', {trPublic} 'Publiczne', {trPublished} 'Publikowane', {trAutomated} 'Automated', //'Automated', {trImplicit} 'Domylne', //hints {trDeprecated} 'odradza si uywania tego identyfikatora', {trPlatformSpecific} 'ten identyfikator jest zaleny od platformy', {trLibrarySpecific} 'ten identyfikator jest zaleny od biblioteki', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Przegld', {trIntroduction} 'Wstp', {trConclusion} 'Podsumowanie', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Wszystkie klasy, interfejsy, obiekty i rekordy', {trHeadlineConstants} 'Wszystkie stae', {trHeadlineFunctionsAndProcedures} 'Wszystkie podprogramy', {trHeadlineIdentifiers} 'Wszystkie identyfikatory', {trHeadlineTypes} 'Wszystkie typy', {trHeadlineUnits} 'Wszystkie moduy', {trHeadlineVariables} 'Wszystkie zmienne', {trSummaryCio} 'Podsumowanie klas, interfejsw, obiektw i rekordw', //column headings {trDeclaration} 'Deklaracja', {trDescription} 'Opis', {trDescriptions} 'Szczegy', //'Descriptions', 'Detailed Descriptions'? {trName} 'Nazwa', {trValues} 'Wartoci', //empty {trNone} 'Brak', {trNoCIOs} 'Modu nie zawiera adnych klas, interfejsw, obiektw ani rekordw.', {trNoCIOsForHierarchy} 'Modu nie zawiera adnych klas, interfejsw ani obiektw.', {trNoTypes} 'Modu nie zawiera adnych typw.', {trNoVariables} 'Modu nie zawiera adnych zmiennych.', {trNoConstants} 'Modu nie zawiera adnych staych.', {trNoFunctions} 'Modu nie zawiera adnych funkcji ani podprogramw.', {trNoIdentifiers} 'Modu nie zawiera adnych identyfikatorw.', //misc {trHelp} 'Pomoc', {trLegend} 'Legenda', {trMarker} 'Kolor', {trWarningOverwrite} 'Uwaga, nie modyfikuj - ten plik zosta wygenerowany automatycznie i moe zosta nadpisany', {trWarning} 'Uwaga', {trGeneratedBy} 'Wygenerowane przez', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} ' - ', {trSearch} 'Szukaj', {trSeeAlso} 'Zobacz take', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Croatia_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000007446�13237143042�026027� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<što?>', //no ID assigned, so far {trLanguage} 'Hrvatski', //map {trUnits} 'Datoteke', {trClassHierarchy} 'Klasna hijerarhija', {trCio} 'Klase, Sučelja i Objekti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikatori', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klase', {trClass} 'Klasa', {trDispInterface} strToDo, {trInterface} 'Sučelje', {trObjects} 'Objekti', {trObject} 'Objekt', {trRecord} strToDo, {trPacked} strToDo, //'Packed', {trHierarchy} 'Hijerarhija', {trFields} 'Polja', {trMethods} 'Metode', {trProperties} 'Osobine', {trLibrary} strToDo, {trPackage} strToDo, {trProgram} strToDo, {trUnit} 'Datoteka', {trUses} strToDo, {trConstants} 'Konstante', {trFunctionsAndProcedures} 'Funkcije i Procedure', {trTypes} 'Tipovi', {trType} 'Tip', {trVariables} 'Varijable', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Kreirano', {trLastModified} 'Zadnja promjena', {trSubroutine} strToDo, {trParameters} 'Parametri', {trReturns} 'Vraća', {trExceptionsRaised} strToDo, {trExceptions} strToDo, {trException} strToDo, {trEnum} strToDo, //visibilities {trVisibility} 'Vidljivost', {trPrivate} strToDo, {trStrictPrivate} strToDo, {trProtected} strToDo, {trStrictProtected} strToDo, {trPublic} strToDo, {trPublished} strToDo, {trAutomated} strToDo, {trImplicit} strToDo, //hints {trDeprecated} 'Ovaj simbol je zastario', {trPlatformSpecific} 'Ovaj simbol je specifičan za neke platforme', {trLibrarySpecific} 'Ovaj simbol je specifičan za neke biblioteke', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pregled', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Sve Klase, Sučelja i Objekti', {trHeadlineConstants} 'Sve Konstante', {trHeadlineFunctionsAndProcedures} 'Sve Funkcije i Procedure', {trHeadlineIdentifiers} 'Svi Identifikatoti', {trHeadlineTypes} 'Svi Tipovi', {trHeadlineUnits} 'Sve Datoteke', {trHeadlineVariables} 'Sve Varijable', {trSummaryCio} 'Ukupno od Klasa, Interfejsa i Objekata', //column headings {trDeclaration} 'Deklaracija', {trDescription} 'Opis', {trDescriptions} 'Detaljni opis', {trName} 'Ime', {trValues} 'Vrijednosti', //'Values', //empty {trNone} 'Ništa', {trNoCIOs} 'Datoteka ne sadrži klase, sučelja, objekte ili zapise.', {trNoCIOsForHierarchy} 'Datoteke ne sadrže klase, sučelja, objekte ili zapise.', {trNoTypes} 'Datoteke ne sadrže tipove.', {trNoVariables} 'Datoteke ne sadrže varijable.', {trNoConstants} 'Datoteke ne sadrže konstante.', {trNoFunctions} 'Datoteke ne sadrže funkcije ili procedure.', {trNoIdentifiers} 'Datoteke ne sadrže indentifikatore.', //misc {trHelp} 'Pomoć', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozorenje: Ne mjenjajte ovu datoteku - kreirana je automatski i velika je mogućnost da će biti prepisana', {trWarning} 'Upozorenje', //'Warning', {trGeneratedBy} 'Generirano od', //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} 'Traži', //'Search', {trSeeAlso} 'Vidi još', {trInternal} 'interno', //'internal', {trAttributes} 'Atributi', //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Indonesian_utf8_bom.inc�������������������������������0000644�0001750�0001750�00000010566�13237143042�026531� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Indonesian', //map {trUnits} 'Unit', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Kelas, Interface, dan Objek', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Kelas', {trClass} 'Kelas', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objek', {trObject} 'Objek', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarki', {trFields} strToDo, //'Fields', {trMethods} strToDo, //'Methods', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strKeep, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanta', {trFunctionsAndProcedures} 'Fungsi dan Prosedur', {trTypes} 'Tipe Bentukan', {trType} 'Tipe Bentukan', {trVariables} 'Variabel', {trAuthors} 'Pembuat', {trAuthor} 'Pembuat', {trCreated} 'Dibuat', {trLastModified} 'Terakhir Dimodifikasi', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sekilas', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Semua Kelas, Interface, dan Objek', {trHeadlineConstants} 'Semua Konstanta', {trHeadlineFunctionsAndProcedures} 'Semua Fungsi dan Prosedur', {trHeadlineIdentifiers} 'Semua Identifier', {trHeadlineTypes} 'Semua Tipe Bentukan', {trHeadlineUnits} 'Semua Unit', {trHeadlineVariables} 'Semua Variabel', {trSummaryCio} 'Ringkasan Kelas, Interface, dan Objek', //column headings {trDeclaration} 'Deklarasi', {trDescription} 'Definisi', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nama', {trValues} strToDo, //'Values', //empty {trNone} 'Tidak Ada', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Bantuan', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Perhatian: Jangan dimodifikasi - ' + 'file ini dihasilkan secara otomatis dan mungkin saja ditimpa ulang', {trWarning} 'Perhatian', //? {trGeneratedBy} 'Dihasilkan oleh', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'pada', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Spanish_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000010753�13237143042�026045� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Spanish', //map {trUnits} 'Unidades', {trClassHierarchy} 'Jerarquía de clases', {trCio} 'Clases, interfaces y objetos', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadores', {trGvUses} 'Gráfico de dependencias de unidades', // {trGvClasses} 'Gráfico de jerarquía de clases', // //tables and members {trClasses} 'Clases', {trClass} 'Clase', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfaz', //'Interface', {trObjects} 'Objetos', {trObject} 'Objeto', {trRecord} 'Registro', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Jerarquía', {trFields} 'Campos', {trMethods} 'Métodos', {trProperties} 'Propiedades', {trLibrary} 'Biblioteca', //'Library', {trPackage} 'Paquete', //'Package', {trProgram} 'Programa', //'Program', {trUnit} 'Unidad', {trUses} 'Unidades', //'Uses', I may use "Unidades utilizadas/referenciadas" (Used/referenced units). {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Funciones y procedimientos', {trTypes} 'Tipos', {trType} 'Tipo', {trVariables} 'Variables', //'Variables', {trAuthors} 'Autores', {trAuthor} 'Autor', {trCreated} 'Creado', {trLastModified} 'Última modificación', {trSubroutine} 'Subrutina', //'Subroutine', {trParameters} 'Parámetros', {trReturns} 'Retorno', //strToDo??? solo uno! {trExceptionsRaised} 'Excepciones lanzadas', {trExceptions} 'Excepciones', {trException} 'Excepción', // {trEnum} 'Enumeración', //'Enumeration', //visibilities {trVisibility} 'Visibilidad', {trPrivate} 'Privado', //'Private', {trStrictPrivate} 'Estrictamente privado', //'Strict Private', {trProtected} 'Protegido', //? {trStrictProtected} 'Estrictamente protegido', //'Strict Protected', {trPublic} 'Público', //'Public', {trPublished} strToDo, //'Published', I would keep that because "Published" is also "Público" in this context (IDE). {trAutomated} 'Automático', //'Automated', {trImplicit} 'Implícito', //'Implicit', //hints {trDeprecated} 'Este símbolo es obsoleto', // {trPlatformSpecific} 'Este símbolo es específico para alguna plataforma', {trLibrarySpecific} 'Este símbolo es específico para alguna biblioteca', // {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Resumen', {trIntroduction} 'Introducción', {trConclusion} 'Conclusión', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Todas las clases, interfaces y objetos', {trHeadlineConstants} 'Todas las constantes', {trHeadlineFunctionsAndProcedures} 'Todos las funciones y procedimientos', {trHeadlineIdentifiers} 'Todos los indentificadores', {trHeadlineTypes} 'Todos los tipos', {trHeadlineUnits} 'Todas las unidades', {trHeadlineVariables} 'Todas las variables', {trSummaryCio} 'Lista de clases, interfaces y objetos', //column headings {trDeclaration} 'Declaración', {trDescription} 'Descripción', {trDescriptions} 'Descripción detallada', //? 'Descriptions', 'Detailed Descriptions'? {trName} 'Nombre', {trValues} 'Valores', //empty {trNone} 'Ninguno', {trNoCIOs} 'Las unidades no contienen clases, interfaces, objetos ni registros.', {trNoCIOsForHierarchy} 'Las unidades no contienen clases, interfaces ni objetos.', {trNoTypes} 'Las unidades no contienen tipo alguno.', {trNoVariables} 'Las unidades no contienen ninguna variable.', // {trNoConstants} 'Las unidades no contienen ninguna constante.', // {trNoFunctions} 'Las unidades no contienen funciones ni procedimientos', // {trNoIdentifiers} 'Las unidades no contienen identificadores.', //misc {trHelp} 'Ayuda', {trLegend} 'Leyenda', {trMarker} 'Marcador', {trWarningOverwrite} 'Atención, no editar - este fichero ha sido creado automaticamente y puede ser sobrescrito', {trWarning} 'Atención', {trGeneratedBy} 'Generado por', //??? strToDo, //'Generador por', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'a', {trSearch} 'Buscar', {trSeeAlso} 'Ver también', // ? {trInternal} 'interno', //'internal', {trAttributes} 'Atributos', //'Attributes', '' //dummy ); ���������������������pasdoc/source/component/lang/PasDoc_Languages_English_utf8.inc��������������������������������������0000644�0001750�0001750�00000007343�13237143042�025175� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'English', //map {trUnits} 'Units', {trClassHierarchy} 'Class Hierarchy', {trCio} 'Classes, Interfaces, Objects and Records', {trInternalCR} 'Internal Classes and Records', {trInternalTypes} 'Internal Types', {trIdentifiers} 'Identifiers', {trGvUses} 'Unit dependency graph', {trGvClasses} 'Classes hierarchy graph', //tables and members {trClasses} 'Classes', {trClass} 'Class', {trDispInterface} 'DispInterface', {trInterface} 'Interface', {trObjects} 'Objects', {trObject} 'Object', {trRecord} 'Record', {trPacked} 'Packed', {trHierarchy} 'Hierarchy', {trFields} 'Fields', {trMethods} 'Methods', {trProperties} 'Properties', {trLibrary} 'Library', {trPackage} 'Package', {trProgram} 'Program', {trUnit} 'Unit', {trUses} 'Uses', {trConstants} 'Constants', {trFunctionsAndProcedures} 'Functions and Procedures', {trTypes} 'Types', {trType} 'Type', {trVariables} 'Variables', {trAuthors} 'Authors', {trAuthor} 'Author', {trCreated} 'Created', {trLastModified} 'Last Modified', {trSubroutine} 'Subroutine', {trParameters} 'Parameters', {trReturns} 'Returns', {trExceptionsRaised} 'Exceptions raised', {trExceptions} 'Exceptions', {trException} 'Exception', {trEnum} 'Enumeration', //visibilities {trVisibility} 'Visibility', {trPrivate} 'Private', {trStrictPrivate} 'Strict Private', {trProtected} 'Protected', {trStrictProtected} 'Strict Protected', {trPublic} 'Public', {trPublished} 'Published', {trAutomated} 'Automated', {trImplicit} 'Implicit', //hints {trDeprecated} 'this symbol is deprecated', {trPlatformSpecific} 'this symbol is specific to some platform', {trLibrarySpecific} 'this symbol is specific to some library', {trExperimental} 'this symbol is experimental', //headings {trOverview} 'Overview', {trIntroduction} 'Introduction', {trConclusion} 'Conclusion', {trEnclosingClass} 'Enclosing Class', {trHeadlineCio} 'All Classes, Interfaces, Objects and Records', {trHeadlineConstants} 'All Constants', {trHeadlineFunctionsAndProcedures} 'All Functions and Procedures', {trHeadlineIdentifiers} 'All Identifiers', {trHeadlineTypes} 'All Types', {trHeadlineUnits} 'All Units', {trHeadlineVariables} 'All Variables', {trSummaryCio} 'Summary of Classes, Interfaces, Objects and Records', //column headings {trDeclaration} 'Declaration', {trDescription} 'Description', {trDescriptions} 'Detailed Descriptions', {trName} 'Name', {trValues} 'Values', //empty {trNone} 'None', {trNoCIOs} 'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} 'The units do not contain any classes, interfaces or objects.', {trNoTypes} 'The units do not contain any types.', {trNoVariables} 'The units do not contain any variables.', {trNoConstants} 'The units do not contain any constants.', {trNoFunctions} 'The units do not contain any functions or procedures.', {trNoIdentifiers} 'The units do not contain any identifiers.', //misc {trHelp} 'Help', {trLegend} 'Legend', {trMarker} 'Marker', {trWarningOverwrite} 'Warning: Do not edit - this file has been created automatically and is likely be overwritten', {trWarning} 'Warning', {trGeneratedBy} 'Generated by', {trGeneratedOn} 'Generated on', {trOnDateTime} 'on', {trSearch} 'Search', {trSeeAlso} 'See also', {trInternal} 'internal', {trAttributes} 'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_English_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000007343�13237143042�026032� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'English', //map {trUnits} 'Units', {trClassHierarchy} 'Class Hierarchy', {trCio} 'Classes, Interfaces, Objects and Records', {trInternalCR} 'Internal Classes and Records', {trInternalTypes} 'Internal Types', {trIdentifiers} 'Identifiers', {trGvUses} 'Unit dependency graph', {trGvClasses} 'Classes hierarchy graph', //tables and members {trClasses} 'Classes', {trClass} 'Class', {trDispInterface} 'DispInterface', {trInterface} 'Interface', {trObjects} 'Objects', {trObject} 'Object', {trRecord} 'Record', {trPacked} 'Packed', {trHierarchy} 'Hierarchy', {trFields} 'Fields', {trMethods} 'Methods', {trProperties} 'Properties', {trLibrary} 'Library', {trPackage} 'Package', {trProgram} 'Program', {trUnit} 'Unit', {trUses} 'Uses', {trConstants} 'Constants', {trFunctionsAndProcedures} 'Functions and Procedures', {trTypes} 'Types', {trType} 'Type', {trVariables} 'Variables', {trAuthors} 'Authors', {trAuthor} 'Author', {trCreated} 'Created', {trLastModified} 'Last Modified', {trSubroutine} 'Subroutine', {trParameters} 'Parameters', {trReturns} 'Returns', {trExceptionsRaised} 'Exceptions raised', {trExceptions} 'Exceptions', {trException} 'Exception', {trEnum} 'Enumeration', //visibilities {trVisibility} 'Visibility', {trPrivate} 'Private', {trStrictPrivate} 'Strict Private', {trProtected} 'Protected', {trStrictProtected} 'Strict Protected', {trPublic} 'Public', {trPublished} 'Published', {trAutomated} 'Automated', {trImplicit} 'Implicit', //hints {trDeprecated} 'this symbol is deprecated', {trPlatformSpecific} 'this symbol is specific to some platform', {trLibrarySpecific} 'this symbol is specific to some library', {trExperimental} 'this symbol is experimental', //headings {trOverview} 'Overview', {trIntroduction} 'Introduction', {trConclusion} 'Conclusion', {trEnclosingClass} 'Enclosing Class', {trHeadlineCio} 'All Classes, Interfaces, Objects and Records', {trHeadlineConstants} 'All Constants', {trHeadlineFunctionsAndProcedures} 'All Functions and Procedures', {trHeadlineIdentifiers} 'All Identifiers', {trHeadlineTypes} 'All Types', {trHeadlineUnits} 'All Units', {trHeadlineVariables} 'All Variables', {trSummaryCio} 'Summary of Classes, Interfaces, Objects and Records', //column headings {trDeclaration} 'Declaration', {trDescription} 'Description', {trDescriptions} 'Detailed Descriptions', {trName} 'Name', {trValues} 'Values', //empty {trNone} 'None', {trNoCIOs} 'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} 'The units do not contain any classes, interfaces or objects.', {trNoTypes} 'The units do not contain any types.', {trNoVariables} 'The units do not contain any variables.', {trNoConstants} 'The units do not contain any constants.', {trNoFunctions} 'The units do not contain any functions or procedures.', {trNoIdentifiers} 'The units do not contain any identifiers.', //misc {trHelp} 'Help', {trLegend} 'Legend', {trMarker} 'Marker', {trWarningOverwrite} 'Warning: Do not edit - this file has been created automatically and is likely be overwritten', {trWarning} 'Warning', {trGeneratedBy} 'Generated by', {trGeneratedOn} 'Generated on', {trOnDateTime} 'on', {trSearch} 'Search', {trSeeAlso} 'See also', {trInternal} 'internal', {trAttributes} 'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Hungarian_1250.inc������������������������������������0000644�0001750�0001750�00000010137�13237143042�025214� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Hungarian', //map {trUnits} 'Egysgek', {trClassHierarchy} 'Osztly hierarchia', {trCio} 'Osztlyok, Kapcsoldsi felletek s Objektumok', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Azonostk', {trGvUses} 'Egysg fggsgi grf', {trGvClasses} 'Osztly hierarchia grf', //tables and members {trClasses} 'Osztlyok', {trClass} 'Osztly', {trDispInterface} 'Kperny felletek', {trInterface} 'Kapcsoldsi fellet', {trObjects} 'Objektumok', {trObject} 'Objektum', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Mezk', {trMethods} 'Metdusok', {trProperties} 'Tulajdonsgok', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Egysg', {trUses} strToDo, //'Uses', {trConstants} 'Konstansok', {trFunctionsAndProcedures} 'Fggvnyek s Eljrsok', {trTypes} 'Tpusok', {trType} 'Tpus', {trVariables} 'Vltozk', {trAuthors} 'Szerzk', {trAuthor} 'Szerz', {trCreated} 'Kszlt', {trLastModified} 'Utols mdosts', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paramterek', {trReturns} 'Visszatrsi rtkek', {trExceptionsRaised} 'Kivtelek kiemelse', {trExceptions} 'Kivtelek', {trException} strToDo, //'Exception', {trEnum} 'Felsorolsok', //visibilities {trVisibility} 'Lthatsg', {trPrivate} 'Privt', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Vdett', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Publikus', {trPublished} 'Publiklt', {trAutomated} 'Automatikus', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'ez az azonost rtk nlkli', {trPlatformSpecific} 'ez az azonost szksges nmely platform szmra', {trLibrarySpecific} 'ez az azonost szksges nmely library szmra', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'ttekints', {trIntroduction} 'Bevezet', {trConclusion} 'sszefoglal', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'sszes Osztly, Kapcsoldsi fellet s Objektumok', {trHeadlineConstants} 'sszes Kontans', {trHeadlineFunctionsAndProcedures} 'sszes Fggvny s Eljrs', {trHeadlineIdentifiers} 'sszes Azonost', {trHeadlineTypes} 'sszes Tpus', {trHeadlineUnits} 'sszes Egysg', {trHeadlineVariables} 'sszes Vltoz', {trSummaryCio} 'szefoglal az Osztlyokrl, Kapcsoldsi felletekrl s Objektumokrl', //column headings {trDeclaration} 'Deklarci', {trDescription} 'Megjegyzs', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nv', {trValues} 'rtkek', //empty {trNone} 'Nincs', {trNoCIOs} 'Az egysg nem tartalmaz osztlyt, interfszt, objektumot, vagy rekordot.', {trNoCIOsForHierarchy} 'Az egysg nem tartalmaz osztlyt, interfszt vagy objektumot.', {trNoTypes} 'Az egysg nem tartalmaz tpusokat', {trNoVariables} 'Az egysg nem tartalmaz vltozkat.', {trNoConstants} 'Az egysg nem tartalmaz konstansokat.', {trNoFunctions} 'Az egysg nem tartalmaz fggvnyeket vagy eljrsokat.', {trNoIdentifiers} 'Az egysg nem tartalmaz azonostkat.', //misc {trHelp} 'Sg', {trLegend} 'Trtnet', {trMarker} 'Jelz', {trWarningOverwrite} 'Vigyzat: Nem szerkesztend file - ez a file automatikusan kszlt, valsznleg fellrsra kerlne', {trWarning} 'Vigyzat', {trGeneratedBy} 'Ksztette', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} ' ', //none in Hungarian language {trSearch} 'Keress', {trSeeAlso} 'Lsd mg', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Dutch_1252.inc����������������������������������������0000644�0001750�0001750�00000010640�13237143042�024350� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Dutch', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Classes, interfaces and objecten', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} strToDo, //'Classes', {trClass} strToDo, //'Class', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objecten', {trObject} strToDo, //'Object', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Velden', {trMethods} strToDo, //'Methods', {trProperties} 'Eigenschappen', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Programma', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constanten', {trFunctionsAndProcedures} 'Functies en procedures', {trTypes} 'Typen', {trType} strToDo, //'Type', {trVariables} 'Variabelen', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Gemaakt', {trLastModified} 'Laatste wijziging', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Overzicht', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alle classes, interfaces en objecten', {trHeadlineConstants} 'Alle constanten', {trHeadlineFunctionsAndProcedures} 'Alle functies en procedures', {trHeadlineIdentifiers} 'Alle identifiers', {trHeadlineTypes} 'Alle typen', {trHeadlineUnits} 'Alle units', {trHeadlineVariables} 'Alle variabelen', {trSummaryCio} 'Overzicht van classes, interfaces & objecten', //column headings {trDeclaration} 'Declaratie', {trDescription} 'Omschrijving', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Naam', {trValues} strToDo, //'Values', //empty {trNone} 'Geen', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Waarschuwing, wijzig niets - dit bestand is automatisch gegenereerd en zal worden overschreven', {trWarning} 'Waarschuwing', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Indonesian_1252.inc�����������������������������������0000644�0001750�0001750�00000010563�13237143042�025374� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Indonesian', //map {trUnits} 'Unit', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Kelas, Interface, dan Objek', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Kelas', {trClass} 'Kelas', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objek', {trObject} 'Objek', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarki', {trFields} strToDo, //'Fields', {trMethods} strToDo, //'Methods', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strKeep, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanta', {trFunctionsAndProcedures} 'Fungsi dan Prosedur', {trTypes} 'Tipe Bentukan', {trType} 'Tipe Bentukan', {trVariables} 'Variabel', {trAuthors} 'Pembuat', {trAuthor} 'Pembuat', {trCreated} 'Dibuat', {trLastModified} 'Terakhir Dimodifikasi', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sekilas', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Semua Kelas, Interface, dan Objek', {trHeadlineConstants} 'Semua Konstanta', {trHeadlineFunctionsAndProcedures} 'Semua Fungsi dan Prosedur', {trHeadlineIdentifiers} 'Semua Identifier', {trHeadlineTypes} 'Semua Tipe Bentukan', {trHeadlineUnits} 'Semua Unit', {trHeadlineVariables} 'Semua Variabel', {trSummaryCio} 'Ringkasan Kelas, Interface, dan Objek', //column headings {trDeclaration} 'Deklarasi', {trDescription} 'Definisi', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nama', {trValues} strToDo, //'Values', //empty {trNone} 'Tidak Ada', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Bantuan', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Perhatian: Jangan dimodifikasi - ' + 'file ini dihasilkan secara otomatis dan mungkin saja ditimpa ulang', {trWarning} 'Perhatian', //? {trGeneratedBy} 'Dihasilkan oleh', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'pada', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Catalan_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000010617�13237143042�026002� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Catalan', //map {trUnits} 'Unitats', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Clases, interfaces i objectes', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadors', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Clases', {trClass} 'Clase', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objectes', {trObject} 'Objecte', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} strToDo, //'Hierarchy', {trFields} 'Camps', {trMethods} 'MŠtodes', {trProperties} 'Propietats', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Unitat', {trUses} strToDo, //'Uses', {trConstants} strToDo, //'Constants', {trFunctionsAndProcedures} 'Funcions i procediments', {trTypes} 'Tipus', {trType} 'Tipus', {trVariables} strToDo, //'Variables', {trAuthors} 'Autors', {trAuthor} 'Autor', {trCreated} 'Creat', {trLastModified} 'Éltima modificaci¢', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Resum', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Totes les clases, interfaces i objectes', {trHeadlineConstants} 'Totes les constants', {trHeadlineFunctionsAndProcedures} 'Totes les funcions i procediments', {trHeadlineIdentifiers} 'Tot els indentificadors', {trHeadlineTypes} 'Tots els tipus', {trHeadlineUnits} 'Totes les unitats', {trHeadlineVariables} 'Totes les variables', {trSummaryCio} 'Llista de clases, interfaces i objectes', //column headings {trDeclaration} 'Declaraci¢', {trDescription} 'Descripci¢', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} strToDo, //'Nom', {trValues} strToDo, //'Values', //empty {trNone} 'Ningu', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Atenci¢, no editar - aquest fitxer ha estat creat automaticament i ser… sobrescrit', {trWarning} 'Atenci¢', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �����������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Czech_iso_8859_2.inc����������������������������������0000644�0001750�0001750�00000010213�13237143042�025450� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ This is translation for Czech language. Pasted into separate file, to minimize chance of messing character codes (and also, to ease iconv call). PasDoc_Languages_Czech_ISO_8859_2.inc contains ISO-8859-2 version. PasDoc_Languages_Czech_CP1250.inc contans Windows CP1250 version, which should be automatically generated from *_ISO_8859_2.inc using iconv ("make PasDoc_Languages_Czech_CP1250.inc" in this dir takes care of that). } RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Czech', //map {trUnits} 'Unity', {trClassHierarchy} 'Hierarchie td', {trCio} 'Tdy, rozhran a objekty', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifiktory', {trGvUses} 'Graf zvislost unit', {trGvClasses} 'Graf zvislost td', //tables and members {trClasses} 'Tdy', {trClass} 'Tda', {trDispInterface} 'DispInterface', {trInterface} 'Rozhran', {trObjects} 'Objekty', {trObject} 'Objekt', {trRecord} strToDo, {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Poloky', {trMethods} 'Metody', {trProperties} 'Vlastnosti', {trLibrary} 'Knihovna', {trPackage} strToDo, {trProgram} 'Aplikace', {trUnit} 'Unita', {trUses} strToDo, {trConstants} 'Konstanty', {trFunctionsAndProcedures} 'Funkce a procedury', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Promnn', {trAuthors} 'Autoi', {trAuthor} 'Autor', {trCreated} 'Vytvoeno', {trLastModified} 'Posledn zmna', {trSubroutine} strToDo, {trParameters} 'Parametery', {trReturns} 'Vrac', {trExceptionsRaised} 'Vyhazuje vyjmku', {trExceptions} 'Vyjmky', {trExceptions} strToDo, {trEnum} 'Vtov typy', //visibilities {trVisibility} 'Viditelnost', {trPrivate} 'Private', {trStrictPrivate} 'Strict Private', {trProtected} 'Protected', {trStrictProtected} 'Strict Protected', {trPublic} 'Public', {trPublished} 'Published', {trAutomated} 'Automated', {trImplicit} 'Implicit', //hints {trDeprecated} 'tato konstrukce je zastaral (deprecated)', {trPlatformSpecific} 'tato konstrukce je zvisl na platform', {trLibrarySpecific} 'tato konstrukce je zvisl na konkrtn knihovn', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pehled', {trIntroduction} 'vod', {trConclusion} 'Zvr', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Vechny tdy, rozhran a objekty', {trHeadlineConstants} 'Seznam konstant', {trHeadlineFunctionsAndProcedures} 'Seznam funkc a procedur', {trHeadlineIdentifiers} 'Seznam identifiktor', {trHeadlineTypes} 'Seznam typ', {trHeadlineUnits} 'Seznam unit', {trHeadlineVariables} 'Seznam promnnch', {trSummaryCio} 'Seznam td, rozhran a objekt', //column headings {trDeclaration} 'Deklarace', {trDescription} 'Popis', {trDescriptions} strToDo, {trName} 'Nzev', {trValues} 'Hodnoty', //empty {trNone} 'Nic', {trNoCIOs} 'Unity neobsahuj dn tdy, rozhran, objekty nebo recordy.', {trNoCIOsForHierarchy} 'Unity neobsahuj dn tdy, rozhran nebo objekty.', {trNoTypes} 'Unity neobsahuj dn typy.', {trNoVariables} 'Unity neobsahuj dn promnn.', {trNoConstants} 'Unity neobsahuj dn konstanty.', {trNoFunctions} 'Unity neobsahuj dn funkce nebo procedury.', {trNoIdentifiers} 'Unity neobsahuj dn identifiktory.', //misc {trHelp} 'Npovda', {trLegend} 'Legenda', {trMarker} 'Znaka', {trWarningOverwrite} 'Varovn: Tento soubor nen uen k editaci. Byl automaticky vygenerovn a me bt opt pepsn.', {trWarning} 'Varovn', {trGeneratedBy} 'Vygenerovno pomoc', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'v', {trSearch} 'Hledat', {trSeeAlso} 'Viz tak', {trInternal} strToDo, //'internal', {trAttributes} 'Atributy', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Template_New_Language.inc�����������������������������0000644�0001750�0001750�00000013542�13237143042�027023� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(* New language template. To add a new language or encoding: 1) Copy this file (PasDoc_Languages_Template_New_Language.inc) into more approprate filename. 2) Add your language to PasDoc_Languages.pas array. See other languages for examples. You want to - add a new value to TLanguageID type, - define a const named aXxx, - and add a new row to LANGUAGE_ARRAY table describing your language. 3) Then, of course, do the actual translation :) Replace all occurences of strToDo by - your translation of the text in the comment, - or rename them into strKeep for all strings that need no translation, - or leave the strToDo in place, if you don't know the translation. For "normal" PasDoc builds, both strToDo and strKeep are equal (in fact, they are just empty strings) and mean "use the English version". The distinction between strToDo and strKeep is mainly for you, and other devs/translators, so that we know when you really want to show English version and when you just can't decide what is the proper translation. *) RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} strToDo, //<<<<<< replace with the name of the new language //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} strToDo, //'Classes, Interfaces, Objects and Records', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} strToDo, //'Classes', {trClass} strToDo, //'Class', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} strToDo, //'Objects', {trObject} strToDo, //'Object', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} strToDo, //'Hierarchy', {trFields} strToDo, //'Fields', {trMethods} strToDo, //'Methods', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} strToDo, //'Constants', {trFunctionsAndProcedures} strToDo, //'Functions and Procedures', {trTypes} strToDo, //'Types', {trType} strToDo, //'Type', {trVariables} strToDo, //'Variables', {trAuthors} strToDo, //'Authors', {trAuthor} strToDo, //'Author', {trCreated} strToDo, //'Created', {trLastModified} strToDo, //'Last Modified', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} strToDo, //'Overview', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} strToDo, //'All Classes, Interfaces, Objects and Records', {trHeadlineConstants} strToDo, //'All Constants', {trHeadlineFunctionsAndProcedures} strToDo, //'All Functions and Procedures', {trHeadlineIdentifiers} strToDo, //'All Identifiers', {trHeadlineTypes} strToDo, //'All Types', {trHeadlineUnits} strToDo, //'All Units', {trHeadlineVariables} strToDo, //'All Variables', {trSummaryCio} strToDo, //'Summary of Classes, Interfaces, Objects and Records', //column headings {trDeclaration} strToDo, //'Declaration', {trDescription} strToDo, //'Description', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} strToDo, //'Name', {trValues} strToDo, //'Values', //empty {trNone} strToDo, //'None', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} strToDo, //'Warning: Do not edit - this file has been created automatically and is likely be overwritten', {trWarning} strToDo, //'Warning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Dutch_utf8_bom.inc������������������������������������0000644�0001750�0001750�00000010643�13237143042�025505� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Dutch', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Classes, interfaces and objecten', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} strToDo, //'Classes', {trClass} strToDo, //'Class', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objecten', {trObject} strToDo, //'Object', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Velden', {trMethods} strToDo, //'Methods', {trProperties} 'Eigenschappen', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} 'Programma', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constanten', {trFunctionsAndProcedures} 'Functies en procedures', {trTypes} 'Typen', {trType} strToDo, //'Type', {trVariables} 'Variabelen', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Gemaakt', {trLastModified} 'Laatste wijziging', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Overzicht', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alle classes, interfaces en objecten', {trHeadlineConstants} 'Alle constanten', {trHeadlineFunctionsAndProcedures} 'Alle functies en procedures', {trHeadlineIdentifiers} 'Alle identifiers', {trHeadlineTypes} 'Alle typen', {trHeadlineUnits} 'Alle units', {trHeadlineVariables} 'Alle variabelen', {trSummaryCio} 'Overzicht van classes, interfaces & objecten', //column headings {trDeclaration} 'Declaratie', {trDescription} 'Omschrijving', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Naam', {trValues} strToDo, //'Values', //empty {trNone} 'Geen', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', {trLegend} strToDo, //'Legend', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Waarschuwing, wijzig niets - dit bestand is automatisch gegenereerd en zal worden overschreven', {trWarning} 'Waarschuwing', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Brasilian_1252.inc������������������������������������0000644�0001750�0001750�00000010521�13237143042�025203� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Brasilian', //map {trUnits} strToDo, //'Units', {trClassHierarchy} 'Hierarquia de Classes', {trCio} 'Classes, Interfaces, Objetos e Registros', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadores', {trGvUses} 'Diagrama de dependncias de units', {trGvClasses} 'Diagrama de hierarquia de Classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objetos', {trObject} 'Objeto', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarquia', {trFields} 'Campos', {trMethods} 'Mtodos', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Funes e Procedimentos', {trTypes} 'Tipos', {trType} 'Tipo', {trVariables} 'Variveis', {trAuthors} 'Autores', {trAuthor} 'Autor', {trCreated} 'Criada', {trLastModified} 'ltima modificao', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Parmetros', {trReturns} 'Retornos', //??? {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} 'Excees', {trException} strToDo, //'Exception', {trEnum} 'Enumeraes', //??? //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} 'este smbolo est depreciado', {trPlatformSpecific} 'este smbolo especfico para alguma plataforma', {trLibrarySpecific} 'este smbolo especfico para alguma biblioteca', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Viso Geral', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Todas as Classes, Interfaces, Objetos e Registros', {trHeadlineConstants} 'Todas as Constantes', {trHeadlineFunctionsAndProcedures} 'Todas as funes e procedimentos', {trHeadlineIdentifiers} 'Todos os Identificadores', {trHeadlineTypes} 'Todos os Tipos', {trHeadlineUnits} 'Todas as Units', {trHeadlineVariables} 'Todas as Variveis', {trSummaryCio} 'Lista das Classes, Interfaces, Objetos e Registros', //column headings {trDeclaration} 'Declarao', {trDescription} 'Descrio', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nome', {trValues} strToDo, //'Values', //empty {trNone} 'Nenhum', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Ajuda', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Aviso, no altere - este arquivo foi gerado automaticamente e ser sobrescrito', {trWarning} strToDo, //'Warning', {trGeneratedBy} 'Gerado por', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'as', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Javanese_1250.inc�������������������������������������0000644�0001750�0001750�00000010545�13237143042�025037� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Javanese', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Kelas, Interface, lan Objek', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Kelas', {trClass} 'Kelas', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objek', {trObject} 'Objek', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarki', {trFields} strToDo, //'Fields', {trMethods} strToDo, //'Methods', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanta', {trFunctionsAndProcedures} 'Fungsi lan Prosedur', {trTypes} 'Macem Gawean', {trType} 'Macem Gawean', {trVariables} 'Variabel', {trAuthors} 'Sing Nggawe', {trAuthor} 'Sing Nggawe', {trCreated} 'Digawe', {trLastModified} 'Terakhir Diowahi', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pambuka', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Kabeh Kelas, Interface, lan Objek', {trHeadlineConstants} 'Kabeh Konstanta', {trHeadlineFunctionsAndProcedures} 'Kabeh Fungsi lan Prosedur', {trHeadlineIdentifiers} 'Kabeh Identifier', {trHeadlineTypes} 'Kabeh Macem Gawean', {trHeadlineUnits} 'Kabeh Unit', {trHeadlineVariables} 'Kabeh Variabel', {trSummaryCio} 'Ringkesan Kelas, Interface, lan Objek', //column headings {trDeclaration} 'Deklarasi', {trDescription} 'Katrangan', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Jeneng', {trValues} strToDo, //'Values', //empty {trNone} 'Mboten Wonten', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Tulung', {trLegend} 'Katrangan', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Ati-ati: Ojo diowahi - ' + 'file iki digawe otomatis dadi iso ilang owahanmu', {trWarning} 'Ati-ati', //? {trGeneratedBy} 'Dihasilne karo', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'ing', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �����������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Swedish_1252.inc��������������������������������������0000644�0001750�0001750�00000010740�13237143042�024710� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Swedish', //map {trUnits} 'Enheter', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Klasser, interface och objekt', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klasser', {trClass} 'Klass', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objekt', //-er ??? {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarki', {trFields} 'Flt', //-er ??? {trMethods} 'Metoder', {trProperties} strToDo, //'Properties', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Enhet', {trUses} strToDo, //'Uses', {trConstants} strToDo, //'Constants', {trFunctionsAndProcedures} strToDo, //'Functions and Procedures', {trTypes} 'Typer', {trType} 'Typer', {trVariables} 'Variabler', {trAuthors} 'Frfattare', {trAuthor} 'Frfattare', {trCreated} 'Skapad', {trLastModified} 'Senast ndrad', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Se parameter', {trReturns} 'Retur', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'versikt', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alla klasser, interface och objekt', {trHeadlineConstants} strToDo, //'All Constants', {trHeadlineFunctionsAndProcedures} 'Alla funktioner och procedurer', {trHeadlineIdentifiers} 'Alla identifierare', {trHeadlineTypes} 'Alla typer', {trHeadlineUnits} 'Alla enheter', {trHeadlineVariables} 'Alla variabler', {trSummaryCio} 'Sammanfattning av Klasser, Interface, Objekt', //column headings {trDeclaration} 'Deklarationer', {trDescription} 'Beskrivning', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Namn', {trValues} strToDo, //'Values', //empty {trNone} 'Ingen/inget.', //??? {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} strToDo, //'Help', // Untranslated to avoid Swedish file name for css {trLegend} 'Frklaring', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Varning: ndra inte denna fil manuellt - filen har skapats automatiskt och kommer troligen att skrivas ver vid ett senare tilflle', {trWarning} 'Varning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������pasdoc/source/component/lang/PasDoc_Languages_Croatia_1250.inc��������������������������������������0000644�0001750�0001750�00000007415�13237143042�024667� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<to?>', //no ID assigned, so far {trLanguage} 'Hrvatski', //map {trUnits} 'Datoteke', {trClassHierarchy} 'Klasna hijerarhija', {trCio} 'Klase, Suelja i Objekti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikatori', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klase', {trClass} 'Klasa', {trDispInterface} strToDo, {trInterface} 'Suelje', {trObjects} 'Objekti', {trObject} 'Objekt', {trRecord} strToDo, {trPacked} strToDo, //'Packed', {trHierarchy} 'Hijerarhija', {trFields} 'Polja', {trMethods} 'Metode', {trProperties} 'Osobine', {trLibrary} strToDo, {trPackage} strToDo, {trProgram} strToDo, {trUnit} 'Datoteka', {trUses} strToDo, {trConstants} 'Konstante', {trFunctionsAndProcedures} 'Funkcije i Procedure', {trTypes} 'Tipovi', {trType} 'Tip', {trVariables} 'Varijable', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Kreirano', {trLastModified} 'Zadnja promjena', {trSubroutine} strToDo, {trParameters} 'Parametri', {trReturns} 'Vraa', {trExceptionsRaised} strToDo, {trExceptions} strToDo, {trException} strToDo, {trEnum} strToDo, //visibilities {trVisibility} 'Vidljivost', {trPrivate} strToDo, {trStrictPrivate} strToDo, {trProtected} strToDo, {trStrictProtected} strToDo, {trPublic} strToDo, {trPublished} strToDo, {trAutomated} strToDo, {trImplicit} strToDo, //hints {trDeprecated} 'Ovaj simbol je zastario', {trPlatformSpecific} 'Ovaj simbol je specifian za neke platforme', {trLibrarySpecific} 'Ovaj simbol je specifian za neke biblioteke', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pregled', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Sve Klase, Suelja i Objekti', {trHeadlineConstants} 'Sve Konstante', {trHeadlineFunctionsAndProcedures} 'Sve Funkcije i Procedure', {trHeadlineIdentifiers} 'Svi Identifikatoti', {trHeadlineTypes} 'Svi Tipovi', {trHeadlineUnits} 'Sve Datoteke', {trHeadlineVariables} 'Sve Varijable', {trSummaryCio} 'Ukupno od Klasa, Interfejsa i Objekata', //column headings {trDeclaration} 'Deklaracija', {trDescription} 'Opis', {trDescriptions} 'Detaljni opis', {trName} 'Ime', {trValues} 'Vrijednosti', //'Values', //empty {trNone} 'Nita', {trNoCIOs} 'Datoteka ne sadri klase, suelja, objekte ili zapise.', {trNoCIOsForHierarchy} 'Datoteke ne sadre klase, suelja, objekte ili zapise.', {trNoTypes} 'Datoteke ne sadre tipove.', {trNoVariables} 'Datoteke ne sadre varijable.', {trNoConstants} 'Datoteke ne sadre konstante.', {trNoFunctions} 'Datoteke ne sadre funkcije ili procedure.', {trNoIdentifiers} 'Datoteke ne sadre indentifikatore.', //misc {trHelp} 'Pomo', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozorenje: Ne mjenjajte ovu datoteku - kreirana je automatski i velika je mogunost da e biti prepisana', {trWarning} 'Upozorenje', //'Warning', {trGeneratedBy} 'Generirano od', //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} 'Trai', //'Search', {trSeeAlso} 'Vidi jo', {trInternal} 'interno', //'internal', {trAttributes} 'Atributi', //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Spanish_1252.inc��������������������������������������0000644�0001750�0001750�00000010714�13237143042�024710� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Spanish', //map {trUnits} 'Unidades', {trClassHierarchy} 'Jerarqua de clases', {trCio} 'Clases, interfaces y objetos', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificadores', {trGvUses} 'Grfico de dependencias de unidades', // {trGvClasses} 'Grfico de jerarqua de clases', // //tables and members {trClasses} 'Clases', {trClass} 'Clase', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfaz', //'Interface', {trObjects} 'Objetos', {trObject} 'Objeto', {trRecord} 'Registro', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Jerarqua', {trFields} 'Campos', {trMethods} 'Mtodos', {trProperties} 'Propiedades', {trLibrary} 'Biblioteca', //'Library', {trPackage} 'Paquete', //'Package', {trProgram} 'Programa', //'Program', {trUnit} 'Unidad', {trUses} 'Unidades', //'Uses', I may use "Unidades utilizadas/referenciadas" (Used/referenced units). {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Funciones y procedimientos', {trTypes} 'Tipos', {trType} 'Tipo', {trVariables} 'Variables', //'Variables', {trAuthors} 'Autores', {trAuthor} 'Autor', {trCreated} 'Creado', {trLastModified} 'ltima modificacin', {trSubroutine} 'Subrutina', //'Subroutine', {trParameters} 'Parmetros', {trReturns} 'Retorno', //strToDo??? solo uno! {trExceptionsRaised} 'Excepciones lanzadas', {trExceptions} 'Excepciones', {trException} 'Excepcin', // {trEnum} 'Enumeracin', //'Enumeration', //visibilities {trVisibility} 'Visibilidad', {trPrivate} 'Privado', //'Private', {trStrictPrivate} 'Estrictamente privado', //'Strict Private', {trProtected} 'Protegido', //? {trStrictProtected} 'Estrictamente protegido', //'Strict Protected', {trPublic} 'Pblico', //'Public', {trPublished} strToDo, //'Published', I would keep that because "Published" is also "Pblico" in this context (IDE). {trAutomated} 'Automtico', //'Automated', {trImplicit} 'Implcito', //'Implicit', //hints {trDeprecated} 'Este smbolo es obsoleto', // {trPlatformSpecific} 'Este smbolo es especfico para alguna plataforma', {trLibrarySpecific} 'Este smbolo es especfico para alguna biblioteca', // {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Resumen', {trIntroduction} 'Introduccin', {trConclusion} 'Conclusin', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Todas las clases, interfaces y objetos', {trHeadlineConstants} 'Todas las constantes', {trHeadlineFunctionsAndProcedures} 'Todos las funciones y procedimientos', {trHeadlineIdentifiers} 'Todos los indentificadores', {trHeadlineTypes} 'Todos los tipos', {trHeadlineUnits} 'Todas las unidades', {trHeadlineVariables} 'Todas las variables', {trSummaryCio} 'Lista de clases, interfaces y objetos', //column headings {trDeclaration} 'Declaracin', {trDescription} 'Descripcin', {trDescriptions} 'Descripcin detallada', //? 'Descriptions', 'Detailed Descriptions'? {trName} 'Nombre', {trValues} 'Valores', //empty {trNone} 'Ninguno', {trNoCIOs} 'Las unidades no contienen clases, interfaces, objetos ni registros.', {trNoCIOsForHierarchy} 'Las unidades no contienen clases, interfaces ni objetos.', {trNoTypes} 'Las unidades no contienen tipo alguno.', {trNoVariables} 'Las unidades no contienen ninguna variable.', // {trNoConstants} 'Las unidades no contienen ninguna constante.', // {trNoFunctions} 'Las unidades no contienen funciones ni procedimientos', // {trNoIdentifiers} 'Las unidades no contienen identificadores.', //misc {trHelp} 'Ayuda', {trLegend} 'Leyenda', {trMarker} 'Marcador', {trWarningOverwrite} 'Atencin, no editar - este fichero ha sido creado automaticamente y puede ser sobrescrito', {trWarning} 'Atencin', {trGeneratedBy} 'Generado por', //??? strToDo, //'Generador por', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'a', {trSearch} 'Buscar', {trSeeAlso} 'Ver tambin', // ? {trInternal} 'interno', //'internal', {trAttributes} 'Atributos', //'Attributes', '' //dummy ); ����������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Danish_1252.inc���������������������������������������0000644�0001750�0001750�00000010564�13237143042�024514� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Danish', //map {trUnits} strToDo, //'Units', {trClassHierarchy} strToDo, //'Class Hierarchy', {trCio} 'Klasser, interfaces og objekter', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} strToDo, //'Identifiers', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klasser', {trClass} 'Klasse', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objekter', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Herarki', {trFields} 'Felter', {trMethods} 'Metoder', {trProperties} 'Egenskaber', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} strToDo, //'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Konstanter', {trFunctionsAndProcedures} 'Funktioner og prosedurer', {trTypes} 'Typer', {trType} strToDo, //'Type', {trVariables} 'Variable', {trAuthors} 'Forfatre', {trAuthor} 'Forfatter', {trCreated} 'Udfrt', {trLastModified} 'Sidst Modificieret', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Sammendrag', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Alle Klasesr, Interfaces og Objekter', {trHeadlineConstants} 'Alle Konstanter', {trHeadlineFunctionsAndProcedures} 'Alle Functioner and Procedurer', {trHeadlineIdentifiers} 'Alle Identifiers', {trHeadlineTypes} 'Alle Typer', {trHeadlineUnits} 'Alle Units', {trHeadlineVariables} 'Alle Variable', {trSummaryCio} 'Oversigt over klasser, interfaces & objekter', //column headings {trDeclaration} strToDo, //'Declaration', {trDescription} 'Beskrivelse', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Navn', {trValues} strToDo, //'Values', //empty {trNone} 'Ingen', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Hjlp', {trLegend} 'Legende', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Advarsel: Editer ikke denne fil, den er autogeneret og vil sansylgvis blive overskret', {trWarning} strToDo, //'Warning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Czech_utf8_bom.inc������������������������������������0000644�0001750�0001750�00000010401�13237143042�025462� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ This is translation for Czech language. Pasted into separate file, to minimize chance of messing character codes (and also, to ease iconv call). PasDoc_Languages_Czech_ISO_8859_2.inc contains ISO-8859-2 version. PasDoc_Languages_Czech_CP1250.inc contans Windows CP1250 version, which should be automatically generated from *_ISO_8859_2.inc using iconv ("make PasDoc_Languages_Czech_CP1250.inc" in this dir takes care of that). } RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Czech', //map {trUnits} 'Unity', {trClassHierarchy} 'Hierarchie tříd', {trCio} 'Třídy, rozhraní a objekty', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikátory', {trGvUses} 'Graf závislostí unit', {trGvClasses} 'Graf závislostí tříd', //tables and members {trClasses} 'Třídy', {trClass} 'Třída', {trDispInterface} 'DispInterface', {trInterface} 'Rozhraní', {trObjects} 'Objekty', {trObject} 'Objekt', {trRecord} strToDo, {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Položky', {trMethods} 'Metody', {trProperties} 'Vlastnosti', {trLibrary} 'Knihovna', {trPackage} strToDo, {trProgram} 'Aplikace', {trUnit} 'Unita', {trUses} strToDo, {trConstants} 'Konstanty', {trFunctionsAndProcedures} 'Funkce a procedury', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Proměnné', {trAuthors} 'Autoři', {trAuthor} 'Autor', {trCreated} 'Vytvořeno', {trLastModified} 'Poslední změna', {trSubroutine} strToDo, {trParameters} 'Parametery', {trReturns} 'Vrací', {trExceptionsRaised} 'Vyhazuje vyjímku', {trExceptions} 'Vyjímky', {trExceptions} strToDo, {trEnum} 'Výčtové typy', //visibilities {trVisibility} 'Viditelnost', {trPrivate} 'Private', {trStrictPrivate} 'Strict Private', {trProtected} 'Protected', {trStrictProtected} 'Strict Protected', {trPublic} 'Public', {trPublished} 'Published', {trAutomated} 'Automated', {trImplicit} 'Implicit', //hints {trDeprecated} 'tato konstrukce je zastaralá (deprecated)', {trPlatformSpecific} 'tato konstrukce je závislá na platformě', {trLibrarySpecific} 'tato konstrukce je závislá na konkrétní knihovně', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Přehled', {trIntroduction} 'Úvod', {trConclusion} 'Závěr', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Všechny třídy, rozhraní a objekty', {trHeadlineConstants} 'Seznam konstant', {trHeadlineFunctionsAndProcedures} 'Seznam funkcí a procedur', {trHeadlineIdentifiers} 'Seznam identifikátorů', {trHeadlineTypes} 'Seznam typů', {trHeadlineUnits} 'Seznam unit', {trHeadlineVariables} 'Seznam proměnných', {trSummaryCio} 'Seznam tříd, rozhraní a objektů', //column headings {trDeclaration} 'Deklarace', {trDescription} 'Popis', {trDescriptions} strToDo, {trName} 'Název', {trValues} 'Hodnoty', //empty {trNone} 'Nic', {trNoCIOs} 'Unity neobsahují žádné třídy, rozhraní, objekty nebo recordy.', {trNoCIOsForHierarchy} 'Unity neobsahují žádné třídy, rozhraní nebo objekty.', {trNoTypes} 'Unity neobsahují žádné typy.', {trNoVariables} 'Unity neobsahují žádné proměnné.', {trNoConstants} 'Unity neobsahují žádné konstanty.', {trNoFunctions} 'Unity neobsahují žádné funkce nebo procedury.', {trNoIdentifiers} 'Unity neobsahují žádné identifikátory.', //misc {trHelp} 'Nápověda', {trLegend} 'Legenda', {trMarker} 'Značka', {trWarningOverwrite} 'Varování: Tento soubor není učený k editaci. Byl automaticky vygenerován a může být opět přepsán.', {trWarning} 'Varování', {trGeneratedBy} 'Vygenerováno pomocí', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'v', {trSearch} 'Hledat', {trSeeAlso} 'Viz také', {trInternal} strToDo, //'internal', {trAttributes} 'Atributy', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Polish_iso_8859_2.inc���������������������������������0000644�0001750�0001750�00000007764�13237143042�025673� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Polish', //map {trUnits} 'Moduy', {trClassHierarchy} 'Hierarchia klas', {trCio} 'Klasy, interfejsy, obiekty i rekordy', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identyfikatory', {trGvUses} 'Graf zalenoci moduw', {trGvClasses} 'Graf dziedziczenia klas', //tables and members {trClasses} 'Klasy', {trClass} 'Klasa', {trDispInterface} 'DispInterface', //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Obiekty', {trObject} 'Obiekt', {trRecord} 'Rekord', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchia', {trFields} 'Pola', {trMethods} 'Metody', {trProperties} 'Waciwoci', {trLibrary} 'Biblioteka', //'Library', {trPackage} 'Pakiet', //'Package', {trProgram} 'Program', //'Program', {trUnit} 'Modu', {trUses} 'Uywa', //'Uses', {trConstants} 'Stae', {trFunctionsAndProcedures} 'Podprogramy', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Zmienne', {trAuthors} 'Autorzy', {trAuthor} 'Autor', {trCreated} 'Utworzony', {trLastModified} 'Ostatnia modyfikacja', {trSubroutine} 'Podprogram', {trParameters} 'Parametry', {trReturns} 'Wynik', {trExceptionsRaised} 'Generowane wyjtki', {trExceptions} 'Wyjtki', {trException} 'Wyjtek', {trEnum} 'Wyliczenie', //visibilities {trVisibility} 'Widoczno', {trPrivate} 'Prywatne', {trStrictPrivate} 'cile prywatne', //'Strict Private', {trProtected} 'Chronione', {trStrictProtected} 'cile chronione', //'Strict Protected', {trPublic} 'Publiczne', {trPublished} 'Publikowane', {trAutomated} 'Automated', //'Automated', {trImplicit} 'Domylne', //hints {trDeprecated} 'odradza si uywania tego identyfikatora', {trPlatformSpecific} 'ten identyfikator jest zaleny od platformy', {trLibrarySpecific} 'ten identyfikator jest zaleny od biblioteki', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Przegld', {trIntroduction} 'Wstp', {trConclusion} 'Podsumowanie', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Wszystkie klasy, interfejsy, obiekty i rekordy', {trHeadlineConstants} 'Wszystkie stae', {trHeadlineFunctionsAndProcedures} 'Wszystkie podprogramy', {trHeadlineIdentifiers} 'Wszystkie identyfikatory', {trHeadlineTypes} 'Wszystkie typy', {trHeadlineUnits} 'Wszystkie moduy', {trHeadlineVariables} 'Wszystkie zmienne', {trSummaryCio} 'Podsumowanie klas, interfejsw, obiektw i rekordw', //column headings {trDeclaration} 'Deklaracja', {trDescription} 'Opis', {trDescriptions} 'Szczegy', //'Descriptions', 'Detailed Descriptions'? {trName} 'Nazwa', {trValues} 'Wartoci', //empty {trNone} 'Brak', {trNoCIOs} 'Modu nie zawiera adnych klas, interfejsw, obiektw ani rekordw.', {trNoCIOsForHierarchy} 'Modu nie zawiera adnych klas, interfejsw ani obiektw.', {trNoTypes} 'Modu nie zawiera adnych typw.', {trNoVariables} 'Modu nie zawiera adnych zmiennych.', {trNoConstants} 'Modu nie zawiera adnych staych.', {trNoFunctions} 'Modu nie zawiera adnych funkcji ani podprogramw.', {trNoIdentifiers} 'Modu nie zawiera adnych identyfikatorw.', //misc {trHelp} 'Pomoc', {trLegend} 'Legenda', {trMarker} 'Kolor', {trWarningOverwrite} 'Uwaga, nie modyfikuj - ten plik zosta wygenerowany automatycznie i moe zosta nadpisany', {trWarning} 'Uwaga', {trGeneratedBy} 'Wygenerowane przez', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} ' - ', {trSearch} 'Szukaj', {trSeeAlso} 'Zobacz take', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ������������pasdoc/source/component/lang/PasDoc_Languages_Czech_1250.inc����������������������������������������0000644�0001750�0001750�00000010213�13237143042�024327� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ This is translation for Czech language. Pasted into separate file, to minimize chance of messing character codes (and also, to ease iconv call). PasDoc_Languages_Czech_ISO_8859_2.inc contains ISO-8859-2 version. PasDoc_Languages_Czech_CP1250.inc contans Windows CP1250 version, which should be automatically generated from *_ISO_8859_2.inc using iconv ("make PasDoc_Languages_Czech_CP1250.inc" in this dir takes care of that). } RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Czech', //map {trUnits} 'Unity', {trClassHierarchy} 'Hierarchie td', {trCio} 'Tdy, rozhran a objekty', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifiktory', {trGvUses} 'Graf zvislost unit', {trGvClasses} 'Graf zvislost td', //tables and members {trClasses} 'Tdy', {trClass} 'Tda', {trDispInterface} 'DispInterface', {trInterface} 'Rozhran', {trObjects} 'Objekty', {trObject} 'Objekt', {trRecord} strToDo, {trPacked} strToDo, //'Packed', {trHierarchy} 'Hierarchie', {trFields} 'Poloky', {trMethods} 'Metody', {trProperties} 'Vlastnosti', {trLibrary} 'Knihovna', {trPackage} strToDo, {trProgram} 'Aplikace', {trUnit} 'Unita', {trUses} strToDo, {trConstants} 'Konstanty', {trFunctionsAndProcedures} 'Funkce a procedury', {trTypes} 'Typy', {trType} 'Typ', {trVariables} 'Promnn', {trAuthors} 'Autoi', {trAuthor} 'Autor', {trCreated} 'Vytvoeno', {trLastModified} 'Posledn zmna', {trSubroutine} strToDo, {trParameters} 'Parametery', {trReturns} 'Vrac', {trExceptionsRaised} 'Vyhazuje vyjmku', {trExceptions} 'Vyjmky', {trExceptions} strToDo, {trEnum} 'Vtov typy', //visibilities {trVisibility} 'Viditelnost', {trPrivate} 'Private', {trStrictPrivate} 'Strict Private', {trProtected} 'Protected', {trStrictProtected} 'Strict Protected', {trPublic} 'Public', {trPublished} 'Published', {trAutomated} 'Automated', {trImplicit} 'Implicit', //hints {trDeprecated} 'tato konstrukce je zastaral (deprecated)', {trPlatformSpecific} 'tato konstrukce je zvisl na platform', {trLibrarySpecific} 'tato konstrukce je zvisl na konkrtn knihovn', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pehled', {trIntroduction} 'vod', {trConclusion} 'Zvr', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Vechny tdy, rozhran a objekty', {trHeadlineConstants} 'Seznam konstant', {trHeadlineFunctionsAndProcedures} 'Seznam funkc a procedur', {trHeadlineIdentifiers} 'Seznam identifiktor', {trHeadlineTypes} 'Seznam typ', {trHeadlineUnits} 'Seznam unit', {trHeadlineVariables} 'Seznam promnnch', {trSummaryCio} 'Seznam td, rozhran a objekt', //column headings {trDeclaration} 'Deklarace', {trDescription} 'Popis', {trDescriptions} strToDo, {trName} 'Nzev', {trValues} 'Hodnoty', //empty {trNone} 'Nic', {trNoCIOs} 'Unity neobsahuj dn tdy, rozhran, objekty nebo recordy.', {trNoCIOsForHierarchy} 'Unity neobsahuj dn tdy, rozhran nebo objekty.', {trNoTypes} 'Unity neobsahuj dn typy.', {trNoVariables} 'Unity neobsahuj dn promnn.', {trNoConstants} 'Unity neobsahuj dn konstanty.', {trNoFunctions} 'Unity neobsahuj dn funkce nebo procedury.', {trNoIdentifiers} 'Unity neobsahuj dn identifiktory.', //misc {trHelp} 'Npovda', {trLegend} 'Legenda', {trMarker} 'Znaka', {trWarningOverwrite} 'Varovn: Tento soubor nen uen k editaci. Byl automaticky vygenerovn a me bt opt pepsn.', {trWarning} 'Varovn', {trGeneratedBy} 'Vygenerovno pomoc', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'v', {trSearch} 'Hledat', {trSeeAlso} 'Viz tak', {trInternal} strToDo, //'internal', {trAttributes} 'Atributy', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Bosnia_utf8_bom.inc�����������������������������������0000644�0001750�0001750�00000010367�13237143042�025654� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Bosnian', //map {trUnits} 'Fajlovi', {trClassHierarchy} 'Klasna hijerarhija', {trCio} 'Klase, Interfejsi i Objekti', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identifikatori', {trGvUses} strToDo, //'Unit dependency graph', {trGvClasses} strToDo, //'Classes hierarchy graph', //tables and members {trClasses} 'Klase', {trClass} 'Klasa', {trDispInterface} strToDo, //'DispInterface', {trInterface} 'Interfejs', {trObjects} 'Objekti', {trObject} 'Objekt', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hijerarhija', {trFields} 'Polja', {trMethods} 'Metode', {trProperties} 'Osibine', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} strToDo, //'Program', {trUnit} 'Fajl', {trUses} strToDo, //'Uses', {trConstants} 'Konstante', {trFunctionsAndProcedures} 'Funkcije i Procedure', {trTypes} 'Tipovi', {trType} 'Tip', {trVariables} 'Promjenjive', {trAuthors} 'Autori', {trAuthor} 'Autor', {trCreated} 'Kreirano', {trLastModified} 'Zadnja promjena', {trSubroutine} strToDo, //'Subroutine', {trParameters} strToDo, //'Parameters', {trReturns} strToDo, //'Returns', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} strToDo, //'Visibility', {trPrivate} 'Privatni', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} 'Zaštićen', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} 'Publikovan', {trPublished} 'Javan', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} strToDo, //'this symbol is deprecated', {trPlatformSpecific} strToDo, //'this symbol is specific to some platform', {trLibrarySpecific} strToDo, //'this symbol is specific to some library', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Pregled', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Sve Klase, Interfejsi i Objekti', {trHeadlineConstants} 'Sve Konstante', {trHeadlineFunctionsAndProcedures} 'Sve Funkcije i Procedure', {trHeadlineIdentifiers} 'Svi Identifikatoti', {trHeadlineTypes} 'Svi Tipovi', {trHeadlineUnits} 'Svi Fajlovi', {trHeadlineVariables} 'Sve Varijable', {trSummaryCio} 'Zbirno od Klasa, Interfejsa i Objekata', //column headings {trDeclaration} 'Deklaracija', {trDescription} 'Opis', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Ime', {trValues} strToDo, //'Values', //empty {trNone} 'Ništa', {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Pomoć', {trLegend} 'Legenda', {trMarker} strToDo, //'Marker', {trWarningOverwrite} 'Upozorenje: Ne mjenjajte fajl - ovaj fajl je kreiran automatski i velika je vjerovatnoća da će biti prepisan', {trWarning} strToDo, //'Warning', {trGeneratedBy} strToDo, //'Generated by', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} strToDo, //'on', {trSearch} strToDo, //'Search', {trSeeAlso} strToDo, //'See also', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/Makefile���������������������������������������������������������������0000600�0001750�0001750�00000000550�13034465544�020356� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Generate automatic translation files (convert encodings). # The plan is to automatically make here as much as possible. ALL_OUTPUT := PasDoc_Languages_Czech_1250.inc .PHONY: all clean all: $(ALL_OUTPUT) clean: rm -f $(ALL_OUTPUT) PasDoc_Languages_Czech_1250.inc: PasDoc_Languages_Czech_iso_8859_2.inc iconv --from ISO_8859-2 --to WINDOWS-1250 < $< > $@ ��������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_French_ISO_8859_15.inc��������������������������������0000644�0001750�0001750�00000010402�13237143042�025545� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'French', //map {trUnits} 'Units', {trClassHierarchy} 'Hirarchie des classes', {trCio} 'Classes, interfaces, enregistrements et objets', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificateurs', {trGvUses} 'Graphe de dpendance d''units', {trGvClasses} 'Graphe de hirarchie des classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strKeep, //'Interface', {trObjects} 'Objets', {trObject} 'Objet', {trRecord} 'Enregistrement', //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarchie', {trFields} 'Champs', {trMethods} 'Mthodes', {trProperties} 'Proprits', {trLibrary} 'Bibliothque', //? {trPackage} 'Paquet', //'Package', {trProgram} 'Logiciel', //? 'Program', {trUnit} 'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Fonctions et procdures', {trTypes} strKeep, //'Types', {trType} strKeep, //'Type', {trVariables} strKeep, //'Variables', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Cre', {trLastModified} 'Dernire modification', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paramtres', {trReturns} 'Retourne', {trExceptionsRaised} 'Exception leves', //'Exceptions raised', {trExceptions} strKeep, //'Exceptions', {trException} strKeep, //'Exception', {trEnum} 'numration', //'Enumeration', //visibilities {trVisibility} 'Visibilit', {trPrivate} 'Priv', {trStrictPrivate} 'Strictement Priv', //? {trProtected} 'Protg', {trStrictProtected} 'Strictement Protg', //? {trPublic} strKeep, //'Public', {trPublished} 'Publis', {trAutomated} 'Automatis', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'ce symbole est dsapprouv', {trPlatformSpecific} 'ce symbole est spcifique une plateforme d''excution', {trLibrarySpecific} 'ce symbole est spcifique une certaine bibliothque', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Aperu', {trIntroduction} strKeep, //'Introduction', {trConclusion} strKeep, //'Conclusion', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} 'Toutes les classes, interfaces, objets et enregistrements', {trHeadlineConstants} 'Toutes les constants', {trHeadlineFunctionsAndProcedures} 'Toutes les fonctions et procdures', {trHeadlineIdentifiers} 'Tous les identificateurs', {trHeadlineTypes} 'Tous les types', {trHeadlineUnits} 'Toutes les units', {trHeadlineVariables} 'Toutes les variables', {trSummaryCio} 'Classes, interfaces, objets et enregistrements', //column headings {trDeclaration} 'Dclaration', {trDescription} strKeep, //'Description', {trDescriptions} strKeep, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nom', {trValues} 'Valeurs', //? //empty {trNone} 'Aucun(e)(s)', //'Rien'? {trNoCIOs} 'L''unit ne contient ni classe, ni interface, ni objets, ni enregistrement.', {trNoCIOsForHierarchy} 'L''unit ne contient ni classe, ni interface, ni objets.', {trNoTypes} 'L''unit ne contient aucun type.', {trNoVariables} 'L''unit ne contient aucune variable.', {trNoConstants} 'L''unit ne contient aucune constante.', {trNoFunctions} 'L''unit ne contient ni fonction ni procdure.', {trNoIdentifiers} 'L''unit ne contient aucun indentificateur.', //misc {trHelp} 'Aide', {trLegend} 'Lgende', {trMarker} 'Marquage', {trWarningOverwrite} 'Attention, ne pas diter - ce fichier est cr automatiquement et va tre cras', {trWarning} 'Attention', {trGeneratedBy} 'Produit par', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'le', {trSearch} 'Cherche', //? 'Recherche' {trSeeAlso} 'Voir aussi', //? {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Russian_1251.inc��������������������������������������0000644�0001750�0001750�00000010143�13237143042�024722� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Russian', //map {trUnits} '', {trClassHierarchy} ' ', {trCio} ', ', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} '', {trGvUses} ' ', {trGvClasses} ' ', //tables and members {trClasses} '', {trClass} '', {trDispInterface} strToDo, //'DispInterface', {trInterface} '', {trObjects} '', {trObject} '', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} '', {trFields} '', {trMethods} '', {trProperties} '', {trLibrary} strToDo, //'Library', {trPackage} strToDo, //'Package', {trProgram} '', {trUnit} '', {trUses} ' ', {trConstants} '', {trFunctionsAndProcedures} ' ', {trTypes} '', {trType} '', {trVariables} '', {trAuthors} '', {trAuthor} '', {trCreated} '', {trLastModified} ' ', {trSubroutine} strToDo, //'Subroutine', {trParameters} '', {trReturns} ' ', {trExceptionsRaised} ' ', {trExceptions} '', {trException} strToDo, //'Exception', {trEnum} '', //visibilities {trVisibility} ' ', {trPrivate} strToDo, //'Private', {trStrictPrivate} strToDo, //'Strict Private', {trProtected} strToDo, //'Protected', {trStrictProtected} strToDo, //'Strict Protected', {trPublic} strToDo, //'Public', {trPublished} strToDo, //'Published', {trAutomated} strToDo, //'Automated', {trImplicit} strToDo, //'Implicit', //hints {trDeprecated} ' ', {trPlatformSpecific} ' ', {trLibrarySpecific} ' ', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} '', {trIntroduction} '', {trConclusion} '', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} ' , ', {trHeadlineConstants} ' ', {trHeadlineFunctionsAndProcedures} ' ', {trHeadlineIdentifiers} ' ', {trHeadlineTypes} ' ', {trHeadlineUnits} ' ', {trHeadlineVariables} ' ', {trSummaryCio} ' , ', //column headings {trDeclaration} '', {trDescription} '', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} '', {trValues} '', //empty {trNone} '', {trNoCIOs} ' , , .', {trNoCIOsForHierarchy} ' , .', {trNoTypes} ' .', {trNoVariables} ' .', {trNoConstants} ' .', {trNoFunctions} ' .', {trNoIdentifiers} ' .', //misc {trHelp} strKeep, //'Help', // Untranslated to avoid Russian file name for css { TODO : how does "Help" interfere with file names? } {trLegend} '', {trMarker} '', {trWarningOverwrite} ': - ', {trWarning} '', {trGeneratedBy} '', // + ' '? {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} '/', //really??? {trSearch} '', {trSeeAlso} ' ', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_Chinese_utf8_bom.inc����������������������������������0000644�0001750�0001750�00000007306�13237143042�026016� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Simplified Chinese (Codepage UTF-8) Translation by Liu Da <xmacmail AT gmail.com> } RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'Chinese_utf8', //map {trUnits} '单元', {trClassHierarchy} '类继承', {trCio} '类、接口、对象和记录', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} '标识符', {trGvUses} '单元依赖关系图', {trGvClasses} '类继承关系图', //tables and members {trClasses} '类', {trClass} '类', {trDispInterface} '调度接口', {trInterface} '接口', {trObjects} '对象', {trObject} '对象', {trRecord} '记录', {trPacked} strToDo, //'Packed', {trHierarchy} '层次结构', {trFields} '字段', {trMethods} '方法', {trProperties} '属性', {trLibrary} '库', {trPackage} '包', {trProgram} '程序', {trUnit} '单元', {trUses} '引用', {trConstants} '常量', {trFunctionsAndProcedures} '函数与过程', {trTypes} '类型', {trType} '类型', {trVariables} '变量', {trAuthors} '作者', {trAuthor} '作者', {trCreated} '创建于', {trLastModified} '最后更新', {trSubroutine} '子程序', {trParameters} '参数', {trReturns} '返回值', {trExceptionsRaised} '抛出的异常', {trExceptions} '异常', {trException} '异常', {trEnum} '枚举', //visibilities {trVisibility} '可见性', {trPrivate} '私有', {trStrictPrivate} '严格私有', {trProtected} '保护', {trStrictProtected} '严格保护', {trPublic} '公有', {trPublished} '发布', {trAutomated} '自动', {trImplicit} '隐式', //hints {trDeprecated} '这个符号是不建议使用的', {trPlatformSpecific} '这个符号仅用于特定的平台', {trLibrarySpecific} '这个符号仅用于特定的库', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} '综述', {trIntroduction} '前言', {trConclusion} '后记', {trEnclosingClass} strToDo, //'Enclosing Class', {trHeadlineCio} '所有的类、接口、对象和记录', {trHeadlineConstants} '所有常量', {trHeadlineFunctionsAndProcedures} '所有函数和过程', {trHeadlineIdentifiers} '所有标识符', {trHeadlineTypes} '所有类型', {trHeadlineUnits} '所有单元', {trHeadlineVariables} '所有变量', {trSummaryCio} '类、接口、对象和记录的摘要', //column headings {trDeclaration} '声明', {trDescription} '描述', {trDescriptions} '描述', {trName} '名称', {trValues} '值', //empty {trNone} '无', {trNoCIOs} '不包含任何类、接口、对象和记录的单元.', {trNoCIOsForHierarchy} '不包含任何类、接口、对象的单元.', {trNoTypes} '不包含任何类型的单元.', {trNoVariables} '不包含任何变量的单元.', {trNoConstants} '不包含任何常量的单元.', {trNoFunctions} '不包含任何函数与过程的单元.', {trNoIdentifiers} '不包含任何标识符的单元.', //misc {trHelp} '帮助', {trLegend} '图例', {trMarker} '标记', {trWarningOverwrite} '警告:不要编辑此文件 - 这是一个自动生成的文件,而且它很可能被覆盖掉', {trWarning} '警告', {trGeneratedBy} '由', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} '生成于', {trSearch} '搜索', {trSeeAlso} '参见', {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/lang/PasDoc_Languages_French_1252.inc���������������������������������������0000644�0001750�0001750�00000010401�13237143042�024501� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RTransTable = ( {trNoTrans} '<what?>', //no ID assigned, so far {trLanguage} 'French', //map {trUnits} 'Units', {trClassHierarchy} 'Hirarchie des classes', {trCio} 'Classes, interfaces, structures et objets', {trInternalCR} strToDo, // 'Internal Classes and Records', {trInternalTypes} strToDo, // 'Internal Types', {trIdentifiers} 'Identificateurs', {trGvUses} 'Graphique de dpendance d''units', {trGvClasses} 'Graphique de hirarchie des classes', //tables and members {trClasses} strKeep, //'Classes', {trClass} 'Classe', {trDispInterface} strToDo, //'DispInterface', {trInterface} strToDo, //'Interface', {trObjects} 'Objets', {trObject} 'Objet', {trRecord} strToDo, //'Record', {trPacked} strToDo, //'Packed', {trHierarchy} 'Hirarchie', {trFields} 'Champs', {trMethods} 'Mthodes', {trProperties} 'Proprits', {trLibrary} 'Bibliothque', //? {trPackage} strToDo, //'Package', {trProgram} 'Logiciel', //? 'Program', {trUnit} 'Unit', {trUses} strToDo, //'Uses', {trConstants} 'Constantes', {trFunctionsAndProcedures} 'Fonctions et procdures', {trTypes} strKeep, //'Types', {trType} strKeep, //'Type', {trVariables} strKeep, //'Variables', {trAuthors} 'Auteurs', {trAuthor} 'Auteur', {trCreated} 'Cre', {trLastModified} 'Dernire modification', {trSubroutine} strToDo, //'Subroutine', {trParameters} 'Paramtres', {trReturns} 'Retourne', {trExceptionsRaised} strToDo, //'Exceptions raised', {trExceptions} strToDo, //'Exceptions', {trException} strToDo, //'Exception', {trEnum} strToDo, //'Enumeration', //visibilities {trVisibility} 'Visibilit', {trPrivate} 'Priv', {trStrictPrivate} 'Strictement Priv', //? {trProtected} 'Protg', {trStrictProtected} 'Strictement Protg', //? {trPublic} strKeep, //'Public', {trPublished} 'Publis', {trAutomated} 'Automatis', {trImplicit} strKeep, //'Implicit', //hints {trDeprecated} 'ce symbole est dsapprouv', {trPlatformSpecific} 'ce symbole est spcifique une plateforme d''excution', {trLibrarySpecific} 'ce symbole est spcifique une certaine bibliothque', {trExperimental} strToDo, //'this symbol is experimental', //headings {trOverview} 'Aperu', {trIntroduction} strToDo, //'Introduction', {trConclusion} strToDo, //'Conclusion', {trHeadlineCio} 'Toutes les classes, interfaces, objets et enregistrements', {trHeadlineConstants} 'Toutes les constants', {trHeadlineFunctionsAndProcedures} 'Toutes les fonctions et procdures', {trHeadlineIdentifiers} 'Tous les identificateurs', {trHeadlineTypes} 'Tous les types', {trHeadlineUnits} 'Toutes les units', {trHeadlineVariables} 'Toutes les variables', {trSummaryCio} 'Classes, interfaces, objets et enregistrements', //column headings {trDeclaration} 'Dclaration', {trDescription} strKeep, //'Description', {trDescriptions} strToDo, //'Descriptions', 'Detailed Descriptions'? {trName} 'Nom', {trValues} 'Valeurs', //? //empty {trNone} 'Aucun(e)(s)', //'Rien'? {trNoCIOs} strToDo, //'The units do not contain any classes, interfaces, objects or records.', {trNoCIOsForHierarchy} strToDo, //'The units do not contain any classes, interfaces or objects.', {trNoTypes} strToDo, //'The units do not contain any types.', {trNoVariables} strToDo, //'The units do not contain any variables.', {trNoConstants} strToDo, //'The units do not contain any constants.', {trNoFunctions} strToDo, //'The units do not contain any functions or procedures.', {trNoIdentifiers} strToDo, //'The units do not contain any identifiers.', //misc {trHelp} 'Aide', {trLegend} 'Lgende', {trMarker} 'Marquage', {trWarningOverwrite} 'Attention, ne pas dtier - ce fichier est cr automatiquement et va tre cras', {trWarning} 'Attention', {trGeneratedBy} 'Produit par', {trGeneratedOn} strToDo, //'Generated on' {trOnDateTime} 'le', {trSearch} 'Cherche', //? 'Recherche' {trSeeAlso} 'Voir aussi', //? {trInternal} strToDo, //'internal', {trAttributes} strToDo, //'Attributes', '' //dummy ); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/external_class_hierarchy.txt.inc��������������������������������������������0000600�0001750�0001750�00000015764�13237143042�024357� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "external_class_hierarchy.txt" } 'IDesignerNotify=IInterface' + LineEnding + 'IInterfaceComponentReference=IInterface' + LineEnding + 'IInterfaceList=IInterface' + LineEnding + 'IReadWriteSync=IInterface' + LineEnding + 'IStreamPersist=IInterface' + LineEnding + 'IStringsAdapter=IInterface' + LineEnding + 'IVCLComObject=IInterface' + LineEnding + 'TInterfaceList=TInterfacedObject' + LineEnding + 'TMultiReadExclusiveWriteSynchronizer=TInterfacedObject' + LineEnding + 'TSimpleRWSync=TInterfacedObject' + LineEnding + 'TStreamAdapter=TInterfacedObject' + LineEnding + 'Exception=TObject' + LineEnding + 'EAbort=Exception' + LineEnding + 'EAbstractError=Exception' + LineEnding + 'EAssertionFailed=Exception' + LineEnding + 'EBitsError=Exception' + LineEnding + 'EComponentError=Exception' + LineEnding + 'EConvertError=Exception' + LineEnding + 'EDuplicate=Exception' + LineEnding + 'EExternal=Exception' + LineEnding + 'EAccessViolation=EExternal' + LineEnding + 'EBusError=EAccessViolation' + LineEnding + 'EControlC=EExternal' + LineEnding + 'EExternalException=EExternal' + LineEnding + 'EInterror=EExternal' + LineEnding + 'EDivByZero=EInterror' + LineEnding + 'EIntOverflow=EInterror' + LineEnding + 'ERangeError=EInterror' + LineEnding + 'EMathError=EExternal' + LineEnding + 'EInvalidArgument=EMathError' + LineEnding + 'EInvalidOp=EMathError' + LineEnding + 'EOverflow=EMathError' + LineEnding + 'EUnderflow=EMathError' + LineEnding + 'EZeroDivide=EMathError' + LineEnding + 'EPrivilege=EExternal' + LineEnding + 'EStackOverflow=EExternal' + LineEnding + 'EFormatError=Exception' + LineEnding + 'EHeapMemoryError=Exception' + LineEnding + 'EInvalidPointer=EHeapMemoryError' + LineEnding + 'EOutOfMemory=EHeapMemoryError' + LineEnding + 'EOutOfResources=EOutOfMemory' + LineEnding + 'EInOutError=Exception' + LineEnding + 'EIntfCastError=Exception' + LineEnding + 'EInvalidCast=Exception' + LineEnding + 'EInvalidContainer=Exception' + LineEnding + 'EInvalidInsert=Exception' + LineEnding + 'EInvalidOperation=Exception' + LineEnding + 'EKeyNotFound=Exception' + LineEnding + 'EListError=Exception' + LineEnding + 'ENoThreadSupport=Exception' + LineEnding + 'ENoWideStringSupport=Exception' + LineEnding + 'EOSError=Exception' + LineEnding + 'EPackageError=Exception' + LineEnding + 'EParserError=Exception' + LineEnding + 'EPropertyConvertError=Exception' + LineEnding + 'EPropertyError=Exception' + LineEnding + 'EPropReadOnly=Exception' + LineEnding + 'EPropWriteOnly=Exception' + LineEnding + 'EResNotFound=Exception' + LineEnding + 'ESafecallException=Exception' + LineEnding + 'EStreamError=Exception' + LineEnding + 'EFCreateError=EStreamError' + LineEnding + 'EFilerError=EStreamError' + LineEnding + 'EClassNotFound=EFilerError' + LineEnding + 'EInvalidImage=EFilerError' + LineEnding + 'EMethodNotFound=EFilerError' + LineEnding + 'EReadError=EFilerError' + LineEnding + 'EWriteError=EFilerError' + LineEnding + 'EFOpenError=EStreamError' + LineEnding + 'EStringListError=Exception' + LineEnding + 'EThread=Exception' + LineEnding + 'EThreadDestroyCalled=EThread' + LineEnding + 'EVariantError=Exception' + LineEnding + 'TAbstractObjectReader=TObject' + LineEnding + 'TBinaryObjectReader=TAbstractObjectReader' + LineEnding + 'TAbstractObjectWriter=TObject' + LineEnding + 'TBinaryObjectWriter=TAbstractObjectWriter' + LineEnding + 'TTextObjectWriter=TAbstractObjectWriter' + LineEnding + 'TBasicActionLink=TObject' + LineEnding + 'TBits=TObject' + LineEnding + 'TCollectionEnumerator=TObject' + LineEnding + 'TComponentEnumerator=TObject' + LineEnding + 'TCustomBucketList=TObject' + LineEnding + 'TBucketList=TCustomBucketList' + LineEnding + 'TObjectBucketList=TBucketList' + LineEnding + 'TFiler=TObject' + LineEnding + 'TReader=TFiler' + LineEnding + 'TWriter=TFiler' + LineEnding + 'TFPCustomHashTable=TObject' + LineEnding + 'TFPDataHashTable=TFPCustomHashTable' + LineEnding + 'TFPObjectHashTable=TFPCustomHashTable' + LineEnding + 'TFPStringHashTable=TFPCustomHashTable' + LineEnding + 'TFPHashList=TObject' + LineEnding + 'TFPHashObject=TObject' + LineEnding + 'TFPHashObjectList=TObject' + LineEnding + 'TFPList=TObject' + LineEnding + 'TFPListEnumerator=TObject' + LineEnding + 'TFPObjectList=TObject' + LineEnding + 'THTCustomNode=TObject' + LineEnding + 'THTDataNode=THTCustomNode' + LineEnding + 'THTObjectNode=THTCustomNode' + LineEnding + 'THTOwnedObjectNode=THTObjectNode' + LineEnding + 'THTStringNode=THTCustomNode' + LineEnding + 'TInterfaceListEnumerator=TObject' + LineEnding + 'TList=TObject' + LineEnding + 'TClassList=TList' + LineEnding + 'TObjectList=TList' + LineEnding + 'TComponentList=TObjectList' + LineEnding + 'TListEnumerator=TObject' + LineEnding + 'Tmatrix2_double=TObject' + LineEnding + 'Tmatrix2_extended=TObject' + LineEnding + 'Tmatrix2_single=TObject' + LineEnding + 'Tmatrix3_double=TObject' + LineEnding + 'Tmatrix3_extended=TObject' + LineEnding + 'Tmatrix3_single=TObject' + LineEnding + 'Tmatrix4_double=TObject' + LineEnding + 'Tmatrix4_extended=TObject' + LineEnding + 'Tmatrix4_single=TObject' + LineEnding + 'TOrderedList=TObject' + LineEnding + 'TQueue=TOrderedList' + LineEnding + 'TObjectQueue=TQueue' + LineEnding + 'TStack=TOrderedList' + LineEnding + 'TObjectStack=TStack' + LineEnding + 'TParser=TObject' + LineEnding + 'TPersistent=TObject' + LineEnding + 'TCollection=TPersistent' + LineEnding + 'TOwnedCollection=TCollection' + LineEnding + 'TCollectionItem=TPersistent' + LineEnding + 'TComponent=TPersistent' + LineEnding + 'TBasicAction=TComponent' + LineEnding + 'TDataModule=TComponent' + LineEnding + 'TInterfacedPersistent=TPersistent' + LineEnding + 'TStrings=TPersistent' + LineEnding + 'TStringList=TStrings' + LineEnding + 'TRecall=TObject' + LineEnding + 'TStream=TObject' + LineEnding + 'TCustomMemoryStream=TStream' + LineEnding + 'TMemoryStream=TCustomMemoryStream' + LineEnding + 'TResourceStream=TCustomMemoryStream' + LineEnding + 'THandleStream=TStream' + LineEnding + 'TFileStream=THandleStream' + LineEnding + 'TOwnerStream=TStream' + LineEnding + 'TProxyStream=TStream' + LineEnding + 'TStringStream=TStream' + LineEnding + 'TStringsEnumerator=TObject' + LineEnding + 'TThread=TObject' + LineEnding + 'TThreadList=TObject' + LineEnding + 'Tvector2_double=TObject' + LineEnding + 'Tvector2_extended=TObject' + LineEnding + 'Tvector2_single=TObject' + LineEnding + 'Tvector3_double=TObject' + LineEnding + 'Tvector3_extended=TObject' + LineEnding + 'Tvector3_single=TObject' + LineEnding + 'Tvector4_double=TObject' + LineEnding + 'Tvector4_extended=TObject' + LineEnding + 'Tvector4_single=TObject' + LineEnding + 'TFPSList=TObject' + LineEnding + 'TFPGList=TFPSList' + LineEnding + 'TFPGObjectList=TFPSList' + LineEnding + 'TFPGInterfacedObjectList=TFPSList' + LineEnding + 'TFPSMap=TFPSList' + LineEnding + 'TFPGMap=TFPSMap' + LineEnding + 'TFPGMapInterfacedObjectData=TFPSMap' + LineEnding + '' ������������pasdoc/source/component/PasDoc_Aspell.pas�����������������������������������������������������������0000600�0001750�0001750�00000014544�13237143042�021152� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Spellchecking using Aspell.) } unit PasDoc_Aspell; {$I pasdoc_defines.inc} interface uses SysUtils, Classes, PasDoc_ProcessLineTalk, PasDoc_ObjectVector, PasDoc_Types; type TSpellingError = class public { the mis-spelled word } Word: string; { offset inside the checked string } Offset: Integer; { comma-separated list of suggestions } Suggestions: string; end; { This is a class to interface with aspell through pipe. It uses underlying @link(TProcessLineTalk) to execute and "talk" with aspell. } TAspellProcess = class private FProcess: TProcessLineTalk; FAspellMode: string; FAspellLanguage: string; FOnMessage: TPasDocMessageEvent; procedure DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string); public { Constructor. Values for AspellMode and AspellLanguage are the same as for aspell @--mode and @--lang command-line options. You can pass here '', then we will not pass appropriate command-line option to aspell. } constructor Create(const AAspellMode, AAspellLanguage: string; AOnMessage: TPasDocMessageEvent); destructor Destroy; override; property AspellMode: string read FAspellMode; property AspellLanguage: string read FAspellLanguage; procedure SetIgnoreWords(Value: TStringList); { Spellchecks AString and returns result. Will create an array of TSpellingError objects, one entry for each misspelled word. Offsets of TSpellingErrors will be relative to AString. } procedure CheckString(const AString: string; const AErrors: TObjectVector); property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; end; implementation uses PasDoc_Utils; function StringsJoin(const List: TStrings; const Glue: string): string; var I: Integer; begin if List.Count <> 0 then begin Result := List[0]; for I := 1 to List.Count - 1 do Result := Result + Glue + List[I]; end else Result := ''; end; constructor TAspellProcess.Create(const AAspellMode, AAspellLanguage: string; AOnMessage: TPasDocMessageEvent); var FirstAspellLine: string; begin inherited Create; FAspellMode := AAspellMode; FAspellLanguage := AAspellLanguage; FOnMessage := AOnMessage; FProcess := TProcessLineTalk.Create(nil); { calculate FProcess.Executable / Parameters } FProcess.Executable := 'aspell'; FProcess.Parameters.Add('-a'); if AspellMode <> '' then FProcess.Parameters.Add(' --mode=' + AspellMode); if AspellLanguage <> '' then FProcess.Parameters.Add(' --lang=' + AspellLanguage); DoMessage(3, pmtInformation, 'Calling aspell process: "' + FProcess.Executable + ' ' + StringsJoin(FProcess.Parameters, ' ') + '"'); { execute } FProcess.Execute; { read and check 1st aspell output line } FirstAspellLine := FProcess.ReadLine; if Copy(FirstAspellLine, 1, 4) <> '@(#)' then raise Exception.CreateFmt('Wrong introduction from aspell: "%s"', [FirstAspellLine]); { switch to aspell terse mode (do not report about correct words; report only mispellings) } FProcess.WriteLine('!'); end; destructor TAspellProcess.Destroy; begin FProcess.Free; inherited; end; procedure TAspellProcess.SetIgnoreWords(Value: TStringList); var i: Integer; begin for i := 0 to Value.Count - 1 do FProcess.WriteLine('@' + Value[i]); end; procedure TAspellProcess.CheckString(const AString: string; const AErrors: TObjectVector); var s: string; p, p2: Integer; LError: TSpellingError; begin AErrors.Clear; { make sure that FAspellMode is set -- should be removed, since it's passed to aspell command-line ? TODO. } if AspellMode <> '' then begin FProcess.WriteLine('-'); FProcess.WriteLine('+' + AspellMode); end; { request spell-checking AString } FProcess.WriteLine('^' + SCharsReplace(AString, WhiteSpaceNL, ' ')); repeat s := FProcess.ReadLine; { aspell returns empty line when it finished spell-checking AString } if s = '' then break; case s[1] of '*': Continue; // no error '#': begin LError := TSpellingError.Create; s := copy(s, 3, MaxInt); // get rid of '# ' p := Pos(' ', s); LError.Word := copy(s, 1, p-1); // get word LError.Suggestions := ''; s := copy(s, p+1, MaxInt); LError.Offset := StrToIntDef(s, 0)-1; AErrors.Add(LError); end; '&': begin LError := TSpellingError.Create; s := copy(s, 3, MaxInt); // get rid of '& ' p := Pos(' ', s); LError.Word := copy(s, 1, p-1); // get word s := copy(s, p+1, MaxInt); p := Pos(' ', s); s := copy(s, p+1, MaxInt); p2 := Pos(':', s); LError.Suggestions := Copy(s, Pos(':', s)+2, MaxInt); SetLength(s, p2-1); LError.Offset := StrToIntDef(s, 0)-1; AErrors.Add(LError); end; else { Actually, it's nowhere formally specified that aspell error messages start with "Error:". So we can possibly accidentaly skip some error messages from aspell. } if IsPrefix('Error:', S) then DoMessage(2, pmtWarning, 'Aspell error: ' + S); end; until false; end; procedure TAspellProcess.DoMessage(const AVerbosity: Cardinal; const MessageType: TPasDocMessageType; const AMessage: string); begin if Assigned(FOnMessage) then FOnMessage(MessageType, AMessage, AVerbosity); end; end. ������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Base.pas�������������������������������������������������������������0000600�0001750�0001750�00000062745�13237143042�020612� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Contains the main TPasDoc component.) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Erwin Scheuch-Heilig (ScheuchHeilig@t-online.de)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Michael van Canneyt (michael@tfdec1.fys.kuleuven.ac.be)) @author(Michalis Kamburelis) @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Arno Garrels <first name.name@nospamgmx.de>) @created(24 Sep 1999) Unit name must be @code(PasDoc_Base) instead of just @code(PasDoc) to not conflict with the name of base program name @code(pasdoc.dpr). } unit PasDoc_Base; {$I pasdoc_defines.inc} interface uses SysUtils, Classes, PasDoc_Items, PasDoc_Languages, PasDoc_Gen, PasDoc_Types, PasDoc_StringVector, PasDoc_SortSettings, PasDoc_StreamUtils, PasDoc_TagManager {$IFNDEF FPC} {$IFDEF WIN32} {$IFNDEF DELPHI_6_UP} ,FileCtrl {$ENDIF} {$ENDIF} {$ENDIF} ; const { } DEFAULT_VERBOSITY_LEVEL = 2; type { The main object in the pasdoc application; first scans parameters, then parses files. All parsed units are then given to documentation generator, which creates one or more documentation output files. } TPasDoc = class(TComponent) private FDescriptionFileNames: TStringVector; { Title of documentation. } FTitle: string; FDirectives: TStringVector; FGeneratorInfo: Boolean; FIncludeDirectories: TStringVector; FOnMessage: TPasDocMessageEvent; { The name PasDoc shall give to this documentation project, also used to name some of the output files. } FProjectName: string; FSourceFileNames: TStringVector; { All TPasUnit objects which have been created from the list of file names during the parsing. } FUnits: TPasUnits; FVerbosity: Cardinal; FCommentMarkers: TStringList; FGenerator: TDocGenerator; FShowVisibilities: TVisibilities; FMarkerOptional: boolean; FIgnoreLeading: string; FCacheDir: string; FSortSettings: TSortSettings; FConclusionFileName: string; FIntroductionFileName: string; FConclusion: TExternalItem; FIntroduction: TExternalItem; FImplicitVisibility: TImplicitVisibility; FHandleMacros: boolean; FAutoLink: boolean; procedure SetDescriptionFileNames(const ADescriptionFileNames: TStringVector); procedure SetDirectives(const ADirectives: TStringVector); procedure SetIncludeDirectories(const AIncludeDirectores: TStringVector); procedure SetSourceFileNames(const ASourceFileNames: TStringVector); procedure SetGenerator(const Value: TDocGenerator); procedure SetStarOnly(const Value: boolean); function GetStarOnly: boolean; procedure SetCommentMarkers(const Value: TStringList); { Creates a @link(TPasUnit) object from the stream and adds it to @link(FUnits). } procedure HandleStream( const InputStream: TStream; const SourceFileName: string); procedure HandleExternalFile( const FileName: string; out ExternalItem: TExternalItem); { Calls @link(HandleStream) for each file name in @link(SourceFileNames). } procedure ParseFiles; {$IFNDEF STRING_UNICODE} procedure SkipBOM(InputStream: TStream); {$ENDIF} protected { Searches the description of each TPasUnit item in the collection for an excluded tag. If one is found, the item is removed from the collection. If not, the fields, methods and properties collections are called with RemoveExcludedItems If the collection is empty after removal of all items, it is disposed of and the variable is set to nil. } procedure RemoveExcludedItems(const c: TPasItems); procedure Notification(AComponent: TComponent; Operation: TOperation); override; public { Creates object and sets fields to default values. } constructor Create(AOwner: TComponent); override; { } destructor Destroy; override; { Adds source filenames from a stringlist } procedure AddSourceFileNames(const AFileNames: TStringList); { Loads names of Pascal unit source code files from a text file. Adds all file names to @link(SourceFileNames). If DashMeansStdin and AFileName = '-' then it will load filenames from stdin. } procedure AddSourceFileNamesFromFile(const FileName: string; DashMeansStdin: boolean); { Raises an exception. } procedure DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); { Forwards a message to the @link(OnMessage) event. } procedure DoMessage(const AVerbosity: Cardinal; const AMessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); { for Generator messages } procedure GenMessage(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); { Starts creating the documentation. } procedure Execute; // After @link(Execute) has been called, @name holds the units that have // been parsed. property Units: TPasUnits read FUnits; // After @link(Execute) has been called, @name holds the conclusion. property Conclusion: TExternalItem read FConclusion; // After @link(Execute) has been called, @name holds the introduction. property Introduction: TExternalItem read FIntroduction; published property DescriptionFileNames: TStringVector read FDescriptionFileNames write SetDescriptionFileNames; property Directives: TStringVector read FDirectives write SetDirectives; property IncludeDirectories: TStringVector read FIncludeDirectories write SetIncludeDirectories; { This is deprecated name for @link(OnMessage) } property OnWarning: TPasDocMessageEvent read FOnMessage write FOnMessage stored false; property OnMessage: TPasDocMessageEvent read FOnMessage write FOnMessage; { The name PasDoc shall give to this documentation project, also used to name some of the output files. } property ProjectName: string read FProjectName write FProjectName; property SourceFileNames: TStringVector read FSourceFileNames write SetSourceFileNames; property Title: string read FTitle write FTitle; property Verbosity: Cardinal read FVerbosity write FVerbosity default DEFAULT_VERBOSITY_LEVEL; property StarOnly: boolean read GetStarOnly write SetStarOnly stored false; property CommentMarkers: TStringList read FCommentMarkers write SetCommentMarkers; property MarkerOptional: boolean read FMarkerOptional write FMarkerOptional default false; property IgnoreLeading: string read FIgnoreLeading write FIgnoreLeading; property Generator: TDocGenerator read FGenerator write SetGenerator; property ShowVisibilities: TVisibilities read FShowVisibilities write FShowVisibilities; property CacheDir: string read FCacheDir write FCacheDir; { This determines how items inside will be sorted. See [https://github.com/pasdoc/pasdoc/wiki/SortOption]. } property SortSettings: TSortSettings read FSortSettings write FSortSettings default []; property IntroductionFileName: string read FIntroductionFileName write FIntroductionFileName; property ConclusionFileName: string read FConclusionFileName write FConclusionFileName; { See command-line option @--implicit-visibility documentation at [https://github.com/pasdoc/pasdoc/wiki/ImplicitVisibilityOption]. This will be passed to parser instance. } property ImplicitVisibility: TImplicitVisibility read FImplicitVisibility write FImplicitVisibility default ivPublic; property HandleMacros: boolean read FHandleMacros write FHandleMacros default true; { This controls auto-linking, see [https://github.com/pasdoc/pasdoc/wiki/AutoLinkOption] } property AutoLink: boolean read FAutoLink write FAutoLink default false; end; implementation uses PasDoc_Parser, PasDoc_ObjectVector, PasDoc_Utils, PasDoc_Serialize; constructor TPasDoc.Create(AOwner: TComponent); begin inherited; FDescriptionFileNames := NewStringVector; FDirectives := NewStringVector; FIncludeDirectories := NewStringVector; FSourceFileNames := NewStringVector; { Set default property values } FGeneratorInfo := true; FVerbosity := DEFAULT_VERBOSITY_LEVEL; FImplicitVisibility := ivPublic; HandleMacros := true; FGenerator := nil; FCommentMarkers := TStringList.Create; FUnits := TPasUnits.Create(True); end; { ---------------------------------------------------------------------------- } destructor TPasDoc.Destroy; begin FCommentMarkers.Free; FDescriptionFileNames.Free; FDirectives.Free; FIncludeDirectories.Free; FSourceFileNames.Free; FUnits.Free; FConclusion.Free; FIntroduction.Free; inherited; end; { ---------------------------------------------------------------------------- } {$IFNDEF STRING_UNICODE} procedure TPasDoc.SkipBOM(InputStream: TStream); var A : array [0..3] of Byte; begin InputStream.ReadBuffer(A, 4); { See also TStreamReader.GetCodePageFromBOM for an implementation that actually uses UTF-x BOM. Here, we only detect BOM to make nice error (in case of UTF-16/32) or skip it (in case of UTF-8). } if (A[0] = $FF) and (A[1] = $FE) and (A[2] = 0) and (A[3] = 0) then begin DoError('Detected UTF-32 (little endian) encoding (right now we cannot read such files)', [], 0); end else if (A[0] = 0) and (A[1] = 0) and (A[2] = $FE) and (A[3] = $FF) then begin DoError('Detected UTF-32 (big endian) encoding (right now we cannot read such files)', [], 0); end else if (A[0] = $FF) and (A[1] = $FE) then begin DoError('Detected UTF-16 (little endian) encoding (right now we cannot read such files, unless compiled with Delphi Unicode)', [], 0); end else if (A[0] = $FE) and (A[1] = $FF) then begin DoError('Detected UTF-16 (big endian) encoding (right now we cannot read such files, unless compiled with Delphi Unicode)', [], 0); end else if (A[0] = $EF) and (A[1] = $BB) and (A[2] = $BF) then begin DoMessage(6, pmtInformation, 'Detected UTF-8 BOM, skipping.', []); InputStream.Position := 3; end else { No BOM: get back to the beginning of the steam } InputStream.Position := 0; end; {$ENDIF} procedure TPasDoc.HandleStream( const InputStream: TStream; const SourceFileName: string); var p: TParser; U: TPasUnit; LLoaded: boolean; LCacheFileName: string; begin LCacheFileName := CacheDir+ChangeFileExt(ExtractFileName(SourceFileName), '.pduc'); p := TParser.Create(InputStream, FDirectives, FIncludeDirectories, {$IFDEF FPC}@{$ENDIF} GenMessage, FVerbosity, SourceFileName, ExtractFilePath(SourceFileName), HandleMacros); try {$IFNDEF STRING_UNICODE} SkipBOM(InputStream); {$ENDIF} p.ShowVisibilities := ShowVisibilities; p.ImplicitVisibility := ImplicitVisibility; p.CommentMarkers := CommentMarkers; p.MarkersOptional := MarkerOptional; p.IgnoreLeading := IgnoreLeading; LLoaded := false; U := nil; if (CacheDir <> '') and FileExists(LCacheFileName) then begin DoMessage(2, pmtInformation, 'Loading data for file %s from cache...', [SourceFileName]); try U := TPasUnit(TPasUnit.DeserializeFromFile(LCacheFileName)); {$IFDEF COMPILER_10_UP} U.CacheDateTime := CheckGetFileDate(LCacheFileName); if U.CacheDateTime < CheckGetFileDate(SourceFileName) then {$ELSE} U.CacheDateTime := FileDateToDateTime(FileAge(LCacheFileName)); if U.CacheDateTime < FileDateToDateTime(FileAge(SourceFileName)) then {$ENDIF} begin DoMessage(2, pmtInformation, 'Cache file for %s is outdated.', [SourceFileName]); end else begin LLoaded := True; end; except on E: EInvalidCacheFileVersion do begin { On EInvalidCacheFileVersion, make nice message and continue (with LLoaded = false, just like the cache would not exist). } DoMessage(2, pmtInformation, 'Cache file for %s is incompatible (probably from a different PasDoc release).', [SourceFileName]); end; end; end; if not LLoaded then begin DoMessage(2, pmtInformation, 'Now parsing file %s...', [SourceFileName]); { In case unit was loaded from cache, but rejected for whatever reason, free it to avoid memory leaks. } FreeAndNil(U); p.ParseUnitOrProgram(U); end; if FUnits.ExistsUnit(U) then begin DoMessage(2, pmtWarning, 'Duplicate unit name "%s" in files "%s" and "%s" (discarded)', [U.Name, TPasUnit(FUnits.FindListItem(U.Name)).SourceFileName, SourceFileName]); U.Free; end else begin U.SourceFileName := SourceFileName; {$IFDEF COMPILER_10_UP} U.SourceFileDateTime := CheckGetFileDate(SourceFileName); {$ELSE} U.SourceFileDateTime := FileDateToDateTime(FileAge(SourceFileName)); {$ENDIF} FUnits.Add(U); { Now we know that unit was 100% successfully parsed. So now we save it to the cache. The current approach to cache stores in cache the exact state of unit as it was generated by parser (that why we can use deserialization as an equivalent of parsing), so we want to save the unit to cache *now*, in case some later processing would change some things. E.g. processing @deprecated tag will change item's IsDeprecated, processing @member and @value will change some item's RawDescription. We want to write the cache *before* such changes occur. } if (CacheDir <> '') and not U.WasDeserialized then U.SerializeToFile(LCacheFileName); end; except on e: Exception do begin DoMessage(2, pmtWarning, 'Error %s: %s while parsing unit %s, continuing...', [e.ClassName, e.Message, ExtractFileName(SourceFileName)]); end; end; p.Free; end; { ---------------------------------------------------------------------------- } procedure TPasDoc.AddSourceFileNamesFromFile(const FileName: string; DashMeansStdin: boolean); var ASV: TStringVector; begin ASV := NewStringVector; try if DashMeansStdin and (FileName = '-') then ASV.LoadFromTextFileAdd(Input) else ASV.LoadFromTextFileAdd(FileName); AddSourceFileNames(ASV); finally ASV.Free; end; end; { ---------------------------------------------------------------------------- } procedure TPasDoc.ParseFiles; var Count, i: Integer; p: string; InputStream: TStream; procedure ParseExternalFile(const FileName: string; var ExternalItem: TExternalItem); begin if FileName <> '' then begin HandleExternalFile(FileName, ExternalItem); Inc(Count); end; end; begin FUnits.clear; DoMessage(1, pmtInformation, 'Starting Source File Parsing ...', []); if FSourceFileNames.IsEmpty then Exit; InputStream := nil; Count := 0; for i := 0 to FSourceFileNames.Count - 1 do begin p := FSourceFileNames[i]; try {$IFDEF STRING_UNICODE} InputStream := TStreamReader.Create(p); {$ELSE} {$IFDEF USE_BUFFERED_STREAM} InputStream := TBufferedStream.Create(p, fmOpenRead or fmShareDenyWrite); {$ELSE} InputStream := TFileStream.Create(p, fmOpenRead or fmShareDenyWrite); {$ENDIF} {$ENDIF} except on E: Exception do begin DoMessage(1, pmtError, 'Cannot open file "%s". Reason: "%s", skipping', [p, E.Message]); Continue; end; end; { Note that HandleStream frees InputStream. Note that Delphi 7 reports here warning ("Variable "InputStream" might not have been initialized") that should be ignored. } HandleStream(InputStream, p); Inc(Count); end; FreeAndNil(FIntroduction); ParseExternalFile(IntroductionFileName, FIntroduction); FreeAndNil(FConclusion); ParseExternalFile(ConclusionFileName, FConclusion); DoMessage(2, pmtInformation, '... %d Source File(s) parsed', [Count]); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.RemoveExcludedItems(const c: TPasItems); var i: Integer; p: TPasItem; begin if c = nil then Exit; i := 0; while (i < c.Count) do begin p := c.PasItemAt[i]; { TODO -- code below checks for @exclude tag too trivially, it accidentally excludes items with comments like '@@exclude' or '@html(@exclude)'. Checking for exclude should be incorporated into doing TTagManager.Execute in ExpandDescription. } if Assigned(p) and (StrPosIA('@EXCLUDE', p.RawDescription) > 0) then begin DoMessage(3, pmtInformation, 'Excluding item %s', [p.Name]); c.Delete(i); end else begin { P has no excluded tag; but if it is a class, interface, object or unit, one of its parts may be excluded } if p.ClassType = TPasCio then begin RemoveExcludedItems(TPasCio(p).Fields); RemoveExcludedItems(TPasItems(TPasCio(p).Properties)); RemoveExcludedItems(TPasItems(TPasCio(p).Methods)); end else if p.ClassType = TPasUnit then begin RemoveExcludedItems(TPasUnit(p).CIOs); RemoveExcludedItems(TPasUnit(p).Constants); RemoveExcludedItems(TPasItems(TPasUnit(p).FuncsProcs)); RemoveExcludedItems(TPasUnit(p).Types); RemoveExcludedItems(TPasUnit(p).Variables); end; Inc(i); end; end; end; { ---------------------------------------------------------------------------- } procedure TPasDoc.Execute; var TimeStart: TDateTime; CacheDirNoDelim: string; UnitsCountBeforeExcluding: Cardinal; I: Integer; begin if not Assigned(Generator) then begin DoError('No Generator present!', [], 1); end; { Do a couple of tests before we actually start processing the source files. } if FSourceFileNames.IsEmpty then begin DoError('No Source Files have been specified.', [], 1); end; if (CacheDir <> '') then begin {$ifdef WIN32} { This is needed to make DirectoryExists and CreateDir work when user used UNIX-like delimiters "/" inside CacheDir (yes, it's normally allowed under Windows, so pasdoc should work with it too) } CacheDir := SCharsReplace(CacheDir, ['/'], PathDelim); {$endif} CacheDirNoDelim := ExcludeTrailingPathDelimiter(CacheDir); CacheDir := IncludeTrailingPathDelimiter(CacheDir); if not DirectoryExists(CacheDirNoDelim) then begin if not CreateDir(CacheDirNoDelim) then begin DoError('Cache directory does not exist and could not be created', [], 1); end; end; end; { Make sure all IncludeDirectories end with a Path Separator. } for I := 0 to FIncludeDirectories.Count - 1 do FIncludeDirectories[I] := IncludeTrailingPathDelimiter(FIncludeDirectories[I]); TimeStart := Now; ParseFiles; UnitsCountBeforeExcluding := FUnits.Count; RemoveExcludedItems(TPasItems(FUnits)); { check if we have any units successfully parsed and not @excluded } if ObjectVectorIsNilOrEmpty(FUnits) then begin if UnitsCountBeforeExcluding <> 0 then DoError('%d units were successfully parsed, but they are all ' + 'marked with @exclude', [UnitsCountBeforeExcluding], 1) else DoError('At least one unit must have been successfully parsed ' + 'to write docs', [], 1); end; if FProjectName <> '' then begin Generator.ProjectName := FProjectName end else begin Generator.ProjectName := 'docs'; end; Generator.Title := Title; Generator.Units := FUnits; Generator.Introduction := FIntroduction; Generator.Conclusion := FConclusion; Generator.AutoLink := AutoLink; Generator.BuildLinks; FUnits.SortDeep(SortSettings); Generator.LoadDescriptionFiles(FDescriptionFileNames); Generator.ExpandDescriptions; Generator.WriteDocumentation; DoMessage(3, pmtInformation, 'Worked %s minutes(s)', [FormatDateTime('nn:ss', (Now - TimeStart))]); DoMessage(1, pmtInformation, 'Done', []); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.DoError(const AMessage: string; const AArguments: array of const; const AExitCode: Word); begin raise EPasDoc.Create(AMessage, AArguments, AExitCode); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.DoMessage(const AVerbosity: Cardinal; const AMessageType: TPasDocMessageType; const AMessage: string; const AArguments: array of const); begin if (AVerbosity <= FVerbosity) and Assigned(FOnMessage) then FOnMessage(AMessageType, Format(AMessage, AArguments), AVerbosity); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.SetDescriptionFileNames(const ADescriptionFileNames: TStringVector); begin FDescriptionFileNames.Assign(ADescriptionFileNames); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.SetDirectives(const ADirectives: TStringVector); begin FDirectives.Assign(ADirectives); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.SetIncludeDirectories(const AIncludeDirectores: TStringVector); begin FIncludeDirectories.Assign(AIncludeDirectores); end; { ---------------------------------------------------------------------------- } procedure TPasDoc.SetSourceFileNames(const ASourceFileNames: TStringVector); begin FSourceFileNames.Clear; AddSourceFileNames(ASourceFileNames); end; procedure TPasDoc.GenMessage(const MessageType: TPasDocMessageType; const AMessage: string; const AVerbosity: Cardinal); begin DoMessage(AVerbosity, MessageType, AMessage, []); end; procedure TPasDoc.SetGenerator(const Value: TDocGenerator); begin if Assigned(FGenerator) then begin FGenerator.OnMessage := nil; end; FGenerator := Value; if Assigned(FGenerator) then begin FGenerator.FreeNotification(Self); {$IFDEF FPC} FGenerator.OnMessage := @GenMessage; {$ELSE} FGenerator.OnMessage := GenMessage; {$ENDIF} end; end; procedure TPasDoc.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (AComponent = FGenerator) and (Operation = opRemove) then begin FGenerator := nil; end; end; procedure TPasDoc.AddSourceFileNames(const AFileNames: TStringList); var SR: TSearchRec; FileMask, Path, s: string; i: Integer; SearchResult: Integer; begin for i := 0 to AFileNames.Count - 1 do begin FileMask := AFileNames[i]; Path := ExtractFilePath(FileMask); { Just ignore last empty line of AFileNames, this may often occur when generating text files with filenames, and is harmless. } if (FileMask = '') and (I = AFileNames.Count - 1) then Continue; SearchResult := SysUtils.FindFirst(FileMask, faArchive or faSysFile or faHidden or faReadOnly, SR); if SearchResult <> 0 then begin DoMessage(1, pmtWarning, 'No regular files found for "%s", skipping', [FileMask]); end else begin repeat s := Path + SR.Name; if not FSourceFileNames.ExistsNameCI(s) then FSourceFileNames.Add(s); SearchResult := FindNext(SR); until SearchResult <> 0; end; SysUtils.FindClose(SR); end; end; procedure TPasDoc.SetStarOnly(const Value: boolean); var Idx: Integer; begin Idx := FCommentMarkers.IndexOf('**'); { Compare Value with previous value, to not add a 2nd string '**' to FCommentMarkers, and only remove valid indexes. } if Value <> (Idx <> -1) then begin if Value then FCommentMarkers.Add('**') else FCommentMarkers.Delete(Idx); end; end; function TPasDoc.GetStarOnly: boolean; begin Result := FCommentMarkers.IndexOf('**') <> -1; end; procedure TPasDoc.SetCommentMarkers(const Value: TStringList); begin FCommentMarkers.Assign(Value); end; procedure TPasDoc.HandleExternalFile(const FileName: string; out ExternalItem: TExternalItem); begin ExternalItem := TExternalItem.Create; try DoMessage(2, pmtInformation, 'Now parsing file %s...', [FileName]); { This check tries to avoid the possibility of accidentaly overwriting user introduction/conclusion file (in case some user would incorrectly think that introduction/conclusion is in raw html, and would create file like my_introduction.html -- without this check, pasdoc could overwrite this file too easily). } if SameText(ExtractFileExt(FileName), Generator.GetFileExtension) then raise Exception.CreateFmt('Introduction/conclusion file extension' + ' is the same as file extension of generated documentation ("%s"), ' + 'refusing to generate documentation', [Generator.GetFileExtension]); ExternalItem.Name := SCharsReplace( ChangeFileExt( ExtractFileName(FileName) , ''), [' '], '_'); ExternalItem.RawDescription := FileToString(FileName); except FreeAndNil(ExternalItem); raise; end; end; end. ���������������������������pasdoc/source/component/PasDoc_StringPairVector.pas�������������������������������������������������0000600�0001750�0001750�00000014066�13237143042�023176� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Simple container for a pair of strings.) } unit PasDoc_StringPairVector; {$I pasdoc_defines.inc} interface uses Classes, PasDoc_ObjectVector; type TStringPair = class Name: string; Value: string; Data: Pointer; { Init Name and Value by @link(ExtractFirstWord) from S. } constructor CreateExtractFirstWord(const S: string); constructor Create; overload; constructor Create(const AName, AValue: string; AData: Pointer = nil); overload; end; { List of string pairs. This class contains only non-nil objects of class TStringPair. Using this class instead of TStringList (with it's Name and Value properties) is often better, because this allows both Name and Value of each pair to safely contain any special characters (including '=' and newline markers). It's also faster, since it doesn't try to encode Name and Value into one string. } TStringPairVector = class(TObjectVector) private function GetItems(i: Integer): TStringPair; procedure SetItems(i: Integer; Item: TStringPair); public property Items[i: Integer]: TStringPair read GetItems write SetItems; default; { Returns all items Names and Values glued together. For every item, string Name + NameValueSepapator + Value is constructed. Then all such strings for every items all concatenated with ItemSeparator. Remember that the very idea of @link(TStringPair) and @link(TStringPairVector) is that Name and Value strings may contain any special characters, including things you give here as NameValueSepapator and ItemSeparator. So it's practically impossible to later convert such Text back to items and Names/Value pairs. } function Text(const NameValueSepapator, ItemSeparator: string): string; { Finds a string pair with given Name. Returns -1 if not found. } function FindName(const Name: string; IgnoreCase: boolean = true): Integer; { Removes first string pair with given Name. Returns if some pair was removed. } function DeleteName(const Name: string; IgnoreCase: boolean = true): boolean; { Load from a stream using the binary format. For each item, it's Name and Value are saved. (TStringPair.Data pointers are @italic(not) saved.) } procedure LoadFromBinaryStream(Stream: TStream); { Save to a stream, in a format readable by @link(LoadFromBinaryStream). } procedure SaveToBinaryStream(Stream: TStream); { Name of first item, or '' if list empty. } function FirstName: string; end; implementation uses SysUtils { For LowerCase under Kylix 3 }, PasDoc_Utils, PasDoc_Serialize; { TStringPair ---------------------------------------------------------------- } constructor TStringPair.CreateExtractFirstWord(const S: string); var FirstWord, Rest: string; begin ExtractFirstWord(S, FirstWord, Rest); Create(FirstWord, Rest); end; constructor TStringPair.Create; begin inherited Create; end; constructor TStringPair.Create(const AName, AValue: string; AData: Pointer); begin Create; Name := AName; Value := AValue; Data := AData; end; { TStringPairVector ---------------------------------------------------------- } function TStringPairVector.GetItems(i: Integer): TStringPair; begin Result := TStringPair(inherited Items[i]); end; procedure TStringPairVector.SetItems(i: Integer; Item: TStringPair); begin inherited Items[i] := Item; end; function TStringPairVector.Text( const NameValueSepapator, ItemSeparator: string): string; var i: Integer; begin if Count > 0 then begin Result := Items[0].Name + NameValueSepapator + Items[0].Value; for i := 1 to Count - 1 do Result := Result + ItemSeparator + Items[i].Name + NameValueSepapator + Items[i].Value; end; end; function TStringPairVector.FindName(const Name: string; IgnoreCase: boolean): Integer; var LowerCasedName: string; begin if IgnoreCase then begin LowerCasedName := LowerCase(Name); for Result := 0 to Count - 1 do if LowerCase(Items[Result].Name) = LowerCasedName then Exit; Result := -1; end else begin for Result := 0 to Count - 1 do if Items[Result].Name = Name then Exit; Result := -1; end; end; function TStringPairVector.DeleteName(const Name: string; IgnoreCase: boolean): boolean; var i: Integer; begin i := FindName(Name, IgnoreCase); Result := i <> -1; if Result then Delete(i); end; procedure TStringPairVector.LoadFromBinaryStream(Stream: TStream); var I, N: Integer; P: TStringPair; begin Clear; N := TSerializable.LoadIntegerFromStream(Stream); Capacity := N; for I := 0 to N - 1 do begin P := TStringPair.Create; Add(P); P.Name := TSerializable.LoadStringFromStream(Stream); P.Value := TSerializable.LoadStringFromStream(Stream); end; end; procedure TStringPairVector.SaveToBinaryStream(Stream: TStream); var I: Integer; begin TSerializable.SaveIntegerToStream(Count, Stream); for i := 0 to Count - 1 do begin TSerializable.SaveStringToStream(Items[I].Name, Stream); TSerializable.SaveStringToStream(Items[I].Value, Stream); end; end; function TStringPairVector.FirstName: string; begin if Count > 0 then Result := Items[0].Name else Result := ''; end; end. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_SortSettings.pas�����������������������������������������������������0000600�0001750�0001750�00000005100�13237143042�022366� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Sorting settings types and names.)} unit PasDoc_SortSettings; {$I pasdoc_defines.inc} interface uses SysUtils; type EInvalidSortSetting = class(Exception); TSortSetting = ( { At unit (TPasUnit) level : } { } ssCIOs, ssConstants, ssFuncsProcs, ssTypes, ssVariables, ssUsesClauses, { At CIO (TPasCio) level : } { } ssRecordFields, ssNonRecordFields, ssMethods, ssProperties); TSortSettings = set of TSortSetting; const AllSortSettings: TSortSettings = [Low(TSortSetting) .. High(TSortSetting)]; { Must be lowercase. Used in @link(SortSettingsToName), @link(SortSettingFromName). } SortSettingNames: array[TSortSetting] of string = ( 'structures', 'constants', 'functions', 'types', 'variables', 'uses-clauses', 'record-fields', 'non-record-fields', 'methods', 'properties' ); { @raises(EInvalidSortSetting if ASortSettingName does not match (case ignored) to any SortSettingNames.) } function SortSettingFromName(const SortSettingName: string): TSortSetting; { Comma-separated list } function SortSettingsToName(const SortSettings: TSortSettings): string; implementation function SortSettingFromName(const SortSettingName: string): TSortSetting; var S: string; begin S := LowerCase(SortSettingName); for Result := Low(Result) to High(Result) do if S = SortSettingNames[Result] then Exit; raise EInvalidSortSetting.CreateFmt('Invalid sort specifier "%s"', [SortSettingName]); end; function SortSettingsToName(const SortSettings: TSortSettings): string; var SS: TSortSetting; begin Result := ''; for SS := Low(SS) to High(SS) do if SS in SortSettings then begin if Result <> '' then Result := Result + ','; Result := Result + SortSettingNames[SS]; end; end; end.����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/external_class_hierarchy.txt������������������������������������������������0000600�0001750�0001750�00000007777�13034465544�023625� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������IDesignerNotify=IInterface IInterfaceComponentReference=IInterface IInterfaceList=IInterface IReadWriteSync=IInterface IStreamPersist=IInterface IStringsAdapter=IInterface IVCLComObject=IInterface TInterfaceList=TInterfacedObject TMultiReadExclusiveWriteSynchronizer=TInterfacedObject TSimpleRWSync=TInterfacedObject TStreamAdapter=TInterfacedObject Exception=TObject EAbort=Exception EAbstractError=Exception EAssertionFailed=Exception EBitsError=Exception EComponentError=Exception EConvertError=Exception EDuplicate=Exception EExternal=Exception EAccessViolation=EExternal EBusError=EAccessViolation EControlC=EExternal EExternalException=EExternal EInterror=EExternal EDivByZero=EInterror EIntOverflow=EInterror ERangeError=EInterror EMathError=EExternal EInvalidArgument=EMathError EInvalidOp=EMathError EOverflow=EMathError EUnderflow=EMathError EZeroDivide=EMathError EPrivilege=EExternal EStackOverflow=EExternal EFormatError=Exception EHeapMemoryError=Exception EInvalidPointer=EHeapMemoryError EOutOfMemory=EHeapMemoryError EOutOfResources=EOutOfMemory EInOutError=Exception EIntfCastError=Exception EInvalidCast=Exception EInvalidContainer=Exception EInvalidInsert=Exception EInvalidOperation=Exception EKeyNotFound=Exception EListError=Exception ENoThreadSupport=Exception ENoWideStringSupport=Exception EOSError=Exception EPackageError=Exception EParserError=Exception EPropertyConvertError=Exception EPropertyError=Exception EPropReadOnly=Exception EPropWriteOnly=Exception EResNotFound=Exception ESafecallException=Exception EStreamError=Exception EFCreateError=EStreamError EFilerError=EStreamError EClassNotFound=EFilerError EInvalidImage=EFilerError EMethodNotFound=EFilerError EReadError=EFilerError EWriteError=EFilerError EFOpenError=EStreamError EStringListError=Exception EThread=Exception EThreadDestroyCalled=EThread EVariantError=Exception TAbstractObjectReader=TObject TBinaryObjectReader=TAbstractObjectReader TAbstractObjectWriter=TObject TBinaryObjectWriter=TAbstractObjectWriter TTextObjectWriter=TAbstractObjectWriter TBasicActionLink=TObject TBits=TObject TCollectionEnumerator=TObject TComponentEnumerator=TObject TCustomBucketList=TObject TBucketList=TCustomBucketList TObjectBucketList=TBucketList TFiler=TObject TReader=TFiler TWriter=TFiler TFPCustomHashTable=TObject TFPDataHashTable=TFPCustomHashTable TFPObjectHashTable=TFPCustomHashTable TFPStringHashTable=TFPCustomHashTable TFPHashList=TObject TFPHashObject=TObject TFPHashObjectList=TObject TFPList=TObject TFPListEnumerator=TObject TFPObjectList=TObject THTCustomNode=TObject THTDataNode=THTCustomNode THTObjectNode=THTCustomNode THTOwnedObjectNode=THTObjectNode THTStringNode=THTCustomNode TInterfaceListEnumerator=TObject TList=TObject TClassList=TList TObjectList=TList TComponentList=TObjectList TListEnumerator=TObject Tmatrix2_double=TObject Tmatrix2_extended=TObject Tmatrix2_single=TObject Tmatrix3_double=TObject Tmatrix3_extended=TObject Tmatrix3_single=TObject Tmatrix4_double=TObject Tmatrix4_extended=TObject Tmatrix4_single=TObject TOrderedList=TObject TQueue=TOrderedList TObjectQueue=TQueue TStack=TOrderedList TObjectStack=TStack TParser=TObject TPersistent=TObject TCollection=TPersistent TOwnedCollection=TCollection TCollectionItem=TPersistent TComponent=TPersistent TBasicAction=TComponent TDataModule=TComponent TInterfacedPersistent=TPersistent TStrings=TPersistent TStringList=TStrings TRecall=TObject TStream=TObject TCustomMemoryStream=TStream TMemoryStream=TCustomMemoryStream TResourceStream=TCustomMemoryStream THandleStream=TStream TFileStream=THandleStream TOwnerStream=TStream TProxyStream=TStream TStringStream=TStream TStringsEnumerator=TObject TThread=TObject TThreadList=TObject Tvector2_double=TObject Tvector2_extended=TObject Tvector2_single=TObject Tvector3_double=TObject Tvector3_extended=TObject Tvector3_single=TObject Tvector4_double=TObject Tvector4_extended=TObject Tvector4_single=TObject TFPSList=TObject TFPGList=TFPSList TFPGObjectList=TFPSList TFPGInterfacedObjectList=TFPSList TFPSMap=TFPSList TFPGMap=TFPSMap TFPGMapInterfacedObjectData=TFPSMap �pasdoc/source/component/PasDoc_GenHtml.pas����������������������������������������������������������0000644�0001750�0001750�00000235621�13237143042�021301� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2018 PasDoc developers. This file is part of "PasDoc". "PasDoc" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. "PasDoc" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with "PasDoc"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ---------------------------------------------------------------------------- } { @abstract(Provides HTML document generator object.) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Alexander Lisnevsky (alisnevsky@yandex.ru)) @author(Erwin Scheuch-Heilig (ScheuchHeilig@t-online.de)) @author(Marco Schmidt (marcoschmidt@geocities.com)) @author(Hendy Irawan (ceefour@gauldong.net)) @author(Wim van der Vegt (wvd_vegt@knoware.nl)) @author(Thomas Mueller (www.dummzeuch.de)) @author(David Berg (HTML Layout) <david@sipsolutions.de>) @author(Grzegorz Skoczylas <gskoczylas@rekord.pl>) @author(Michalis Kamburelis) @author(Richard B. Winston <rbwinst@usgs.gov>) @author(Ascanio Pressato) @author(Arno Garrels <first name.name@nospamgmx.de>) Implements an object to generate HTML documentation, overriding many of @link(TDocGenerator)'s virtual methods. } unit PasDoc_GenHtml; {$I pasdoc_defines.inc} interface uses PasDoc_Utils, PasDoc_Gen, PasDoc_Items, PasDoc_Languages, PasDoc_StringVector, PasDoc_Types, Classes, PasDoc_StringPairVector; type { @abstract(generates HTML documentation) Extends @link(TDocGenerator) and overwrites many of its methods to generate output in HTML (HyperText Markup Language) format. } TGenericHTMLDocGenerator = class(TDocGenerator) private FUseTipueSearch: boolean; FNumericFilenames: boolean; FLinkCount: Integer; FHeader, FFooter, FHtmlBodyBegin, FHtmlBodyEnd, FHtmlHead: string; { The content of the CSS file. } FCSS: string; FOddTableRow: boolean; FImages: TStringList; { Makes a link. @param href is the link's reference @param caption is the link's text @param CssClass is the link's CSS class } function MakeLink(const href, caption, CssClass: string): string; { Used by WriteItemsSummary and WriteItemsDetailed. } procedure WriteItemTableRow(Item: TPasItem; ShowVisibility: boolean; WriteItemLink: boolean; MakeAnchor: boolean); procedure WriteItemsSummary(Items: TPasItems; ShowVisibility: boolean; HeadingLevel: Integer; const SectionAnchor: string; SectionName: TTranslationId); procedure WriteItemsDetailed(Items: TPasItems; ShowVisibility: boolean; HeadingLevel: Integer; SectionName: TTranslationId); { Writes information on doc generator to current output stream, including link to pasdoc homepage. } procedure WriteAppInfo; { Writes authors to output, at heading level HL. Will not write anything if collection of authors is not assigned or empty. } procedure WriteAuthors(HL: integer; Authors: TStringVector); procedure WriteCodeWithLinks(const p: TPasItem; const Code: string; WriteItemLink: boolean); procedure WriteEndOfDocument; { Finishes an HTML paragraph element by writing a closing P tag. } procedure WriteEndOfParagraph; { Finishes an HTML table cell by writing a closing TD tag. } procedure WriteEndOfTableCell; { Finishes an HTML table by writing a closing TABLE tag. } procedure WriteEndOfTable; { Finishes an HTML table row by writing a closing TR tag. } procedure WriteEndOfTableRow; procedure WriteFooter; { Writes the Item's AbstractDescription. Only if AbstractDescription is not available, uses DetailedDescription. } procedure WriteItemShortDescription(const AItem: TPasItem); (*Writes the Item's AbstractDescription followed by DetailedDescription. If OpenCloseParagraph then code here will open and close paragraph for itself. So you shouldn't surround it inside WriteStart/EndOfParagraph, like @longcode(# { BAD EXAMPLE } WriteStartOfParagraph; WriteItemLongDescription(Item, true); WriteEndOfParagraph; #) While you can pass OpenCloseParagraph = @false, do it with caution, and note that long description has often such large content that it really should be separated by paragraph. Passing OpenCloseParagraph = @false is sensible only if you will wrap this anyway inside some paragraph or similar block level element. *) procedure WriteItemLongDescription(const AItem: TPasItem; OpenCloseParagraph: boolean = true); { Does WriteItemLongDescription writes anything. When @false, you can avoid calling WriteItemLongDescription altogether. } function HasItemLongDescription(const AItem: TPasItem): boolean; procedure WriteOverviewFiles; procedure WriteStartOfDocument(AName: string); { Starts an HTML paragraph element by writing an opening P tag. } procedure WriteStartOfParagraph; overload; procedure WriteStartOfParagraph(const CssClass: string); overload; { Starts an HTML table with a css class } procedure WriteStartOfTable(const CssClass: string); procedure WriteStartOfTableCell; overload; procedure WriteStartOfTableCell(const CssClass: string); overload; procedure WriteStartOfTable1Column(const CssClass: string); procedure WriteStartOfTable2Columns(const CssClass: string; const t1, t2: string); procedure WriteStartOfTable3Columns(const CssClass: string; const t1, t2, t3: string); procedure WriteStartOfTableRow(const CssClass: string); { Writes a cell into a table row with the Item's visibility image. } procedure WriteVisibilityCell(const Item: TPasItem); { output all the necessary images } procedure WriteBinaryFiles; { output the index.html file } procedure WriteIndex; { write the legend file for visibility markers } procedure WriteVisibilityLegendFile; function MakeImage(const src, alt, CssClass: string): string; { writes a link @param href is the link's reference @param caption is the link's caption (must already been converted) @param CssClass is the link's CSS class } procedure WriteLink(const href, caption, CssClass: string); procedure WriteSpellChecked(const AString: string); { Writes a single class, interface or object CIO to output, at heading level HL. } procedure WriteCIO(HL: integer; const CIO: TPasCio); { Calls @link(WriteCIO) with each element in the argument collection C, using heading level HL. } procedure WriteCIOs(HL: integer; c: TPasItems); procedure WriteCIOSummary(HL: integer; c: TPasItems); { Writes heading S to output, at heading level I. For HTML, only levels 1 to 6 are valid, so that values smaller than 1 will be set to 1 and arguments larger than 6 are set to 6. The String S will then be enclosed in an element from H1 to H6, according to the level. } procedure WriteHeading(HL: integer; const CssClass: string; const s: string); { Returns HTML heading tag. You can also make the anchor at this heading by passing AnchorName <> ''. } function FormatHeading(HL: integer; const CssClass: string; const s: string; const AnchorName: string): string; { Writes dates Created and LastMod at heading level HL to output (if at least one the two has a value assigned). } procedure WriteDates(const HL: integer; const Created, LastMod: string); function FormatAnAnchor(const AName, Caption: string): string; protected { Return common HTML content that goes inside <head>. } function MakeHead: string; { Return common HTML content that goes right after <body>. } function MakeBodyBegin: string; virtual; { Return common HTML content that goes right before </body>. } function MakeBodyEnd: string; virtual; function ConvertString(const s: string): string; override; { Called by @link(ConvertString) to convert a character. Will convert special characters to their html escape sequence -> test } function ConvertChar(c: char): string; override; procedure WriteUnit(const HL: integer; const U: TPasUnit); override; { overrides @inherited.HtmlString to return the string verbatim (@inherited discards those strings) } function HtmlString(const S: string): string; override; // FormatPascalCode will cause Line to be formatted in // the way that Pascal code is formatted in Delphi. function FormatPascalCode(const Line: string): string; override; // FormatComment will cause AString to be formatted in // the way that comments other than compiler directives are // formatted in Delphi. See: @link(FormatCompilerComment). function FormatComment(AString: string): string; override; // FormatHex will cause AString to be formatted in // the way that Hex are formatted in Delphi. function FormatHex(AString: string): string; override; // FormatNumeric will cause AString to be formatted in // the way that Numeric are formatted in Delphi. function FormatNumeric(AString: string): string; override; // FormatFloat will cause AString to be formatted in // the way that Float are formatted in Delphi. function FormatFloat(AString: string): string; override; // FormatKeyWord will cause AString to be formatted in // the way that strings are formatted in Delphi. function FormatString(AString: string): string; override; // FormatKeyWord will cause AString to be formatted in // the way that reserved words are formatted in Delphi. function FormatKeyWord(AString: string): string; override; // FormatCompilerComment will cause AString to be formatted in // the way that compiler directives are formatted in Delphi. function FormatCompilerComment(AString: string): string; override; { Makes a String look like a coded String, i.e. <CODE>TheString</CODE> in Html. } function CodeString(const s: string): string; override; { Returns a link to an anchor within a document. HTML simply concatenates the strings with a "#" character between them. } function CreateLink(const Item: TBaseItem): string; override; procedure WriteStartOfCode; override; procedure WriteEndOfCode; override; procedure WriteAnchor(const AName: string); overload; { Write an anchor. Note that the Caption is assumed to be already processed with the @link(ConvertString). } procedure WriteAnchor(const AName, Caption: string); overload; function Paragraph: string; override; function EnDash: string; override; function EmDash: string; override; function LineBreak: string; override; function URLLink(const URL: string): string; override; procedure WriteExternalCore(const ExternalItem: TExternalItem; const Id: TTranslationID); override; function MakeItemLink(const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; override; function EscapeURL(const AString: string): string; virtual; function FormatSection(HL: integer; const Anchor: string; const Caption: string): string; override; function FormatAnchor(const Anchor: string): string; override; function FormatBold(const Text: string): string; override; function FormatItalic(const Text: string): string; override; function FormatPreformatted(const Text: string): string; override; function FormatImage(FileNames: TStringList): string; override; function FormatList(ListData: TListData): string; override; function FormatTable(Table: TTableData): string; override; function FormatTableOfContents(Sections: TStringPairVector): string; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; { Returns HTML file extension ".htm". } function GetFileExtension: string; override; { The method that does everything - writes documentation for all units and creates overview files. } procedure WriteDocumentation; override; published { some HTML code to be written as header for every page } property Header: string read FHeader write FHeader; { some HTML code to be written as footer for every page } property Footer: string read FFooter write FFooter; property HtmlBodyBegin: string read FHtmlBodyBegin write FHtmlBodyBegin; property HtmlBodyEnd: string read FHtmlBodyEnd write FHtmlBodyEnd; property HtmlHead: string read FHtmlHead write FHtmlHead; { the content of the cascading stylesheet } property CSS: string read FCSS write FCSS; { if set to true, numeric filenames will be used rather than names with multiple dots } property NumericFilenames: boolean read FNumericFilenames write FNumericFilenames default false; { Enable Tiptue fulltext search. See [https://github.com/pasdoc/pasdoc/wiki/UseTipueSearchOption] } property UseTipueSearch: boolean read FUseTipueSearch write FUseTipueSearch default False; end; { Right now this is the same thing as TGenericHTMLDocGenerator. In the future it may be extended to include some things not needed for HtmlHelp generator. } THTMLDocGenerator = class(TGenericHTMLDocGenerator) protected function MakeBodyBegin: string; override; function MakeBodyEnd: string; override; end; const DefaultPasdocCss = {$I pasdoc.css.inc}; implementation uses SysUtils, StrUtils, { if you are using Delphi 5 or fpc 1.1.x you must add ..\component\strutils to your search path } PasDoc_Base, PasDoc_ObjectVector, PasDoc_HierarchyTree, PasDoc_Tipue, PasDoc_Aspell, PasDoc_Versions; const img_automated : {$I automated.gif.inc}; img_private : {$I private.gif.inc}; img_public : {$I public.gif.inc}; img_published : {$I published.gif.inc}; img_protected : {$I protected.gif.inc}; constructor TGenericHTMLDocGenerator.Create(AOwner: TComponent); begin inherited Create(AOwner); FLinkCount := 1; FCSS := DefaultPasdocCss; FImages := TStringList.Create; end; destructor TGenericHTMLDocGenerator.Destroy; begin FImages.Free; inherited; end; function TGenericHTMLDocGenerator.HtmlString(const S: string): string; begin Result := S; end; function TGenericHTMLDocGenerator.FormatString(AString: string): string; begin result := '<span class="pascal_string">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatKeyWord(AString: string): string; begin result := '<span class="pascal_keyword">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatComment(AString: string): string; begin result := '<span class="pascal_comment">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatHex(AString: string): string; begin result := '<span class="pascal_hex">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatNumeric(AString: string): string; begin result := '<span class="pascal_numeric">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatFloat(AString: string): string; begin result := '<span class="pascal_float">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.FormatCompilerComment(AString: string): string; begin result := '<span class="pascal_compiler_comment">' + ConvertString(AString) + '</span>'; end; function TGenericHTMLDocGenerator.CodeString(const s: string): string; begin Result := '<code>' + s + '</code>'; end; function TGenericHTMLDocGenerator.CreateLink(const Item: TBaseItem): string; function NewLink(const AFullName: string): string; begin if NumericFilenames then begin Result := Format('%.8d', [FLinkCount]) + GetFileExtension; Inc(FLinkCount); end else begin Result := AFullName + GetFileExtension; end; end; begin Result := ''; if (not Assigned(Item)) then Exit; if (Item is TPasItem) and Assigned(TPasItem(Item).MyUnit) then begin if (not (Item is TPasCio)) and Assigned(TPasItem(Item).MyObject) then begin { it's a method, a field or a property } Result := TPasItem(Item).MyObject.FullLink + '#' + Item.Name; end else begin if Item is TPasCio then begin { it's an object / a class } Result := NewLink(TPasItem(Item).QualifiedName) end else begin { it's a constant, a variable, a type or a function / procedure } Result := TPasItem(Item).MyUnit.FullLink + '#' + Item.Name; end; end; end else if Item is TAnchorItem then begin Result := TAnchorItem(Item).ExternalItem.FullLink + '#' + Item.Name; end else begin Result := NewLink(Item.Name); end; end; function TGenericHTMLDocGenerator.GetFileExtension: string; begin Result := '.html'; end; procedure TGenericHTMLDocGenerator.WriteAppInfo; begin if (not ExcludeGenerator) or IncludeCreationTime then begin { write a horizontal line, pasdoc version and a link to the pasdoc homepage } WriteDirect('<hr>'); WriteDirect('<span class="appinfo">'); WriteDirect('<em>'); if not ExcludeGenerator then begin WriteConverted(FLanguage.Translation[trGeneratedBy] + ' '); WriteLink(PASDOC_HOMEPAGE, PASDOC_NAME_AND_VERSION, ''); WriteConverted('. '); end; if IncludeCreationTime then begin WriteConverted(FLanguage.Translation[trGeneratedOn] + ' ' + FormatDateTime('yyyy-mm-dd hh:mm:ss', Now)); WriteConverted('.'); end; WriteDirectLine('</em>'); WriteDirectLine('</span>'); end; end; procedure TGenericHTMLDocGenerator.WriteAuthors(HL: integer; Authors: TStringVector); var i: Integer; s, S1, S2: string; Address: string; begin if IsEmpty(Authors) then Exit; if (Authors.Count = 1) then WriteHeading(HL, 'authors', FLanguage.Translation[trAuthor]) else WriteHeading(HL, 'authors', FLanguage.Translation[trAuthors]); WriteDirectLine('<ul class="authors">'); for i := 0 to Authors.Count - 1 do begin s := Authors[i]; WriteDirect('<li>'); if ExtractEmailAddress(s, S1, S2, Address) then begin WriteConverted(S1); WriteLink('mailto:' + Address, ConvertString(Address), ''); WriteConverted(S2); end else if ExtractWebAddress(s, S1, S2, Address) then begin WriteConverted(S1); WriteLink('http://' + Address, ConvertString(Address), ''); WriteConverted(S2); end else begin WriteConverted(s); end; WriteDirectLine('</li>'); end; WriteDirectLine('</ul>'); end; procedure TGenericHTMLDocGenerator.WriteCIO(HL: integer; const CIO: TPasCio); type TSections = (dsDescription, dsHierarchy, dsEnclosingClass, dsInternalCRs, dsInternalTypes, dsFields, dsMethods, dsProperties); TSectionSet = set of TSections; TSectionAnchors = array[TSections] of string; const SectionAnchors: TSectionAnchors = ( 'PasDoc-Description', 'PasDoc-Hierarchy', 'PasDoc-EnclosingClass', 'PasDoc-InternalCRs', 'PasDoc-InternalTypes', 'PasDoc-Fields', 'PasDoc-Methods', 'PasDoc-Properties'); type TCIONames = array[TCIOType] of string; const CIO_NAMES: TCIONames = ( 'class', 'packed class', 'dispinterface', 'interface', 'object', 'packed object', 'record', 'packed record'); procedure WriteMethodsSummary; begin WriteItemsSummary(CIO.Methods, CIO.ShowVisibility, HL + 1, SectionAnchors[dsMethods], trMethods); end; procedure WriteMethodsDetailed; begin WriteItemsDetailed(CIO.Methods, CIO.ShowVisibility, HL + 1, trMethods); end; procedure WritePropertiesSummary; begin WriteItemsSummary(CIO.Properties, CIO.ShowVisibility, HL + 1, SectionAnchors[dsProperties], trProperties); end; procedure WritePropertiesDetailed; begin WriteItemsDetailed(CIO.Properties, CIO.ShowVisibility, HL + 1, trProperties); end; procedure WriteFieldsSummary; begin WriteItemsSummary(CIO.Fields, CIO.ShowVisibility, HL + 1, SectionAnchors[dsFields], trFields); end; procedure WriteFieldsDetailed; begin WriteItemsDetailed(CIO.Fields, CIO.ShowVisibility, HL + 1, trFields); end; procedure WriteInternalCioSummary; var I, J: Integer; LCio: TPasCio; begin for I := 0 to CIO.Cios.Count - 1 do begin LCio := TPasCio(CIO.Cios.PasItemAt[I]); LCio.FullDeclaration := LCIO.NameWithGeneric + ' = ' + CIO_NAMES[LCIO.MyType] + GetClassDirectiveName(LCIO.ClassDirective); if LCio.Ancestors.Count <> 0 then begin LCio.FullDeclaration := LCio.FullDeclaration + '('; for J := 0 to LCIO.Ancestors.Count - 1 do begin LCio.FullDeclaration := LCio.FullDeclaration + LCio.Ancestors[J].Value; if (J <> LCio.Ancestors.Count - 1) then LCio.FullDeclaration := LCio.FullDeclaration + ', '; end; LCio.FullDeclaration := LCio.FullDeclaration + ')'; end; end; WriteItemsSummary(CIO.Cios, CIO.ShowVisibility, HL + 1, SectionAnchors[dsInternalCRs], trInternalCR); end; procedure WriteInternalTypesSummary; begin WriteItemsSummary(CIO.Types, CIO.ShowVisibility, HL + 1, SectionAnchors[dsInternalTypes], trInternalTypes); end; procedure WriteInternalTypesDetailed; begin WriteItemsDetailed(CIO.Types, CIO.ShowVisibility, HL + 1, trInternalTypes); end; { writes all ancestors of the given item and the item itself } procedure WriteHierarchy(Name: string; Item: TBaseItem); var CIO: TPasCio; begin if not Assigned(Item) then begin WriteDirectLine('<li class="ancestor">' + Name + '</li>'); { recursion ends here, when the item is an external class } end else if Item is TPasCio then begin CIO := TPasCio(Item); { first, write the ancestors } WriteHierarchy(CIO.Ancestors.FirstName, CIO.FirstAncestor); { then write itself } WriteDirectLine('<li class="ancestor">' + MakeItemLink(CIO, CIO.UnitRelativeQualifiedName, lcNormal) + '</li>') end; { todo --check: Is it possible that the item is assigned but is not a TPasCio ? } end; var i: Integer; s: string; SectionsAvailable: TSectionSet; SectionHeads: array[TSections] of string; Section: TSections; AnyItem: boolean; Fv: TPasFieldVariable; begin if not Assigned(CIO) then Exit; SectionHeads[dsDescription] := FLanguage.Translation[trDescription]; SectionHeads[dsHierarchy] := FLanguage.Translation[trHierarchy]; SectionHeads[dsFields ]:= FLanguage.Translation[trFields]; SectionHeads[dsMethods ]:= FLanguage.Translation[trMethods]; SectionHeads[dsProperties ]:= FLanguage.Translation[trProperties]; SectionHeads[dsInternalTypes]:= FLanguage.Translation[trInternalTypes]; SectionHeads[dsInternalCRs]:= FLanguage.Translation[trInternalCR]; SectionHeads[dsEnclosingClass]:= FLanguage.Translation[trEnclosingClass]; SectionsAvailable := [dsDescription]; if Assigned(CIO.Ancestors) and (CIO.Ancestors.Count > 0) then Include(SectionsAvailable, dsHierarchy); if not ObjectVectorIsNilOrEmpty(CIO.Fields) then Include(SectionsAvailable, dsFields); if not ObjectVectorIsNilOrEmpty(CIO.Methods) then Include(SectionsAvailable, dsMethods); if not ObjectVectorIsNilOrEmpty(CIO.Properties) then Include(SectionsAvailable, dsProperties); if not ObjectVectorIsNilOrEmpty(CIO.Types) then Include(SectionsAvailable, dsInternalTypes); if not ObjectVectorIsNilOrEmpty(CIO.Cios) then Include(SectionsAvailable, dsInternalCRs); if CIO.MyObject <> nil then Include(SectionsAvailable, dsEnclosingClass); if not ObjectVectorIsNilOrEmpty(CIO.Fields) then begin for I := 0 to CIO.Fields.Count - 1 do begin Fv := TPasFieldVariable(CIO.Fields.PasItemAt[I]); if Fv.IsConstant then Fv.FullDeclaration := FLanguage.Translation[trInternal] + ' ' + Fv.FullDeclaration; end; end; s := GetCIOTypeName(CIO.MyType) + ' ' + CIO.UnitRelativeQualifiedName; WriteStartOfDocument(CIO.MyUnit.Name + ': ' + s); WriteAnchor(CIO.Name); WriteHeading(HL, 'cio', s); WriteDirectLine('<div class="sections">'); for Section := Low(TSections) to High(TSections) do begin { Most classes don't contain nested types so exclude this stuff if not available in order to keep it simple. } if (not (Section in SectionsAvailable)) and (Section in [dsEnclosingClass..dsInternalTypes]) then Continue; WriteDirect('<div class="one_section">'); if Section in SectionsAvailable then WriteLink('#'+SectionAnchors[Section], SectionHeads[Section], 'section') else WriteConverted(SectionHeads[Section]); WriteDirect('</div>'); end; WriteDirectLine('</div>'); WriteAnchor(SectionAnchors[dsDescription]); { write unit link } if Assigned(CIO.MyUnit) then begin WriteHeading(HL + 1, 'unit', FLanguage.Translation[trUnit]); WriteStartOfParagraph('unitlink'); WriteLink(CIO.MyUnit.FullLink, ConvertString(CIO.MyUnit.Name), ''); WriteEndOfParagraph; end; { write declaration link } WriteHeading(HL + 1, 'declaration', FLanguage.Translation[trDeclaration]); WriteStartOfParagraph('declaration'); WriteStartOfCode; WriteConverted('type ' + CIO.NameWithGeneric + ' = '); WriteConverted(CIO_NAMES[CIO.MyType]); WriteConverted(GetClassDirectiveName(CIO.ClassDirective)); if CIO.Ancestors.Count <> 0 then begin WriteConverted('('); for i := 0 to CIO.Ancestors.Count - 1 do begin if CIO.Ancestors[i].Data <> nil then WriteDirect(MakeItemLink(TObject(CIO.Ancestors[i].Data) as TPasItem, CIO.Ancestors[i].Value, lcNormal)) else WriteConverted(CIO.Ancestors[i].Value); if (i <> CIO.Ancestors.Count - 1) then WriteConverted(', '); end; WriteConverted(')'); end; if CIO.ClassDirective = CT_HELPER then WriteConverted(' for ' + CIO.HelperTypeIdentifier); WriteEndOfCode; WriteEndOfParagraph; { Write Description } WriteHeading(HL + 1, 'description', FLanguage.Translation[trDescription]); WriteItemLongDescription(CIO); { Write Hierarchy } if CIO.Ancestors.Count <> 0 then begin WriteAnchor(SectionAnchors[dsHierarchy]); WriteHeading(HL + 1, 'hierarchy', SectionHeads[dsHierarchy]); WriteDirect('<ul class="hierarchy">'); WriteHierarchy(CIO.Ancestors.FirstName, CIO.FirstAncestor); WriteDirect('<li class="thisitem">' + CIO.UnitRelativeQualifiedName + '</li>'); WriteDirect('</ul>'); end; { Write Enclosing Class } if CIO.MyObject <> nil then begin WriteAnchor(SectionAnchors[dsEnclosingClass]); WriteHeading(HL + 1, 'hierarchy', SectionHeads[dsEnclosingClass]); WriteDirect('<ul class="hierarchy"><li class="thisitem">'); WriteLink(CIO.MyObject.FullLink, CIO.MyObject.Name, 'ancestor'); WriteDirect('</li></ul>'); end; AnyItem := (not ObjectVectorIsNilOrEmpty(CIO.Fields)) or (not ObjectVectorIsNilOrEmpty(CIO.Methods)) or (not ObjectVectorIsNilOrEmpty(CIO.Properties)) or (not ObjectVectorIsNilOrEmpty(CIO.Types)) or (not ObjectVectorIsNilOrEmpty(CIO.Cios)); { AnyItem is used here to avoid writing headers "Overview" and "Description" when there are no items. } if AnyItem then begin WriteHeading(HL + 1, 'overview', FLanguage.Translation[trOverview]); WriteInternalCioSummary; WriteInternalTypesSummary; WriteFieldsSummary; WriteMethodsSummary; WritePropertiesSummary; WriteHeading(HL + 1, 'description', FLanguage.Translation[trDescription]); WriteInternalTypesDetailed; WriteFieldsDetailed; WriteMethodsDetailed; WritePropertiesDetailed; end; WriteAuthors(HL + 1, CIO.Authors); WriteDates(HL + 1, CIO.Created, CIO.LastMod); WriteFooter; WriteAppInfo; WriteEndOfDocument; end; procedure TGenericHTMLDocGenerator.WriteCIOs(HL: integer; c: TPasItems); procedure LocalWriteCio(const HL: Integer; const ACio: TPasCio); begin if (ACio.MyUnit <> nil) and ACio.MyUnit.FileNewerThanCache(DestinationDirectory + ACio.OutputFileName) then begin DoMessage(3, pmtInformation, 'Data for "%s" was loaded from cache, '+ 'and output file of this item exists and is newer than cache, '+ 'skipped.', [ACio.Name]); Exit; end; if not CreateStream(ACio.OutputFileName) then Exit; DoMessage(3, pmtInformation, 'Creating Class/Interface/Object file for "%s"...', [ACio.Name]); WriteCIO(HL, ACio); end; procedure LocalWriteCios(const HL: Integer; const ACios: TPasItems); var LCio: TPasCio; I: Integer; begin for I := 0 to ACios.Count -1 do begin LCio := TPasCio(ACios.PasItemAt[I]); LocalWriteCio(HL, LCio); if LCio.Cios.Count > 0 then LocalWriteCios(HL, LCio.Cios); end; end; begin if c = nil then Exit; LocalWriteCios(HL, c); CloseStream; end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteCIOSummary(HL: integer; c: TPasItems); procedure WriteCioRow(ACio: TPasCio); begin WriteStartOfTableRow(''); { name of class/interface/object and unit } WriteStartOfTableCell('itemname'); WriteConverted(GetCIOTypeName(ACio.MyType)); WriteDirect(' '); WriteLink(ACio.FullLink, CodeString(ACio.UnitRelativeQualifiedName), 'bold'); WriteEndOfTableCell; { Description of class/interface/object } WriteStartOfTableCell('itemdesc'); { Write only the AbstractDescription and do not opt for DetailedDescription, like WriteItemShortDescription does. } if ACio.AbstractDescription <> '' then WriteSpellChecked(ACio.AbstractDescription) else WriteDirect(' '); WriteEndOfTableCell; WriteEndOfTableRow; end; var j: Integer; p: TPasCio; begin if ObjectVectorIsNilOrEmpty(c) then Exit; WriteAnchor('PasDoc-Classes'); WriteHeading(HL, 'cio', FLanguage.Translation[trCio]); WriteStartOfTable2Columns('classestable', FLanguage.Translation[trName], FLanguage.Translation[trDescription]); for j := 0 to c.Count - 1 do begin p := TPasCio(c.PasItemAt[j]); WriteCioRow(p); end; WriteEndOfTable; end; procedure TGenericHTMLDocGenerator.WriteCodeWithLinks(const p: TPasItem; const Code: string; WriteItemLink: boolean); begin WriteCodeWithLinksCommon(p, Code, WriteItemLink, '<b>', '</b>'); end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteDates(const HL: integer; const Created, LastMod: string); begin if Created <> '' then begin WriteHeading(HL, 'created', FLanguage.Translation[trCreated]); WriteStartOfParagraph; WriteDirectLine(Created); WriteEndOfParagraph; end; if LastMod <> '' then begin WriteHeading(HL, 'modified', FLanguage.Translation[trLastModified]); WriteStartOfParagraph; WriteDirectLine(LastMod); WriteEndOfParagraph; end; end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteDocumentation; begin StartSpellChecking('sgml'); inherited; WriteUnits(1); WriteBinaryFiles; WriteOverviewFiles; WriteVisibilityLegendFile; WriteIntroduction; WriteConclusion; WriteIndex; if UseTipueSearch then begin DoMessage(2, pmtInformation, 'Writing additional files for tipue search engine', []); TipueAddFiles(Units, Introduction, Conclusion, MakeHead, MakeBodyBegin, MakeBodyEnd, LanguageCode(FLanguage.Language), DestinationDirectory); end; EndSpellChecking; end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteEndOfDocument; begin WriteDirect(MakeBodyEnd); WriteDirect('</body>'); WriteDirectLine('</html>'); end; procedure TGenericHTMLDocGenerator.WriteEndOfCode; begin WriteDirect('</code>'); end; function TGenericHTMLDocGenerator.MakeItemLink( const Item: TBaseItem; const LinkCaption: string; const LinkContext: TLinkContext): string; var CssClass: string; begin if LinkContext = lcNormal then CssClass := 'normal' else CssClass := ''; Result := MakeLink(Item.FullLink, ConvertString(LinkCaption), CssClass); end; function TGenericHTMLDocGenerator.MakeLink( const href, caption, CssClass: string): string; begin Result := Format('<a %s href="%s">%s</a>', [ifthen(CssClass = '', '', 'class="' + CssClass + '"'), EscapeURL(href), caption]); end; procedure TGenericHTMLDocGenerator.WriteLink( const href, caption, CssClass: string); begin WriteDirect(MakeLink(href, caption, CssClass)); end; procedure TGenericHTMLDocGenerator.WriteEndOfParagraph; begin WriteDirectLine('</p>'); end; procedure TGenericHTMLDocGenerator.WriteEndOfTableCell; begin WriteDirectLine('</td>'); end; procedure TGenericHTMLDocGenerator.WriteEndOfTable; begin WriteDirectLine('</table>'); end; procedure TGenericHTMLDocGenerator.WriteEndOfTableRow; begin WriteDirectLine('</tr>'); end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteFooter; begin WriteDirect(Footer); end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteItemTableRow( Item: TPasItem; ShowVisibility: boolean; WriteItemLink: boolean; MakeAnchor: boolean); begin WriteStartOfTableRow(''); if ShowVisibility then WriteVisibilityCell(Item); { todo: assign a class } WriteStartOfTableCell('itemcode'); if MakeAnchor then WriteAnchor(Item.Name); WriteCodeWithLinks(Item, Item.FullDeclaration, WriteItemLink); WriteEndOfTableCell; WriteEndOfTableRow; end; procedure TGenericHTMLDocGenerator.WriteItemsSummary( Items: TPasItems; ShowVisibility: boolean; HeadingLevel: Integer; const SectionAnchor: string; SectionName: TTranslationId); var i: Integer; begin if ObjectVectorIsNilOrEmpty(Items) then Exit; WriteAnchor(SectionAnchor); WriteHeading(HeadingLevel + 1, 'summary', FLanguage.Translation[SectionName]); WriteStartOfTable1Column('summary'); for i := 0 to Items.Count - 1 do WriteItemTableRow(Items.PasItemAt[i], ShowVisibility, true, false); WriteEndOfTable; end; procedure TGenericHTMLDocGenerator.WriteItemsDetailed( Items: TPasItems; ShowVisibility: boolean; HeadingLevel: Integer; SectionName: TTranslationId); var Item: TPasItem; i: Integer; ColumnsCount: Cardinal; begin if ObjectVectorIsNilOrEmpty(Items) then Exit; WriteHeading(HeadingLevel + 1, 'detail', FLanguage.Translation[SectionName]); for i := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[i]; { calculate ColumnsCount } ColumnsCount := 1; if ShowVisibility then Inc(ColumnsCount); WriteStartOfTable('detail'); WriteItemTableRow(Item, ShowVisibility, false, true); { Using colspan="0" below would be easier, but Konqueror and IE can't handle it correctly. It seems that they treat it as colspan="1" ? } WriteDirectLine(Format('<tr><td colspan="%d">', [ColumnsCount])); WriteItemLongDescription(Item); WriteDirectLine('</td></tr>'); WriteEndOfTable; end; end; function TGenericHTMLDocGenerator.FormatHeading(HL: integer; const CssClass: string; const s: string; const AnchorName: string): string; var c: string; begin if (HL < 1) then HL := 1; if HL > 6 then begin DoMessage(2, pmtWarning, 'HTML generator cannot write headlines of level 7 or greater; will use 6 instead.', []); HL := 6; end; c := IntToStr(HL); Result := ConvertString(S); if AnchorName <> '' then Result := '<span id="' + AnchorName + '"></span>' + Result; Result := '<h' + c + ' class="' + CssClass + '">' + Result + '</h' + c + '>' + LineEnding; end; procedure TGenericHTMLDocGenerator.WriteHeading(HL: integer; const CssClass: string; const s: string); begin WriteDirect(FormatHeading(HL, CssClass, s, '')); end; procedure TGenericHTMLDocGenerator.WriteItemShortDescription(const AItem: TPasItem); begin if AItem = nil then Exit; if AItem.AbstractDescription <> '' then begin WriteSpellChecked(AItem.AbstractDescription); end else begin if AItem.DetailedDescription <> '' then begin WriteSpellChecked(AItem.DetailedDescription) end else begin WriteDirect(' '); end; end; end; function TGenericHTMLDocGenerator.HasItemLongDescription(const AItem: TPasItem): boolean; begin Result := Assigned(AItem) and ( (AItem.HintDirectives <> []) or (AItem.AbstractDescription <> '') or (AItem.DetailedDescription <> '') or (AItem is TPasCio) or (not ObjectVectorIsNilOrEmpty(AItem.Attributes)) or (AItem is TPasMethod) or (not ObjectVectorIsNilOrEmpty(AItem.SeeAlso)) or (AItem is TPasEnum) ); end; procedure TGenericHTMLDocGenerator.WriteItemLongDescription( const AItem: TPasItem; OpenCloseParagraph: boolean); procedure WriteDescriptionSectionHeading(const Caption: TTranslationID); begin WriteHeading(6, 'description_section', FLanguage.Translation[Caption]); end; { writes the parameters or exceptions list } procedure WriteParamsOrRaises(Func: TPasMethod; const Caption: TTranslationID; List: TStringPairVector; LinkToParamNames: boolean; const CssListClass: string); procedure WriteParameter(const ParamName: string; const Desc: string); begin { Note that <dt> and <dd> below don't need any CSS class, they can be accessed via "dl.parameters dt" or "dl.parameters dd" (assuming that CssListClass = 'parameters'). } WriteDirect('<dt>'); WriteDirect(ParamName); WriteDirectLine('</dt>'); WriteDirect('<dd>'); WriteSpellChecked(Desc); WriteDirectLine('</dd>'); end; var i: integer; ParamName: string; begin if ObjectVectorIsNilOrEmpty(List) then Exit; WriteDescriptionSectionHeading(Caption); WriteDirectLine('<dl class="' + CssListClass + '">'); for i := 0 to List.Count - 1 do begin ParamName := List[i].Name; if LinkToParamNames then ParamName := SearchLink(ParamName, Func, '', true); WriteParameter(ParamName, List[i].Value); end; WriteDirectLine('</dl>'); end; procedure WriteSeeAlso(SeeAlso: TStringPairVector); var i: integer; SeeAlsoItem: TBaseItem; SeeAlsoLink: string; begin if ObjectVectorIsNilOrEmpty(SeeAlso) then Exit; WriteDescriptionSectionHeading(trSeeAlso); WriteDirectLine('<dl class="see_also">'); for i := 0 to SeeAlso.Count - 1 do begin SeeAlsoLink := SearchLink(SeeAlso[i].Name, AItem, SeeAlso[i].Value, true, SeeAlsoItem); WriteDirect(' <dt>'); if SeeAlsoItem <> nil then WriteDirect(SeeAlsoLink) else WriteConverted(SeeAlso[i].Name); WriteDirectLine('</dt>'); WriteDirect(' <dd>'); if (SeeAlsoItem <> nil) and (SeeAlsoItem is TPasItem) then WriteDirect(TPasItem(SeeAlsoItem).AbstractDescription); WriteDirectLine('</dd>'); end; WriteDirectLine('</dl>'); end; procedure WriteAttributes(Attributes: TStringPairVector); var i: integer; name, value: string; AttributesItem: TBaseItem; AttributesLink: string; begin if ObjectVectorIsNilOrEmpty(Attributes) then Exit; WriteDescriptionSectionHeading(trAttributes); WriteDirectLine('<dl class="attributes">'); for i := 0 to Attributes.Count - 1 do begin WriteDirect(' <dt>'); name := Attributes.Items[I].Name; value := Attributes.Items[I].Value; { In case of attribute named 'GUID', it (may) come from interface GUID. So we should not actually search for identifier named 'GUID' (neither should we make a confusing warning that it cannot be found). } if name = 'GUID' then begin AttributesLink := name; AttributesItem := nil; end else AttributesLink := SearchLink(name, AItem, name, true, AttributesItem); WriteDirect(AttributesLink); WriteConverted(value); WriteDirectLine('</dt>'); WriteDirect(' <dd>'); if (AttributesItem <> nil) and (AttributesItem is TPasItem) then WriteDirect(TPasItem(AttributesItem).AbstractDescription); WriteDirectLine('</dd>'); end; WriteDirectLine('</dl>'); end; procedure WriteReturnDesc(Func: TPasMethod; ReturnDesc: string); begin if ReturnDesc = '' then exit; WriteDescriptionSectionHeading(trReturns); WriteDirect('<p class="return">'); WriteSpellChecked(ReturnDesc); WriteDirect('</p>'); end; procedure WriteHintDirective(const S: string; const Note: string = ''); var Text: string; begin WriteDirect('<p class="hint_directive">'); Text := FLanguage.Translation[trWarning] + ': ' + S; if Note <> '' then Text := Text + ': ' + Note else Text := Text + '.'; WriteConverted(Text); WriteDirect('</p>'); end; var Ancestor: TBaseItem; AncestorName: string; AItemMethod: TPasMethod; EnumMember: TPasItem; i: Integer; begin if not Assigned(AItem) then Exit; if hdDeprecated in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trDeprecated], AItem.DeprecatedNote); if hdPlatform in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trPlatformSpecific]); if hdLibrary in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trLibrarySpecific]); if hdExperimental in AItem.HintDirectives then WriteHintDirective(FLanguage.Translation[trExperimental]); if AItem.AbstractDescription <> '' then begin if OpenCloseParagraph then WriteStartOfParagraph; WriteSpellChecked(AItem.AbstractDescription); if AItem.DetailedDescription <> '' then begin if not AItem.AbstractDescriptionWasAutomatic then begin WriteEndOfParagraph; { always try to write closing </p>, to be clean } WriteStartOfParagraph; end; WriteSpellChecked(AItem.DetailedDescription); end; if OpenCloseParagraph then WriteEndOfParagraph; end else begin if AItem.DetailedDescription <> '' then begin if OpenCloseParagraph then WriteStartOfParagraph; WriteSpellChecked(AItem.DetailedDescription); if OpenCloseParagraph then WriteEndOfParagraph; end else begin if (AItem is TPasCio) and (TPasCio(AItem).Ancestors.Count <> 0) then begin AncestorName := TPasCio(AItem).Ancestors.FirstName; Ancestor := TPasCio(AItem).FirstAncestor; if Assigned(Ancestor) and (Ancestor is TPasItem) then begin WriteDirect('<div class="nodescription">'); WriteConverted(Format( 'No description available, ancestor %s description follows', [AncestorName])); WriteDirect('</div>'); WriteItemLongDescription(TPasItem(Ancestor)); end; end else begin WriteDirect(' '); end; end; end; WriteAttributes(AItem.Attributes); if AItem is TPasMethod then begin AItemMethod := TPasMethod(AItem); WriteParamsOrRaises(AItemMethod, trParameters, AItemMethod.Params, false, 'parameters'); WriteReturnDesc(AItemMethod, AItemMethod.Returns); WriteParamsOrRaises(AItemMethod, trExceptionsRaised, AItemMethod.Raises, true, 'exceptions_raised'); end; WriteSeeAlso(AItem.SeeAlso); if AItem is TPasEnum then begin WriteDescriptionSectionHeading(trValues); WriteDirectLine('<ul>'); for i := 0 to TPasEnum(AItem).Members.Count - 1 do begin EnumMember := TPasEnum(AItem).Members.PasItemAt[i]; WriteDirectLine('<li>'); WriteAnchor(EnumMember.Name, ConvertString(EnumMember.FullDeclaration)); if HasItemLongDescription(EnumMember) then begin WriteConverted(': '); WriteItemLongDescription(EnumMember, false); end; WriteDirectLine('</li>'); end; WriteDirectLine('</ul>'); end; end; { ---------- } procedure TGenericHTMLDocGenerator.WriteOverviewFiles; function CreateOverviewStream(Overview: TCreatedOverviewFile): boolean; var BaseFileName, Headline: string; begin BaseFileName := OverviewFilesInfo[Overview].BaseFileName; Result := CreateStream(BaseFileName + GetFileExtension); if not Result then Exit; DoMessage(3, pmtInformation, 'Writing overview file "' + BaseFileName + '" ...', []); Headline := FLanguage.Translation[ OverviewFilesInfo[Overview].TranslationHeadlineId]; WriteStartOfDocument(Headline); WriteHeading(1, 'allitems', Headline); end; { Creates an output stream that lists up all units and short descriptions. } procedure WriteUnitOverviewFile; var c: TPasItems; Item: TPasItem; j: Integer; begin c := Units; if not CreateOverviewStream(ofUnits) then Exit; if Assigned(c) and (c.Count > 0) then begin WriteStartOfTable2Columns('unitstable', FLanguage.Translation[trName], FLanguage.Translation[trDescription]); for j := 0 to c.Count - 1 do begin Item := c.PasItemAt[j]; WriteStartOfTableRow(''); WriteStartOfTableCell('itemname'); WriteLink(Item.FullLink, Item.Name, 'bold'); WriteEndOfTableCell; WriteStartOfTableCell('itemdesc'); WriteDirect('<p>'); WriteItemShortDescription(Item); WriteDirect('</p>'); WriteEndOfTableCell; WriteEndOfTableRow; end; WriteEndOfTable; end; WriteFooter; WriteAppInfo; WriteEndOfDocument; CloseStream; end; { Writes a Hierarchy list - this is more useful than the simple class list } procedure WriteHierarchy; { todo -o twm: Make this recursive to handle closing </li> easily } var Level, OldLevel: Integer; Node: TPasItemNode; begin CreateClassHierarchy; if not CreateOverviewStream(ofClassHierarchy) then Exit; if FClassHierarchy.IsEmpty then begin WriteStartOfParagraph; WriteConverted(FLanguage.Translation[trNoCIOsForHierarchy]); WriteEndOfParagraph; end else begin OldLevel := -1; Node := FClassHierarchy.FirstItem; while Node <> nil do begin Level := Node.Level; if Level > OldLevel then WriteDirectLine('<ul class="hierarchylevel">') else while Level < OldLevel do begin WriteDirectLine('</ul>'); if OldLevel > 1 then WriteDirectLine('</li>'); Dec(OldLevel); end; OldLevel := Level; WriteDirect('<li>'); if Node.Item = nil then WriteConverted(Node.Name) else WriteLink(Node.Item.FullLink, ConvertString(Node.Item.UnitRelativeQualifiedName), 'bold'); { We can't simply write here an explicit '</li>' because current list item may be not finished yet (in case next Nodes (with larger Level) will follow in the FClassHierarchy). } Node := FClassHierarchy.NextItem(Node); end; while OldLevel > 0 do begin WriteDirectLine('</ul>'); if OldLevel > 1 then WriteDirectLine('</li>'); Dec(OldLevel); end; end; WriteFooter; WriteAppInfo; WriteEndOfDocument; CloseStream; end; procedure WriteItemsOverviewFile(Overview: TCreatedOverviewFile; Items: TPasItems); var Item: TPasItem; j: Integer; begin if not CreateOverviewStream(Overview) then Exit; if not ObjectVectorIsNilOrEmpty(Items) then begin WriteStartOfTable3Columns('itemstable', FLanguage.Translation[trName], FLanguage.Translation[trUnit], FLanguage.Translation[trDescription]); Items.SortShallow; for j := 0 to Items.Count - 1 do begin Item := Items.PasItemAt[j]; WriteStartOfTableRow(''); WriteStartOfTableCell('itemname'); WriteLink(Item.FullLink, Item.UnitRelativeQualifiedName, 'bold'); WriteEndOfTableCell; WriteStartOfTableCell('itemunit'); WriteLink(Item.MyUnit.FullLink, Item.MyUnit.Name, 'bold'); WriteEndOfTableCell; WriteStartOfTableCell('itemdesc'); WriteDirect('<p>'); WriteItemShortDescription(Item); WriteDirect('</p>'); WriteEndOfTableCell; WriteEndOfTableRow; end; WriteEndOfTable; end else begin WriteStartOfParagraph; WriteConverted(FLanguage.Translation[ OverviewFilesInfo[Overview].NoItemsTranslationId]); WriteEndOfParagraph; end; WriteFooter; WriteAppInfo; WriteEndOfDocument; CloseStream; end; var ItemsToCopy: TPasItems; PartialItems: TPasItems; Overview: TCreatedOverviewFile; procedure CiosInsertIntoPartialItems(const ACios: TPasNestedCios); var I: Integer; LCio: TPasCio; begin if Overview = ofCIos then PartialItems.InsertItems(ACios); for I := 0 to ACios.Count -1 do begin LCio := TPasCio(ACios.PasItemAt[I]); if Overview = ofTypes then PartialItems.InsertItems(LCio.Types); if LCio.Cios.Count > 0 then CiosInsertIntoPartialItems(LCio.Cios); end; end; var TotalItems: TPasItems; // Collect all Items for final listing. PU: TPasUnit; i, j: Integer; begin WriteUnitOverviewFile; WriteHierarchy; // Make sure we don't free the Items when we free the container. TotalItems := TPasItems.Create(False); try for Overview := ofCios to HighCreatedOverviewFile do begin // Make sure we don't free the Items when we free the container. PartialItems := TPasItems.Create(False); try for j := 0 to Units.Count - 1 do begin PU := Units.UnitAt[j]; case Overview of ofCIos : ItemsToCopy := PU.CIOs; ofTypes : ItemsToCopy := PU.Types; ofVariables : ItemsToCopy := PU.Variables; ofConstants : ItemsToCopy := PU.Constants; ofFunctionsAndProcedures: ItemsToCopy := PU.FuncsProcs; else ItemsToCopy := nil; end; PartialItems.InsertItems(ItemsToCopy); if (Overview in [ofCIos, ofTypes]) and not ObjectVectorIsNilOrEmpty(PU.CIOs) then for i := 0 to PU.CIOs.Count - 1 do CiosInsertIntoPartialItems(TPasCio(PU.CIOs.PasItemAt[i]).Cios); end; WriteItemsOverviewFile(Overview, PartialItems); TotalItems.InsertItems(PartialItems); finally PartialItems.Free end; end; WriteItemsOverviewFile(ofIdentifiers, TotalItems); finally TotalItems.Free end; end; { ---------------------------------------------------------------------------- } function TGenericHTMLDocGenerator.FormatAnAnchor( const AName, Caption: string): string; begin result := Format('<span id="%s">%s</span>', [AName, Caption]); end; procedure TGenericHTMLDocGenerator.WriteAnchor(const AName: string); begin WriteAnchor(AName, ''); end; procedure TGenericHTMLDocGenerator.WriteAnchor(const AName, Caption: string); begin WriteDirect(FormatAnAnchor(AName, Caption)); end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteStartOfCode; begin WriteDirect('<code>'); end; { ---------------------------------------------------------------------------- } function TGenericHTMLDocGenerator.MakeHead: string; begin Result := '<meta name="viewport" content="width=device-width, initial-scale=1">' + LineEnding; if not ExcludeGenerator then Result := Result + '<meta name="generator" content="' + PASDOC_NAME_AND_VERSION + '">' + LineEnding; if FLanguage.CharSet <> '' then Result := Result + '<meta http-equiv="content-type" content="text/html; charset=' + FLanguage.CharSet + '">' + LineEnding; if UseTipueSearch then Result := Result + TipueSearchButtonHead + LineEnding; // StyleSheet Result := Result + '<link rel="StyleSheet" type="text/css" href="' + EscapeURL('pasdoc.css') + '">' + LineEnding; Result := Result + FHtmlHead; end; function TGenericHTMLDocGenerator.MakeBodyBegin: string; begin Result := FHtmlBodyBegin; end; function TGenericHTMLDocGenerator.MakeBodyEnd: string; begin Result := FHtmlBodyEnd; end; procedure TGenericHTMLDocGenerator.WriteStartOfDocument(AName: string); begin WriteDirectLine('<!DOCTYPE html>'); WriteDirectLine('<html lang="' + LanguageCode(FLanguage.Language) + '">'); WriteDirectLine('<head>'); // Title WriteDirect('<title>'); if Title <> '' then WriteConverted(Title + ': '); WriteConverted(AName); WriteDirectLine(''); WriteDirect(MakeHead); WriteDirectLine(''); WriteDirectLine(''); WriteDirect(MakeBodyBegin); if Length(Header) > 0 then begin WriteSpellChecked(Header); end; end; procedure TGenericHTMLDocGenerator.WriteStartOfParagraph(const CssClass: string); begin if CssClass <> '' then WriteDirectLine('

') else WriteStartOfParagraph; end; procedure TGenericHTMLDocGenerator.WriteStartOfParagraph; begin WriteDirectLine('

'); end; procedure TGenericHTMLDocGenerator.WriteStartOfTable(const CssClass: string); begin FOddTableRow := false; { Every table create by WriteStartOfTable has class wide_list } WriteDirectLine(''); end; procedure TGenericHTMLDocGenerator.WriteStartOfTable1Column(const CssClass: string); begin WriteStartOfTable(CssClass); end; procedure TGenericHTMLDocGenerator.WriteStartOfTable2Columns(const CssClass: string; const t1, t2: string); begin WriteStartOfTable(CssClass); WriteDirectLine(''); WriteDirect(''); WriteDirect(''); WriteDirectLine(''); end; procedure TGenericHTMLDocGenerator.WriteStartOfTable3Columns( const CssClass: string; const t1, t2, t3: string); begin WriteStartOfTable(CssClass); WriteDirectLine(''); WriteDirect(''); WriteDirect(''); WriteDirect(''); WriteDirectLine(''); end; procedure TGenericHTMLDocGenerator.WriteStartOfTableCell( const CssClass: string); var s: string; begin if CssClass <> '' then s := Format(''); end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteUnit(const HL: integer; const U: TPasUnit); type TSections = (dsDescription, dsUses, dsClasses, dsFuncsProcs, dsTypes, dsConstants, dsVariables); TSectionSet = set of TSections; TSectionAnchors = array[TSections] of string; const SectionAnchors: TSectionAnchors = ( 'PasDoc-Description', 'PasDoc-Uses', 'PasDoc-Classes', 'PasDoc-FuncsProcs', 'PasDoc-Types', 'PasDoc-Constants', 'PasDoc-Variables'); procedure WriteUnitDescription(HL: integer; U: TPasUnit); begin WriteHeading(HL, 'description', FLanguage.Translation[trDescription]); WriteItemLongDescription(U); end; procedure WriteUnitUses(const HL: integer; U: TPasUnit); var i: Integer; ULink: TPasItem; begin if WriteUsesClause and not IsEmpty(U.UsesUnits) then begin WriteHeading(HL, 'uses', FLanguage.Translation[trUses]); WriteDirect('
    '); for i := 0 to U.UsesUnits.Count-1 do begin WriteDirect('
  • '); ULink := TPasUnit(U.UsesUnits.Objects[i]); if ULink <> nil then begin WriteLink(ULink.FullLink, U.UsesUnits[i], ''); end else begin WriteConverted(U.UsesUnits[i]); end; WriteDirect('
  • '); end; WriteDirect('
'); end; end; procedure WriteFuncsProcsSummary; begin WriteItemsSummary(U.FuncsProcs, false, HL + 1, SectionAnchors[dsFuncsProcs], trFunctionsAndProcedures); end; procedure WriteFuncsProcsDetailed; begin WriteItemsDetailed(U.FuncsProcs, false, HL + 1, trFunctionsAndProcedures); end; procedure WriteTypesSummary; begin WriteItemsSummary(U.Types, false, HL + 1, SectionAnchors[dsTypes], trTypes); end; procedure WriteTypesDetailed; begin WriteItemsDetailed(U.Types, false, HL + 1, trTypes); end; procedure WriteConstantsSummary; begin WriteItemsSummary(U.Constants, false, HL + 1, SectionAnchors[dsConstants], trConstants); end; procedure WriteConstantsDetailed; begin WriteItemsDetailed(U.Constants, false, HL + 1, trConstants); end; procedure WriteVariablesSummary; begin WriteItemsSummary(U.Variables, false, HL + 1, SectionAnchors[dsVariables], trVariables); end; procedure WriteVariablesDetailed; begin WriteItemsDetailed(U.Variables, false, HL + 1, trVariables); end; var SectionsAvailable: TSectionSet; SectionHeads: array[TSections] of string; Section: TSections; procedure ConditionallyAddSection(Section: TSections; Condition: boolean); begin if Condition then Include(SectionsAvailable, Section); end; var AnyItemSummary, AnyItemDetailed: boolean; begin if not Assigned(U) then begin DoMessage(1, pmtError, 'TGenericHTMLDocGenerator.WriteUnit: ' + 'Unit variable has not been initialized.', []); Exit; end; if U.FileNewerThanCache(DestinationDirectory + U.OutputFileName) then begin DoMessage(3, pmtInformation, 'Data for unit "%s" was loaded from cache, '+ 'and output file of this unit exists and is newer than cache, '+ 'skipped.', [U.Name]); Exit; end; if not CreateStream(U.OutputFileName) then Exit; SectionHeads[dsDescription] := FLanguage.Translation[trDescription]; SectionHeads[dsUses] := FLanguage.Translation[trUses]; SectionHeads[dsClasses] := FLanguage.Translation[trCio]; SectionHeads[dsFuncsProcs]:= FLanguage.Translation[trFunctionsAndProcedures]; SectionHeads[dsTypes]:= FLanguage.Translation[trTypes]; SectionHeads[dsConstants]:= FLanguage.Translation[trConstants]; SectionHeads[dsVariables]:= FLanguage.Translation[trVariables]; SectionsAvailable := [dsDescription]; ConditionallyAddSection(dsUses, WriteUsesClause and not IsEmpty(U.UsesUnits)); ConditionallyAddSection(dsClasses, not ObjectVectorIsNilOrEmpty(U.CIOs)); ConditionallyAddSection(dsFuncsProcs, not ObjectVectorIsNilOrEmpty(U.FuncsProcs)); ConditionallyAddSection(dsTypes, not ObjectVectorIsNilOrEmpty(U.Types)); ConditionallyAddSection(dsConstants, not ObjectVectorIsNilOrEmpty(U.Constants)); ConditionallyAddSection(dsVariables, not ObjectVectorIsNilOrEmpty(U.Variables)); DoMessage(2, pmtInformation, 'Writing Docs for unit "%s"', [U.Name]); WriteStartOfDocument(U.Name); if U.IsUnit then WriteHeading(HL, 'unit', FLanguage.Translation[trUnit] + ' ' + U.Name) else if U.IsProgram then WriteHeading(HL, 'program', FLanguage.Translation[trProgram] + ' ' + U.Name) else WriteHeading(HL, 'library', FLanguage.Translation[trLibrary] + ' ' + U.Name); WriteDirectLine('
'); for Section := Low(TSections) to High(TSections) do begin WriteDirect('
'); if Section in SectionsAvailable then WriteLink('#'+SectionAnchors[Section], SectionHeads[Section], 'section') else WriteConverted(SectionHeads[Section]); WriteDirect('
'); end; WriteDirectLine('
'); WriteAnchor(SectionAnchors[dsDescription]); WriteUnitDescription(HL + 1, U); WriteAnchor(SectionAnchors[dsUses]); WriteUnitUses(HL + 1, U); AnyItemDetailed := (not ObjectVectorIsNilOrEmpty(U.FuncsProcs)) or (not ObjectVectorIsNilOrEmpty(U.Types)) or (not ObjectVectorIsNilOrEmpty(U.Constants)) or (not ObjectVectorIsNilOrEmpty(U.Variables)); AnyItemSummary := AnyItemDetailed or (not ObjectVectorIsNilOrEmpty(U.CIOs)); { AnyItemSummary/Detailed are used here to avoid writing headers "Overview" and "Description" when there are no items. } if AnyItemSummary then begin WriteHeading(HL + 1, 'overview', FLanguage.Translation[trOverview]); WriteCIOSummary(HL + 2, U.CIOs); WriteFuncsProcsSummary; WriteTypesSummary; WriteConstantsSummary; WriteVariablesSummary; end; if AnyItemDetailed then begin WriteHeading(HL + 1, 'description', FLanguage.Translation[trDescription]); WriteFuncsProcsDetailed; WriteTypesDetailed; WriteConstantsDetailed; WriteVariablesDetailed; end; WriteAuthors(HL + 1, U.Authors); WriteDates(HL + 1, U.Created, U.LastMod); WriteFooter; WriteAppInfo; WriteEndOfDocument; CloseStream; WriteCIOs(HL, U.CIOs); end; function TGenericHTMLDocGenerator.MakeImage(const src, alt, CssClass: string): string; begin Result := Format('%s', [IfThen(CssClass = '', '', 'class="' + CssClass + '"'), src, alt, alt]); end; const VisibilityImageName: array[TVisibility] of string = ( 'published.gif', 'public.gif', 'protected.gif', 'protected.gif', 'private.gif', 'private.gif', 'automated.gif', { Implicit visibility uses published visibility image, for now } 'published.gif' ); VisibilityTranslation: array[TVisibility] of TTranslationID = ( trPublished, trPublic, trProtected, trStrictProtected, trPrivate, trStrictPrivate, trAutomated, trImplicit ); procedure TGenericHTMLDocGenerator.WriteVisibilityCell(const Item: TPasItem); procedure WriteVisibilityImage(Vis: TVisibility); begin WriteLink('legend.html', MakeImage(VisibilityImageName[Vis], ConvertString(FLanguage.Translation[ VisibilityTranslation[Vis]]), ''), ''); end; begin WriteStartOfTableCell('visibility'); WriteVisibilityImage(Item.Visibility); WriteEndOfTableCell; end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteVisibilityLegendFile; procedure WriteLegendEntry(Vis: TVisibility); var VisTrans: string; begin VisTrans := FLanguage.Translation[VisibilityTranslation[Vis]]; WriteStartOfTableRow(''); WriteStartOfTableCell('legendmarker'); WriteDirect(MakeImage(VisibilityImageName[Vis], ConvertString(VisTrans), '')); WriteEndOfTableCell; WriteStartOfTableCell('legenddesc'); WriteConverted(VisTrans); WriteEndOfTableCell; WriteEndOfTableRow; end; const Filename = 'legend'; begin if not CreateStream(Filename + GetFileextension) then Abort; try WriteStartOfDocument(FLanguage.Translation[trLegend]); WriteHeading(1, 'markerlegend', FLanguage.Translation[trLegend]); WriteStartOfTable2Columns('markerlegend', FLanguage.Translation[trMarker], FLanguage.Translation[trVisibility]); { Order of entries below is important (because it is shown to the user), so we don't just write all TVisibility values in the order they were declared in TVisibility type. } WriteLegendEntry(viStrictPrivate); WriteLegendEntry(viPrivate); WriteLegendEntry(viStrictProtected); WriteLegendEntry(viProtected); WriteLegendEntry(viPublic); WriteLegendEntry(viPublished); WriteLegendEntry(viAutomated); WriteLegendEntry(viImplicit); WriteEndOfTable; WriteFooter; WriteAppInfo; WriteEndOfDocument; finally CloseStream; end; end; { ---------------------------------------------------------------------------- } procedure TGenericHTMLDocGenerator.WriteSpellChecked(const AString: string); { TODO -- this code is scheduled to convert it to some generic version like WriteSpellCheckedGeneric in TDocGenerator to be able to easily do the similar trick for other output formats like LaTeX and future output formats. Note: don't you dare to copy&paste this code to TTexDocGenerator ! If you want to work on it, make it generic, i.e. copy&paste this code to TDocGenerator and make it "generic" there. *Then* create specialized version in TTexDocGenerator that calls the generic version. Or maybe such generic version should be better inside PasDoc_Aspell ? This doesn't really matter. } var LErrors: TObjectVector; i, temp: Integer; LString, s: string; begin LErrors := TObjectVector.Create(True); CheckString(AString, LErrors); if LErrors.Count = 0 then begin WriteDirect(AString); end else begin // build s s := ''; LString := AString; for i := LErrors.Count-1 downto 0 do begin // everything after the offending word temp := TSpellingError(LErrors.Items[i]).Offset+Length(TSpellingError(LErrors.Items[i]).Word) + 1; s := ( '">' + TSpellingError(LErrors.Items[i]).Word + '' + Copy(LString, temp, MaxInt)) + s; // insert into string if Length(TSpellingError(LErrors.Items[i]).Suggestions) > 0 then begin s := 'suggestions: '+TSpellingError(LErrors.Items[i]).Suggestions + s; end else begin s := 'no suggestions' + s; end; s := ' and

are needed ? Well, basic idea is that pasdoc should always try to make closing and opening tags explicit, even though they can be omitted for paragraphs in html. And paragraph must end before

 and if there is any text after
    
than new paragraph must be opened. Besides the feeling of being "clean", specifying explicit paragraph endings is also important because IE sometimes reacts stupidly when paragraph is not explicitly closed, see [http://sourceforge.net/mailarchive/message.php?msg_id=11388479]. In order to fix it, WriteItemLongDescription always wraps what it writes between

...

This works perfectly except for the cases where @longcode is at the end of description, then we have

Some text

Some Pascal code

Because there is no text between "" and "

" this means that paragraph is not implicitly opened there. This, in turn, means that html validator complains that we have

without opening a paragraph. So the clean solution must be to mark explicitly that paragraph always ends before
 and always begins after 
. } result := '

' + LineEnding + LineEnding + '
' +
       inherited FormatPascalCode(Line) + '
' + LineEnding + LineEnding + '

'; end; function TGenericHTMLDocGenerator.Paragraph: string; begin { LineEndings are inserted here only to make HTML sources look more readable (this makes life easier when looking for pasdoc's bugs, comparing generating two tests results etc.). They are of course meaningless for anything that interprets this HTML. } Result := LineEnding + LineEnding + '

'; end; function TGenericHTMLDocGenerator.EnDash: string; begin Result := '–'; end; function TGenericHTMLDocGenerator.EmDash: string; begin Result := '—'; end; function TGenericHTMLDocGenerator.LineBreak: string; begin Result := '
'; end; function TGenericHTMLDocGenerator.URLLink(const URL: string): string; begin Result := MakeLink(URL, ConvertString(URL), ''); end; procedure TGenericHTMLDocGenerator.WriteExternalCore( const ExternalItem: TExternalItem; const Id: TTranslationID); var HL: integer; begin if not CreateStream(ExternalItem.OutputFileName) then Exit; WriteStartOfDocument(ExternalItem.ShortTitle); HL := 1; WriteHeading(HL, 'externalitem', ExternalItem.Title); WriteSpellChecked(ExternalItem.DetailedDescription); WriteAuthors(HL + 1, ExternalItem.Authors); WriteDates(HL + 1, ExternalItem.Created, ExternalItem.LastMod); WriteFooter; WriteAppInfo; WriteEndOfDocument; CloseStream; end; function TGenericHTMLDocGenerator.FormatSection(HL: integer; const Anchor, Caption: string): string; begin { We use `HL + 1' because user is allowed to use levels >= 1, and heading level 1 is reserved for section title. } result := FormatHeading(HL + 1, '', Caption, Anchor); end; function TGenericHTMLDocGenerator.FormatAnchor( const Anchor: string): string; begin result := FormatAnAnchor(Anchor, ''); end; function TGenericHTMLDocGenerator.FormatBold(const Text: string): string; begin Result := '' + Text + ''; end; function TGenericHTMLDocGenerator.FormatItalic(const Text: string): string; begin Result := '' + Text + ''; end; function TGenericHTMLDocGenerator.FormatPreformatted( const Text: string): string; begin { See TGenericHTMLDocGenerator.FormatPascalCode for comments why these

and

are needed here. LineEndings are added only to make html source more readable. } Result := '

' + LineEnding + LineEnding + '
' +
       inherited FormatPreformatted(Text) + '
' + LineEnding + LineEnding + '

'; end; function TGenericHTMLDocGenerator.FormatImage(FileNames: TStringList): string; var ChosenFileName, OutputImageFileName: string; ImageId, I: Integer; CopyNeeded: boolean; begin { Calculate ChosenFileName, i.e. choose right image format for html. Anything other than eps or pdf is good. } ChosenFileName := ''; for I := 0 to FileNames.Count - 1 do if (LowerCase(ExtractFileExt(FileNames[I])) <> '.eps') and (LowerCase(ExtractFileExt(FileNames[I])) <> '.pdf') then begin ChosenFileName := FileNames[I]; Break; end; if ChosenFileName = '' then ChosenFileName := FileNames[0]; { Calculate ImageId and CopyNeeded } ImageId := FImages.IndexOf(ChosenFileName); CopyNeeded := ImageId = -1; if CopyNeeded then ImageId := FImages.Add(ChosenFileName); OutputImageFileName := 'image_' + IntToStr(ImageId) + ExtractFileExt(ChosenFileName); if CopyNeeded then CopyFile(ChosenFileName, DestinationDirectory + OutputImageFileName); Result := Format('%s', [ OutputImageFileName, { Just use basename of chosen filename, that's the best alt text for the image as we can get... } DeleteFileExt(ExtractFileName(ChosenFileName))]); end; function TGenericHTMLDocGenerator.FormatList(ListData: TListData): string; const ListTag: array[TListType]of string = ( 'ul', 'ol', 'dl' ); ListClass: array[TListItemSpacing]of string = ( 'compact_spacing', 'paragraph_spacing' ); var i: Integer; ListItem: TListItemData; Attributes: string; begin { We're explicitly marking end of previous paragraph and beginning of next one. This is required to always validate clearly. This also makes empty lists (no items) be handled correctly, i.e. they should produce paragraph break. } Result := '

' + LineEnding + LineEnding; { HTML requires that
    /
      contains at least one
    • . } if ListData.Count <> 0 then begin Result := Result + Format('<%s class="%s">', [ListTag[ListData.ListType], ListClass[ListData.ItemSpacing]]) + LineEnding; for i := 0 to ListData.Count - 1 do begin ListItem := ListData.Items[i] as TListItemData; if ListData.ListType = ltDefinition then begin { Note: We're not writing

      ..

      inside
      , because officially
      can't contain any paragraphs. Yes, this means that if user will use paragraphs inside @itemLabel then our output HTML will not be validated as correct HTML. I don't see any easy way to fix this ? After all we don't want to "fake"
      ,
      and
      using some other tags and complex css. So I guess that this should be blamed as an "unavoidable limitation of HTML output", if someone will ask :) -- Michalis } Result := Result + '
      ' + ListItem.ItemLabel + '
      ' + LineEnding + '

      ' + ListItem.Text + '

      ' + LineEnding; end else begin if ListData.ListType = ltOrdered then Attributes := Format(' value="%d"', [ListItem.Index]) else Attributes := ''; Result := Result + Format('

      %s

    • ', [Attributes, ListItem.Text]) + LineEnding; end; end; Result := Result + Format('', [ListTag[ListData.ListType]]) + LineEnding + LineEnding; end; Result := Result + '

      '; end; function TGenericHTMLDocGenerator.FormatTable(Table: TTableData): string; const CellTag: array[boolean]of string = ('td', 'th'); var RowNum, ColNum: Integer; Row: TRowData; NormalRowOdd: boolean; RowClass: string; begin Result := '

      ' + LineEnding + LineEnding + '
'); WriteConverted(t1); WriteDirectLine(''); WriteConverted(t2); WriteDirectLine('
'); WriteConverted(t1); WriteDirectLine(''); WriteConverted(t2); WriteDirectLine(''); WriteConverted(t3); WriteDirectLine('
'); end; procedure TGenericHTMLDocGenerator.WriteStartOfTableCell; begin WriteStartOfTableCell(''); end; procedure TGenericHTMLDocGenerator.WriteStartOfTableRow(const CssClass: string); var s: string; begin if CssClass <> '' then begin s := Format('
' + LineEnding; NormalRowOdd := true; for RowNum := 0 to Table.Count - 1 do begin Row := Table.Items[RowNum] as TRowData; if Row.Head then RowClass := 'head' else begin if NormalRowOdd then RowClass := 'odd' else RowClass := 'even'; NormalRowOdd := not NormalRowOdd; end; Result := Result + ' ' + LineEnding; for ColNum := 0 to Row.Cells.Count - 1 do Result := Result + Format(' <%s>

%s

%2:s', [CellTag[Row.Head], Row.Cells[ColNum], LineEnding]); Result := Result + ' ' + LineEnding; end; Result := Result + '
' + LineEnding + LineEnding + '

'; end; function TGenericHTMLDocGenerator.FormatTableOfContents( Sections: TStringPairVector): string; var i: Integer; begin if Sections.Count = 0 then begin Result := ''; Exit; end; Result := '

    ' + LineEnding; for i := 0 to Sections.Count - 1 do begin Result := Result + '
  1. ' + Sections[i].Value + '' + LineEnding + FormatTableOfContents(TStringPairVector(Sections[i].Data)) + '
  2. ' + LineEnding; end; Result := Result + '
' + LineEnding; end; { THTMLDocGenerator ---------------------------------------------------------- } function THTMLDocGenerator.MakeBodyBegin: string; function MakeNavigation: string; function LocalMakeLink(const Filename, Caption: string): string; overload; begin Result := '

' + ConvertString(Caption) + '

'; end; function LocalMakeLink(const Filename: string; CaptionId: TTranslationID): string; overload; begin Result := LocalMakeLink(Filename, FLanguage.Translation[CaptionId]); end; var Overview: TCreatedOverviewFile; begin Result := ''; if Title <> '' then Result := Result + '

' + ConvertString(Title) + '

'; if Introduction <> nil then begin if Introduction.ShortTitle = '' then Result := Result + LocalMakeLink(Introduction.OutputFileName, trIntroduction) else Result := Result + LocalMakeLink(Introduction.OutputFileName, Introduction.ShortTitle); end; for Overview := LowCreatedOverviewFile to HighCreatedOverviewFile do Result := Result + LocalMakeLink( OverviewFilesInfo[Overview].BaseFileName + GetFileExtension, OverviewFilesInfo[Overview].TranslationId); if LinkGraphVizUses <> '' then Result := Result + LocalMakeLink( OverviewFilesInfo[ofGraphVizUses].BaseFileName + '.' + LinkGraphVizUses, OverviewFilesInfo[ofGraphVizUses].TranslationId); if LinkGraphVizClasses <> '' then Result := Result + LocalMakeLink( OverviewFilesInfo[ofGraphVizClasses].BaseFileName + '.' + LinkGraphVizClasses, OverviewFilesInfo[ofGraphVizClasses].TranslationId); if Conclusion <> nil then begin if Conclusion.ShortTitle = '' then Result := Result + LocalMakeLink(Conclusion.OutputFileName, trConclusion) else Result := Result + LocalMakeLink(Conclusion.OutputFileName, Conclusion.ShortTitle); end; if UseTipueSearch then Result := Result + Format(TipueSearchButton, [ConvertString(FLanguage.Translation[trSearch])]); end; begin Result := inherited; { TODO: get rid of layout, use
for navigation instead } Result := Result + '
' + LineEnding; end; function THTMLDocGenerator.MakeBodyEnd: string; begin Result := '
'; // end Result := Result + inherited; end; end. pasdoc/source/component/tipue/0000700000175000017500000000000013237143042017110 5ustar michalismichalispasdoc/source/component/tipue/README0000600000175000017500000000214613034465644020007 0ustar michalismichalisIntegration with Tipue (http://www.tipue.com/search/ ), version 3.0.1. Some of the files here are copied from Tipue sources (it's Ok to copy, MIT license). The tipuesearch.css needed some tiny modifications (see "PasDoc" comments inside). Our results page is called "_tipue_results.html" (we picked a name to avoid collisions with user unit name). These files are processed by programs file_to_pascal_string and file_to_pascal_data (in ../../tools/) and then their contents are included in PasDoc_Tipue unit. So all the needed tipue data is compiled inside pasdoc binary. This way you don't have to download and unpack tipue to use it with pasdoc --- Tipue data is inside PasDoc sources, and compiled inside PasDoc binary. As pasdoc can automatically generate tipue index data, users do not have to do (or even know) *anything* about tipue to use it with pasdoc. It's just a matter of passing --use-tipue-search. (we can't use tipue by default, without explicit request by --use-tipue-search option, since it's not suitable for really large documentation, see [https://github.com/pasdoc/pasdoc/wiki/UseTipueSearchOption]). pasdoc/source/component/tipue/search.png0000700000175000017500000000047313034465544021103 0ustar michalismichalisPNG  IHDRH-IDAT(SA Eo;T P*@ׁS%wrf$??uYYC 0 sYUi;Zn ))aLAaZ=xqF@]=)4 @&bIM/_Z lلDk1T)U] 8U_"Wu}i: V@ EO֣<2MJ~O39"Ԣ+M#DuȿTrFNޠ rH'IENDB`pasdoc/source/component/tipue/tipuesearch.js0000600000175000017500000004404213034465544022001 0ustar michalismichalis /* Tipue Search 3.0.1 Copyright (c) 2013 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ (function($) { $.fn.tipuesearch = function(options) { var set = $.extend( { 'show' : 7, 'newWindow' : false, 'showURL' : true, 'minimumLength' : 3, 'descriptiveWords' : 25, 'highlightTerms' : true, 'highlightEveryTerm' : false, 'mode' : 'static', 'liveDescription' : '*', 'liveContent' : '*', 'contentLocation' : 'tipuesearch/tipuesearch_content.json' }, options); return this.each(function() { var tipuesearch_in = { pages: [] }; $.ajaxSetup({ async: false }); if (set.mode == 'live') { for (var i = 0; i < tipuesearch_pages.length; i++) { $.get(tipuesearch_pages[i], '', function (html) { var cont = $(set.liveContent, html).text(); cont = cont.replace(/\s+/g, ' '); var desc = $(set.liveDescription, html).text(); desc = desc.replace(/\s+/g, ' '); var t_1 = html.toLowerCase().indexOf(''); var t_2 = html.toLowerCase().indexOf('', t_1 + 7); if (t_1 != -1 && t_2 != -1) { var tit = html.slice(t_1 + 7, t_2); } else { var tit = 'No title'; } tipuesearch_in.pages.push({ "title": tit, "text": desc, "tags": cont, "loc": tipuesearch_pages[i] }); } ); } } if (set.mode == 'json') { $.getJSON(set.contentLocation, function(json) { tipuesearch_in = $.extend({}, json); } ); } if (set.mode == 'static') { tipuesearch_in = $.extend({}, tipuesearch); } var tipue_search_w = ''; if (set.newWindow) { tipue_search_w = ' target="_blank"'; } function getURLP(name) { return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20')) || null; } if (getURLP('q')) { $('#tipue_search_input').val(getURLP('q')); getTipueSearch(0, true); } $('#tipue_search_button').click(function() { getTipueSearch(0, true); }); $(this).keyup(function(event) { if(event.keyCode == '13') { getTipueSearch(0, true); } }); function getTipueSearch(start, replace) { $('#tipue_search_content').hide(); var out = ''; var results = ''; var show_replace = false; var show_stop = false; var d = $('#tipue_search_input').val().toLowerCase(); d = $.trim(d); var d_w = d.split(' '); d = ''; for (var i = 0; i < d_w.length; i++) { var a_w = true; for (var f = 0; f < tipuesearch_stop_words.length; f++) { if (d_w[i] == tipuesearch_stop_words[f]) { a_w = false; show_stop = true; } } if (a_w) { d = d + ' ' + d_w[i]; } } d = $.trim(d); d_w = d.split(' '); if (d.length >= set.minimumLength) { if (replace) { var d_r = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_replace.words.length; f++) { if (d_w[i] == tipuesearch_replace.words[f].word) { d = d.replace(d_w[i], tipuesearch_replace.words[f].replace_with); show_replace = true; } } } d_w = d.split(' '); } var d_t = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_stem.words.length; f++) { if (d_w[i] == tipuesearch_stem.words[f].word) { d_t = d_t + ' ' + tipuesearch_stem.words[f].stem; } } } d_w = d_t.split(' '); var c = 0; found = new Array(); for (var i = 0; i < tipuesearch_in.pages.length; i++) { var score = 1000000000; var s_t = tipuesearch_in.pages[i].text; for (var f = 0; f < d_w.length; f++) { var pat = new RegExp(d_w[f], 'i'); if (tipuesearch_in.pages[i].title.search(pat) != -1) { score -= (200000 - i); } if (tipuesearch_in.pages[i].text.search(pat) != -1) { score -= (150000 - i); } if (set.highlightTerms) { if (set.highlightEveryTerm) { var patr = new RegExp('(' + d_w[f] + ')', 'gi'); } else { var patr = new RegExp('(' + d_w[f] + ')', 'i'); } s_t = s_t.replace(patr, "$1"); } if (tipuesearch_in.pages[i].tags.search(pat) != -1) { score -= (100000 - i); } } if (score < 1000000000) { found[c++] = score + '^' + tipuesearch_in.pages[i].title + '^' + s_t + '^' + tipuesearch_in.pages[i].loc; } } if (c != 0) { if (show_replace == 1) { out += '
Showing results for ' + d + '
'; out += '
Search for ' + d_r + '
'; } if (c == 1) { out += '
1 result
'; } else { c_c = c.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); out += '
' + c_c + ' results
'; } found.sort(); var l_o = 0; for (var i = 0; i < found.length; i++) { var fo = found[i].split('^'); if (l_o >= start && l_o < set.show + start) { out += ''; var t = fo[2]; var t_d = ''; var t_w = t.split(' '); if (t_w.length < set.descriptiveWords) { t_d = t; } else { for (var f = 0; f < set.descriptiveWords; f++) { t_d += t_w[f] + ' '; } } t_d = $.trim(t_d); if (t_d.charAt(t_d.length - 1) != '.') { t_d += ' ...'; } out += '
' + t_d + '
'; if (set.showURL) { t_url = fo[3]; if (t_url.length > 45) { t_url = fo[3].substr(0, 45) + ' ...'; } out += ''; } } l_o++; } if (c > set.show) { var pages = Math.ceil(c / set.show); var page = (start / set.show); out += '
    '; if (start > 0) { out += '
  • Prev
  • '; } if (page <= 2) { var p_b = pages; if (pages > 3) { p_b = 3; } for (var f = 0; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } else { var p_b = page + 3; if (p_b > pages) { p_b = pages; } for (var f = page; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } if (page + 1 != pages) { out += '
  • Next
  • '; } out += '
'; } } else { out += '
Nothing found
'; } } else { if (show_stop) { out += '
Nothing found
Common words are largely ignored
'; } else { out += '
Search too short
'; if (set.minimumLength == 1) { out += '
Should be one character or more
'; } else { out += '
Should be ' + set.minimumLength + ' characters or more
'; } } } $('#tipue_search_content').html(out); $('#tipue_search_content').slideDown(200); $('#tipue_search_replaced').click(function() { getTipueSearch(0, false); }); $('.tipue_search_foot_box').click(function() { var id_v = $(this).attr('id'); var id_a = id_v.split('_'); getTipueSearch(parseInt(id_a[0]), id_a[1]); }); } }); }; })(jQuery); pasdoc/source/component/tipue/loader.gif.inc0000600000175000017500000005147013237143042021626 0ustar michalismichalis{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "loader.gif" } array [0 .. 4177] of Byte = ( $47, $49, $46, $38, $39, $61, $20, $00, $20, $00, $F5, $00, $00, $FF, $FF, $FF, $55, $55, $55, $FB, $FB, $FB, $D7, $D7, $D7, $EF, $EF, $EF, $F4, $F4, $F4, $DF, $DF, $DF, $A8, $A8, $A8, $BB, $BB, $BB, $F8, $F8, $F8, $EE, $EE, $EE, $FC, $FC, $FC, $B6, $B6, $B6, $AE, $AE, $AE, $EB, $EB, $EB, $CF, $CF, $CF, $BF, $BF, $BF, $F2, $F2, $F2, $C8, $C8, $C8, $E7, $E7, $E7, $7E, $7E, $7E, $8E, $8E, $8E, $94, $94, $94, $A7, $A7, $A7, $C4, $C4, $C4, $F3, $F3, $F3, $86, $86, $86, $9C, $9C, $9C, $5C, $5C, $5C, $55, $55, $55, $DE, $DE, $DE, $DA, $DA, $DA, $E4, $E4, $E4, $72, $72, $72, $93, $93, $93, $68, $68, $68, $87, $87, $87, $CA, $CA, $CA, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $21, $FE, $1A, $43, $72, $65, $61, $74, $65, $64, $20, $77, $69, $74, $68, $20, $61, $6A, $61, $78, $6C, $6F, $61, $64, $2E, $69, $6E, $66, $6F, $00, $21, $F9, $04, $00, $0A, $00, $00, $00, $21, $FF, $0B, $4E, $45, $54, $53, $43, $41, $50, $45, $32, $2E, $30, $03, $01, $00, $00, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $24, $16, $38, $1C, $47, $71, $C9, $24, $4E, $12, $C4, $41, $A7, $33, $28, $0A, $9A, $4C, $09, $C5, $12, $9D, $56, $87, $05, $05, $14, $4B, $7C, $50, $28, $8F, $A1, $94, $3A, $14, $28, $14, $05, $72, $B1, $42, $D1, $8C, $D7, $5F, $40, $58, $21, $2F, $1A, $CE, $0C, $42, $78, $42, $6E, $62, $7D, $45, $17, $67, $04, $00, $83, $00, $6F, $11, $72, $06, $06, $45, $04, $67, $1B, $8C, $5E, $00, $09, $6F, $57, $44, $09, $63, $00, $04, $07, $07, $0C, $4A, $43, $10, $67, $13, $05, $03, $03, $05, $0B, $6F, $71, $6D, $11, $6F, $0B, $84, $08, $A3, $07, $10, $B1, $09, $17, $93, $45, $0B, $19, $B5, $00, $0B, $7B, $70, $7E, $0D, $B8, $03, $9D, $72, $C5, $11, $CB, $44, $02, $0F, $B8, $18, $7D, $C5, $A0, $4D, $05, $10, $07, $A6, $64, $AF, $AE, $87, $A1, $E0, $C2, $4B, $02, $05, $E6, $E7, $05, $CF, $72, $02, $EC, $ED, $02, $0B, $AC, $F1, $F1, $8B, $87, $85, $6F, $F7, $0A, $F2, $F2, $7C, $F5, $F8, $F8, $E5, $E8, $CC, $A9, $C3, $B2, $C0, $5D, $BB, $71, $BF, $C4, $81, $D3, $A4, $60, $20, $39, $43, $EB, $66, $29, $80, $24, $27, $C3, $3D, $87, $C3, $8A, $7D, $93, $43, $EC, $5E, $06, $75, $9B, $1E, $2D, $FB, $48, $2E, $18, $21, $89, $10, $85, $DC, $BB, $16, $F2, $DD, $A7, $05, $AF, $8C, $0D, $09, $C9, $4F, $C8, $4B, $22, $31, $E3, $14, $BA, $B2, $07, $E4, $35, $2E, $26, $7B, $6A, $ED, $54, $A9, $20, $C3, $42, $42, $6F, $C6, $0C, $65, $D8, $F0, $A8, $C4, $36, $9C, $86, $3C, $05, $B7, $14, $40, $D5, $42, $3F, $B1, $B8, $31, $0A, $B5, $29, $18, $AF, $47, $BB, $62, $0C, $4B, $84, $16, $B8, $20, $00, $21, $F9, $04, $00, $0A, $00, $01, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $24, $26, $34, $1A, $42, $71, $C9, $24, $12, $04, $44, $03, $85, $62, $28, $0E, $9A, $CC, $CF, $01, $11, $9D, $56, $87, $A2, $CE, $06, $5B, $34, $1C, $0E, $5F, $80, $94, $3A, $1C, $74, $3A, $22, $72, $91, $71, $68, $40, $D5, $DE, $61, $A8, $C3, $29, $C8, $89, $0E, $67, $0F, $42, $6B, $5F, $10, $6F, $07, $7F, $45, $18, $67, $7E, $85, $00, $05, $1C, $1D, $23, $72, $04, $4A, $44, $05, $67, $10, $78, $6C, $07, $6F, $57, $46, $09, $43, $09, $03, $03, $1F, $7E, $6D, $67, $04, $09, $06, $06, $09, $0E, $6F, $14, $44, $02, $11, $0A, $0A, $0B, $42, $0B, $1E, $A5, $03, $06, $77, $02, $18, $0E, $4B, $06, $21, $C2, $00, $0B, $05, $B6, $0A, $A8, $43, $04, $BC, $03, $0E, $B8, $7F, $C9, $B6, $11, $77, $45, $0B, $13, $BC, $20, $D3, $CA, $A2, $64, $02, $06, $03, $CC, $58, $0B, $CB, $D2, $7F, $DF, $7F, $E8, $D8, $02, $EE, $EF, $02, $EC, $72, $F0, $EF, $E6, $CA, $F7, $D7, $F3, $F7, $FB, $FC, $0A, $EA, $FA, $FD, $16, $D0, $73, $27, $AF, $DC, $C0, $78, $4D, $0A, $26, $54, $24, $24, $81, $82, $7C, $4D, $04, $F8, $FB, $43, $AB, $DA, $9F, $0C, $CA, $20, $0E, $41, $A6, $AC, $80, $42, $6C, $D4, $14, $64, $80, $E8, $B0, $DA, $B5, $91, $4B, $04, $64, $90, $56, $D1, $D6, $3F, $6F, $46, $6C, $2D, $58, $90, $20, $C1, $4C, $5B, $E4, $4A, $2A, $08, $C5, $CE, $9E, $1F, $36, $89, $0F, $21, $D9, $22, $F9, $8F, $09, $35, $5C, $40, $EF, $D8, $CA, $C0, $70, $08, $D0, $6F, $49, $1B, $0E, $6D, $0A, $A0, $D6, $4E, $21, $51, $85, $58, $6D, $9A, $15, $40, $D7, $A7, $0C, $25, $32, $75, $3A, $75, $48, $32, $8D, $5C, $CB, $52, $95, $23, $93, $61, $10, $00, $21, $F9, $04, $00, $0A, $00, $02, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $24, $0A, $1A, $8D, $42, $71, $C9, $24, $26, $16, $44, $C7, $E1, $E0, $28, $1A, $9A, $4C, $C5, $C0, $13, $9D, $56, $87, $0D, $0A, $03, $5B, $24, $0C, $06, $84, $A1, $94, $3A, $34, $50, $28, $0D, $72, $F1, $73, $86, $02, $D6, $5F, $80, $85, $A2, $49, $C8, $89, $05, $67, $13, $42, $78, $42, $0F, $6F, $10, $7F, $45, $20, $67, $02, $77, $5E, $00, $09, $1A, $14, $15, $72, $02, $8E, $46, $67, $57, $85, $10, $6F, $57, $44, $0C, $63, $42, $0B, $0A, $0A, $11, $98, $84, $67, $09, $02, $0E, $0E, $02, $04, $6F, $1B, $44, $25, $23, $1D, $1D, $9F, $00, $19, $A5, $0A, $05, $76, $0B, $20, $4A, $45, $13, $16, $69, $00, $6E, $B6, $1D, $14, $45, $02, $BB, $0A, $7E, $7F, $05, $22, $C8, $23, $89, $4C, $09, $BB, $C1, $64, $24, $B6, $1C, $07, $D9, $4C, $0B, $05, $0A, $A8, $58, $06, $1D, $22, $79, $72, $76, $7F, $B8, $45, $0B, $97, $F0, $97, $EB, $7F, $F1, $F0, $A4, $CD, $BB, $E4, $64, $CC, $F8, $FD, $CD, $CF, $F4, $FC, $29, $78, $57, $4F, $C0, $3C, $32, $04, $EB, $1D, $1C, $B2, $B0, $49, $C3, $26, $D7, $F4, $31, $61, $06, $10, $8B, $80, $08, $A5, $22, $FC, $D1, $55, $4A, $E2, $28, $71, $A5, $7A, $FD, $09, $B7, $2B, $83, $BE, $6B, $19, $51, $99, $5C, $22, $20, $83, $9D, $8B, $BB, $2A, $C6, $74, $52, $6A, $C1, $82, $04, $4F, $EE, $7D, $43, $A9, $C0, $C9, $13, $37, $22, $3A, $01, $F0, $73, $04, $F2, $64, $45, $26, $20, $A1, $0C, $15, $52, $2A, $83, $22, $23, $A5, $9E, $2D, $8D, $D4, $F1, $A9, $10, $8C, $3D, $85, $4C, $05, $80, $D5, $EA, $D6, $AF, $51, $9F, $32, $73, $3A, $64, $2B, $00, $71, $1E, $C5, $56, $B5, $AA, $A8, $E6, $D3, $20, $00, $21, $F9, $04, $00, $0A, $00, $03, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $24, $2E, $06, $03, $41, $71, $C9, $34, $16, $0B, $C8, $42, $D1, $D1, $64, $26, $14, $19, $22, $74, $20, $1D, $96, $0E, $8F, $6A, $51, $A0, $50, $28, $85, $DB, $2E, $C0, $71, $38, $94, $C4, $C5, $48, $79, $98, $1E, $22, $0E, $8D, $33, $5C, $48, $56, $24, $D0, $51, $42, $06, $6D, $03, $7B, $4F, $65, $0B, $00, $75, $02, $0D, $07, $0C, $70, $02, $7A, $42, $0B, $65, $52, $75, $03, $6D, $54, $44, $12, $12, $43, $94, $0A, $11, $92, $57, $0A, $0B, $0B, $05, $05, $A6, $6D, $10, $44, $03, $15, $14, $14, $13, $43, $19, $65, $0A, $A8, $74, $92, $42, $04, $08, $5D, $13, $1B, $AF, $14, $1B, $63, $B4, $7E, $86, $09, $0D, $BF, $15, $61, $56, $B4, $6A, $55, $17, $AF, $1A, $10, $7F, $55, $A6, $66, $7B, $13, $14, $0D, $04, $86, $00, $89, $86, $B1, $4C, $0B, $91, $E3, $91, $DE, $7B, $5B, $48, $E9, $0E, $C3, $C3, $B8, $55, $03, $1D, $F1, $F2, $1D, $1C, $EC, $B4, $D3, $7B, $F0, $F3, $F1, $1C, $E2, $E4, $E5, $DC, $1C, $A4, $1B, $A8, $69, $89, $39, $38, $07, $E1, $5C, $71, $B7, $84, $0C, $BE, $2A, $02, $E4, $80, $DA, $33, $AB, $0C, $C3, $6E, $05, $98, $25, $0C, $97, $B1, $4C, $06, $5C, $A3, $40, $E9, $F9, $D8, $30, $83, $B7, $88, $F7, $88, $A4, $1C, $32, $AA, $54, $82, $04, $A5, $2A, $11, $09, $39, $13, $A6, $11, $99, $7D, $94, $74, $04, $F9, $90, $49, $C7, $2A, $44, $39, $85, $78, $E4, $36, $A4, $CF, $B4, $A0, $00, $46, $5D, $6C, $22, $B1, $A8, $C5, $21, $4D, $B9, $21, $05, $30, $D5, $A8, $54, $2C, $44, $A6, $2A, $B2, $46, $54, $18, $D7, $AE, $70, $10, $71, $0B, $02, $00, $21, $F9, $04, $00, $0A, $00, $04, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $B1, $C0, $5C, $26, $14, $99, $67, $94, $08, $1A, $4C, $AA, $45, $A8, $42, $2A, $14, $93, $01, $85, $C1, $00, $04, $2E, $46, $8E, $43, $F3, $D0, $A3, $76, $B6, $CB, $C7, $04, $7E, $2C, $24, $A8, $1D, $77, $53, $47, $49, $72, $0B, $6A, $1F, $6D, $02, $67, $42, $0B, $47, $54, $72, $0E, $6A, $54, $44, $1F, $88, $8C, $47, $11, $8B, $57, $48, $00, $8A, $9D, $6A, $06, $5C, $0C, $07, $07, $04, $43, $19, $47, $0A, $05, $76, $05, $8B, $42, $09, $1E, $64, $04, $10, $A4, $07, $10, $61, $A9, $0A, $7A, $77, $02, $25, $B5, $0C, $A1, $56, $A9, $93, $60, $18, $A4, $0D, $03, $AE, $45, $0B, $05, $7C, $6D, $04, $07, $25, $C4, $6D, $76, $CF, $4C, $0B, $8A, $D9, $8A, $D5, $60, $09, $06, $DF, $E0, $06, $04, $B9, $B9, $CA, $4C, $06, $14, $E9, $EA, $14, $1A, $E4, $A9, $BB, $77, $E8, $EB, $E9, $1A, $D8, $DA, $DB, $81, $00, $04, $E1, $E0, $A6, $4B, $DC, $55, $00, $E5, $BB, $62, $AE, $C8, $80, $0E, $07, $A6, $2D, $11, $F0, $46, $41, $84, $3B, $21, $3A, $74, $E0, $70, $EB, $5F, $33, $47, $00, $95, $38, $A0, $20, $B1, $43, $88, $01, $45, $36, $39, $3C, $93, $41, $99, $80, $0C, $4E, $06, $8C, $E8, $B8, $81, $C8, $3B, $22, $9B, $16, $2C, $48, $90, $40, $A6, $23, $22, $07, $38, $48, $84, $59, $B3, $C9, $4D, $34, $39, $17, $17, $15, $38, $C0, $A0, $CD, $45, $42, $5B, $00, $1C, $C9, $92, $6F, $CF, $2E, $39, $00, $36, $15, $64, $D2, $30, $4E, $52, $00, $55, $F3, $41, $ED, $74, $55, $0C, $BC, $44, $58, $B4, $38, $13, $D2, $6C, $2A, $AF, $AB, $4D, $DB, $0C, $CA, $17, $04, $00, $21, $F9, $04, $00, $0A, $00, $05, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $02, $66, $42, $0B, $47, $69, $7E, $57, $65, $46, $0A, $43, $86, $0A, $11, $84, $8A, $7D, $52, $8F, $69, $43, $19, $1F, $03, $03, $79, $00, $71, $87, $4E, $00, $05, $84, $85, $19, $4E, $09, $06, $9B, $03, $06, $61, $47, $75, $73, $0B, $20, $AA, $1F, $04, $4C, $8A, $0A, $97, $60, $B2, $9B, $0E, $A1, $4B, $0B, $5D, $A4, $4B, $09, $03, $20, $C2, $4C, $BE, $60, $9D, $45, $0B, $83, $CE, $83, $C9, $55, $02, $0E, $D4, $D5, $0E, $5D, $AE, $D9, $C7, $4B, $0E, $07, $DE, $DF, $07, $0D, $D9, $D9, $CB, $60, $DD, $E0, $DE, $0D, $CD, $CF, $D0, $7A, $A2, $D6, $D5, $B9, $CC, $EE, $B5, $EE, $57, $DB, $44, $06, $14, $10, $E5, $4A, $02, $6C, $90, $E6, $58, $A0, $40, $41, $C3, $03, $64, $D8, $70, $45, $53, $42, $60, $03, $41, $0A, $16, $58, $11, $B9, $15, $09, $93, $B0, $01, $21, $1C, $08, $31, $50, $E1, $21, $03, $22, $AE, $96, $4D, $5A, $90, $20, $C1, $02, $07, $1D, $3A, $88, $20, $02, $41, $03, $C1, $89, $26, $9B, $1C, $3A, $B3, $45, $44, $CA, $01, $13, $21, $48, $50, $83, $AD, $CF, $96, $35, $02, $1C, $3A, $84, $70, $E7, $E6, $48, $1E, $3F, $00, $0E, $A4, $84, $40, $14, $00, $C0, $A2, $8B, $84, $8C, $E8, $C0, $41, $1E, $18, $A4, $34, $A3, $02, $18, $90, $F2, $A3, $1E, $28, $59, $A0, $12, $A2, $D0, $A1, $44, $D3, $56, $F8, $CE, $0E, $E1, $E3, $2E, $08, $00, $21, $F9, $04, $00, $0A, $00, $06, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $02, $66, $42, $0B, $47, $69, $7E, $57, $65, $45, $09, $79, $00, $86, $0A, $11, $84, $8A, $7D, $52, $90, $69, $6E, $6C, $48, $43, $71, $87, $4E, $00, $05, $84, $85, $19, $4E, $0B, $5D, $87, $61, $47, $75, $7A, $A7, $91, $A2, $43, $8A, $0A, $98, $60, $AD, $8E, $4C, $A6, $8B, $6A, $86, $05, $9F, $BA, $7A, $8F, $B7, $83, $C2, $83, $BD, $60, $A6, $05, $C8, $C9, $64, $AA, $AA, $AF, $4C, $05, $03, $D1, $D2, $D1, $CC, $CC, $CE, $4B, $D0, $D3, $D2, $0B, $C3, $C2, $C5, $55, $02, $C9, $E2, $D7, $DF, $CF, $BF, $00, $57, $D7, $44, $0E, $07, $03, $EA, $63, $9A, $81, $6A, $08, $07, $07, $0D, $06, $B7, $AD, $BC, $73, $05, $10, $F5, $07, $08, $1C, $30, $52, $25, $89, $D3, $2B, $03, $16, $08, $08, $71, $C0, $E0, $DF, $03, $22, $AA, $6C, $51, $62, $77, $C0, $01, $01, $0A, $14, $1A, $10, $19, $D0, $A0, $1E, $91, $46, $BD, $2E, $01, $18, $D0, $A1, $C3, $00, $00, $0D, $30, $E2, $73, $33, $E0, $83, $9A, $53, $49, $48, $9A, $44, $A7, $81, $82, $85, $73, $76, $56, $C9, $3C, $09, $00, $02, $C6, $2B, $87, $E7, $34, $0D, $D9, $39, $A4, $02, $05, $0D, $B6, $C0, $F8, $11, $42, $54, $88, $01, $8C, $12, $7E, $41, $C9, $32, $B4, $24, $4F, $21, $1B, $28, $5C, $C5, $C9, $D4, $2A, $D7, $97, $1C, $38, $08, $D4, $13, $04, $00, $21, $F9, $04, $00, $0A, $00, $07, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $02, $66, $42, $0B, $47, $69, $7E, $57, $65, $45, $09, $79, $00, $86, $0A, $11, $84, $8A, $7D, $52, $90, $69, $6E, $6C, $48, $43, $71, $87, $4E, $00, $05, $84, $85, $19, $4E, $0B, $5D, $87, $61, $47, $75, $7A, $A7, $91, $A2, $43, $8A, $0A, $98, $60, $AD, $8E, $4C, $A6, $8B, $6A, $86, $05, $9F, $BA, $7A, $8F, $B7, $83, $C2, $83, $BD, $82, $C3, $C4, $AA, $C9, $B9, $73, $64, $CA, $CE, $AA, $AF, $4C, $CD, $CA, $0B, $C7, $C4, $BF, $D5, $D6, $C5, $43, $DB, $D2, $BF, $00, $57, $D1, $45, $05, $03, $0E, $DD, $4F, $9A, $81, $6A, $1E, $03, $ED, $04, $B7, $AD, $BC, $CC, $06, $ED, $03, $1E, $B3, $42, $B1, $92, $42, $05, $21, $03, $4A, $0E, $10, $60, $2A, $F0, $A1, $DE, $04, $22, $AA, $6C, $6D, $E8, $D0, $C1, $00, $01, $08, $10, $08, $14, $38, $70, $A0, $04, $11, $07, $F5, $88, $34, $EA, $E5, $80, $21, $05, $00, $06, $28, $50, $30, $00, $A0, $04, $45, $07, $4D, $1C, $28, $50, $43, $81, $21, $CA, $90, $23, $CF, $34, $38, $80, $E0, $9B, $90, $01, $0C, $0F, $08, $81, $49, $12, $C0, $00, $32, $8A, $3D, $7F, $8D, $E8, $C0, $01, $13, $CF, $21, $0C, $0E, $34, $10, $A7, $04, $02, $43, $08, $43, $8E, $0A, $71, $40, $F1, $C3, $AF, $12, $1D, $42, $10, $91, $2A, $04, $C2, $01, $10, $36, $8B, $70, $0D, $CB, $24, $81, $06, $0D, $EF, $F4, $04, $01, $00, $21, $F9, $04, $00, $0A, $00, $08, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $02, $66, $42, $0B, $47, $69, $7E, $57, $65, $45, $09, $79, $00, $86, $0A, $11, $84, $8A, $7D, $52, $90, $69, $6E, $6C, $48, $43, $71, $87, $4E, $00, $05, $84, $85, $19, $4E, $0B, $5D, $87, $61, $47, $75, $7A, $A7, $91, $A2, $43, $8A, $0A, $98, $60, $AD, $8E, $4C, $A6, $8B, $6A, $86, $05, $9F, $BA, $7A, $8F, $B7, $83, $C2, $83, $BD, $82, $C3, $C4, $AA, $C9, $B9, $73, $64, $CA, $CE, $AA, $AF, $4C, $CD, $CA, $0B, $C7, $C4, $BF, $D5, $D6, $C5, $43, $0E, $D8, $BF, $05, $07, $1C, $03, $CC, $AB, $60, $10, $23, $1D, $1D, $23, $73, $9D, $CB, $45, $06, $14, $E9, $1D, $14, $06, $73, $B8, $47, $19, $A2, $1B, $F2, $23, $25, $42, $09, $16, $EA, $15, $29, $E0, $81, $8A, $00, $4D, $E5, $00, $A4, $E3, $70, $60, $16, $03, $0A, $14, $26, $14, $18, $30, $20, $14, $45, $10, $44, $62, $11, $61, $B0, $A1, $DB, $10, $02, $10, $37, $00, $70, $70, $E0, $40, $37, $10, $14, $67, $FD, $B3, $B5, $64, $03, $44, $02, $23, $4B, $76, $5B, $40, $D1, $C3, $AF, $21, $F0, $28, $40, $10, $42, $D2, $24, $4F, $31, $8A, $30, $6F, $56, $A0, $A0, $21, $4F, $4F, $8F, $00, $3E, $50, $DC, $C6, $E4, $01, $C4, $07, $DC, $64, $0E, $99, $38, $40, $C1, $AF, $01, $14, $2C, $10, $39, $4A, $C4, $C0, $80, $2C, $37, $8B, $70, $0D, $2B, $A8, $41, $03, $95, $60, $82, $00, $00, $21, $F9, $04, $00, $0A, $00, $09, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $02, $66, $42, $0B, $47, $69, $7E, $57, $65, $45, $09, $79, $00, $86, $0A, $11, $84, $8A, $7D, $52, $90, $69, $6E, $6C, $48, $43, $71, $87, $4E, $00, $05, $84, $85, $19, $4E, $0B, $5D, $87, $61, $47, $75, $7A, $A7, $91, $A2, $43, $8A, $0A, $98, $60, $AD, $8E, $4C, $A6, $8B, $6A, $86, $05, $9F, $BA, $7A, $8F, $4C, $0E, $03, $C3, $C4, $03, $0E, $BF, $67, $83, $CA, $52, $1C, $1D, $CE, $CF, $1D, $10, $BF, $64, $AA, $AA, $CD, $D0, $CE, $D2, $7A, $D4, $D5, $0A, $C2, $C5, $C3, $C7, $7A, $0B, $CB, $CA, $BD, $44, $04, $BF, $E7, $55, $09, $10, $1A, $06, $73, $50, $B6, $4C, $0F, $15, $14, $14, $15, $73, $9D, $B9, $4A, $13, $1B, $F7, $14, $36, $4C, $98, $83, $EB, $48, $06, $51, $0C, $00, $56, $18, $30, $06, $81, $B8, $27, $A4, $C6, $68, $5A, $25, $E4, $9E, $06, $08, $8E, $1E, $1C, $38, $40, $40, $80, $03, $07, $02, $2E, $11, $89, $45, $44, $02, $83, $74, $43, $0A, $6C, $94, $56, $60, $58, $9A, $53, $A2, $1A, $A9, $81, $B0, $F1, $A5, $CB, $3F, $58, $90, $09, $71, $B0, $91, $21, $A8, $2B, $9B, $00, $14, $BD, $02, $C3, $E0, $40, $03, $2A, $2D, $07, $CC, $D2, $84, $CC, $C0, $46, $78, $42, $92, $CE, $C2, $F3, $0B, $C4, $01, $04, $5C, $80, $46, $E5, $A7, $33, $AA, $D6, $AE, $B7, $86, $0D, $5D, $12, $04, $00, $21, $F9, $04, $00, $0A, $00, $0A, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $4C, $12, $05, $47, $41, $51, $CA, $54, $26, $14, $99, $67, $94, $58, $50, $24, $AA, $D3, $AD, $10, $AA, $A0, $02, $C8, $05, $70, $31, $72, $1C, $92, $CD, $99, $B6, $5A, $EB, $1D, $8B, $C9, $DF, $39, $F7, $98, $7C, $0B, $8F, $11, $6A, $10, $10, $45, $0B, $47, $69, $7E, $57, $65, $45, $09, $79, $00, $06, $1D, $1D, $23, $03, $44, $8A, $7D, $52, $86, $0A, $69, $6E, $6C, $48, $42, $05, $21, $91, $1D, $24, $0E, $43, $05, $66, $43, $0B, $19, $4E, $0B, $5D, $87, $45, $10, $1C, $A2, $07, $9B, $6A, $AE, $0A, $11, $A8, $A6, $1B, $A2, $24, $73, $B7, $8E, $4C, $0E, $14, $1D, $94, $6A, $86, $05, $4E, $73, $06, $7A, $00, $CA, $45, $04, $06, $D2, $D3, $06, $04, $CD, $67, $02, $D9, $DA, $00, $1A, $14, $DE, $DF, $14, $0F, $CD, $64, $47, $E5, $0A, $DD, $E0, $DE, $E2, $7A, $E4, $E6, $0A, $D1, $D4, $D2, $D6, $7A, $0B, $DA, $F6, $CF, $5C, $CD, $F8, $55, $02, $03, $0D, $A5, $6A, $A0, $04, $63, $62, $80, $C1, $81, $03, $0C, $E6, $C4, $11, $A3, $84, $00, $84, $83, $07, $20, $CC, $03, $D3, $AA, $5C, $06, $5D, $0F, $20, $32, $00, $21, $64, $81, $87, $5A, $6E, $56, $8D, $E9, $54, $67, $C8, $C1, $06, $03, $CC, $4C, $18, $30, $20, $C1, $82, $46, $0B, $32, $81, $54, $A4, $80, $C8, $87, $07, $20, $FB, $0D, $60, $E6, $C7, $95, $AE, $32, $46, $6A, $0C, $B0, $94, $E2, $07, $C0, $AB, $6B, $00, $0A, $B0, $04, $58, $54, $91, $2E, $35, $1F, $58, $3A, $29, $0A, $A0, $D3, $35, $02, $2C, $27, $52, $C5, $D3, $2C, $C3, $00, $0F, $74, $50, $75, $79, $7A, $8D, $2A, $52, $30, $7C, $9A, $05, $01, $00, $21, $F9, $04, $00, $0A, $00, $0B, $00, $2C, $00, $00, $00, $00, $20, $00, $20, $00, $00, $06, $FF, $40, $80, $70, $48, $2C, $2A, $14, $8B, $A2, $72, $49, $34, $14, $88, $82, $A3, $A0, $38, $65, $2A, $19, $9D, $10, $54, $4A, $2C, $28, $12, $D6, $22, $A4, $D3, $81, $0C, $A3, $8A, $2A, $00, $FD, $0C, $13, $47, $1D, $4E, $1B, $AD, $CE, $1C, $DD, $C5, $01, $79, $23, $A4, $F7, $8F, $60, $78, $44, $14, $64, $0E, $6B, $5C, $00, $47, $11, $6E, $0F, $0F, $45, $0E, $64, $14, $87, $69, $00, $09, $88, $43, $09, $81, $00, $13, $14, $14, $15, $06, $44, $07, $64, $A0, $02, $53, $0B, $47, $6D, $7D, $11, $47, $49, $95, $16, $9D, $14, $17, $04, $42, $05, $24, $03, $4A, $0B, $19, $AD, $0B, $5E, $A8, $45, $0F, $1A, $B0, $10, $9A, $61, $BD, $0A, $11, $6A, $44, $09, $0C, $B0, $17, $78, $C6, $C4, $4B, $04, $1B, $14, $A0, $6E, $A7, $05, $AD, $78, $13, $82, $00, $DA, $45, $05, $0E, $E2, $E3, $0E, $A9, $78, $A5, $E8, $A5, $00, $0D, $07, $ED, $EE, $07, $D6, $E7, $47, $F3, $F3, $EC, $EF, $ED, $F1, $6E, $68, $F4, $A8, $E4, $E3, $E6, $61, $16, $A4, $43, $F7, $0D, $4A, $B7, $82, $56, $16, $38, $18, $00, $70, $49, $94, $68, $D2, $3E, $0C, $18, $F0, $01, $8F, $9D, $4B, $45, $12, $18, $98, $38, $C0, $00, $44, $5C, $C6, $32, $24, $DB, $C4, $F1, $43, $86, $21, $22, $95, $08, $D0, $A5, $6A, $1E, $31, $8E, $0E, $B4, $59, $42, $B2, $20, $D3, $82, $53, $0A, $CC, $CD, $54, $40, $44, $C1, $84, $35, $64, $38, $9F, $F8, $E9, $35, $32, $93, $9B, $5E, $49, $FC, $24, $CA, $D9, $ED, $0C, $A0, $3F, $94, $2A, $61, $C4, $B3, $8A, $27, $54, $35, $55, $9B, $2A, $9D, $A4, $06, $CD, $47, $87, $0A, $4E, $3A, $8D, $4A, $8B, $6C, $D3, $B1, $23, $CF, $32, $61, $D5, $2D, $08, $00, $3B, $00, $00, $00, $00, $00, $00, $00, $00, $00) pasdoc/source/component/tipue/jquery.min.js0000600000175000017500000024222713034465544021573 0ustar michalismichalis/*! jQuery v2.0.0 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery.min.map */ (function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],f="2.0.0",p=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=f.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return p.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,f,p,h,d,g,m,y="sizzle"+-new Date,v=e.document,b={},w=0,T=0,C=ot(),k=ot(),N=ot(),E=!1,S=function(){return 0},j=typeof undefined,D=1<<31,A=[],L=A.pop,q=A.push,H=A.push,O=A.slice,F=A.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",R="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=M.replace("w","w#"),$="\\["+R+"*("+M+")"+R+"*(?:([*^$|!~]?=)"+R+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+R+"*\\]",B=":("+M+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",I=RegExp("^"+R+"+|((?:^|[^\\\\])(?:\\\\.)*)"+R+"+$","g"),z=RegExp("^"+R+"*,"+R+"*"),_=RegExp("^"+R+"*([>+~]|"+R+")"+R+"*"),X=RegExp(R+"*[+~]"),U=RegExp("="+R+"*([^\\]'\"]*)"+R+"*\\]","g"),Y=RegExp(B),V=RegExp("^"+W+"$"),G={ID:RegExp("^#("+M+")"),CLASS:RegExp("^\\.("+M+")"),TAG:RegExp("^("+M.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+B),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),"boolean":RegExp("^(?:"+P+")$","i"),needsContext:RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},J=/^[^{]+\{\s*\[native \w/,Q=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,et=/'|\\/g,tt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,nt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{H.apply(A=O.call(v.childNodes),v.childNodes),A[v.childNodes.length].nodeType}catch(rt){H={apply:A.length?function(e,t){q.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function it(e){return J.test(e+"")}function ot(){var e,t=[];return e=function(n,i){return t.push(n+=" ")>r.cacheLength&&delete e[t.shift()],e[n]=i}}function st(e){return e[y]=!0,e}function at(e){var t=c.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ut(e,t,n,r){var i,o,s,a,u,f,d,g,x,w;if((t?t.ownerDocument||t:v)!==c&&l(t),t=t||c,n=n||[],!e||"string"!=typeof e)return n;if(1!==(a=t.nodeType)&&9!==a)return[];if(p&&!r){if(i=Q.exec(e))if(s=i[1]){if(9===a){if(o=t.getElementById(s),!o||!o.parentNode)return n;if(o.id===s)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(s))&&m(t,o)&&o.id===s)return n.push(o),n}else{if(i[2])return H.apply(n,t.getElementsByTagName(e)),n;if((s=i[3])&&b.getElementsByClassName&&t.getElementsByClassName)return H.apply(n,t.getElementsByClassName(s)),n}if(b.qsa&&(!h||!h.test(e))){if(g=d=y,x=t,w=9===a&&e,1===a&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(d=t.getAttribute("id"))?g=d.replace(et,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=f.length;while(u--)f[u]=g+mt(f[u]);x=X.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return H.apply(n,x.querySelectorAll(w)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(I,"$1"),t,n,r)}o=ut.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},l=ut.setDocument=function(e){var t=e?e.ownerDocument||e:v;return t!==c&&9===t.nodeType&&t.documentElement?(c=t,f=t.documentElement,p=!o(t),b.getElementsByTagName=at(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),b.attributes=at(function(e){return e.className="i",!e.getAttribute("className")}),b.getElementsByClassName=at(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),b.sortDetached=at(function(e){return 1&e.compareDocumentPosition(c.createElement("div"))}),b.getById=at(function(e){return f.appendChild(e).id=y,!t.getElementsByName||!t.getElementsByName(y).length}),b.getById?(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){return e.getAttribute("id")===t}}):(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n?n.id===e||typeof n.getAttributeNode!==j&&n.getAttributeNode("id").value===e?[n]:undefined:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),r.find.TAG=b.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=b.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&p?t.getElementsByClassName(e):undefined},d=[],h=[],(b.qsa=it(t.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+R+"*(?:value|"+P+")"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){var t=c.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&h.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(b.matchesSelector=it(g=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){b.disconnectedMatch=g.call(e,"div"),g.call(e,"[s!='']:x"),d.push("!=",B)}),h=h.length&&RegExp(h.join("|")),d=d.length&&RegExp(d.join("|")),m=it(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,n){if(e===n)return E=!0,0;var r=n.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(n);return r?1&r||!b.sortDetached&&n.compareDocumentPosition(e)===r?e===t||m(v,e)?-1:n===t||m(v,n)?1:u?F.call(u,e)-F.call(u,n):0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],l=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:u?F.call(u,e)-F.call(u,n):0;if(o===s)return lt(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)l.unshift(r);while(a[i]===l[i])i++;return i?lt(a[i],l[i]):a[i]===v?-1:l[i]===v?1:0},c):c},ut.matches=function(e,t){return ut(e,null,null,t)},ut.matchesSelector=function(e,t){if((e.ownerDocument||e)!==c&&l(e),t=t.replace(U,"='$1']"),!(!b.matchesSelector||!p||d&&d.test(t)||h&&h.test(t)))try{var n=g.call(e,t);if(n||b.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return ut(t,c,null,[e]).length>0},ut.contains=function(e,t){return(e.ownerDocument||e)!==c&&l(e),m(e,t)},ut.attr=function(e,t){(e.ownerDocument||e)!==c&&l(e);var n=r.attrHandle[t.toLowerCase()],i=n&&n(e,t,!p);return i===undefined?b.attributes||!p?e.getAttribute(t):(i=e.getAttributeNode(t))&&i.specified?i.value:null:i},ut.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ut.uniqueSort=function(e){var t,n=[],r=0,i=0;if(E=!b.detectDuplicates,u=!b.sortStable&&e.slice(0),e.sort(S),E){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return e};function lt(e,t){var n=t&&e,r=n&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ct(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}function ft(e,t,n){var r;return n?undefined:r=e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ht(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function dt(e){return st(function(t){return t=+t,st(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}i=ut.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r];r++)n+=i(t);return n},r=ut.selectors={cacheLength:50,createPseudo:st,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(tt,nt),e[3]=(e[4]||e[5]||"").replace(tt,nt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ut.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ut.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return G.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&Y.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(tt,nt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ut.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,v=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){f=t;while(f=f[g])if(a?f.nodeName.toLowerCase()===v:1===f.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[y]||(m[y]={}),l=c[e]||[],h=l[0]===w&&l[1],p=l[0]===w&&l[2],f=h&&m.childNodes[h];while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if(1===f.nodeType&&++p&&f===t){c[e]=[w,h,p];break}}else if(x&&(l=(t[y]||(t[y]={}))[e])&&l[0]===w)p=l[1];else while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if((a?f.nodeName.toLowerCase()===v:1===f.nodeType)&&++p&&(x&&((f[y]||(f[y]={}))[e]=[w,p]),f===t))break;return p-=i,p===r||0===p%r&&p/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||ut.error("unsupported pseudo: "+e);return i[y]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?st(function(e,n){var r,o=i(e,t),s=o.length;while(s--)r=F.call(e,o[s]),e[r]=!(n[r]=o[s])}):function(e){return i(e,0,n)}):i}},pseudos:{not:st(function(e){var t=[],n=[],r=s(e.replace(I,"$1"));return r[y]?st(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:st(function(e){return function(t){return ut(e,t).length>0}}),contains:st(function(e){return function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:st(function(e){return V.test(e||"")||ut.error("unsupported lang: "+e),e=e.replace(tt,nt).toLowerCase(),function(t){var n;do if(n=p?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===c.activeElement&&(!c.hasFocus||c.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Z.test(e.nodeName)},input:function(e){return K.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:dt(function(){return[0]}),last:dt(function(e,t){return[t-1]}),eq:dt(function(e,t,n){return[0>n?n+t:n]}),even:dt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:dt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:dt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:dt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=ht(t);function gt(e,t){var n,i,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=r.preFilter;while(a){(!n||(i=z.exec(a)))&&(i&&(a=a.slice(i[0].length)||a),u.push(o=[])),n=!1,(i=_.exec(a))&&(n=i.shift(),o.push({value:n,type:i[0].replace(I," ")}),a=a.slice(n.length));for(s in r.filter)!(i=G[s].exec(a))||l[s]&&!(i=l[s](i))||(n=i.shift(),o.push({value:n,type:s,matches:i}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ut.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,r){var i=t.dir,o=r&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,r,a){var u,l,c,f=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,r,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[y]||(t[y]={}),(l=c[i])&&l[0]===f){if((u=l[1])===!0||u===n)return u===!0}else if(l=c[i]=[f],l[1]=e(t,r,a)||n,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[y]&&(r=bt(r)),i&&!i[y]&&(i=bt(i,o)),st(function(o,s,a,u){var l,c,f,p=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,p,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(f=l[c])&&(y[h[c]]=!(m[h[c]]=f))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(f=y[c])&&l.push(m[c]=f);i(null,y=[],l,u)}c=y.length;while(c--)(f=y[c])&&(l=i?F.call(o,f):p[c])>-1&&(o[l]=!(s[l]=f))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):H.apply(s,y)})}function wt(e){var t,n,i,o=e.length,s=r.relative[e[0].type],u=s||r.relative[" "],l=s?1:0,c=yt(function(e){return e===t},u,!0),f=yt(function(e){return F.call(t,e)>-1},u,!0),p=[function(e,n,r){return!s&&(r||n!==a)||((t=n).nodeType?c(e,n,r):f(e,n,r))}];for(;o>l;l++)if(n=r.relative[e[l].type])p=[yt(vt(p),n)];else{if(n=r.filter[e[l].type].apply(null,e[l].matches),n[y]){for(i=++l;o>i;i++)if(r.relative[e[i].type])break;return bt(l>1&&vt(p),l>1&&mt(e.slice(0,l-1)).replace(I,"$1"),n,i>l&&wt(e.slice(l,i)),o>i&&wt(e=e.slice(i)),o>i&&mt(e))}p.push(n)}return vt(p)}function Tt(e,t){var i=0,o=t.length>0,s=e.length>0,u=function(u,l,f,p,h){var d,g,m,y=[],v=0,x="0",b=u&&[],T=null!=h,C=a,k=u||s&&r.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(a=l!==c&&l,n=i);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,f)){p.push(d);break}T&&(w=N,n=++i)}o&&((d=!m&&d)&&v--,u&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,f);if(u){if(v>0)while(x--)b[x]||y[x]||(y[x]=L.call(p));y=xt(y)}H.apply(p,y),T&&!u&&y.length>0&&v+t.length>1&&ut.uniqueSort(p)}return T&&(w=N,a=C),b};return o?st(u):u}s=ut.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[y]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ut(e,t[r],n);return n}function kt(e,t,n,i){var o,a,u,l,c,f=gt(e);if(!i&&1===f.length){if(a=f[0]=f[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&p&&r.relative[a[1].type]){if(t=(r.find.ID(u.matches[0].replace(tt,nt),t)||[])[0],!t)return n;e=e.slice(a.shift().value.length)}o=G.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],r.relative[l=u.type])break;if((c=r.find[l])&&(i=c(u.matches[0].replace(tt,nt),X.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=i.length&&mt(a),!e)return H.apply(n,i),n;break}}}return s(e,f)(i,t,!p,n,X.test(e)),n}r.pseudos.nth=r.pseudos.eq;function Nt(){}Nt.prototype=r.filters=r.pseudos,r.setFilters=new Nt,b.sortStable=y.split("").sort(S).join("")===y,l(),[0,0].sort(S),b.detectDuplicates=E,at(function(e){if(e.innerHTML="","#"!==e.firstChild.getAttribute("href")){var t="type|href|height|width".split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ft}}),at(function(e){if(null!=e.getAttribute("disabled")){var t=P.split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ct}}),x.find=ut,x.expr=ut.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ut.uniqueSort,x.text=ut.getText,x.isXMLDoc=ut.isXML,x.contains=ut.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(f){for(t=e.memory&&f,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(f[0],f[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!a||n&&!u||(r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))this.cache[i]=t;else for(r in t)o[r]=t[r]},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){return t===undefined||t&&"string"==typeof t&&n===undefined?this.get(e,t):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i=this.key(e),o=this.cache[i];if(t===undefined)this.cache[i]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):t in o?r=[t]:(r=x.camelCase(t),r=r in o?[r]:r.match(w)||[]),n=r.length;while(n--)delete o[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){delete this.cache[this.key(e)]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.substring(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t); x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,i="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,s=0,a=x(this),u=t,l=e.match(w)||[];while(o=l[s++])u=i?u:!a.hasClass(o),a[u?"addClass":"removeClass"](o)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i,o=x(this);1===this.nodeType&&(i=r?e.call(this,n,o.val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.boolean.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.boolean.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.boolean.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,f,p,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(p=x.event.special[d]||{},d=(o?p.delegateType:p.bindType)||d,p=x.event.special[d]||{},f=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,p.setup&&p.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),p.add&&(p.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,f):h.push(f),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,f,p,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){f=x.event.special[h]||{},h=(r?f.delegateType:f.bindType)||h,p=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));s&&!p.length&&(f.teardown&&f.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,f,p,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),p=x.event.special[d]||{},i||!p.trigger||p.trigger.apply(r,n)!==!1)){if(!i&&!p.noBubble&&!x.isWindow(r)){for(l=p.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:p.bindType||d,f=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),f&&f.apply(a,n),f=c&&a[c],f&&x.acceptData(a)&&f.apply&&f.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||p._default&&p._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return 3===e.target.nodeType&&(e.target=e.target.parentNode),s.filter?s.filter(e,o):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=x.expr.match.needsContext,Q={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return t=this,this.pushStack(x(e).filter(function(){for(r=0;i>r;r++)if(x.contains(t[r],this))return!0}));for(n=[],r=0;i>r;r++)x.find(e,this[r],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(Z(this,e||[],!0))},filter:function(e){return this.pushStack(Z(this,e||[],!1))},is:function(e){return!!e&&("string"==typeof e?J.test(e)?x(e,this.context).index(this[0])>=0:x.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],s=J.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function K(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return K(e,"nextSibling")},prev:function(e){return K(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(Q[e]||x.unique(i),"p"===e[0]&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function Z(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var et=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,tt=/<([\w:]+)/,nt=/<|&#?\w+;/,rt=/<(?:script|style|link)/i,it=/^(?:checkbox|radio)$/i,ot=/checked\s*(?:[^=]|=\s*.checked.)/i,st=/^$|\/(?:java|ecma)script/i,at=/^true\/(.*)/,ut=/^\s*\s*$/g,lt={option:[1,""],thead:[1,"
","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};lt.optgroup=lt.option,lt.tbody=lt.tfoot=lt.colgroup=lt.caption=lt.col=lt.thead,lt.th=lt.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(gt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&ht(gt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(gt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!rt.test(e)&&!lt[(tt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(et,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(gt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=p.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,f=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&ot.test(d))return this.each(function(r){var i=f.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(gt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,gt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,pt),l=0;s>l;l++)a=o[l],st.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(ut,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=gt(a),o=gt(e),r=0,i=o.length;i>r;r++)mt(o[r],s[r]);if(t)if(n)for(o=o||gt(e),s=s||gt(a),r=0,i=o.length;i>r;r++)dt(o[r],s[r]);else dt(e,a);return s=gt(a,"script"),s.length>0&&ht(s,!u&>(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,f=e.length,p=t.createDocumentFragment(),h=[];for(;f>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(nt.test(i)){o=o||p.appendChild(t.createElement("div")),s=(tt.exec(i)||["",""])[1].toLowerCase(),a=lt[s]||lt._default,o.innerHTML=a[1]+i.replace(et,"<$1>")+a[2],l=a[0];while(l--)o=o.firstChild;x.merge(h,o.childNodes),o=p.firstChild,o.textContent=""}else h.push(t.createTextNode(i));p.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=gt(p.appendChild(i),"script"),u&&ht(o),n)){l=0;while(i=o[l++])st.test(i.type||"")&&n.push(i)}return p},cleanData:function(e){var t,n,r,i=e.length,o=0,s=x.event.special;for(;i>o;o++){if(n=e[o],x.acceptData(n)&&(t=q.access(n)))for(r in t.events)s[r]?x.event.remove(n,r):x.removeEvent(n,r,t.handle);L.discard(n),q.discard(n)}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"text",async:!1,global:!1,success:x.globalEval})}});function ct(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function pt(e){var t=at.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function ht(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function dt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=x.extend({},o),l=o.events,q.set(t,s),l)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function gt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function mt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&it.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var yt,vt,xt=/^(none|table(?!-c[ea]).+)/,bt=/^margin/,wt=RegExp("^("+b+")(.*)$","i"),Tt=RegExp("^("+b+")(?!px)[a-z%]+$","i"),Ct=RegExp("^([+-])=("+b+")","i"),kt={BODY:"block"},Nt={position:"absolute",visibility:"hidden",display:"block"},Et={letterSpacing:0,fontWeight:400},St=["Top","Right","Bottom","Left"],jt=["Webkit","O","Moz","ms"];function Dt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=jt.length;while(i--)if(t=jt[i]+n,t in e)return t;return r}function At(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function Lt(t){return e.getComputedStyle(t,null)}function qt(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&At(r)&&(o[s]=q.access(r,"olddisplay",Pt(r.nodeName)))):o[s]||(i=At(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=Lt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return qt(this,!0)},hide:function(){return qt(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:At(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=yt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=Dt(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=Ct.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=Dt(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=yt(e,t,r)),"normal"===i&&t in Et&&(i=Et[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),yt=function(e,t,n){var r,i,o,s=n||Lt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Tt.test(a)&&bt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ht(e,t,n){var r=wt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ot(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+St[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+St[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+St[o]+"Width",!0,i))):(s+=x.css(e,"padding"+St[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+St[o]+"Width",!0,i)));return s}function Ft(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Lt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=yt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Tt.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ot(e,t,n||(s?"border":"content"),r,o)+"px"}function Pt(e){var t=o,n=kt[e];return n||(n=Rt(e,t),"none"!==n&&n||(vt=(vt||x("

Below are the nightly builds of PasDoc. They are build automatically every night, always from current SVN code. Use at your own risk, and please report any bugs.