pasdoc/0000700000175000017500000000000012561642323012465 5ustar michalismichalispasdoc/tests/0000700000175000017500000000000012561642320013624 5ustar michalismichalispasdoc/tests/ok_description_test.txt0000600000175000017500000000053710347260567020460 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/ok_external_class_hierarchy.pas0000600000175000017500000000047611462624743022110 0ustar michalismichalisunit ok_external_class_hierarchy; interface type TMyClass0 = class end; TMyClass1 = class(TObject) end; { TMyClass2 is not defined in the source code. But we define in ok_external_class_hierarchy.txt that TMyClass2 descends from TMyClass1. } TMyClass3 = class(TMyClass2) end; implementation end. pasdoc/tests/ok_introduction_pre_link.txt0000600000175000017500000000044710331725025021466 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/ok_tag_params_no_parens.pas0000600000175000017500000000322111464244237021212 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/error_line_number_3.pas0000600000175000017500000000204210433472246020267 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/ok_at_character_in_verbatim.pas0000600000175000017500000000125711773122712022032 0ustar michalismichalis(* Test that @@( and @@) and @@@@ (see http://pasdoc.sipsolutions.net/SupportedTags and http://pasdoc.sipsolutions.net/TagsParametersMatching) work Ok inside all @@-tags. Including tags that don't interpret other @@-tags inside, like @@latex or @@html. @italic(This is a closing paren @) and open @( and "at" char @@ using italic font.) @latex({\bf This is a closing paren @) and open @( and "at" char @@ inside LaTeX.}) @html(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/ok_expanding_descriptions.pas0000600000175000017500000001111211464244237021571 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/ok_bom.pas0000600000175000017500000000012711464174617015613 0ustar michalismichalis{ UTF-8 file with BOM ($EF, $BB, $BF). } unit ok_bom; interface implementation end. pasdoc/tests/ok_table.pas0000600000175000017500000000340310305576640016120 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/warning_value_member_tags.pas0000600000175000017500000000173610237304274021551 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/ok_include_quoted.pas0000600000175000017500000000012610447532327020035 0ustar michalismichalisunit ok_include_quoted; {$I 'ok_include_quoted.inc'} interface implementation end.pasdoc/tests/ok_cdecl_external.pas0000600000175000017500000000103510236141175017776 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/ok_auto_link.pas0000600000175000017500000000302410331733542017010 0ustar michalismichalis{ @abstract(Auto-link tests.) Self name: ok_auto_link, simple identifiers Var1, qualified ident: ok_auto_link.Var1. Ident that can't be auto-linked: no_auto_link_to_me. Explicit link to ident that can't be auto-linked: @link(no_auto_link_to_me). } unit ok_auto_link; interface const { @noAutoLinkHere } no_auto_link_to_me = 1; type TMyClass = class Field: Integer; end; var { @definitionList( @itemLabel Test of auto-linking: @item( Self name is Var1, simple ident is TMyClass, qualified ident is TMyClass.Field. Ident that can't be auto-linked: no_auto_link_to_me. Explicit link to ident that can't be auto-linked: @link(no_auto_link_to_me). Note that auto-linking works also inside @@code: @code( Self name is Var1, simple ident is TMyClass, qualified ident is TMyClass.Field. ) ) @itemLabel Test of @@noAutoLink: @item( Things below should @italic(not) be converted to links: @noAutoLink( Self name is Var1, simple ident is TMyClass, qualified ident is TMyClass.Field. Ident that can't be auto-linked: no_auto_link_to_me. Explicit link to ident that can't be auto-linked: @link(no_auto_link_to_me). @noAutoLink(Simple ident once again TMyClass.) Inside @@code: @code( Self name is Var1, simple ident is TMyClass, qualified ident is TMyClass.Field.) ) ) ) } Var1: Integer; implementation end.pasdoc/tests/ok_attributes.pas0000600000175000017500000000113711773743214017224 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/ok_generic.pas0000600000175000017500000000401611617731461016447 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/ok_vorbisfile_conf.inc0000600000175000017500000000014311460613422020157 0ustar michalismichalis{ Yes, under both Linux and Windows we want cdecl. Tested. } {$define libvorbisfile_decl := cdecl} pasdoc/tests/ok_enum_field_var.pas0000600000175000017500000000054310500611254017776 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/ok_external_class_hierarchy.txt0000600000175000017500000000002411462624743022131 0ustar michalismichalisTMyClass2=TMyClass1 pasdoc/tests/ok_not_defined_omit.pas0000600000175000017500000000064010433472246020336 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/ok_lists.pas0000600000175000017500000000350310302733523016160 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/error_macros_recursive.pas0000600000175000017500000000051210307373744021124 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/ok_back_comment_class.pas0000600000175000017500000000120710526574113020636 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/error_introduction_twice_anchors_unit.pas0000600000175000017500000000011410252757042024233 0ustar michalismichalisunit error_introduction_twice_anchors_unit; interface implementation end.pasdoc/tests/ok_dispid_method.pas0000600000175000017500000000107710361320655017645 0ustar michalismichalis{ Testcase for bug "[ 1403317 ] Error parsing automatically generated unit" } unit ok_dispid_method; interface type INetFwOpenPortsDisp = dispinterface ['{C0E9D7FA-E07E-430A-B19A-090CE82D92E2}'] property Count: Integer readonly dispid 1; procedure Add(const Port: INetFwOpenPort); dispid 2; procedure Remove(portNumber: Integer; ipProtocol: NET_FW_IP_PROTOCOL_); dispid 3; function Item(portNumber: Integer; ipProtocol: NET_FW_IP_PROTOCOL_): INetFwOpenPort; dispid 4; property _NewEnum: IUnknown readonly dispid -4; end; implementation end.pasdoc/tests/warning_back_comment.pas0000600000175000017500000000076310327063261020507 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 // to DetailedDescription, but not to AbstractDescription. This is second paragraph. } TTest4 = class end; implementation end.pasdoc/tests/ok_list_item_set_number.pas0000600000175000017500000000040110464077371021243 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/ok_longcode_dash.pas0000600000175000017500000000031010252037754017613 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/ok_description_test.pas0000600000175000017500000000024310347260567020416 0ustar michalismichalisunit ok_description_test; interface type { TMyClass description from source file. } TMyClass = class public procedure Foo; end; implementation end.pasdoc/tests/error_line_number.pas0000600000175000017500000000112010225100572020026 0ustar michalismichalis{ pasdoc should fail on parsing this unit, because the file "not_existing.inc" does not exist. The important thing is that failure message should indicate correct line number in this unit. There was a bug submitted to pasdoc-main list [http://sourceforge.net/mailarchive/forum.php?thread_id=6960993&forum_id=4647] that caused incorrect line number to be printed by pasdoc (lines between $ifdef NOT_DEFINED were not counted). Fixed with revision 1.18 of PasDoc_Tokenizer.pas } {$ifdef NOT_DEFINED} A few lines here, please 1 2 3 4 5 6 7 8 9 10 {$endif} {$I not_existing.inc}pasdoc/tests/ok_library.dpr0000600000175000017500000000137610447512764016512 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/ok_different_image_same_filename_dir2/0000700000175000017500000000000012561642320023212 5ustar michalismichalispasdoc/tests/ok_different_image_same_filename_dir2/image.png0000600000175000017500000000051710376031754025014 0ustar michalismichalisPNG  IHDR2#PLTEٟ pHYs  tIME4UUtEXtCommentCreated with The GIMPd%nIDAT8c 0ʌ! CxeU"d>ȣ"xQddcy47>=>1 ' "$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="$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 pasdoc/tests/scripts/check_cache.sh0000700000175000017500000000172710333143433020055 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 file for docs for this script. # functions ------------------------------------------------------------ run_echo () { echo "$@" scripts/find_all_tests_for_check_cache.sh | "$@" } 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 .. 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/download_correct_tests_output.sh0000700000175000017500000000171010315524457024050 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/check_cache_format_independent.sh0000700000175000017500000000300210333143433023766 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 file for docs for this script. # functions ------------------------------------------------------------ run_echo () { echo "$@" scripts/find_all_tests_for_check_cache.sh | "$@" } 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 .. # 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/scripts/upload_correct_tests_output.sh0000700000175000017500000001057211575333733023537 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 ../, this way we can pack files using # "$FORMAT"/ instead of ../"$FORMAT"/. Some tar versions would # strip "../" automatically, but some would not. cd ../ 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. # # After uploading, I change 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). # Although this isn't really needed: since new SF username is like # "kambi,pasdoc" (not just "kambi"), so I'm logged with default # group "pasdoc" already. ssh "$SF_USERNAME",pasdoc@shell.sourceforge.net < document. (While version installed # from Debian package works OK). This is probably not really # related to Cygwin "core" functionality, but to some specific # problem of Cygwin installation of onsgmls. So I decided to simply # disable validating index.html, so that Cygwin users will not # have problems. # # It's not a big deal because index.html is a small file, # and you can always check it manually with `onsgmls -s -e -g index.html'. # # Earlier I printed here a warning: # echo "---- Not validating $FFF due to problems with Cygwin's onsgmls" # but it seems that this warning is too terse (people see it and # think that it's some validation problem that they should report), # so now index.html is just "silently" ignored. find html/ -iname '*.html' \ '(' -not -iname 'index.html' ')' \ -exec sh -c 'echo ---- Validating {}' ';' \ -exec onsgmls -s -e -g '{}' ';' pasdoc/tests/ok_macros_off.pas0000600000175000017500000000060510307376053017146 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/ok_directive_as_identifier.pas0000600000175000017500000000151310225100572021660 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/ok_deprecated_tag.pas0000600000175000017500000000142510237220740017755 0ustar michalismichalis{ @abstract(Test @@deprecated tag.) Everything in this unit is deprecated. Even this whole unit itself. @deprecated } unit ok_deprecated_tag; interface { @deprecated } procedure MyProc; type { @deprecated Normal type deprecated. } TMyType = Integer; { @deprecated Deprecated class. } TMyClass = class { Deprecated field. @deprecated } MyField: Integer; { @deprecated @deprecated @deprecated @deprecated Property is deprecated (you can specify @@deprecated as many times as you want, because it's harmless). } property MyProperty: Integer read MyField write MyField; { @deprecated } procedure MyMethodLibrary; end; var { @deprecated } MyVar: Integer; const { @deprecated } MyConst = 1; implementation end.pasdoc/tests/ok_longcode_end_semicolon.pas0000600000175000017500000000030210743534125021512 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/ok_multiple_vars.pas0000600000175000017500000000046311365167407017726 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/warning_abstract_termination.pas0000600000175000017500000000073710226515772022311 0ustar michalismichalis{@abstract(The abstract tag for @link(TAbstractTerminationClass) is unterminated. PasDoc should either terminate the tag itself, give a warning, or both) Submitted in thread "Pasdoc tests" 2004-04-10 on pasdoc-main. } unit warning_abstract_termination; interface Type {@abstract(This abstract tag lacks the closing parenthesis. How will PasDoc handle this error?} TAbstractTerminationClass = Class(TObject) DummyField: integer; end; implementation end. pasdoc/tests/ok_interface_implicit.pas0000600000175000017500000000052510537700544020664 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/ok_cvar.pas0000600000175000017500000000016211465510715015762 0ustar michalismichalis{$mode objfpc} unit ok_cvar; interface var DummyVar : pointer; cvar; external 'dummy'; implementation end. pasdoc/tests/warning_back_comment_over_uses_clause.pas0000600000175000017500000000022510527243320024124 0ustar michalismichalisunit warning_back_comment_over_uses_clause; interface uses Unit2, Unit3; {< This comment shouldn't be assigned to anything. } implementation end.pasdoc/tests/warning_abstract_twice.pas0000600000175000017500000000034110226627606021062 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/ok_deprecated_const_string.pas0000600000175000017500000000024011462170674021723 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/test_subdir/0000700000175000017500000000000012561642317016161 5ustar michalismichalispasdoc/tests/test_subdir/ok_relative_include_conf.inc0000600000175000017500000000001610447552640023667 0ustar michalismichalis{$mode objfpc}pasdoc/tests/test_subdir/ok_relative_include_1.pas0000600000175000017500000000072210447552640023120 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/test_subdir/another_test_subdir/0000700000175000017500000000000012561642317022230 5ustar michalismichalispasdoc/tests/test_subdir/another_test_subdir/ok_relative_include_2.pas0000600000175000017500000000100610447552640027164 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/error_unexpected_eof_2.pas0000600000175000017500000000004510320071151020746 0ustar michalismichalis{ No non-white tokens in this file. }pasdoc/tests/ok_anonymous_methods.pas0000600000175000017500000000043211464032401020570 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/ok_operator_test.pas0000600000175000017500000000662011463543450017726 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/ok_caret_character.pas0000600000175000017500000000122110342221444020125 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/ok_longcode_comment.pas0000600000175000017500000000017210251303300020322 0ustar michalismichalis(* @longcode(# { Some multiline comment } #) *) unit ok_longcode_comment; interface implementation end.pasdoc/tests/ok_links.pas0000600000175000017500000000230010236025636016141 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/ok_latex_head.pas0000600000175000017500000000050010250150017017103 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/ok_dot_unitname.pas0000600000175000017500000000013410560451322017505 0ustar michalismichalisunit ok.dot.unitname; interface uses dot.inside.unitname; implementation end.pasdoc/tests/warning_desc_end.pas0000600000175000017500000000010110755262506017623 0ustar michalismichalis{ @code(} unit warning_desc_end; interface implementation end.pasdoc/tests/ok_program.pas0000600000175000017500000000014310350360657016475 0ustar michalismichalisprogram ok_program; uses foo, bar; procedure my_proc; var my_var: Integer; begin end; begin end.pasdoc/tests/ok_include_2.txt0000600000175000017500000000004610375424717016735 0ustar michalismichalisThis is file @code(ok_include_2.txt). pasdoc/tests/todo/0000700000175000017500000000000012561642317014577 5ustar michalismichalispasdoc/tests/todo/ok_accidental_exclude.pas0000600000175000017500000000041310225100572021560 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/todo/warning_no_params.pas0000600000175000017500000000113610236141047021002 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/todo/ok_record_descr.pas0000600000175000017500000000074510245770310020433 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/todo/ok_comment_for_hidden_field.pas0000600000175000017500000000204310353616050022754 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/todo/ok_different_image_same_filename/0000700000175000017500000000000012561642317023245 5ustar michalismichalispasdoc/tests/todo/ok_record_in_record.pas0000600000175000017500000000077510245770310021302 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/ok_ignore_leading_star.pas0000600000175000017500000000021211063733275021024 0ustar michalismichalisunit ok_ignore_leading_star; interface const {** * @--ignore-leading=* works with @--staronly *} A = 1; implementation end. pasdoc/tests/ok_links_2.pas0000600000175000017500000000036710236025636016375 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/ok_value_member_tags.pas0000600000175000017500000000154010240161421020473 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/ok_table_of_contents.txt0000600000175000017500000000077010332010155020541 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/ok_ignore_leading_hash.pas0000600000175000017500000000046711063733275021012 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/ok_line_break.pas0000600000175000017500000000035710236361773017133 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/ok_macro_include.inc0000600000175000017500000000020111365167407017620 0ustar michalismichalis{$DEFINE CLASS_CONSTRUCTOR:=Constructor Init; Overload} {$DEFINE SPAWNABLE_CONSTRUCTOR:=Constructor Init(Param:String); Overload}pasdoc/tests/ok_introduction_conclusion.pas0000600000175000017500000000052310252757042022004 0ustar michalismichalisunit ok_introduction_conclusion; interface const { This is some constant, with a link to my introduction: @link(ok_introduction) and @link(ok_conclusion My conclusion). Link to @link(SecSecond second section of introduction), link to @link(SomeAnchor some anchor in introduction) } MyConstant = 1; implementation end.pasdoc/tests/ok_link_explicite_name.pas0000600000175000017500000000047210240271556021033 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/ok_image_picture.eps0000600000175000017500000003630310375740324017656 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/warning_not_existing_tags.pas0000600000175000017500000000036310225100572021603 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/ok_multiple_fields.pas0000600000175000017500000000234410325753257020220 0ustar michalismichalisunit ok_multiple_fields; interface type TRec1 = record { Descr of F1, F2, F3 } F1, F2, F3: Integer; F4: Integer; { Descr of F5 and F6 } F5, F6, { Descr of F7 and F8 } F7, F8, { Descr of F9 and F10 } F9, F10: Integer; F11: Integer; F12, { Descr of F13 and F14 } F13, F14, { Descr of F15 } F15: Integer; end; TRec2 = record case Integer of 0: ( { Descr of F1, F2, F3 } F1, F2, F3: Integer; F4: Integer; { Descr of F5 and F6 } F5, F6, { Descr of F7 and F8 } F7, F8, { Descr of F9 and F10 } F9, F10: Integer;); 1: ( F11: Integer; F12, { Descr of F13 and F14 } F13, F14, { Descr of F15 } F15: Integer;); end; var { Descr of F1, F2, F3 (multiline) } F1, F2, F3: Integer; F4: Integer; { Descr of F5 and F6 (multiline) } F5, F6, { Descr of F7 and F8 (multiline) } F7, F8, { Descr of F9 and F10 (multiline) } F9, F10: Integer; F11: Integer; F12, { Descr of F13 and F14 (multiline) } F13, F14, { Descr of F15 (multiline) } F15: Integer; implementation end.pasdoc/tests/ok_enum_explicit_assign.pas0000600000175000017500000000024010344627335021237 0ustar michalismichalisunit ok_enum_explicit_assign; interface type TEnum1 = (e1One, e1Two = 12, e1Three, e1Four := 15); TEnum2 = (e2One := 3, e1Two := 4); implementation end.pasdoc/tests/ok_if_directive.pas0000600000175000017500000000326410344703560017466 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 [http://pasdoc.sipsolutions.net/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/ok_include_quoted.inc0000600000175000017500000000000010447532327020012 0ustar michalismichalispasdoc/tests/ok_nodescription_printing.pas0000600000175000017500000000203210225100572021604 0ustar michalismichalis{ pasdoc's LaTeX documentation of this unit omitted many things before revision 1.20 of PasDoc_GenLatex.pas. Html docs were ok. I explained why omitting docs for things that don't have any documentation comment is bad in the letter "Fix for LaTeX genetator omitting some things" [http://sourceforge.net/mailarchive/forum.php?thread_id=6948809&forum_id=4647] Now, all identifiers in this unit should be visible in LaTeX documentation (and in html output too, of course). } unit ok_nodescription_printing; interface type TClass1 = class MyField: Integer; procedure MyMethod; property MyProperty read FMyProperty; end; TMyRecord = record end; { This record has a description, but still LaTeX output will not list it in it's summary list (in the "Overview" section). (i.e. before applying my patch) } TMyRecord2 = record end; TMyRecord3 = record MyRecField: Integer; end; TMySimpleType = Integer; procedure MyProc; const MyConst = 9; var MyVariable: Integer; implementation end.pasdoc/tests/ok_image_picture.jpg0000600000175000017500000000442410375177030017644 0ustar michalismichalisJFIFC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((G4" u+TjeK#vVؼ},4_/xt}n%Z #$qի#+ sCwp!PIP?"$"2s6oDdN⩛Y-ϙ^Ỉ<̈́a[{Z֘m}DJCaR+ :g؃)!WV%1ƫY+R1?'e+ Ɔl`,[A(k3Rdy:~65 qTW1]\D-A͕14eg@!Ts)uC亗cgW1! a?B!N0lvv&ֆи?#$ !1A#2a?9 z6l`i`bgzÍ Դ)CYgwAT΃Sח1 !12AQ"B#Raq3b? KGn0TpNU1qMX /EH9!An S ZdwHfEk1?Ij~hxnu=TlWwx)i[:\3(\)"բؐ./B\7hMA\ cƏ"*lHv8!UneԻPm $pA`N6UZ+M̩Zd.Ko OP/y_>!#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/ok_longcode_underscores.pas0000600000175000017500000000070410251273753021237 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/ok_longcode_special_chars.pas0000600000175000017500000000033510252443623021477 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/ok_item_set_number.pas0000600000175000017500000000074210307501075020205 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/ok_include_1.txt0000600000175000017500000000012010375424717016725 0ustar michalismichalisBlah blah blah. This is file @code(ok_include_1.txt). @include(ok_include_2.txt)pasdoc/tests/error_macros.pas0000600000175000017500000000042210307373744017035 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/ok_include_environment.pas0000600000175000017500000000442711365167056021113 0ustar michalismichalis{ @abstract(Test of handling the "@italic($I or $INCLUDE : Include compiler info)" feature of FPC, see [http://www.freepascal.org/docs-html/prog/progsu38.html].) PasDoc bug spotted by Michalis on 2005-12-04 when trying `make htmldocs' on fpc compiler sources, in file version.pas. Notes about how it should be implemented in PasDoc : PasDoc will @italic(not) expand these macros. Instead PasDoc will just explicitly show that e.g. value of MacDATE is %DATE%, value of MacFPCTARGET is %FPCTARGET% etc. Reasons: @unorderedList( @item(For %DATE% and %TIME%, PasDoc could expand them, but it's not sensible. After all, at compilation they will be set to something different. So what PasDoc should do (and will) is to show user that the value of MacDATE is %DATE%. This way user will know that MacDATE's value depends on time of compilation.) @item(For %FPC???% macros, PasDoc couldn't expand them, even if it should. After all, we don't know what FPC version will be used to compile the given unit.) @item(For %environment-variable%: argument like with %FPC???% macros: PasDoc is not able to predict what value $environment-variable will have at compilation time.) @item(Finally, for %FILE% and %LINE%: this is the only case when actually PasDoc could just expand them, just like FPC will. For now, my decision is to not expand them, for consistency with handling all other %xxx%.) ) } unit ok_include_environment; interface const MacDATE = {$I %DATE%}; //< Inserts the current date. MacFPCTARGET = {$I %FPCTARGET%}; //< Inserts the target CPU name. (deprecated, use FPCTARGETCPU) MacFPCTARGETCPU = {$I %FPCTARGETCPU%}; //< Inserts the target CPU name. MacFPCTARGETOS = {$I %FPCTARGETOS%}; //< Inserts the target OS name. MacFPCVERSION = {$I %FPCVERSION%}; //< Current compiler version number. MacFILE = {$I %FILE%}; //< Filename in which the directive is found. MacLINE = {$I %LINE%}; //< Linenumer on which the directive is found. MacTIME = {$I %TIME%}; //< Current time. { If xxx inside %xxx% is none of the above, then it is assumed to be the name of an environment variable. Its value will be fetched. } MacUSEREnv = {$I %USER%}; MacPathEnv = {$I %PATH%}; implementation end.pasdoc/tests/ok_class_record_helpers.pas0000600000175000017500000000127711464032401021212 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/error_bom_utf16_be.pas0000600000175000017500000000074611464225541020026 0ustar michalismichalis{ UTF-16 file with big endian BOM. When compiled without STRING_UNICODE, PasDoc cannot handle it (but should make a nice error at least). For STRING_UNICODE, this should work fine. } unit error_bom_utf16_be; interface implementation end. pasdoc/tests/ok_include_intro_include.txt0000600000175000017500000000014210375424717021427 0ustar michalismichalis@section(1 Sec2 Second section in ok_include_intro_include.txt file) Second section dummy text. pasdoc/tests/ok_macros.pas0000600000175000017500000000336411365167407016327 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/warning_incorrect_tag_nesting.pas0000600000175000017500000000117110331275355022435 0ustar michalismichalisunit warning_incorrect_tag_nesting; interface type EFoo = class(Exception); { Now there is control inside PasDoc what tags can be embedded inside what. pasdoc should display appropriate warnings on following input: @code(This is a code @raises(EFoo with a raises inside ???).) @raises(EFoo @raises(EFoo What are you doing, using raises inside @@raises ?!?)) @raises() @created(2005-05-13 @unknowntag, this will cause a warning about unknown_tag.) @created(2005-05-13 @code(this will cause a warning) that no known tag may be used within @@created.) } procedure TestMe; implementation end.pasdoc/tests/ok_record_case_parsing.pas0000600000175000017500000000143510324615402021017 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/ok_helpinsight_comments.pas0000600000175000017500000000155711714437001021254 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/ok_non_matching_paren.pas0000700000175000017500000000102310372350535020654 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/ok_tag_name_case.pas0000600000175000017500000000023110241415152017560 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/ok_conclusion.txt0000600000175000017500000000002510245462644017237 0ustar michalismichalisSome conclusion text.pasdoc/tests/ok_different_image_same_filename_dir1/0000700000175000017500000000000012561642320023211 5ustar michalismichalispasdoc/tests/ok_different_image_same_filename_dir1/image.png0000600000175000017500000000046710376031754025017 0ustar michalismichalisPNG  IHDR2#PLTEٟ pHYs  tIME}X$tEXtCommentCreated with The GIMPd%nIDAT8c 0ʌ! C2*2?Pejo2HXe'.s"3geIgp|q2mϫ|5-ر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/ok_link_1_char.pas0000600000175000017500000000123410240502431017164 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/error_unexpected_eof.pas0000600000175000017500000000010610320071151020523 0ustar michalismichalisunit error_unexpected_eof; interface type TRec = record case (pasdoc/tests/ok_image_picture.pdf0000600000175000017500000000531110375740324017633 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/ok_final.pas0000600000175000017500000000020311717234334016114 0ustar michalismichalisunit ok_final; interface type TMyObject = class public procedure MyFinalMethod; virtual; final; end; implementation end. pasdoc/tests/ok_bold_italic.pas0000600000175000017500000000105110267637227017301 0ustar michalismichalis{ @abstract(@bold(This is a test) of @@bold and @@italic tags.) Some @bold(bold text). Some @bold(@italic(bold and italic text)). Some @bold(some bold and @italic(italic) and @italic(italic) and @italic(italic once again) text). Some @italic(italic text). Some @bold(bold text with some tags: My name is @name, some @code(begin end) and a link to me: @link(ok_bold_italic)). Some @bold(bold text and @bold(some more)). Some @italic(italic text and @italic(some more)). } unit ok_bold_italic; interface implementation end.pasdoc/tests/warning_lists.pas0000600000175000017500000000177210302733523017222 0ustar michalismichalis{ @abstract(Test various pasdoc warnings related to lists.) These should cause warnings: @orderedList( @@ @item(One) ) @unorderedList( @- @item(One) ) @orderedList( @item(One) -- ) @unorderedList( @item(One) --- ) @orderedList( foo @item(One) bar ) @orderedList( http://pasdoc.sf.net/ @item(One) ) These should cause warnings, because @@item must always be placed directly inside @@orderedList or @@unorderedList, and @@orderedList and @@unorderedList can contain only @@item tags. @orderedList( @author(kambi) ) @unorderedList( @code(begin end) ) @item(Item at toplevel is not allowed.) @code( @item(Item inside @@-tag other than @@xxxList is not allowed.) ) Warnings related to @@definitionList and @@itemLabel: @orderedList( @itemLabel( @@itemLabel is allowed only inside @@definitionList ) ) Warnings related to @@itemSpacing: @itemSpacing(compact) @orderedList( @itemSpacing(ThisIsInvalid) ) } unit warning_lists; interface implementation end.pasdoc/tests/ok_longcode_float_hex.pas0000600000175000017500000000031010254077150020641 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/warning_link_in_seealso.pas0000600000175000017500000000035710334223327021221 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/error_line_number_2.pas0000600000175000017500000000063510361315342020265 0ustar michalismichalis{ Obviously this unit is incorrect. But the reported error message on 2006-01-12 is also incorrect, because line number doesn't count the "//" lines. This happens only when this file has UNIX-style line endings (#10, not Windows-style #13#10). Fixed now. } unit error_line_number_2; // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // :pasdoc/tests/Makefile0000600000175000017500000000250111026526471015267 0ustar michalismichalis# See README for docs how to use this Makefile. # Making docs ---------------------------------------- .PHONY: html pdf latex dvi htmlhelp simplexml html: scripts/mk_tests.sh html dvi: latex/docs.dvi pdf: latex/docs.pdf latex: latex/docs.tex latex2rtf: latex2rtf/docs.tex htmlhelp: scripts/mk_tests.sh htmlhelp simplexml: scripts/mk_tests.sh simplexml latex/docs.tex: scripts/mk_tests.sh latex # (Yes, I must do `cd latex' before calling pdflatex, I can't simply call # `pdflatex latex/docs.tex' because then many output files of pdflatex # would be placed in current dir) latex/docs.pdf: latex/docs.tex cd latex; pdflatex --file-line-error-style -interaction=nonstopmode docs.tex cd latex; pdflatex --file-line-error-style -interaction=nonstopmode docs.tex latex/docs.dvi: latex/docs.tex cd latex; latex --file-line-error-style -interaction=nonstopmode docs.tex cd latex; latex --file-line-error-style -interaction=nonstopmode docs.tex latex2rtf/docs.tex: scripts/mk_tests.sh latex2rtf # Other targets ---------------------------------------- validate_html: scripts/validate_html.sh validate_simplexml: scripts/validate_simplexml.sh clean: rm -Rf html/ latex/ htmlhelp/ latex2rtf/ simplexml/ \ scripts/check_cache_tmp/ \ scripts/upload_correct_tests_output_tmp/ # eof ----------------------------------------pasdoc/tests/ok_unit_uses_filename.pas0000600000175000017500000000025211365167407020712 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/ok_back_comment.pas0000600000175000017500000000175011365167407017462 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/ok_procedural_const.pas0000600000175000017500000000027611462170674020406 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/ok_packed_class_object.pas0000600000175000017500000000025011453241634020765 0ustar michalismichalisunit ok_packed_class_object; interface type TMyPackedClass = packed class Blah: Integer; end; TMyPackedObject = packed object end; implementation end. pasdoc/tests/ok_hint_directives.pas0000600000175000017500000001276312022737345020224 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/ok_see_also.pas0000700000175000017500000000067710266460057016636 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/ok_table_nonlatex.pas0000600000175000017500000000251510305576640020033 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/ok_record_with_case.pas0000600000175000017500000000265710324615402020336 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/ok_dashes.pas0000600000175000017500000000166710275753650016316 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/ok_utf8_failchar.pas0000600000175000017500000002530211464237302017546 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/ok_introduction_pre_link_unit.pas0000600000175000017500000000010410331725025022457 0ustar michalismichalisunit ok_introduction_pre_link_unit; interface implementation end.pasdoc/tests/ok_back_comment_private.pas0000600000175000017500000000101110526570553021200 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/ok_implicit_visibility.pas0000600000175000017500000000053610267302360021107 0ustar michalismichalisunit ok_implicit_visibility; interface type TMyClass = class MyField: Integer; property MyProperty: Integer read MyField write MyField; procedure MyMethod; end; {$M+} TMyClassInMState = class MyField: Integer; property MyProperty: Integer read MyField write MyField; procedure MyMethod; end; implementation end. pasdoc/tests/error_expected_semicolon.pas0000600000175000017500000000013710324033265021413 0ustar michalismichalisunit error_expected_semicolon; interface type TMyType = (A, B) record implementation end.pasdoc/tests/ok_const_1st_comment_missing.pas0000600000175000017500000000045610240502431022207 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/ok_image.pas0000600000175000017500000000123410375740324016112 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/ok_latex_head.tex0000600000175000017500000000012610250150017017124 0ustar michalismichalis\sloppy \hyphenation{anotherverylong-wordthistimeitshouldbebrokenbecauseofhyphenation}pasdoc/tests/ok_class_var.pas0000600000175000017500000000071310433452223016777 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/warning_table.pas0000600000175000017500000000052510305576640017156 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/warning_tags_no_parameters.pas0000600000175000017500000000042310225100572021725 0ustar michalismichalisunit warning_tags_no_parameters; interface { Some tags are not allowed to have parameters. pasdoc should print a warning when you try to give some parameters for such tags: e.g. @nil(parameters that will be ignored), @true(blah). } procedure Foo; implementation end.pasdoc/tests/ok_longcode_highlight.pas0000600000175000017500000000054510370300750020643 0ustar michalismichalis{ @abstract(Test of highlighting in @@longCode some things.) See [https://sourceforge.net/tracker/?func=detail&atid=354213&aid=1422011&group_id=4213] @longCode(# TOptions = class(TForm) private procedure WMSysCmd(var Msg: TWMSysCommand); message WM_SYSCOMMAND; ... end; #) } unit ok_longcode_highlight; interface implementation end.pasdoc/tests/ok_excluded_unit.pas0000600000175000017500000000035310526574113017664 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/ok_deprecated_directive_note.pas0000600000175000017500000000255112452071420022206 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/ok_include.pas0000600000175000017500000000073010375424717016460 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/error_introduction_twice_anchors.txt0000600000175000017500000000016710252757042023240 0ustar michalismichalisSections with the same internal anchor-names are bad: @section(1 SecName 1st section) @section(1 SecName 2nd section) pasdoc/tests/ok_no_sort.pas0000600000175000017500000000047310244777072016524 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/ok_class_function.pas0000600000175000017500000000102510246150532020031 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/ok_complicated_record.pas0000600000175000017500000000316710245714541020657 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/ok_comment_over_uses_clause.pas0000600000175000017500000000023110527243320022105 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/ok_preformatted_test.pas0000600000175000017500000000105210274026302020550 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/ok_include_intro.txt0000600000175000017500000000033710375424717017732 0ustar michalismichalis@tableOfContents Demo that you can also split introduction and conclusion using @@include tag: @section(1 Sec1 First section in ok_include_intro.txt file) First section dummy text. @include(ok_include_intro_include.txt)pasdoc/tests/test_description.txt0000600000175000017500000000005011025045105017734 0ustar michalismichalisThis is description called @bold(main). pasdoc/tests/ok_ignore_leading_length2.pas0000600000175000017500000000024611063733275021425 0ustar michalismichalisunit ok_ignore_leading_length2; interface const (*#? #? multiple chars can be ignored too #? @--ignore-leading=#? #?*) A = 1; implementation end. pasdoc/tests/error_back_comments.pas0000600000175000017500000000035411041132756020352 0ustar michalismichalisunit test; interface type MyEnum = ( me1, //) @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/ok_paragraph_in_single_line_comment.pas0000600000175000017500000000067710232077745023571 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/www/0000700000175000017500000000000012561642322013310 5ustar michalismichalispasdoc/www/screenshots/0000700000175000017500000000000012561642322015650 5ustar michalismichalispasdoc/www/screenshots/gui.png0000600000175000017500000020307312333766741017162 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_class.png0000600000175000017500000031126212333766741020527 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/latex_class.png0000600000175000017500000057165612333766741020717 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.png0000600000175000017500000064445712333766741020745 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|`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/snapshots/0000700000175000017500000000000012561642322015332 5ustar michalismichalispasdoc/www/snapshots/README.txt0000600000175000017500000000063211602523411017023 0ustar michalismichalisThese are things used to generate nightly builds on http://michalis.ii.uni.wroc.pl/pasdoc-snapshots/ . .HEADER.html is just a welcome text for visitors. pasdoc_snapshot is the bash script that does the actual job. It contains some paths hardcoded for the michalis.ii.uni.wroc.pl server configuration, but still it may serve as a useful example how to setup snapshots, cross-compile etc. project like pasdoc. pasdoc/www/snapshots/.HEADER.html0000600000175000017500000000045211602523411017221 0ustar michalismichalis

pasdoc/www/snapshots/pasdoc_snapshot0000700000175000017500000000321511602526700020445 0ustar michalismichalis#!/bin/bash set -eu # log messages and dates in English export LANG=C # Make sure you have fpc on $PATH export PATH=/usr/local/bin:"${PATH}" OUTPUT_PATH=~/public_html/pasdoc-snapshots/`date +%F`/ mkdir -p "$OUTPUT_PATH" OUTPUT_LOG="$OUTPUT_PATH"compilation_output.log cd ~/sources/pasdoc/trunk/ svn up > "$OUTPUT_LOG" PASDOC_VERSION=`make version` # make dist-src >> "$OUTPUT_LOG" 2>&1 # Useless, it checks out stable version. make dist-linux-x86 >> "$OUTPUT_LOG" 2>&1 make dist-win32 FPC_WIN32='fpc -Twin32' LAZBUILD_OPTIONS='--operating-system=win32 --widgetset=win32' >> "$OUTPUT_LOG" 2>&1 echo '---- Build OK.' >> "$OUTPUT_LOG" # 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 ~/public_html/pasdoc-snapshots/latest ln -s `date +%F` ~/public_html/pasdoc-snapshots/latest # Clean old snapshots, to conserve disk space. # Keep only snapshots from last couple of days. cd ~/public_html/pasdoc-snapshots/ 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 echo '---- The end, everything finished Ok.' >> "$OUTPUT_LOG" pasdoc/pasdoc-fpc.cfg0000700000175000017500000000240711470260443015170 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/source/0000700000175000017500000000000012561642317013770 5ustar michalismichalispasdoc/source/tools/0000700000175000017500000000000012561642313015124 5ustar michalismichalispasdoc/source/tools/fpc_sources_parse_for_external_class_hierarchy.sh0000700000175000017500000000163111462465764027200 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.dpr0000600000175000017500000001713612337202423020774 0ustar michalismichalis{ -*- compile-command: "make -C ../../ build-pascal_pre_proc" -*- } { Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { A Pascal preprocessor. See [http://pasdoc.sipsolutions.net/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; { 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/file_to_pascal_string.dpr0000600000175000017500000000625112337202423022166 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/tools/file_to_pascal_data.dpr0000600000175000017500000000426612337202423021575 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/packages/0000700000175000017500000000000012561642317015546 5ustar michalismichalispasdoc/source/packages/README0000600000175000017500000000246510234050565016430 0ustar michalismichalisIn this directory you should be able to find packages that allow you to install PasDoc components in Lazarus and Delphi IDE. For Delphi package files may be specific to platform (Linux or Windows) and Delphi version. Note that Kylix packages are in delphi/linux/ subdirectory, there is no kylix/ subdirectory. For Lazarus we will provide packages just for latest version of Lazarus. There should be no reason to provide separate packages for different Lazarus versions, after all Lazarus is free and you can always upgrade it. (Although in this README file may be some remarks how to install this package in older versions of Lazarus.) Great advantage of Lazarus packages is that they are not tied to a particular platform, so there is no need to maintain different package files for different platforms. Note for Lazarus 0.9.6 beta and older: You must select the "Use Ansi Strings (-Sh)" compiler option (under "Parsing"). This will not be automatically selected because Lazarus 0.9.7 stores this setting in XML element in pasdoc_package.lpk, while 0.9.6 reads element. Package name is "pasdoc_package", not just "pasdoc", to avoid any name conflicts with unit PasDoc.pas and the pasdoc program. Version of the package reflects version stored in PASDOC_VERSION constant in PasDoc unit.pasdoc/source/packages/lazarus/0000700000175000017500000000000012561642317017227 5ustar michalismichalispasdoc/source/packages/lazarus/pasdoc_package.lpk0000600000175000017500000001364012561551434022670 0ustar michalismichalis pasdoc/source/packages/delphi/0000700000175000017500000000000012561642317017013 5ustar michalismichalispasdoc/source/packages/delphi/linux/0000700000175000017500000000000012561642317020152 5ustar michalismichalispasdoc/source/packages/delphi/linux/k3/0000700000175000017500000000000012561642317020467 5ustar michalismichalispasdoc/source/packages/delphi/linux/k3/pasdoc_package.kof0000600000175000017500000000122710253545327024117 0ustar michalismichalis[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=1 P=1 Q=1 R=1 S=0 T=0 U=0 V=1 W=0 X=1 Y=1 Z=1 ShowHints=1 ShowWarnings=1 UnitAliases= [Linker] MapFile=0 OutputObjs=0 ConsoleApp=1 DebugInfo=0 RemoteSymbols=0 ResourceReserve=1048576 ImageBase=4194304 ExeDescription=PasDoc components DynamicLoader=/lib/ld-linux.so.2 [Directories] SearchPath= Packages=rtl:pvisualclx:pvisualdbclx:dataclx:xmlrtl:netdataclx:netclx:indy:soaprtl Conditionals= DebugSourceDirs= UsePackages=0 [Parameters] RunParams= HostApplication= Launcher=/usr/X11R6/bin/xterm -T KylixDebuggerOutput -e bash -i -c %debuggee% UseLauncher=0 DebugCWD= pasdoc/source/packages/delphi/linux/k3/pasdoc_package.dpk0000600000175000017500000000421210526527722024115 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl; contains PasDoc_Utils in '../../../../component/PasDoc_Utils.pas', PasDoc_ObjectVector in '../../../../component/PasDoc_ObjectVector.pas', PasDoc_Base in '../../../../component/PasDoc_Base.pas', PasDoc_Gen in '../../../../component/PasDoc_Gen.pas', PasDoc_GenHtml in '../../../../component/PasDoc_GenHtml.pas', PasDoc_GenLatex in '../../../../component/PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '../../../../component/PasDoc_HierarchyTree.pas', PasDoc_Items in '../../../../component/PasDoc_Items.pas', PasDoc_Languages in '../../../../component/PasDoc_Languages.pas', PasDoc_Parser in '../../../../component/PasDoc_Parser.pas', PasDoc_Reg in '../../../../component/PasDoc_Reg.pas', PasDoc_Scanner in '../../../../component/PasDoc_Scanner.pas', PasDoc_Serialize in '../../../../component/PasDoc_Serialize.pas', PasDoc_TagManager in '../../../../component/PasDoc_TagManager.pas', PasDoc_Tokenizer in '../../../../component/PasDoc_Tokenizer.pas', PasDoc_Types in '../../../../component/PasDoc_Types.pas', PasDoc_StreamUtils in '../../../../component/PasDoc_StreamUtils.pas', PasDoc_StringVector in '../../../../component/PasDoc_StringVector.pas', PasDoc_Hashes in '../../../../component/PasDoc_Hashes.pas', PasDoc_Tipue in '../../../../component/tipue/PasDoc_Tipue.pas', PasDoc_SortSettings in '../../../../component/PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '../../../../component/PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '../../../../component/PasDoc_StringPairVector.pas', PasDoc_Aspell in '../../../../component/PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '../../../../component/PasDoc_ProcessLineTalk.pas'; end. pasdoc/source/packages/delphi/win32/0000700000175000017500000000000012561642317017755 5ustar michalismichalispasdoc/source/packages/delphi/win32/5.0/0000700000175000017500000000000012561642317020257 5ustar michalismichalispasdoc/source/packages/delphi/win32/5.0/pasdoc_package.dof0000600000175000017500000002244110530016770023672 0ustar michalismichalis[Compiler] A=1 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=1 R=1 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; [Linker] MapFile=3 OutputObjs=0 ConsoleApp=1 DebugInfo=0 RemoteSymbols=0 MinStackSize=16384 MaxStackSize=1048576 ImageBase=4194304 ExeDescription=PasDoc components [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath=$(DELPHI)\Source\Vcl;$(DELPHI)\Lib\Debug Packages=Vcl50;Vclx50;VclSmp50;DJCL50;Vcldb50;DBVT5;JVCL200_R50;dclusr50;Qrpt50;tdbf_d5r;JvCoreD5R;JvBandsD5R;JvCtrlsD5R;JvSystemD5R;JvStdCtrlsD5R;JvPageCompsD5R;JvCmpD5R;JvMMD5R;JvJansD5R;vclie50;JvGlobusD5R;JvDotNetCtrlsD5R;JvCustomD5R;JvAppFrmD5R;JvValidatorsD5R;JvDBD5R;JvDlgsD5R;ObjectDataset50;JvDockingD5R;JclD50;MPHexEditor_D5;RxCtl5;JvHMID5R Conditionals= DebugSourceDirs= UsePackages=0 [Parameters] RunParams= HostApplication= [Version Info] IncludeVerInfo=1 AutoIncBuild=1 MajorVer=0 MinorVer=0 Release=3 Build=3 Debug=1 PreRelease=0 Special=0 Private=1 DLL=0 Locale=1049 CodePage=0 [Version Info Keys] CompanyName= FileDescription= FileVersion=0.0.3.3 InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion=1.0.0.0 LastCompiled=2006-11-16 23:38:47 PrivateBuild= [Excluded Packages] D:\Borland\AddOns\Tools_and_demos\VCL_Browser\VCLTree.bpl=VCL Components Hierarchy Browser $(DELPHI)\Projects\Bpl\ProDsgn50.bpl=Pro VCL Extensions Library $(DELPHI)\Projects\Bpl\DclRx5.bpl=RX Library Controls and Tools $(DELPHI)\Projects\Bpl\vgDVCL5.bpl=VG Library VCL Components $(DELPHI)\Projects\Bpl\DSpatialD5.bpl=DSpatial components for D5 $(DELPHI)\Bin\dclaxserver50.bpl=Microsoft Office 97 / Borland Sample Automation Server Components?? $(DELPHI)\Projects\Bpl\KWizardD5.bpl=K Wizard Design Time Package $(DELPHI)\Projects\Bpl\VKDBF.bpl=VK DBF V 1.0.5 beta for D5 $(DELPHI)\Bin\dclocx50.bpl=Borland Sample Imported ActiveX Controls d:\borland\AddOns\mmc\MMCExpert.bpl=MMC Snapin Expert $(DELPHI)\Projects\Bpl\JvBandsD5D.bpl=JVCL Band Objects $(DELPHI)\Projects\Bpl\JvBDED5D.bpl=JVCL BDE Components $(DELPHI)\Projects\Bpl\JvCryptD5D.bpl=JVCL Encryption and Compression $(DELPHI)\Projects\Bpl\JvDockingD5D.bpl=JVCL Docking Components $(DELPHI)\Projects\Bpl\JvDotNetCtrlsD5D.bpl=JVCL DotNet Controls $(DELPHI)\Projects\Bpl\JvEDID5D.bpl=JVCL EDI Components $(DELPHI)\Projects\Bpl\JvGlobusD5D.bpl=JVCL Globus Components $(DELPHI)\Projects\Bpl\JvHMID5D.bpl=JVCL HMI Controls $(DELPHI)\Projects\Bpl\JvInterpreterD5D.bpl=JVCL Interpreter Components $(DELPHI)\Projects\Bpl\JvJansD5D.bpl=JVCL Jans Components $(DELPHI)\Projects\Bpl\JvManagedThreadsD5D.bpl=JVCL Managed Threads $(DELPHI)\Projects\Bpl\JvMMD5D.bpl=JVCL Multimedia and Image Components $(DELPHI)\Projects\Bpl\JvNetD5D.bpl=JVCL Network Components $(DELPHI)\Projects\Bpl\JvPluginD5D.bpl=JVCL Plugin Components $(DELPHI)\Projects\Bpl\JvPrintPreviewD5D.bpl=JVCL Print Preview Components $(DELPHI)\Projects\Bpl\JvRuntimeDesignD5D.bpl=JVCL Runtime Design Components $(DELPHI)\Projects\Bpl\JvTimeFrameworkD5D.bpl=JVCL Time Framework $(DELPHI)\Projects\Bpl\JvUIBD5D.bpl=JVCL Unified Interbase Components $(DELPHI)\Projects\Bpl\JvValidatorsD5D.bpl=JVCL Validators and Error Provider Components $(DELPHI)\Projects\Bpl\JvWizardD5D.bpl=JVCL Wizard $(DELPHI)\Projects\Bpl\JvXPCtrlsD5D.bpl=JVCL XP Controls $(DELPHI)\Bin\dclbde50.bpl=Borland BDE DB Components $(DELPHI)\Projects\Bpl\dclCnPack_D5.bpl=CnPack Components Designtime Package $(DELPHI)\Bin\DCLADO50.bpl=Borland ADO DB Components $(DELPHI)\Projects\Bpl\dclrxdb5.bpl=RX Library Database Components $(DELPHI)\Projects\Bpl\Polaris50DT.bpl=Polaris Components $(DELPHI)\Projects\Bpl\EssHtmlReports_DesignTime.bpl=ESS Html Reports. Design Time $(DELPHI)\Bin\dclnet50.bpl=Borland Internet Components $(DELPHI)\Bin\dclie50.bpl=Internet Explorer Components $(DELPHI)\Projects\Bpl\ExtLib_D5.bpl=Extension library $(DELPHI)\Projects\Bpl\dclFth50.bpl=4th GUI Library $(DELPHI)\Projects\Bpl\GR32_DSGN_D5.bpl=Graphics32 Design Time Package $(DELPHI)\Projects\Bpl\GR32_D5.bpl=Graphics32 $(DELPHI)\Projects\Bpl\PTShellControlPack.bpl=Shell Control Pack V1.3c $(DELPHI)\Projects\Bpl\FmHelp5.bpl=TFormHelp Component $(DELPHI)\Projects\Bpl\vgDDB5.bpl=VG Library DB Components $(DELPHI)\Projects\Bpl\vgDRXDB5.bpl=VG Library DB Components (RX) $(DELPHI)\Projects\Bpl\MirrorKOLPackage.bpl=_KOL_ mirror controls for Delphi5 $(DELPHI)\Projects\Bpl\DclEhlib50.bpl=EhLib 3.0 Components $(DELPHI)\Projects\Bpl\dclrxbd5.bpl=RX Library BDE Database Components $(DELPHI)\Projects\Bpl\FIBPlus5.bpl=FIBPlus $(DELPHI)\Projects\Bpl\FR5.bpl=FastReport 2.4 Components $(DELPHI)\Projects\Bpl\FRIBX5.bpl=FastReport 2.4 IBX Components $(DELPHI)\Projects\Bpl\FRBDE5.bpl=FastReport 2.4 BDE Components $(DELPHI)\Projects\Bpl\FRADO5.bpl=FastReport 2.4 ADO Components $(DELPHI)\Bin\dclwbm50.bpl=Borland InternetExpress Components $(DELPHI)\Bin\applet50.bpl=Borland Control Panel Applet Package $(DELPHI)\Bin\DBWEBXPRT.BPL=Borland Web Wizard Package $(DELPHI)\Bin\dclqrt50.bpl=QuickReport Components $(DELPHI)\Bin\dcltqr50.bpl=TeeChart 5.0 for QuickReport Components Design Package $(DELPHI)\Bin\dcltee50.bpl=TeeChart 5.0 Components $(DELPHI)\Bin\dcldss50.bpl=Borland Decision Cube Components $(DELPHI)\Bin\DCLNMF50.bpl=NetMasters Fastnet Tools $(DELPHI)\Bin\DCLIB50.bpl=InterBase Data Access Components $(DELPHI)\Bin\dclmid50.bpl=Borland MIDAS Components D:\Borland\AddOns\Tools_and_demos\CompPalette\AWSExpertGP_D5Rus.bpl=AWSExpert 1.1 GroupPallete $(DELPHI)\Projects\Bpl\DBVT5.bpl=DB Virtual TreeView $(DELPHI)\Projects\Bpl\ImgZoom.bpl=Image Zoom Package, (c) 2000 by Dott. Cosimo De Michele $(DELPHI)\Projects\Bpl\denasVcl.bpl=some little gadgets $(DELPHI)\Projects\Bpl\FindApp.bpl=Searching for Excel, InternetExplorer... $(DELPHI)\Bin\dcloffice2k50.bpl=Microsoft Office 2000 Automation Components $(DELPHI)\Projects\Bpl\FIBPlusEditors5.bpl=FIBPlus property editors D:\Borland\AddOns\FIBC\pFIBPlusTools5.bpl=FIBPlus Projects Tools C:\WINDOWS\system32\ibevnt50.bpl=Borland Interbase Event Alerter Component $(DELPHI)\Projects\Bpl\Mappack.bpl=BAIKONUR GIS ToolKit Professional $(DELPHI)\Bin\dclite50.bpl=Borland Integrated Translation Environment [HistoryLists\hlUnitAliases] Count=1 Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; [HistoryLists\hlSearchPath] Count=1 Item0=E:\Download\Borland\PasDoc\svn\source\component\strutils\;D:\IpponUPS\Programs\dcu;$(DELPHI)\Source\Vcl;$(DELPHI)\Lib\Debug;D:\Borland\AddOns\Rus;D:\Borland\AddOns\SynaSer\source\;D:\Borland\AddOns\MPHexEdit\vcl;D:\IpponUPS\Programs\COMsetup;D:\Borland\AddOns\Jedi\jcl\source\common;D:\Borland\AddOns\Jedi\jcl\source\windows\;E:\Download\Borland\PasDoc\svn\source\component\images [Included Packages-Delphi5] $(DELPHI)\Bin\dclstd50.bpl=Borland Standard Components $(DELPHI)\Bin\dcldb50.bpl=Borland Database Components $(DELPHI)\Bin\dclsmpedit50.bpl=Borland Editor Script Enhancements $(DELPHI)\Bin\dclsmp50.bpl=Borland Sample Components $(DELPHI)\Bin\dcl31w50.bpl=Delphi 1.0 Compatibility Components $(DELPHI)\Projects\Bpl\dclusr50.bpl=Borland User Components $(DELPHI)\Projects\Bpl\ccpack50.bpl=Custom Containers Pack $(DELPHI)\Projects\Bpl\vgr_dsgnCommonControlsD5.bpl=vtkTools CommonControls $(DELPHI)\Projects\Bpl\vgr_dsgnGridReportD5.bpl=vtkTools GridReport $(DELPHI)\Projects\Bpl\MPHexEditor_D5.bpl=mirkes.de HexEditor vcl $(DELPHI)\Projects\Bpl\tdbf_d5d.bpl=TDbf for Delphi 5 $(DELPHI)\Projects\Bpl\EPCDUnitWizard50.bpl=EPC DUnit Wizard $(DELPHI)\Projects\Bpl\ThemeManagerD5D.bpl=Theme Manager design time package $(DELPHI)\Projects\Bpl\VirtualTreesD5D.bpl=Virtual Treeview design time package $(DELPHI)\Projects\Bpl\ObjectDataset50.bpl=ObjectDataset $(DELPHI)\Projects\Bpl\JvCoreD5D.bpl=JVCL Core Components $(DELPHI)\Projects\Bpl\JvCtrlsD5D.bpl=JVCL Visual Controls $(DELPHI)\Projects\Bpl\JvSystemD5D.bpl=JVCL System Components $(DELPHI)\Projects\Bpl\JvStdCtrlsD5D.bpl=JVCL Standard Controls $(DELPHI)\Projects\Bpl\JvCmpD5D.bpl=JVCL Non-Visual Components $(DELPHI)\Projects\Bpl\JvPageCompsD5D.bpl=JVCL Page Style Components $(DELPHI)\Projects\Bpl\JvCustomD5D.bpl=JVCL Custom Controls $(DELPHI)\Projects\Bpl\JvDBD5D.bpl=JVCL Database Components $(DELPHI)\Projects\Bpl\JvAppFrmD5D.bpl=JVCL Application and Form Components $(DELPHI)\Projects\Bpl\JvDlgsD5D.bpl=JVCL Dialog Components $(DELPHI)\Projects\Bpl\JclUsesExpertd50.bpl=JCL Uses Wizard $(DELPHI)\Projects\Bpl\JclBaseExpertD50.bpl=JCL Package containing common units for JCL Experts $(DELPHI)\Projects\Bpl\JclThreadNameExpertd50.bpl=JCL Thread Name IDE expert $(DELPHI)\Projects\Bpl\JclProjectAnalysisExpertd50.bpl=JCL Project Analyzer $(DELPHI)\Projects\Bpl\JclRepositoryExpertd50.bpl=JCL Package containing repository wizards $(DELPHI)\Projects\Bpl\JclFavoriteFoldersExpertd50.bpl=JCL Open and Save IDE dialogs with favorite folders $(DELPHI)\Projects\Bpl\JclVersionControlExpertd50.bpl=JCL Integration of version control systems in the IDE $(DELPHI)\Projects\Bpl\JclSIMDViewExpertd50.bpl=JCL Debug Window of XMM registers $(DELPHI)\Projects\Bpl\JclDebugExpertd50.bpl=JCL Debug IDE extension d:\borland\addons\CompBAR\CompBAR5.bpl=Component Bar Expert $(DELPHI)\Projects\Bpl\pasdoc_package.bpl=PasDoc components pasdoc/source/packages/delphi/win32/5.0/pasdoc_package.dpk0000600000175000017500000000443011464312753023705 0ustar michalismichalispackage pasdoc_package; {$R *.RES} {$ALIGN ON} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires vclx50, vcl50; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/5.0/Makefile0000600000175000017500000000036110527011653021712 0ustar michalismichalispasdoc_package.dpk: ../7.0/pasdoc_package.dpk sed $< \ -e 's/{$$R \*.res}/{$$R *.RES} {$$ALIGN ON}/ig' \ -e 's/rtl,//ig' \ -e 's/vclx,/vclx50,/ig' \ -e 's/vcl;/vcl50;/ig' \ > $@ .PHONY: clean clean: rm -f pasdoc_package.dpkpasdoc/source/packages/delphi/win32/5.0/pasdoc_package.cfg0000600000175000017500000000055510530016770023663 0ustar michalismichalis-$A+ -$B- -$C+ -$D+ -$E- -$F- -$G+ -$H+ -$I+ -$J- -$K- -$L+ -$M- -$N+ -$O+ -$P+ -$Q+ -$R+ -$S- -$T- -$U- -$V+ -$W- -$X+ -$YD -$Z1 -GD -cg -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -H+ -W+ -M -$M16384,1048576 -K$00400000 -LE"d:\borland\delphi5\Projects\Bpl" -LN"d:\borland\delphi5\Projects\Bpl" -Zpasdoc/source/packages/delphi/win32/2009/0000700000175000017500000000000012561642317020347 5ustar michalismichalispasdoc/source/packages/delphi/win32/2009/pasdoc_package.dpk0000600000175000017500000000443011464312753023775 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/2009/pasdoc_package.dproj0000600000175000017500000001726111463363552024345 0ustar michalismichalis {8e4600a9-342b-487a-ad12-37343bf61652} pasdoc_package.dpk Debug AnyCPU DCC32 C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\5.0\Bpl\pasdoc_package.bpl 12.0 Debug true true Base true true Base true 00400000 false C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\6.0\Bpl\pasdoc_package.bpl true PasDoc components true true true 1 true 7.0 False False True True 0 ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) RELEASE;$(DCC_Define) False False 7.0 True True ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) False False Delphi.Personality.12 Package False True False True False 0 9 0 0 False False False False False 1045 1250 0.12.0 0.12.0 pasdoc_package.dpk 12 MainSource Base Cfg_2 Base Cfg_1 Base pasdoc/source/packages/delphi/win32/7.0/0000700000175000017500000000000012561642317020261 5ustar michalismichalispasdoc/source/packages/delphi/win32/7.0/pasdoc_package.dof0000600000175000017500000000467711046152433023707 0ustar michalismichalis[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=1 R=1 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=PasDoc components [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath=..\..\..\..\component\images;..\..\..\..\component\tipue 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;Rave50CLX;Rave50VCL;dclOfficeXP Conditionals= DebugSourceDirs= UsePackages=0 [Parameters] RunParams= HostApplication= Launcher= UseLauncher=0 DebugCWD= [Language] ActiveLang= ProjectLang= RootDir=C:\Program Files\Borland\Delphi7\Bin\ [Version Info] IncludeVerInfo=1 AutoIncBuild=0 MajorVer=0 MinorVer=9 Release=0 Build=0 Debug=0 PreRelease=0 Special=0 Private=0 DLL=0 Locale=1031 CodePage=1252 [Version Info Keys] CompanyName= FileDescription= FileVersion=1.0.0.0 InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion=1.0.0.0 [HistoryLists\hlUnitAliases] Count=1 Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; [HistoryLists\hlSearchPath] Count=1 Item0=..\..\..\..\component\images;..\..\..\..\component\tipue pasdoc/source/packages/delphi/win32/7.0/pasdoc_package.dpk0000600000175000017500000000433311464312753023711 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/7.0/pasdoc_package.cfg0000600000175000017500000000120311046152433023654 0ustar michalismichalis-$A8 -$B- -$C+ -$D+ -$E- -$F- -$G+ -$H+ -$I+ -$J- -$K- -$L+ -$M- -$N+ -$O+ -$P+ -$Q+ -$R+ -$S- -$T- -$U- -$V+ -$W- -$X+ -$YD -$Z1 -cg -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -H+ -W+ -M -$M16384,1048576 -K$00400000 -LE"c:\program files\borland\delphi7\Projects\Bpl" -LN"c:\program files\borland\delphi7\Projects\Bpl" -U"..\..\..\..\component\images;..\..\..\..\component\tipue" -O"..\..\..\..\component\images;..\..\..\..\component\tipue" -I"..\..\..\..\component\images;..\..\..\..\component\tipue" -R"..\..\..\..\component\images;..\..\..\..\component\tipue" -Z -w-UNSAFE_TYPE -w-UNSAFE_CODE -w-UNSAFE_CAST pasdoc/source/packages/delphi/win32/2006/0000700000175000017500000000000012561642317020344 5ustar michalismichalispasdoc/source/packages/delphi/win32/2006/pasdoc_package.dpk0000600000175000017500000000443011464312753023772 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/2006/pasdoc_package.bdsproj0000600000175000017500000002042311463363552024661 0ustar michalismichalis pasdoc_package.dpk 7.0 8 0 1 1 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 1 0 1 1 1 True True WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; False True True False True True False True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True False False False True True True True True True 0 0 False 1 False False False 16384 1048576 4194304 PasDoc components ..\..\..\..\component\images False False True False $00000000 C:\Program Files\Borland\Delphi7\Bin\ True False 0 9 0 0 False False False False False 1045 1250 0.12.0 0.12.0 pasdoc/source/packages/delphi/win32/2010/0000700000175000017500000000000012561642317020337 5ustar michalismichalispasdoc/source/packages/delphi/win32/2010/pasdoc_package.dpk0000600000175000017500000000443011464312753023765 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/2010/pasdoc_package.dproj0000600000175000017500000001717011463363552024334 0ustar michalismichalis {8e4600a9-342b-487a-ad12-37343bf61652} pasdoc_package.dpk Debug AnyCPU DCC32 C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\5.0\Bpl\pasdoc_package.bpl 12.0 Debug true true Base true true Base true 00400000 false C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\7.0\Bpl\pasdoc_package.bpl true PasDoc components true true true true 7.0 False False True True 0 ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) RELEASE;$(DCC_Define) False False 7.0 True True ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) False False Delphi.Personality.12 Package False True False True False 0 9 0 0 False False False False False 1045 1250 0.12.0 0.12.0 pasdoc_package.dpk 12 MainSource Base Cfg_2 Base Cfg_1 Base pasdoc/source/packages/delphi/win32/2007/0000700000175000017500000000000012561642317020345 5ustar michalismichalispasdoc/source/packages/delphi/win32/2007/pasdoc_package.dpk0000600000175000017500000000443011464312753023773 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/2007/pasdoc_package.dproj0000600000175000017500000001523611463363552024343 0ustar michalismichalis {8e4600a9-342b-487a-ad12-37343bf61652} pasdoc_package.dpk Debug AnyCPU DCC32 C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\5.0\Bpl\pasdoc_package.bpl 7.0 False False True True 0 ..\..\..\..\component\images ..\..\..\..\component\images ..\..\..\..\component\images ..\..\..\..\component\images RELEASE False False 7.0 True True ..\..\..\..\component\images ..\..\..\..\component\images ..\..\..\..\component\images ..\..\..\..\component\images False False Delphi.Personality Package False True False PasDoc components False False False C:\Program Files\Borland\Delphi7\Bin\ True False 0 9 0 0 False False False False False 1045 1250 0.12.0 0.12.0 pasdoc_package.dpk MainSource pasdoc/source/packages/delphi/win32/XE/0000700000175000017500000000000012561642317020271 5ustar michalismichalispasdoc/source/packages/delphi/win32/XE/pasdoc_package.dpk0000600000175000017500000000443011464312753023717 0ustar michalismichalispackage pasdoc_package; {$R *.res} {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO ON} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} {$LONGSTRINGS ON} {$OPENSTRINGS ON} {$OPTIMIZATION ON} {$OVERFLOWCHECKS ON} {$RANGECHECKS ON} {$REFERENCEINFO ON} {$SAFEDIVIDE OFF} {$STACKFRAMES OFF} {$TYPEDADDRESS OFF} {$VARSTRINGCHECKS ON} {$WRITEABLECONST OFF} {$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DESCRIPTION 'PasDoc components'} {$IMPLICITBUILD OFF} requires rtl, vclx, vcl; contains PasDoc_Utils in '..\..\..\..\component\PasDoc_Utils.pas', PasDoc_ObjectVector in '..\..\..\..\component\PasDoc_ObjectVector.pas', PasDoc_Base in '..\..\..\..\component\PasDoc_Base.pas', PasDoc_Gen in '..\..\..\..\component\PasDoc_Gen.pas', PasDoc_GenHtml in '..\..\..\..\component\PasDoc_GenHtml.pas', PasDoc_GenLatex in '..\..\..\..\component\PasDoc_GenLatex.pas', PasDoc_HierarchyTree in '..\..\..\..\component\PasDoc_HierarchyTree.pas', PasDoc_Items in '..\..\..\..\component\PasDoc_Items.pas', PasDoc_Languages in '..\..\..\..\component\PasDoc_Languages.pas', PasDoc_Parser in '..\..\..\..\component\PasDoc_Parser.pas', PasDoc_Reg in '..\..\..\..\component\PasDoc_Reg.pas', PasDoc_Scanner in '..\..\..\..\component\PasDoc_Scanner.pas', PasDoc_Serialize in '..\..\..\..\component\PasDoc_Serialize.pas', PasDoc_TagManager in '..\..\..\..\component\PasDoc_TagManager.pas', PasDoc_Tokenizer in '..\..\..\..\component\PasDoc_Tokenizer.pas', PasDoc_Types in '..\..\..\..\component\PasDoc_Types.pas', PasDoc_StreamUtils in '..\..\..\..\component\PasDoc_StreamUtils.pas', PasDoc_StringVector in '..\..\..\..\component\PasDoc_StringVector.pas', PasDoc_Hashes in '..\..\..\..\component\PasDoc_Hashes.pas', PasDoc_Tipue in '..\..\..\..\component\tipue\PasDoc_Tipue.pas', PasDoc_SortSettings in '..\..\..\..\component\PasDoc_SortSettings.pas', PasDoc_GenHtmlHelp in '..\..\..\..\component\PasDoc_GenHtmlHelp.pas', PasDoc_StringPairVector in '..\..\..\..\component\PasDoc_StringPairVector.pas', PasDoc_Aspell in '..\..\..\..\component\PasDoc_Aspell.pas', PasDoc_ProcessLineTalk in '..\..\..\..\component\PasDoc_ProcessLineTalk.pas', PasDoc_Versions in '..\..\..\..\component\PasDoc_Versions.pas'; end. pasdoc/source/packages/delphi/win32/XE/pasdoc_package.dproj0000600000175000017500000001753611463363552024274 0ustar michalismichalis {8e4600a9-342b-487a-ad12-37343bf61652} pasdoc_package.dpk Debug DCC32 C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\5.0\Bpl\pasdoc_package.bpl 12.2 Debug True Win32 Package VCL true true Base true true Base true WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) 00400000 false C:\Dokumente und Einstellungen\All Users\Dokumente\RAD Studio\7.0\Bpl\pasdoc_package.bpl true PasDoc components true true true true 7.0 False False True True 0 ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) RELEASE;$(DCC_Define) False False 7.0 True True ..\..\..\..\component\images;$(DCC_UnitSearchPath) ..\..\..\..\component\images;$(DCC_ResourcePath) ..\..\..\..\component\images;$(DCC_ObjPath) ..\..\..\..\component\images;$(DCC_IncludePath) False False Delphi.Personality.12 Package True False 0 9 0 0 False False False False False 1045 1250 0.12.0 0.12.0 pasdoc_package.dpk True 12 MainSource Cfg_2 Base Base Cfg_1 Base pasdoc/source/delphi_gui/0000700000175000017500000000000012561642317016101 5ustar michalismichalispasdoc/source/delphi_gui/pasdoc_gui_manifest.xml0000600000175000017500000000117212337202423022620 0ustar michalismichalis Windows Shell pasdoc/source/delphi_gui/preferencesfrm.pas0000600000175000017500000000456412337202423021616 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { This unit implements TPreferences form (run by TPreferences.Execute). @author(Michalis Kamburelis) @author(Arno Garrels )} 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; EditWWWBrowserCommand: TEdit; EditWWWHelpServer: TEdit; LabelWWWBrowserCommand: TLabel; 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 EditWWWBrowserCommand.Text := DefaultWWWBrowserCommand; EditWWWHelpServer.Text := DefaultWWWHelpServer; cbLoadLastProject.Checked := TRUE; end; class procedure TPreferences.Execute; var F: TPreferences; begin F := TPreferences.Create(nil); try F.EditWWWBrowserCommand.Text := WWWBrowserRunner.BrowserCommand; F.EditWWWHelpServer.Text := WWWHelpServer; F.cbLoadLastProject.Checked := AutoLoadLastProject; if F.ShowModal = mrOK then begin WWWBrowserRunner.BrowserCommand := F.EditWWWBrowserCommand.Text; WWWHelpServer := F.EditWWWHelpServer.Text; AutoLoadLastProject := F.cbLoadLastProject.Checked; end; finally F.Free; end; end; end. pasdoc/source/delphi_gui/pasdoc_gui.dpr0000600000175000017500000000117312337202423020720 0ustar michalismichalisprogram 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/HelpProcessor.pas0000600000175000017500000000615412337202423021375 0ustar michalismichalis{ @author(Richard B. Winston ) 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/frmAboutUnit.pas0000600000175000017500000000444712337202423021227 0ustar michalismichalis{ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA } { @author(Richard B. Winston ) @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/preferencesfrm.dfm0000600000175000017500000000405512337202423021574 0ustar michalismichalisobject 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 LabelWWWBrowserCommand: TLabel Left = 8 Top = 6 Width = 345 Height = 39 Caption = 'C&ommand to run WWW browser :'#10'(%s will be replaced with the URL,' + ' %% with %)'#10'(under Windows you can leave this blank to use defau' + 'lt WWW browser)' Color = clBtnFace FocusControl = EditWWWBrowserCommand ParentColor = False end 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 EditWWWBrowserCommand: TEdit Left = 8 Top = 46 Width = 392 Height = 21 TabOrder = 0 Text = 'EditWWWBrowserCommand' 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/pasdoc_gui_manifest.rc0000600000175000017500000000003612337202423022422 0ustar michalismichalis1 24 "pasdoc_gui_manifest.xml"pasdoc/source/delphi_gui/WWWBrowserRunnerDM.pas0000600000175000017500000000545612337202423022254 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { @author(Michalis Kamburelis) @author(Arno Garrels ) } 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 BrowserCommand: string; procedure RunBrowser(const URL: string); end; var WWWBrowserRunner: TWWWBrowserRunner; const DefaultWWWBrowserCommand = {$ifdef WIN32} '' {$else} 'sh -c "$BROWSER %s"' {$endif}; implementation uses {$ifdef WIN32} Windows, ShellAPI, {$endif} PasDocGuiSettings; {$R *.dfm} { TWWWBrowserRunner } procedure TWWWBrowserRunner.DataModuleCreate(Sender: TObject); begin BrowserCommand := IniFile.ReadString('Main', 'WWWBrowserCommand', DefaultWWWBrowserCommand); end; procedure TWWWBrowserRunner.DataModuleDestroy(Sender: TObject); begin IniFile.WriteString('Main', 'WWWBrowserCommand', BrowserCommand); 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} if Trim(BrowserCommand) = '' then begin ShellExecuteURL; Exit; end; {$endif} end; end. pasdoc/source/delphi_gui/pasdoc_gui.dof0000600000175000017500000000337712337202423020713 0ustar michalismichalis[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/PasDocGuiSettings.pas0000600000175000017500000001301312337202423022134 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 = 'http://pasdoc.sipsolutions.net/'; 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/frmhelpgeneratorunit.dfm0000600000175000017500000013423612337202423023037 0ustar michalismichalisobject 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
,'#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 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
,'#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 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/frmhelpgeneratorunit.pas0000600000175000017500000015555312337202423023061 0ustar michalismichalis{ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA } { @abstract(@name contains the main form of Help Generator.) @author(Richard B. Winston ) @author(Michalis Kamburelis) @author(Arno Garrels ) @created(2004-11-28) @cvs($Date: 2008-08-04 03:40:15 +0200 (Mo, 04 Aug 2008) $) } 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: result := 'pt'; // Portuguese used for brazilian. 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: TPasCios; I, J: Integer; ClassNode: TTreeNode; FieldsNode: TTreeNode; MethodNode: TTreeNode; PropertiesNode: TTreeNode; TypesNode: TTreeNode; PasItem: TPasItem; begin LCios := TPasCios(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/WWWBrowserRunnerDM.dfm0000600000175000017500000000027112337202423022225 0ustar michalismichalisobject WWWBrowserRunner: TWWWBrowserRunner OldCreateOrder = True OnCreate = DataModuleCreate OnDestroy = DataModuleDestroy Left = 15 Top = 15 Height = 161 Width = 278 end pasdoc/source/delphi_gui/pasdoc_gui.dproj0000600000175000017500000001065612337202423021257 0ustar michalismichalis {d6674a0e-9e27-4eb8-9b5f-d0b955f2e525} pasdoc_gui.dpr Debug AnyCPU DCC32 pasdoc_gui.exe 7.0 False False 0 ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue RELEASE 7.0 ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue ..\component;..\component\images;..\component\tipue DEBUG Delphi.Personality VCLApplication ..\component;..\Console;..\component\tipue False True False False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 pasdoc_gui.dpr MainSource
frmAbout
frmHelpGenerator
preferencesfrm
WWWBrowserRunner
pasdoc/source/delphi_gui/frmAboutUnit.dfm0000600000175000017500000000260312337202423021202 0ustar michalismichalisobject 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/gui/0000700000175000017500000000000012561642317014554 5ustar michalismichalispasdoc/source/gui/preferencesfrm.pas0000600000175000017500000000332012337202423020256 0ustar michalismichalis{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { This unit implements TPreferences form (run by TPreferences.Execute). @author(Michalis Kamburelis) } unit PreferencesFrm; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ButtonPanel; type { TPreferences } TPreferences = class(TForm) ButtonPanel1: TButtonPanel; EditWWWHelpServer: TEdit; LabelWWWHelpServer: TLabel; private { private declarations } public class procedure Execute; end; implementation uses PasDocGuiSettings; class procedure TPreferences.Execute; var F: TPreferences; begin F := TPreferences.Create(nil); try F.EditWWWHelpServer.Text := WWWHelpServer; if F.ShowModal = mrOK then begin WWWHelpServer := F.EditWWWHelpServer.Text; end; finally F.Free; end; end; initialization {$I preferencesfrm.lrs} end. pasdoc/source/gui/preferencesfrm.lfm0000600000175000017500000000273212170553131020257 0ustar michalismichalisobject Preferences: TPreferences Left = 459 Height = 150 Top = 282 Width = 362 HorzScrollBar.Page = 423 VertScrollBar.Page = 191 AutoSize = True BorderWidth = 10 Caption = 'Preferences' ClientHeight = 150 ClientWidth = 362 Position = poMainFormCenter LCLVersion = '1.0.10.0' object LabelWWWHelpServer: TLabel AnchorSideTop.Side = asrBottom Left = 8 Height = 26 Top = 8 Width = 253 BorderSpacing.Top = 16 Caption = 'Base &URL of PasDoc help pages' FocusControl = EditWWWHelpServer ParentColor = False end object EditWWWHelpServer: TEdit AnchorSideTop.Control = LabelWWWHelpServer AnchorSideTop.Side = asrBottom Left = 8 Height = 35 Top = 34 Width = 346 Anchors = [akTop, akLeft, akRight] TabOrder = 0 Text = 'EditWWWHelpServer' end object ButtonPanel1: TButtonPanel AnchorSideTop.Control = EditWWWHelpServer AnchorSideTop.Side = asrBottom Left = 10 Height = 63 Top = 77 Width = 342 Anchors = [akTop, akLeft, akRight] BorderSpacing.Top = 8 BorderSpacing.Around = 0 OKButton.Name = 'OKButton' OKButton.DefaultCaption = True HelpButton.Name = 'HelpButton' HelpButton.DefaultCaption = True CloseButton.Name = 'CloseButton' CloseButton.DefaultCaption = True CancelButton.Name = 'CancelButton' CancelButton.DefaultCaption = True TabOrder = 1 Spacing = 8 ShowButtons = [pbOK, pbCancel] ShowBevel = False end end pasdoc/source/gui/icons/0000700000175000017500000000000012561642317015667 5ustar michalismichalispasdoc/source/gui/icons/PasDoc032.png0000600000175000017500000000112212221630742017761 0ustar michalismichalisPNG  IHDR V%(sRGB!tEXtSoftwareGraphicConverter (Intel)wIDATxbO0PC?Up<(?a.5@xĭ`̽Ϥk?p=؅(X. 6FwߠYT}xY:N=@㍓$?_4Tv d*n*F|_47{+!)X)z 0H_]6}P#0sMo"_Bq$~@{v8p>'gSW8TkbX+,+$rf@ޡH'uI_[\q*x$0qU~?U% dmGQ?CnƎ?d:~٥a&[?o_a y|tJ* (٘-Nmor k[gޠ^dQs耬nIENDB`pasdoc/source/gui/icons/PasDoc256.png0000600000175000017500000003326012221630742020001 0ustar michalismichalisPNG  IHDRysRGB!tEXtSoftwareGraphicConverter (Intel)w6=IDATx]u\TfXCSEEE0PlED AAQQTQZbw]TbA]|Μ9ss?;@k%5@ uhк_hZ/ZwK;@k%5@ uhк_hZc4$"apg z{{"DNh,چ\{[+?bs*ۺzG8MnF+oy LH/n(M`k[6\1+mW٭۴u3W]]  GЬ\3-7 ˨hpȏ G `߉8:%'($$$((Diӳ )sCO300ayMCCٳfhK3#gp]~*pVQy;w~Zۥsĸ o=u>^wo]x+#Uq.&eқC`tלyKrI Cݿ~b2Cy~f2Lo|,iu`DvxF757556Ve}Ԗy*hh  jӤD{ւ'x@/27ŕJ j <+&]&$lL N" dh*MKF`*|=!nkuYvѱa#0EQטpy}J:LmL\i5Hm^IZAHo8-)4gn[;@$"~َikkôwz I|}}l О쐅r4]T5vއh*-LOO+k\ha8?;#---#+';&&->e%Bj/GVQ{GsMInj§w!/=٫iU$o^={ODD'aziI@wIl*?"kL؋w^8}~{:vǣ_Q3m*M~tcݳwgoxRC-|)R"]-gX߉/A~.ݳuJLM[Z;z<ʮ쟈 Vv֋[,Ya/:}Sƌ >?!Փ{741T!#).&*&&)ofc#8o|HƂo63PSUP20quFe@.y p]f~w2UbgA32УѬJHoWbE3ңP(zF&fVn~QՅ{j@h̀ Gka,5&Zb| HE`0$UvK#3kc 'Έ`?0:0*jde/;f~}; #-;謝+# gbadeB4#5i = b_s;,Tp= hAή} ᛿+ 9B(#_Y$ӇR($WXJ^ESG@_[M^B6]+P^Hn˄#85t fi)ʊ r hv%}77A0Yak1k,!&&v~ E9lnjXSZFIIH&o"7 ϳYi-VXPT7wvSDvQC"06Eא®aߐh$- gfaSݾy֥V( PB :(僘s4`0zqrKg:o[kl󉇉43$b_]. 46pSWo`L֛]tvKu!0CKKwtVq~MLJUS}e7Q+3xi|A((((fx4^عvөB>}*,orkBez2q}4ؒ0UO\|S +kj*s? V1HcIp 9lN1m~W_ J-j`{}M}ی_GM e>;@|Iv{-ha0760^{h1eQd;1#3BWuƧIyU]}}9ϮT$`<31llaiw1! bہ PS {Z[-EQJ'^dXΈmE%vبr q%h6q\߻ºiIĘ DӣPHC0-W3fpMv57T%8k @\EHd>w7Uӓ:a؈$9+:CdWﰔ L!ض겂計ל, Q:=a&k&)yk&R{IpLLh43 ;'kw|P5 8TU9ܺqֺb@OyzFbN'efgRKn'"/*)##+'3d NǮVcz o)H }}agm61בs+& ,ٷHU#S+fdmrqxJin`U~斖,]rm{~LDn̊ yxV.03SOGKSMIF M@7b[ᇻ{ (fnQE /GWP3?w"?]Rj˾cǎ<}{F%7z~B_{uVt33V!-.*,$L@ۜq2=in&$y2"8t?xY  PoA(MWuɞ_ zǘԜ >7&}a073ixz3UQ eul:&rs%@/dRچX8 j++;lsgi ~1 Zw-$ rb&` t_G10nPxN,[}N PQ !(6| [w8ٽu?/ g"msTyX)P~Es8:HxlMKm l3,V9?~c덤&^fe ՝SWhH 1") QŘ?`6rl,ϋF!Ѽ2zy> N5-9a+%_N%|/:;יv9bѲqN澹bo$G2 *;t򚆦Ƽkx&t4ZӶ6.(B0$֊)TR[uLG0 Yn82 ?'kmA7Ƞ`j?~tY l _z[N4ߔpJgW]VhJy d$'-%{'Q>["JWym#)?GD^#n4e [ЏmȊ~qjC9nFjbJ*SU e=?h`ahYo^]%` >>r8W :aIz+5J@]laXs(,9,oF.[˾^d(Ig:xmPKv\*FE h{M t]%fiù4\Q2II,Сn߯ͣ\M<Vp)-?{?T%̡/D><,} t`0:KO&qAU hG_v& çB` !7Ba[ru 5 >= 1IY$R_էkɞ J7J@Ƥ{:\"$w}m=rh/|h>@$Mi?ZMxSeULŔFy6fYVykP ZW[KktjuZM *О A)"8 HkκO,teWyck Z#$@kfq+07GjT^_$1x)47wcj =ԗ` ҒsC_Da~"@1E7a@[(EMH=.р)$ ׂԷ5Ֆf'?DW m =b{GtbWYܓkg|YRޒˋrTL KuNj$JQN1t`|%%Ǿun\U ~F0؍R9<"#kVn>]\jnqEM]}]MYnb~kM0; + 19/[)r Jk\ţ+M5dDDDDxY YbΖK/ \a 1YϏoarśQqq/m_)Š5mϾmD\EP+ka[VYI )ik+c =Mȩn#eHa,' ;,}܎n+ 1iQӚ1OK0?gQTRaG_)s6Jqq*Eڋ#T%gRA*,PhN1yO?;J}K84zF :eXJz+d\t=$J'#ce TXt40}J{ґFW(4Ҝ{HɎ= z މu?#Dlɇ[;櫊 B@8 .1eUͬQ+}pgV:rJs7^|S0Y$BOcN,RK]Onm*pBIS|azjS^\fj6CBlGXFfspT; %֜ru%/|7b;.)?.[s}RjV8*p {\w$-!!)b̋acJۺjlUE9)qq1qI*چ W<T҃څ;ʒ^ݽpĉWFd7Lۀ2K\ؿj<3V?2&O29eyp8 gtykEFto\mlv\ͭ跱zKR^'tNU"D"w'}ˁ\Ny&>ʪ brn=r`=E*l+Ãxt?s}}IџJ7C5v p=}tԖdef׵t K)"︪8'33+B (C}w^4`X az0y.۩q/ً -Q,jsK 3sr@KTiβݗ%L7EsLOBAM 5U%yY)qa~n64=Yt `U5pS~ӟ]t ,m׭_~ݺukح^z07+9M#gxn4eLњ]p+ιwdvYuN&xMpE©X) ħO#?=ճ-4bg&Y@ey-m2NЬ-eWVQUYQVZ\5oÛAat&>{FaƯAkLPArCo?>T=\_UsUaH/0xqiA^Dj0 韞^޵T, eǞ|ckR"흗fan!9$&ߠ'VHv?@3 1eOeR Hkx SƸZ?@uAYlt}(jxd ۃ#'~o7I" uuA-BV>mΊ*I _ P/i,+.,((,.ml* eƚR¢ҊvlO?~4(H*AGϯJD)vޠz\WsuQVro_ 9s*wdaғb"߅[95 & ,XUc.<4eܻ$H68-W.9yIoy? 5W~l,Juǁ]YHQѴ0[yY.pgߎ0[ܼfŋ,]nq}Cb&uS U_҉}W/^h͎ؒ{0<;RkzŁ޹惬]ikpebcQRυ[P3z׻~ #\S0+GVS!++;C^IECwҍ.y#u'od$a0s~LIwGUzsVSbga+$ml)ЯemToΈxxy qAN6!47̕Gm<2mȺOzoTQxoh+MzqD]B ŕ@mw+'1EVm-Izy}xggb3tz /GCHO,L|X12`GkHp3p8 ; /\ZR|,(43 C*Ř Ge,y0K/<<} Z |- V!yEg((ˈ4].q-Ζc,Ҁ!+-L,V&nUcZL߈ݥVrB]#=?(;=h.y# lۮ^h$<"jֻqbK-!K7H[,^j9z R27]]e ݱ {z[ՍV@$ v>8TC ӳ +^/^p=g2c5 .F S񡰍a`?z:/R$gӝokӮOٿs9&+W;F%1GWI$k<v B[Zok }wiJ0+~sFl)Ri 9-g㨬F`ۍlOxuR|0ZHwͅJA7E 8#fWږ,v5Uf~IHJ/ičHފVIjK`NLj_cIm+|iȯzw{EnzExgl%n ⼜Lzf^~.m^b1u me/@XYk6y0?tdA]ePR[seZv 44φR>:z[^Q60$+!]#%]g: OkŅEM>JkA@?g3%K0GÀ[N5:g(ؒJ*l8 _\(ǎk~(.=23$<&7蔵4yՖxZ?(9B#3`KC Z6^P(LcK#n姇J|q/n䖂_体\Ȓ*e;j2CJ@kn#z!Ý@꫉mo ~ 4k+.8@sж-;ҔJ߻ui]4p bUr2I"p@e}<8켭*(c86£s@g̒f{}4Pv&`wL|[FA)S] !zRuX%֏pf?CDu7S8צ#8Аto,B=j sέ.W:Y:9HL6Ns a`4p2,oMy2Z>+%d9!Ío.SMZ8E-Y'a"Jޞ%C,<2M ROPw&)C#/ZʢɱGc'ѷVG!kY QrȞ^[!*X -olІ9ncЖx8DhmE16.d-u%[{;LОp`4>ؐxw$x/q؆ߜ|!8_c: f&4X;LJК=TSո:фψ|;vxf`ym`hR[$7<ឲ*ybWYq]01u|SwT =?Qy6, 'ϳFW5( 9T@/yX8@ UNB#>Ɂaɋ hL X>3"Ԟ4!g?* UM{WR5cHY쐹Q<ϸ {!LgL﮹}7exT*m&&yt 3W}VLPم=3*\{{ ",py>b:tc t@wl7Wz` 9Mv Q-5 1.M\SgÍ60e Mh"&FpH#8P3:6Li<6;d}0A3\W7*,4^4|aK,?3A!ZSYg,>"w S)y߈Bho3jwc7uG8B'ȰgʻMB[cgӡq.€0sl2Z=_WDtc L&|i!QL tY ,2&v *Z<04\[AqХx3fJHG(\:y#& [T,_бxފX?~@79TV^'4)I -e0t1 v[3G\Z=伃q. [jYc[tUJC@]`2 ]gahCz$Q"`0{}>pf iP. r+v{?r%xn) KyH L :ϡ3tFL|sý&DjoJH I; 'Oo혚)Iln5 oh%u&no'P*6'_`AK cW9\@nz&2}22یUC,R~ S(11>AgtHV)S'3]yu6`h ӽ~MI@gSXz*(5:SZsmaळͩ.m-u!+Bz.njy80w8x^w% ;v=ձwBC<+GZS5#RJJJGcոIԣ.>.uD00Se ˠ g[xqJSsY/OZ+V"=o?o9KD\ه)` ʇã/P X%>1VԗGqObou]"d]VE"vFk7_մV5j2RZ(GEgD~pp@4V{:[j waE " 1n ۲_^.Xv]|gtYp,Ί*r!m~"G"t~@J@q_N k\!;=r(ņnw_{mp#+75do\g2VQ!7C7{Ϫ(3]u0dPBF\}ȶFJBl(}3@6_՟_^`_| gOݶv!H Sy0[BT,FC09& Ѱz2__7aD sZڴ}޽7.4TFYO=\5Ki<bp)#LSK+V,Z`2SS^W~r?$#XXhFz(%SxނG<^.m M rw0W`A(fnYUsMLf s3CIrFkO?N,/%͈XegH r2B݄!P\BҪm~2@i-Mwi bB|||2 qnPba#W[\]C^̳.[(ˈ Wў o3{~<(ґ{(a>ϓ2kpSPOZ&zzz3.YEW95퓐#KUG:{sf22]v?fVw +Lſy" QP^iM%4 Sٽ+.{wn߲eӾ#g xM,x\ƹvr7n3KGϛbWSEAfzgdV6uAjS]n/J |t;w=xcRVI\h¶T%G}]Ooǁџy76L[+a;ݽPUS>G`1E9ɉ WcpSft4UMJOHSXV f򪲤o@"RC2P_WW։_Cu74 UП& <$_ i6?dpr/ZwK;@k1 0'@iz@t]z@t]z@tR4f𛹅IENDB`pasdoc/source/gui/icons/PasDoc.ico0000600000175000017500000020407612221630742017537 0ustar michalismichalis (( uuuggg___]]]```iiixxxuuufff___^^^bbbkkkxxx{{{FFF:::;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<===AAAGGGPPP^^^ppppppKKK111!!!###333LLLqqquuuNNN222!!!"""...???SSSvvvWWW ///GGGgggHHH"""   """GGG~~~OOO&&&///{{{RRR    888bbbqqq333&&&999EEEIIIDDD777$$$111nnn}}}<<<###...222000)))gggSSS +++KKKYYYYYYYYYYYYYYYXXXUUUPPPGGG:::+++ BBB|||ttt... '''QQQzzzwwwNNN%%% +++ooo666 :::]]]xxxpppYYY>>>===wwwSSSYYYfffEEE%%% 111ooo888 ///kkkiii--- 333???'''ZZZSSS###vvvrrr@@@ ,,,nnnPPP%%%iiiiii%%%KKKVVV(((fffSSS$$$|||NNN 111{{{{{{)))NNNOOO%%%uuu{{{***]]]SSS$$${{{LLL AAATTT'''yyy{{{(((OOOQQQ BBBSSS$$${{{::: ___777@@@BBB 444222 mmmSSS$$${{{lll!!!444yyy$$$VVVZZZ"""uuunnn999SSS$$${{{DDD aaafffhhhmmmcccYYYPPPSSS$$${{{iii @@@YYY!!!uuuzzz$$$VVVIII cccSSS$$${{{222(((~~~QQQ &&&}}}*** MMM@@@oooSSS$$${{{III eeeLLL (((,,, III;;;!!!uuuSSS$$${{{___ PPPLLL (((,,, III:::!!!uuuSSS$$${{{pppAAAPPP %%%}}}*** MMM===pppSSS$$${{{}}}&&&666YYY!!!uuu{{{$$$UUUDDDeeeSSS$$${{{---///eeehhhnnnbbbPPP TTTSSS$$${{{000***xxx$$$VVV\\\!!!tttaaa===SSS$$${{{222(((666???EEE 444zzz%%%%%%vvvSSS$$${{{000(((RRR&&&xxx~~~***OOO>>>LLLSSS$$${{{,,,***yyy'''MMMRRR%%%uuuaaa%%%lllSSS$$${{{|||&&&///NNN###ggglll'''LLL;;; 444zzzSSS$$${{{nnn888666 ---hhhlll000 444ppp(((555oooSSS$$${{{[[[DDDrrr--- $$$NNNvvvxxxPPP''' +++oooaaa### '''NNNsssqqq]]]jjjSSS$$${{{CCC VVVqqq333$$$777DDDHHHDDD888%%%111nnnccc+++ """333>>>BBB???777+++555SSS$$${{{+++mmmIII###  """GGG~~~xxxDDD!!!111SSS$$${{{YYY222rrrMMM333###"""222LLLpppqqqNNN555%%%(((666```SSS$$${{{222QQQxxxjjjaaa^^^aaaiiiwww{{{lllccc^^^^^^bbbiiisssSSS$$${{{NNN(((yyySSS$$${{{``` PPPSSS$$${{{bbb''' 666SSS$$$zzzTTT###)))oooSSSfff^^^777'''fffSSS;;;fffyyyzzzzzzyyywwwtttoooggg]]]OOO???+++000jjjSSS###$$$######!!!   EEE|||SSS ***EEEllljjj///!!!"""""""""""""""""""""""""""###$$$%%%)))...666AAAQQQfffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyzzz}}}~~~ccc```hhhdddFFF555...000;;;PPPqqqVVV777...222EEE{{{rrr\\\JJJ<<<333------111;;;MMMhhh@@@YYYvvv<<<  !!!BBBsssHHHVVVddd444   666bbb... IIIuuu///   '''WWW]]] >>>xxx444 &&&((("""LLL/// JJJ;;; ???VVV]]]UUUBBB)))<<>> )))UUU///(((\\\\\\AAA...!!!AAANNN!!! '''JJJxxx/// ,,,000111666===IIIYYYpppttteee[[[TTTOOOIII444BBBCCC///QQQxxx/// 333RRR|||www555BBBNNN555\\\///***UUUJJJ BBBuuu$$$###SSS///CCC^^^aaa\\\SSSEEE222 ???NNN BBBTTT\\\///888jjjCCC999LLL DDDCCC BBB/// HHHaaa+++ DDDCCC III???ZZZ/// JJJjjj)))aaa111SSSFFF XXX/// JJJZZZ999\\\eeeYYY ===/// JJJ666oookkk???OOOssseee+++---{{{)))QQQ/// JJJUUUUUUXXX!!!666KKK]]]jjjpppooo```DDD### SSSUUU:::XXXkkkrrrpppgggYYYGGG555DDD/// JJJkkkDDDppp***   BBBNNN$$$xxx/// JJJyyy###:::sssNNN555"""  +++RRRccc777 <<U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~mk IDATxgsJ769:̩{8$2Sgi%6T z~ߛB!.]O@!HB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB !P?_};P2B!~vv;v߽ĵVYokp !Rv 8 .| QXDwwwww$BqTfwلc^WM>/:{ Yb,ߛJ,`+vZjrV+l6:mLl^}8?Xc!Tf]VX,l>c\|>XбT[0f3}~ >^",ߌ pV friiZ$6l6b$IlXj *(t~ch42h4-hdf{<ؠH{P2t:db4܇#\y" zmZfiV+sbc_3YB]DX4,xl6L=XR6(p{O֯za V[jvB2$f3L&6^__m2X\.*yVp [p!,nv~ y{LְB\3ZȀbĒ$$IB>&b`pf74,vbj鄣Y׳Ncn7-DX!:aAQX,,M` d2lfI\M ]/Abf74b zb^V3.iB\ Ni1`PT|of)Ń9v +X°z!~4|n~ߖ˥Pjl[ c.41i6>2Q33O4Mb0< !<7!fc+FQpE7x˂e;{ %0"Edfi,Ӿoy0ʗd !D5܌"a5 +V0&e;\Ibfw4,!^n .k AvnVU  8cQNj|>"`Ę <5PH|܄nq#"d%I HArwfrM+z~b?ā3Y[ !8Gqy,XV4n!l Y>EIPj:Ja҅[~~Br3 vOwQ- |_/,_#iJڦi&^Z-[,lJ?A@ϸB Ąᅥ FwcxDȄ5R!!>#\Fa~n($}NapDh4XI`zv=s#c~!$g&&Hj۶Z`0 Ǹ{ 0OXr_?:!,\~МeK;*[~x-Xy nne[ r9>;:H/Duaz@ѹ 1bC#XtyU{~y]bOy0m=g>o|N%_](ٿ|NX\q}2!=Ws|hR?9za$~^b/cʋ^"w#/X)^}l8â t/ƼBtLؽ_k:&|n|>7XFpyMOLc->w[\88I_3W[~OIqn_9[0MLbEU^P.v9'7]޽sF5*O|(7"B6Zև,aC\1~A;XROYU o֏r5wڋ1/<~f.ȢZ3qhn :9-.1MwD/YmqM9f73w^[œnkv;*BĐWHQC^Y)c Ą7ʖ/,p ^~. W^y p s zTm[wk"׀w7c6,y8?9W<3 n3! pEBݞE|,^/M,ňY쭡E"$np  [׳pn q[rI繛yŢ$ItjIO >ٮlW$pNF t:ij ObIX>k^oaXt!^C<ͯ~$WhD=zx8BdgYXy1 .Chc y=_^ Dp<Æbe2'ka&IbĦөM&L&6=1,|n*5sχnho wcv oYm![!l^)bj;bŢ[2x$#[Ppcs0X  1g9f3zaS1m݆| |7+H|n& ،a3D C 19l2ņxX,lfˆcC $E7(8"FLd}K 0$Il:{X|q -_bx28 -Uo9a1[2I%;:6TZF&fk@|f } V26c&ވX(7af3lV q}wK|E e,Xnr9'Se x:ۛ[ .gz{!;w?>gmۖ$IpOr<`\s}•D3C`___k؀M&{{{ ~usg9MP\/:e&h O:fqf̷R-߼ZS| ;"pt:Oqcu|?lY&9/{4b2H+[y bypE^X,\'  Ḇ$I1"ϗHw=*5E' aT,[C.sEǞ ?k_Y $^K&%Gizy8]Fhʥ`v7Oqsi;{qg3S'x-CpYY<* [ō7f鲥19bÃm΢lfDx|>υofx]x S!Zxb!>Ar/gz>1 xqOX{S\.l~h1z@C\ƈYxY|c X~d[V&}n[ Z3t:@~1,`Qm2!V˒$ B:?$c>g6p0X¢bf8׆Xy3b{6%E K7)hɃ/x\`$:nEo>wA|aˋs =k۪Vk Y6?S d^UL);>$KYH:t~}ʐ{ s NlZVk57@f\ͰBp} M dO'{G^nk0#>$-sqK\#^gZZj >S-`vA= -6Cn?焞<5py@$3K`v/}|>\S,phl4p8 vEDŽ/O}"w?s>0p <I|E3V_+R{]tXܑ]paqXsIT`r^[^^ܭx8 , 0,( g@N& ~E" GOd<`05 ,MSt:Jm!k^B6 h zá=>>=??c`xM|B% IQP,sXʎEHDL|} [ |2>R Xx}97Ez3VėԼ2`Nh}tIh-n3uű:Rcg\>'?i!Ӯؽ^Ԡ0{xx'{~~g{xx v~~ۗ tfK1\Sc3 (B|bEvӱ#=gXp=d%>xb>'ㄚ``>X/X?p?%:ˮb7}M(, vXd2\zp>yjzS`iM{M{ ܪ1G{zzʈ0\ WK#"hd||&W!bb;ivX>$CbV$~s.cn-bל\^WLxcH>O%rdrW$ h򆩌IO|Xױsa'!F" 74]>,9;;O|&/p!b\ߧvrv( HVP6 +~-K9 nVD-xzLnv1/K*bM?%d<̦VV+=V0o2Y~F-沺c*^b47Y>V.+XĐs6.>zDm 0PK5b94vxMH‚ƃ q{cU}i~|XCNL9^oEbe!X1˼5𖱟Ns^,@Os9s3ǼSD.S[ 7%ʽdyo!j끻{\CŠOM9ٿͻz/xʆU\sȥ]yyΒp={e|u;%~<.E̮T"8\Upw+οq}>H|E#^?IXx=ax$ber"M{zV0O.Obͱd*_>ZC6@,Ϳ\_F^)Y6js_JTW".Ab.gߐO0r/xxY^,TlKB%͂vsn XEʹ1H(9'k&+'-q-W&33ϫT$⫑;bb[T.gD/桾K#ʖrn٥N s3opMӮX}>Dߑ`@g@-.@3p!s L_R 3}rz8uN1V\|U //\fQ?eE]Ǹo"WV~sSFknNcl|Yb %/~dJH~f[nN\.J" >Sb])ay"Z]X5mP$\m{07V{_|(&!f?xio,^ޅ{w37gGM(XNWY_I&ܨ>o>i"-»F`׷@< |UFBY Z|gnN}Lbvf6& &>qlibFOOO3'_K-X(Ƭ`}Cc-`Vwa~oTZ8y٘FL ߍ`,`^@*l6X,K޻9>Ǯ1DYtטt]ʺ!j0h4 ?и IDAT?˞2|(N'y!e .{^'oh.h|>XLbC(,0??!`?`v C q(./%\qy1l< M6j'hN/j1XY9/~zL VrٮkŦq;UYL6nBق_*06 rʼ7!vuLF(,_}xx/{~~gC".CL%%V$zkͲybq܄!~Xصvܭ(Oc} d,IC^l_`0Ȍd0[E=}"+zq߼p>|2pt:͸NatJŵrS$|>|pi~+;sl?Ȑvn3",! 0f`TKD.~ 1 &CKq_X^$\A|nf;#c냛R\#vV/NCSS=Ie~6:3E]ᱎZJUs3l m7xKԈr&t \0G ']cvF_ݤU﫿n8ZEH> r<ٟڋ/]VI^}<ljO3:` lCkQTr,Xf^/u gQݮ`enXց Uxf+jb8y>g<Jq$;[. Ux. mıE?/rܔ]0R4/]XCxH@L^_.z.'ZEٵe]~<~\^sy#ky69yh>06Ip^8q6lt:Q^\ܜŅؚ̯m$h/.pV/v椓P;GyʂVj̋Q$f)ᅟ ? f1,8$ 5ej6) Mp BggfOs^_M pK.Y>,Ht#nHv/&>_N,?'>K3X|SYyWvsXHXN ri:,yzo p {hwZf b 3h!"wh㳂0 b_cbHKݺh!mvƢcW3ڻb`gƚ2R2_}Hh$IbiV06T‹9\vV2%ܴf0qݶj>_n6Lؗ/ q*7/Ea)C%eΜ]}mw^ bO> ݋+HYƇ,`.kYƃğ$IBVY 8) %QM_]xػ1״_(M 0>\ ORBq^/.>l{][`γx9ܕ]cN-`c/ NjYyNX>\v;p˔Q.| Z =4v{iqS=ֻݮLOyl:p31׳tC O[ d,N=>v1 #9_/jFNl'>g; o gͦe7-}\Ysli v-nkId k4XV,b!ҥY@E,'X`犿[h]ysO!lr 愭XW[^ ln]%߇"c}9ef4yW4lO`3 k'0BS{{֍FmK4Lk!z0l6 p 6m5UaQM 0D%ndba|!'İ3ڽ%,Enj EaAFM`#D_b]߿~rhsGYys [#$z 0\D1^q_f22DMFnm/7`AX4b1 5[,>3w$&\F)(Mi6EbC>dfY+_ĤVe2yY~,%|pfZz!Z!Qņ{sBN'#¾TPְ܄ڏ {?hI!1KEHu㺱[湜^vN6L-@JAQl-_s7['yױͭoъ\ $-In8w,>Y9˄,ϸnB.<{+cx=f3jqEqX'[vCE ǡK\Мb+#Rf)Xj2xo sb/8Cy:ZOg\=-bxq;q,ķ_M0>؜ ݦƐύY1dL}wwH/$~‹=܇x;\[s=~zHsLOS rKη>Gt 4|q-B T,Xk bŋ`nB 88\uˊmoC/Xо-c!,x<1p9hs''+&l6 gq|$&2N{>[p`V*'!1Bc:Ŀj6f>1}9 `]s]Ì>p}!pA|^~}}^^^^__8KPŋ4k!GLyEY.KfnC;0⓲̲ms$Ih⋜$!Q*>SK\cqwZje3}J0A-HRD^^^ ],N^xgm)7)&y> ʈǹ<l`s<,<9֢S\n6K$:i KnVeػ}Zu,am~6`i8Gc zjLB`0MUp! _p|cٺfY@+BcU])!1wlEaB?>~L~wX wwp6h6:? \vL`D~Z_48$Cn5l4=>>mFyyΡf}XgC7M6d4,ႆ"[fa c!?3} 2{`E,Nˍ `r/! d~ p;#^^F2)=#B|wwg.nۙ)XN'ZȞfbL&n3z=ĈD.?\yX߅?dOOOz|{E_h.6+{vh4BLqV괹w3J hq,Ni8Y%fi,X"C,NˎP_X^',Q ΏlF,Y͙;1ߊ 1b6GV B֯C'E'!+sv4\E6įFbA,NlA>!4}yCzeOOO9DeExL~|}#f4;@F<%D:uEೀ'lV6.&`q<Ceۍ}y$ėg;s3KcZ?yV]a̙pr2Ot0A\"OBgv,~:dxOMxoѐdZ _!ŗS1!c(g$ [fK`ٖ)Qc }֔͸X 0"`W4v<;5~|/%?{V1F#@VAV}&`qlnM/,Ύx'\Cﰅ<_.3 4_۸_&)`>LiXa807HS >icy#"68+Bsk38D"><hWX qv9sɡ>,`9^ 3|Y+3}<#,"?Tƒ`-.'_-+"GwX\8=Y2`nV/[X !⋯tp1s+{}Xf3iՌY{t:жr^?ޜHHI`bS&i2p/|j};@8{.Z'wlBy2ւs60'o݌LjpǞZN0T=\+።<6n9eykaqŧ8dC+ ܩxDZD3vgбwZ_C<ǘ`1s? Y*%M,t"Z~"k6ttLR1k/=(H*(`}/pݺs\$Sݽ_Lx_q(󽤹a؟]b.g=??冇MFV; u=Zy/ PNO([_? 8xݗ]\`nZ1l6p, dxNg d>$k}]RYkB֯/4>v̥ur:3ŴIZcaNz5"qDŽσ|m<x Evٲ]Мݏ4IXI[^KsVt@ >yjA667Į[ߘVo 6 BVk0β` a7 _Ʉ><zAl!! Φ IDATF,NݮFömRX,l8Z6BD-в"\B[Ϋ=f>fuaEW/$I Ț,$I2kY k\Z!NKq, /ޟb,{/c&X xOo=Bۙ OOOnB %~d=m8fJe3;jppn!X,r{b‹Ŗ TI`X7d2&4>IL] ,KP<qeZ~e4g?B\$dUƉNsSCQ‚\.?$cVQ^,9q1A\V烚]|oلsQ,<2/ l6aE1b h}S_ e<1 ;y<2^x\z=l2q-?<&2@,> OBj:Lbx'2Mӣgr׿Ʀph.ul&8Ɇá=>>c`dBC([Vpz.c1mZ? Ú7AZқS5e Ğ?7^ns,vzkػ"Ch4 82^<$SpwFa.,1zθX1ov1"ׯ_62,^l*d-6!\ҲX, _#b5yjZ 1!Ox-g9cP\' +{Ce8kf$[?dOOO<%,>[^+]g^/v\ndV>Fw 2ab;2V$ aS$Ih.Od"adX,! G-gzd=^OEs㶝eރ9_e kK`cSeql$C%.&v/ =}p3'9_[ K|˕%,F#` Ƈ݋X`a#;nX7,Bzvf` <9C>w*ٟsc ;R"{OxgOȯ_>$]!*֛O w%q‹ułx܃5M%xC-;`Ab)t::B1`.-5Lm6%I;3/}~K~^z+1yP|2sސs! nׄ#_~eNb3k"S 8Gx4e>Ed,^5{2xpl>ž%t!By H,~Q%R}a<c^_Br{F[V7@EƲY' I6;nqY 2y,;k"x`4xxx4}ȋ=~չMVX9b3[}BQ d2d|- Jy˗{CqmM(0wO \[.``bhltx!IV /?GJϼ{|g߁Mȣ(,NNHOi@,%C/y0?nkId9V0u^ cw7gγ%E]Y#f'f.}l(iUz 4-`Nxc; _Cxc1ONyqg-`l3k#6 0ZkD~N`-fQV" 5cQff 'BQݵ|c,3[:~ Vol5foX`TcMޝ;?ۚѰ֏,zYpcˉX,§ 0o|b_yK|EY*˂k,vC Cez>P rp_cqMn]<`ޘ‹n~Qim[s>[ ?{ػVMy#u8?N'EsRw1>͜|e˸%q"Ovg|=zPk]R۟R?dPec,\ >0׸rk޴;7E8uZnieSv:U.`3DkK*7;1Wˍ}r9R3?gA 0+&!ϱa? & q 0[SeXË/1 (qfޔy ׻r׋OM& \eA{WKn8ok um9Y-ĥWqT"y. >8ׅ? E93܏>4f&nUYimΛX}oomf&Cv~|!>Xg-}v5D:vY?1$~oqsb{"/z-_E(~^}o|k& 9(1\(n bb[% -nj~%1_C^QYE~?P|o$ȳjge/[YJ&5 tC):GǼ_yxމX!uB!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!$B!DHB ! B!*@,BTX! BQ`!U?kf~[Ven~.x$pv;v>~ ZA񽻻H,Yx !~:@lۭv;nnp]O'ݟh~c{$Bzۭm6p^mلCE3~Ld !~ЮV+[VX,lZzjmD؋[Be3_mV _e8f!KB|p, [.^m^ "*֋-znq,&ޱ1YB,%$j|nf%IbibBl|V/ aF^>F}11fXq[H r <m:t:$I5 +Z).#E. .n kZ{wXI\b!wF\m6[.ixl&%IbIjjYV۹H}<. 1 n^l63nl?-[|".{,<^__3b6HE5|)b-[j2vZ-k2yB|W$x x^bt: " Kx>_ |5O!^!|˖+[Z+NnqY7M*0!v$:` ѝL&fU p,Dzj}-.ioZ`v]vtZ׳Nc21[9QK",H+ 8 ^.wt: k`&&b[* Y,ˢ#M vm.<~Xfa!@\ 9PuH.14MNc"$D*HHvIB\ aE|g}ea"8e\rs?+i "/KO\f~n$Bk@\آh,\\WC ^x_?[CqIX2pVLXq H+$~c= 9/8e7&Єz[,^1{b 1 {xJU#X|;N.kr;{4 0[]^˰ c>ދn`a?YVX", pxs߷hz~P(%O3 0 /[\ !ĸ2ƘG\C5"7_+?0\a!DUH+oz C{xxhd00ˈ/n,` QbJn>n1.?_ tu: 5BT`Cݮ {xxG{xxp`U~ gLYpº\.m>AE2g7s)#5o^y֙f3.U vA#M<<<ӓ=<`RC7Q 6 09 K: P/GdKX,>0QO7!.S03Vc,b/:biF\fYLl>Y~/k6 <v߇ NZ", 1 —,~^gK# b0 #!zvuLrnbaf,uvoni RHO ʋ#{5pI0>d2 Ͻ^vp7 NihQ&. x?yS2-+\HAXEn nfi* U kO$ZNJR|z?h4ID, b|o6f уX,hXe`K3q \|B\ 8__˙|V/g!1y11a%Igղ`JHNM! 4,Vf ! \vlq(cExX'v57ڄ⫑/#fscه2 ml27)/KK$qF5aK\Vpy||0kD,/\=/t<:]ѭV+d`%l63M:n~*j}#X[uQvBMEᯕ^/`q6|ƴYwB}cjh֞nCaZF&-Q:C\=nLduPȣF, /Ll~],/AǸ!< "8e<WO :a'h!faX Q`A_ˡՇ¿ϏZ}ϫob<.y Iى0kq]V+[,GczS$a~?KGX.Z"u ޿єEG"ϵ[=>/9$ET8 s/(s}ೇs*Ds8)/2&f_~g׎߬1/!R^`cr ۱i,`?vm^[Ѱv{3nm`^ /~ۻyad˝5~b]o< rr^r:lhјG{Lp{Is#'4퐹#fǶ\Vu`B5j^9\$>GKbY#t`,,jhoʍVӟLW/|}xyetXR%s'1+afVeZVhR6 8^qc;M0_d2|Il6!! _",& ]-Xv*〃x>G\^`cXLUv z /g#^a\~5|^ ,~ _ Zk_#w5_Qm{uo[k>7`Q)ac2!&IfiXxl. =[{8l^ԼU&.k/,xa乡}|/^t(cˋ(t(o6Pۍx2?npR@$߇ \o]+ ! / u΍XTB%qf+N{\d2XbX莅gāiaqGBwpC&l6xݍ1%\zEi`en+CopGT4M?lT$ Yq-`6xc{L b9ph0\_0z.$Rx,,b1SeCn7)Kh>u^gs9_#X,D|]xifŁ'乞fAEB]xQixH<6 3zm8c5,zm\>)_lxGjuVE ʮ%E,vIv0`0fv4=jᄫ-@:Hˆڸ t0|s.M<mK1yv: A Q[,v=o9I+&>-^_6g~?;-F9`YQcal†ahg 97`Q9yV0m 6t: cbH,Nk$&]&I^ϋ.9ng_O=?X>fb|&4nNas-I:Nݶ~D[ᢍ7d!<,_ϸNy+=?YqZ^_nG5瞗hX,µX9% l6pOKn\ƌ?Vpkc:F{IRX{>VYΈ/c1lym>|2^^^ [W.{D\c˖0A^4! Y"!aC'% -z-2ƌ_ߘe ~z^%d}_+ a b$"yx!e"?Yblb.Ebfk,OXp)>Lp(6y 6fҡص`ۙeyNJۇavW4Kŵ߿3^-y o|k6p̥C_:}Y—:`qXەw`!]v1K8FCKQdᠳhs3JJӹ{~yQe Hc`n+iZdlY)# |c_k?}1L&?-p~lbc#9̯ʉ>iġ1i0dD +X,?@āClWrN",/`/[2q0zL/]p,ǯ g5&W夯5{v]a~`]tXB^ d2^_ Tێ&_OyfXzf3v{?p8~-l$BG74'u>-Ǘ#ŲgY. /bqUfnQ$IH$ɰ8alh4ܲc{˳c1=,TEd<xg_88۹ZaW36h \'~[*[쓯|&\$p%ίX\5,±,>RXL?U5 /}xxN` /#$}$ׁ sRC,.EKXa.e/as.Xi 1-B>>>fʉXh܉y8f8O}NVfcf#Y^xSl./"vm"_\E׆z~6m4[`?e3{f*07Ϧϊqa<1ΈyoA{80oQKKb !  ٞ9#pMȉ4y<~]>X0/'ﰧV+3cwbnwǥ4>IJ+o^|?V|l ӓ===ke4| pu|r' <ε}~%nC=LJ`:C_tLygȳp%88c1~5}||gWfaY4_dFl6kZP~n|+.;da̡/3f^,/l+dŸ /`0lxėˏ8Qҋ؋o58̛/;H.h/Q啇QfwZ,1WnH|E ^/ CfQ%\bBŖnzb/]}>/l}l6Xd}[5171;f7} _ٞ%H>D66|Ǭb߀Ň8=g޳rn$q`Sx~/)abe-*\ ł w4eTg,^1 E&C`nXrn6Ktlsi`n=zL3ׄ#k\+ZַNw+Oc]6J` w8 /=yE3E_9C^PB:Mm*aXF#cBb,a`uryTsV 4K?d<%S ˹ 1l?yz/y>%[޵DVe1p^LOb*rEcx8{jX5^B`|bls&]EnxQCxǖodqkR}.G )Vpὤ#̷edK ,CE,S?%.tvk`w=gg[9<].'! A36#$^pߖsVHŷ p"%&dEV&ė)G\Wnsg` Hz>cUov_5/@$4F`O ^^ݐo!>%9ҽT'EZsպXE*7q fk-a_FRP{ˣ.eۻ֭4nނ hIO1"IFuToݬfB8Nlp8;;+BL`hQ 19D| gsJQϐ!75sAD<&a.KCiLS/1eZ^pf?1j4Hm xypk7jzL&`c2r,4{M ,ػV<H[>Š8쌧i Iqq}s"7Kу g6MǭJm%9sk8[aK64 OC2&:T[(G#GuJ & ,{-9NU2+HG8tm0Fxt|ƨ=`cR<*/)|Q_qѮ3ˉ- `4q.y]I|MGԑAU 5K ؘ"Yõ5,2ak&S76,7ث;/6SntwԍOb 8p9ۖDq R7MlL UD{teͅzx?MKLr75D`6 >( XɷMQJ卧JQb*`6&6!߶rDu&4˞9#ƻR*=/M٨FMG3W[%H)u{ `ްD! {lLU1-PShs^W>ܪ68.yDbfm3s\)QMYTGo1zD,Y5~eM*ˎ9H"'EEjϕV[FJ0E. c&`c2ЬT=Vd%ΘL.rdv5m<:Rιk!޶(%*RǬ{&JĹ2ݩ1^d5)}O$9ֻ_KUQL{LJm1#J U,x߳1`-\3#:%&߫6т {L&Cc+1 z&`c`ˎ@~ݖ:B.smr=ޛIu[EI{[#c -@x<==KpX%f]|Ҧ":S~WߩI2ЏBUd0 _NBwۥnW"6@L%e7WUձ15pxȑ ^{u-goD]jN1)"\m窯!ϥO 7bUDUSul | wݦvאveh.C M<nU{3JMM3zXA:x뤧hGݨ)lq/<_&a| iߒX,EA̜=>&˸o0)ݥB J)td"~/kdL0}mALOOO' JFQ]"32m2trD<8_$;7S (ܮc)=aU}jהxM rϟ?K >H)>|PyZȲQe# Bh p0C x7U^~tm$hTvOj:5{Ny&`cT`Eɗc,CPafYA"-˂!KCz7zжG丞y6x#[6Y+ SWΐo ($nz.sS^c 8ƀ㾐7MGl6>==JҾt_ &{,GWI԰*O3G4 7Dt]hy)m$ kɎ敻qX`6F ow٤fS ڔ9Fk&ʀf[bIff/*7%êekԦPW~^pM:&m^sFmL0Ag~!5?<<?~)Ίr,HwZp_3ql,1k &*bbpJ|5M&9uCt ȗm}Appܵo"Xjlr\ 1n.C3J>W\&@_Ox_! =X8Ws2`691_< y7n= b;??/jU<@\4zJpc|Mk˄˲b40 K.i/\J[^p׵D_t1$@61SY'c  QIW _9Mw6/djuA"tC_$,6,c}TYwWU/CGU6, 93Lps 1B>S\'c ٹ~A>} _U`824z>]CN갈 B8<"&0g84W4+dA%#W4BSxQpp+r18&!Ll ZnWܔ$^&`qOW 6łƁ*ű{7|#MeS,|uG;Jf6ƴ ^ZZ> LFoВ/nr k~~~~nL/{Qq_$ [4(0lޘ\bjtnx;C} HM4'Q$ki/mhaG"jr!n۷t{{~~lH,IDAT/ަ"nK:]__?Zr,e?BouDƕ*)fׯi@/6q\7lӴEqR脕ҟyCJF8 ظ{.pÇeΠ7z+\j.ݥo߾k f>c^37/ H߆a/?k=)=`=6Vv96 Fx"` jǶ^ {݈w߿/<`<@ĸmzzzj%G tuuj* v 0\ O-ym8Tf0Q )X[?==U/{7,3\. /ׯ_% zH28{=_3M=Y^8Qehm.Me&-f)bHWWW 7qLy7#"ޔ39Uwww~9syvvV/2" Ft0Xc 6 d&yהRqm0|N/Ԕ(ih5 ]@دקj 9xm(VlcFb[/ו^轣I8q4rfpf}V|}Vׯ_ߋ#xu$]V%夫@^*?MĜpFn{W]zg5w߇&%^3/._[$Y`bRtNl6Kͦ$ǯV6DoIwy&`5/R=hCM߿/2!CW0M{ss>}~97]zDK^EThqhz%Y湖/ȗ뙵kTΘGlUitY'IרRH@dU 7!?>>4#,M<1pNB_i6ՆܑH=E1j~AMr O&ܔ<`V ]3{9k^ӡ  Ǐ2+JMץA͑/aەup8Ј6M5k^/(tk=quDb(MRR!H8[8>Vq*J%h:2iqs3<xxa@Y:l2  ⽹)a|bQpR <3r|"  1fsP*{*)PBv$>^?LM BAaՁC1 k7 F$us\o}|qqݴx}}Mϕܺ@Q`'A7eL7|n] )?IV,9sC ooo cR~oEŢS!=j8BĜl301 ƧE!/Ek+x8΀nhIe!lX"===6Yan: v-6ȳf5~]Jɝj[<#ؘ@Xj~:1D;x̃9Īr!w:j} nzx0~)}EM.$=3?%^/K\ O1'5v]8Mx_^^E.`OaT#R|f[ ?וakU0/gM)jZ~OT5@?v-lv;mX,PrY8& iIN|A{},L@,M^ETↆr+Le~xx(DrU'F3'\}]ׅ:ԸжLZFQl[x|mx=`ȞRjfP#css^ܴȜgn-?Eָk:r/Kr=Lg\lV܇);}ϒz^4{rѺdڅ)'Vz>?C0 ,>1 %yPr3oL&b&dgLvKS|<%߱1d_~sqQ&C!HJ`d#2 "VFJZ7{8v\ ċG.[O8Nfa:~ uh@Sj{.?~/H f~бPtID87=*Ij!ñj f>.u`9N4 gS 9|9 ;)i*,=<<7CaP 㽟?.^ܤb8|&=3T>??O///惯<Ϩ, =+̈υ!ERX#z9 8{-ܑIgԍ#ң:7r _zACg?9@cdX>.ɫq-}sUT45 vmc)7nxo20F4)^+ɩsYXC &3m؝&#C])u)~ qnoNjC|yfg(_qP[U ,f?, ۇ 62D%V s2Zu3ɇ5>l 3la֌CIaeb=R [6oؓn pK } 2fk9Մ7*x]^^ ߔLcXdNՑ0n6>癦HZLxs&.Wb@sЄKLAZ]UO Mp>T?&0МLˠ"#V[b>}*ՌsV#&MIX-S* MFڔ Fy mqrIXf"ih iM88ܚ<_<0Ί#noB;`#0j./RtbHc5ǂ=BV (q=??/˜e%4 i. Zߓ ){ ljeu NTCM6x<%aZ7l{7(M HQj>HU7 ba*_T;^U`V fݔֵ3de}uUAY1{,/s?^$HAlr8&R(P$׋ ,r,3VZEQZ rBz]l{"Wdj2nXDJ ~%ɘIL)l|q1hǶhE&`MPy70v0r3{< jx(} HR*٠"^˱8yđAU#qgaȕUnM/Xp_Nq-i///3Wb's~~^-lXEs86tHSSsě2ܳ(vE MS"7~]M5&'].Edd]l@y8S%Hc+7<2gtHX<&`\ead/..c)D N0 ߇Bݭsh{sPgM@ױ|^xo[ qJ煍rX]cwp$DPoHBx%L,qq+hR4߰,%lo@uI/V~D! lҸ"&fa^v"Oc7E9XnϓdPOˆ@U-"ucFV3y]sdf-S} pnZ9->>>j{Ȣdz斒PD 7gl87qc51MCvCgYarsW(Hv$$h-o[ۈpT+Ţne3d{A%GcLl񚍩Q\3yHD{zs{MD@mX!!D̟ 6iv7^7d z`N _!/ҍ.-~6j0#YZ?)YDj4ƅUڍ<6JݮDLL*Gk=oe1lx`o2#OspSUo]_X+LzZr,~ݺ>x0oң܎9j  gYp`8[r J$ 4_[ʩ$ϻņEdX31<@lUl4PC X7~8q& k%oa(0.R: =(_I7c"D{3Bҟzl99,*N`( l `~1n7F<:ױkJtuw7#c%b)׼UZ6$SgՒ#5j\st42GcI!ևU>xSkJU4ǣs4h(AGUpi0_dsشk݈L;ߐw d']@|`yexGr4σ5<1fKޢ&ySzb-C.:݅DKQ L k{+gmtfUfkn>ۥ3,x8Yod_1$X0hEr*.7><͒te@6jRI]C׬|+*(%m}K[^~VuQڅv< aAɜYY"A+1lӑt%yN:@!mp)m#W``@DŽa̾8!ّ;6Pd}rdtd4#c;4rd=@?hiMCDbJlb l{+r2N]~6q_]Q`pcF#ScY::z, z?l%=z)O3zxFB`*)>%ŽsxhKlP4;PlGq.[Buk UPcaC(: ^Mbe%6[6b4 {dszYmAJ%{t{5&Z0{L\#V[EyĬ nX۵eq%͡^ck&uSW!p'TSG-/' $٠I_s!SM/ue%nٷ I~/^=6t' lK Uk?w(F*B:0-4Mb<h3CdGߠw93&^^^NVZa1Lqyc&ƦAŀǸ-Pya2\uwkS %FL @\bQ4IENDB`pasdoc/source/gui/icons/PasDoc128.png0000600000175000017500000001011312221630742017767 0ustar michalismichalisPNG  IHDRU>sRGB!tEXtSoftwareGraphicConverter (Intel)wIDATxy\[wjJZhhG+Jl6Kp<ĥ$˚K$K7D$Yh%njZgi֞SLSfw__?zΜ~|sh?rY-a2[9<7h+5A"7nM}񦢑+@o.pٺg۾:8MDZ[|) %a60(jYxGf~3}(ұqu4B_Bt{89u畓P z?3%Գ%ZZy~ɕj`l|K6u> ٕ7~4A\izVJ4j~evt 8 :͗>mLVo ;cdԄQQWSj>rR"~S[1'#zCk2 ήL~dr;^r^sp!b$^7oqg[;>SpNQb Kl7%pX N}=F`^>H`pgx ];Γ#8`]54@븆*[1S Ӑ/h9[bgܚ@Wc,ߵ7BWݑ7_50`Snao_W p?sӑ33YeEh]Nm}N'I#ߪ";r59U_#m6[&le1j#{B!8 KnH]QQ=Ka~; NhvĈJ X]"P)G `ƥZ.YWfMb~WF݈@mz雚ӓp@g]VjN[N9nOFܟ5]w'”ojM&RwOє%~;ՎJy(_/2Fw/愹Z=7]J'0@[ 2b Y$Yf%;Np_dxӹԫ0AM='Z|VMQ֓{7.;z?AV_{V>kQg. Ϯ핖s6Z<{{=LOvNn @[1ωaw8x/z l̽xd0&K;D9eeGќOZL0}>@{$jg61˦ϊM klƑ-_v*6>6d,7@SnZhzT&WzJˣ#6<+54W&}1Ye<њ|AIAQ527:GN*.t3ة?u x^[ֽ>CEأ}Pi:P#qV5MмJ|w%휧a.*"Ơav(뺋P#I0|0'?3@tQ'ۿ*i 6NiKAMA]452^P׷Nҁwj#7G]ɀr߻"%ZSzeԝs; ҆7Y0D>_K*xAOCB'RrRCX3e>͊6?ۈ դ:زs֥N2%2g*5m(ρc>tҶ$$|4n2 u$D0sӡ.,n54j qML], ]Yn7D[ U7_~*Wp(RC/kGjoc;3SuQnۻ4*3FZ7~Rj]QN•+l)|pHؾk+XB8)GF?.6FqFC5<ʣ&%3C)xO` Zk+K>4DֆҢ~~~~~@G++_H,?G*o *j8_B@ ;gip)uXL,GڻxyqrYΗ0o΅ hpS/_B5bjl?GA !nIO1?44t[HP%. d5}uՍg^ꨇocObmy' 8-fxH0|}RO}/-bWXB(u~h=.9Y=~ݻktN}IԔg% ŽCO_T0>Mvn^;^We_ 9UqW/[lMUrUǡՈu}ig|I @{S"]0ZG}ٍGh7x6JOz؛jFC,JCUe h91݄AaD@gKPVv}"mLe !@'Q}ǸM@o#3"?s#ss4:LvEwGu'D 29)Ka4"{ƋHsIfQvIѯ(63N[5z!ljg>%=p%/ᣱ5l{YS<; zOH)vц Jk@t>Ag~m6TY_ p ΀{]$OWe8hsY 祯,3"+i!F"xg0֙n]- I{{pDmH&ppW*p8`FqO>KiF?;(EE`*4O_ T@6j..NJKfw[X}"TG0jzp[ t.>Mq8gЀ8*4[(K /zhس%Cbܬ2^- @qqj!ǷZ̐YtqcDwέN\mY%DD~تkE%̪wE)  KQ{ nil then begin IniFile.WriteString('Main', 'WWWHelpServer', WWWHelpServer); IniFile.UpdateFile; FreeAndNil(IniFile); end; end. pasdoc/source/gui/README0000600000175000017500000000452012170541222015424 0ustar michalismichalisThis is converted to Lazarus version of VCL/CLX program HelpGenerator by Richard B. Winston. I (Michalis) converted it to Lazarus (LCL). This is a portable code, it should compile and work everywhere where FPC, FCL, LCL are ported. It depends on pasdoc_package for Lazarus in pasdoc sources, so be sure to install pasdoc_package in Lazarus before opening pasdoc_gui project. I'm also putting this source code under GNU GPL (original version was on public domain). This should effectively solve any legal concerns with HelpGenerator that I mentioned on pasdoc-main list: now we have - GNU GPLed program that uses - GNU GPLed pasdoc and - LCL (released on modified GNU LGPL). So everything if free, legal, binaries of this program may be distributed without problems etc. Of course solving the legal concerns was not the main goal, the main goals are: - demonstrate using pasdoc components in Lazarus - provide alternative way to use pasdoc for people that don't want to learn pasdoc's command-line and don't need to call pasdoc in "batch" mode. This was also intention of original HelpGenerator, but now we got it absolutely free, without any dependency on Delphi/Kylix, and portable everywhere where FPC is. TODO: Although it should be easy to modify this program to let it be called in batch mode. This would allow users to create their configuration using GUI, then call this program (or some other) giving name of the file with settings as parameter. This would allow users to still use pasdoc functionality in batch mode, and at the same time not learn pasdoc's command-line. See HISTORY file for changes that I did while converting HelpGenerator to FPC/Lazarus pasdoc_gui. Development things: - In case of uncertainties, we should try to conform to GNOME HIG 2.0 standards. This is (at least for now) not to be taken *too* strictly, so don't worry if you don't know GNOME HIG. - pasdoc_gui.lpi XML file contains many important project settings, but also many settings that you can easily modify "by accident". (actually, this is the same problem as with Delphi/Kylix config files) We just have to live with it. So: when committing don't worry if you accidentaly modified something in pasdoc_gui.lpi file, but try to not commit anything really "breaking" there, that could make difficult for other developers to open a project. pasdoc/source/gui/frmhelpgeneratorunit.lfm0000600000175000017500000015374312170540073021527 0ustar michalismichalisobject frmHelpGenerator: TfrmHelpGenerator Left = 471 Height = 566 Top = 142 Width = 777 HelpType = htKeyword HelpKeyword = 'PasDocGui' HorzScrollBar.Page = 739 VertScrollBar.Page = 415 ActiveControl = PanelLeft AutoSize = True Caption = 'pasdoc gui' ClientHeight = 533 ClientWidth = 777 Font.Height = -16 Font.Name = 'MS Sans Serif' KeyPreview = True Menu = MainMenu1 OnClose = FormClose OnCreate = FormCreate OnDestroy = FormDestroy OnKeyDown = FormKeyDown Position = poScreenCenter ShowHint = True LCLVersion = '1.0.10.0' object NotebookMain: TNotebook Left = 208 Height = 533 Top = 0 Width = 569 PageIndex = 0 Align = alClient TabOrder = 0 TabStop = True object pageOptions: TPage Hint = 'Options' object LabelTitle: TLabel Left = 8 Height = 20 Top = 8 Width = 31 HelpType = htKeyword Caption = 'Title' FocusControl = edTitle ParentColor = False end object LabelOutputType: TLabel AnchorSideTop.Control = edTitle AnchorSideTop.Side = asrBottom Left = 8 Height = 20 Top = 57 Width = 96 HelpType = htKeyword Caption = 'Output Type' FocusControl = comboGenerateFormat ParentColor = False end object LabelProjectName: TLabel AnchorSideTop.Control = EditOutputDirectory AnchorSideTop.Side = asrBottom Left = 8 Height = 20 Top = 165 Width = 387 HelpType = htKeyword Caption = 'Output filename (without directory; not for HTML)' FocusControl = edProjectName ParentColor = False end object LabelLanguages: TLabel AnchorSideTop.Control = edProjectName AnchorSideTop.Side = asrBottom Left = 8 Height = 20 Top = 214 Width = 77 HelpType = htKeyword Caption = 'Language' FocusControl = comboLanguages ParentColor = False end object LabelOutputDirectory: TLabel AnchorSideTop.Control = comboGenerateFormat AnchorSideTop.Side = asrBottom Left = 8 Height = 20 Top = 116 Width = 131 HelpType = htKeyword Caption = 'Output directory' ParentColor = False end object CheckAutoAbstract: TCheckBox AnchorSideTop.Control = CheckUseTipueSearch AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Hint = 'If this is checked, the 1st sentence of each description'#10'will be treated as the abstract of that description'#10'(unless you override it by using the @abstract tag).' Top = 331 Width = 665 HelpType = htKeyword HelpKeyword = 'AutoAbstractOption' Caption = 'Automatically deduce @abstract description from the 1st sentence of description' OnChange = SomethingChanged TabOrder = 0 end object CheckUseTipueSearch: TCheckBox AnchorSideTop.Control = CheckWriteUsesList AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Hint = 'Check this to get working "Search" button in your HTML documentation.' Top = 302 Width = 336 HelpType = htKeyword HelpKeyword = 'UseTipueSearchOption' Caption = 'Use tipue search engine in HTML output' OnChange = SomethingChanged TabOrder = 1 end object edTitle: TEdit AnchorSideTop.Control = LabelTitle AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Hint = 'Title for your documentation. In HTML output, this appears in the web browser caption.' Top = 28 Width = 274 HelpType = htKeyword HelpKeyword = 'DocumentationTitle' OnChange = SomethingChanged TabOrder = 2 end object comboGenerateFormat: TComboBox AnchorSideTop.Control = LabelOutputType AnchorSideTop.Side = asrBottom Left = 8 Height = 39 Top = 77 Width = 254 HelpType = htKeyword ItemHeight = 0 Items.Strings = ( 'HTML' 'HTML Help Workshop' 'LaTeX' 'LaTeX for latex2rtf' ) OnChange = comboGenerateFormatChange Style = csDropDownList TabOrder = 3 end object edProjectName: TEdit AnchorSideTop.Control = LabelProjectName AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Hint = 'The project name is used to specify the main part of '#10'the output file name for HtmlHelp or LaTeX output.' Top = 185 Width = 274 HelpType = htKeyword HelpKeyword = 'NameOption' OnChange = SomethingChanged TabOrder = 4 end object comboLanguages: TComboBox AnchorSideTop.Control = LabelLanguages AnchorSideTop.Side = asrBottom Left = 8 Height = 39 Top = 234 Width = 258 HelpType = htKeyword HelpKeyword = 'OutputLanguage' Anchors = [akTop, akLeft, akRight] ItemHeight = 0 OnChange = comboLanguagesChange Style = csDropDownList TabOrder = 5 end object CheckAutoLink: TCheckBox AnchorSideTop.Control = CheckAutoAbstract AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Top = 360 Width = 580 HelpType = htKeyword HelpKeyword = 'AutoLinkOption' Caption = 'Automatically turn identifiers into links, without the need for @link tag' OnChange = SomethingChanged TabOrder = 7 end object CheckHandleMacros: TCheckBox AnchorSideTop.Control = CheckAutoLink AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Top = 389 Width = 369 HelpType = htKeyword HelpKeyword = 'NoMacroOption' Caption = 'Recognize FPC macros syntax when parsing' Checked = True OnChange = SomethingChanged State = cbChecked TabOrder = 6 end object CheckStoreRelativePaths: TCheckBox AnchorSideTop.Control = CheckHandleMacros AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Top = 418 Width = 327 HelpType = htKeyword HelpKeyword = 'PasDocGui/StoreRelativePaths' Caption = 'Store only relative paths in project file' Checked = True OnChange = SomethingChanged State = cbChecked TabOrder = 8 end object CheckWriteUsesList: TCheckBox AnchorSideTop.Control = comboLanguages AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Top = 273 Width = 182 HelpType = htKeyword HelpKeyword = 'WriteUsesList' Caption = 'Show units uses list' OnChange = SomethingChanged TabOrder = 9 end object EditOutputDirectory: TDirectoryEdit AnchorSideTop.Control = LabelOutputDirectory AnchorSideTop.Side = asrBottom Left = 8 Height = 29 Top = 136 Width = 483 HelpType = htKeyword HelpKeyword = 'OutputOption' DialogTitle = 'Select output directory' ShowHidden = False ButtonWidth = 23 NumGlyphs = 1 MaxLength = 0 TabOrder = 10 OnChange = SomethingChanged end end object pageSourceFiles: TPage Hint = 'Source Files' object Label8: TLabel Left = 8 Height = 160 Top = 8 Width = 547 HelpType = htKeyword Align = alCustom Anchors = [akTop, akLeft, akRight] Caption = 'Add the filenames of source files you wish to include in your project. The directories for each file will be automatically added to the "Include" directories if you use the "Browse" button to add the source files.' FocusControl = memoFiles ParentColor = False WordWrap = True end object memoFiles: TMemo AnchorSideTop.Control = btnBrowseSourceFiles AnchorSideTop.Side = asrBottom Left = 8 Height = 257 Top = 225 Width = 547 HelpType = htKeyword Anchors = [akTop, akLeft, akRight, akBottom] BorderSpacing.Around = 10 OnChange = SomethingChanged ScrollBars = ssBoth TabOrder = 0 WordWrap = False end object btnBrowseSourceFiles: TButton AnchorSideTop.Control = Label8 AnchorSideTop.Side = asrBottom Left = 8 Height = 47 Top = 168 Width = 547 Align = alCustom Anchors = [akTop, akLeft, akRight] AutoSize = True BorderSpacing.InnerBorder = 4 Caption = 'Browse' OnClick = btnBrowseSourceFilesClick TabOrder = 1 end end object pageIncludeDirectories: TPage Hint = 'Include Directories' object PanelIncludeDirectoriesTop: TPanel Left = 0 Height = 151 Top = 0 Width = 563 Align = alTop AutoSize = True BevelOuter = bvNone BorderWidth = 10 ClientHeight = 151 ClientWidth = 563 FullRepaint = False TabOrder = 1 object Label9: TLabel Left = 10 Height = 94 Top = 10 Width = 543 HelpType = htKeyword Align = alTop Caption = 'The directories where PasDoc can find include files.'#10'(If you use $I, $INCLUDE compiler directives.)' FocusControl = memoIncludeDirectories ParentColor = False WordWrap = True end object btnBrowseIncludeDirectory: TButton Left = 10 Height = 47 Top = 104 Width = 543 Align = alTop AutoSize = True BorderSpacing.InnerBorder = 4 Caption = 'Browse' OnClick = btnBrowseIncludeDirectoryClick TabOrder = 0 end end object memoIncludeDirectories: TMemo Left = 10 Height = 321 Top = 161 Width = 543 HelpType = htKeyword HelpKeyword = 'IncludeInSearchPath' Align = alClient BorderSpacing.Around = 10 OnChange = SomethingChanged ScrollBars = ssBoth TabOrder = 0 WordWrap = False end end object pageDefines: TPage Hint = 'Defines' object Label12: TLabel Left = 10 Height = 325 Top = 10 Width = 543 Align = alTop BorderSpacing.Around = 10 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.'#10#10'Note that your compiler may define some symbols by default (for example, "FPC" by FreePascal, "VER150" by Delphi 7, target OS and architecture like "UNIX", "MSWINDOWS" etc.) --- you may want to define some of these for pasdoc too.' FocusControl = memoDefines ParentColor = False WordWrap = True end object memoDefines: TMemo Left = 10 Height = 137 Top = 345 Width = 543 HelpType = htKeyword HelpKeyword = 'ConditionalDefines' Align = alClient BorderSpacing.Around = 10 OnChange = SomethingChanged ScrollBars = ssBoth TabOrder = 0 WordWrap = False end end object PageVisibleMembers: TPage Hint = 'Visible members' ChildSizing.LeftRightSpacing = 10 ChildSizing.TopBottomSpacing = 10 ChildSizing.VerticalSpacing = 10 object LabelVisibleMembers: TLabel Left = 10 Height = 94 Top = 10 Width = 543 HelpType = htKeyword Align = alTop Caption = 'Structures (classes etc.) members (properties, methods, events, fields) to show in documentation :' FocusControl = CheckListVisibleMembers ParentColor = False WordWrap = True end object CheckListVisibleMembers: TCheckListBox Left = 10 Height = 130 Top = 114 Width = 543 HelpType = htKeyword HelpKeyword = 'IncludeByVisibility' Align = alTop Items.Strings = ( 'Published' 'Public' 'Protected' 'Private' 'Automated' 'Implicit' ) ItemHeight = 19 OnClick = CheckListVisibleMembersClick TabOrder = 0 Data = { 06000000000000000000 } end object RadioImplicitVisibility: TRadioGroup Left = 10 Height = 134 Top = 254 Width = 543 HelpType = htKeyword HelpKeyword = 'ImplicitVisibilityOption' Align = alTop AutoFill = True AutoSize = True Caption = 'Default visibility of members' ChildSizing.LeftRightSpacing = 6 ChildSizing.TopBottomSpacing = 6 ChildSizing.EnlargeHorizontal = crsHomogenousChildResize ChildSizing.EnlargeVertical = crsHomogenousChildResize ChildSizing.ShrinkHorizontal = crsScaleChilds ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 ClientHeight = 107 ClientWidth = 539 ItemIndex = 0 Items.Strings = ( '"Public", unless the class is declared within {$M+} state, then it''s "published"' 'Always "published"' 'Always "implicit"' ) OnClick = SomethingChanged TabOrder = 1 end end object pageCustomFiles: TPage Hint = 'Custom Files' ChildSizing.LeftRightSpacing = 10 ChildSizing.TopBottomSpacing = 10 ChildSizing.HorizontalSpacing = 10 ChildSizing.ControlsPerLine = 1 object LabelConclusionFile: TLabel AnchorSideTop.Control = EditIntroductionFileName AnchorSideTop.Side = asrBottom Left = 8 Height = 28 Top = 138 Width = 158 HelpType = htKeyword Caption = 'Conclusion file' FocusControl = EditConclusionFileName ParentColor = False end object LabelIntroductionFile: TLabel AnchorSideTop.Control = EditCssFileName AnchorSideTop.Side = asrBottom Left = 8 Height = 28 Top = 73 Width = 173 HelpType = htKeyword Caption = 'Introduction file' FocusControl = EditIntroductionFileName ParentColor = False end object LabelCssFileName: TLabel AnchorSideTop.Side = asrBottom Left = 8 Height = 28 Hint = 'Custom CSS file. Leave empty to use default pasdoc.css.' Top = 8 Width = 377 HelpType = htKeyword Caption = 'Custom CSS file (for HTML output)' FocusControl = EditCssFileName ParentColor = False end object EditConclusionFileName: TFileNameEdit AnchorSideTop.Control = LabelConclusionFile AnchorSideTop.Side = asrBottom Left = 8 Height = 37 Hint = 'Optional file used as a conclusion to your project.' Top = 166 Width = 426 HelpType = htKeyword HelpKeyword = 'IntroductionAndConclusion' DialogTitle = 'Choose conclusion file' DialogOptions = [] FilterIndex = 0 HideDirectories = False ButtonWidth = 23 NumGlyphs = 1 Anchors = [akTop, akLeft, akRight] MaxLength = 0 TabOrder = 0 OnChange = SomethingChanged end object EditIntroductionFileName: TFileNameEdit AnchorSideTop.Control = LabelIntroductionFile AnchorSideTop.Side = asrBottom Left = 8 Height = 37 Hint = 'Optional file used as an introduction to your project.' Top = 101 Width = 426 HelpType = htKeyword HelpKeyword = 'IntroductionAndConclusion' DialogTitle = 'Choose introduction file' DialogOptions = [] FilterIndex = 0 HideDirectories = False ButtonWidth = 23 NumGlyphs = 1 Anchors = [akTop, akLeft, akRight] MaxLength = 0 TabOrder = 1 OnChange = SomethingChanged end object EditCssFileName: TFileNameEdit AnchorSideTop.Control = LabelCssFileName AnchorSideTop.Side = asrBottom Left = 8 Height = 37 Top = 36 Width = 483 HelpType = htKeyword HelpKeyword = 'CssOption' DialogTitle = 'Choose custom CSS file' DialogOptions = [] Filter = 'Cascading Style Sheets (*.css)|*.css' FilterIndex = 0 HideDirectories = False ButtonWidth = 23 NumGlyphs = 1 MaxLength = 0 TabOrder = 2 OnChange = SomethingChanged end end object pageLatexOptions: TPage Hint = 'LaTeX Options' object LabelLatexGraphicsPackage: TLabel AnchorSideTop.Control = rgLineBreakQuality AnchorSideTop.Side = asrBottom Left = 8 Height = 28 Top = 103 Width = 263 Caption = 'LateX graphics package' FocusControl = comboLatexGraphicsPackage ParentColor = False end object LabelHyphenatedWords: TLabel Left = 8 Height = 127 Top = 173 Width = 563 HelpType = htKeyword Align = alCustom Anchors = [akTop, akLeft, akRight] Caption = 'You can specify how you want words to be hyphenated here. Just enter the word (one per line) with hyphens in the correct places. Only English letters are allowed.' ParentColor = False WordWrap = True end object rgLineBreakQuality: TRadioGroup Left = 0 Height = 103 Top = 0 Width = 563 HelpType = htKeyword HelpKeyword = 'PasDocGui/LatexLineBreaks' Align = alTop AutoFill = True AutoSize = True Caption = 'Line Breaks' ChildSizing.LeftRightSpacing = 6 ChildSizing.TopBottomSpacing = 6 ChildSizing.EnlargeHorizontal = crsHomogenousChildResize ChildSizing.EnlargeVertical = crsHomogenousChildResize ChildSizing.ShrinkHorizontal = crsScaleChilds ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 ClientHeight = 76 ClientWidth = 559 ItemIndex = 0 Items.Strings = ( 'strict' 'sloppy' ) OnClick = SomethingChanged TabOrder = 1 end object comboLatexGraphicsPackage: TComboBox AnchorSideTop.Control = LabelLatexGraphicsPackage AnchorSideTop.Side = asrBottom Left = 8 Height = 38 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.' Top = 131 Width = 148 Enabled = False ItemHeight = 0 ItemIndex = 0 Items.Strings = ( 'None' 'PDF' 'DVI' ) OnChange = SomethingChanged Style = csDropDownList TabOrder = 0 Text = 'None' end object memoHyphenatedWords: TMemo AnchorSideTop.Control = LabelHyphenatedWords AnchorSideTop.Side = asrBottom Left = 8 Height = 189 Top = 300 Width = 549 Align = alCustom Anchors = [akTop, akLeft, akRight, akBottom] OnChange = SomethingChanged TabOrder = 2 end end object pageHeadFoot: TPage Hint = 'Header / Footer' object PanelHeaderHidden: TPanel Left = 0 Height = 179 Top = 0 Width = 563 Align = alTop BevelOuter = bvNone BorderWidth = 10 ClientHeight = 179 ClientWidth = 563 TabOrder = 0 object LabelHeader: TLabel Left = 10 Height = 28 Top = 10 Width = 543 HelpType = htKeyword Align = alTop Caption = '&Header (Will appear at the top of every web page)' FocusControl = memoHeader ParentColor = False end object memoHeader: TMemo Left = 10 Height = 131 Top = 38 Width = 543 HelpType = htKeyword HelpKeyword = 'FileAsHeaderOrFooter' Align = alClient OnChange = SomethingChanged TabOrder = 0 WordWrap = False end end object Splitter2: TSplitter Cursor = crVSplit Left = 0 Height = 9 Top = 179 Width = 563 Align = alTop ResizeAnchor = akTop end object PanelFooterHidden: TPanel Left = 0 Height = 304 Top = 188 Width = 563 Align = alClient BevelOuter = bvNone BorderWidth = 10 ClientHeight = 304 ClientWidth = 563 TabOrder = 1 object LabelFooter: TLabel Left = 10 Height = 28 Top = 10 Width = 543 HelpType = htKeyword Align = alTop Caption = '&Footer (Will appear at the bottom of every page)' FocusControl = memoFooter ParentColor = False end object memoFooter: TMemo Left = 10 Height = 256 Top = 38 Width = 543 HelpType = htKeyword HelpKeyword = 'FileAsHeaderOrFooter' Align = alClient OnChange = SomethingChanged TabOrder = 0 WordWrap = False end end end object pageGraphs: TPage Hint = 'Graphs' object Label22: TLabel AnchorSideTop.Control = cbVizGraphUses AnchorSideTop.Side = asrBottom Left = 14 Height = 61 Top = 92 Width = 465 BorderSpacing.Top = 20 Caption = 'You will have to generate graphs yourself. '#10'Use the "dot" program from GraphViz:' ParentColor = False end object cbVizGraphUses: TCheckBox AnchorSideTop.Control = cbVizGraphClasses AnchorSideTop.Side = asrBottom Left = 8 Height = 31 Top = 41 Width = 347 HelpType = htKeyword HelpKeyword = 'GraphVizSupport' Caption = 'Generate and use Uses graph' OnChange = SomethingChanged TabOrder = 0 end object cbVizGraphClasses: TCheckBox Left = 8 Height = 31 Top = 10 Width = 376 HelpType = htKeyword HelpKeyword = 'GraphVizSupport' Caption = 'Generate and use Classes graph' OnChange = SomethingChanged TabOrder = 1 end object ButtonGraphVizURL: TButton AnchorSideTop.Control = Label22 AnchorSideTop.Side = asrBottom Left = 14 Height = 47 Top = 153 Width = 292 AutoSize = True BorderSpacing.InnerBorder = 4 Caption = 'http://www.graphviz.org/' OnClick = ButtonURLClick TabOrder = 2 end end object pageSpellChecking: TPage Hint = 'Spell Checking' object PanelSpellCheckingTop1: TPanel Left = 0 Height = 208 Top = 0 Width = 563 Align = alTop AutoSize = True BevelOuter = bvNone BorderWidth = 10 ClientHeight = 208 ClientWidth = 563 FullRepaint = False TabOrder = 1 object Label20: TLabel AnchorSideTop.Control = ButtonAspellURL AnchorSideTop.Side = asrBottom Left = 10 Height = 61 Top = 147 Width = 546 HelpType = htKeyword Anchors = [akTop, akLeft, akRight] AutoSize = False Caption = 'Enter words that should be ignored when spell-checking below.'#10'One word per line.' FocusControl = memoSpellCheckingIgnore ParentColor = False WordWrap = True end object Label23: TLabel AnchorSideTop.Control = cbCheckSpelling AnchorSideTop.Side = asrBottom Left = 8 Height = 61 Top = 39 Width = 546 Anchors = [akTop, akLeft, akRight] Caption = 'GNU Aspell must be installed and available on $PATH for spell checking :' ParentColor = False WordWrap = True end object cbCheckSpelling: TCheckBox Left = 8 Height = 31 Top = 8 Width = 185 HelpType = htKeyword HelpKeyword = 'SpellChecking' Caption = 'Check Spelling' OnChange = cbCheckSpellingChange TabOrder = 0 end object ButtonAspellURL: TButton AnchorSideTop.Control = Label23 AnchorSideTop.Side = asrBottom Left = 8 Height = 47 Top = 100 Width = 336 AutoSize = True BorderSpacing.InnerBorder = 4 Caption = 'http://aspell.sourceforge.net/' OnClick = ButtonURLClick TabOrder = 1 end end object memoSpellCheckingIgnore: TMemo Left = 10 Height = 264 Top = 218 Width = 543 HelpType = htKeyword HelpKeyword = 'SpellChecking' Align = alClient BorderSpacing.Around = 10 ScrollBars = ssAutoBoth TabOrder = 0 WordWrap = False end end object pageMarkers: TPage Hint = 'Markers' object LabelCommentMarkers: TLabel AnchorSideTop.Control = rgCommentMarkers AnchorSideTop.Side = asrBottom Left = 8 Height = 28 Top = 142 Width = 287 HelpType = htKeyword BorderSpacing.Top = 8 Caption = 'Special comment markers' FocusControl = memoCommentMarkers ParentColor = False end object memoCommentMarkers: TMemo AnchorSideTop.Control = LabelCommentMarkers AnchorSideTop.Side = asrBottom Left = 10 Height = 338 Top = 180 Width = 543 HelpType = htKeyword HelpKeyword = 'CommentMarker' Anchors = [akTop, akLeft, akRight, akBottom] BorderSpacing.Around = 10 OnChange = SomethingChanged TabOrder = 0 end object rgCommentMarkers: TRadioGroup Left = 0 Height = 134 Top = 0 Width = 699 HelpType = htKeyword HelpKeyword = 'CommentMarker' AutoFill = True AutoSize = True Caption = 'Comment marker treatment' ChildSizing.LeftRightSpacing = 6 ChildSizing.TopBottomSpacing = 6 ChildSizing.EnlargeHorizontal = crsHomogenousChildResize ChildSizing.EnlargeVertical = crsHomogenousChildResize ChildSizing.ShrinkHorizontal = crsScaleChilds ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 ClientHeight = 107 ClientWidth = 695 ItemIndex = 1 Items.Strings = ( 'Ignore special comment markers' 'Include all comments but remove special comment markers' 'Include only comments with special comment markers' ) OnClick = rgCommentMarkersClick TabOrder = 1 end end object PageSort: TPage Hint = 'Sort' object LabelItemsToSort: TLabel Left = 8 Height = 28 Top = 8 Width = 300 HelpType = htKeyword Caption = 'Items to sort alphabetically' ParentColor = False end object clbSorting: TCheckListBox AnchorSideTop.Control = LabelItemsToSort AnchorSideTop.Side = asrBottom Left = 8 Height = 448 Hint = 'Which items will be sorted alphabetically '#10'and which will be displayed in their declared order.' Top = 36 Width = 548 HelpType = htKeyword HelpKeyword = 'SortOption' Anchors = [akTop, akLeft, akRight, akBottom] Items.Strings = ( 'structures' 'constants' 'global functions' 'types' 'variables' 'uses-clauses' 'record-fields' 'non-record-fields' 'methods' 'properties' ) ItemHeight = 19 OnClick = SomethingChanged TabOrder = 0 TopIndex = -1 Data = { 0A00000000000000000000000000 } end end object pageGenerate: TPage Hint = 'Generate' object PanelGenerateTop: TPanel Left = 0 Height = 105 Top = 0 Width = 563 Align = alTop Alignment = taLeftJustify BevelOuter = bvNone BorderWidth = 10 ClientHeight = 105 ClientWidth = 563 FullRepaint = False TabOrder = 1 object Label7: TLabel AnchorSideLeft.Control = seVerbosity AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = seVerbosity AnchorSideTop.Side = asrCenter Left = 82 Height = 28 Top = 12 Width = 309 HelpType = htKeyword BorderSpacing.Left = 8 Caption = 'Verbosity level (default is 2)' ParentColor = False end object seVerbosity: TSpinEdit Left = 10 Height = 37 Hint = 'The higher the message level, the more messages will be shown.' Top = 8 Width = 64 HelpType = htKeyword MaxValue = 6 OnChange = SomethingChanged TabOrder = 0 Value = 2 end object ButtonGenerateDocs: TButton Left = 10 Height = 39 Top = 56 Width = 543 Align = alBottom AutoSize = True Caption = 'Generate documentation' OnClick = ButtonGenerateDocsClick TabOrder = 1 end end object memoMessages: TMemo Left = 10 Height = 403 Top = 115 Width = 543 HelpType = htKeyword Align = alClient BorderSpacing.Around = 10 ScrollBars = ssBoth TabOrder = 0 end end object pageDisplayComments: TPage Hint = 'Display Comments' object tvUnits: TTreeView Left = 0 Height = 268 Top = 28 Width = 563 Align = alClient DefaultItemHeight = 29 TabOrder = 0 OnClick = tvUnitsClick end inline seComment: TSynEdit Left = 0 Height = 191 Top = 301 Width = 563 Align = alBottom Font.Height = -16 Font.Name = 'courier' Font.Pitch = fpFixed Font.Quality = fqNonAntialiased ParentColor = False ParentFont = False TabOrder = 1 Gutter.Width = 61 Gutter.MouseActions = < item ClickCount = ccAny ClickDir = cdDown Command = emcOnMainGutterClick end item Button = mbRight Command = emcContextMenu end> RightGutter.Width = 0 RightGutter.MouseActions = <> Keystrokes = < item Command = ecUp ShortCut = 38 end item Command = ecSelUp ShortCut = 8230 end item Command = ecScrollUp ShortCut = 16422 end item Command = ecDown ShortCut = 40 end item Command = ecSelDown ShortCut = 8232 end item Command = ecScrollDown ShortCut = 16424 end item Command = ecLeft ShortCut = 37 end item Command = ecSelLeft ShortCut = 8229 end item Command = ecWordLeft ShortCut = 16421 end item Command = ecSelWordLeft ShortCut = 24613 end item Command = ecRight ShortCut = 39 end item Command = ecSelRight ShortCut = 8231 end item Command = ecWordRight ShortCut = 16423 end item Command = ecSelWordRight ShortCut = 24615 end item Command = ecPageDown ShortCut = 34 end item Command = ecSelPageDown ShortCut = 8226 end item Command = ecPageBottom ShortCut = 16418 end item Command = ecSelPageBottom ShortCut = 24610 end item Command = ecPageUp ShortCut = 33 end item Command = ecSelPageUp ShortCut = 8225 end item Command = ecPageTop ShortCut = 16417 end item Command = ecSelPageTop ShortCut = 24609 end item Command = ecLineStart ShortCut = 36 end item Command = ecSelLineStart ShortCut = 8228 end item Command = ecEditorTop ShortCut = 16420 end item Command = ecSelEditorTop ShortCut = 24612 end item Command = ecLineEnd ShortCut = 35 end item Command = ecSelLineEnd ShortCut = 8227 end item Command = ecEditorBottom ShortCut = 16419 end item Command = ecSelEditorBottom ShortCut = 24611 end item Command = ecToggleMode ShortCut = 45 end item Command = ecCopy ShortCut = 16429 end item Command = ecPaste ShortCut = 8237 end item Command = ecDeleteChar ShortCut = 46 end item Command = ecCut ShortCut = 8238 end item Command = ecDeleteLastChar ShortCut = 8 end item Command = ecDeleteLastChar ShortCut = 8200 end item Command = ecDeleteLastWord ShortCut = 16392 end item Command = ecUndo ShortCut = 32776 end item Command = ecRedo ShortCut = 40968 end item Command = ecLineBreak ShortCut = 13 end item Command = ecSelectAll ShortCut = 16449 end item Command = ecCopy ShortCut = 16451 end item Command = ecBlockIndent ShortCut = 24649 end item Command = ecLineBreak ShortCut = 16461 end item Command = ecInsertLine ShortCut = 16462 end item Command = ecDeleteWord ShortCut = 16468 end item Command = ecBlockUnindent ShortCut = 24661 end item Command = ecPaste ShortCut = 16470 end item Command = ecCut ShortCut = 16472 end item Command = ecDeleteLine ShortCut = 16473 end item Command = ecDeleteEOL ShortCut = 24665 end item Command = ecUndo ShortCut = 16474 end item Command = ecRedo ShortCut = 24666 end item Command = ecGotoMarker0 ShortCut = 16432 end item Command = ecGotoMarker1 ShortCut = 16433 end item Command = ecGotoMarker2 ShortCut = 16434 end item Command = ecGotoMarker3 ShortCut = 16435 end item Command = ecGotoMarker4 ShortCut = 16436 end item Command = ecGotoMarker5 ShortCut = 16437 end item Command = ecGotoMarker6 ShortCut = 16438 end item Command = ecGotoMarker7 ShortCut = 16439 end item Command = ecGotoMarker8 ShortCut = 16440 end item Command = ecGotoMarker9 ShortCut = 16441 end item Command = ecSetMarker0 ShortCut = 24624 end item Command = ecSetMarker1 ShortCut = 24625 end item Command = ecSetMarker2 ShortCut = 24626 end item Command = ecSetMarker3 ShortCut = 24627 end item Command = ecSetMarker4 ShortCut = 24628 end item Command = ecSetMarker5 ShortCut = 24629 end item Command = ecSetMarker6 ShortCut = 24630 end item Command = ecSetMarker7 ShortCut = 24631 end item Command = ecSetMarker8 ShortCut = 24632 end item Command = ecSetMarker9 ShortCut = 24633 end item Command = ecNormalSelect ShortCut = 24654 end item Command = ecColumnSelect ShortCut = 24643 end item Command = ecLineSelect ShortCut = 24652 end item Command = ecTab ShortCut = 9 end item Command = ecShiftTab ShortCut = 8201 end item Command = ecMatchBracket ShortCut = 24642 end> MouseActions = < item ShiftMask = [ssShift, ssAlt] ClickDir = cdDown Command = emcStartSelections MoveCaret = True end item Shift = [ssShift] ShiftMask = [ssShift, ssAlt] ClickDir = cdDown Command = emcStartSelections MoveCaret = True Option = 1 end item Shift = [ssAlt] ShiftMask = [ssShift, ssAlt] ClickDir = cdDown Command = emcStartColumnSelections MoveCaret = True end item Shift = [ssShift, ssAlt] ShiftMask = [ssShift, ssAlt] ClickDir = cdDown Command = emcStartColumnSelections MoveCaret = True Option = 1 end item Button = mbRight Command = emcContextMenu end item ClickCount = ccDouble ClickDir = cdDown Command = emcSelectWord MoveCaret = True end item ClickCount = ccTriple ClickDir = cdDown Command = emcSelectLine MoveCaret = True end item ClickCount = ccQuad ClickDir = cdDown Command = emcSelectPara MoveCaret = True end item Button = mbMiddle ClickDir = cdDown Command = emcPasteSelection MoveCaret = True end item Shift = [ssCtrl] ShiftMask = [ssShift, ssAlt, ssCtrl] Command = emcMouseLink end> MouseSelActions = < item ClickDir = cdDown Command = emcStartDragMove end> VisibleSpecialChars = [vscSpace, vscTabAtLast] SelectedColor.BackPriority = 50 SelectedColor.ForePriority = 50 SelectedColor.FramePriority = 50 SelectedColor.BoldPriority = 50 SelectedColor.ItalicPriority = 50 SelectedColor.UnderlinePriority = 50 BracketHighlightStyle = sbhsBoth BracketMatchColor.Background = clNone BracketMatchColor.Foreground = clNone BracketMatchColor.Style = [fsBold] FoldedCodeColor.Background = clNone FoldedCodeColor.Foreground = clGray FoldedCodeColor.FrameColor = clGray MouseLinkColor.Background = clNone MouseLinkColor.Foreground = clBlue LineHighlightColor.Background = clNone LineHighlightColor.Foreground = clNone inline TSynGutterPartList object TSynGutterMarks Width = 24 MouseActions = <> end object TSynGutterLineNumber Width = 21 MouseActions = <> MarkupInfo.Background = clBtnFace MarkupInfo.Foreground = clNone DigitCount = 2 ShowOnlyLineNumbersMultiplesOf = 1 ZeroStart = False LeadingZeros = False end object TSynGutterChanges Width = 4 MouseActions = <> ModifiedColor = 59900 SavedColor = clGreen end object TSynGutterSeparator Width = 2 MouseActions = <> MarkupInfo.Background = clWhite MarkupInfo.Foreground = clGray end object TSynGutterCodeFolding MouseActions = < item Button = mbRight Command = emcCodeFoldContextMenu end item ShiftMask = [ssShift] Button = mbMiddle ClickCount = ccAny ClickDir = cdDown Command = emcCodeFoldCollaps end item Shift = [ssShift] ShiftMask = [ssShift] Button = mbMiddle ClickCount = ccAny ClickDir = cdDown Command = emcCodeFoldCollaps Option = 1 end item ClickCount = ccAny ClickDir = cdDown Command = emcNone end> MarkupInfo.Background = clNone MarkupInfo.Foreground = clGray MouseActionsExpanded = < item ClickCount = ccAny ClickDir = cdDown Command = emcCodeFoldCollaps end> MouseActionsCollapsed = < item Shift = [ssCtrl] ShiftMask = [ssCtrl] ClickCount = ccAny ClickDir = cdDown Command = emcCodeFoldExpand end item ShiftMask = [ssCtrl] ClickCount = ccAny ClickDir = cdDown Command = emcCodeFoldExpand Option = 1 end> end end end object Splitter1: TSplitter Cursor = crVSplit Left = 0 Height = 5 Top = 296 Width = 563 Align = alBottom ResizeAnchor = akBottom end object pnlEditCommentInstructions: TPanel Left = 0 Height = 28 Top = 0 Width = 563 Align = alTop Caption = 'Click on an item in the tree view to see its comment.' FullRepaint = False TabOrder = 2 end end end object PanelLeft: TPanel Left = 0 Height = 533 Top = 0 Width = 208 Align = alLeft BevelOuter = bvNone ClientHeight = 533 ClientWidth = 208 TabOrder = 1 object lbNavigation: TListBox Left = 0 Height = 482 Top = 51 Width = 208 Align = alClient ItemHeight = 0 OnClick = lbNavigationClick ScrollWidth = 206 TabOrder = 0 TopIndex = -1 end object ButtonGenerate: TBitBtn Left = 10 Height = 31 Hint = 'Generate documentation (F9)' Top = 10 Width = 188 Align = alTop AutoSize = True BorderSpacing.Around = 10 Caption = 'Generate' OnClick = MenuGenerateRunClick TabOrder = 1 end end object PasDoc1: TPasDoc OnMessage = PasDoc1Warning MarkerOptional = True Generator = HtmlDocGenerator ShowVisibilities = [] left = 136 top = 528 end object HtmlDocGenerator: THTMLDocGenerator CSS = 'body { font-family: Verdana,Arial; '#10' color: black; background-color: white; '#10' font-size: 12px; }'#10'body.navigationframe { font-family: Verdana,Arial; '#10' color: white; background-color: #787878; '#10' font-size: 12px; }'#10#10'img { border:0px; }'#10#10'a:link {color:#C91E0C; text-decoration: none; }'#10'a:visited {color:#7E5C31; text-decoration: none; }'#10'a:hover {text-decoration: underline; }'#10'a:active {text-decoration: underline; }'#10#10'a.navigation:link { color: white; text-decoration: none; font-size: 12px;}'#10'a.navigation:visited { color: white; text-decoration: none; font-size: 12px;}'#10'a.navigation:hover { color: white; font-weight: bold; '#10' text-decoration: none; font-size: 12px; }'#10'a.navigation:active { color: white; text-decoration: none; font-size: 12px;}'#10#10'a.bold:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'a.bold:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'a.bold:hover {text-decoration: underline; font-weight:bold; }'#10'a.bold:active {text-decoration: underline; font-weight:bold; }'#10#10'a.section {color: green; text-decoration: none; font-weight: bold; }'#10'a.section:hover {color: green; text-decoration: underline; font-weight: bold; }'#10#10'ul.useslist a:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'ul.useslist a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'ul.useslist a:hover {text-decoration: underline; font-weight:bold; }'#10'ul.useslist a:active {text-decoration: underline; font-weight:bold; }'#10#10'ul.hierarchy { list-style-type:none; }'#10'ul.hierarchylevel { list-style-type:none; }'#10#10'p.unitlink a:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'p.unitlink a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'p.unitlink a:hover {text-decoration: underline; font-weight:bold; }'#10'p.unitlink a:active {text-decoration: underline; font-weight:bold; }'#10#10'tr.list { background: #FFBF44; }'#10'tr.list2 { background: #FFC982; }'#10'tr.listheader { background: #C91E0C; color: white; }'#10#10'table { border-spacing:2px; padding:4px; width:100%; }'#10#10'table.markerlegend { width:auto; }'#10'table.markerlegend td.legendmarker { text-align:center; }'#10#10'table.sections { background:white; }'#10'table.sections td {background:lightgray; }'#10#10'table.summary td.itemcode { width:100%; }'#10'table.detail td.itemcode { width:100%; }'#10#10'td { vertical-align:top; padding:4px; }'#10#10'td.itemname {white-space:nowrap; }'#10'td.itemunit {white-space:nowrap; }'#10'td.itemdesc { width:100%; }'#10#10'div.nodescription {color:red;}'#10'dl.parameters {;}'#10'dl.parameters dt {color:blue;}'#10'dl.parameters dd {;}'#10#10'/* Style applied to Pascal code in documentation '#10' (e.g. produced by @longcode tag) } */'#10'span.pascal_string { color: #000080; }'#10'span.pascal_keyword { font-weight: bolder; }'#10'span.pascal_comment { color: #000080; font-style: italic; }'#10'span.pascal_compiler_comment { color: #008000; }'#10'span.pascal_numeric { }'#10'span.pascal_hex { }'#10#10'p.hint_directive { color: red; }'#10#10'input#search_text { }'#10'input#search_submit_button { }'#10#10'acronym.mispelling { background-color: #ffa; }'#10 left = 168 top = 528 end object OpenDialog1: TOpenDialog Title = 'Open existing file' 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] top = 528 end object SaveDialog1: TSaveDialog Title = 'Save file as' DefaultExt = '.pds' Filter = 'PasDoc GUI Settings (*.pds)|*.pds' FilterIndex = 0 left = 96 top = 528 end object OpenDialog2: TOpenDialog Title = 'Open existing file' DefaultExt = '.pds' Filter = 'PasDoc GUI Settings (*.pds)|*.pds' FilterIndex = 0 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 = 'Online Help' OnClick = MenuContextHelpClick end object MenuAbout: TMenuItem Caption = '&About' OnClick = MenuAboutClick end end end object TexDocGenerator: TTexDocGenerator left = 200 top = 528 end object HtmlHelpDocGenerator: THTMLHelpDocGenerator CSS = 'body { font-family: Verdana,Arial; '#10' color: black; background-color: white; '#10' font-size: 12px; }'#10'body.navigationframe { font-family: Verdana,Arial; '#10' color: white; background-color: #787878; '#10' font-size: 12px; }'#10#10'img { border:0px; }'#10#10'a:link {color:#C91E0C; text-decoration: none; }'#10'a:visited {color:#7E5C31; text-decoration: none; }'#10'a:hover {text-decoration: underline; }'#10'a:active {text-decoration: underline; }'#10#10'a.navigation:link { color: white; text-decoration: none; font-size: 12px;}'#10'a.navigation:visited { color: white; text-decoration: none; font-size: 12px;}'#10'a.navigation:hover { color: white; font-weight: bold; '#10' text-decoration: none; font-size: 12px; }'#10'a.navigation:active { color: white; text-decoration: none; font-size: 12px;}'#10#10'a.bold:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'a.bold:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'a.bold:hover {text-decoration: underline; font-weight:bold; }'#10'a.bold:active {text-decoration: underline; font-weight:bold; }'#10#10'a.section {color: green; text-decoration: none; font-weight: bold; }'#10'a.section:hover {color: green; text-decoration: underline; font-weight: bold; }'#10#10'ul.useslist a:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'ul.useslist a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'ul.useslist a:hover {text-decoration: underline; font-weight:bold; }'#10'ul.useslist a:active {text-decoration: underline; font-weight:bold; }'#10#10'ul.hierarchy { list-style-type:none; }'#10'ul.hierarchylevel { list-style-type:none; }'#10#10'p.unitlink a:link {color:#C91E0C; text-decoration: none; font-weight:bold; }'#10'p.unitlink a:visited {color:#7E5C31; text-decoration: none; font-weight:bold; }'#10'p.unitlink a:hover {text-decoration: underline; font-weight:bold; }'#10'p.unitlink a:active {text-decoration: underline; font-weight:bold; }'#10#10'tr.list { background: #FFBF44; }'#10'tr.list2 { background: #FFC982; }'#10'tr.listheader { background: #C91E0C; color: white; }'#10#10'table { border-spacing:2px; padding:4px; width:100%; }'#10#10'table.markerlegend { width:auto; }'#10'table.markerlegend td.legendmarker { text-align:center; }'#10#10'table.sections { background:white; }'#10'table.sections td {background:lightgray; }'#10#10'table.summary td.itemcode { width:100%; }'#10'table.detail td.itemcode { width:100%; }'#10#10'td { vertical-align:top; padding:4px; }'#10#10'td.itemname {white-space:nowrap; }'#10'td.itemunit {white-space:nowrap; }'#10'td.itemdesc { width:100%; }'#10#10'div.nodescription {color:red;}'#10'dl.parameters {;}'#10'dl.parameters dt {color:blue;}'#10'dl.parameters dd {;}'#10#10'/* Style applied to Pascal code in documentation '#10' (e.g. produced by @longcode tag) } */'#10'span.pascal_string { color: #000080; }'#10'span.pascal_keyword { font-weight: bolder; }'#10'span.pascal_comment { color: #000080; font-style: italic; }'#10'span.pascal_compiler_comment { color: #008000; }'#10'span.pascal_numeric { }'#10'span.pascal_hex { }'#10#10'p.hint_directive { color: red; }'#10#10'input#search_text { }'#10'input#search_submit_button { }'#10#10'acronym.mispelling { background-color: #ffa; }'#10 left = 232 top = 528 end end pasdoc/source/gui/frmaboutunit.lfm0000600000175000017500000000335111461245245017774 0ustar michalismichalisobject frmAbout: TfrmAbout Left = 338 Height = 372 Top = 91 Width = 488 HorzScrollBar.Page = 407 VertScrollBar.Page = 346 ActiveControl = MemoInformation Caption = 'About' ClientHeight = 372 ClientWidth = 488 Font.Height = -16 Font.Name = 'MS Sans Serif' OnCreate = frmAboutCreate Position = poMainFormCenter LCLVersion = '0.9.28.2' object LabelTitle: TLabel Left = 13 Height = 33 Top = 8 Width = 452 Alignment = taCenter Anchors = [akTop, akLeft, akRight] Caption = 'PasDoc GUI' Font.Height = -19 Font.Name = 'MS Sans Serif' Font.Style = [fsBold] ParentColor = False ParentFont = False end object BtnClose: TBitBtn AnchorSideTop.Side = asrBottom Left = 374 Height = 43 Top = 318 Width = 99 Anchors = [akRight, akBottom] AutoSize = True BorderSpacing.InnerBorder = 2 Caption = '&Close' Kind = bkClose NumGlyphs = 0 TabOrder = 0 end object MemoInformation: TMemo AnchorSideTop.Control = LabelTitle AnchorSideTop.Side = asrBottom AnchorSideBottom.Control = ButtonPasDocURL Left = 13 Height = 224 Top = 41 Width = 460 Anchors = [akTop, akLeft, akRight, akBottom] Color = clBtnFace ReadOnly = True TabOrder = 1 end object ButtonPasDocURL: TButton AnchorSideLeft.Control = MemoInformation AnchorSideLeft.Side = asrCenter AnchorSideTop.Side = asrBottom AnchorSideBottom.Control = BtnClose Left = 70 Height = 43 Top = 265 Width = 346 Anchors = [akLeft, akBottom] AutoSize = True BorderSpacing.Bottom = 10 BorderSpacing.InnerBorder = 2 Caption = 'http://pasdoc.sourceforge.net/' OnClick = ButtonPasDocURLClick TabOrder = 2 end end pasdoc/source/gui/pasdoc_gui.ico0000600000175000017500000020204712221630742017364 0ustar michalismichalis PNG  IHDR)IDATxwpU׽Oul&cʀ1\PŘb\:P%0&@HXYD bХ" z c&ynIG2Hߵg=kU deeee*`eeee,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^* h++++/Kemeee奲RY@[YYYy,TVVVV^\ oLjn꥕[68׿~x~<7=sd|w߻DHޏ?$_.A:4++++7" A!d?|y K"8 )7heeeS.ZYtv۷o\z/^<: .]tҥK$d\v_͛7oݺ NMEm-^,ZڌXR[YYr  RSS3g$%%%$$>|@`tإ#G=z411$/ӧ׿&''r~ʕ7n@mZxMq8k3bImee{@1AA7Hipyqqq[lټyfLݺumHÎ;vIzvo>Pa'HٳgiT۸lkӧOeiӹU++MǏoݺ'ťg!–,Y(״ء%..].[,<<|Ŋ$cʕW/֭[!8޵knx}I,6zjJJʝ;w=z$RkCm:7bkee(ϱw޽rʩS0POSDDļyf̘1yǏMKx&L0qĠI&M2eڴi>3gDž q 6 ȦEn`}1]Fۃиeի+W ;Ν;wڵk1t~'ݻw\V4q>.۷ 4hIG9zh8awHH٤F%**jzǎ:)) O! tYd++7^huƍ'OB7LgΜ cΝ۴iӴi&ij֬Y[hѲeVZm۶k׮C:uڵ{Pޯ_!C@?SΚ5kaaa4&O@ŋǏ4Ϯih++WQ6={DX7oܾ}裏TR9OTť.UVz5jԨUVڵIFݺu? * }}}v.]wkiZ0ӧOA+Wݳg]0}%0}޽T3⁕z9P<|֭[#""QmԨ|,W\ŋ榊9T>>PA  =z?O۶m_zʕ;w`+ȍh[YY-@'8uܹoڴ)44 0m۶L2Eyw:MKq鷿maHLpC}c1Xl`ݪU+5S7nƌ .ܰaÎ;x'Nouփhhh++_\4Hзo>{޽{ׯ_Ǝ۳g͛C=,-կ~U5W.G%\.T&5RJ͚5իפI6mtܹO>C !!!K,Yf͗_~{Ǐ?믿-^Bh.?}?O?LJwuٳ  ⲁ5>(_|ժU 6lٲeN틛4iܹs#""h꫄7n8휁azdkRY%J|ᇕ*UUV ZnݵkWp顡0:..ȑ#t X}gheeM@*M~s8yl5PdrU^~Z֭[`` .\f͚m۶K;u8yИ/׮]ӧO_VVV奀~~8_ `_= \O0`_۷d]v۷Ⱋ{x׆kl)`8M4v|÷lrq'Oh tF y/EBgxסCP'N2et]6mԩSuҤIAAA&L7nܘ1c~:l0te>\Cjlu2e/N ;3}L5BZ7o-Hٳ׬Ycǎcǎ]tݻǼ-̍[YYR@WHō;v-^[rH>+VDDD˗/[lҥ:`sΝ5kVHHP{ĈX0nѪUFծ]C-L{=}F}8 111_Ǐ[d J/oh"Eʕ+W^=0קO#G!ի7lذm۶piK\ںu_~y7u}Vaaa .3gΌ3ڣG:t(֭f{ҥKC[|zJ*5lذSN\Vƃ=zTo ΍,z䥀Ʒ+V .]8l/tq.)?~̥ĄsC8p`߾}_}ծ]t""jxp6b1ڵk6mk͚5Imɒ%a4f99̙3ĉȑ# {n\6)K.={6zĈ}k֬VvD &@OZ~}CU$$޽{O>(UfF@ |m۶-hBύ7ݻ_^\z҃߿ ޽{[nq~Ϟ={)L7c 7o޼f5nܸAu޽UV@bŊ4bȒzDӇ .^xӦM4 ܚĤ>\sF.XYYwy/K.ӡCӧXb۶mD3wi֥gϞ}7x8$믿ӧO;vlv킡 LիW6m*TGgs<ژhްa.] 6l֬YQQQq8}A 0UfR@U?ڵkw JbiW^ =@kSv_.Iҏ?%I'O$fg}- ݻwڵ3fL^˜RJ7ra:Xҥˈ#0ѻw>y$ךo h++r2޻wˉ[n6mZ```֭[l… g9ʡguر!CBBB̔k׮Y_c8[d&xύRRR0/9[n7TF9<WԮ]m۶ IpkN:}wN07Sץ3OnT2P+Ε6o,ej Oӻw^pa߾}7n\dӢEի,Y< }EJ*Uf֭[-WtңG;Vny":cFQ Nڽ{ڵk͛aFUX=fURiӦzҶv6lطo*{vHα =IDdTQt'O<~xbbѣGdk||tC>|8!!ߒk\;|H> Ab Ovg v 8P,%P 5=6Hݫ8L r|'8qh݀js d=Ha:tRa^QHp1cѣI&0f wyUTC~E\[pHt+qO+ߕ+WMvaNӺ_l]nZ'7n޼/+~ "|#$C mkCEx4Tq6@Y&8PoٲŜsKP'&_}I܂V%ha,3 04 PB'ݻwfͪVZxq<)F[øU!>TiSiNqYfYaf4^"SwIUSATTʕ+WX|r)O>?>_kaaa+P {x1H 2߾}[t~Ĵ], 9emC̑l˖- M9.PW|!w!Ѧq5j#P,澔:<;HSh{:SH{O0;T';5aĉ}m޼yjJ(L;H"+Vlܸq݉#&pSNo:Y+A.y:u{TuO͞=;$$$88xʔ)<JH'Oǟ_ :u3 G5ٹe4ւzb~a_QHG4`<]`GDDch |gΜI'OLu )&:Sf͂\Mm$'栟b5trr2.\:SɄ Іe(J<ׯifЍ5+3ݳg+"ҏfc齚>͛7ԩSe"",̑6L݆ӦM1Ç 2hР}իW=~RnݺO>ٳ'48qzW_ɸp21]c0b$ϏުU+A@:u|||j֬IjժUTTX>M\K<,_V!]vݺuA !h\ػwoĭC+J۷7~3%%EV'2ã^hgEt&7FG!x@CJL 8M _֭i`1"\ L$r? 5ߩ\2O!9E\F&sOb91=J m)MU%4y9*;$!b8 xwr% &|LJҧ&ЁdcWXPO:w#IA6DSe˒Ja/^X1&wi*' |D:rq½pF 5"IR}'$$={0Z>ڍ9ů"7:kXqE4|r ,3m!1)B \V- BM`ѢEM \P5E.]t2e7Wj#Gd+gRDҊP?~ # L%ƠvBb9;N$ Ϟ=ΧNڿ?t%*2LĻac1bFM6DT~rPBdo~ 3MNO|/~@ 0p/\4P*pvcƌ1c #8;'ƍb4 LjΝÙٳj*S eRx|@UMo\[F)9-|_V!8Wԙ6luVpS$0qqqtYlBrc+:Ses]8l2 UƎx7:"l[n"Iv.]fQFx7*-- F`I0! Yn~^Є8pY87ߑ"6l ]vi~ J3 9<=z(m mpxx8] iPCPr2헎B팶[IR/N#A)tYmۦ#)98*d^[aBFr9: ߼y3 ŘCWZʫs r;w$b ,rS})eʔ<^ PjժE; 2;wekUzY@g,@=۷O>Muݺu<ȨQ~Ro9? &MZl_sk&Xʕ'NT|:2daoݺ5^z , rȒN^k!dPm^׮]q%::Finݺ3ysN[A21%%EYt^hє)S(M6 4 4Մ"t_"fE+=9 d3ffZe( "m/T}{TTٳ1;w YV3Y9Ssc+n7J:W\}'K[lI$A3("Ybr!}Ÿ4lf4 _ `4c40žDh/J6:A"O:` >X 4g!sP;nQ]\/_^sh6 e^8vǎ f̘'СUr7p }xSiٱc׼z* -$&`kjzƍׯN:TK h4P5pIwM>bJ.MM?L< gӘ{f˗קҥ % Yx`_hLtfwe> uo<8Ng9qWV 2端& GmR u8ó2C\p[vdJ4~ɇ r#|A?ܝr|4)'3g,*%׌eMаҽ{JK.2e 718x@SHVJ(,&D۬R1WثUF5cCΥk 9l֬YϞ=f:HwƖlASYZAWBǏ_vo5&NM־΀.d89hfy[j۶m[IKCZ-[b~4h0'd4)1pEy̘1Fhr_t\gW>xQn/#""Q\uF(3䉀cϮ,PA'ᢜh8a:LKxp4)ڵVxSVqkUZ5 u]c)Քmw]ϱ7otI駟b֏mիBs={p"~i(9}PDxje Sfs=z! 00pHW߾}_z b`d)g0PB '~LETkR#ѣGwAHcN!&w 'mhR)WFCH ,A D{hymѿ>}G߬9Rc)z'\A#Hvg2#<@=l)+VS1x!@˗oݺUS8 k ǫ<XMRܔbhK+5#pKڠ!PƋh]tk X0bĈѣGӮiӦ4a' &Æ d\֭!"qd:H<ܡ!{LAs"> %%%DӪۑnjv ,tN$tMfϞrJ̓;X hofn߾}9j \ZMx4|I-T-jΝ;{ (t{5@aQW?Ғ6L>|Р xvM x.2M1K,!)A u e{C&x5L%vHq-[:tPg\;=F!˗5g P<,] ǝ 5qEs)QSǎK #a %8UiRC7Bϟ?w\~Aj\֭RAMYTL$ܿ߮$BY@?G]~;޽ZNÄfgl48Ԣh.x)ɓ'>mBcA(e|\=k,j;#l~#i^S'lڴiݺuE+XC-h;:R|2d=Vi_~Ŋ5/C gN9weĈ\Re&d;p0VZEMܹ3I5s{2ryp& d!(l:ʜ몰ğ |/مlJdu.8 kL7(2R{3oiMՀNOoCSfj.3|ߠ'-8GR1:,i∱ƀ8$$#PpI r,S IOO>Ľ~Hs?s(-jF+V 4Q={lٲO2e .졑svڙY"O xf1y@d/kHve#k͛уHLl%t3*?\n:4\BgcF΃H ΍,Mo/ӏl xDLcs_˦Kʒ,\0FzxX o\IWFf/%x!:LdYX^QWq[.고LlAavd$oW\y˗CX`9x&&S0mZ8RNI6V^hn=<ׂ ƌC0k2[]g+Uwؑ&gԩ ]4횯 >aY_-āS t|;EK&C)2f~sR w ^ uMm#PovW7_s06h,6fJiSQ޽ '(;O2[GDg` ]iy7#E2n<<rnXQ5 )YC=ZTH HE8TkךA<*s3\ׂ8L;j_'VM(:RKמ~xN6M+w~UVgow}gOя==%qilD c6Xfrg'D'< _"\ :z׊nذaS5!b̙C*_$ %6nmv7$g_m%H:uk. `ʔ)gM:ҧ/5bw(Xs?9zuG齆UyO]o<=hw+w'^fC ::%֜}sjǟWjfz*ٳMr!99 8 -˯ #,F$bkf&Ǐӧ&<,f }-V@bg6'kq;hrି/}JHfh,6 퓊իwųhfzT9rX9rqNfRHeR Bao.]488XtnժGZC":t(-cz0^4]`dHOdՏv.em2%I]ҥ)m۶4hrSZϭhĉG!=)X`*WLwۋ62`FH/~rV97鹬7ژM p _vmhhiӆ &:u|=BМis 5V_ͦ?IiVۧ\f k˷'O޽;::zܹpaÆ7{BWV֭[0e˖#GYH:2C1Ϛ u0MxϢttfi4KI+7Qv#^ ju@c ;t3fҤI^lN˖-E%Kf|M+\aĈft\n92$37.G3L1$99y6l;v,"D׿uf5h稉.\̾iaHHTrk6f,2;]z̺"u7D;əVN@Ϝ9sqqq'Nq ⤟ud^a[ltIW,]I諒Bٳ1" p=/{3i&$:zyf!kYNsAope6ReEub{ o}ٰ@o֪0/V<́y h`zyͱE UTQc;k/f렭2WǧC΂;$%M5@Y~˗pK7322r…ӦM̰ZĭI'tFE)[,?:JyT'NTNAϼj(N{ԩSbXTð5c<52r6'8,YbJ5ZcT?ݼySB캼y(+/,ӆ&MoqFFv0C b ȟEzEIIꫯ`=4BBBfC ܮaÆ8;s'K:S-y"s\"1߮6~4fiNUP9rl&k_@Z;w\Gm]N3 8BSl4i<55-_Z3R]}ff?~ڵkO7VZȪU֪U>}5kl߾%GH"1|1Ti,^EGGf* >wذa}ԩS-իGMS>OI-pA,˹H-C0%yqqqd̙3!Tǎunfk 0 EhZ}m<Ǘ_~ipOϬڵku sP+湬YhMVӺXjfΝ C%MgRA6O8uy.3hР iJhު*'@hGzuڵszBCa0{]:wӼ̃6۳i %Kh & ًC/σg6y#U3 *`L0јܾ}1B/^¥pʟ.\]i4vX>dȐKbd*B37*Z(PliukBg җOLLpAO6 ߶ƃwh KVv@{. MGݎhyh8$VvS:jGCa^=?헄á?+’cZ/4mڴC500ZjDSNO+#5  :ԜIʷnݚKa>*U`gp=n Y!_X1~^V-.kH ?~TTԮ]pXΝuoHPhuhvs; KHq1 43f̠rFS}d9bIAՎ[lٷouljv簘~;奀(VXFu&Μ|\y>ݻS!2ֆ_5k֬QFT!SjUY2eJ(A2@-&i҆52־dɒ\ʷhSE8w{Q蜒CU4A7oYLHhhgֶ ݻ7&&,gʕ~gVSR%J#_~G"0M|r"+m16K] Fc:D**iӦK?֘%, :^zX5k[(_\ҥKe\ 㚕gj =Y.Hٓ*.~)JNN5YI緰Ry4y3ۢSapC;)c@pϟ?ń-2j'nd;4vG]v ذa/|ԩ˗/imqЎ{=^@qt/[!,8RjժR-0' 2FqeS P\rAMm8f.P)OѡC]Ԑ0ur@i4y hrS'hzΝPybF9dҤIs }vJx*s0-b*/Հ6+,%b8T%>ܰX>w"\SL2Q;vHL2eV/\@YVt9C;OWV']Yj @sѽضm[dd$VqȐ!D֎fσ6@k>zEvD6mZt)`8p`۶mubt֭ۢE 'ÒSV\K3NShmks gf͚7#00p!!!Oٺu+|С'N={ʕ+7ot{ 7L 9.qh2nXb=+TPz:u`& G:>z(hή^kY݈<1:55UEk۷o0j=ȸt= .?Kɴ^@mϚ50ahp޽7nDO<a˗=,\"GCmf[h+0c [DDDtt4ۿ =4fa+\$6Pz{7qWR"PUڷo-Rsʔ)f|LLJJDTE |1g)k YL{#"cb: 쒳Ow`ӫ؟&м} 6@gĉ װaCB]D fӫS([-X&Iͣxo5<0ڼQFi:wܷoߡC3[EEE vA ٷop@kmk# EV|Xʕ+תU^zUV'C\ ġn')1{wN)횭 8k6b@ A0%[}~˖-_5XKvZ:aaaU!Ǐ>HN+5/N! b2єpZ#{^99础_&zo (Qex|Ubbb={Ȏ'Ni3lԩ8A@=]4h@w`3/\s9tf&%UdŴ(E(8ҜRV)J*^MӪ.Oe0bIqzwy+@Yմ p~R"EwMtq1up\lYK[M/vTF5mڴuTnݺѣ 9r f̘A!Κ5k0N+@maf;y[𥟎/X-/{M@C)2Ё_Oa0 , .5xd2qDb8~qƑ^ K͎i hcUȉ=*bEQ!&C<)IgF166VSNы׏ԫspR‘>7v*#U. |2fZ3SCxd:O?8;/;v,mÇ#9Ξ~4!t;t@qM#ULN\hXDS( 4o0n߾]&DGW@\#3{¥!8jIGDBWػwobb"UFiO<{\lNesh:3XLAhт,3;Oaߴ Vv\*Pq~Z|P@3F2?9}GDՇG'!͘AӲ,**M kBW~L׮]iJ>Q #P٣݉rK j 1\Jy.Aŋ1˗GDDb}xuQ,wM]:tPbb"^x.P(ǩ|L+qiL7o޼|2ȑ#TW: k׮ , >ayp|d ,"n;Oqw};(٧7tPH`4L(Ұ ĖO6lܓ!͜<U4TeaA΍LC{s͛7DX<5k\ZRLL̆ @0;ŻvJCd gϞTb|(N.2{ntֈ32hrxLxAЈA߂СC_Ƃ%LP._ 8KG[isiP6si$q\?noV9bMO[z5V~'zjӦf[,0*6;yi!"YF.ݺugL}h+'FIsew6}k 8pA "n1!!رcIIIT#A`Brʤc5Ϝ΂~Xޫi`yXJрh&/hzGqpZj:@/ 3jF#.rYs Z ֭MsMɓ' ;5::܌3FM[HiuB1" ُF5EN7 POc.]JJhun˥KYceV^ hX@RJӦMwÇ/[ ]cY1ŀ"^ 1I&%ee~oFљ>_M@0{?[x0:th֬Yk֬yoNz}%@ˀhvZ^jU\h },Hm&3~-cn˒J^1DVRG%P\)+V7oބ ` >X:afifvi*׶}L<:yfۢVSi&o$W^u\ v:z&Q?.߻.Aa E#bzsTSl7N93({1M۪ׯ";w_><<|Μ9HCݺu1qb2jL*!^%Y+}.Ŭiv&5rqOԩHҥҢE }g’%KGٿX %տ2:W:pSJ5jd&;jvwL30l0\>Q!P|hVzz֌2BzrN4Xi3D&zjj/#<MuF#J="ԩSuЎ;>|^vQWKM㶨C wF:vãM?Cfs g˧8vȆfO1j*AAARPAQYh6 شGo/\.K'[Ǐ?i$j>-3ifӹs?F1j(Խ{w!>іo?eB޳gv˗5Nr+Ri Mi"/MT&4^0n߾FMoW>'|gk֬Q-=򤟇 ۧlر0%m99+ L,wzkB-t7ʕ+uTT?%2?2u09gxvN-JMMOTt$tDрI.%DA>>>*Uҋ~SKp:A/XJai# 'Cg⬕l:Zɶe(I7$ˠ!%nU9 V,W]N8̕mxx8V׈7kR#9v?i0{~ i3H |H>O?gtBJ;w˜YЌe6l҆񡡡xdƍa.,&GD:'N Nt餤$_aJ<8zzG> @K44998p`zLmڴԩSGӴ&ͮ ٤I.ы-Znc.]tm*grg=ɪ5Hp  xZmM ;x_8e-܎*Mv9s_p}ʕW/RJJ R !%!rrUJQi.RNXΞ=+L zЀiy' a{M6W-K` s`M< 2eʔKnذ`:(kt~2lNjj*ŋڏ8** ;n8*6tyŋg8 kJ*9<((CdpX{ʚ~dsjGh-ȚT&>|y~3f̠/ϽN>:%$ٻCmΝ;7oL>fҦIӒ"Ҳe˒qft6͓,RT.|4 %4$іXk_,}'z`N/n (QiѢ8PCdtR٫DIkZn&5j:f4J & x={6ml0w@K7LCmM'&&;![l1ihtn׮]}}}D+d&7ZFT_۶m3DOC:?i JNNLd,ِ͐wyd 7L.}^W2lr[~6HT;~;Ma~)Q+RH7RzLklNSRRt~BRRMi:-Z4sLrL0еnݺQFjKT(s<8:s [ɓdZ@^Y@'j+W;k.:ŐkԨQ=z[fXc5*_ܭ[aÆiz,Ik\4kch+a92CJ0)C{u4i>ӴVTEa,;ҪsBM6w8|X[[nΝ;Ĵv:?ɜG𤸭}mܸ1444((oga\r>>>͚5C~r<Y{rsRs,SzSo#M#|H;aG9^,󍨷z=H… ޲e˲ePպ`g*0@EĈmݺ5!!ſtdž/f: PvǙ3g9B b E/}DU\Q͚5k`ҤI6СCྤፉpt5׃OKotGѣGӦM!ofX' x…˔)CT9L Zd e.LͧKep6m|||J.cRgdɒtf[lٷo &,^o&ˈjo5i*lÜC͛7Sf̘Aۭ[&MTVTRZ乮-[N:۷]ݻ7nܸRJEtRLٳׯ_ʲ95adSr!ibbΝ;kJZn5wjԨAת_~AAAaaazOxy-WyO:Hy'OB(8EU6l!_>-\pfh㤀8(p_~=s7o_zt:GTWMi۶-5n /^̆?~<6W-_,󇨐<ǏqIIIxUVi:ԩSzace={;v7n!o~Y.Mw)@$LkHF?|ڵkfj<" 6X"m3 FeI&*-ڰaþ}(o~TCcG=zcǶoQ]f6H7V.yrI7o>x ػwҮ /v׭[g >t6fdF%mOF}iq)lpW^bϓ/ zWrMv\ae?D=(=x ۶m[bԩS кuZj,YC%tO>&LXt)V76-SCsٳvڹsj#:;Ak:a\QlٲFJ*Xt~t}}}Q>yd*aV!̔gAk199Ν;f#G*⚔SNi|֬YnC_Zd~ohy0 E)I0D)Sk~̬ld9ġńy\VtK9u˗O4DBJK%Q qITB򈜒K8 ;?~\{u)SPB$tJ&<ƴ +W__ZwӦM{5nܸŋx߿[/ _,^DH"*T2‘#GΛ7oڵ{R42K*( o>C}k`jժUtiχƂrիWϏ|vڕ$@S f_;ݶ"jB CMʬ`"ȞMT^y}8q"+rJ'4+ W:v8d1Ǐ,#tg#M0ꫯh( fjժy+@-[&!!!J6~쇙76bϟ?'h]aڝ5gH^6~ _~P6?*Uf͚$Ft˖-. B% !tc#"". -ƮjV(;wNM/ŊDn[F=}hQVZ5w\A޽qv4*ZCy!iWxL-D6+14G &Ο Kwa<8፯~܁H;A )qqqQQQ:7]d f69DE[BS;wByi2tP*WBv)kTEA6ޞ?;n4 һf3 "0t.]:un֭20a K?ʕ+q{"̆΅t&L< 4ŋD… IJIIq6^.%na'I mk|rVڵJ̶/ؽ{^N^,[?=z_02J;w6{zٝF:'=gЉq*A̶v̠+!&vEG.k+W 7;~`Yb95K7'z?Id3<#eBBHR߸qÜfNEvȫ n}/ ѣ{-J,Y+8tYd-1MNNkt\3~odj#vcW8q… 52СN3@XyB^G9M%hb`cbb0f;vܴiSԤ6 M(9ED#3XgRƜ^Pɓ>z͛ ɓ&nM_>y84Gh h÷y,^-vtf7mӧv1B*U/#ZkpaR*<&Q֏ ?IN t@9Th&mX93Y6mqSLad2ijopcfi"T{Bd&qR<;gΜzL7z!Gptqñc&!ݢ"" s⇳!4OķCBJ<л/Rg_1}^:&_ߨPB ( 8=5:k6X4Ha~XT"Eʖ-[hѣGepppxx8 `` VL߽{_c 4O\ɠ A':p )h͙3'((66_V-rPB:#K@fh\dKkIec־tЗAzW B KshnB HK(0 H%z " zvo;{CvN?w^^Zj yi+ʰ`)S%0J2 Dj?(wt7ԃԦa)kWOk2-"fBRՍ*֭=}|@CUXQɠӻQEo]lYFn޹|Di)&; :ۘJۊA!mB>+<%x*T_>ǏzIIIɇ|2f2~FBBF#%xЪO>;wnժU h4Kt.@h _.AjP_󈈈#F̜9փ 8FYK9GmF qjsQKl.]ۭ\֮];(/%ȣICSS`KiC3GpuZ7Ǐ̬ 6P QIH 78yd$3XD96U~7nσzR磴hٳg#u!5 K x={X*|#1 'X|x0iPAp|/t&R/"QdI>Sx#mHY@gY@g24@H-f,4ȴ0L r˕+WV-\&9LA}<'Np @yƌݻv\F (!4c\? %M M|ӕPF`"ÉAEp!XAj _Ɖ_~y1r:j.ʸ *@FGCȦI={GQQQK<,O7o wAt6f_W%=aη(Xۙ84izc@?~2YO7K>ӌ.sjɮodY@g֭[J?4g*D@1. k曈S7L;t$r*!<+]yȑLA}޶m[`Tn]: `+hA)2>/$?XoQ|Wxx8e@Λ7/11ri"ٳ.\(AloT߷oŽ5pQreЬ`'|w*UHlʇi~hXHYf4Ku2+ݶb qxGd8iرTᬥ$<2Z2 -=STWN4iR||<СCx g#:cwMБBDgtO(Sjch4RxqtժUlӦMa.). :'ׯOZ xu -fc Ccݧ'| _עE |G}(J m4u#͕6W9S<JS}zM/̐ҦMk׮'*ZEEޜ>}'nvt% }MGFnZKIVcʆg F g=P&RP9x0TfLP{je\z=~ͤ` R6%δG9n2~CXh'F|qYt"?kE ] N+D6G(V)$2o/0?ѫW/)igΜt钖SWOĥ h PSw OY@g'3IЃZfRx`ٮI># ct…yԛ.@^@N 4]&:#Cp@tL1AbyB &"й9̷6 !m`ZiYfǎGpHh0&mp[„4CҞx8j!^SMA\Bj o#Z>8E)5hRzЬe {`p'S8u*g1rdk5 dt93 2.]\9Poر}Օ%JK4ˣ095=L" ; kgT$@a?5V Aj&͂EEE$&&n۶-55U2r3q*#G5::G|X4!5bvn~2i58Ke vڭZ;hӧ8'O^|YAb"<k)Q߀f,RZfD:hojl߾}ʕpP'ڶm[n] ,eKp(1'+SD(b۽{wppF2Zj{凤$:k֬?&[z,1$5 |NF|*lz樷فu?@)9% 4G.84nc̾={u-YЙƹsYz9,^/;t>$[J" c3{AIę׮]Js9E4 tqDrr5kb5ӔBjYs.(S%KA>#41̀6 Qp\pB»(*C1LX ڏhxJ!-s~zX`AuB QFd׮] p&F3tƻ0NYrY:eKY_U=!&v/CըQQUBLP17#'u3MFG3uƂ 2 uօRyڪjKIØ~oA'-,,G!xQ7FHoذ;v\LkqGe gϞMQaY=p/ՊG[5)G@Cq$yBBvh(h4 JC6C7 ?d{v4uƍ\;pcz SAm'W}^=?;)i@BO'<퀫^|99r כYr@+CY vĘU mU,4è0EG%/iOwm ߿/ vQ:Jf)ׯ K0RaGqhU:!|fgc> ;nAeGСCu勵:'\AU>|(F 'e֬Yٹsg0'آO\{P0< \Rk]B8%J\52ޅQJU8-"D]fzjժE9Ȧ4)TÜA#P_mΟ lذaq p 0Y uvptv3kvPG XZK.\@k0>֭[QI1(z10:g70ڬӿܛ8q")׿Uhop"NґB5jYlQ-e1nozVP5!>pUF`0!B1~x ֈGA:1Oi|Z " Pʻt!}s<.y|/bt }QNT'Sq@3KthX02'edV|X|SZ9:Z;T^MD:NNRlO>>Re\>aiUF1#laݙ o޼hgEǰcZ1,XÐ%&/IRx-ܻwojEDDt-eΎ/W3 -MR&?s xeV@[4M6t .aBq>(08'5D~YhzR2k \ӹp♲xI9 %kd7Q*0D[XKYS*4N5- M \2UޡL}sBuM8_T3NOisvL9I!)p}aDLs̪@̃zyhTnpV30pIaQ1u)d|X9gL|s\<PB)q;[S/jQLriZ16҄3(cSS5ZQ b*xa_/H ҩ2*:LzagMfkL3?.C-psv8L<ά61 `Î4|X /1:ԃk(eE(IfsL2U<>yyS#Nh=T+. ^rzSp A\an,Sm-D[9U`VB'8 53]9f J|X&Hk~#-x|Qz'N:u̙3ߩ.W\ܢ6Fkk-qޢvV5kX40L(J `/m۶qu֭]vuVuY]D!7o޼e˖۷ܹ399r a7ߠ [FbNXFHVI+k֬k9Вp ѡU` ?ŋϝ;w֬YYa36egϞ㲸8J5o޼O?t .K,YlYbb+;vرjS/}_իW8ޤf-[X4R&ue3j0n|ĉ?aÆ 00eQQQ#F9r$5jԘ1cƎ;~ɓ'O:uƌCpEm7r{֭vڻw/±cΞ=r ĝ;wDG9@,Y 5˙=ÇQ(ʃ7HI&A~u֭SN:2|Ν;w%<}:Jz!a`_SSSՐGEk|4 ,R Ӗ֬L@Cfvy`O?E8G}7]v,5 Peu]V^7hРaÆ5jҤIӦM[hѪU6mڴk+@TvGFz#ڨl$6QBBBªU>-[$''Cj4Z?~gaJikBr&Q?ӽ{.]R˖-^Æ Cl&VPtR+.+㲲e˾;ʕ{w˗/O!+VXJjժըQSra7q)^SQFO>dܹzʕׯ߶m۞={9pݻii)m1mZ[G! .?~|޽۶m Š-Z@W^su[,X_/… o[oUX%JtP]zuFnx >5={_~H"`Q˵`wP 9&Q.e#GdjРA @ӧW^=zS`AV6MIPkJo.\RSNh*L(V]x6mڴŋ'Nx۷!F֬eY@ /PqƨfK?~<sΜ9_-p|}y.;wn\\>{3gPӧO2eҤI&L7nXP2pwdSxnРAZP֒oBW_FP._|E--[F<?:u" ѿ+gXYlNyE,ؿwވ_t%MLLTX6s_^nYfժUoŊ}ٲe`"d|P45~R.RWTr)0}*5Ui+(\Z*K. EQ`Q{.m idaZt?`-ZB @[n&Jy#>vӭwNNN޹s۷nݺyf" .] %Avll, 'ZF֩SA;ittRZK:oiդIh޽{֬=NPH%J '[hѷoh^HC/^]]t.prٹsxԙ3g`㩩<Cp k.M@$^|.T]#G8p`=:vزezVoM /֒4q믿^dʕ+a4^!>> BQ_~Q-Y$Nې|xϷmۖ>}eː/H!$cy=}벻wq7n̫W^rqM'= Ѱ;v zʕ qqqlر`gϞ`wX"-\4A/RsXD|˒%K ~9bmZfttʔ):t0|ٳg^zݒ駟~%`m?(n{!߁ 6dQzɐzڵ LSݻS&MTV-Z\JhyH#""hKF/ ]f-:m@ Ȳe֭[SNy֯_я_`keqۿ )o믢N- وntk.^GYC={ԟ}٧~5jԀHZj/^˗/@FS}ҥKרQUV=zx);^ ?h1f-3:mB@wީW|ʿpw}W:_eʔUVv7yde#un%{c<% l*.S*c7\oݺgn߾畼0)U HY*Yo -c!l5br$uo#B@盞rz4Uv[:IZfx1^z锔yƎۻw6mԬYt҅ eamܸqns̑%9I|gBŌ"d(!KLpe~o̙3sI><4FLqZy3o$wx@Y))a+2fFy"#']棃[(H7opϷ0lo-Lt[GS`pĉ]v3g1bDDDDfͪTRDi%#Knݺرc| Cl2(eucmeGChOg2Q`ߏObt%''Ӫ;w{7_ܻw/?tѣGx&k]3_Jcgue)eAnYK waMkAw|>:p}D(u1l˖+ OJJ'#5]7$?V?r \6eIJ/-FQ#-I{-[lܸQ7]8pvG>zj1LҿvXl}HfyU-l f4 hϣ`%\F@!xn;>>~޼yyIplwẗ}0ߡCI>?f̘ &Q< -(FAmHL礻z#3 *A'F)`ev\]T1bİaA9Cyt 1}D( NwnpOO~|3F{ )\;V7tC:( "c| ^%=х }/ ۡ}Bg#M&,4,D[s,8q"2={ڵkΝ;vȠ"h׮][iF?~}$Ǔ EpynGY&b45e$`!L+FF֘^ %b]xt1eӥ_V^Mpi1 hC۾}уҥ s֣k8̣$+9ˣ& )o#l*HO tp@n*:Zf^2nݺ]w֭RHFdƍ+VXhz|XbUVmٲe޽a /GEWYHeM'i cH3eG,3h^f>sInݚQFׯSc F TRrʕ\F3~5j|AsyCjdϷ0MLL eT4˗̔Ykz}ofPY L ginLpx$mѢ`Æ jժYGTVjyԪU+ ޡCz vC7HnJ9P1O-KV9O: Z`#LP%Apg 2K.X` [$ .2+':ͫBd*sٹl(yϞ=BҥKAikݘΜD[ӦMj3aaa ڊTD o[o~-YdRʔ)S\9.@ x2p[""" z IH( ]CcG'ꫯ(3ܙ02zy޽7n0f$ʕ+f{eڍђ'-_g hf!&f>L?wx*' +s+&_D3s̉f@ӧsΠQFx/|EΒ6b隧>&L-@0q ~QTD ~!2 zNr*F rSSSnݺtR(ЫW/G ?WZ ƬU@ig] QFL m@`7HN8Cb.!yI&M:thϞ=)9@ jz)32c̷0FoMLMIPN:Ԉd4N:h^ 鬭tYkbZj…ӦMϡQ9,,Lz.jA}teZfM… +y8Kʬ%fsV;='aD(ᅬG-:m`N4a@/z*BlΝ _BK0D(^V9N G4 }Jnwsg7w-=g FGG3 tyZ5j=|dw}zJpTo jGǂ +| ̧ky`xAv2Lm@zcShoϟOuUkӦ bŊPPh#yMD^i>xe]|C _KKefxLU!MD?tN:1I.d/ vOqߒ =謝[2 Lypƍ߿?FVQ*9#p^)fb[lo_AXs4z1UhQzF͚5ҥ OizC @?]QOg>L3Ǽ*x"3|L!10VڪU+-C;Zg:#f͚5zhhРAJSJfiv`LlsDtDI&Mύ5x;:lR fb}=΅ Jr@uRRR,5 h\@s]vĉ[lIHHbF!\{bEЌ *=z T-ZtaڊܳUu11l .DZ^ݻ7djHRK+|Ҵ VJJ-ڶm \gֽ{.2~С 6x&) hPٯ_?Mݻ?a6gFhoi J;Sp}S`%$e4ǭ^O[͎rp踶2(1:N);tD(g4D=E!?~/J/3ڵkh-oavZbŌ3h%ƫZq|VcvCkQLtUfJg޽{%hE֬YCItfVXq*ljAh⟴M*֭[3u֫W/d!CܠǺMZI@0|GZlLOJH0hjhDiSꅡsT.rdΝ;NA⮊+F!e";ЄL&}Dk, PNA"atw Dɞ={Va7Nٔ߃>Z,d4 rDo@v]@f*r0ك d,Z xazS}lV~ NLKoe1P M0aʔ)111&0_m̀4cO*'#Nb iI9`NFC'08qgϞ5Y{䅡6d>c)(eM@ /oP .=Г A#}Dk1NJ̜9㲸8KKzP92s . y,G_+?3GGAlllbb֭[A0 hfV9;zQ;&O5#%b:bjU1I6Izc/ ̙3{՝4qtw}j8=s@3$)L`׵|r]BO;.Yd GP{ڴi8Q_D3A> ,zX@1 h!q-[>}3<* CY긊 {BՁZܺu 6A1>>tt~hѢh.LLKsU@éTYW8p61MyXsxzArz娨Fd1dAlt .ene?ױcGB4/)D  J\2sF8d@q@;3 ;w)AO8λ% :@ҝ4/z˘#"m1m$fi"iԩS ec 5j2@"jE pݴiѣGOvJD-ne&2&@v6d@s Asz%e3xnC\& rU3mO;A[4K2T1ٳn&E SvcnTsۙ.p߬__\9mQfid"1@a̙3Ʃ]vҥi( =6r,1ߌ cqCqӧav2Q[榘q*#EN81...11QӞfP1L{w3.gnouEOc8 y|F{uvƇ׆\3ul׮]߾}w=|Q.s9ss;ͣG>@MD("722y %K턼+K'hiOgƢw`JL ʺh20o]vm'Pv |% 3#(<恴' .F8̽X@1 @LӉ `eDx4bĈ.]PqJWQs)y?znLsA4% bs=vօ ƍ)4)A DľlOB`5km۶GQQQf>S2]Qaa"@P1̘^F='. LSDJO:ZjiI s&Q/_>]8;u4h U(Mt(h#7SG-=u/|YBb>i(K)󕋕iNa%xʺ7t~v 4|*<\"Wt v0+2 @L֙oF!UC GP &4.qsx@<9N&%ꌉ6lqtÆ ˗/U2K⃗_~)SF[h= eLսSTrfsޅ>xIDx>c f>6qʕ+iYfXavtP~[h^; CTR;<7}e&峥ٳa Sh(Df&&A_{0}s2xk* [5>Uw@H“f|yu-EQ|k/o2Q(עE;́f͚UX1 BC*Fv͉ :op8D&N= at&j+2 h]͠R|['ߛǭպ'pcK.-[Zjɒ%V CZD}&_thaT)2wgΜqsqJ*!߃J=@uk׮W^fK }`N黏ݔ&kK5`2Hx\qݱcǔzҤIs. X~RLаD4QJ N |RjӦM8p O *7o:Zb/^\Ur&M8:zvzDx2?{,fGl'`ṗҘBU}َ;,xn]G̑#G~|q!_ziЙOLLDLVO+/'qZr.Fׯ#Ұiԩ(vr[[Q|ΔI0b׮][2^`#% RC[6Pr-nh} ,,̬N<C:| gPr3MMc}Ih XՂS-th1TR {Gf |%M^HS$699yժUT4hЀvF @^ \q5jhӦL PMpohLNˌ綀ocFڊΤ2ѡw/+Qs?0`bA@ RzAy˖-)S|Qj>^=)-C삠7l+Eg]yh|FG޽{C%B )թ]4 kt폧پ}SDzh $/0aiժcI;7\йvF^G9^F :W_ݼySq鷂N<>3bݴ1BM Uyj uVPUuH}ܹ&7SӟWbtwQdd$T⫐@MY{y^.@FO: nNTTT׮](qS'D[:cƌшUF#3#)itc ) sgp}uRTlذ!0IԶg[w.f1j+zȐ!:tUR&4"vΜ9c%4˗;S| ZErҿuԡ d;OyΊ8w)͓ >&MMRBIi}ksj4}tD2&3nq4Z}F>oڴ)>>^u%榷PzZ(Rӧ '}BBBRRҁғ_eA1 hjA]n߾*b.Brذa:ubz蔇߳*4Bd^dɖ-[?XV( w[7ݻ#u_:\?~܉m{)ɣh+iGBLT|X*\"qqqTоE: I}D+1762Džt2(.݇S(by <<\GڗR@B7nRzΟ?!#܄u7 h =rasVE֭"c\W0Qthٲe>}POH)a;3JihNtFlO]F>c #u6^fL~z9EڵKRª ^V$J%:1\@LLJ@ eg .6,, wܙZ;Ԃ6ǯ\r=t~bm*J:vC̝;wĈ hS'N$uq@렚2J#-Z7Q3 (sHf͐(Mu"`4rmN~'Ёx#fy=:22rRZW; &@&ǤH'6[ZR=b3qXoӦ Ust67JH(X .9K. io|IR޴izڵkc%J x׬YC(;!nРAr *Cf۷׆˗o߾@SB0ZwhCfm݌[.YG~̽;)`D4c[ҵnͭPĽf}C3GQ:NSsZ;Os E3^7 h :3CAk}C=ƎۣGL{v`j<^f^|dj JD vν[^Iʕ+{~h= кGG0SA7$4i".)))-nhOz. h hj;t%Q_\rZkF茯AkBjK̾zjӶ~~}73v:txff ~+\]reLL 4 `yZPw}aÆtȑ#WD9sb%ek6x`L250uFC|1u۷fMyL! u*4RSS͵ݻwעӛo7ooMsn?~E4LfmZ) õn.>"HZB.zhܸ C<^ɋd!;}\vlʎRfM^BF,ƍ[p!-Fz?(~bx s1#iS_.կlZcmQ}t: loЁ[PeQ۹tyb"aÆ@r(ΧtiСѺU@7x4Zp[iѫSg;USKh͸8N7 c&EU-MZj*U,= ?gu͹sx6:*֫@dv$&OWZ5uT-@묚 vfZoL:tiSUYgwzOh[]ӫW-Zc UZhNi۶mwrY&f$$Yw~R Q3_2^rرc[lIHH3fLdddӦMdY%70ʿU 3ٯ"Q6JH,BDB)~~O|g155l8u^q$Hw}iZz9s5kRRR=o<7 O&Iǎn4@+뒦W\Ikw+[P?tPRR… GdiʕScÅ 8pƌ*s< t@(vq{ZAEԡݻ;Vz89Hek[e\{\3f2oh^+bX[祱:v 4-3tQC L'IkY6}͍J-_Is긊22L-)atAgjtD1B fɢES}rՀ6#ҼF^y e˖E:!oAl.%|n2ߣC)!B'[` c57b%4镕bn[MdN/Y1Lzؠtm۶8qڵk>ط9fif.MLLԥmڴ X5kׅ^>#zlr|`*ЦC3(kĹX{@kɜ'4wޭguì\r9oPv˺nXrC5 \ hs~Z/j iٲeʕ~/\6n8""bʰLs9g+Fӡzi apRHJ`#G(QrFJt_󄔓ꥨNTY 5rt[j&NLb`L;ۋkG`JJt2 M8""~:?mvtoigW朮iTF 09M#YzR~۹L +T=vƍՠf*ah׊Pv\)9]zuL5Z($(Gl5 ؼyJ*vD3c3J?7gY@^@k˭[ 6ԩS'czcn&+V$''#2*޿t#M$)ML Dž:u*D@UJS:9w׬ fwDm:w4y9k 1ݟ㝡9=:ڙml4UC~?s Lvg.^-v2&V~M2%11qΝTh6oF,+4kp013G۵;~y1Nq&^tJÆ ]E<η)M `́>2bй)GN)#pVʕ2chU<=',.ʑbA,s|fv$ɓ'q4~hh)))&#OP.'5,J:I8 DGGhgVx|;(8̵\J$7ɒl+ITM6 \hљbk}֭[JvZgȐ!;v4٥uGmg*>5+6- ON(g6PK7^6$WM%Y`6;+۾}{bb"a%hclv6h4 hoZ ISV{cUW斿:(:M{ns kPgXx_N@ef||NӘ7fh窎w>Z:?f<Š>+Ve $O@6M6ÇϚ5˙Z H<]|}wϟ?p\[|S>`g7. ' 3f̀Z,jӹc3t:47kn"()u͍!+Z '0}C&KFeڲ7X@ @{g"z.99Y7.c ߀ i2,$B qm (3m6m=#""P;LI 0СC <eƕ@~NB)/o߾+t/XW#{ 27z\f6xtn ,s)0{*J[u;Iʕҷwc}cʕY {m z+oٳaNСY`Rѡ1bܹsu@M}7_n]\\eҥN+O[KgҤ i̙3g:Ԥ prȑ;mm34yBˬ^ҍ9R۟}=ȤM4q뱾yL_x;vR>:ԬSM:`QqD޽{2(J"Q@ĩ*)7X ۷/(ItZ@qkkk `:Us65 n3ϒ:\`ׯZjʿCq3QdI.(AcĨ`|7Mjs؄~Y`B~͐PfA4Q)i۷7˻,x -Y~k< n'ܬ :WZ٬>;3[nT1Ig$AÇK>oF눁av5hۙ6n~y\Ä:5 f (ttJ\}W:BmjʹͶŒNq޶NKjs#rq{,Zʹ(XX3 hA֊DVڵc:И~_nlUVTUN}Qpgrرcˁ@UTNu3/I";L+B{sNN^m9$׼y OF_fM]w#'57Fj|[@~Xܐ|(Ps{ʕÆ #lԨ3"Է13e:ypIVJAB$Jd,B6`[&` @9f ^Pd""0fp&$jG/|33ϓ}߾⋛˟#E@ET˪[UuM2Ev{g#*s6QGu駧Ϧ A2\ϋp\;bĈK8n9Agn,̥*'q9 y2 r2jٮ+os0'2UpYf9|~|n?,P99)?O値$hR6YfŊH'3O6 eSds /fegsuDKKMv7gF7-oƥ<zJ.>}j?kp֜$P /-?uk[D%LPfnP]Vdɒn N|HE>Gs=$9a^E% i5qfODtȞy¡b,AY_q>74wҙ3gfwi!n C=DO<9&gYl@%I .$&t9昌>y^>lN9蠃9Rkx in+s<ȑ#w}?dUV%!.ޤcuwYo 嘤!rKɆo$bf&$E}ݧQ3EK][u>*AC.2Fj2}Ϟ==QdB_r.]t>G'}>(۰a4SV> ֭i-ZDgn/- ;yDrތY$+駟^Vm?hz311Sk~75k~g5ti5jԄ x-U>ede.EN?L),Y"\yĉŏ*JFd ˉ']FҰٜM| O\K$~zKd }#8Sଧe3ߟA-ڵ9-9ɣʗ^zisړymݕahMrwr2jۥ>22#} pT&\ @`GyyE쩧9rzjhG@/ra^z.fv2%p3fL;#tw&Ri[y9#;F?W\"US%WVD țtVC/[L]tEpNwT@63I-Rz1tRot {=zcY򜑍h_~YЛ(UCٸq1B n"C=UxmѢE+TE>Rlܴ,;#Dlnrd'd=il^6gJ.(Riэ~$͟?4Fd|C9餓rP4/R-l9{/ۈJv.3fH4m:Y&@G1J6A7s$+9 u13k֬ɓ'cXfx-mX4\O䐊S怞,m3ٔizBr(roj")""'^r>oۏh]M7ݤYfMN]yk9> j@IY.xhm/NQX$HJ*A7Usl<P5y睗^z)p«?~~%vavGFo[7Ν;{Yz{aT\[p[Pv]vYfȴ8;ZvBTgo8)%m/BpH4- jZYЬ5WK3 ѾCz[~}N(;Vr@ʶhM;v,5pW_3P:=GWNnV|G$z;'o>{l.z7g= `tB&UR4{w7|E sZZu0Yӝq۬JЧve]VKZRGRs ;gD>KK.Vi[o4/dtK+d>7g/~V.}EoiPqN:E=C舁Rѕ%3M/*bRi.[l;k>"Lԛ¸?m)K*:,2n:1/l?}#LPqsjsv5\SD ljdy67X0mCp-׾{Lo_z *gzEAN++[EaÆf"3J>Oh[SdĠΑD_yMGhB_? ?(;J-Cܑ} 5 J 38`"-;'Gq7er,Rz7x9f2q`tu<\8g?IE F뱥"zvژsEdEZ*uth4PQ=,@jwqN#5=δ&TU;w.)ustK{vfJ).^o:u*J9z6!sHiOOr-MK,f$zͻKO9ҾإdeOuQW_} ^z::(:4pˇ;ˣRz>ďϵݟ9? [ gΥeSS6J\-@*PIq)S^O9YftILJ8}Z*P%$8zfLl5jԉ'H̜9s"M lK:zƖhoф\YyĈ,V޲G{sΙ>}z_*MVg?fQ`^x^t rŚɌn"+msE>M҃teLIz){mX0!3C^\rijUwhrAL/OcC®OKu-̼.3VpYrEr #&ʄg1. h!m: D%Z]გx (:f Rƒ2]IT!eO/{"\, u)yrԯ֭_Eh]8qJ=# s@qJn'|a8[_vCD)#b ??`upR~g4DzxŞ`&L_?k֬Pĉ?ѣGtAHVͫ;І˚lpA2;x޶ lMn9Z0t?dd 퍣Fˢ|Gi4 g#h)MRn]-l- I;jsϥ4 n4$^Fҽ|ޕM{ ]k`{~9?+:pt& -UNiW| vb)ZG?{ RK6kssIlz,&>0u xeA_͎bVtJ=#;ȑ#:07oW{pe63ly>x͚5ޜ4|}鸣$5S 0)EPt"V6͠su鳣F:<ótʕ^7ސKjEh̰bʬFz0Y:h4Fty䑧r Wѽh=9JL B3[ЖQxH΋-Rq0\;e F"y g&'+[^弁ŷ(J\Cn90}rt G?Wh,Lx)\)3Keg/abJ 4)^}$l[o U1RaHSH~B6i@pNWK+A &×62e W/& ]:dViĿ2G|}M7A^T ZԾL%ԅEFH&,qe]&)sNl,Vs5g6m㦍]r)rVqGIg;ki,h6W/IHgq@BG?>ǒ;Uý׬&g*LBTg)[i2ʹ[АP}~]w rTti%Qѡĉ?|uuq5q676.y^` 3/fϞ\r ʠġlAz%n^{%PE4d3xied#C21y/9:U-muWk{ WS^s5zM:DOП0FDSP@sʯwyGG?#39:c8{3`۰9#eҤIrr1Ys=B́ JU$wi đM8E¸43 mat˜(U?}:uw`5Z~~˦h=e+F#'3qԬnEKG)YӀti%^,i 2񃿨Kнvv7erlQfao Լ|t7,蓚S3|$6D>i[]Gwvea l-,YJ2ۛNF5jԸqN=TV>}8-hZWt}Mv\Ư/.P ~O/g^WmՂ=;I9)}>֔;iÏ9~YvmfڹO՘$m.(馛uf] SG1"uħ&\ye8 ?@4 Iˆ<*ջQb;"a =pz9K_r'rչw9zF*q RI0/9d5("a9:˙q}2g,[K%}*(Ƨrܬ~ AK{ŀtIјQ rA-׺!,<4f~;1/"PXc|_Ǜy >aNYD2Qa-{ڼl\_hTJ m:ʒp<1ɘIw)e'İt|/ AO+pFt=r5(+گfȦDrP=gl)vI|wr̪LaKlM#8!%+@uD|rST_=)eOc}2dqb5+Ks-) ~J0 ]@S7?&|c=vB}| b 0oor͐6X >~>;`rJEY ePs[. M~rU3qv&ڌ$$hzZ!>2✸n7SA|^ -!umrFƱAvjlmҜ$lDVR~vE? >$h4KѤWpc]C91]8 QKQRziJPHQ+k/l/~Q  A7@rq~{Agj<0]@qׅzap-Gת VHd̙םwIш_|7(f4Aʁ Fg޳>VhD)JlY)f{h1 3&d ~ZH l-'w!B^5^jHfꍏY.blv~ Շd蹍]^,{׮]HˁT*ҟEEDE1kًQ'oIԯ;d,1|@HLKʥNG !0~b8U8eŋOݣ[wb~`+UdzRG5'g̪Kɫ`5O)aq18y:>uyC`tgd ̥2#y{-3$U٤ʴiӮOQF|_one޶.|kY%Yzn{nNžHVdRIBqq݃G32_(_2^.azSrfӧ?\tC=30_sQ!7\K}û~Zj幒MIE9C9uzσ +U/^Cʵϲ'Ұ|?eʔ\-,Xn]$Ø/܋^&@H6y-kҤI(k-܂6-lrb\"?G>IT- _YXMZ6G%㲬7!w_pegƝ7lؠViȝئy /KsoJqzG|Y2b23LJK4>쓓 Z.5H: ř` &@ON`N.[ہ=~WiZb:l YQjdQ;s('/t%l"oZ+&M˜ Qϝ;w…ٝ{P/~ٵ:㸓(43k9@.7^y*"O3f$c3] Ԝ)r'l62.i&apTɃAN,Xpw?_~&NfG@E{֭{g8]NKU\ve8c?pvY/-vr ^9@ob0ˉzX%ʚ9yoÙqkr݆tjFې"+˒(%v@Y*=l3;vE+ry!/p $3l2L}Bz#rf=(D̆0ZUX[o%8C:Yo#J`2叽vhI>X 4Jxz'%)>l6B$,d{. Pwh> 6(vSS yq/"T9y2~X".Y3.'K)UEeJUa@ٯFJ(qH&dzN29c+)Ħ8$?h;+45$j 02PZVM6cƌk?.]}qf|שf尒5A\4utpk4N;H Lw뮻N]phN2'RɑlGojP¿9SY3s*&́2H/yH!\WLdz'o 9+f %h'xonq{g>Jbl,] zH(>U 2x3RUJlg /VP5dž-A9L4)&_x112sL\P7!&tAz꩓&M ٥;饗^*]L)DZ{V+9GeN ~qgC dH:Cb Mw}7*䨶K.D$Hd]N ܚYB#v4vBY珳t)luAe_ĉIfWtWӏ-Im!ߍдKJ)H dv)tL#ORvb.={6jN̠vVjzU;sO sREK,{/W\ b"t/!rG =Z8)3=pK-YScZm .bU -i ?^pl тa&2GQb: yVF`ELVI:^bJI812eA)#eUb8zܕMӸփ4fIbZCεx'.["y[-DRVg^f[gnذ!tP(eC)CFSxA cX:Μ9S+h_2+|#{G!eDS.gbt$C2sP9c(-3M MGMMej&(N jg̘.4-6,F)E .< FFob/s9MB΀tΰ%R4hE(Wҭޢ=s#.n~z/&D9\@|C4|U*zS9z)n"t s]Ĥ4=%QdQG8nVvoi_}Čh1z9r 14/U e&7j~6mKg.DBG\.)*:%ܐ"-F._5S>nQZF #ɚ[9'AWTl.znBօJ&G]]IUkC6v)IYإXpq#1VSʽtEŧZR f!?!?/S}}(t Rhb4G[dhR t#Z>2Cڬm=dF>`iCצP CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ CQ C \1qIENDB`pasdoc/source/gui/frmhelpgeneratorunit.pas0000600000175000017500000014223612170540073021527 0ustar michalismichalis{ Copyright 2004-2008 Richard B. Winston, U.S. Geological Survey (USGS) Copyright 2005-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA } { @abstract(@name contains the main form of Help Generator.) @author(Richard B. Winston ) @author(Michalis Kamburelis) @created(2004-11-28) @cvs($Date: 2013-07-14 17:14:03 +0200 (nie) $) } unit frmHelpGeneratorUnit; {$mode objfpc}{$H+} interface uses SysUtils, Classes, LResources, Graphics, Controls, Forms, Dialogs, PasDoc_Gen, PasDoc_GenHtml, PasDoc_Base, StdCtrls, PasDoc_Types, ComCtrls, ExtCtrls, CheckLst, PasDoc_Languages, Menus, Buttons, Spin, PasDoc_GenLatex, PasDoc_Serialize, IniFiles, PasDoc_GenHtmlHelp, EditBtn, PasDoc_Utils, LCLType, SynEdit, 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 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; // @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; EditConclusionFileName: TFileNameEdit; EditCssFileName: TFileNameEdit; EditIntroductionFileName: TFileNameEdit; // @name is used to set the name of the project. edProjectName: TEdit; CssFileNameFileNameEdit1: TFileNameEdit; edTitle: TEdit; HtmlHelpDocGenerator: THTMLHelpDocGenerator; LabelProjectName: TLabel; LabelHeader: TLabel; LabelFooter: TLabel; LabelConclusionFile: TLabel; LabelIntroductionFile: TLabel; LabelCssFileName: TLabel; LabelLanguages: TLabel; LabelTitle: TLabel; Label20: TLabel; LabelVisibleMembers: TLabel; Label22: TLabel; Label23: TLabel; LabelLatexGraphicsPackage: TLabel; LabelOutputType: TLabel; Label7: TLabel; Label9: TLabel; memoCommentMarkers: TMemo; memoDefines: TMemo; // @name holds the complete paths of all the source files // in the project. memoFiles: TMemo; memoFooter: TMemo; memoHeader: 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; PageVisibleMembers: TPage; pageDisplayComments: TPage; pageDefines: TPage; pageGenerate: TPage; pageGraphs: TPage; pageHeadFoot: TPage; pageIncludeDirectories: TPage; pageLatexOptions: TPage; pageCustomFiles: TPage; pageMarkers: TPage; pageOptions: TPage; pageSourceFiles: TPage; pageSpellChecking: TPage; PanelFooterHidden: TPanel; PanelHeaderHidden: TPanel; pnlEditCommentInstructions: TPanel; PanelGenerateTop: TPanel; PanelIncludeDirectoriesTop: TPanel; PanelSpellCheckingTop1: TPanel; // @name is the main workhorse of @classname. It analyzes the source // code and cooperates with @link(HtmlDocGenerator) // and @link(TexDocGenerator) to create the output. PasDoc1: TPasDoc; // @name generates HTML output. HtmlDocGenerator: THTMLDocGenerator; OpenDialog1: TOpenDialog; RadioImplicitVisibility: TRadioGroup; rgLineBreakQuality: TRadioGroup; SaveDialog1: TSaveDialog; OpenDialog2: TOpenDialog; MainMenu1: TMainMenu; MenuFile: TMenuItem; MenuOpen: TMenuItem; MenuSaveAs: TMenuItem; MenuExit: TMenuItem; MenuNew: TMenuItem; seVerbosity: TSpinEdit; Splitter1: TSplitter; seComment: TSynEdit; Splitter2: TSplitter; // @name generates Latex output. TexDocGenerator: TTexDocGenerator; MenuHelp: TMenuItem; tvUnits: TTreeView; Label12: TLabel; PageSort: TPage; LabelItemsToSort: TLabel; clbSorting: TCheckListBox; PanelLeft: TPanel; lbNavigation: TListBox; ButtonGenerate: TBitBtn; LabelOutputDirectory: TLabel; EditOutputDirectory: TDirectoryEdit; Label8: TLabel; btnBrowseSourceFiles: TButton; LabelHyphenatedWords: TLabel; memoHyphenatedWords: TMemo; LabelCommentMarkers: TLabel; rgCommentMarkers: TRadioGroup; 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 AnAction: 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); private function GetCheckListVisibleMembersValue: TVisibilities; procedure SetCheckListVisibleMembersValue(const AValue: TVisibilities); private 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; procedure FillNavigationListBox; procedure SetOutputDirectory(const FileName: string); // @name fills @link(tvUnits) with a heirarchical representation of the // TPasItems in PasDoc1. procedure FillTreeView; { 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 UpdateSettingsFileName then sets SettingsFileName property to FileName. if ClearChanged then sets Changed to false. } procedure SaveSettingsToFile(const FileName: string; UpdateSettingsFileName, 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 Changed: 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 open 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 LCLIntf, PasDoc_SortSettings, frmAboutUnit, HelpProcessor, 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 EditOutputDirectory.Directory := 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; Changed := true; if (memoFiles.Lines.Count > 0) and (EditOutputDirectory.Directory = '') 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 OpenURL((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 EditOutputDirectory.Directory = '' 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.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.PageCount -1 do begin page := NotebookMain.Page[Index]; if page.Tag = 1 then begin lbNavigation.Items.AddObject(page.Hint, page); end; end; lbNavigation.ItemIndex := 0; { otherwise it may stay -1 after program loads } finally lbNavigation.OnClick := @lbNavigationClick; end; end; procedure TfrmHelpGenerator.cbCheckSpellingChange(Sender: TObject); begin Changed := True; end; procedure TfrmHelpGenerator.CheckListVisibleMembersClick(Sender: TObject); var NewValue: TVisibilities; begin NewValue := CheckListVisibleMembersValue; if PasDoc1.ShowVisibilities <> NewValue then begin Changed := 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 := ''; EditOutputDirectory.Directory := GetTempDir(true); seVerbosity.Value := 2; comboGenerateFormat.ItemIndex := 0; memoFiles.Clear; memoIncludeDirectories.Clear; memoMessages.Clear; memoDefines.Lines.Assign(DefaultDirectives); EditCssFileName.FileName := ''; EditIntroductionFileName.FileName := ''; EditConclusionFileName.FileName := ''; CheckWriteUsesList.Checked := false; CheckAutoAbstract.Checked := false; CheckAutoLink.Checked := false; CheckHandleMacros.Checked := true; CheckUseTipueSearch.Checked := false; for SortIndex := Low(TSortSetting) to High(TSortSetting) do clbSorting.Checked[Ord(SortIndex)] := false; CheckStoreRelativePaths.Checked := true; Changed := False; end; procedure TfrmHelpGenerator.UpdateCaption; var NewCaption: string; begin { Caption value follows GNOME HIG 2.0 standard } NewCaption := ''; if Changed then NewCaption += '*'; NewCaption += SettingsFileNameNice; NewCaption += ' - PasDoc GUI'; Caption := NewCaption; 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 MisspelledWords:= TStringList.Create; MisspelledWords.Sorted := True; MisspelledWords.Duplicates := dupIgnore; 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 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(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]); MenuGenerateRun.ShortCut := ShortCut(VK_F9, []); // A Tag of 1 means the page should be visible. for Index := NotebookMain.PageCount -1 downto 0 do begin NotebookMain.Page[Index].Tag := 1; end; comboGenerateFormatChange(nil); FillNavigationListBox; Changed := False; end; procedure TfrmHelpGenerator.FillTreeView; var Lang: TPasDocLanguages; procedure TreeAddCio(const ALLCiosNode: TTreeNode); var LCio: TPasCio; LCios: TPasCios; I, J: Integer; ClassNode: TTreeNode; FieldsNode: TTreeNode; MethodNode: TTreeNode; PropertiesNode: TTreeNode; TypesNode: TTreeNode; PasItem: TPasItem; begin LCios := TPasCios(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 EditOutputDirectory.Directory = '' then begin Beep; MessageDlg('You need to specify the output directory on the "Options" tab.', Dialogs.mtWarning, [mbOK], 0); Exit; end; Screen.Cursor := crHourGlass; try memoMessages.Clear; 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.FileName <> '' then TGenericHTMLDocGenerator(PasDoc1.Generator).CSS := FileToString(EditCssFileName.FileName) else TGenericHTMLDocGenerator(PasDoc1.Generator).CSS := DefaultPasDocCss; TGenericHTMLDocGenerator(PasDoc1.Generator).UseTipueSearch := CheckUseTipueSearch.Checked; TGenericHTMLDocGenerator(PasDoc1.Generator).AspellLanguage := LanguageAspellCode(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 DirectoryExists(EditOutputDirectory.Directory) then begin CreateDir(EditOutputDirectory.Directory) end; PasDoc1.Generator.DestinationDirectory := EditOutputDirectory.Directory; 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.Execute; 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 OpenURL(HtmlDocGenerator.DestinationDirectory + 'index.html'); finally Screen.Cursor := crDefault; end; end; procedure TfrmHelpGenerator.comboLanguagesChange(Sender: TObject); begin Changed := 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.btnOpenClick(Sender: TObject); 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; if OpenDialog2.Execute then begin SettingsFileName := OpenDialog2.FileName; 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); EditOutputDirectory.Directory := 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.FileName := ExpandNotEmptyFileName( Ini.ReadString('Main', 'CssFileName', '')); EditIntroductionFileName.FileName := ExpandNotEmptyFileName( Ini.ReadString('Main', 'IntroductionFileName', '')); EditConclusionFileName.FileName := 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; Changed := False; end; end; procedure TfrmHelpGenerator.SaveSettingsToFile(const FileName: string; UpdateSettingsFileName, 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(EditOutputDirectory.Directory)); 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.FileName)); Ini.WriteString('Main', 'IntroductionFileName', CorrectFileName( EditIntroductionFileName.FileName)); Ini.WriteString('Main', 'ConclusionFileName', CorrectFileName( EditConclusionFileName.FileName)); 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 UpdateSettingsFileName then SettingsFileName := FileName; if ClearChanged then Changed := 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 Changed 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 AnAction: TCloseAction); begin if not SaveChanges then AnAction := caNone; end; procedure TfrmHelpGenerator.MenuNewClick(Sender: TObject); begin if not SaveChanges then Exit; SetDefaults; SettingsFileName := ''; Changed := 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; Changed := true; end; procedure TfrmHelpGenerator.lbNavigationClick(Sender: TObject); var Page: TPage; Index: Integer; begin if lbNavigation.ItemIndex = -1 then Exit; Page := lbNavigation.Items.Objects[lbNavigation.ItemIndex] as TPage; { We want to set NotebookMain.ActivePageComponent := Page. There doesn't seem to exist a comfortable way to do this (Page.PageIndex was removed, ActivePageComponent is not settable, our lbNavigation.ItemIndex is not necessarily what we need...), so just search NotebookMain.Page[] for the right page. } for Index := 0 to NotebookMain.PageCount -1 do if Page = NotebookMain.Page[Index] then begin NotebookMain.PageIndex := Index; Break; end; end; procedure TfrmHelpGenerator.MenuContextHelpClick(Sender: TObject); var HelpControl: TControl; begin HelpControl := nil; if (Sender is TMenuItem) or (Sender = lbNavigation) then begin HelpControl := NotebookMain.ActivePageComponent; 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); OpenURL(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 Changed := 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; initialization {$I frmhelpgeneratorunit.lrs} end. pasdoc/source/gui/helpprocessor.pas0000600000175000017500000000613610332504132020143 0ustar michalismichalis{ @author(Richard B. Winston ) 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; {$mode objfpc}{$H+} 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; 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/gui/frmaboutunit.pas0000600000175000017500000000430612170540073017775 0ustar michalismichalis{ Copyright 2004-2005 Richard B. Winston, U.S. Geological Survey (USGS) Copyright 2005-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA } { @author(Richard B. Winston ) @author(Michalis Kamburelis) } unit frmAboutUnit; {$mode objfpc}{$H+} interface uses SysUtils, Classes, LResources, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons; type { TfrmAbout } TfrmAbout = class(TForm) ButtonPasDocURL: TButton; LabelTitle: TLabel; BitBtn1: TBitBtn; MemoInformation: TMemo; procedure ButtonPasDocURLClick(Sender: TObject); procedure frmAboutCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmAbout: TfrmAbout; implementation uses PasDoc_Base, LCLIntf, PasDoc_Versions; { TfrmAbout } procedure TfrmAbout.frmAboutCreate(Sender: TObject); begin MemoInformation.Lines.Text := 'Authors:' + LineEnding + 'Richard B. Winston (rbwinst@usgs.gov), ' + 'U.S. Geological Survey (USGS)' + LineEnding + 'and Michalis Kamburelis.' + 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 OpenURL((Sender as TButton).Caption); end; initialization {$I frmaboutunit.lrs} end. pasdoc/source/gui/pasdoc_gui.lpi0000600000175000017500000000715012221630742017374 0ustar michalismichalis <UseXPManifest Value="True"/> <Icon Value="0"/> </General> <BuildModes Count="1"> <Item1 Name="default" Default="True"/> </BuildModes> <PublishOptions> <Version Value="2"/> <DestinationDirectory Value="/tmp/aaa/"/> <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"/> <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> </local> </RunParams> <RequiredPackages Count="4"> <Item1> <PackageName Value="SynEdit"/> <MinVersion Major="1" Valid="True"/> </Item1> <Item2> <PackageName Value="pasdoc_package"/> </Item2> <Item3> <PackageName Value="LCL"/> </Item3> <Item4> <PackageName Value="FCL"/> <MinVersion Major="1" Valid="True"/> </Item4> </RequiredPackages> <Units Count="6"> <Unit0> <Filename Value="pasdoc_gui.lpr"/> <IsPartOfProject Value="True"/> <UnitName Value="pasdoc_gui"/> </Unit0> <Unit1> <Filename Value="frmhelpgeneratorunit.pas"/> <IsPartOfProject Value="True"/> <ComponentName Value="frmHelpGenerator"/> <HasResources Value="True"/> <ResourceBaseClass Value="Form"/> <UnitName Value="frmHelpGeneratorUnit"/> </Unit1> <Unit2> <Filename Value="frmaboutunit.pas"/> <IsPartOfProject Value="True"/> <ComponentName Value="frmAbout"/> <HasResources Value="True"/> <ResourceBaseClass Value="Form"/> <UnitName Value="frmAboutUnit"/> </Unit2> <Unit3> <Filename Value="helpprocessor.pas"/> <IsPartOfProject Value="True"/> <UnitName Value="HelpProcessor"/> </Unit3> <Unit4> <Filename Value="preferencesfrm.pas"/> <IsPartOfProject Value="True"/> <ComponentName Value="Preferences"/> <HasResources Value="True"/> <ResourceBaseClass Value="Form"/> <UnitName Value="PreferencesFrm"/> </Unit4> <Unit5> <Filename Value="pasdocguisettings.pas"/> <IsPartOfProject Value="True"/> <UnitName Value="PasDocGuiSettings"/> </Unit5> </Units> </ProjectOptions> <CompilerOptions> <Version Value="11"/> <SearchPaths> <SrcPath Value="$(LazarusDir)/lcl;$(LazarusDir)/lcl/interfaces/$(LCLWidgetType)"/> </SearchPaths> <Linking> <Debugging> <UseLineInfoUnit Value="False"/> <StripSymbols Value="True"/> </Debugging> <Options> <Win32> <GraphicApplication Value="True"/> </Win32> </Options> </Linking> <Other> <Verbosity> <ShowHints Value="False"/> </Verbosity> <CompilerPath Value="$(CompPath)"/> </Other> </CompilerOptions> <Debugging> <Exceptions Count="2"> <Item1> <Name Value="ECodetoolError"/> </Item1> <Item2> <Name Value="EFOpenError"/> </Item2> </Exceptions> </Debugging> </CONFIG> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/gui/TODO������������������������������������������������������������������������������0000600�0001750�0001750�00000006205�12170541222�015236� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������- We should store filenames like Lazarus files: - property in ini file for FilePathDelim - when reading we 1st read FilePathDelim, then in all filenames we replace FilePathDelim with current PathDelim. - when writing we set FilePathDelim to current PathDelim Add then to [http://pasdoc.sipsolutions.net/PasDocGui] text like Moreover, as long as you will keep ''Store relative paths in project file'' option checked, you can freely open and save the same *.pds file using any OS. E.g. you can create and save {{{test.pds}}} using Linux version of pasdoc_gui, then switch to Windows and open the same {{{test.pds}}} file using Windows version of pasdoc_gui, etc. - GraphViz improvements: - There must be a way to specify file extension (e.g. there *must* be a way to differ between svg and png formats; not to mention that there *should* be a way to differ between various pixel-based image formats). - Also for command-line pasdoc: By default dot should be automatically run by pasdoc component, although there should be a way to turn it off. It would be also nice to have a way to let pasdoc component automatically call dot but at the same time change some dot's command-line options (e.g. force "-Grankdir=LR"). Last possibility could be used by pasdoc_gui to provide some GUI controls that affect generated command-line options passed to dot. E.g. pasdoc_gui could provide TRadioBox to control "-Grankdir=LR|RL|BT" option for dot. - Also for command-line pasdoc: See also requests about using client-side image map generated by "dot", see [http://pasdoc.sipsolutions.net/WantedFeatures]. - When we will learn how to generate nice offline documentation from our moinmoin wiki and we will distribute pasdoc + pasdoc_gui + offline docs in one package, this will fire up WWW browser with a local HTML page (still, configuration option will be added to allow users who are always online to see the latest version of documentation from WWW, instead of looking at offline version). - pasdoc_gui should allow user to configure default state of "Defines". Actually, it should allow user to configure default state of *all* options. E.g. maybe someone always wants to make default language of docs = Polish ? Maybe someone wants default verbosity = 6 ? Maybe someone has some include directory with his include files that he wants to always be added to "Include dirs" by default ? This can all be very nicely solved by storing some "default project settings" in user's directory and loading it on program start (and menu "New" execution). Then the code that currently loads contents from Ini file can be modified to actually have really good default values, and instead of using "SetDefaults" we simply load from a file where "default project settings" for this user are stored (like ~/.pasdoc_gui/default.pds on Unixes) - ButtonAspellURL and ButtonGraphVizURL and ButtonPasdocURL should be changed to have blue and underlined font and cursor crHand. Maybe also turn them into labels. This seems not possible now (with Lazarus 0.9.10 on GTK interface), for now normal buttons look best. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/gui/HISTORY���������������������������������������������������������������������������0000600�0001750�0001750�00000013623�10231557153�015642� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������- Done item from TO-DO file: Caption should reflect current filename of the project, or 'noname.pds' if it's not saved yet. Also '*' should be added when Changed = true. These are the common ways to say user what filename he is editing (because he *is* editing a file using pasdoc_gui: he's editing his PasDoc Settings, pds file) and what is the value of Changed. This would also render unnecessary the code "PageControl1.ActivePageIndex := 0;" currently done when user executes "New" menu command. I find it unpleasant, but for now it's sometimes necessary to clearly show the user that settings were reseted. For later changes see cvs logs. Although some changes may be mentioned in this file if they were previously mentioned in TO-DO file. Upon fixing such things you can move text from TO-DO file to this HISTORY file. kambi, 2005-04-20: Changes done to HelpGenerator to make it work cleanly with FPC/Lazarus: - I renamed it to "pasdoc_gui" (instead of "HelpGenerator"), because I just consider it a better name. I also changed output extension to "pds" (was "hgs"). This not only reflects new name, but it also reflects the fact that pasdoc_gui *cannot* read files written by HelpGenerator. See lower in this file for description why I changed the way settings are read/written. - I removed dependency on MemCheck unit, not only because it's does not comply with GNU GPL free but also because it's absolutely useless for FPC programs. (HeapTrc unit exists for FPC that does roughly what MemCheck unit does for Delphi). - I also removed USGS copyright notices at the beginning of the file frmhelpgeneratorunit.pas because they were making unclear statements about what and how is required. I replaced them with standard GNU GPL copyright preamble. My basis is that original code by Richard is said to be on public domain, so I can do anything with it, including licensing modified version of HelpGenerator as GNU GPL sources. If someone thinks that I cannot do this, I will obey. Although I prefer to develop free software using GNU GPL, and a "clean GNU GPL", without any additional legal statements. Richard: even if what I did is OK, you may still want me to change the first line of copyright. I put there "Copyright 2004-2005 Richard B. Winston, U.S. Geological Survey (USGS)" basing on previous copyright comments. - Part of "Options" tab splitted to "Header/Footer" tab to make it smaller. - "About" form changed. - Running external browser is implemented using TProcess. - Let me elaborate a little why previous system with saving setting was not working correctly: When you save a component to a stream, Delphi and FPC do not write properties that have a default value. This is against the spirit of what was assumed in HelpGenerator code, that incorrectly *assumed* that this will always be done. You can see this bug in HelpGenerator: 1. clear "Defines" memo 2. save project as "foo.hgs" 3. write some values in "Defines" memo, like 'FPC' 4. load project as "foo.hgs" Bug: "Defines" memo contains value 'FPC', but it shouldn't, because "foo.hgs" says that no defines should be specified. Why ? Because ObjectPascal streaming system did not record in "foo.hgs" file value of Directives property, it assumed that having Count=0 is the default state of "Defines" property, so there is no need to save it. There are a couple of property types where this behavior will always be present, e.g. string properties are never saved when their value is '' etc. For *some* properties (namely, ones that are obtained via GetOrdProp RTTI call, with the exception of "Integer default $80000000" because $80000000 is special) you can reliably tell Delphi to always save them (regardless of their value) but 1. this is uncleanly done in Delphi (because it's not a general solution, it doesn't work for all property types (it doesn't work for TString property or a string property), and there's that funny thing with $80000000 being special) 2. unfortunately FPC does not implement it for now. This means that in FPC property always has some implicit default value, like "false" for booleans and "0" for integers. There is *no* way to tell FPC to always save a boolean property to a file (regardless of value of that property). See this thread in fpc-pascal mailing archives: [http://www.nl.freepascal.org/lists/fpc-pascal/2005-April/008267.html] What does it mean in a "general view" ? Using ObjectPascal streaming system is a perfect (and easy) way when you always load object from a file *right after* creating it and you're prepared that if some property has some default value, it's "Set" method will not be called by the streaming system at all. Streaming system simply assumes that properties are already correctly set to their default values. That's why I decided that it will be simplest to simply resign from using separate THelpGeneratorProjectOptions class at all. I simply remade reading/writing everything using simple TIniFile. This means that adding new things to a settings file is a little more error-prone (you don't have to add only one property to some class, you have to remember to add both the reading and the writing code to appropriate places). Although in fact it's simpler and shorter (less dummy Get/Set methods, also no need for dummy splitting of clbMethodVisibility items to 5 boolean properties.) As for now, I see that my version of frmHelpGenerator has 250 lines less than original one :) OK, I surprised myself :) - Implementation of SetDefaults extended with things that were originally only in New1Click. This is for clarity. - Oh, and I changed default "Defines" from Delphi and Win32 oriented to FPC and Linux oriented. Sorry, I just couldn't resists :) Seriously, this is TO-DO item in TO-DO file, see item "pasdoc_gui should allow user to configure default state of Defines" �������������������������������������������������������������������������������������������������������������pasdoc/source/gui/pasdoc_gui.lpr��������������������������������������������������������������������0000600�0001750�0001750�00000000637�12170551750�017414� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������program pasdoc_gui; {$mode objfpc}{$H+} uses Interfaces, // this includes the LCL widgetset Forms { add your units here }, frmAboutUnit, frmHelpGeneratorUnit, pasdoc_package, HelpProcessor, PreferencesFrm, PasDocGuiSettings; {$R *.res} begin Application.Initialize; Application.CreateForm(TfrmHelpGenerator, frmHelpGenerator); Application.CreateForm(TfrmAbout, frmAbout); Application.Run; end. �������������������������������������������������������������������������������������������������pasdoc/source/console/������������������������������������������������������������������������������0000700�0001750�0001750�00000000000�12561642316�015431� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/console/pasdoc.bdsproj����������������������������������������������������������������0000600�0001750�0001750�00000021111�10526527722�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/console/pasdoc.kof��������������������������������������������������������������������0000600�0001750�0001750�00000001674�10526527722�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.dpr��������������������������������������������������������������������0000600�0001750�0001750�00000004164�12337202423�017410� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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} {$APPTYPE CONSOLE} {$ENDIF} uses {$ifdef USE_FASTMM} FastMM4, {$endif} PasDoc_Main; begin Main; end. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/console/pasdoc.dof��������������������������������������������������������������������0000600�0001750�0001750�00000000222�11462132235�017363� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Directories] SearchPath=..\component;..\component\images;..\component\tipue DebugSourceDirs=..\component;..\Console;..\component\tipue OutputDir=������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/console/PasDoc_Main.pas���������������������������������������������������������������0000600�0001750�0001750�00000057510�12561547475�020277� 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, OptionFooter, OptionHeader, 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); OptionFooter := TStringOption.Create('F', 'footer'); OptionFooter.Explanation := 'Include file as footer for HTML output'; AddOption(OptionFooter); OptionHeader := TStringOption.Create('H', 'header'); OptionHeader.Explanation := 'Include file as header for HTML output'; AddOption(OptionHeader); 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 OptionFooter.WasSpecified then Generator.Footer := FileToString(OptionFooter.Value); if OptionHeader.WasSpecified then Generator.Header := FileToString(OptionHeader.Value); { If external CSS file was specified } 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 := LanguageAspellCode(PasDoc.Generator.Language) else if OptionASPELL.Value = '' then PasDoc.Generator.AspellLanguage := LanguageAspellCode(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.lpi��������������������������������������������������������������������0000600�0001750�0001750�00000011522�11473144447�017416� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <CONFIG> <ProjectOptions> <PathDelim Value="\"/> <Version Value="7"/> <General> <Flags> <SaveClosedFiles Value="False"/> <MainUnitHasUsesSectionForAllUnits Value="False"/> <MainUnitHasCreateFormStatements Value="False"/> <MainUnitHasTitleStatement Value="False"/> <LRSInOutputDirectory Value="False"/> </Flags> <MainUnit Value="0"/> <TargetFileExt Value=""/> <Title Value="pasdoc"/> <ActiveEditorIndexAtStart Value="0"/> </General> <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="3"> <Unit0> <Filename Value="pasdoc.dpr"/> <IsPartOfProject Value="True"/> <CursorPos X="1" Y="42"/> <TopLine Value="20"/> <EditorIndex Value="0"/> <UsageCount Value="21"/> <Loaded Value="True"/> </Unit0> <Unit1> <Filename Value="PasDoc_Main.pas"/> <UnitName Value="PasDoc_Main"/> <CursorPos X="1" Y="171"/> <TopLine Value="148"/> <EditorIndex Value="2"/> <UsageCount Value="10"/> <Loaded Value="True"/> </Unit1> <Unit2> <Filename Value="..\component\PasDoc_Base.pas"/> <UnitName Value="PasDoc_Base"/> <CursorPos X="1" Y="603"/> <TopLine Value="603"/> <EditorIndex Value="1"/> <UsageCount Value="10"/> <Loaded Value="True"/> </Unit2> </Units> <JumpHistory Count="12" HistoryIndex="11"> <Position1> <Filename Value="PasDoc_Main.pas"/> <Caret Line="1" Column="1" TopLine="1"/> </Position1> <Position2> <Filename Value="PasDoc_Main.pas"/> <Caret Line="26" Column="22" TopLine="4"/> </Position2> <Position3> <Filename Value="PasDoc_Main.pas"/> <Caret Line="171" Column="1" TopLine="146"/> </Position3> <Position4> <Filename Value="PasDoc_Main.pas"/> <Caret Line="168" Column="28" TopLine="146"/> </Position4> <Position5> <Filename Value="PasDoc_Main.pas"/> <Caret Line="171" Column="1" TopLine="148"/> </Position5> <Position6> <Filename Value="pasdoc.dpr"/> <Caret Line="41" Column="1" TopLine="1"/> </Position6> <Position7> <Filename Value="..\component\PasDoc_Base.pas"/> <Caret Line="651" Column="1" TopLine="629"/> </Position7> <Position8> <Filename Value="pasdoc.dpr"/> <Caret Line="41" Column="1" TopLine="1"/> </Position8> <Position9> <Filename Value="..\component\PasDoc_Base.pas"/> <Caret Line="651" Column="1" TopLine="629"/> </Position9> <Position10> <Filename Value="pasdoc.dpr"/> <Caret Line="42" Column="1" TopLine="1"/> </Position10> <Position11> <Filename Value="..\component\PasDoc_Base.pas"/> <Caret Line="651" Column="1" TopLine="629"/> </Position11> <Position12> <Filename Value="pasdoc.dpr"/> <Caret Line="42" Column="1" TopLine="22"/> </Position12> </JumpHistory> </ProjectOptions> <CompilerOptions> <Version Value="8"/> <PathDelim Value="\"/> <SearchPaths> <IncludeFiles Value="..\component\"/> </SearchPaths> <Parsing> <SyntaxOptions> <IncludeAssertionCode Value="True"/> <CStyleMacros Value="True"/> <UseAnsiStrings 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> <CompilerPath Value="$(CompPath)"/> </Other> </CompilerOptions> <Debugging> <Watches Count="1"> <Item1> <Expression Value="Options"/> </Item1> </Watches> <Exceptions Count="2"> <Item1> <Name Value="ECodetoolError"/> </Item1> <Item2> <Name Value="EFOpenError"/> </Item2> </Exceptions> </Debugging> </CONFIG> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/autodoc/������������������������������������������������������������������������������0000700�0001750�0001750�00000000000�12561642317�015426� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/autodoc/autodoc.pds�������������������������������������������������������������������0000600�0001750�0001750�00000001613�11027555126�017574� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Main] StoreRelativePaths=1 Language=en GenerateFormat=0 Verbosity=2 ClassMembers_0=1 ClassMembers_1=1 ClassMembers_2=1 ClassMembers_3=0 ClassMembers_4=1 ClassMembers_5=0 ImplicitVisibility=0 Sorting_0=0 Sorting_1=0 Sorting_2=0 Sorting_3=0 Sorting_4=0 Sorting_5=0 Sorting_6=0 Sorting_7=0 Sorting_8=0 Sorting_9=0 WriteUsesList=1 AutoAbstract=1 AutoLink=0 HandleMacros=1 UseTipueSearch=1 LineBreakQuality=0 SpecialMarkerTreatment=1 Title=PasDoc's autodoc VizGraphClasses=1 VizGraphUses=1 CheckSpelling=0 LatexGraphicsPackage=0 OutputDir=html_by_pasdoc_gui/ IntroductionFileName=introduction.txt ClassMembers_6=1 ClassMembers_7=1 [Defines] Count=0 [Header] Count=0 [Footer] Count=0 [IncludeDirectories] Count=1 Item_0=../component [Files] Count=3 Item_0=../component/*.pas Item_1=../component/tipue/*.pas Item_2=../console/*.pas [HyphenatedWords] Count=0 [SpecialMarkers] Count=0 [IgnoreWords] Count=0 ���������������������������������������������������������������������������������������������������������������������pasdoc/source/autodoc/introduction.txt��������������������������������������������������������������0000600�0001750�0001750�00000007304�10332011436�020700� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@shorttitle(Overview) @title(Pasdoc Sources Overview) This is the documentation of the pasdoc sources, intended for pasdoc developers. For user's documentation see [http://pasdoc.sourceforge.net/]. Contents: @tableOfContents General overview of the data flow in pasdoc: @section(1 SecParsing Parsing) @link(TTokenizer) reads the source file, and converts it to a series of @link(TToken)s. @link(TScanner) uses an underlying @link(TTokenizer) and also returns a series of @link(TToken)s, but in addition it understands and interprets $define, $ifdef and similar compiler directives. While @link(TTokenizer) simply returns all tokens, @link(TScanner) returns only those tokens that are not "$ifdefed out". E.g. if WIN32 is not defined then the @link(TScanner) returns only tokens "@code(const LineEnding = #10;)" for the following code: @longcode# const LineEnding = {$ifdef WIN32} #13#10 {$else} #10 {$endif}; # Finally @link(TParser) uses an underlying @link(TScanner) and interprets the series of tokens, as e.g. "here I see a declaration of variable Foo, of type Integer". The Parser stores everything it reads in a @link(TPasUnit) instance. If you ever wrote a program that interprets a text language, you will see that there is nothing special here: We have a lexer (@link(TScanner), a simplified lexer in @link(TTokenizer)) and a parser (@link(TParser)). It is important to note that pasdoc's parser is somewhat unusual, compared to "normal" parsers that are used e.g. in Pascal compilers. @orderedList( @item( Pasdoc's parser does not read the implementation section of a unit file (although this may change some day, see [http://pasdoc.sipsolutions.net/WantedFeaturesParsingImplementation]).) @item( Pasdoc's parser is "cheating": It does not really understand everything it reads. E.g. the parameter section of a procedure declaration is parsed "blindly", by simply reading tokens up to a matching closing parenthesis. Such cheating obviously simplifies the parser implementation, but it also makes pasdoc's parser "dumber", see [http://pasdoc.sipsolutions.net/ToDoParser].) @item( Pasdoc's parser collects the comments before each declaration, since these comments must be converted and placed in the final documentation (while "normal" parsers usually treat comments as a meaningless white-space).) ) @section(1 SecStoring Storing) The unit @link(PasDoc_Items) provides a comfortable class hierarchy to store a parsed Pascal source tree. @link(TPasUnit) is a "root class" (container-wise), it contains references to all other items within a unit, every item is some instance of @link(TPasItem). @section(1 SecGenerators Generators) The last link in the chain are the generators. A generator uses the stored @link(TPasItem) tree and generates the final documentation. The base abstract class for a generator is @link(TDocGenerator), this provides some general mechanisms used by all generators. From @link(TDocGenerator) descend more specialized generator classes, like @link(TGenericHTMLDocGenerator), @link(THTMLDocGenerator), @link(TTexDocGenerator) and others. @section(1 SecNotes Notes) Note that the parser and the generators do not communicate with each other directly. The parser stores things in the @link(TPasItem) tree. Generators read and process the @link(TPasItem) tree. So the parser cannot do any stupid thing like messing with some HTML-specific or LaTeX-specific issues of generating documentation. And the generator cannot deal with parsing Pascal source code. Actually, this makes the implementation of the generator independent enough to be used in other cases, e.g. to generate an "introduction" file for the final documentation, like the one you are reading right now. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/autodoc/Makefile����������������������������������������������������������������������0000600�0001750�0001750�00000014307�11575333733�017100� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This Makefile creates PasDoc generated documentation for PasDoc itself. # Documentation is created in subdirectories named after pasdoc's --format # names (html/, latex/ etc.) # # Targets: # # html latex pdf dvi ps html-latex htmlhelp rtf # Make documentation in requested format. # # clean # Delete all generated documentation. # # public # Generate documentation in all formats that we want to show # on http://pasdoc.sourceforge.net/autodoc/. # # upload # Upload documentation generated by `public' # to http://pasdoc.sourceforge.net/autodoc/. # Of course you need to have sourceforge account and sufficient privileges # on sourceforge web server to do this (you need to be a pasdoc developer). # It uses scp program. You will be asked for password (more than once) # unless you configured ssh keys for your sourceforge account, # so configuring ssh keys is really advised. # You should override SF_USERNAME variable at command-line to your # username on sourceforge. # # Note that scp displays progress meter on output, if you don't want this # (e.g. because you run "make" into Emacs compilation buffer) # you can pass option `-q' to scp, calling make like this # `make upload SCP_OPTIONS=-q SF_USERNAME=my_user_name' # # For the sake of other pasdoc developers that would like # to also be able to execute `make upload' to upload freshest # version of autodoc, this target makes sure the uploaded files # are writeable by the group `pasdoc', so other pasdoc developers # may override them. # # Some hints: # To completely remake all documentation for # http://pasdoc.sourceforge.net/autodoc/ # just call `make clean public upload SF_USERNAME=my_user_name' # Making documentation ---------------------------------------- # Name of pasdoc binary. Remember that you can override it at # make's command-line, like `make PASDOC=my_pasdoc' PASDOC=pasdoc # These options will be passed to every pasdoc invocation, # i.e. for every output format. PASDOC_OPTIONS=--include ../component \ ../component/*.pas ../component/tipue/*.pas \ ../console/*.pas \ -DFPC -DVER2 \ --title "PasDoc's autodoc" --write-uses-list --auto-abstract \ --introduction=introduction.txt GRAPHVIZ_COMMANDS=dot -Grankdir=LR -Tjpg -oGVClasses.jpg GVClasses.dot; \ dot -Grankdir=LR -Tjpg -oGVUses.jpg GVUses.dot # These options will be passed only when making docs in format that # supports including graphviz graphs. PASDOC_GRAPHVIZ_OPTIONS=--graphviz-classes --graphviz-uses \ --link-gv-classes jpg --link-gv-uses jpg # How to call hhc (html help compiler) ? # Default value means that it must be available on path. # As usual, remember you can override it at make's command-line. HHC=hhc .PHONY: html latex pdf dvi ps html-latex clean htmlhelp rtf html: mkdir -p html/ $(PASDOC) $(PASDOC_OPTIONS) $(PASDOC_GRAPHVIZ_OPTIONS) \ --output=html/ --use-tipue-search cd html/; $(GRAPHVIZ_COMMANDS) # Ignore exit code from hhc (it's always 1 ???) htmlhelp: mkdir -p htmlhelp/ $(PASDOC) $(PASDOC_OPTIONS) $(PASDOC_GRAPHVIZ_OPTIONS) \ --format=htmlhelp --output=htmlhelp/ cd htmlhelp/; $(GRAPHVIZ_COMMANDS) -cd htmlhelp/; $(HHC) docs.hhp # Just shortcuts latex: latex/docs.tex pdf: latex/docs.pdf dvi: latex/docs.dvi ps: latex/docs.ps html-latex: latex/docs.html rtf: latex2rtf/docs.rtf latex/docs.tex: mkdir -p latex/ $(PASDOC) $(PASDOC_OPTIONS) \ --format=latex --output=latex/ # (Yes, I must do `cd latex' before calling pdflatex, I can't simply call # `pdflatex latex/docs.tex' because then many output files of pdflatex # would be placed in current dir) latex/docs.pdf: latex/docs.tex cd latex; pdflatex --file-line-error-style -interaction=nonstopmode docs.tex cd latex; pdflatex --file-line-error-style -interaction=nonstopmode docs.tex latex/docs.dvi: latex/docs.tex cd latex; latex --file-line-error-style -interaction=nonstopmode docs.tex cd latex; latex --file-line-error-style -interaction=nonstopmode docs.tex latex/docs.ps: latex/docs.dvi cd latex; dvips docs.dvi -o docs.ps # When working htlatex overrides latex/docs.dvi with a version # that is not really a useful to browse (it's only for htlatex internals). # That's why I `rm' it afterwards. # # As far as I understand how htlatex works, it's not needed to run # htlatex twice (like it's needed with pdflatex and latex). latex/docs.html: latex/docs.tex cd latex; htlatex docs.tex rm latex/docs.dvi latex2rtf/docs.tex: mkdir -p latex2rtf/ $(PASDOC) $(PASDOC_OPTIONS) \ --format=latex2rtf --output=latex2rtf/ # I must have latex/docs.tex as a prerequisite, to run latex over it # to generate docs.aux file. Then I can use latex/docs.aux file with latex2rtf # so that latex2rtf can make appropriate links. latex2rtf/docs.rtf: latex2rtf/docs.tex latex/docs.tex cd latex/; latex --file-line-error-style -interaction=nonstopmode docs.tex cd latex2rtf/; latex2rtf -a ../latex/docs.aux docs.tex clean: rm -Rf html/ latex/ latex2rtf/ htmlhelp/ # ------------------------------------------------------------ # Making and uploading autodoc for http://pasdoc.sourceforge.net/autodoc/ # html-latex format output used to be included here too, # but honestly htlatex is too bad to show publicly. # Besides htlatex is broken on my system right now :) # If you want to restore html-latex for public autodoc demo, # add to the upload target # scp $(SCP_OPTIONS) latex/docs.html $(SF_CONNECT)latex/ # scp $(SCP_OPTIONS) latex/docs.css $(SF_CONNECT)latex/ .PHONY: public upload public: html pdf latex # Override this at command-line to your username, # like `make upload SF_USERNAME=my_user_name' SF_USERNAME=kambi SF_HOST=web.sourceforge.net SF_PATH=/home/project-web/pasdoc/htdocs/autodoc/ SF_CONNECT=$(SF_USERNAME),pasdoc@$(SF_HOST):$(SF_PATH) SCP_OPTIONS= upload: scp $(SCP_OPTIONS) -r html/ $(SF_CONNECT) scp $(SCP_OPTIONS) latex/docs.pdf $(SF_CONNECT)latex/ scp $(SCP_OPTIONS) latex/docs.tex $(SF_CONNECT)latex/ # Not required anymore: with new SF shell, I'm logging in with ",pasdoc" # in username, so the files will already be owned by "pasdoc" group by default. # ../../tests/scripts/ssh_chmod_writeable_by_pasdoc.sh \ # $(SF_USERNAME),pasdoc $(SF_PATH) # eof ------------------------------------------------------------ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/autodoc/autodoc.bat�������������������������������������������������������������������0000600�0001750�0001750�00000001571�11460570733�017561� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@echo off rem Generate PasDoc autodoc under Windows. rem rem Note that it's adviced to use Makefile (you will need GNU `make') rem in this directory instead of this BAT script. rem Makefile is portable and will be always more up-to-date than this rem BAT script, not to mention that Makefile gives you many more possibilities. set PASDOC=..\console\pasdoc set INCLUDE=..\component set SOURCE=..\component\*.pas ..\component\tipue\*.pas ..\console\*.pas set OPTIONS=--write-uses-list --auto-abstract --title "PasDoc's autodoc" --introduction=introduction.txt --use-tipue-search set GRAPHVIZ=--graphviz-classes --graphviz-uses --link-gv-classes jpg --link-gv-uses jpg set OUTPUT=html\ %PASDOC% --include=%INCLUDE% --output=%OUTPUT% %OPTIONS% %GRAPHVIZ% %SOURCE% dot -Grankdir=LR -Tjpg -ohtml\GVClasses.jpg html\GVClasses.dot dot -Grankdir=LR -Tjpg -ohtml\GVUses.jpg html\GVUses.dot pause ���������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/����������������������������������������������������������������������������0000700�0001750�0001750�00000000000�12561642316�015771� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/PasDoc_SortSettings.pas�����������������������������������������������������0000600�0001750�0001750�00000005100�12337202423�022365� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/PasDoc_Hashes.pas�����������������������������������������������������������0000600�0001750�0001750�00000031312�12337202423�021134� 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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_StreamUtils.pas������������������������������������������������������0000600�0001750�0001750�00000135660�12337202423�022210� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { @cvs($Date: 2014-05-21 21:57:07 +0200 (śro) $) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Arno Garrels <first name.name@nospamgmx.de>) @abstract(A few stream utility functions.) TBufferedStream, TStreamReader and TStreamWriter by Arno Garrels. } unit PasDoc_StreamUtils; {$I pasdoc_defines.inc} {$IFDEF COMPILER_12_UP} {.$WARN IMPLICIT_STRING_CAST OFF} {.$WARN IMPLICIT_STRING_CAST_LOSS OFF} {$WARN EXPLICIT_STRING_CAST OFF} {$WARN EXPLICIT_STRING_CAST_LOSS OFF} {$ENDIF} interface uses {$IFDEF MSWINDOWS} Windows, {$ENDIF} SysUtils, Classes, PasDoc_Types; {$IFDEF USE_BUFFERED_STREAM} const DEFAULT_BUFSIZE = 4096; MIN_BUFSIZE = 128; MAX_BUFSIZE = 1024 * 64; type TBufferedStream = class(TStream) private FStream : TStream; FOwnsStream : Boolean; FBuffer : TBytes; FBufferSize : Integer; FBufferedDataSize : Integer; // Number of bytes currently buffered FDirtyCount : Integer; // Range of dirty bytes in buffer counted from buffer index zero FStreamBufPos : Int64; // First byte of the buffer in stream FPosition : Int64; // Helper var, partly calculated FFastSize : Int64; // Size of FStream at the time IsReadOnly is set to TRUE. See property IsReadOnly below FIsReadOnly : Boolean; // See property IsReadOnly below protected procedure SetIsReadOnly(const Value: Boolean); procedure SetSize(NewSize: Integer); override; procedure SetSize(const NewSize: Int64); override; function InternalGetSize: Int64; {$IFDEF USE_INLINE} inline;{$ENDIF} function GetSize: Int64; override; procedure Init; virtual; function FillBuffer: Boolean; {$IFDEF USE_INLINE} inline;{$ENDIF} public constructor Create; overload; // Dummy, don't call! constructor Create(Stream : TStream; BufferSize : Integer = DEFAULT_BUFSIZE; OwnsStream : Boolean = FALSE); overload; virtual; constructor Create(const FileName : String; Mode : Word; BufferSize : Integer = DEFAULT_BUFSIZE); overload; virtual; destructor Destroy; override; procedure Flush; {$IFDEF USE_INLINE} inline;{$ENDIF} function Read(var Buffer; Count: Integer): Integer; override; function Seek(Offset: Integer; Origin: Word): Integer; override; function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override; function Write(const Buffer; Count: Integer): Integer; override; { Set IsReadOnly if you are sure you will never write to the stream and nobody else will do, this speeds up getter Size and in turn Seeks as well. IsReadOnly is set to TRUE if a constructor with filename is called with a read only mode and a share lock. } property IsReadOnly: Boolean read FIsReadOnly write SetIsReadOnly; property FastSize: Int64 read GetSize; end; {$ENDIF} {$IFDEF STRING_UNICODE} EStreamReaderError = class(Exception); EStreamWriterError = class(Exception); TLineBreakStyle = (ilbsCRLF, ilbsLF, ilbsCR); TStreamReader = class(TBufferedStream) private FReadBuffer : TBytes; FReadBufSize : Integer; FCodePage : LongWord; FLeadBytes : TCharSet; FDetectBOM : Boolean; { Max. number of chars (elements) forcing a new line even though } { none of the break chars was found. Note that this value is not } { accurate since multi-byte code points including UTF-8 will be } { preserved. Default = MAXINT } FMaxLineLength : Integer; function InternalReadLn: Boolean; function InternalReadLnWLe: Boolean; function InternalReadLnWBe: Boolean; procedure EnsureReadBufferW(Size: Integer; var P: PWideChar); {$IFDEF USE_INLINE} inline;{$ENDIF} procedure EnsureReadBufferA(Size: Integer; var P: PAnsiChar); {$IFDEF USE_INLINE} inline;{$ENDIF} procedure SetMaxLineLength(const Value: Integer); procedure SetCodePage(const Value : LongWord); protected function GetCodePageFromBOM: LongWord; virtual; procedure Init; override; public constructor Create(Stream : TStream; BufferSize : Integer = DEFAULT_BUFSIZE; OwnsStream : Boolean = FALSE); override; constructor Create(Stream : TStream; DetectBOM : Boolean = FALSE; CodePage : LongWord = CP_ACP; OwnsStream : Boolean = FALSE; BufferSize : Integer = DEFAULT_BUFSIZE); overload; constructor Create(const FileName : String; Mode : Word; BufferSize : Integer = DEFAULT_BUFSIZE); override; constructor Create(const FileName : String; DetectBOM : Boolean = TRUE; CodePage : LongWord = CP_ACP; BufferSize : Integer = DEFAULT_BUFSIZE); overload; function DetectLineBreakStyle: TLineBreakStyle; function ReadLine(var S: RawByteString): Boolean; overload; virtual; function ReadLine(var S: UnicodeString): Boolean; overload; virtual; procedure ReadToEnd(var S: RawByteString); overload; virtual; procedure ReadToEnd(var S: UnicodeString); overload; virtual; property CurrentCodePage: LongWord read FCodePage write SetCodePage; property MaxLineLength: Integer read FMaxLineLength write SetMaxLineLength; property LeadBytes: TCharSet read FLeadBytes; end; TStreamWriter = class(TBufferedStream) private FWriteBuffer : TBytes; // For charset conversion FWriteBufSize : Integer; FReadBuffer : TBytes; // For charset conversion FReadBufSize : Integer; FLineBreakStyle : TLineBreakStyle; FCodePage : LongWord; FLineBreak : AnsiString; procedure SetLineBreakStyle(Value: TLineBreakStyle); procedure EnsureWriteBuffer(Size: Integer); {$IFDEF USE_INLINE} inline; {$ENDIF} procedure EnsureReadBuffer(Size: Integer); {$IFDEF USE_INLINE} inline; {$ENDIF} procedure SetCodePage(const Value: LongWord); protected function GetBomFromCodePage(ACodePage: LongWord) : TBytes; virtual; function GetCodePageFromBOM: LongWord; virtual; procedure Init; override; public constructor Create(Stream : TStream; BufferSize : Integer = DEFAULT_BUFSIZE; OwnsStream : Boolean = FALSE); override; constructor Create(Stream : TStream; Append : Boolean = TRUE; DetectBOM : Boolean = FALSE; CodePage : LongWord = CP_ACP; OwnsStream : Boolean = FALSE; BufferSize : Longint = DEFAULT_BUFSIZE); overload; constructor Create(const FileName : String; Mode : Word; BufferSize : Integer = DEFAULT_BUFSIZE); override; constructor Create(const FileName : String; Append : Boolean = TRUE; DetectBOM : Boolean = TRUE; CodePage : LongWord = CP_ACP; BufferSize : Integer = DEFAULT_BUFSIZE); overload; function DetectLineBreakStyle: TLineBreakStyle; procedure Write(const S : UnicodeString); reintroduce; overload; virtual; procedure Write(const S : RawByteString; SrcCodePage : LongWord = CP_ACP); reintroduce; overload; virtual; { procedure Write(Value: Boolean); reintroduce; overload; procedure Write(Value: WideChar); reintroduce; overload; procedure Write(Value: AnsiChar); reintroduce; overload; .. } procedure WriteLine(const S : UnicodeString); overload; {$IFDEF USE_INLINE} inline; {$ENDIF} procedure WriteLine(const S : RawByteString; SrcCodePage : LongWord = CP_ACP); overload; {$IFDEF USE_INLINE} inline; {$ENDIF} procedure WriteBOM; property CurrentCodePage : LongWord read FCodePage write SetCodePage; property LineBreakStyle : TLineBreakStyle read FLineBreakStyle write SetLineBreakStyle; end; {$ENDIF} function StreamReadLine(const AStream: TStream): AnsiString; { Write AString contents, then LineEnding to AStream } procedure StreamWriteLine(const AStream: TStream; const AString: AnsiString); { Just write AString contents to AStream } procedure StreamWriteString(const AStream: TStream; const AString: AnsiString); implementation uses PasDoc_Utils; // for LineEnding in Kylix/Delphi {---------------------------------------------------------------------------} { TBufferedStream } {---------------------------------------------------------------------------} {$IFDEF USE_BUFFERED_STREAM} {$IFOPT R+} {$DEFINE SETRANGECHECKSBACK} { We'll turn off range checking temporarily } {$ENDIF} type TDummyByteArray = array [0..0] of Byte; { Casts require range checks OFF } constructor TBufferedStream.Create(Stream: TStream; BufferSize: Longint = DEFAULT_BUFSIZE; OwnsStream: Boolean = FALSE); begin inherited Create; Assert(Stream <> nil, 'Stream must be assigned'); FStream := Stream; FOwnsStream := OwnsStream; FBufferSize := BufferSize; Init; end; {---------------------------------------------------------------------------} constructor TBufferedStream.Create; begin Create(nil); // dummy! end; {---------------------------------------------------------------------------} constructor TBufferedStream.Create(const FileName: String; Mode: Word; BufferSize: Integer); begin inherited Create; { Even in mode fmOpenWrite we need to read from file as well } if (Mode <> fmCreate) and (Mode and fmOpenWrite <> 0) then begin Mode := Mode and not fmOpenWrite; Mode := Mode or fmOpenReadWrite; end; FStream := TFileStream.Create(FileName, Mode); FBufferSize := BufferSize; FOwnsStream := True; IsReadOnly := (Mode <> fmCreate) and (Mode and fmOpenWrite = 0) and (Mode and fmOpenReadWrite = 0) and ((Mode and fmShareDenyWrite = fmShareDenyWrite) or (Mode and fmShareExclusive = fmShareExclusive)); Init; end; {---------------------------------------------------------------------------} destructor TBufferedStream.Destroy; begin Flush; if FOwnsStream then FreeAndNil(FStream); inherited Destroy; end; {---------------------------------------------------------------------------} procedure TBufferedStream.Flush; begin if FDirtyCount > 0 then begin FStream.Position := FStreamBufPos; FStream.WriteBuffer(FBuffer[0], FDirtyCount); FDirtyCount := 0; end; end; {---------------------------------------------------------------------------} procedure TBufferedStream.Init; begin if FBufferSize < MIN_BUFSIZE then FBufferSize := MIN_BUFSIZE else if FBufferSize > MAX_BUFSIZE then FBufferSize := MAX_BUFSIZE else FBufferSize := (FBufferSize div MIN_BUFSIZE) * MIN_BUFSIZE; SetLength(FBuffer, FBufferSize); FPosition := FStream.Position; end; {---------------------------------------------------------------------------} function TBufferedStream.Read(var Buffer; Count: Integer): Longint; var BufPos : Integer; SrcIndex : Integer; Remaining: Integer; begin Result := Count; while Count > 0 do begin if not ((FStreamBufPos <= FPosition) and (FPosition < (FStreamBufPos + FBufferedDataSize))) then if not FillBuffer then Break; { Read from buffer } SrcIndex := Result - Count; Remaining := Count; BufPos := FPosition - FStreamBufPos; if Remaining > FBufferedDataSize - BufPos then Remaining := FBufferedDataSize - BufPos; {$R-} Move(FBuffer[BufPos], TDummyByteArray(Buffer)[SrcIndex], Remaining); {$IFDEF SETRANGECHECKSBACK} {$R+} {$ENDIF} Inc(FPosition, Remaining); Dec(Count, Remaining); end; Result := Result - Count; end; {---------------------------------------------------------------------------} function TBufferedStream.FillBuffer: Boolean; begin Flush; FStream.Position := FPosition; FStreamBufPos := FPosition; FBufferedDataSize := FStream.Read(FBuffer[0], FBufferSize); Result := FBufferedDataSize > 0; end; {---------------------------------------------------------------------------} function TBufferedStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; var NewPos: Int64; begin case Origin of soBeginning : NewPos := Offset; soCurrent : NewPos := FPosition + Offset; soEnd : begin NewPos := InternalGetSize + Offset; if (FDirtyCount > 0) and (NewPos < FStreamBufPos + FDirtyCount) then begin Flush; NewPos := FStream.Size + Offset; end; end; else NewPos := -1; end; if NewPos < 0 then NewPos := -1 else FPosition := NewPos; Result := NewPos; end; {---------------------------------------------------------------------------} function TBufferedStream.Seek(Offset: Integer; Origin: Word): Integer; begin Result := Seek(Int64(Offset), TSeekOrigin(Origin)); end; {---------------------------------------------------------------------------} procedure TBufferedStream.SetIsReadOnly(const Value: Boolean); begin FIsReadOnly := Value; if FIsReadOnly then FFastSize := FStream.Size else FFastSize := -1; end; {---------------------------------------------------------------------------} function TBufferedStream.InternalGetSize: Int64; begin if IsReadOnly then Result := FFastSize else Result := FStream.Size; end; {---------------------------------------------------------------------------} function TBufferedStream.GetSize: Int64; begin { Gets the calculated size in order to not trigger Flush in method } { Seek which was wasted time. Do not call inherited. } Result := InternalGetSize; if Result < FStreamBufPos + FDirtyCount then Result := FStreamBufPos + FDirtyCount; end; {---------------------------------------------------------------------------} procedure TBufferedStream.SetSize(const NewSize: Int64); begin FStream.Size := NewSize; FPosition := FStream.Position; if NewSize < (FStreamBufPos + FDirtyCount) then begin FDirtyCount := NewSize - FStreamBufPos; if FDirtyCount < 0 then FDirtyCount := 0; end; if NewSize < (FStreamBufPos + FBufferedDataSize) then begin FBufferedDataSize := NewSize - FStreamBufPos; if FBufferedDataSize < 0 then FBufferedDataSize := 0; end; end; {---------------------------------------------------------------------------} procedure TBufferedStream.SetSize(NewSize: Integer); begin SetSize(Int64(NewSize)); end; {---------------------------------------------------------------------------} function TBufferedStream.Write(const Buffer; Count: Integer): Longint; var DestPos : Integer; SrcIndex : Integer; Remaining : Integer; begin Result := Count; while Count > 0 do begin if not ((FStreamBufPos <= FPosition) and (FPosition < (FStreamBufPos + FBufferedDataSize))) then if not ((FStreamBufPos <= FPosition) and (FPosition < (FStreamBufPos + FBufferSize))) then FillBuffer; { Write to buffer } SrcIndex := Result - Count; Remaining := Count; DestPos := FPosition - FStreamBufPos; if Remaining > FBufferSize - DestPos then Remaining := FBufferSize - DestPos; if FBufferedDataSize < DestPos + Remaining then FBufferedDataSize := DestPos + Remaining; {$R-} Move(TDummyByteArray(Buffer)[SrcIndex], FBuffer[DestPos], Remaining); {$IFDEF SETRANGECHECKSBACK} {$R+} {$ENDIF} FDirtyCount := DestPos + Remaining; Inc(FPosition, Remaining); Dec(Count, Remaining); end; Result := Result - Count; end; {---------------------------------------------------------------------------} {$ENDIF} { TStreamReader } {$IFDEF STRING_UNICODE} const S_ERR_CP_NOSUPPORT = 'Unsupported code page %s'; const DEFAULT_READBUFFER_SIZE = 1024 * SizeOf(Char); {---------------------------------------------------------------------------} constructor TStreamReader.Create(Stream: TStream; BufferSize: Integer = DEFAULT_BUFSIZE; OwnsStream: Boolean = FALSE); begin Create(Stream, False); end; {---------------------------------------------------------------------------} constructor TStreamReader.Create(Stream: TStream; DetectBOM: Boolean = FALSE; CodePage: LongWord = CP_ACP; OwnsStream: Boolean = FALSE; BufferSize: Integer = DEFAULT_BUFSIZE); begin FDetectBOM := DetectBOM; FCodePage := CodePage; inherited Create(Stream, BufferSize, OwnsStream); end; {---------------------------------------------------------------------------} constructor TStreamReader.Create(const FileName: String; Mode: Word; BufferSize: Integer = DEFAULT_BUFSIZE); begin Create(FileName, FALSE); end; {---------------------------------------------------------------------------} constructor TStreamReader.Create(const FileName: String; DetectBOM: Boolean = TRUE; CodePage: LongWord = CP_ACP; BufferSize: Integer = DEFAULT_BUFSIZE); begin FDetectBOM := DetectBOM; FCodePage := CodePage; inherited Create(FileName, fmOpenRead or fmShareDenyWrite, BufferSize); end; {---------------------------------------------------------------------------} procedure TStreamReader.Init; begin inherited; FReadBufSize := DEFAULT_READBUFFER_SIZE; SetMaxLineLength(MAXINT); SetLength(FReadBuffer, FReadBufSize + SizeOf(Char)); if FDetectBom then SetCodePage(GetCodePageFromBOM) else SetCodePage(FCodePage); end; {---------------------------------------------------------------------------} procedure TStreamReader.SetMaxLineLength(const Value: Integer); begin if Value < 1 then FMaxLineLength := 1 else FMaxLineLength := Value end; {---------------------------------------------------------------------------} procedure TStreamReader.SetCodePage(const Value: LongWord); var CPInfo : TCPInfo; I : Integer; J : Byte; begin case Value of CP_UTF32 : raise EStreamReaderError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE']); CP_UTF32Be : raise EStreamReaderError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 BE']); CP_ACP : begin FLeadBytes := SysUtils.Leadbytes; FCodePage := Value; end; CP_UTF8, CP_UTF16, CP_UTF16Be : begin FLeadBytes := []; FCodePage := Value; end; else if GetCPInfo(Value, CPInfo) then begin FCodePage := Value; if CPInfo.MaxCharSize > 1 then begin I := 0; while (I < MAX_LEADBYTES) and ((CPInfo.LeadByte[I] or CPInfo.LeadByte[I + 1]) <> 0) do begin for J := CPInfo.LeadByte[I] to CPInfo.LeadByte[I + 1] do Include(FLeadBytes, AnsiChar(J)); Inc(I, 2); end; end else FLeadBytes := []; end else raise EStreamReaderError.Create(SysErrorMessage(GetLastError)); end; end; {---------------------------------------------------------------------------} function TStreamReader.GetCodePageFromBOM: LongWord; var OldPos : Int64; A : array [0..3] of Byte; BomLen : Integer; begin FillChar(A, 4, #0); OldPos := Position; Seek(0, soBeginning); Read(A, 4); if (A[0] = $FF) and (A[1] = $FE) and (A[2] = 0) and (A[3] = 0) then begin raise EStreamReaderError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE detected']); end else if (A[0] = 0) and (A[1] = 0) and (A[2] = $FE) and (A[3] = $FF) then begin raise EStreamReaderError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 BE detected']); end else if (A[0] = $FF) and (A[1] = $FE) then begin Result := CP_UTF16; BomLen := 2; end else if (A[0] = $FE) and (A[1] = $FF) then begin Result := CP_UTF16Be; BomLen := 2; end else if (A[0] = $EF) and (A[1] = $BB) and (A[2] = $BF) then begin Result := CP_UTF8; BomLen := 3; end else begin Result := CP_ACP; BomLen := 0; end; if OldPos > BomLen then Position := OldPos else Position := BomLen; end; {---------------------------------------------------------------------------} function TStreamReader.DetectLineBreakStyle: TLineBreakStyle; var OldPos : Int64; ChA : AnsiChar; ChW : WideChar; CodePage : LongWord; begin Result := ilbsCRLF; OldPos := Position; CodePage := GetCodePageFromBOM; try case CodePage of CP_UTF16, CP_UTF16Be : begin Seek(2, soBeginning); while Read(ChW, SizeOf(ChW)) = SizeOf(ChW) do begin if CodePage = CP_UTF16Be then ChW := WideChar((Word(ChW) shl 8) or (Word(ChW) shr 8)); case ChW of #10 : begin if Result = ilbsCRLF then begin Result := ilbsLF; Exit; end else if Result = ilbsCR then begin Result := ilbsCRLF; Exit; end; end; #13 : begin Result := ilbsCR; end; else if Result = ilbsCR then Exit; Result := ilbsCRLF; end; end; end; else // case if CodePage = CP_UTF8 then Seek(3, soBeginning); while Read(ChA, SizeOf(ChA)) = SizeOf(ChA) do begin case ChA of #10 : begin if Result = ilbsCRLF then begin Result := ilbsLF; Exit; end else if Result = ilbsCR then begin Result := ilbsCRLF; Exit; end; end; #13 : begin Result := ilbsCR; end; else if Result = ilbsCR then Exit; Result := ilbsCRLF; end; end; end; finally Position := OldPos; end; end; {---------------------------------------------------------------------------} function TStreamReader.InternalReadLn: Boolean; var Ch : AnsiChar; Idx : Integer; P : PAnsiChar; Flag : Boolean; begin Flag := FALSE; Idx := -1; P := PAnsiChar(@FReadBuffer[0]); while Read(Ch, SizeOf(AnsiChar)) = SizeOf(AnsiChar) do begin Inc(Idx); if (Idx >= FMaxLineLength) then begin if ((FCodePage <> CP_UTF8) and (not (Ch in FLeadBytes))) or ((FCodePage = CP_UTF8) and (not IsUtf8TrailByte(Byte(Ch)))) then begin Seek(-1, soCurrent); Result := TRUE; Exit; end; end; EnsureReadBufferA(Idx + 1, P); case Ch of #10 : begin P[Idx] := #0; Result := TRUE; Exit; end; #13 : begin if Flag then begin Seek(-1, soCurrent); Result := TRUE; Exit; end; P[Idx] := #0; Flag := TRUE; end; else if Flag then begin Seek(-1, soCurrent); Result := TRUE; Exit; end; P[Idx] := Ch; end; end; if Idx >= 0 then begin P[Idx + 1] := #0; Result := TRUE; end else begin P[0] := #0; Result := FALSE; end; end; {---------------------------------------------------------------------------} function TStreamReader.InternalReadLnWLe: Boolean; var Ch : WideChar; Idx : Integer; P : PWideChar; Flag : Boolean; begin Flag := FALSE; Idx := -1; P := PWideChar(@FReadBuffer[0]); while Read(Ch, SizeOf(WideChar)) = SizeOf(WideChar) do begin Inc(Idx); if (Idx >= FMaxLineLength) and (not IsLeadChar(Ch)) then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; EnsureReadBufferW((Idx + 1) * 2, P); case Ch of #10 : begin P[Idx] := #0; Result := TRUE; Exit; end; #13 : begin if Flag then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; P[Idx] := #0; Flag := TRUE; end; else if Flag then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; P[Idx] := Ch; end; end; if Idx >= 0 then begin P[Idx + 1] := #0; Result := TRUE; end else begin P[0] := #0; Result := FALSE; end; end; {---------------------------------------------------------------------------} function TStreamReader.InternalReadLnWBe: Boolean; var Ch : WideChar; Wrd : Word; Idx : Integer; P : PWideChar; Flag : Boolean; begin Flag := FALSE; Idx := -1; P := PWideChar(@FReadBuffer[0]); while Read(Wrd, SizeOf(Word)) = SizeOf(Word) do begin Inc(Idx); Ch := WideChar((Wrd shr 8) or (Wrd shl 8)); if (Idx >= FMaxLineLength) and (not IsLeadChar(Ch)) then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; EnsureReadBufferW((Idx + 1) * 2, P); case Ch of #10 : begin P[Idx] := #0; Result := TRUE; Exit; end; #13 : begin if Flag then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; P[Idx] := #0; Flag := TRUE; end; else if Flag then begin Seek(-2, soCurrent); Result := TRUE; Exit; end; P[Idx] := Ch; end; end; if Idx >= 0 then begin P[Idx + 1] := #0; Result := TRUE; end else begin P[0] := #0; Result := FALSE; end; end; {---------------------------------------------------------------------------} function TStreamReader.ReadLine(var S: UnicodeString): Boolean; begin case FCodePage of CP_UTF16 : begin Result := InternalReadLnWLe; S := PWideChar(@FReadBuffer[0]); end; CP_UTF16Be : begin Result := InternalReadLnWBe; S := PWideChar(@FReadBuffer[0]); end; else Result := InternalReadLn; S := AnsiToUnicode(PAnsiChar(@FReadBuffer[0]), FCodePage); end; end; {---------------------------------------------------------------------------} function TStreamReader.ReadLine(var S: RawByteString): Boolean; begin case FCodePage of CP_UTF16 : begin Result := InternalReadLnWLe; S := UnicodeToAnsi(PWideChar(@FReadBuffer[0]), CP_ACP, TRUE); end; CP_UTF16Be : begin Result := InternalReadLnWBe; S := UnicodeToAnsi(PWideChar(@FReadBuffer[0]), CP_ACP, TRUE); end; else Result := InternalReadLn; S := RawByteString(PAnsiChar(@FReadBuffer[0])); {$IFDEF COMPILER_12_UP} if (S <> '') and (FCodePage <> CP_ACP) then PWord(INT_PTR(S) - 12)^ := FCodePage; {$ENDIF} end; end; {---------------------------------------------------------------------------} procedure TStreamReader.ReadToEnd(var S: RawByteString); var Buf : TBytes; begin case FCodePage of CP_UTF16 : begin SetLength(Buf, (Size - Position) + 2); Read(Buf[0], Length(Buf) - 2); Buf[Length(Buf) - 1] := 0; Buf[Length(Buf) - 2] := 0; S := UnicodeToAnsi(PWideChar(@Buf[0]), CP_ACP, TRUE); end; CP_UTF16Be : begin SetLength(Buf, (Size - Position) + 2); Read(Buf[0], Length(Buf) - 2); Buf[Length(Buf) - 1] := 0; Buf[Length(Buf) - 2] := 0; Swap16Buf(@Buf[0], @Buf[0], (Length(Buf) - 2) div 2); S := UnicodeToAnsi(PWideChar(@Buf[0]), CP_ACP, TRUE); end; else SetLength(S, Size - Position); Read(PAnsiChar(S)^, Length(S)); {$IFDEF COMPILER_12_UP} if (S <> '') and (FCodePage <> CP_ACP) then PWord(INT_PTR(S) - 12)^ := FCodePage; {$ENDIF} end; end; {---------------------------------------------------------------------------} procedure TStreamReader.ReadToEnd(var S: UnicodeString); var Buf : TBytes; begin case FCodePage of CP_UTF16 : begin SetLength(S, (Size - Position) div 2); Read(PWideChar(S)^, Length(S) * 2); end; CP_UTF16Be : begin SetLength(S, (Size - Position) div 2); Read(PWideChar(S)^, Length(S) * 2); Swap16Buf(Pointer(S), Pointer(S), Length(S)); end; else SetLength(Buf, (Size - Position) + 1); Read(Buf[0], Length(Buf) - 1); Buf[Length(Buf) - 1] := 0; S := AnsiToUnicode(PAnsiChar(@Buf[0]), FCodePage); end; end; {---------------------------------------------------------------------------} procedure TStreamReader.EnsureReadBufferW(Size: Integer; var P: PWideChar); begin if Size > FReadBufSize then begin while Size > FReadBufSize do Inc(FReadBufSize, DEFAULT_READBUFFER_SIZE); SetLength(FReadBuffer, FReadBufSize); P := @FReadBuffer[0]; end; end; {---------------------------------------------------------------------------} procedure TStreamReader.EnsureReadBufferA(Size: Integer; var P: PAnsiChar); begin if Size > FReadBufSize then begin while Size > FReadBufSize do Inc(FReadBufSize, DEFAULT_READBUFFER_SIZE); SetLength(FReadBuffer, FReadBufSize); P := @FReadBuffer[0]; end; end; {---------------------------------------------------------------------------} { TStreamWriter } {---------------------------------------------------------------------------} constructor TStreamWriter.Create(Stream: TStream; BufferSize: Integer = DEFAULT_BUFSIZE; OwnsStream: Boolean = FALSE); begin Create(Stream, TRUE, FALSE, CP_ACP, FALSE, BufferSize); end; {---------------------------------------------------------------------------} constructor TStreamWriter.Create(Stream: TStream; Append: Boolean = TRUE; DetectBOM: Boolean = FALSE; CodePage: LongWord = CP_ACP; OwnsStream: Boolean = FALSE; BufferSize: Integer = DEFAULT_BUFSIZE); begin FCodePage := CodePage; inherited Create(Stream, BufferSize, OwnsStream); if DetectBom then FCodePage := GetCodePageFromBOM; if Append then Seek(0, soEnd); end; {---------------------------------------------------------------------------} constructor TStreamWriter.Create(const FileName: String; Mode: Word; BufferSize: Integer = DEFAULT_BUFSIZE); begin FCodePage := CP_ACP; inherited Create(FileName, Mode, BufferSize); end; {---------------------------------------------------------------------------} constructor TStreamWriter.Create(const FileName: String; Append: Boolean = TRUE; DetectBOM: Boolean = TRUE; CodePage: LongWord = CP_ACP; BufferSize: Integer = DEFAULT_BUFSIZE); var Mode : Word; begin FCodePage := CodePage; if Append and FileExists(FileName) then begin Mode := fmOpenReadWrite or fmShareDenyWrite; inherited Create(FileName, Mode, BufferSize); if DetectBom then FCodePage := GetCodePageFromBOM; Seek(0, soEnd); end else begin Mode := fmCreate; inherited Create(FileName, Mode, BufferSize); end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.Init; begin inherited; FReadBufSize := DEFAULT_READBUFFER_SIZE; SetLength(FReadBuffer, FReadBufSize); FWriteBufSize := DEFAULT_READBUFFER_SIZE; SetLength(FWriteBuffer, FWriteBufSize); LineBreakStyle := ilbsCRLF; end; {---------------------------------------------------------------------------} function TStreamWriter.GetCodePageFromBOM: LongWord; var OldPos : Int64; A : array [0..3] of Byte; BomLen : Integer; begin FillChar(A, 4, #0); OldPos := Position; Seek(0, soBeginning); Read(A, 4); if (A[0] = $FF) and (A[1] = $FE) and (A[2] = 0) and (A[3] = 0) then begin raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE detected']); end else if (A[0] = 0) and (A[1] = 0) and (A[2] = $FE) and (A[3] = $FF) then begin raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 BE detected']); end else if (A[0] = $FF) and (A[1] = $FE) then begin Result := CP_UTF16; BomLen := 2; end else if (A[0] = $FE) and (A[1] = $FF) then begin Result := CP_UTF16Be; BomLen := 2; end else if (A[0] = $EF) and (A[1] = $BB) and (A[2] = $BF) then begin Result := CP_UTF8; BomLen := 3; end else begin Result := CP_ACP; BomLen := 0; end; if OldPos > BomLen then Position := OldPos else Position := BomLen; end; {---------------------------------------------------------------------------} function TStreamWriter.GetBomFromCodePage(ACodePage: LongWord) : TBytes; begin case ACodePage of CP_UTF16 : begin SetLength(Result, 2); Result[0] := $FF; Result[1] := $FE; end; CP_UTF16Be : begin SetLength(Result, 2); Result[0] := $FE; Result[1] := $FF; end; CP_UTF8 : begin SetLength(Result, 3); Result[0] := $EF; Result[1] := $BB; Result[2] := $BF; end; CP_UTF32 : raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE']); CP_UTF32Be : raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE']); else SetLength(Result, 0); end; end; {---------------------------------------------------------------------------} function TStreamWriter.DetectLineBreakStyle: TLineBreakStyle; var OldPos : Int64; ChA : AnsiChar; ChW : WideChar; CodePage : LongWord; begin Result := ilbsCRLF; OldPos := Position; CodePage := GetCodePageFromBOM; try case CodePage of CP_UTF16, CP_UTF16Be : begin Seek(2, soBeginning); while Read(ChW, SizeOf(ChW)) = SizeOf(ChW) do begin if CodePage = CP_UTF16Be then ChW := WideChar((Word(ChW) shl 8) or (Word(ChW) shr 8)); case ChW of #10 : begin if Result = ilbsCRLF then begin Result := ilbsLF; Exit; end else if Result = ilbsCR then begin Result := ilbsCRLF; Exit; end; end; #13 : begin Result := ilbsCR; end; else if Result = ilbsCR then Exit; Result := ilbsCRLF; end; end; end; else // case if CodePage = CP_UTF8 then Seek(3, soBeginning); while Read(ChA, SizeOf(ChA)) = SizeOf(ChA) do begin case ChA of #10 : begin if Result = ilbsCRLF then begin Result := ilbsLF; Exit; end else if Result = ilbsCR then begin Result := ilbsCRLF; Exit; end; end; #13 : begin Result := ilbsCR; end; else if Result = ilbsCR then Exit; Result := ilbsCRLF; end; end; end; finally Position := OldPos; end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.WriteBOM; var Bom : TBytes; begin Bom := GetBomFromCodePage(FCodePage); if Length(Bom) > 0 then begin Seek(0, soBeginning); Write(Bom[0], Length(Bom)); end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.EnsureWriteBuffer(Size: Integer); begin if Size > FWriteBufSize then begin while Size > FWriteBufSize do Inc(FWriteBufSize, DEFAULT_READBUFFER_SIZE); SetLength(FWriteBuffer, FWriteBufSize); end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.EnsureReadBuffer(Size: Integer); begin if Size > FReadBufSize then begin while Size > FReadBufSize do Inc(FReadBufSize, DEFAULT_READBUFFER_SIZE); SetLength(FReadBuffer, FReadBufSize); end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.Write(const S: UnicodeString); var Len : Integer; SLen : Integer; begin SLen := Length(S); if SLen = 0 then Exit; case FCodePage of CP_UTF16 : begin WriteBuffer(Pointer(S)^, SLen * 2); end; CP_UTF16Be : begin EnsureWriteBuffer((SLen + 1) * 2); Move(Pointer(S)^, FWriteBuffer[0], SLen * 2); PWideChar(FWriteBuffer)[SLen] := #0; Swap16Buf(@FWriteBuffer[0], @FWriteBuffer[0], SLen); WriteBuffer(FWriteBuffer[0], SLen * 2); end; else Len := WideCharToMultiByte(FCodePage, 0, Pointer(S), SLen, nil, 0, nil, nil); EnsureWriteBuffer(Len); Len := WideCharToMultiByte(FCodePage, 0, Pointer(S), SLen, @FWriteBuffer[0], Len, nil, nil); WriteBuffer(FWriteBuffer[0], Len); end; //case end; {---------------------------------------------------------------------------} procedure TStreamWriter.Write(const S: RawByteString; SrcCodePage: LongWord = CP_ACP); var Len : Integer; Len1 : Integer; SLen : Integer; begin SLen := Length(S); if SLen = 0 then Exit; case FCodePage of CP_UTF8, CP_UTF7 : begin if SrcCodePage <> FCodePage then begin Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, nil, 0); EnsureReadBuffer(Len); Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, @FReadBuffer[0], Len); Len1 := WideCharToMultibyte(FCodePage, 0, @FReadBuffer[0], Len, nil, 0, nil, nil); EnsureWriteBuffer(Len1); Len1 := WideCharToMultibyte(FCodePage, 0, @FReadBuffer[0], Len, @FWriteBuffer[0], Len1, nil, nil); WriteBuffer(FWriteBuffer[0], Len1); end else WriteBuffer(Pointer(S)^, SLen); end; CP_UTF16 : begin Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, nil, 0); EnsureWriteBuffer(Len * 2); Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, @FWriteBuffer[0], Len); WriteBuffer(FWriteBuffer[0], Len * 2); end; CP_UTF16Be : begin Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, nil, 0); EnsureWriteBuffer((Len + 1) * 2); Len := MultibyteToWideChar(SrcCodePage, 0, Pointer(S), SLen, @FWriteBuffer[0], Len); PWideChar(FWriteBuffer)[Len] := #0; Swap16Buf(@FWriteBuffer[0], @FWriteBuffer[0], Len); WriteBuffer(FWriteBuffer[0], Len * 2); end; else WriteBuffer(Pointer(S)^, SLen); end; //case end; {---------------------------------------------------------------------------} procedure TStreamWriter.WriteLine(const S: RawByteString; SrcCodePage: LongWord = CP_ACP); begin Write(S, SrcCodePage); Write(FLineBreak, SrcCodePage); end; {---------------------------------------------------------------------------} procedure TStreamWriter.WriteLine(const S: UnicodeString); begin Write(S); Write(UnicodeString(FLineBreak)); end; {---------------------------------------------------------------------------} procedure TStreamWriter.SetLineBreakStyle(Value: TLineBreakStyle); begin FLineBreakStyle := Value; case FLineBreakStyle of ilbsCRLF : FLineBreak := #13#10; ilbsLF : FLineBreak := #10; else FLineBreak := #13; end; end; {---------------------------------------------------------------------------} procedure TStreamWriter.SetCodePage(const Value: LongWord); var LCPInfo: TCPInfo; begin case Value of CP_ACP, CP_UTF8, CP_UTF16, CP_UTF16Be : FCodePage := Value; CP_UTF32 : raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 LE']); CP_UTF32Be : raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, ['UTF-32 BE']); else if not GetCPInfo(Value, LCPInfo) then raise EStreamWriterError.CreateFmt(S_ERR_CP_NOSUPPORT, [SysErrorMessage(GetLastError)]); FCodePage := FCodepage; end; end; {---------------------------------------------------------------------------} {$ENDIF} function StreamReadLine(const AStream: TStream): AnsiString; // totally junky implementation!! var c: AnsiChar; l: Integer; begin l := 0; SetLength(Result, 100); c := #0; while (AStream.Position < AStream.Size) and (c <> #13) and (c <> #10) do begin AStream.Read(c, 1); Inc(l); if l > Length(Result) then SetLength(Result, Length(Result) + 100); Result[l] := c; end; if (c = #13) then begin AStream.Read(c, 1); if c <> #10 then begin AStream.Seek(-1, soFromCurrent); end; end; SetLength(Result, l); end; procedure StreamWriteLine(const AStream: TStream; const AString: AnsiString); var LineTerminator: AnsiString; begin if length(AString) > 0 then begin AStream.WriteBuffer(AString[1], Length(AString)); end; LineTerminator := LineEnding; AStream.Write(LineTerminator[1], Length(LineTerminator)); end; procedure StreamWriteString(const AStream: TStream; const AString: AnsiString); begin if length(AString) > 0 then begin AStream.WriteBuffer(AString[1], Length(AString)); end; end; end. ��������������������������������������������������������������������������������pasdoc/source/component/PasDoc_Tokenizer.pas��������������������������������������������������������0000600�0001750�0001750�00000104377�12452071420�021706� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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_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', '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/external_class_hierarchy.txt������������������������������������������������0000600�0001750�0001750�00000007777�11617717624�023631� 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_HierarchyTree.pas����������������������������������������������������0000600�0001750�0001750�00000020271�12337202423�022461� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { @cvs($Date: 2014-05-21 21:57:07 +0200 (śro) $) @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/images/���������������������������������������������������������������������0000700�0001750�0001750�00000000000�12561642314�017234� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/published.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�10352607623�022456� 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/protected.gif��������������������������������������������������������0000600�0001750�0001750�00000000215�10352607623�021714� 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�10352607623�022147� 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/published.gif��������������������������������������������������������0000600�0001750�0001750�00000000215�10352607623�021702� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL8���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/automated.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�10352607623�022462� 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/public.gif�����������������������������������������������������������0000600�0001750�0001750�00000000215�10352607623�021201� 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�10352607623�021706� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL?���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/Makefile�������������������������������������������������������������0000600�0001750�0001750�00000000605�10352607623�020677� 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/protected.gif.inc����������������������������������������������������0000600�0001750�0001750�00000001524�10352607623�022470� 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/private.gif����������������������������������������������������������0000600�0001750�0001750�00000000215�10352607623�021375� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a � ��fL���!�����!Created with The GIMP�,���� � ��E @�%J(Q Ą F0a„!&L0"@ &1a„*L0@ &PD @�;�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/images/public.gif.inc�������������������������������������������������������0000600�0001750�0001750�00000001521�10352607623�021752� 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/PasDoc_Reg.pas��������������������������������������������������������������0000600�0001750�0001750�00000003072�12337202423�020440� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { @abstract(Registers the PasDoc components into the IDE. ) @author(Ralf Junker (delphi@zeitungsjunge.de)) @author(Johannes Berg <johannes@sipsolutions.de>) @author(Michalis Kamburelis) @cvs($Date: 2014-05-21 21:57:07 +0200 (śro) $) 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_Languages.pas��������������������������������������������������������0000600�0001750�0001750�00000050735�12561551651�021652� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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, 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, //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 //the table of the selected language pTable: PTransTable; FCharSet: string; { @abstract(gets a translation token) } function GetTranslation(ATranslationID: TTranslationID): string; procedure SetTranslation(id: TTranslationID; const into: string); property FTranslation[id: TTranslationID]: string read GetTranslation write SetTranslation; 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 suitable for Aspell. } function LanguageAspellCode(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 := pTable^[ATranslationID]; if Result <= strKeep then Result := aEnglish[ATranslationID]; end; procedure TPasDocLanguages.SetTranslation(id: TTranslationID; const into: string); begin pTable^[id] := into; end; constructor TPasDocLanguages.Create; begin inherited; SetLanguage(DEFAULT_LANGUAGE); end; procedure TPasDocLanguages.SetLanguage(const Value: TLanguageID); begin 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} //get table pTable := LANGUAGE_ARRAY[Value].Table; Assert(Assigned(pTable)); 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 LanguageAspellCode(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_kylixversions.inc����������������������������������������������������0000600�0001750�0001750�00000002422�12337202423�022740� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/PasDoc_ProcessLineTalk.pas��������������������������������������������������0000600�0001750�0001750�00000015674�12337202423�023000� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------- } { @abstract(Talking with another process through pipes.) @author(Michalis Kamburelis) @author(Arno Garrels <first name.name@nospamgmx.de>)} unit PasDoc_ProcessLineTalk; {$I pasdoc_defines.inc} {$ifdef FPC} {$IFNDEF VER1_0} {$ifdef UNIX} {$define HAS_PROCESS} {$endif} {$ifdef WIN32} {$define HAS_PROCESS} {$endif} {$ELSE} {$ifdef LINUX} {$define HAS_PROCESS} {$endif} {$ifdef BSD} {$define HAS_PROCESS} {$endif} {$ifdef WIN32} {$define HAS_PROCESS} {$endif} {$ENDIF} {$endif} interface uses SysUtils, Classes {$ifdef HAS_PROCESS} , Process {$endif}; type { TTextReader reads given Stream line by line. Lines may be terminated in Stream with #13, #10, #13+#10 or #10+#13. This way I can treat any TStream quite like standard Pascal text files: I have simple Readln method. After calling Readln or Eof you should STOP directly using underlying Stream (but you CAN use Stream right after creating TTextReader.Create(Stream) and before any Readln or Eof operations on this TTextReader). Original version of this class comes from Michalis Kamburelis code library, see [http://www.camelot.homedns.org/~michalis/], unit base/KambiClassUtils.pas. } TTextReader = class private Stream: TStream; ReadBuf: string; FOwnsStream: boolean; { This is either #0 or #10 (tells to ignore next #13 char) or #13 (tells to ignore next #10 char) } LastNewLineChar: char; public { This is a comfortable constructor, equivalent to TTextReader.Create(TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite), true) } constructor CreateFromFileStream(const FileName: string); { If AOwnsStream then in Destroy we will free Stream object. } constructor Create(AStream: TStream; AOwnsStream: boolean); destructor Destroy; override; { Reads next line from Stream. Returned string does not contain any end-of-line characters. } function Readln: string; function Eof: boolean; end; { This is a subclass of TProcess that allows to easy "talk" with executed process by pipes (read process stdout/stderr, write to process stdin) on a line-by-line basis. If symbol HAS_PROCESS is not defined, this defines a junky implementation of TProcessLineTalk class that can't do anything and raises exception when you try to execute a process. } {$ifdef HAS_PROCESS} TProcessLineTalk = class(TProcess) private OutputLineReader: TTextReader; public { Adds poUsePipes to Options, since it's not reasonable to use this class when you don't want to communicate with process using pipes. } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Execute; override; procedure WriteLine(const S: string); function ReadLine: string; end; {$else HAS_PROCESS} TProcessLineTalk = class(TComponent) private FCommandLine: string; public procedure Execute; procedure WriteLine(const S: string); function ReadLine: string; published property CommandLine: string read FCommandLine write FCommandLine; end; {$endif else HAS_PROCESS} implementation uses PasDoc_Types, PasDoc_Utils, PasDoc_StreamUtils; { TTextReader ---------------------------------------------------------------- } constructor TTextReader.CreateFromFileStream(const FileName: string); begin Create(TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite), true); end; constructor TTextReader.Create(AStream: TStream; AOwnsStream: boolean); begin inherited Create; Stream := AStream; FOwnsStream := AOwnsStream; LastNewLineChar := #0; end; destructor TTextReader.Destroy; begin if FOwnsStream then Stream.Free; inherited; end; function TTextReader.Readln: string; const BUF_INC = 100; var ReadCnt, i: integer; begin i := 1; { Note that ReadBuf may contain data that we already read from stream at some time but did not returned it to user of this class (because we realized we have read too much). } repeat if i > Length(ReadBuf) then begin SetLength(ReadBuf, Length(ReadBuf) + BUF_INC); ReadCnt := Stream.Read(ReadBuf[Length(ReadBuf) - BUF_INC + 1], BUF_INC); SetLength(ReadBuf, Length(ReadBuf) - BUF_INC + ReadCnt); if ReadCnt = 0 then begin Result := ReadBuf; ReadBuf := ''; Exit; end; end; if ((ReadBuf[i] = #10) and (LastNewLineChar = #13)) or ((ReadBuf[i] = #13) and (LastNewLineChar = #10)) then begin { We got 2nd newline character ? Ignore it. } Assert(i = 1); Delete(ReadBuf, 1, 1); LastNewLineChar := #0; end else if IsCharInSet(ReadBuf[i], [#10, #13]) then begin Result := Copy(ReadBuf, 1, i-1); LastNewLineChar := ReadBuf[i]; Delete(ReadBuf, 1, i); Exit; end else begin LastNewLineChar := #0; Inc(i); end; until false; end; function TTextReader.Eof: boolean; var ReadCnt: Integer; begin if ReadBuf = '' then begin SetLength(ReadBuf, 1); ReadCnt := Stream.Read(ReadBuf[1], 1); SetLength(ReadBuf, ReadCnt); end; Result := ReadBuf = ''; end; { TProcessLineTalk ----------------------------------------------------------- } {$ifdef HAS_PROCESS} constructor TProcessLineTalk.Create(AOwner: TComponent); begin inherited; Options := Options + [poUsePipes, poStdErrToOutput]; end; destructor TProcessLineTalk.Destroy; begin FreeAndNil(OutputLineReader); Active := False; inherited; end; procedure TProcessLineTalk.Execute; begin inherited; FreeAndNil(OutputLineReader); OutputLineReader := TTextReader.Create(Output, false); end; procedure TProcessLineTalk.WriteLine(const S: string); begin StreamWriteLine(Input, S); end; function TProcessLineTalk.ReadLine: string; begin Result := OutputLineReader.Readln; end; {$else HAS_PROCESS} procedure TProcessLineTalk.Execute; begin raise Exception.Create('TProcessLineTalk.Execute: not implemented'); end; procedure TProcessLineTalk.WriteLine(const S: string); begin raise Exception.Create('TProcessLineTalk.WriteLine: not implemented'); end; function TProcessLineTalk.ReadLine: string; begin raise Exception.Create('TProcessLineTalk.ReadLine: not implemented'); end; {$endif else HAS_PROCESS} end.��������������������������������������������������������������������pasdoc/source/component/PasDoc_GenSimpleXML.pas�����������������������������������������������������0000600�0001750�0001750�00000027060�12561510772�022202� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ Copyright 1998-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/tipue/����������������������������������������������������������������������0000700�0001750�0001750�00000000000�12561642315�017116� 5����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pasdoc/source/component/tipue/tipuesearch.js��������������������������������������������������������0000600�0001750�0001750�00000044042�12224616420�021770� 0����������������������������������������������������������������������������������������������������ustar �michalis������������������������michalis��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� /* 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('<title>'); 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/_tipue_results.html.inc0000600000175000017500000000143112224616420023615 0ustar michalismichalis{ -*- buffer-read-only: t -*- } { DON'T EDIT -- this file was automatically generated from "_tipue_results.html" } '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + 'Search Results' + LineEnding + '' + LineEnding + '###-PASDOC-HEAD-###' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '###-PASDOC-BODY-BEGIN-###' + LineEnding + '' + LineEnding + '

Search results

' + LineEnding + '' + LineEnding + '
' + LineEnding + '' + LineEnding + '###-PASDOC-BODY-END-###' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' pasdoc/source/component/tipue/jquery.js0000600000175000017500000072510412337204203020775 0ustar michalismichalis/*! * jQuery JavaScript Library v2.0.0 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ * * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2013-04-18 */ (function( window, undefined ) { // Can't do this because several apps including ASP.NET trace // the stack via arguments.caller.callee and Firefox dies if // you try to trace through "use strict" call chains. (#13335) // Support: Firefox 18+ //"use strict"; var // A central reference to the root jQuery(document) rootjQuery, // The deferred used on DOM ready readyList, // Support: IE9 // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` core_strundefined = typeof undefined, // Use the correct document accordingly with window argument (sandbox) location = window.location, document = window.document, docElem = document.documentElement, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // [[Class]] -> type pairs class2type = {}, // List of deleted data cache ids, so we can reuse them core_deletedIds = [], core_version = "2.0.0", // Save a reference to some core methods core_concat = core_deletedIds.concat, core_push = core_deletedIds.push, core_slice = core_deletedIds.slice, core_indexOf = core_deletedIds.indexOf, core_toString = class2type.toString, core_hasOwn = class2type.hasOwnProperty, core_trim = core_version.trim, // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Used for matching numbers core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, // Used for splitting on whitespace core_rnotwhite = /\S+/g, // A simple way to check for HTML strings // Prioritize #id over to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([\da-z])/gi, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return letter.toUpperCase(); }, // The ready event handler and self cleanup method completed = function() { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); jQuery.ready(); }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: core_version, constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle HTML strings if ( typeof selector === "string" ) { if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; // scripts is true for back-compat jQuery.merge( this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The default length of a jQuery object is 0 length: 0, toArray: function() { return core_slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Add the callback jQuery.ready.promise().done( fn ); return this; }, slice: function() { return this.pushStack( core_slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: core_push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ // Unique for each copy of jQuery on the page expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Abort if there are pending holds or we're already ready if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger("ready").off("ready"); } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray, isWindow: function( obj ) { return obj != null && obj === obj.window; }, isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, type: function( obj ) { if ( obj == null ) { return String( obj ); } // Support: Safari <= 5.1 (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ core_toString.call(obj) ] || "object" : typeof obj; }, isPlainObject: function( obj ) { // Not plain objects: // - Any object or value whose internal [[Class]] property is not "[object Object]" // - DOM nodes // - window if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } // Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if ( obj.constructor && !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { return false; } } catch ( e ) { return false; } // If the function hasn't returned already, we're confident that // |obj| is a plain object, created by {} or constructed with new Object return true; }, isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }, error: function( msg ) { throw new Error( msg ); }, // data: string of html // context (optional): If specified, the fragment will be created in this context, defaults to document // keepScripts (optional): If true, will include scripts passed in the html string parseHTML: function( data, context, keepScripts ) { if ( !data || typeof data !== "string" ) { return null; } if ( typeof context === "boolean" ) { keepScripts = context; context = false; } context = context || document; var parsed = rsingleTag.exec( data ), scripts = !keepScripts && []; // Single tag if ( parsed ) { return [ context.createElement( parsed[1] ) ]; } parsed = jQuery.buildFragment( [ data ], context, scripts ); if ( scripts ) { jQuery( scripts ).remove(); } return jQuery.merge( [], parsed.childNodes ); }, parseJSON: JSON.parse, // Cross-browser xml parsing parseXML: function( data ) { var xml, tmp; if ( !data || typeof data !== "string" ) { return null; } // Support: IE9 try { tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } catch ( e ) { xml = undefined; } if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context globalEval: function( code ) { var script, indirect = eval; code = jQuery.trim( code ); if ( code ) { // If the code includes a valid, prologue position // strict mode pragma, execute code by injecting a // script tag into the document. if ( code.indexOf("use strict") === 1 ) { script = document.createElement("script"); script.text = code; document.head.appendChild( script ).parentNode.removeChild( script ); } else { // Otherwise, avoid the DOM node creation, insertion // and removal by using an indirect global eval indirect( code ); } } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }, // args is for internal usage only each: function( obj, callback, args ) { var value, i = 0, length = obj.length, isArray = isArraylike( obj ); if ( args ) { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } } return obj; }, trim: function( text ) { return text == null ? "" : core_trim.call( text ); }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArraylike( Object(arr) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { core_push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { return arr == null ? -1 : core_indexOf.call( arr, elem, i ); }, merge: function( first, second ) { var l = second.length, i = first.length, j = 0; if ( typeof l === "number" ) { for ( ; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var retVal, ret = [], i = 0, length = elems.length; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, i = 0, length = elems.length, isArray = isArraylike( elems ), ret = []; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return core_concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { var tmp, args, proxy; if ( typeof context === "string" ) { tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind args = core_slice.call( arguments, 2 ); proxy = function() { return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || jQuery.guid++; return proxy; }, // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function access: function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, length = elems.length, bulk = key == null; // Sets many values if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); } // Sets one value } else if ( value !== undefined ) { chainable = true; if ( !jQuery.isFunction( value ) ) { raw = true; } if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < length; i++ ) { fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); } } } return chainable ? elems : // Gets bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet; }, now: Date.now, // A method for quickly swapping in/out CSS properties to get correct calculations. // Note: this method belongs to the css module but it's needed here for the support module. // If support gets modularized, this method should be moved back to the css module. swap: function( elem, options, callback, args ) { var ret, name, old = {}; // Remember the old values, and insert the new ones for ( name in options ) { old[ name ] = elem.style[ name ]; elem.style[ name ] = options[ name ]; } ret = callback.apply( elem, args || [] ); // Revert the old values for ( name in options ) { elem.style[ name ] = old[ name ]; } return ret; } }); jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); // Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready setTimeout( jQuery.ready ); } else { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed, false ); } } return readyList.promise( obj ); }; // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); function isArraylike( obj ) { var length = obj.length, type = jQuery.type( obj ); if ( jQuery.isWindow( obj ) ) { return false; } if ( obj.nodeType === 1 && length ) { return true; } return type === "array" || type !== "function" && ( length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj ); } // All jQuery objects should point back to these rootjQuery = jQuery(document); /*! * Sizzle CSS Selector Engine v1.9.2-pre * http://sizzlejs.com/ * * Copyright 2013 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2013-04-16 */ (function( window, undefined ) { var i, cachedruns, Expr, getText, isXML, compile, outermostContext, sortInput, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + -(new Date()), preferredDoc = window.document, support = {}, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), hasDuplicate = false, sortOrder = function() { return 0; }, // General-purpose constants strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, // Array methods arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf if we can't use a native one indexOf = arr.indexOf || function( elem ) { var i = 0, len = this.length; for ( ; i < len; i++ ) { if ( this[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/css3-syntax/#characters characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", // Loosely modeled on CSS identifier characters // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = characterEncoding.replace( "w", "w#" ), // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", // Prefer arguments quoted, // then not containing pseudos/brackets, // then attribute selectors/non-parenthetical expressions, // then anything else // These preferences are here to reduce the number of selectors // needing tokenize in the PSEUDO preFilter pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rsibling = new RegExp( whitespace + "*[+~]" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + characterEncoding + ")" ), "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "boolean": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rescape = /'|\\/g, // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, funescape = function( _, escaped ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint return high !== high ? escaped : // BMP codepoint high < 0 ? String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }; // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } /** * For feature detection * @param {Function} fn The function to test for native support */ function isNative( fn ) { return rnative.test( fn + "" ); } /** * Create key-value caches of limited size * @returns {Function(string, Object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var cache, keys = []; return (cache = function( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key += " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key ] = value); }); } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created div and expects a boolean result */ function assert( fn ) { var div = document.createElement("div"); try { return !!fn( div ); } catch (e) { return false; } finally { if ( div.parentNode ) { div.parentNode.removeChild( div ); } // release memory in IE div = null; } } function Sizzle( selector, context, results, seed ) { var match, elem, m, nodeType, // QSA vars i, groups, old, nid, newContext, newSelector; if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; results = results || []; if ( !selector || typeof selector !== "string" ) { return results; } if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { return []; } if ( documentIsHTML && !seed ) { // Shortcuts if ( (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") if ( (m = match[1]) ) { if ( nodeType === 9 ) { elem = context.getElementById( m ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE, Opera, and Webkit return items // by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } } else { // Context is not a document if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Speed-up: Sizzle("TAG") } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Speed-up: Sizzle(".CLASS") } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // QSA path if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; newSelector = nodeType === 9 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { groups = tokenize( selector ); if ( (old = context.getAttribute("id")) ) { nid = old.replace( rescape, "\\$&" ); } else { context.setAttribute( "id", nid ); } nid = "[id='" + nid + "'] "; i = groups.length; while ( i-- ) { groups[i] = nid + toSelector( groups[i] ); } newContext = rsibling.test( selector ) && context.parentNode || context; newSelector = groups.join(","); } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch(qsaError) { } finally { if ( !old ) { context.removeAttribute("id"); } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Detect xml * @param {Element|Object} elem An element or a document */ isXML = Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var doc = node ? node.ownerDocument || node : preferredDoc; // If no document and documentElement is available, return if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } // Set our document document = doc; docElem = doc.documentElement; // Support tests documentIsHTML = !isXML( doc ); // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert(function( div ) { div.appendChild( doc.createComment("") ); return !div.getElementsByTagName("*").length; }); // Support: IE<8 // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) support.attributes = assert(function( div ) { div.className = "i"; return !div.getAttribute("className"); }); // Check if getElementsByClassName can be trusted support.getElementsByClassName = assert(function( div ) { div.innerHTML = "
"; // Support: Safari<4 // Catch class over-caching div.firstChild.className = "i"; // Support: Opera<10 // Catch gEBCN failure to find non-leading classes return div.getElementsByClassName("i").length === 2; }); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert(function( div1 ) { // Should return 1, but returns 4 (following) return div1.compareDocumentPosition( document.createElement("div") ) & 1; }); // Support: IE<10 // Check if getElementById returns elements by name // Support: Windows 8 Native Apps // Assigning innerHTML with "name" attributes throws uncatchable exceptions // (http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx) // and the broken getElementById methods don't pick up programatically-set names, // so use a roundabout getElementsByName test support.getById = assert(function( div ) { docElem.appendChild( div ).id = expando; return !doc.getElementsByName || !doc.getElementsByName( expando ).length; }); // ID find and filter if ( support.getById ) { Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== strundefined && documentIsHTML ) { var m = context.getElementById( id ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute("id") === attrId; }; }; } else { Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== strundefined && documentIsHTML ) { var m = context.getElementById( id ); return m ? m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? [m] : undefined : []; } }; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; } // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== strundefined ) { return context.getElementsByTagName( tag ); } } : function( tag, context ) { var elem, tmp = [], i = 0, results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { while ( (elem = results[i++]) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } } return tmp; } return results; }; // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { return context.getElementsByClassName( className ); } }; // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See http://bugs.jquery.com/ticket/13378 rbuggyQSA = []; if ( (support.qsa = isNative(doc.querySelectorAll)) ) { // Build QSA regex // Regex strategy adopted from Diego Perini assert(function( div ) { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // http://bugs.jquery.com/ticket/12359 div.innerHTML = ""; // Support: IE8 // Boolean attributes and "value" are not treated correctly if ( !div.querySelectorAll("[selected]").length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } }); assert(function( div ) { // Support: Opera 10-12/IE8 // ^= $= *= and empty values // Should not select anything // Support: Windows 8 Native Apps // The type attribute is restricted during .innerHTML assignment var input = document.createElement("input"); input.setAttribute( "type", "hidden" ); div.appendChild( input ).setAttribute( "t", "" ); if ( div.querySelectorAll("[t^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":enabled").length ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Opera 10-11 does not throw on post-comma invalid pseudos div.querySelectorAll("*,:x"); rbuggyQSA.push(",.*:"); }); } if ( (support.matchesSelector = isNative( (matches = docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector) )) ) { assert(function( div ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( div, "div" ); // This should fail with an exception // Gecko does not error, returns false instead matches.call( div, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); }); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); // Element contains another // Purposefully does not implement inclusive descendent // As in, an element does not contain itself contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; return a === bup || !!( bup && bup.nodeType === 1 && ( adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 )); } : function( a, b ) { if ( b ) { while ( (b = b.parentNode) ) { if ( b === a ) { return true; } } } return false; }; // Document order sorting sortOrder = docElem.compareDocumentPosition ? function( a, b ) { // Flag for duplicate removal if ( a === b ) { hasDuplicate = true; return 0; } var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); if ( compare ) { // Disconnected nodes if ( compare & 1 || (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document if ( a === doc || contains(preferredDoc, a) ) { return -1; } if ( b === doc || contains(preferredDoc, b) ) { return 1; } // Maintain original order return sortInput ? ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; } // Not directly comparable, sort on existence of method return a.compareDocumentPosition ? -1 : 1; } : function( a, b ) { var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ]; // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; return 0; // Parentless nodes are either documents or disconnected } else if ( !aup || !bup ) { return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check } else if ( aup === bup ) { return siblingCheck( a, b ); } // Otherwise we need full lists of their ancestors for comparison cur = a; while ( (cur = cur.parentNode) ) { ap.unshift( cur ); } cur = b; while ( (cur = cur.parentNode) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy while ( ap[i] === bp[i] ) { i++; } return i ? // Do a sibling check if the nodes have a common ancestor siblingCheck( ap[i], bp[i] ) : // Otherwise nodes in our document sort first ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; }; return document; }; Sizzle.matches = function( expr, elements ) { return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); // rbuggyQSA always contains :focus, so no need for an existence check if ( support.matchesSelector && documentIsHTML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr)) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9 elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch(e) {} } return Sizzle( expr, document, null, [elem] ).length > 0; }; Sizzle.contains = function( context, elem ) { // Set document vars if needed if ( ( context.ownerDocument || context ) !== document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], val = fn && fn( elem, name, !documentIsHTML ); return val === undefined ? support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null : val; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; // Document sorting and removing duplicates Sizzle.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates; sortInput = !support.sortStable && results.slice( 0 ); results.sort( sortOrder ); if ( hasDuplicate ) { while ( (elem = results[i++]) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } } while ( j-- ) { results.splice( duplicates[ j ], 1 ); } } return results; }; /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns Returns -1 if a precedes b, 1 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } // Fetches boolean attributes by node function boolHandler( elem, name, isXML ) { var val; return isXML ? undefined : (val = elem.getAttributeNode( name )) && val.specified ? val.value : elem[ name ] === true ? name.toLowerCase() : null; } // Fetches attributes without interpolation // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx function interpolationHandler( elem, name, isXML ) { var val; return isXML ? undefined : (val = elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 )); } // Returns a function to use in pseudos for input types function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } // Returns a function to use in pseudos for buttons function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } // Returns a function to use in pseudos for positionals function createPositionalPseudo( fn ) { return markFunction(function( argument ) { argument = +argument; return markFunction(function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ (j = matchIndexes[i]) ] ) { seed[j] = !(matches[j] = seed[j]); } } }); }); } /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { var node, ret = "", i = 0, nodeType = elem.nodeType; if ( !nodeType ) { // If no nodeType, this is expected to be an array for ( ; (node = elem[i]); i++ ) { // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (see #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } // Do not include comment or processing instruction nodes return ret; }; Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }, preFilter: { "ATTR": function( match ) { match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase(); if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments } else if ( match[3] ) { Sizzle.error( match[0] ); } return match; }, "PSEUDO": function( match ) { var excess, unquoted = !match[5] && match[2]; if ( matchExpr["CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is if ( match[4] ) { match[2] = match[4]; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) (excess = tokenize( unquoted, true )) && // advance to the next closing parenthesis (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }, filter: { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { var pattern = classCache[ className + " " ]; return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); }); }, "ATTR": function( name, operator, check ) { return function( elem ) { var result = Sizzle.attr( elem, name ); if ( result == null ) { return operator === "!="; } if ( !operator ) { return true; } result += ""; return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; }, "CHILD": function( type, what, argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; return first === 1 && last === 0 ? // Shortcut for :nth-*(n) function( elem ) { return !!elem.parentNode; } : function( elem, context, xml ) { var cache, outerCache, node, diff, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType; if ( parent ) { // :(first|last|only)-(child|of-type) if ( simple ) { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { return false; } } // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } return true; } start = [ forward ? parent.firstChild : parent.lastChild ]; // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { // Seek `elem` from a previously-cached index outerCache = parent[ expando ] || (parent[ expando ] = {}); cache = outerCache[ type ] || []; nodeIndex = cache[0] === dirruns && cache[1]; diff = cache[0] === dirruns && cache[2]; node = nodeIndex && parent.childNodes[ nodeIndex ]; while ( (node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start (diff = nodeIndex = 0) || start.pop()) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { outerCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } // Use previously-cached element index if available } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { diff = cache[1]; // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) } else { // Use the same loop as above to seek `elem` from the start while ( (node = ++nodeIndex && node && node[ dir ] || (diff = nodeIndex = 0) || start.pop()) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { // Cache the index of each encountered element if ( useCache ) { (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; } if ( node === elem ) { break; } } } } // Incorporate the offset, then check against cycle size diff -= last; return diff === first || ( diff % first === 0 && diff / first >= 0 ); } }; }, "PSEUDO": function( pseudo, argument ) { // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos var args, fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || Sizzle.error( "unsupported pseudo: " + pseudo ); // The user may use createPseudo to indicate that // arguments are needed to create the filter function // just as Sizzle does if ( fn[ expando ] ) { return fn( argument ); } // But maintain support for old signatures if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? markFunction(function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { idx = indexOf.call( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : function( elem ) { return fn( elem, 0, args ); }; } return fn; } }, pseudos: { // Potentially complex pseudos "not": markFunction(function( selector ) { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators var input = [], results = [], matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? markFunction(function( seed, matches, context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { if ( (elem = unmatched[i]) ) { seed[i] = !(matches[i] = elem); } } }) : function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); return !results.pop(); }; }), "has": markFunction(function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; }), "contains": markFunction(function( text ) { return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; }), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value // being equal to the identifier C, // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { // lang value must be a valid identifier if ( !ridentifier.test(lang || "") ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { if ( (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); return false; }; }), // Miscellaneous "target": function( elem ) { var hash = window.location && window.location.hash; return hash && hash.slice( 1 ) === elem.id; }, "root": function( elem ) { return elem === docElem; }, "focus": function( elem ) { return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); }, // Boolean properties "enabled": function( elem ) { return elem.disabled === false; }, "disabled": function( elem ) { return elem.disabled === true; }, "checked": function( elem ) { // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); }, "selected": function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, // Contents "empty": function( elem ) { // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), // not comment, processing instructions, or others // Thanks to Diego Perini for the nodeName shortcut // Greater than "@" means alpha characters (specifically not starting with "#" or "?") for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { return false; } } return true; }, "parent": function( elem ) { return !Expr.pseudos["empty"]( elem ); }, // Element/input types "header": function( elem ) { return rheader.test( elem.nodeName ); }, "input": function( elem ) { return rinputs.test( elem.nodeName ); }, "button": function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === "button" || name === "button"; }, "text": function( elem ) { var attr; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); }, // Position-in-collection "first": createPositionalPseudo(function() { return [ 0 ]; }), "last": createPositionalPseudo(function( matchIndexes, length ) { return [ length - 1 ]; }), "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; }), "even": createPositionalPseudo(function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "odd": createPositionalPseudo(function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; }), "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; }) } }; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { Expr.pseudos[ i ] = createInputPseudo( i ); } for ( i in { submit: true, reset: true } ) { Expr.pseudos[ i ] = createButtonPseudo( i ); } function tokenize( selector, parseOnly ) { var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[ selector + " " ]; if ( cached ) { return parseOnly ? 0 : cached.slice( 0 ); } soFar = selector; groups = []; preFilters = Expr.preFilter; while ( soFar ) { // Comma and first run if ( !matched || (match = rcomma.exec( soFar )) ) { if ( match ) { // Don't consume trailing commas as valid soFar = soFar.slice( match[0].length ) || soFar; } groups.push( tokens = [] ); } matched = false; // Combinators if ( (match = rcombinators.exec( soFar )) ) { matched = match.shift(); tokens.push( { value: matched, // Cast descendant combinators to space type: match[0].replace( rtrim, " " ) } ); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || (match = preFilters[ type ]( match ))) ) { matched = match.shift(); tokens.push( { value: matched, type: type, matches: match } ); soFar = soFar.slice( matched.length ); } } if ( !matched ) { break; } } // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens return parseOnly ? soFar.length : soFar ? Sizzle.error( selector ) : // Cache the tokens tokenCache( selector, groups ).slice( 0 ); } function toSelector( tokens ) { var i = 0, len = tokens.length, selector = ""; for ( ; i < len; i++ ) { selector += tokens[i].value; } return selector; } function addCombinator( matcher, combinator, base ) { var dir = combinator.dir, checkNonElements = base && dir === "parentNode", doneName = done++; return combinator.first ? // Check against closest ancestor/preceding element function( elem, context, xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } } } : // Check against all ancestor/preceding elements function( elem, context, xml ) { var data, cache, outerCache, dirkey = dirruns + " " + doneName; // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching if ( xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; } } } } else { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || (elem[ expando ] = {}); if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { if ( (data = cache[1]) === true || data === cachedruns ) { return data === true; } } else { cache = outerCache[ dir ] = [ dirkey ]; cache[1] = matcher( elem, context, xml ) || cachedruns; if ( cache[1] === true ) { return true; } } } } } }; } function elementMatcher( matchers ) { return matchers.length > 1 ? function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { if ( !matchers[i]( elem, context, xml ) ) { return false; } } return true; } : matchers[0]; } function condense( unmatched, map, filter, context, xml ) { var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null; for ( ; i < len; i++ ) { if ( (elem = unmatched[i]) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { map.push( i ); } } } } return newUnmatched; } function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { if ( postFilter && !postFilter[ expando ] ) { postFilter = setMatcher( postFilter ); } if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } return markFunction(function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : elems, matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? // ...intermediate processing is necessary [] : // ...otherwise use results directly results : matcherIn; // Find primary matches if ( matcher ) { matcher( matcherIn, matcherOut, context, xml ); } // Apply postFilter if ( postFilter ) { temp = condense( matcherOut, postMap ); postFilter( temp, [], context, xml ); // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { if ( (elem = temp[i]) ) { matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); } } } if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) ) { // Restore matcherIn since elem is not yet a final match temp.push( (matcherIn[i] = elem) ); } } postFinder( null, (matcherOut = []), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } } } // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut ); if ( postFinder ) { postFinder( null, results, matcherOut, xml ); } else { push.apply( results, matcherOut ); } } }); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[ tokens[0].type ], implicitRelative = leadingRelative || Expr.relative[" "], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) matchContext = addCombinator( function( elem ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { return indexOf.call( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); } ]; for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; } else { matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { if ( Expr.relative[ tokens[j].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), j < len && toSelector( tokens ) ); } matchers.push( matcher ); } } return elementMatcher( matchers ); } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { // A counter to specify which element is currently being matched var matcherCachedRuns = 0, bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function( seed, context, xml, results, expandContext ) { var elem, j, matcher, setMatched = [], matchedCount = 0, i = "0", unmatched = seed && [], outermost = expandContext != null, contextBackup = outermostContext, // We must always have either seed elements or context elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), // Use integer dirruns iff this is the outermost matcher dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); if ( outermost ) { outermostContext = context !== document && context; cachedruns = matcherCachedRuns; } // Add elements passing elementMatchers directly to results // Keep `i` a string if there are no elements so `matchedCount` will be "00" below for ( ; (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; while ( (matcher = elementMatchers[j++]) ) { if ( matcher( elem, context, xml ) ) { results.push( elem ); break; } } if ( outermost ) { dirruns = dirrunsUnique; cachedruns = ++matcherCachedRuns; } } // Track unmatched elements for set filters if ( bySet ) { // They will have gone through all possible matchers if ( (elem = !matcher && elem) ) { matchedCount--; } // Lengthen the array for every element, matched or not if ( seed ) { unmatched.push( elem ); } } } // Apply set filters to unmatched elements matchedCount += i; if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { if ( !(unmatched[i] || setMatched[i]) ) { setMatched[i] = pop.call( results ); } } } // Discard index placeholder values to get only actual matches setMatched = condense( setMatched ); } // Add matches to results push.apply( results, setMatched ); // Seedless set matches succeeding multiple successful matchers stipulate sorting if ( outermost && !seed && setMatched.length > 0 && ( matchedCount + setMatchers.length ) > 1 ) { Sizzle.uniqueSort( results ); } } // Override manipulation of globals by nested matchers if ( outermost ) { dirruns = dirrunsUnique; outermostContext = contextBackup; } return unmatched; }; return bySet ? markFunction( superMatcher ) : superMatcher; } compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], cached = compilerCache[ selector + " " ]; if ( !cached ) { // Generate a function of recursive functions that can be used to check each element if ( !group ) { group = tokenize( selector ); } i = group.length; while ( i-- ) { cached = matcherFromTokens( group[i] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { elementMatchers.push( cached ); } } // Cache the compiled function cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); } return cached; }; function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { Sizzle( selector, contexts[i], results ); } return results; } function select( selector, context, results, seed ) { var i, tokens, token, type, find, match = tokenize( selector ); if ( !seed ) { // Try to minimize operations if there is only one group if ( match.length === 1 ) { // Take a shortcut and set the context if the root selector is an ID tokens = match[0] = match[0].slice( 0 ); if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; if ( !context ) { return results; } selector = selector.slice( tokens.shift().value.length ); } // Fetch a seed set for right-to-left matching i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; while ( i-- ) { token = tokens[i]; // Abort if we hit a combinator if ( Expr.relative[ (type = token.type) ] ) { break; } if ( (find = Expr.find[ type ]) ) { // Search, expanding context for leading sibling combinators if ( (seed = find( token.matches[0].replace( runescape, funescape ), rsibling.test( tokens[0].type ) && context.parentNode || context )) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); selector = seed.length && toSelector( tokens ); if ( !selector ) { push.apply( results, seed ); return results; } break; } } } } } // Compile and execute a filtering function // Provide `match` to avoid retokenization if we modified the selector above compile( selector, match )( seed, context, !documentIsHTML, results, rsibling.test( selector ) ); return results; } // Deprecated Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Easy API for creating new setFilters function setFilters() {} setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); // One-time assignments // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; // Initialize against the default document setDocument(); // Support: Chrome<<14 // Always assume duplicates if they aren't passed to the comparison function [0, 0].sort( sortOrder ); support.detectDuplicates = hasDuplicate; // Support: IE<8 // Prevent attribute/property "interpolation" assert(function( div ) { div.innerHTML = ""; if ( div.firstChild.getAttribute("href") !== "#" ) { var attrs = "type|href|height|width".split("|"), i = attrs.length; while ( i-- ) { Expr.attrHandle[ attrs[i] ] = interpolationHandler; } } }); // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies assert(function( div ) { if ( div.getAttribute("disabled") != null ) { var attrs = booleans.split("|"), i = attrs.length; while ( i-- ) { Expr.attrHandle[ attrs[i] ] = boolHandler; } } }); jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.pseudos; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })( window ); // String to Object options format cache var optionsCache = {}; // Convert String-formatted options into Object-formatted ones and store in cache function createOptions( options ) { var object = optionsCache[ options ] = {}; jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; }); return object; } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options ); var // Last fire value (for non-forgettable lists) memory, // Flag to know if list was already fired fired, // Flag to know if list is currently firing firing, // First callback to fire (used internally by add and fireWith) firingStart, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = !options.once && [], // Fire callbacks fire = function( data ) { memory = options.memory && data; fired = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; firing = true; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { memory = false; // To prevent further calls using add break; } } firing = false; if ( list ) { if ( stack ) { if ( stack.length ) { fire( stack.shift() ); } } else if ( memory ) { list = []; } else { self.disable(); } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // First, we save the current length var start = list.length; (function add( args ) { jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); if ( type === "function" ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); })( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away } else if ( memory ) { firingStart = start; fire( memory ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { jQuery.each( arguments, function( _, arg ) { var index; while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( firing ) { if ( index <= firingLength ) { firingLength--; } if ( index <= firingIndex ) { firingIndex--; } } } }); } return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, // Remove all callbacks from the list empty: function() { list = []; firingLength = 0; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; if ( list && ( !fired || stack ) ) { if ( firing ) { stack.push( args ); } else { fire( args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; }; jQuery.extend({ Deferred: function( func ) { var tuples = [ // action, add listener, listener list, final state [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], [ "notify", "progress", jQuery.Callbacks("memory") ] ], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done( arguments ).fail( arguments ); return this; }, then: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred(function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { var action = tuple[ 0 ], fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; // deferred[ done | fail | progress ] for forwarding actions to newDefer deferred[ tuple[1] ](function() { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .done( newDefer.resolve ) .fail( newDefer.reject ) .progress( newDefer.notify ); } else { newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); } }); }); fns = null; }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; // Keep pipe for back-compat promise.pipe = promise.then; // Add list-specific methods jQuery.each( tuples, function( i, tuple ) { var list = tuple[ 2 ], stateString = tuple[ 3 ]; // promise[ done | fail | progress ] = list.add promise[ tuple[1] ] = list.add; // Handle state if ( stateString ) { list.add(function() { // state = [ resolved | rejected ] state = stateString; // [ reject_list | resolve_list ].disable; progress_list.lock }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); } // deferred[ resolve | reject | notify ] deferred[ tuple[0] ] = function() { deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); return this; }; deferred[ tuple[0] + "With" ] = list.fireWith; }); // Make the deferred a promise promise.promise( deferred ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( subordinate /* , ..., subordinateN */ ) { var i = 0, resolveValues = core_slice.call( arguments ), length = resolveValues.length, // the count of uncompleted subordinates remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, // the master Deferred. If resolveValues consist of only a single Deferred, just use that. deferred = remaining === 1 ? subordinate : jQuery.Deferred(), // Update function for both resolve and progress values updateFunc = function( i, contexts, values ) { return function( value ) { contexts[ i ] = this; values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; if( values === progressValues ) { deferred.notifyWith( contexts, values ); } else if ( !( --remaining ) ) { deferred.resolveWith( contexts, values ); } }; }, progressValues, progressContexts, resolveContexts; // add listeners to Deferred subordinates; treat others as resolved if ( length > 1 ) { progressValues = new Array( length ); progressContexts = new Array( length ); resolveContexts = new Array( length ); for ( ; i < length; i++ ) { if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { resolveValues[ i ].promise() .done( updateFunc( i, resolveContexts, resolveValues ) ) .fail( deferred.reject ) .progress( updateFunc( i, progressContexts, progressValues ) ); } else { --remaining; } } } // if we're not waiting on anything, resolve the master if ( !remaining ) { deferred.resolveWith( resolveContexts, resolveValues ); } return deferred.promise(); } }); jQuery.support = (function( support ) { var input = document.createElement("input"), fragment = document.createDocumentFragment(), div = document.createElement("div"), select = document.createElement("select"), opt = select.appendChild( document.createElement("option") ); // Finish early in limited environments if ( !input.type ) { return support; } input.type = "checkbox"; // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) support.checkOn = input.value !== ""; // Must access the parent to make an option select properly // Support: IE9, IE10 support.optSelected = opt.selected; // Will be defined later support.reliableMarginRight = true; support.boxSizingReliable = true; support.pixelPosition = false; // Make sure checked status is properly cloned // Support: IE9, IE10 input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Check if an input maintains its value after becoming a radio // Support: IE9, IE10 input = document.createElement("input"); input.value = "t"; input.type = "radio"; support.radioValue = input.value === "t"; // #11217 - WebKit loses check when the name is after the checked attribute input.setAttribute( "checked", "t" ); input.setAttribute( "name", "t" ); fragment.appendChild( input ); // Support: Safari 5.1, Android 4.x, Android 2.3 // old WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; // Support: Firefox, Chrome, Safari // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) support.focusinBubbles = "onfocusin" in window; div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; support.clearCloneStyle = div.style.backgroundClip === "content-box"; // Run tests that need a body at doc ready jQuery(function() { var container, marginDiv, // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box", body = document.getElementsByTagName("body")[ 0 ]; if ( !body ) { // Return for frameset docs that don't have a body return; } container = document.createElement("div"); container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; // Check box-sizing and margin behavior. body.appendChild( container ).appendChild( div ); div.innerHTML = ""; // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). div.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%"; // Workaround failing boxSizing test due to offsetWidth returning wrong value // with some non-1 values of body zoom, ticket #13543 jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { support.boxSizing = div.offsetWidth === 4; }); // Use window.getComputedStyle because jsdom on node.js will break without it. if ( window.getComputedStyle ) { support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; // Support: Android 2.3 // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. (#3333) // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right marginDiv = div.appendChild( document.createElement("div") ); marginDiv.style.cssText = div.style.cssText = divReset; marginDiv.style.marginRight = marginDiv.style.width = "0"; div.style.width = "1px"; support.reliableMarginRight = !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); } body.removeChild( container ); }); return support; })( {} ); /* Implementation Summary 1. Enforce API surface and semantic compatibility with 1.9.x branch 2. Improve the module's maintainability by reducing the storage paths to a single mechanism. 3. Use the same single mechanism to support "private" and "user" data. 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 5. Avoid exposing implementation details on user objects (eg. expando properties) 6. Provide a clear path for implementation upgrade to WeakMap in 2014 */ var data_user, data_priv, rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, rmultiDash = /([A-Z])/g; function Data() { // Support: Android < 4, // Old WebKit does not have Object.preventExtensions/freeze method, // return new empty object instead with no [[set]] accessor Object.defineProperty( this.cache = {}, 0, { get: function() { return {}; } }); this.expando = jQuery.expando + Math.random(); } Data.uid = 1; Data.accepts = function( owner ) { // Accepts only: // - Node // - Node.ELEMENT_NODE // - Node.DOCUMENT_NODE // - Object // - Any return owner.nodeType ? owner.nodeType === 1 || owner.nodeType === 9 : true; }; Data.prototype = { key: function( owner ) { // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. // Always return the key for a frozen object. if ( !Data.accepts( owner ) ) { return 0; } var descriptor = {}, // Check if the owner object already has a cache key unlock = owner[ this.expando ]; // If not, create one if ( !unlock ) { unlock = Data.uid++; // Secure it in a non-enumerable, non-writable property try { descriptor[ this.expando ] = { value: unlock }; Object.defineProperties( owner, descriptor ); // Support: Android < 4 // Fallback to a less secure definition } catch ( e ) { descriptor[ this.expando ] = unlock; jQuery.extend( owner, descriptor ); } } // Ensure the cache object if ( !this.cache[ unlock ] ) { this.cache[ unlock ] = {}; } return unlock; }, set: function( owner, data, value ) { var prop, // There may be an unlock assigned to this node, // if there is no entry for this "owner", create one inline // and set the unlock as though an owner entry had always existed unlock = this.key( owner ), cache = this.cache[ unlock ]; // Handle: [ owner, key, value ] args if ( typeof data === "string" ) { cache[ data ] = value; // Handle: [ owner, { properties } ] args } else { // Support an expectation from the old data system where plain // objects used to initialize would be set to the cache by // reference, instead of having properties and values copied. // Note, this will kill the connection between // "this.cache[ unlock ]" and "cache" if ( jQuery.isEmptyObject( cache ) ) { this.cache[ unlock ] = data; // Otherwise, copy the properties one-by-one to the cache object } else { for ( prop in data ) { cache[ prop ] = data[ prop ]; } } } }, get: function( owner, key ) { // Either a valid cache is found, or will be created. // New caches will be created and the unlock returned, // allowing direct access to the newly created // empty data object. A valid owner object must be provided. var cache = this.cache[ this.key( owner ) ]; return key === undefined ? cache : cache[ key ]; }, access: function( owner, key, value ) { // In cases where either: // // 1. No key was specified // 2. A string key was specified, but no value provided // // Take the "read" path and allow the get method to determine // which value to return, respectively either: // // 1. The entire cache object // 2. The data stored at the key // if ( key === undefined || ((key && typeof key === "string") && value === undefined) ) { return this.get( owner, key ); } // [*]When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties // 2. A key and value // this.set( owner, key, value ); // Since the "set" path can have two possible entry points // return the expected data based on which path was taken[*] return value !== undefined ? value : key; }, remove: function( owner, key ) { var i, name, unlock = this.key( owner ), cache = this.cache[ unlock ]; if ( key === undefined ) { this.cache[ unlock ] = {}; } else { // Support array or space separated string of keys if ( jQuery.isArray( key ) ) { // If "name" is an array of keys... // When data is initially created, via ("key", "val") signature, // keys will be converted to camelCase. // Since there is no way to tell _how_ a key was added, remove // both plain key and camelCase key. #12786 // This will only penalize the array argument path. name = key.concat( key.map( jQuery.camelCase ) ); } else { // Try the string as a key before any manipulation if ( key in cache ) { name = [ key ]; } else { // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace name = jQuery.camelCase( key ); name = name in cache ? [ name ] : ( name.match( core_rnotwhite ) || [] ); } } i = name.length; while ( i-- ) { delete cache[ name[ i ] ]; } } }, hasData: function( owner ) { return !jQuery.isEmptyObject( this.cache[ owner[ this.expando ] ] || {} ); }, discard: function( owner ) { delete this.cache[ this.key( owner ) ]; } }; // These may be used throughout the jQuery core codebase data_user = new Data(); data_priv = new Data(); jQuery.extend({ acceptData: Data.accepts, hasData: function( elem ) { return data_user.hasData( elem ) || data_priv.hasData( elem ); }, data: function( elem, name, data ) { return data_user.access( elem, name, data ); }, removeData: function( elem, name ) { data_user.remove( elem, name ); }, // TODO: Now that all calls to _data and _removeData have been replaced // with direct calls to data_priv methods, these can be deprecated. _data: function( elem, name, data ) { return data_priv.access( elem, name, data ); }, _removeData: function( elem, name ) { data_priv.remove( elem, name ); } }); jQuery.fn.extend({ data: function( key, value ) { var attrs, name, elem = this[ 0 ], i = 0, data = null; // Gets all values if ( key === undefined ) { if ( this.length ) { data = data_user.get( elem ); if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { attrs = elem.attributes; for ( ; i < attrs.length; i++ ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( elem, name, data[ name ] ); } } data_priv.set( elem, "hasDataAttrs", true ); } } return data; } // Sets multiple values if ( typeof key === "object" ) { return this.each(function() { data_user.set( this, key ); }); } return jQuery.access( this, function( value ) { var data, camelKey = jQuery.camelCase( key ); // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the // `value` parameter was not undefined. An empty jQuery object // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. if ( elem && value === undefined ) { // Attempt to get data from the cache // with the key as-is data = data_user.get( elem, key ); if ( data !== undefined ) { return data; } // Attempt to get data from the cache // with the key camelized data = data_user.get( elem, camelKey ); if ( data !== undefined ) { return data; } // Attempt to "discover" the data in // HTML5 custom data-* attrs data = dataAttr( elem, camelKey, undefined ); if ( data !== undefined ) { return data; } // We tried really hard, but the data doesn't exist. return; } // Set the data... this.each(function() { // First, attempt to store a copy or reference of any // data that might've been store with a camelCased key. var data = data_user.get( this, camelKey ); // For HTML5 data-* attribute interop, we have to // store property names with dashes in a camelCase form. // This might not apply to all properties...* data_user.set( this, camelKey, value ); // *... In the case of properties that might _actually_ // have dashes, we need to also store a copy of that // unchanged property. if ( key.indexOf("-") !== -1 && data !== undefined ) { data_user.set( this, key, value ); } }); }, null, value, arguments.length > 1, null, true ); }, removeData: function( key ) { return this.each(function() { data_user.remove( this, key ); }); } }); function dataAttr( elem, key, data ) { var name; // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : // Only convert to a number if it doesn't change the string +data + "" === data ? +data : rbrace.test( data ) ? JSON.parse( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later data_user.set( elem, key, data ); } else { data = undefined; } } return data; } jQuery.extend({ queue: function( elem, type, data ) { var queue; if ( elem ) { type = ( type || "fx" ) + "queue"; queue = data_priv.get( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !queue || jQuery.isArray( data ) ) { queue = data_priv.access( elem, type, jQuery.makeArray(data) ); } else { queue.push( data ); } } return queue || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), startLength = queue.length, fn = queue.shift(), hooks = jQuery._queueHooks( elem, type ), next = function() { jQuery.dequeue( elem, type ); }; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); startLength--; } hooks.cur = fn; if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } // clear up the last queue stop function delete hooks.stop; fn.call( elem, next, hooks ); } if ( !startLength && hooks ) { hooks.empty.fire(); } }, // not intended for public consumption - generates a queueHooks object, or returns the current one _queueHooks: function( elem, type ) { var key = type + "queueHooks"; return data_priv.get( elem, key ) || data_priv.access( elem, key, { empty: jQuery.Callbacks("once memory").add(function() { data_priv.remove( elem, [ type + "queue", key ] ); }) }); } }); jQuery.fn.extend({ queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } if ( arguments.length < setter ) { return jQuery.queue( this[0], type ); } return data === undefined ? this : this.each(function() { var queue = jQuery.queue( this, type, data ); // ensure a hooks for this queue jQuery._queueHooks( this, type ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = setTimeout( next, time ); hooks.stop = function() { clearTimeout( timeout ); }; }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, obj ) { var tmp, count = 1, defer = jQuery.Deferred(), elements = this, i = this.length, resolve = function() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } }; if ( typeof type !== "string" ) { obj = type; type = undefined; } type = type || "fx"; while( i-- ) { tmp = data_priv.get( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; tmp.empty.add( resolve ); } } resolve(); return defer.promise( obj ); } }); var nodeHook, boolHook, rclass = /[\t\r\n]/g, rreturn = /\r/g, rfocusable = /^(?:input|select|textarea|button)$/i; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); }, removeProp: function( name ) { return this.each(function() { delete this[ jQuery.propFix[ name ] || name ]; }); }, addClass: function( value ) { var classes, elem, cur, clazz, j, i = 0, len = this.length, proceed = typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call( this, j, this.className ) ); }); } if ( proceed ) { // The disjunction here is for better compressibility (see removeClass) classes = ( value || "" ).match( core_rnotwhite ) || []; for ( ; i < len; i++ ) { elem = this[ i ]; cur = elem.nodeType === 1 && ( elem.className ? ( " " + elem.className + " " ).replace( rclass, " " ) : " " ); if ( cur ) { j = 0; while ( (clazz = classes[j++]) ) { if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } } elem.className = jQuery.trim( cur ); } } } return this; }, removeClass: function( value ) { var classes, elem, cur, clazz, j, i = 0, len = this.length, proceed = arguments.length === 0 || typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call( this, j, this.className ) ); }); } if ( proceed ) { classes = ( value || "" ).match( core_rnotwhite ) || []; for ( ; i < len; i++ ) { elem = this[ i ]; // This expression is here for better compressibility (see addClass) cur = elem.nodeType === 1 && ( elem.className ? ( " " + elem.className + " " ).replace( rclass, " " ) : "" ); if ( cur ) { j = 0; while ( (clazz = classes[j++]) ) { // Remove *all* instances while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { cur = cur.replace( " " + clazz + " ", " " ); } } elem.className = value ? jQuery.trim( cur ) : ""; } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.match( core_rnotwhite ) || []; while ( (className = classNames[ i++ ]) ) { // check each className given, space separated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } // Toggle whole class name } else if ( type === core_strundefined || type === "boolean" ) { if ( this.className ) { // store className if set data_priv.set( this, "__className__", this.className ); } // If the element has a class name or if we're passed "false", // then remove the whole classname (if there was one, the above saved it). // Otherwise bring back whatever was previously saved (if anything), // falling back to the empty string if nothing was stored. this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most common string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var val, self = jQuery(this); if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, option, options = elem.options, index = elem.selectedIndex, one = elem.type === "select-one" || index < 0, values = one ? null : [], max = one ? index + 1 : options.length, i = index < 0 ? max : one ? index : 0; // Loop through all the selected options for ( ; i < max; i++ ) { option = options[ i ]; // IE6-9 doesn't update selected after form reset (#2551) if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } return values; }, set: function( elem, value ) { var optionSet, option, options = elem.options, values = jQuery.makeArray( value ), i = options.length; while ( i-- ) { option = options[ i ]; if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { optionSet = true; } } // force browsers to behave consistently when non-matching value is set if ( !optionSet ) { elem.selectedIndex = -1; } return values; } } }, attr: function( elem, name, value ) { var hooks, ret, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === core_strundefined ) { return jQuery.prop( elem, name, value ); } // All attributes are lowercase // Grab necessary hook if one is defined if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( jQuery.expr.match.boolean.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, value + "" ); return value; } } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret; } }, removeAttr: function( elem, value ) { var name, propName, i = 0, attrNames = value && value.match( core_rnotwhite ); if ( attrNames && elem.nodeType === 1 ) { while ( (name = attrNames[i++]) ) { propName = jQuery.propFix[ name ] || name; // Boolean attributes get special treatment (#10870) if ( jQuery.expr.match.boolean.test( name ) ) { // Set corresponding property to false elem[ propName ] = false; } elem.removeAttribute( name ); } } }, attrHooks: { type: { set: function( elem, value ) { if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to default in case type is set after value during creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } } }, propFix: { "for": "htmlFor", "class": "className" }, prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? ret : ( elem[ name ] = value ); } else { return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? ret : elem[ name ]; } }, propHooks: { tabIndex: { get: function( elem ) { return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? elem.tabIndex : -1; } } } }); // Hooks for boolean attributes boolHook = { set: function( elem, value, name ) { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { elem.setAttribute( name, name ); } return name; } }; jQuery.each( jQuery.expr.match.boolean.source.match( /\w+/g ), function( i, name ) { var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; jQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) { var fn = jQuery.expr.attrHandle[ name ], ret = isXML ? undefined : /* jshint eqeqeq: false */ // Temporarily disable this handler to check existence (jQuery.expr.attrHandle[ name ] = undefined) != getter( elem, name, isXML ) ? name.toLowerCase() : null; // Restore handler jQuery.expr.attrHandle[ name ] = fn; return ret; }; }); // Support: IE9+ // Selectedness for an option in an optgroup can be inaccurate if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { var parent = elem.parentNode; if ( parent && parent.parentNode ) { parent.parentNode.selectedIndex; } return null; } }; } jQuery.each([ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; }); // Radios and checkboxes getter/setter jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } }; if ( !jQuery.support.checkOn ) { jQuery.valHooks[ this ].get = function( elem ) { // Support: Webkit // "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; }; } }); var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; function returnTrue() { return true; } function returnFalse() { return false; } function safeActiveElement() { try { return document.activeElement; } catch ( err ) { } } /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { global: {}, add: function( elem, types, handler, data, selector ) { var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = data_priv.get( elem ); // Don't attach events to noData or text/comment nodes (but allow plain objects) if ( !elemData ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first if ( !(events = elemData.events) ) { events = elemData.events = {}; } if ( !(eventHandle = elemData.handle) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events eventHandle.elem = elem; } // Handle multiple events separated by a space types = ( types || "" ).match( core_rnotwhite ) || [""]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[t] ) || []; type = origType = tmp[1]; namespaces = ( tmp[2] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { continue; } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, origType: origType, data: data, handler: handler, guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), namespace: namespaces.join(".") }, handleObjIn ); // Init the event handler queue if we're the first if ( !(handlers = events[ type ]) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var j, origCount, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = data_priv.hasData( elem ) && data_priv.get( elem ); if ( !elemData || !(events = elemData.events) ) { return; } // Once for each type.namespace in types; type may be omitted types = ( types || "" ).match( core_rnotwhite ) || [""]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[t] ) || []; type = origType = tmp[1]; namespaces = ( tmp[2] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); // Remove matching events origCount = j = handlers.length; while ( j-- ) { handleObj = handlers[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !tmp || tmp.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { handlers.splice( j, 1 ); if ( handleObj.selector ) { handlers.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { delete elemData.handle; data_priv.remove( elem, "events" ); } }, trigger: function( event, data, elem, onlyHandlers ) { var i, cur, tmp, bubbleType, ontype, handle, special, eventPath = [ elem || document ], type = core_hasOwn.call( event, "type" ) ? event.type : event, namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; cur = tmp = elem = elem || document; // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf(".") >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } ontype = type.indexOf(":") < 0 && "on" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[ jQuery.expando ] ? event : new jQuery.Event( type, typeof event === "object" && event ); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3; event.namespace = namespaces.join("."); event.namespace_re = event.namespace ? new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : null; // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ? [ event ] : jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; if ( !rfocusMorph.test( bubbleType + type ) ) { cur = cur.parentNode; } for ( ; cur; cur = cur.parentNode ) { eventPath.push( cur ); tmp = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( tmp === (elem.ownerDocument || document) ) { eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path i = 0; while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Native handler handle = ontype && cur[ ontype ]; if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { event.preventDefault(); } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Don't do default actions on window, that's where global variables be (#6170) if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ ontype ]; if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( tmp ) { elem[ ontype ] = tmp; } } } } return event.result; }, dispatch: function( event ) { // Make a writable jQuery.Event from the native event object event = jQuery.event.fix( event ); var i, j, ret, matched, handleObj, handlerQueue = [], args = core_slice.call( arguments ), handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { return; } // Determine handlers handlerQueue = jQuery.event.handlers.call( this, event, handlers ); // Run delegates first; they may want to stop propagation beneath us i = 0; while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { event.currentTarget = matched.elem; j = 0; while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { // Triggered event must either 1) have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) .apply( matched.elem, args ); if ( ret !== undefined ) { if ( (event.result = ret) === false ) { event.preventDefault(); event.stopPropagation(); } } } } } // Call the postDispatch hook for the mapped type if ( special.postDispatch ) { special.postDispatch.call( this, event ); } return event.result; }, handlers: function( event, handlers ) { var i, matches, sel, handleObj, handlerQueue = [], delegateCount = handlers.delegateCount, cur = event.target; // Find delegate handlers // Black-hole SVG instance trees (#13180) // Avoid non-left-click bubbling in Firefox (#3861) if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { for ( ; cur !== this; cur = cur.parentNode || this ) { // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) if ( cur.disabled !== true || event.type !== "click" ) { matches = []; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; // Don't conflict with Object.prototype properties (#13203) sel = handleObj.selector + " "; if ( matches[ sel ] === undefined ) { matches[ sel ] = handleObj.needsContext ? jQuery( sel, this ).index( cur ) >= 0 : jQuery.find( sel, this, null, [ cur ] ).length; } if ( matches[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { handlerQueue.push({ elem: cur, handlers: matches }); } } } } // Add the remaining (directly-bound) handlers if ( delegateCount < handlers.length ) { handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); } return handlerQueue; }, // Includes some event props shared by KeyEvent and MouseEvent 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( event, original ) { // Add which for key events if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; } }, mouseHooks: { props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { var eventDoc, doc, body, button = original.button; // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; } }, fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // Create a writable copy of the event object and normalize some properties var i, prop, copy, type = event.type, originalEvent = event, fixHook = this.fixHooks[ type ]; if ( !fixHook ) { this.fixHooks[ type ] = fixHook = rmouseEvent.test( type ) ? this.mouseHooks : rkeyEvent.test( type ) ? this.keyHooks : {}; } copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; event = new jQuery.Event( originalEvent ); i = copy.length; while ( i-- ) { prop = copy[ i ]; event[ prop ] = originalEvent[ prop ]; } // Support: Safari 6.0+, Chrome < 28 // Target should not be a text node (#504, #13143) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } return fixHook.filter? fixHook.filter( event, originalEvent ) : event; }, special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== safeActiveElement() && this.focus ) { this.focus(); return false; } }, delegateType: "focusin" }, blur: { trigger: function() { if ( this === safeActiveElement() && this.blur ) { this.blur(); return false; } }, delegateType: "focusout" }, click: { // For checkbox, fire native event so checked state will be right trigger: function() { if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { this.click(); return false; } }, // For cross-browser consistency, don't fire native .click() on links _default: function( event ) { return jQuery.nodeName( event.target, "a" ); } }, beforeunload: { postDispatch: function( event ) { // Support: Firefox 20+ // Firefox doesn't alert if the returnValue field is not set. if ( event.result !== undefined ) { event.originalEvent.returnValue = event.result; } } } }, simulate: function( type, elem, event, bubble ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true, originalEvent: {} } ); if ( bubble ) { jQuery.event.trigger( e, null, elem ); } else { jQuery.event.dispatch.call( elem, e ); } if ( e.isDefaultPrevented() ) { event.preventDefault(); } } }; jQuery.removeEvent = function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = ( src.defaultPrevented || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( e && e.preventDefault ) { e.preventDefault(); } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( e && e.stopPropagation ) { e.stopPropagation(); } }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } }; // Create mouseenter/leave events using mouseover/out and event-time checks // Support: Chrome 15+ jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var ret, target = this, related = event.relatedTarget, handleObj = event.handleObj; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || (related !== target && !jQuery.contains( target, related )) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; }); // Create "bubbling" focus and blur events // Support: Firefox, Chrome, Safari if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0, handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); }; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; }); } jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { this.on( type, selector, data, types[ type ], one ); } return this; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return this; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { jQuery.event.add( this, types, fn, data, selector ); }); }, one: function( types, selector, data, fn ) { return this.on( types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { var handleObj, type; if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each(function() { jQuery.event.remove( this, types, fn, selector ); }); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { var elem = this[0]; if ( elem ) { return jQuery.event.trigger( type, data, elem, true ); } } }); var isSimple = /^.[^:#\[\.,]*$/, rneedsContext = jQuery.expr.match.needsContext, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self, matched, i, l = this.length; if ( typeof selector !== "string" ) { self = this; return this.pushStack( jQuery( selector ).filter(function() { for ( i = 0; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }) ); } matched = []; for ( i = 0; i < l; i++ ) { jQuery.find( selector, this[ i ], matched ); } // Needed because $( selector, context ) becomes $( context ).find( selector ) matched = this.pushStack( l > 1 ? jQuery.unique( matched ) : matched ); matched.selector = ( this.selector ? this.selector + " " : "" ) + selector; return matched; }, has: function( target ) { var targets = jQuery( target, this ), l = targets.length; return this.filter(function() { var i = 0; for ( ; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector || [], true) ); }, filter: function( selector ) { return this.pushStack( winnow(this, selector || [], false) ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". rneedsContext.test( selector ) ? jQuery( selector, this.context ).index( this[ 0 ] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var cur, i = 0, l = this.length, matched = [], pos = ( rneedsContext.test( selectors ) || typeof selectors !== "string" ) ? jQuery( selectors, context || this.context ) : 0; for ( ; i < l; i++ ) { for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { // Always skip document fragments if ( cur.nodeType < 11 && (pos ? pos.index(cur) > -1 : // Don't pass non-elements to Sizzle cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors)) ) { cur = matched.push( cur ); break; } } } return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return core_indexOf.call( jQuery( elem ), this[ 0 ] ); } // Locate the position of the desired element return core_indexOf.call( this, // If it receives a jQuery object, the first element is used elem.jquery ? elem[ 0 ] : elem ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( jQuery.unique(all) ); }, addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter(selector) ); } }); function sibling( cur, dir ) { while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} return cur; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return sibling( elem, "nextSibling" ); }, prev: function( elem ) { return sibling( elem, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var matched = jQuery.map( this, fn, until ); if ( name.slice( -5 ) !== "Until" ) { selector = until; } if ( selector && typeof selector === "string" ) { matched = jQuery.filter( selector, matched ); } if ( this.length > 1 ) { // Remove duplicates if ( !guaranteedUnique[ name ] ) { jQuery.unique( matched ); } // Reverse order for parents* and prev* if ( name[ 0 ] === "p" ) { matched.reverse(); } } return this.pushStack( matched ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 && elem.nodeType === 1 ? jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; })); }, dir: function( elem, dir, until ) { var matched = [], truncate = until !== undefined; while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { if ( elem.nodeType === 1 ) { if ( truncate && jQuery( elem ).is( until ) ) { break; } matched.push( elem ); } } return matched; }, sibling: function( n, elem ) { var matched = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { matched.push( n ); } } return matched; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep( elements, function( elem, i ) { /* jshint -W018 */ return !!qualifier.call( elem, i, elem ) !== not; }); } if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; }); } if ( typeof qualifier === "string" ) { if ( isSimple.test( qualifier ) ) { return jQuery.filter( qualifier, elements, not ); } qualifier = jQuery.filter( qualifier, elements ); } return jQuery.grep( elements, function( elem ) { return ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not; }); } var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, rtagName = /<([\w:]+)/, rhtml = /<|&#?\w+;/, rnoInnerhtml = /<(?:script|style|link)/i, manipulation_rcheckableType = /^(?:checkbox|radio)$/i, // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rscriptType = /^$|\/(?:java|ecma)script/i, rscriptTypeMasked = /^true\/(.*)/, rcleanScript = /^\s*\s*$/g, // We have to close these tags to support XHTML (#13200) wrapMap = { // Support: IE 9 option: [ 1, "" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], _default: [ 0, "", "" ] }; // Support: IE 9 wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.col = wrapMap.thead; wrapMap.th = wrapMap.td; jQuery.fn.extend({ text: function( value ) { return jQuery.access( this, function( value ) { return value === undefined ? jQuery.text( this ) : this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) ); }, null, value, arguments.length ); }, append: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } }); }, prepend: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } }); }, before: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } }); }, after: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } }); }, // keepData is for internal use only--do not document remove: function( selector, keepData ) { var elem, elems = selector ? jQuery.filter( selector, this ) : this, i = 0; for ( ; (elem = elems[i]) != null; i++ ) { if ( !keepData && elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem ) ); } if ( elem.parentNode ) { if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { setGlobalEval( getAll( elem, "script" ) ); } elem.parentNode.removeChild( elem ); } } return this; }, empty: function() { var elem, i = 0; for ( ; (elem = this[i]) != null; i++ ) { if ( elem.nodeType === 1 ) { // Prevent memory leaks jQuery.cleanData( getAll( elem, false ) ); // Remove any remaining nodes elem.textContent = ""; } } return this; }, clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; return this.map( function () { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); }); }, html: function( value ) { return jQuery.access( this, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined && elem.nodeType === 1 ) { return elem.innerHTML; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = value.replace( rxhtmlTag, "<$1>" ); try { for ( ; i < l; i++ ) { elem = this[ i ] || {}; // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; // If using innerHTML throws an exception, use the fallback method } catch( e ) {} } if ( elem ) { this.empty().append( value ); } }, null, value, arguments.length ); }, replaceWith: function() { var // Snapshot the DOM in case .domManip sweeps something relevant into its fragment args = jQuery.map( this, function( elem ) { return [ elem.nextSibling, elem.parentNode ]; }), i = 0; // Make the changes, replacing each context element with the new content this.domManip( arguments, function( elem ) { var next = args[ i++ ], parent = args[ i++ ]; if ( parent ) { jQuery( this ).remove(); parent.insertBefore( elem, next ); } // Allow new content to include elements from the context set }, true ); // Force removal if there was no new content (e.g., from empty arguments) return i ? this : this.remove(); }, detach: function( selector ) { return this.remove( selector, true ); }, domManip: function( args, callback, allowIntersection ) { // Flatten any nested arrays args = core_concat.apply( [], args ); var fragment, first, scripts, hasScripts, node, doc, i = 0, l = this.length, set = this, iNoClone = l - 1, value = args[ 0 ], isFunction = jQuery.isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { return this.each(function( index ) { var self = set.eq( index ); if ( isFunction ) { args[ 0 ] = value.call( this, index, self.html() ); } self.domManip( args, callback, allowIntersection ); }); } if ( l ) { fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { fragment = first; } if ( first ) { scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); hasScripts = scripts.length; // Use the original fragment for the last item instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for ( ; i < l; i++ ) { node = fragment; if ( i !== iNoClone ) { node = jQuery.clone( node, true, true ); // Keep references to cloned scripts for later restoration if ( hasScripts ) { // Support: QtWebKit // jQuery.merge because core_push.apply(_, arraylike) throws jQuery.merge( scripts, getAll( node, "script" ) ); } } callback.call( this[ i ], node, i ); } if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; // Reenable scripts jQuery.map( scripts, restoreScript ); // Evaluate executable scripts on first document insertion for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src ) { // Hope ajax is available... jQuery._evalUrl( node.src ); } else { jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); } } } } } } return this; } }); jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { var elems, ret = [], insert = jQuery( selector ), last = insert.length - 1, i = 0; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems ); // Support: QtWebKit // .get() because core_push.apply(_, arraylike) throws core_push.apply( ret, elems.get() ); } return this.pushStack( ret ); }; }); jQuery.extend({ clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), inPage = jQuery.contains( elem.ownerDocument, elem ); // Support: IE >= 9 // Fix Cloning issues if ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); for ( i = 0, l = srcElements.length; i < l; i++ ) { fixInput( srcElements[ i ], destElements[ i ] ); } } // Copy the events from the original to the clone if ( dataAndEvents ) { if ( deepDataAndEvents ) { srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); for ( i = 0, l = srcElements.length; i < l; i++ ) { cloneCopyEvent( srcElements[ i ], destElements[ i ] ); } } else { cloneCopyEvent( elem, clone ); } } // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } // Return the cloned set return clone; }, buildFragment: function( elems, context, scripts, selection ) { var elem, tmp, tag, wrap, contains, j, i = 0, l = elems.length, fragment = context.createDocumentFragment(), nodes = []; for ( ; i < l; i++ ) { elem = elems[ i ]; if ( elem || elem === 0 ) { // Add nodes directly if ( jQuery.type( elem ) === "object" ) { // Support: QtWebKit // jQuery.merge because core_push.apply(_, arraylike) throws jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node } else if ( !rhtml.test( elem ) ) { nodes.push( context.createTextNode( elem ) ); // Convert html into DOM nodes } else { tmp = tmp || fragment.appendChild( context.createElement("div") ); // Deserialize a standard representation tag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; // Descend through wrappers to the right content j = wrap[ 0 ]; while ( j-- ) { tmp = tmp.firstChild; } // Support: QtWebKit // jQuery.merge because core_push.apply(_, arraylike) throws jQuery.merge( nodes, tmp.childNodes ); // Remember the top-level container tmp = fragment.firstChild; // Fixes #12346 // Support: Webkit, IE tmp.textContent = ""; } } } // Remove wrapper from fragment fragment.textContent = ""; i = 0; while ( (elem = nodes[ i++ ]) ) { // #4087 - If origin and destination elements are the same, and this is // that element, do not do anything if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { continue; } contains = jQuery.contains( elem.ownerDocument, elem ); // Append to fragment tmp = getAll( fragment.appendChild( elem ), "script" ); // Preserve script evaluation history if ( contains ) { setGlobalEval( tmp ); } // Capture executables if ( scripts ) { j = 0; while ( (elem = tmp[ j++ ]) ) { if ( rscriptType.test( elem.type || "" ) ) { scripts.push( elem ); } } } } return fragment; }, cleanData: function( elems ) { var data, elem, type, l = elems.length, i = 0, special = jQuery.event.special; for ( ; i < l; i++ ) { elem = elems[ i ]; if ( jQuery.acceptData( elem ) ) { data = data_priv.access( elem ); if ( data ) { for ( type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } } } // Discard any remaining `private` and `user` data // One day we'll replace the dual arrays with a WeakMap and this won't be an issue. // (Splices the data objects out of the internal cache arrays) data_user.discard( elem ); data_priv.discard( elem ); } }, _evalUrl: function( url ) { return jQuery.ajax({ url: url, type: "GET", dataType: "text", async: false, global: false, success: jQuery.globalEval }); } }); // Support: 1.x compatibility // Manipulating tables requires a tbody function manipulationTarget( elem, content ) { return jQuery.nodeName( elem, "table" ) && jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? elem.getElementsByTagName("tbody")[0] || elem.appendChild( elem.ownerDocument.createElement("tbody") ) : elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; return elem; } function restoreScript( elem ) { var match = rscriptTypeMasked.exec( elem.type ); if ( match ) { elem.type = match[ 1 ]; } else { elem.removeAttribute("type"); } return elem; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { var l = elems.length, i = 0; for ( ; i < l; i++ ) { data_priv.set( elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) ); } } function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; } // 1. Copy private data: events, handlers, etc. if ( data_priv.hasData( src ) ) { pdataOld = data_priv.access( src ); pdataCur = jQuery.extend( {}, pdataOld ); events = pdataOld.events; data_priv.set( dest, pdataCur ); if ( events ) { delete pdataCur.handle; pdataCur.events = {}; for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } } // 2. Copy user data if ( data_user.hasData( src ) ) { udataOld = data_user.access( src ); udataCur = jQuery.extend( {}, udataOld ); data_user.set( dest, udataCur ); } } function getAll( context, tag ) { var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : []; return tag === undefined || tag && jQuery.nodeName( context, tag ) ? jQuery.merge( [ context ], ret ) : ret; } // Support: IE >= 9 function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button. if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { dest.checked = src.checked; // Fails to return the selected option to the default selected state when cloning options } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } } jQuery.fn.extend({ wrapAll: function( html ) { var wrap; if ( jQuery.isFunction( html ) ) { return this.each(function( i ) { jQuery( this ).wrapAll( html.call(this, i) ); }); } if ( this[ 0 ] ) { // The elements to wrap the target around wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); if ( this[ 0 ].parentNode ) { wrap.insertBefore( this[ 0 ] ); } wrap.map(function() { var elem = this; while ( elem.firstElementChild ) { elem = elem.firstElementChild; } return elem; }).append( this ); } return this; }, wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { return this.each(function( i ) { jQuery( this ).wrapInner( html.call(this, i) ); }); } return this.each(function() { var self = jQuery( this ), contents = self.contents(); if ( contents.length ) { contents.wrapAll( html ); } else { self.append( html ); } }); }, wrap: function( html ) { var isFunction = jQuery.isFunction( html ); return this.each(function( i ) { jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); }); }, unwrap: function() { return this.parent().each(function() { if ( !jQuery.nodeName( this, "body" ) ) { jQuery( this ).replaceWith( this.childNodes ); } }).end(); } }); var curCSS, iframe, // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, rmargin = /^margin/, rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), elemdisplay = { BODY: "block" }, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: 0, fontWeight: 400 }, cssExpand = [ "Top", "Right", "Bottom", "Left" ], cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; // return a css property mapped to a potentially vendor prefixed property function vendorPropName( style, name ) { // shortcut for names that are not vendor prefixed if ( name in style ) { return name; } // check for vendor prefixed names var capName = name.charAt(0).toUpperCase() + name.slice(1), origName = name, i = cssPrefixes.length; while ( i-- ) { name = cssPrefixes[ i ] + capName; if ( name in style ) { return name; } } return origName; } function isHidden( elem, el ) { // isHidden might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); } // NOTE: we've included the "window" in window.getComputedStyle // because jsdom on node.js will break without it. function getStyles( elem ) { return window.getComputedStyle( elem, null ); } function showHide( elements, show ) { var display, elem, hidden, values = [], index = 0, length = elements.length; for ( ; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } values[ index ] = data_priv.get( elem, "olddisplay" ); display = elem.style.display; if ( show ) { // Reset the inline display of this element to learn if it is // being hidden by cascaded rules or not if ( !values[ index ] && display === "none" ) { elem.style.display = ""; } // Set elements which have been overridden with display: none // in a stylesheet to whatever the default browser style is // for such an element if ( elem.style.display === "" && isHidden( elem ) ) { values[ index ] = data_priv.access( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); } } else { if ( !values[ index ] ) { hidden = isHidden( elem ); if ( display && display !== "none" || !hidden ) { data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") ); } } } } // Set the display of most of the elements in a second loop // to avoid the constant reflow for ( index = 0; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } if ( !show || elem.style.display === "none" || elem.style.display === "" ) { elem.style.display = show ? values[ index ] || "" : "none"; } } return elements; } jQuery.fn.extend({ css: function( name, value ) { return jQuery.access( this, function( elem, name, value ) { var styles, len, map = {}, i = 0; if ( jQuery.isArray( name ) ) { styles = getStyles( elem ); len = name.length; for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); } return map; } return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); }, show: function() { return showHide( this, true ); }, hide: function() { return showHide( this ); }, toggle: function( state ) { var bool = typeof state === "boolean"; return this.each(function() { if ( bool ? state : isHidden( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } }); } }); jQuery.extend({ // Add in style property hooks for overriding the default // behavior of getting and setting a style property cssHooks: { opacity: { get: function( elem, computed ) { if ( computed ) { // We should always get a number back from opacity var ret = curCSS( elem, "opacity" ); return ret === "" ? "1" : ret; } } } }, // Exclude the following css properties to add px cssNumber: { "columnCount": true, "fillOpacity": true, "fontWeight": true, "lineHeight": true, "opacity": true, "orphans": true, "widows": true, "zIndex": true, "zoom": true }, // Add in properties whose names you wish to fix before // setting or getting the value cssProps: { // normalize float css property "float": "cssFloat" }, // Get and set the style property on a DOM Node style: function( elem, name, value, extra ) { // Don't set styles on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } // Make sure that we're working with the right name var ret, type, hooks, origName = jQuery.camelCase( name ), style = elem.style; name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); // gets hook for the prefixed version // followed by the unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // Check if we're setting a value if ( value !== undefined ) { type = typeof value; // convert relative number strings (+= or -=) to relative numbers. #7345 if ( type === "string" && (ret = rrelNum.exec( value )) ) { value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); // Fixes bug #9237 type = "number"; } // Make sure that NaN and null values aren't set. See: #7116 if ( value == null || type === "number" && isNaN( value ) ) { return; } // If a number was passed in, add 'px' to the (except for certain CSS properties) if ( type === "number" && !jQuery.cssNumber[ origName ] ) { value += "px"; } // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, // but it would mean to define eight (for every problematic property) identical functions if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { style[ name ] = "inherit"; } // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { style[ name ] = value; } } else { // If a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { return ret; } // Otherwise just get the value from the style object return style[ name ]; } }, css: function( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ); // Make sure that we're working with the right name name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); // gets hook for the prefixed version // followed by the unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { val = curCSS( elem, name, styles ); } //convert "normal" to computed value if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // Return, converting to number if forced or a qualifier was provided and val looks numeric if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; } }); curCSS = function( elem, name, _computed ) { var width, minWidth, maxWidth, computed = _computed || getStyles( elem ), // Support: IE9 // getPropertyValue is only needed for .css('filter') in IE9, see #12537 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, style = elem.style; if ( computed ) { if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // Support: Safari 5.1 // A tribute to the "awesome hack by Dean Edwards" // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; } } return ret; }; function setPositiveNumber( elem, value, subtract ) { var matches = rnumsplit.exec( value ); return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : value; } function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { var i = extra === ( isBorderBox ? "border" : "content" ) ? // If we already have the right measurement, avoid augmentation 4 : // Otherwise initialize for horizontal or vertical properties name === "width" ? 1 : 0, val = 0; for ( ; i < 4; i += 2 ) { // both box models exclude margin, so add it if we want it if ( extra === "margin" ) { val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); } if ( isBorderBox ) { // border-box includes padding, so remove it if we want content if ( extra === "content" ) { val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // at this point, extra isn't border nor margin, so remove border if ( extra !== "margin" ) { val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } else { // at this point, extra isn't content, so add padding val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // at this point, extra isn't content nor padding, so add border if ( extra !== "padding" ) { val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } return val; } function getWidthOrHeight( elem, name, extra ) { // Start with offset property, which is equivalent to the border-box value var valueIsBorderBox = true, val = name === "width" ? elem.offsetWidth : elem.offsetHeight, styles = getStyles( elem ), isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; // some non-html elements return undefined for offsetWidth, so check for null/undefined // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 if ( val <= 0 || val == null ) { // Fall back to computed then uncomputed css if necessary val = curCSS( elem, name, styles ); if ( val < 0 || val == null ) { val = elem.style[ name ]; } // Computed unit is not pixels. Stop here and return. if ( rnumnonpx.test(val) ) { return val; } // we need the check for style in case a browser which returns unreliable values // for getComputedStyle silently falls back to the reliable elem.style valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); // Normalize "", auto, and prepare for extra val = parseFloat( val ) || 0; } // use the active box-sizing model to add/subtract irrelevant styles return ( val + augmentWidthOrHeight( elem, name, extra || ( isBorderBox ? "border" : "content" ), valueIsBorderBox, styles ) ) + "px"; } // Try to determine the default display value of an element function css_defaultDisplay( nodeName ) { var doc = document, display = elemdisplay[ nodeName ]; if ( !display ) { display = actualDisplay( nodeName, doc ); // If the simple way fails, read from inside an iframe if ( display === "none" || !display ) { // Use the already-created iframe if possible iframe = ( iframe || jQuery("

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.