diff --git a/components/onlinepackagemanager/opkman_common.pas b/components/onlinepackagemanager/opkman_common.pas index 9561f4e83b..d10bfe4ccb 100644 --- a/components/onlinepackagemanager/opkman_common.pas +++ b/components/onlinepackagemanager/opkman_common.pas @@ -127,6 +127,7 @@ function GetDirSize(const ADirName: String; var AFileCnt, ADirCnt: Integer): Int procedure FindPackages(const ADirName: String; APackageList: TStrings); procedure FindAllFilesEx(const ADirName: String; AFileList: TStrings); function FixProtocol(const AURL: String): String; +function IsDirectoryEmpty(const ADirectory: String): Boolean; implementation @@ -439,5 +440,27 @@ begin Result := 'https://' + Result; end; +function IsDirectoryEmpty(const ADirectory: String): Boolean; +var + SearchRec: TSearchRec; + SearchRes: Longint; +begin + Result := true; + SearchRes := FindFirst(IncludeTrailingPathDelimiter(ADirectory) + AllFilesMask, faAnyFile + faSymLink, SearchRec); + try + while SearchRes = 0 do + begin + if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then + begin + Result := False; + Break; + end; + SearchRes := FindNext(SearchRec); + end; + finally + SysUtils.FindClose(SearchRec); + end; +end; + end. diff --git a/components/onlinepackagemanager/opkman_const.pas b/components/onlinepackagemanager/opkman_const.pas index 831ba0b679..546a8e5af5 100644 --- a/components/onlinepackagemanager/opkman_const.pas +++ b/components/onlinepackagemanager/opkman_const.pas @@ -393,6 +393,7 @@ resourcestring rsRepositories_InputBox_Caption0 = 'Add repository'; rsRepositories_InputBox_Caption1 = 'Edit repository'; rsRepositories_InputBox_Text = 'Type the repository address:'; + rsRepositories_Info1 = 'The following repository: "%s" is already in the list.'; //create private repository rsCreateRepositoryFrm_Caption = 'Create private repository'; @@ -409,9 +410,50 @@ resourcestring rsCreateRepositoryFrm_VSTPackages_Column0 = 'Repository/Packages'; rsCreateRepositoryFrm_VSTDetails_Column0 = 'Description'; rsCreateRepositoryFrm_VSTDetails_Column1 = 'Data'; + rsCreateRepositoryFrm_RepositoryAddress = 'Address'; + rsCreateRepositoryFrm_RepositoryDescription = 'Description'; + rsCreateRepositoryFrm_VSTText_Category = 'Category'; + rsCreateRepositoryFrm_VSTText_RepositoryFilename = 'Repository filename'; + rsCreateRepositoryFrm_VSTText_RepositoryFileSize = 'Repository filesize'; + rsCreateRepositoryFrm_VSTText_RepositoryFileHash = 'Repository filehash'; + rsCreateRepositoryFrm_VSTText_RepositoryFileDate = 'Available since'; + rsCreateRepositoryFrm_VSTText_HomePageURL = 'Home page'; + rsCreateRepositoryFrm_VSTText_DownloadURL = 'Update link (JSON)'; + rsCreateRepositoryFrm_VSTText_Version = 'Version'; + rsCreateRepositoryFrm_VSTText_Description = 'Description'; + rsCreateRepositoryFrm_VSTText_Author = 'Author'; + rsCreateRepositoryFrm_VSTText_LazCompatibility = 'Lazarus compatibility'; + rsCreateRepositoryFrm_VSTText_FPCCompatibility = 'FPC compatibility'; + rsCreateRepositoryFrm_VSTText_SupportedWidgetsets = 'Supported widgetsets'; + rsCreateRepositoryFrm_VSTText_Packagetype = 'Package type'; + rsCreateRepositoryFrm_VSTText_Dependecies = 'Dependencies'; + rsCreateRepositoryFrm_VSTText_License = 'License'; + rsCreateRepositoryFrm_VSTText_PackageType0 = 'Designtime and runtime'; + rsCreateRepositoryFrm_VSTText_PackageType1 = 'Designtime'; + rsCreateRepositoryFrm_VSTText_PackageType2 = 'Runtime'; + rsCreateRepositoryFrm_VSTText_PackageType3 = 'Runtime only, cannot be installed in IDE'; rsCreateRepositoryFrm_Error1 = 'Cannot open private repository. Error message: ' + sLineBreak + '"%s"'; rsCreateRepositoryFrm_Error2 = 'File ' + cRemoteJSONFile + ' not found.'; rsCreateRepositoryFrm_Error3 = 'Cannot save private repository. Error message: ' + sLineBreak + '"%s"'; + rsCreateRepositoryFrm_Info1 = 'The following directory: "%s" is not empty.' + sLineBreak + 'It''s recommended to save the repository to an empty directory. Continue?'; + rsCreateRepositoryFrm_Info2 = 'The following directory: "%s" is read only.'; + + //repository details + rsRepositoryDetails_Caption = 'Repository details'; + rsRepositoryDetails_lbName_Caption = 'Name'; + rsRepositoryDetails_edName_Hint = 'Enter the repository name'; + rsRepositoryDetails_lbAddress_Caption = 'Address'; + rsRepositoryDetails_edAddress_Hint = 'Enter the repository address(Ex: "http://localhost/packages/")'; + rsRepositoryDetails_lbDescription_Caption = 'Description'; + rsRepositoryDetails_mDescription_Hint = 'Enter the repository description'; + rsRepositoryDetails_bOk_Caption = 'OK'; + rsRepositoryDetails_bOk_Hint = 'Save and close the dialog'; + rsRepositoryDetails_bCancel_Caption = 'Cancel'; + rsRepositoryDetails_bCancel_Hint = 'Close the dialog without saving'; + rsRepositoryDetails_Info1 = 'Please enter the repository name.'; + rsRepositoryDetails_Info2 = 'Please enter the repository address.'; + rsRepositoryDetails_Info3 = 'The following repository: "%s" is already in the repository list. Continue?'; + implementation diff --git a/components/onlinepackagemanager/opkman_createrepositoryfrm.lfm b/components/onlinepackagemanager/opkman_createrepositoryfrm.lfm index b2a9458bd5..b8bb9b170d 100644 --- a/components/onlinepackagemanager/opkman_createrepositoryfrm.lfm +++ b/components/onlinepackagemanager/opkman_createrepositoryfrm.lfm @@ -12,7 +12,6 @@ object CreateRepositoryFrm: TCreateRepositoryFrm OnCreate = FormCreate OnDestroy = FormDestroy PopupMode = pmExplicit - PopupParent = MainFrm.Owner Position = poOwnerFormCenter LCLVersion = '1.9.0.0' object pnButtons: TPanel @@ -28,10 +27,10 @@ object CreateRepositoryFrm: TCreateRepositoryFrm TabOrder = 2 OnResize = pnButtonsResize object bOpen: TButton - Left = 96 + Left = 101 Height = 27 Top = 4 - Width = 80 + Width = 85 Caption = 'Open' OnClick = bOpenClick ParentShowHint = False @@ -42,42 +41,18 @@ object CreateRepositoryFrm: TCreateRepositoryFrm Left = 16 Height = 27 Top = 4 - Width = 80 + Width = 85 Caption = 'Create' OnClick = bCreateClick ParentShowHint = False ShowHint = True TabOrder = 0 end - object bAdd: TButton - Left = 368 - Height = 27 - Top = 4 - Width = 80 - BorderSpacing.Around = 1 - Caption = 'Add' - Constraints.MinWidth = 80 - ParentShowHint = False - ShowHint = True - TabOrder = 2 - end - object bDelete: TButton - Left = 448 - Height = 27 - Top = 4 - Width = 80 - BorderSpacing.Around = 1 - Caption = 'Delete' - Constraints.MinWidth = 80 - ParentShowHint = False - ShowHint = True - TabOrder = 3 - end object bCancel: TButton - Left = 702 + Left = 700 Height = 27 Top = 4 - Width = 80 + Width = 85 Anchors = [akTop, akRight] BorderSpacing.Around = 1 Caption = 'Cancel' @@ -85,6 +60,100 @@ object CreateRepositoryFrm: TCreateRepositoryFrm ModalResult = 2 ParentShowHint = False ShowHint = True + TabOrder = 2 + end + object bAdd: TBitBtn + Left = 311 + Height = 27 + Top = 4 + Width = 85 + Caption = 'Add' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BDD8E8005FA7D3FF56A2D0FFB5D3 + E500009600FF009600FF009600FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00D7E9F20078B7DBFF2D8EC8FF8FCDEBFF6FB7E2FF408E + C8FF009600FF00C000FF009600FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00ECF4F90093C9E3FF3F9CCEFF82C4E5FFCCF4FFFFC4EFFFFF8BD2F1FF8ACE + F0FF009600FF00C000FF009600FFD1E9E100FFFFFF00FFFFFF00FAFDFE00AFD8 + EB0055ABD5FF7DC0E0FFC7EEFCFFCCF2FFFFA8E8FFFF009600FF009600FF0096 + 00FF009600FF00C000FF009600FF009600FF009600FF009600FF6FB8D80077BD + DCFFBFE5F6FFDBF6FFFFC1EEFFFFA5E5FFFF9FE3FFFF009600FF00C000FF00C0 + 00FF00C000FF00C000FF00C000FF00C000FF00C000FF009600FF45A9D3FFE7FB + FEFFDDF6FFFFC1EFFFFFB7EBFFFFABE8FFFFA4E4FFFF009600FF009600FF0096 + 00FF009600FF00C000FF009600FF009600FF009600FF009600FF4EAED6FFE2F6 + FCFFD4F3FFFFC9F0FFFFBEEDFFFFB3EAFFFFADE7FFFF7CD9FEFF48C7EFFF43C4 + EAFF009600FF00C000FF009600FF40A7E1FF83C5ECFF328DC7FF51B1D6FFE2F6 + FCFFD7F4FFFFCEF2FFFFC8EFFFFFBAEBFFFF92DBFBFF56C1F1FF48C2F9FF3BBD + F0FF009600FF00C000FF009600FF47B1E6FF88CAEEFF3490C8FF53B4D7FFE2F6 + FDFFDAF4FFFFD5F3FFFFBDEBFFFF89D5F7FF69C9F5FF4CB4E9FF8DDAFBFF8CDC + FFFF009600FF009600FF009600FF4FBBE8FF8CD0F0FF3693C9FF55B6D8FFE2F8 + FDFFD4F3FFFFB0E4FAFF86CFF1FF7FD0F5FF78D0F5FF4CB1E4FFB0E4FAFFB6E9 + FFFF9BE1FFFF78D6FEFF40BDF5FF3DB5E9FF90D5F1FF3895CAFF4FB4D8FFE1F8 + FEFFCDEBF9FF92D2EDFF84CCEBFF6FBFE5FF56B1DBFF3B94C8FFCEECFAFFD9F5 + FFFFB9EAFFFF95DFFEFF77D5FFFFA5E4FFFF84DCFBFF3193C9FF89CADE004EB5 + D9FFA5D9EDFFD2EBF5FFBEDEEDFF95C9DEFF89C3DBFF70B8D6FF69B9DDFF90D7 + F5FF7FCFF5FF9DDBF8FFAAE3FAFF84CAECFF51A6D5FF74B3D500FFFFFF00C7E4 + EE0076C4DEFF7EC6E0FFD1EEF7FFF6FFFFFFF0FEFFFFCBEDFBFF50ADDAFF8BD7 + F7FFAAE1F9FF95D6F2FF62B2DBFF61AED4FFBAD9E800FFFFFF00FFFFFF00FFFF + FF00FCFEFE00AFD8E60063BDDBFF92CFE5FFE6F8FCFFE3F6FEFFAFDDF2FFB2E4 + F7FF72C0E1FF55ADD5FFA3CFE100F8FCFD00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00F0F9FC0099CEE00055B6D9FF9CD5EAFF88CCE7FF4DAF + D6FF8FC7DD00ECF6FB00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E1F2F8007DC3DCFF76C0DCFFDCEF + F700FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + GlyphShowMode = gsmAlways + ParentShowHint = False + ShowHint = True + TabOrder = 3 + end + object bDelete: TBitBtn + Left = 396 + Height = 27 + Top = 4 + Width = 85 + Caption = 'Delete' + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BDD8E8005FA7D3FF56A2D0FFB5D3 + E500009600FF009600FF009600FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00D7E9F20078B7DBFF2D8EC8FF8FCDEBFF6FB7E2FF408E + C8FF009600FF00C000FF009600FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00ECF4F90093C9E3FF3F9CCEFF82C4E5FFCCF4FFFFC4EFFFFF8BD2F1FF8ACE + F0FF009600FF00C000FF009600FFD1E9E100FFFFFF00FFFFFF00FAFDFE00AFD8 + EB0055ABD5FF7DC0E0FFC7EEFCFFCCF2FFFFA8E8FFFF009600FF009600FF0096 + 00FF009600FF00C000FF009600FF009600FF009600FF009600FF6FB8D80077BD + DCFFBFE5F6FFDBF6FFFFC1EEFFFFA5E5FFFF9FE3FFFF009600FF00C000FF00C0 + 00FF00C000FF00C000FF00C000FF00C000FF00C000FF009600FF45A9D3FFE7FB + FEFFDDF6FFFFC1EFFFFFB7EBFFFFABE8FFFFA4E4FFFF009600FF009600FF0096 + 00FF009600FF00C000FF009600FF009600FF009600FF009600FF4EAED6FFE2F6 + FCFFD4F3FFFFC9F0FFFFBEEDFFFFB3EAFFFFADE7FFFF7CD9FEFF48C7EFFF43C4 + EAFF009600FF00C000FF009600FF40A7E1FF83C5ECFF328DC7FF51B1D6FFE2F6 + FCFFD7F4FFFFCEF2FFFFC8EFFFFFBAEBFFFF92DBFBFF56C1F1FF48C2F9FF3BBD + F0FF009600FF00C000FF009600FF47B1E6FF88CAEEFF3490C8FF53B4D7FFE2F6 + FDFFDAF4FFFFD5F3FFFFBDEBFFFF89D5F7FF69C9F5FF4CB4E9FF8DDAFBFF8CDC + FFFF009600FF009600FF009600FF4FBBE8FF8CD0F0FF3693C9FF55B6D8FFE2F8 + FDFFD4F3FFFFB0E4FAFF86CFF1FF7FD0F5FF78D0F5FF4CB1E4FFB0E4FAFFB6E9 + FFFF9BE1FFFF78D6FEFF40BDF5FF3DB5E9FF90D5F1FF3895CAFF4FB4D8FFE1F8 + FEFFCDEBF9FF92D2EDFF84CCEBFF6FBFE5FF56B1DBFF3B94C8FFCEECFAFFD9F5 + FFFFB9EAFFFF95DFFEFF77D5FFFFA5E4FFFF84DCFBFF3193C9FF89CADE004EB5 + D9FFA5D9EDFFD2EBF5FFBEDEEDFF95C9DEFF89C3DBFF70B8D6FF69B9DDFF90D7 + F5FF7FCFF5FF9DDBF8FFAAE3FAFF84CAECFF51A6D5FF74B3D500FFFFFF00C7E4 + EE0076C4DEFF7EC6E0FFD1EEF7FFF6FFFFFFF0FEFFFFCBEDFBFF50ADDAFF8BD7 + F7FFAAE1F9FF95D6F2FF62B2DBFF61AED4FFBAD9E800FFFFFF00FFFFFF00FFFF + FF00FCFEFE00AFD8E60063BDDBFF92CFE5FFE6F8FCFFE3F6FEFFAFDDF2FFB2E4 + F7FF72C0E1FF55ADD5FFA3CFE100F8FCFD00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00F0F9FC0099CEE00055B6D9FF9CD5EAFF88CCE7FF4DAF + D6FF8FC7DD00ECF6FB00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E1F2F8007DC3DCFF76C0DCFFDCEF + F700FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + GlyphShowMode = gsmAlways + ParentShowHint = False + ShowHint = True TabOrder = 4 end end @@ -135,11 +204,24 @@ object CreateRepositoryFrm: TCreateRepositoryFrm TabOrder = 3 Visible = False end + object SD: TSaveDialog + DefaultExt = '.opkman' + Filter = '*.opkman|*.opkman' + Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail] + left = 41 + top = 83 + end + object OD: TOpenDialog + DefaultExt = '.opkman' + Filter = '*.opkman|*.opkman' + left = 88 + top = 84 + end object imTree: TImageList left = 40 - top = 24 + top = 32 Bitmap = { - 4C69030000001000000010000000A38D780095806C12B3A18B9FC5B49FFEC6B5 + 4C691A0000001000000010000000A38D780095806C12B3A18B9FC5B49FFEC6B5 A0FFC6B5A0FFC6B5A0FFC6B5A1FFBEAD98E3A5917C4BFFFFFF00988674000000 0000000000000000000000000000FFEAD300AC9A886AD5C9BBF9E3D9CBFFE2D9 CAFFE2D9CAFFE2D9CAFFE3D9CAFFE0D6C8FFC3B4A4CB84715C189B8874000000 @@ -235,20 +317,743 @@ object CreateRepositoryFrm: TCreateRepositoryFrm CA2B2E90C9A52C8EC8FE8FCDEBFF6FB7E2FF408EC8FF2485C4AC2383C331FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF002A8BC6462889C5BE2687C5C42485C44DFFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00 + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000 + 0000000000000000000000000000C8E6F240C6E5F04000000000000000001CA7 + 1D6014AB26BF1FB438FF19AA23FF00000000000000000000000000000000C9E7 + F220C2E7F4CFB3E6F9FFACE1F9FFADE1F8FFAEE1F7FFAEE1F6FFADDFF5FF90D8 + DCFF77E294FF98EDAAFF5BC962FF000000000000000000000000C9E7F230BFE8 + F6EFADE7FCFFABE3F9FFA3DEF8FFA9E1FAFFB0E4F9FFB7E7F9FFB6E7F9FFA7DE + F5FFB8F4C3FFB6F4B7FF5AC65BFF0000000000000000C9E7F230B6E7F8EFA4E0 + F8FFA5E1F9FF95D6F3FFB0E4F7FFA6DFF8FFA4DFFAFFA5DFFAFFACE2F9FFA7DF + F6FF7BD296FF67CC67FF2EB02EFFD1BDA9FFC9BAA7FFAFD4DAFFA2DEF5FF98D7 + F1FF9AD8F3FFA0DEF6FF97D8F4FFA5DEF5FFAEE3F9FF9FDCF8FF8CD3F3FF75C6 + EDFF3CAA82FF20A921FF0DA00DFFD1BDA9FFCAEBF5FFA8E0F4FF8DCEE8FFA0DD + F6FF92D2EDFF9BD9F3FF78BFDDFF9BDAF7FF89D0F0FF79C9EFFF61BEE9FF57B8 + E4FF299058FF15A415FF10A110FFD1BDA9FFC2E5F1FF99D0E4FFAAE4FBFF87CA + E6FFA4DFF8FF79C0DDFF9CDBF4FF7FC1DCFF6399ABFF5A91A4FF48656BFF91B2 + BE8F19A02460029A0280059B0550D1BDA9FFEEF7FAFFC1E8F3FF90CFE8FFA4DE + F4FF86C9E6FF98D7F1FF85C4DFFF6E7F7FFF9A8A7BFFC1B5ABFF77604EFFDCD5 + D030000000000000000000000000D1BDA9FFF5FAFCFFB3D5DFFF8CC6DDFFAEE0 + F0FF96CFE4FFA3DBF1FF739DA9FFB7ADA0FFF2EBE4FFFFFFFFFF8F7966FF0000 + 0000000000000000000000000000D1BDA9FFFFFFFFFFFBF5EEFFE1E6E4FFB6D0 + D7FF99C6D5FF87BBCDFFC4CAC6FFF7F1EAFFFBF5EEFFFFFFFFFF8F7966FF0000 + 0000000000000000000000000000D1BDA9FFFFFFFFFFFAF2EAFFFAF2EAFFFAF2 + EAFFFAF2EAFFF3EEE8FFFAF2EAFFFAF2EAFFFAF2EAFFFFFFFFFF8F7966FF0000 + 0000000000000000000000000000D1BDA9FFFFFFFFFFF9F0E7FFF9F0E7FFF9F0 + E7FFF9F0E7FFF9F0E7FFF9F0E7FFF9F0E7FFF9F0E7FFFFFFFFFF8F7966FF0000 + 0000000000000000000000000000C9B4A1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F7966FF0000 + 0000000000000000000000000000927C69FF8F7966FF8F7966FF8F7966FF8F79 + 66FF8F7966FF8F7966FF8F7966FF8F7966FF8F7966FF8F7966FF8F7966FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000004D46 + 45114D4645DD4D4645FF4C4544EC4B4444B5494544D545403F4F000000000000 + 0000000000000000000000000000000000000000000000000000000000004A44 + 42E647423FFF464140FF3C3230FF352725FF392C2AFF413C3BFF3F3A393A0000 + 0000000000000000000000000000000000000000000000000000413C3A15413D + 3BFF423C3AFF301F1BFF5D7270FF719798FF464D4CFF2E1E1AFF3B3735750000 + 00000000000000000000000000000000000000000000000000003B39391E3024 + 21FF2D1B13FF343031FF99EAF2FFB6FFFFFFA7FDFFFF4A585DFF291F1A740000 + 00000000000000000000000000000000000000000000000000003519001B667B + 81FF74B8D9FF95E7FFFF9AE8FFFF8BD5FCFF9AF4FFFF84C6CFFF2713055E0000 + 00000000000000000000000000000000000000000000000000000C3CA51DACEF + FFFF8CE8FFFF74D0FFFF5BC4FBFF56C3FAFF59CEFFFF4FAFE9FF223F853C0000 + 00000000000000000000000000000000000000000000000000000000000086D0 + FFFF49B9F9FF3AB0F8FF3EB3FAFF40B3F9FF47C3FFFF37A1F2FF0D35BE240000 + 0000000000000000000000000000000000000000000000000000000000002D80 + EAD14CBFFFFF2BA6FCFF3AAAFAFF3AABFAFF27AEFFFF0B4496BB000000000000 + 0000000000000000000000000000000000000000000000000000180400317278 + 89E77BC3FFFF198AF0FF0A87FDFF0281F4FF55A9FDFF9B939DFF332A14760000 + 000000000000000000000000000000000000000000001F1B1963736F6DFFFFFF + FFFFFDFEFFFFCAD8F6FFA4BBD5FFBACFEDFFFFFFFFFFFFFFFFFF50494AFF221E + 1CB500000000000000000000000000000000191614467A7576FF7F7B7AFF7D79 + 78FFFFFFFFFFFFECC2FFFFCE56FFFFF4BEFFF5F8FFFF989392FF322A29FF433E + 3DFF282423950000000000000000191615483C3736CC9A9696FF352F2FFF2A25 + 24FF706E71FFFFFFFFFFEBC170FFFFFFFFFF969396FF211A1AFF45403FFF4944 + 43FF302B2AFF221F1F4C0000000033302EB47A7674FF5C5654FF373330FF322C + 2AFF575355FFFFFFFCFFE4AF55FFFFFFFAFF807F84FF272221FF403B39FF423D + 3BFF3A3734FF23201EC400000000474342D27E7976FF3E3836FF393533FF3630 + 2EFF3B3D43FFFDEFD4FFD4901DFFFFF9D4FF63666CFF241E1BFF3E3836FF3E39 + 37FF3F3D39FF211E1CE6000000003A3835CD555351FF35312FFF383432FF3C36 + 34FF272B38FFFFEEC6FFEB8B00FFFFEA9AFF6D7587FF25201BFF383432FF332F + 2DFF2E2A29FF1F1B1AE500000000100D0C000F0D0C38171312971A1817CE1E1A + 18F6131218F3625847F3563100F3685030F32C2F39F7120E0EDF1C1817B01512 + 1286150F104B1816152100000000000000000000000000000000000000000000 + 000000000000653E2F8C663E2EEB663F30E96643358300000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000067473BB5694639FFFDE6D8FFFDE6D8FF694639FF674A3FB1000000000000 + 000000000000000000000000000000000000000000000000000000000000582A + 180F694639FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6D8FF694639FF674A3FB10000 + 00000000000000000000000000000000000067473BB9694639FF694639FF6946 + 39FFF3C0A0FFFAE1D1FFFDE6D8FFFDE6D8FFFDE6D8FFF3C0A0FF694639FF6946 + 39FF694639FF67473BB90000000067473BB967463AFFFDE6D8FFFDE6D8FFFDE6 + D8FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6D8FFFDE6 + D8FFFDE6D8FF67463AFC67473BB967473BB9694639FFFDE6D8FF313131FF3131 + 31FF313131FF857468FFFDE6D8FFFDE6D8FF857468FF313131FF313131FF3131 + 31FFFDE6D8FF694639FF67473BB900000000694639FFEBB492FFFDE6D8FF3131 + 31FFFDFFFFFF313131FFF9DBC9FFEFBFA1FF313131FFFDFFFFFF313131FFEBB4 + 92FFEBB492FF694639FF000000000000000000000000694639FFFDE6D8FFFDE6 + D8FF857468FF313131FFEBB492FFEBB492FF313131FF857468FFEBB492FFEBB4 + 92FF694639FF00000000000000000000000000000000694639FFFDE6D8FFFDE6 + D8FF313131FFEBB492FFEBB492FFEBB492FFEBB492FF313131FFEBB492FFEBB4 + 92FF694639FF000000000000000000000000694639FFEBB492FFFDE6D8FFFDE6 + D8FF313131FFEBB492FF313131FF313131FFEBB492FF313131FFEBB492FFEBB4 + 92FFEBB492FF694639FF0000000067473BB9694639FFFDE6D8FFFCE2D2FFEBB4 + 92FF313131FFEBB492FF313131FF313131FFEBB492FF313131FFEBB492FFEBB4 + 92FFEBB492FF694639FF67473BB967473BB967463AFFFCE2D2FFEBB492FFEBB4 + 92FFEBB492FF656061FFEBB492FFEBB492FF656061FFEBB492FFEBB492FFEBB4 + 92FFEBB492FF67463AFF67473BB90000000067473BB9694639FF694639FF6946 + 39FFEBB492FFEBB492FFEBB492FFEBB492FFEBB492FFEBB492FF694639FF6946 + 39FF694639FF67473BB900000000000000000000000000000000000000000000 + 0000694639FFEBB492FFEBB492FFEBB492FFEBB492FF694639FF000000000000 + 0000000000007878780100000000000000000000000000000000000000000000 + 000067473BB9694639FFEBB492FFEBB492FF694639FF674A3FB1000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000068483CB4694639FF694639FF684A3E9A00000000000000000000 + 0000000000000000000000000000759FC7FE668FB0FE69839BFE918F93FEC8B4 + A2FECDA78CFEC69573FEC3906FFEC5A590FEC5A691FEC4A591FEC49E85FEC085 + 5EFEC0855DFEC59574F9C5A48E386B8EB0FE79AECEFE6381A2FE7A8396FEA791 + 83FEEBA36FFEFA893CFEFB934DFEFCE5D5FEFDAC7AFEFDAB78FEFD9A5BFEFC65 + 04FEFB6502FEF96707FDD58B5BF992B0C4FE6E92B0FE6CA2C7FE617A99FE798B + 97FEB39074FEF69856FEFC9A58FEFDD7BEFEFE670BFEFE6506FEFE6502FEFE65 + 00FEFD6500FEFD6500FDE0752CFDA3C7D8FE5A84AAFE66A5D2FE577FA6FE7299 + B1FE8E7771FEEB9D67FEFCA062FEFEEEE3FEFEC6A2FEFEC59FFEFE8334FEFE65 + 00FEFE6500FEFE6500FEE0752BFE4D5368FE4E6F98FE5489C0FE5080B2FE566A + 87FE73534EFED9925FFEFCA367FEFED9C2FEFE6E16FEFE6C12FEFE6607FEFE64 + 01FEFE6500FEFE6500FEE1752CFE403D49FE75A5BCFE82C9E7FE73B1D8FE5B82 + 96FE87746EFEE8A371FEFCA468FEFED6BCFEFE9652FEFEBD93FEFEBA8EFEFEA7 + 70FEFE6D0FFEFE6500FEE1752CFE5B6A77FE6F9EB0FE9AD4F1FE91D0EDFE7EAF + CCFE9D9896FEEEA775FEFC8E44FEFD8738FEFEB382FEFEB48AFEFE7B2CFEFECE + AEFEFEA168FEFE6401FEE1752CFE90B6CCFE4A586EFE8AC0DFFE86C6ECFE75B2 + DDFE9FA3A3FEF4B17FFEFC8B3DFEFD7012FEFEB382FEFEAC7DFEFE6E16FEFEC9 + A7FEFE9859FEFE6500FEE1752CFE8DC2D9FE374254FE6DAAD6FE65A7DAFE7ABA + DCFE9DB2BCFEE8B28BFEFB924AFEFD7418FEFEB484FEFEDECBFEFEC7A3FEFEA5 + 6CFEFE6808FEFE6500FEE1752CFE5A7994FE405770FE659CCDFE5A91C7FE82BC + DAFEAFCAD3FECFB097FEF79B5BFEFD7B24FEFEB687FEFEAA79FEFE6506FEFE64 + 03FEFE6403FEFE6500FEE1752CFE343A4AFE74A2BDFE72ADDFFE477CA4FE5872 + 86FE858988FEA68B72FEEB985DFEFC802BFEFEAA72FEFE9D64FEFE8A41FEFEB7 + 89FEFEBA8DFEFE7C2AFEE1752CFE444756FE769FBFFE89B7D9FE8EAEBFFE4C46 + 4DFE52312AFE845738FEEE975CFEFC7F2AFEFE6C0CFEFE8438FEFECCACFEFE75 + 20FEFE731DFEFE6F13FEE1752CFE45596EFE87ACC7FE99C3D5FEB5DAE3FE98A2 + A2FE5D4133FED1946BFEFA9753FEFC7921FEFE6806FEFEAD7DFEFEA46BFEFE64 + 01FEFE6500FEFE6500FEE1752BFE5E7E8EFE85A9BDFE9CBFCEFEA7C8D0FE9EA0 + 9AFEB69171FEF4A36BFEFC8737FEFD7112FEFE6602FEFEA46CFEFEB88AFEFE65 + 03FEFE6400FEFE6500FEE0752BFE546873FE838F9EFE899AA5FE817F81FECBAC + 97FEF0AB7BFEFC9148FEFD761DFEFD6906FEFE6500FEFE7119FEFED1B4FEFEB4 + 84FEFDA167FEFD8437FDE08549F9717A82006B6B74FE9BA0A3FEA8A29EFEDBBD + A6FEE7AB7FFEE48E53FEE17B37FEE1752DFEE1742CFEE1742BFEE17B37FEE195 + 62FEE19460FEDF8B53F9D7966838000000000000000000000000000000000000 + 000000000000F1CF9020F1CF9034F1CF9034F1CF9015F1CD8DFFF1D091060000 + 000000000000000000000000000000000000000000000000000000000000F7D4 + 8C87F1CF8FFFF1CF8FFFF1CF8FD7F1CE90EAF1CE8EFFF0CD8EFFF1CD8DFF0000 + 000000000000000000000000000000000000415CF15F314AF585C0AAA651FFDD + 83FFF4D08D5A000000000000000000000000EECA8ACBEFCA89FFF6C682FFCFD1 + A06257F3FD8329EDF35F00000000415BF1C55978F3FF4866F3FF2539F4FF090E + FC1100000000000000000000000000000000EFCA89FFF4C5822DA2D6B45E79F8 + FFFFA5F6FDFF4BF1F4FF15CEF6C53C55F0FF5270F2FF4662F1FF2F3FEFFF2420 + EE8500000000000000000000000000000000000000000000000012F2FF8177F4 + F9FF95F6FAFF41F2F4FF16C5F7FF2E3BEFFF374CEFFF3243EFFF282BEEFF231C + ED8800000000000000000000000000000000000000000000000013D2F67320E8 + F4FF2BEDF4FF16DBF4FF19ABFAFF1618F74D1A1BF6FF1C1AF2FF1611F6E70000 + 00000000000000000000000000000000000000000000000000000000000018B3 + F8E816B6F9FF0FA6FFFF0B99FF5C00000000D4A97EC95040D34A000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00001198FF34B7AB866AF3B0572EE3B56F74E6B76BFFEAB968E2000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000EFAC528ADDAA5E86DFAF68FFDEAF67E3DEAE67EFDEAE66930000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000DBA556C4D8A5575B00000000DBA95DA8DBA95CB7000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000D49F4D06D49F4DFFD59F4E0C00000000D8A4570CD6A254FFD5A1515A0000 + 0000000000000000000049B5742247B3708A45AD662200000000DE9A42FF0000 + 0000D19A42CFD099419A000000000000000000000000D29C4848D29C47FFD19A + 4399000000003BB776444EBF87FF4FC28DFF47B26CFF35A95839DB9536B4CE95 + 38FFCD9537DF0000000000000000000000000000000000000000CF963C20CE95 + 38DCD99230FF3AB471C34FC28CFF50C491FF48B370FF34A753C1D88F29FFC98F + 2AFFC88E26C3C88E26FF00000000000000000000000000000000000000000000 + 00000000000038AB5FBC46B26DFF48B36EFF43AB5EFF34A449BC000000000000 + 0000C88E25060000000000000000000000000000000000000000000000000000 + 0000000000003EA54C1B3FA44BFD3FA44DFF3EA245E83CA2451B000000000000 + 0000000000000000000000000000170B0B166952246F53411C59453418493B2F + 1340392B113A32291237332512363325123632291237392B113A3B2F13404335 + 18484E3C1B545F4B20654031164340311643EFBB52FFEFBB52FFEFBB52FFDCAC + 4BEBD5A648E4EFBB52FFECB952FFEBB952FFECB952FFE2B14DF2CB9E46D9EFBB + 52FFEFBB52FFEFBB52FF8D6F3097624C1F68EEBA51FFEEBA51FF7A5F2A83FFFF + FF00FFFFFF00E2B14EFAE7B550FFE8B651FFEDB951FF43351548FFFFFF00342B + 113ADCAD4BEDEEBA51FF9F7D35AB84682C90ECB84FFF6F562579FFFFFF00FFFF + FF00FFFFFF00D7A84BF5E3B24EFFEBB74FFFECB84FFF372A113CFFFFFF00FFFF + FF003B2F1340E9B54FFEAC863BBFAB8537BBA58036B3FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D7A84AF5EAB64DFFEBB74DFFEBB74DFF372A113CFFFFFF00FFFF + FF00FFFFFF0084692D99BF9540D4BB913CCD261F0C28FFFFFF00FFFFFF00FFFF + FF00FFFFFF00DEAC49F4EAB64CFFEAB64CFFEAB64CFF372A113CFFFFFF00FFFF + FF00FFFFFF002621162BBC923ED2FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00DDAC47F4E8B44AFFE8B44AFFE8B44AFF372A113CFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00DCAB46F4E7B349FFE7B349FFE7B349FF372B123DFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00DBA943F4E5B147FFE5B147FFE4B047FF392F1B46FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00DAA842F4E4B046FFE3AF46FFDCAA46FF39301C48FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D8A640F4E1AD44FFDAA944FFD8A844FF352F1B46FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00D6A53EF4D9A842FFD7A742FFD9A842FF332B123DFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00CE9F3EF6D5A541FFD7A641FFDEAA41FF3629103DFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000004044 + 440224251F25D5A43FFFD6A53FFFDDA93FFFDEAA3FFF513E155EFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000141505107159 + 238CB98E37DED7A53EFFDBA83EFFDCA83EFFDCA83EFFD19F3AF3826325972B20 + 0A2FFFFFFF00FFFFFF00FFFFFF00000000000000000040444401191A0E156951 + 2081644D1D785C46196C55411965563F166459431869634B1A736A501C7C2C22 + 0A34FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0078CF82D475CD80FF73CA7DFE70C77AB4FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0077CF + 821278CD82FF9CD9A7FF98D8A2FF6DC476ECFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0072C97CF497D8A2FF8DD297FF69C072BEFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0079D083FF76CE81FF74CB7EFF71C9 + 7BFF6FC678FE97D7A1FF93D59DFF65BC6EF062B86AED5FB567EF5BB163EFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0076CE80FF9BD9A6FF99D8A4FF98D7 + A2FF96D7A1FF95D59EFF93D49CFF8FD198FF8CD095FF8ACF94FF57AD5EFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0073CB7DFF99D8A3FF97D7A1FF79CB + 87FF69C377FF65C273FF64C171FF67C273FF66C071FF8BCF94FF53A95AFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0070C77AFF6DC477FF7CC985FF93D4 + 9CFF65C172FF62C06FFF5FBE6CFF5DBD69FF5ABB66FF88CF90FF66B56DFF4CA1 + 52FF489D4EFF45994AFFFFFFFF00FFFFFF00FFFFFF00FFFFFF0066BD6FFF90D2 + 99FF60BF6DFF5EBD6AFF5BBC68FF59BB64FF56BA61FF65BF6FFF83CC8BFF82CA + 89FF80CA88FF419646FFFFFFFF00FFFFFF00FFFFFF00FFFFFF0063B96BFF8DD1 + 96FF5DBC69FF5ABB66FF58BA63FF55B960FF52B75DFF62BD6BFF81CA88FF7EC8 + 85FF7EC884FF3E9242FFFFFFFF00FFFFFF0065BC6EFF62B86AFF72C07AFF8BCF + 93FF58BB64FF56BA61FF53B85FFF51B65BFF4FB559FF80CA87FF5CAC62FF4094 + 45F93D9142FF3A8E3FFFFFFFFF00FFFFFF0062B86AFF8BCF95FF8ACF92FF69C1 + 72FF86CD8EFF84CC8CFF83CB8AFF81CA88FF5DBB66FF7EC884FF409445FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005EB465FF88CF91FF56B961FF85CD + 8DFF65B56CFF4CA152FF499E4FFF5DAD63FF7CC783FF7BC681FF3C9041FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005AAF61FF86CD8EFF84CC8CFF83CA + 89FF4CA152FFFFFFFF00FFFFFF00429647FF7AC681FF76C37CFF398D3DFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0056AB5DFF52A759FF4FA455FF4BA0 + 51FF489C4DF7FFFFFF00FFFFFF003E9243FD3B8F40FD398C3DF4368A3AE6FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0036BAEC4438BBECF23FBDEDF33CBCEDF238BBECF236BAEC3FFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0036B7 + E9836ACBEFF6ABE4F8FBC6EFFCFDC3EEFCFDAAE3F8FB5DC6EEF536B7E980FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0036B3E58E7ED0 + F0F7C7F1FEFEBEF1FFFFB6EFFFFFB6EFFFFFBFF1FFFFC8F1FEFE7ACFEFF736B3 + E58EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0036AFE14769C5EAF6C4F2 + FFFFABECFFFF88D8F4FF66BFE5FF65BFE4FF84D5F1FFACECFFFFC5F2FFFF5FC1 + E8F536AFE139FFFFFF00FFFFFF00FFFFFF0036ABDD093CAEDEF299DBF4FBA5EA + FFFF81D5F3FF54AFDAFF51B2DDFF50B3DEFF53AED9FF7BCFEFFFA6EAFFFF97DA + F3FA3AADDEF236ABDD06FFFFFF00FFFFFF0036A7D9093CAADAF29AE0F8FC91E5 + FFFF5FB7DEFF4CACD9FF48C0EEFF48C0EEFF4CAFDCFF5BB2DAFF92E5FFFF9ADF + F7FC3CAADAF236A7D909FFFFFF00FFFFFF0036A2D4063AA4D5F294DEF8FD86E2 + FFFF59B0D9FF49A7D4FF48C0EEFF48C0EEFF49ABD8FF56ABD5FF87E3FFFF90DC + F7FC38A3D5F236A2D403FFFFFF00FFFFFF00FFFFFF00369DCF9D7CCEEFFA80DF + FFFF6CCAEFFF4695C3FF46A1CFFF46A4D2FF4595C3FF68C4EAFF81E0FFFF7ACD + EDFA369DCF97FFFFFF00FFFFFF00FFFFFF00FFFFFF003698CA3945A3D1F479D9 + FAFE73DCFFFF63C4EBFF50A6D0FF50A5D0FF60C0E7FF73DCFFFF78D9FAFE41A0 + CFF33698CA33FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003693C57858B1 + DBF76ED6FBFE6CD9FFFF6BD9FFFF6BD9FFFF6CD9FFFF6ED5FAFE56AFD9F63693 + C575FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00368EC0644096 + C5F365C0E7FE64D5FDFF64D7FFFF64D7FFFF66D7FEFF65C0E7FE3A91C2F2368E + C041FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00368ABC614493C2F396D9 + F4FD66C3EBFF4FADD8FF49A1CEFD4AA2CFFD4FACD8FF68C3E9FF8ACDEBFB368A + BCA5368ABC17FFFFFF00FFFFFF00FFFFFF003686B811428EBDF39EDAF2FD86DF + FFFF65D7FFFF59BCE7FA3787B9F23989BBF25DC5EFFC68D7FFFF90E2FFFF7EBC + DDF93686B87AFFFFFF00FFFFFF00FFFFFF003682B41A458EBCF383D7F7FE63D6 + FFFF56B9E5FA3783B5F23682B4393682B4553B88B9F35BC8F2FD6AD8FFFF91DA + F7FE3B86B7F23682B409FFFFFF00FFFFFF00FFFFFF00367EB0754590BFF456B1 + DDF9377FB1F2367EB036FFFFFF00FFFFFF00367EB0643E88B9F360C7F1FD458F + BEF4367EB075FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00367BAD2B367B + AD86367BAD22FFFFFF00FFFFFF00FFFFFF00FFFFFF00367BAD61367BADC4367B + AD61FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000 + 0000000000000000000000000000565B82030000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000006F7B + E1377F84AE335A5A5A0100000000616DDA814251E1C27077B65C7B7C850A0000 + 00000000000000000000000000000000000000000000000000005E6DF3701F35 + FDF94F5CD9C6848484126E6F74014D5BE1BF1D31FFFF152BFEFF7178B1917B7B + 7B0700000000000000000000000000000000000000007E84B7451F34FDFD2437 + FFFF3143FEFE81849D5F86868E0A4555F9F42E40FFFF4E5BDFF48484846D7878 + 780600000000000000000000000000000000000000008383830D7479AD91394A + FBFC3D4DFEFF6670DBCF85889D4C4755FEFF4756FAFE818396B08484841E0000 + 0000505578010000000000000000000000000000000000000000838383147D81 + A68A5360F9FA5966FDFE7F86D4C75864FEFF787EBDDF86878A53747DCA5B4859 + F9AE5360DABA8483840F00000000000000007380EA546C76D0657980C1528386 + A64F868AB4A36D78FAFC6F79FDFE717CF9FE747CD6E75360F9F73747FFFF2538 + FFFF394AEAED8484842F0000000000000000505CD2A62135FFFF3344FFFF4655 + FEFF5864FEFF6A75FEFF7980FEFF717AFDFF6470FDFF4E5BFEFF394AFEFF273A + FFFF2B3FF9FB8484844400000000000000005E67C18B1E33FFFF3143FEFF5763 + EFFC747BC8EC747DEFFB6F7AFCFE6873FDFF7F85C6E9898A8D9F898A909E8587 + 95A5818499A58484843A0000000000000000767AA75B5E67C3D980839CC08484 + 84867C80B3A15361FDFF757DD0F06570EEF54D5BFEFF6B74CFB28585871A8383 + 830D7A7A7A0E7373730500000000000000008282820C838383328383831C8285 + A1234756F7EF4151FEFF797EB0C37A7EB2973D4DFEFF3344FFFF5460DBC08586 + 8B18000000000000000000000000000000000000000000000000000000004F5E + EBB1283BFFFF3244FEFF85869492848485234A58EBE32437FFFF192EFEFF666F + C1AC8383830B00000000000000000000000000000000000000008085AD332337 + F7F8172DFEFF3849F1FA84848460838383057479AC751F34FBFE666EB9E28484 + 84718282820B00000000000000000000000000000000000000007F7E7F0A8484 + 8C62626AB9C55E68C4DA8383833700000000848485158082998D848484558282 + 820D000000000000000000000000000000000000000000000000000000007171 + 71058383831D8383833C8282820F000000004F4F4F017B7B7B0B6E6E6E040000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000BC990000BDCC0000BDCC0000 + BDCC0000BDCC0000BDCC0000BDCC0000BDCC0000BDCC0000BDCC0000BDCC0000 + BDCC0000BDCC0000BC99FFFFFF00FFFFFF000000B3CC817AFCFF7468FBFF7468 + FBFF7468FBFF7468FBFF7468FBFF7468FBFF7468FBFF6E61FAFF5B4DF7FF5244 + F9FF6159FAFF0000B3CCFFFFFF00FFFFFF000000A4CC5D50E9FF4A38E4FF4A38 + E4FF4A38E4FF4A38E4FF4A38E4FF4A38E4FF3926DEFF200AD7FF1C06D8FF1D06 + DBFF3523E2FF0000A4CCFFFFFF00FFFFFF000000939900008DCC00008DCC0000 + 8DCC00008DCC00008DCC00008DCC00008DCC00008DCC00008DCC00008DCC0000 + 8DCC00008DCC00009399FFFFFF00FFFFFF00C18701A6C28801DEC28801DEC288 + 01DEC28801DEC28801DEC28801DEC28801DEC28801DEC28801DEC28801DEC288 + 01DEC28801DEC18701A6FFFFFF00FFFFFF00B77C01DCF9D071FFF6CD6EFFF6CD + 6EFFF6CD6EFFF6CD6EFFF6CD6EFFF3C968FFEEC054FFEFBD49FFF0BE49FFF2BF + 49FFF7C44EFFB77C01DCFFFFFF00FFFFFF00A76C01D8E7BE5FFFE0B758FFE0B7 + 58FFE0B758FFE0B758FFD8AC47FFCC9C2EFFCD9D2CFFD09F2DFFD2A12DFFD6A3 + 2EFFDFAD37FFA76C01D8FFFFFF00FFFFFF00955801A08F5101D48F5101D48F51 + 01D48F5101D48F5101D48F5101D48F5101D48F5101D48F5101D48F5101D48F51 + 01D48F5101D4955801A0FFFFFF00FFFFFF0000A7529900A853CC00A853CC00A8 + 53CC00A853CC00A853CC00A853CC00A853CC00A853CC00A853CC00A853CC00A8 + 53CC00A853CC00A75299FFFFFF00FFFFFF00009A49CC7FEBB5FF7BE8B2FF7BE8 + B2FF7BE8B2FF75E4ADFF62DC9FFF59DB9AFF58DC9AFF59DE9CFF59DF9CFF5AE1 + 9DFF5EE6A2FF009A49CCFFFFFF00FFFFFF0000883ACC6CD9A3FF65D29CFF65D2 + 9CFF55C78EFF3DB87BFF3AB779FF3BBA7BFF3CBD7DFF3DC07FFF3EC280FF3EC5 + 82FF48CE8BFF00883ACCFFFFFF00FFFFFF0000722999006B23CC006B23CC006B + 23CC006B23CC006B23CC006B23CC006B23CC006B23CC006B23CC006B23CC006B + 23CC006B23CC00722999FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A6968886A69688FFA69688FFA696 + 88FFA69688FFA696885D000000000000000000000000A696880AA69688B9A696 + 88FFA69688FFA69688FFA69688FFA69688FFA69688FFDFD0C2FFECDDCFFFC0AF + A0FFB7A799FFA69688FF000000000000000000000000A6968810A69688FFBAAA + 9CFFBAAA9CFFBAAA9CFFB9AA9CFFB8A99BFFA69688FFC2B2A4FFECDDCFFFC1B1 + A2FFB7A799FFA69688FF000000005CA8CAFF5CA8CAFF5CA8CAFF5CA8CAFF5CA8 + CAFF5BA7C9FF4897BCFF2E82ABFF2A7EA8FFA69688B9A69688FFA69688FFA696 + 88FFA69688FFA696889D000000005CA8CAFFB2EFF9FFB2EFF9FFB2EFF9FFB2EF + F9FFB2EFF9FFB2EFF9FFB2EFF9FF2A7EA8FF00000000A69688FFFBF8F5FFCFC1 + B6FFA69688FFA6968800000000005CA8CAFFB2EFF9FF88D4F0FF97DEF3FF4F95 + DBFFACEBF8FFB2EFF9FFB5F1FAFF2A7EA8FF00000000A69688FFC7BBB1FF735F + 4EFFA69688FFA6968800000000005CA8CAFF73BDDBFF7AC2DDFF7FC5DEFF83C8 + DFFF86CAE0FF88CBE1FF89CBE1FF2A7EA8FF00000000A69688FFF6F1EBFFAF9F + 91FFA69688FFA6968800000000005BA7CAFFB2EFF9FFB2EFF9FFB2EFF9FF4F95 + DBFFBEF6FCFFC3FAFDFFC6FBFEFF2A7EA8FF00000000A69688FFC2B9B2FF9281 + 72FFA69688FFA6968800000000004393B9FFB2EFF9FFA1E4F5FFAFEDF9FFBBF4 + FBFFC2F9FDFFC7FCFEFFCAFEFFFF2A7EA8FF00000000A69688FFF3ECE5FF9E8C + 7DFFA69688FFA6968800000000002B7FA8FF2A7EA8FF2A7EA8FF2A7EA8FF2A7E + A8FF2A7EA8FF2A7EA8FF2A7EA8FF2A7EA8FFA69688FFA69688FFA69688FFA696 + 88FFA69688FFA696889D00000000000000000000000000000000A69688FFB7A7 + 99FFB7A799FFB7A799FFB7A799FFB7A799FFA69688FFDFD0C2FFECDDCFFFC1B1 + A2FFB7A799FFA69688FF00000000000000000000000000000000A696889DA696 + 88FFA69688FFA69688FFA69688FFA69688FFA69688FFDFD0C2FFECDDCFFFC0AF + A0FFB7A799FFA69688FF00000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A69688FFA69688FFA696 + 88FFA69688FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000A69688B9A69688FFA69688FFCABBADFFB9A9 + 9AFFA69688FFA69688FFA69688B9000000000000000000000000000000000000 + 0000000000000000000000000000A69688FFF5E7D9FFECDDCFFFB3A69AFFB3A6 + 9AFFC9B8A9FFBDAB9CFFA69688FF000000000000000000000000000000000000 + 0000000000000000000000000000A69688B9A69688FFA69688D9A6968872A696 + 8872A69688D9A69688FFA69688B9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000C17B7440C17B7AB0C17B7EE0C17B7FA0C17B7EE0C17B7AB0C17B744FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000C17B51A0C17 + B5902B3AC3FB7087E2FD97B2F3FF9EBAF6FF97B2F3FF7087E2FD2B3AC3FB0C17 + B590FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000D16B381586A + D5FD86A7F1FF5987EDFF3E73EAFF3970EAFF3E73EAFF5987EDFF86A7F1FF0D16 + B3F7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000D16B01A0D16 + B0900D16B0FA366BE7FF366BE7FF366BE7FF366BE7FF366BE7FF0D16B0FA0D16 + B090FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0049997496499974FF4999 + 74960D15AD930D15ADFA3365E3FF3365E3FF3365E3FF0D15ADFA0D15AD93B16A + 428EB16A42F2B16A428EFFFFFF00FFFFFF0043936F4865A88BFFC6E5DBFF4393 + 6FFF43936F960E15AA930E15AAFA2F5EDFFF0E15AAFA0E15AA93AD653F8EAD65 + 3FF2EDCCAFFFBF825FF6AD653F47FFFFFF003D8C69B18BC1ACFF72BDA4FFC2E3 + D8FF3D8C69FF3D8C69960E14A6930E14A6FA0E14A693A9603B8EA9603BF2EBC9 + ACFFD79358FFD5A17CFBA9603BABFFFFFF00378664EA7CBEA6FF68B79BFF68B7 + 9BFFBEE0D4FF378664FF378664963786640FA55A378EA55A37F2EAC6A9FFD48D + 52FFD48D52FFD69968FEA55A37DE317F5E0333805FFF67B497FF5FB092FF5FB0 + 92FF5FB092FFBADDD0FF317F5EFF398565FF995836F3E8C3A5FFD0874BFFD087 + 4BFFD0874BFFD28C53FFA15634F2FFFFFF002B7858ED52A686FF55A989FF55A9 + 89FF55A989FF55A989FFAED4C5FF337E5FFFDBBC9EFFCD8144FFCD8144FFCD81 + 44FFCD8144FFCA7E43FE9C502FE1FFFFFF00257253B4459776FF4BA380FF4BA3 + 80FF4BA380FF4BA380FF4EA381FF2D785AFFC07A3FFFCA7B3EFFCA7B3EFFCA7B + 3EFFCA7B3EFFBD713EFB984A2BABFFFFFF001F6B4D4B327E60FF429D78FF429D + 78FF429D78FF429D78FF479D7AFF277154FFBD7539FFC77638FFC77638FFC776 + 38FFC77638FFA55935F694452747FFFFFF00FFFFFF00196548A22D8562FF3997 + 71FF399771FF399771FF3E9873FF216B4FFFBA7033FFC47132FFC47132FFC471 + 32FFB2602DFA9040249AFFFFFF00FFFFFF00FFFFFF0014604339166245FF247B + 58FF32916AFF32926AFF37936CFF1C664AFFB86C2EFFC26D2DFFC26D2DFFAA58 + 27F98E3E22F28C3C2036FFFFFF00FFFFFF00FFFFFF00FFFFFF00105B3F21105B + 3F93166647FF237E59FF308D65FF186246FFB4662AFFB05B25FB954320F58938 + 1D8E89381D22FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000C573C480C573CB10C573CE7374B30C286351BE986351BA886351B44FFFF + FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000000000000000000000000000000000000000000000000000 + 000000000000CECFD8B19C9CAEFFA5A5B4FABABABD16F3F3F5C1A2A3B4FFA4A4 + B5FFA9A9AF5C0000000000000000000000000000000000000000E5E5E52DFDFD + FD7FFAFAFB807D7F9CF9595B80FF9B9CAEE1F4F4F47FAFB0C2FE5C5E82FF7C7D + 98FDE3E3E577A5A5A52C00000000000000000000000000000000D4D4E1C1C6C6 + D7FFBDBED1FF46487DFF46487DFFB3B4C8FFCECFDDFF5F618EFF46487CFF9495 + B2FFD4D4E1FFC1C1CAA0000000000000000000000000B9BAC02934367EFE1E20 + 6FFF232572FF31337BFF444587FF464788FF464788FF464788FF464788FF4647 + 88FF464788FF8384A27D000000000000000000000000C0C1D35256589AC35658 + 9AD30D1073FF090C7DFF41448DE16C6DA8E14E5098FF444692FF5E609FEE6F71 + A9DA6768A3D773738216000000000000000000000000FBFBFB89FAFAFAFCD0D0 + EBFC0A0D92FF1C1FAAFFE8E8EBF4F3F4F9F4191B90FF0A0D88FFC8C8DCF3ECED + EEDE7F7F8503000000000000000000000000A6A6AF148F91D7F78788D3FF5153 + C7FF0B0DA2FF3638BBFF9596E1FF7375E3FF0D10C2FF1F21A7FF9899D6FF9E9F + D9FE78788135000000000000000000000000C1C1EB690D0EBCFF0C0DBCFF0F10 + CEFF0D0EC0FF1012DDFF1113E5FF0F10D2FF1112E3FF0C0DBAFF0C0DB9FF3536 + B9E2545468040000000000000000000000009B9BCF427272D6717070EBC3100F + E3FF2625E2FD6D6CDD837D7DF5EC1311EAFF1B1BDDFE6160D5936060DF8E8080 + CF510000000000000000000000000000000000000000000000007080F9D5132B + F5FF525CD9C0D0D0D7208A9EFEFD1837F8FF4B5ADFC700000000000000000000 + 00000000000000000000000000000000000000000000BBC1CB2D2B70FEFF1C8E + FEFF798AB663DADEE33E3696FFFF1B80FEFF799BC56200000000000000000000 + 00000000000000000000000000000000000000000000A6B5CC2D62B6F17E7FE2 + F78167777D0DC1DAE63A62C2FE8E6DC3F7906576820B00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000FFFFFF00000000000000000000000000B0A4 + 8DFFCCC6B6FF00000000000000000000000000000000B1A58DFFCFC8B5FF0000 + 00000000000000000000FFFFFF00FFFFFF005173D2FF0748FEFF0045FFFF9689 + 6DFFCDC7B7FF3062EEFF0546FCFF0848FCFF0045FFFF96896DFFCFC9B6FF0041 + FFFF0647FDFF5173D2FFFFFFFF00FFFFFF000138F1FF9DB4FCFF98B1FFFF7F70 + 4AFFD2CDB7FFA5B5EBFF9AB1FBFF9CB2FBFF99B2FFFF80704AFFD4CDB6FF95AE + FFFF9DB3FBFF0138F1FFFFFFFF00FFFFFF000020E7FF506DEEFF0016E6FF000E + BDFF000CBCFF0017E6FF0018E2FF0018E2FF0019E7FF000EBDFF000CBBFF0015 + E5FF506DEEFF0020E7FFFFFFFF00FFFFFF00A39C89FFFFFFFDFFF2EDDEFFF4EF + E0FFF5EFE0FFF6EFDFFFF5EFDEFFF4EFDDFFF4EFDEFFF4EFE0FFF3EFE0FFF2ED + DDFFFFFFFDFFA39C89FFFFFFFF00FFFFFF00948F8BFFFFFFFFFFE8E6E2FFE9E6 + E2FFEDE8E5FFF1E9E7FFECE8E4FFE8E7E2FFE7E6E1FFE7E6E2FFE6E6E1FFE6E6 + E1FFFFFFFFFF948F8BFFFFFFFF00FFFFFF008E8C89FFFFFFFFFFF2EAEBFFF4EA + ECFFFDEDF1FF008444FFF4EBEDFFECEAE9FFEAE9E8FFEAE8E7FFEAE9E8FFEAE9 + E8FFFFFFFEFF8E8C88FFFFFFFF00FFFFFF008D8987FFFFFFFFFF008342FFFFF4 + F9FF008546FFB1D6CAFFF6F0F1FF9B9A9AFFBDBDBDFFEFEFEEFF9B9B9BFFBDBD + BDFFFFFFFFFF8C8886FFFFFFFF00FFFFFF00898683FFFFFFFFFFFFF5F9FF0083 + 43FFFFF5FBFFFDF2F6FFF5F0F2FFF2F0F1FFF1F0F0FFF1EFF0FFF1F0F0FFF2F0 + F1FFFFFFFFFF888682FFFFFFFF00FFFFFF0086827FFFFFFFFFFFFBF6F6FFFFF6 + F8FFFFF7F9FFAFD8CAFFFAF5F5FFF4F3F2FFF2F2F1FFF2F2F1FFF3F3F1FFF3F3 + F2FFFFFFFFFF85827FFFFFFFFF00FFFFFF00837F7DFFFFFFFFFFFFFAFDFFFFFA + FDFFFFFDFFFF008141FFFFFAFDFFFAF9F9FFF7F7F8FFF7F7F7FFF8F8F8FFF9F9 + F9FFFFFFFFFF827F7DFFFFFFFF00FFFFFF00807D7AFFFFFFFFFF008140FFFFFF + FFFF008242FFBDE1D5FFFFFFFFFF979696FFC1C1C1FFFEFEFEFF979797FFC2C2 + C2FFFFFFFFFF7F7D79FFFFFFFF00FFFFFF007D7A76FFFFFFFFFFFFFFFFFF0081 + 41FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF7D7976FFFFFFFF00FFFFFF007C7976FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF7C7976FFFFFFFF00FFFFFF0075726FC07A7773FF787470FF7873 + 70FF777370FF767370FF76736FFF76736FFF76736FFF76736FFF76736FFF7673 + 70FF7A7773FF75726FC0FFFFFF00FFFFFF000000002300000033000000330000 + 0033000000330000003300000033000000330000003300000033000000330000 + 00330000003300000023FFFFFF00000000000000000000000000000000000000 + 000000000000C96C0616EDC887EAE7BA6AE900000000BF6A1A2DC07C3A76B365 + 1B5B000000000000000000000000000000000000000000000000000000000000 + 0000D078081FEFCE95EFFFF3A9FFFFEC8BFFE0A037DDC8854FD1E4FFFFFFBAA2 + 8DFF00000000000000000000000000000000000000000000000000000000D681 + 111EEFD196F4FFEF9DFFD0B377FFCEB37FFFFFD052FFF1C678FFF1FFFFFFBAA2 + 8DFF000000000000000000000000000000000000000000000000DC8A171FF0D1 + 97EFFFE78BFFD4B16CFF9798A0FF979AA4FFCDA65FFFF9B42FFFE7E5D7FFBAA2 + 8DFF0000000000000000000000000000000000000000E1941F1EF1D192F4FFD9 + 79FFD3AC62FF8D8C96FFA7A3A6FFA6A4A4FF9FA2B1FFD5A147FFE89500FFC899 + 5AFDAA45002C000000000000000000000000E8A02B1DF1D090EFFECC62FFD1A7 + 5BFFA7A9B3FFA9A7A8FF908C8BFF8D8987FFBCBCC0FFC1C5CFFFD09939FFE681 + 00FFCD7704EDA248091D00000000EFBB5A88F2CD82F3F6BC4CFFCFA24FFFA9AB + B8FFD0CFD1FFA9A3A1FF847E7EFF807B7AFFBEB9B6FFD4D6D9FFCBD3E2FFD9A7 + 45FFE68A00FFC97301F3B1590488EEBD5CE4EEAF34FFCF9E4FFFB0B4BEFFCFCF + D3FFD2CECDFFD4D1D0FFD3D0CFFFD4D2CFFFDEDDDBFFD7D4D3FFD6D7DDFFD6DE + E9FFDDAF4CFFDA8200FFCA7400E400000000ECA52AFFCDCFD6FFD2D3D7FFD6D4 + D0FFDAD9D7FFAFACACFFA9A7A6FFAAA9A8FFAFADACFFE0DFDEFFDCDAD8FFDFE1 + E6FFDCE3EDFFAB4700F50000000000000000EA9F24FFD8D8DBFFD8D7D9FFDAD7 + D7FFE9E7E6FF545051FF242324FF272425FF585152FFF0EFEFFFE1E0E0FFE5E5 + E5FFE6E7EAFFA64100ED0000000000000000EAA024FFDDDDE0FFDFDDDFFFE1DE + DDFFEFEFEDFF787574FF535151FF565554FF7C7A78FFF4F4F3FFE7E6E5FFEAEA + EBFFEBEDEEFFA84100EB0000000000000000E99E23FFE2E4E6FFE4E3E5FFE4E5 + E3FFF3F3F2FF82807FFF605E5CFF504F4EFF7D7978FFFDFCFBFFEDEDECFFF1F1 + F1FFF2F5F4FFA74200EB0000000000000000E99E23FFE9EAEBFFEAEBEBFFEAEA + E9FFF9F8F8FF8F8A89FF6B6663FF605C5AFF898785FFFFFFFFFFF3F2F2FFF5F7 + F6FFFEFFFFFFA53E00EB0000000000000000E89F26FFF0F4FFFFF0F5FFFFF0F5 + FEFFFEFFFFFF929399FF67666EFF6B6871FF98989FFFFFFFFFFFFCFFFFFFFDFF + FFFFFFFFFFFFA53E00EB0000000000000000E89F26FFF9F6E2FFF8F2E0FFF9F3 + DEFFFFFCE0FFB5AD9FFF95897BFF938878FFB5AE9DFFFFF4D0FFFDEBC6FFFDEC + C5FFFDEBBDFFA74400EC0000000000000000F8CD64FFF8CD64FFF5C755F4F1BC + 4EF3F0B846F3F4BB4FF3F5B647F3F2AE3BFFEBA52FFFDE900DFFD88500FFD57E + 00FFD77E00FFD77E00EA000000000000000000000000000000005BCA7BFF4ED0 + 82F34BC877F351CC7DF431993EFD000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000086DBAEFF24D8 + 86FF20D177FF23D578FF249035FF000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000007FD19DFF2CD3 + 77FF2BCA6CFF2ED06DFF268931FF000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000085C99DFF30D2 + 71FF2BC763FF2ECE65FF227625FF000000000000000000000000000000000000 + 0000000000000000000000000000218E2ED43A9D43FF3BA14FFF58C078FF31CB + 68FF2BC35BFF2EC55AFF259038FF237E2AFF20661EFF20611F82000000000000 + 000000000000000000000000000000000000227F26D886D69FFF42DD7BFF1BBA + 48FF2FBF57FF2EC358FF31DA60FF279935FF1E5E1A8900000000000000000000 + 00000000000000000000000000000000000000000000145F0DDA74BD82FF47D7 + 74FF22BD49FF33CC58FF26892EFF14490B7B0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000004700D467B7 + 72FF4DDF72FF0B7C14FF0A430284000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000001F5B + 18C7036506FF2B5A266500000000000000000000000000000000000000000000 + 0000000000000000000000000000AFABA80AACA9A55DACA6A356C0B2B74DB4AB + AD4E6A7C65ABC4B4BB38B4ABAB53ACA7A355ABA7A455ACA7A455ACA7A455ADA7 + A555B5A9AB54ADA8A662AFABA816BCB7B5DFF0F1F0FFF0EFF0FFECEDECFFF5F2 + F4FFFFF9FFF7EEEFEDFFEEEFEDFFEEEFEEFFEEEFEEFFEEEFEEFFF0EEEFFFF6F1 + F4FFEDEAE8FFFDF9FDFFC6C1C0F4BDB9B7FCFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBAE8 + C6FF0CBB4DFFD1EED3FFE4DADFF8B1AFABF2FFFFFFFFF8F8F7FFFAFAF9FFFAFA + F9FFFAFAF9FFFAFAF9FFFAFAF9FFFAFAF9FFFAFAF9FFFAFAF9FFFFFFFFFFB0D7 + B6FF18A237FFCEE3CBFFD4CDD0F3A7A4A0F2F4F3F4FFCDCBCBFFD0CECEFFD0CE + CEFFD0CECEFFD0CECEFFD0CECEFFD0CECEFFD0CECEFFD0CECEFFD1D0CFFFDFD4 + D9FFE3CFD9FFF9F2F6FFBBB9B7F2A29E9CFFEDEBEBFFA9A6A3FFAFABAAFFAFAB + AAFFAFABAAFFAFABAAFFAFABAAFFAFABAAFFAFABAAFFAFABAAFFAFABA9FFAFAC + AAFFACA8A7FFE1DEDCFFB2AFADFF7F7A7900AAA7A5F9B3AFAEF3B2AEADF3B2AE + ADF3B2AEADF3B2AEADF3B2AEADF3B2AEADF3B2AEADF3B2AEADF3B2AEADF3B2AE + ADF3B3AFAEF3AFABA8F7827E7CB1FFFFFF00DF943800E4993B00E89D3F00EA9F + 4048EA9F4048E89D3F00E4993B00DF943800A76F2A006E481B00A46C2800A46C + 280036230C000000000000000000FFFFFF00DF943800E4993B00E89D3F5CE89D + 3FCCE89D3FCCE89D3F5CE4993B00DF943800DE933700DB903500DA8F3400DA8F + 3400D4892F009B62200032200A00FFFFFF00DF943800E4993B5CE4993BCCFEDB + 8FFFFEDB8FFFE4993BCCE4993B5CDF943800DE933700DB903500DA8F3400DA8F + 3400D4892F00CD822A00C87D2600FFFFFF00DF94385CDF9438CCFCD68AFFFAC9 + 7DFFFAC97DFFFCD589FFDF9438CCDF94385CDE933700DB903500DA8F3400DA8F + 3400D4892F00CD822A00C87D2600FFFFFF00DB903599DA8F34CCDA8F34CCF9D1 + 85FFF9D084FFDA8F34CCDA8F34CCDB903599D88D3300D88D3200D98E3399D98E + 335CD4892F00CD822A00C87D2600FFFFFF00DA8F3400D78C3100D4892FCCF7CA + 7EFFF6CA7EFFD4892FCCD4892F00D2872D00CF842B00D1862D00D4892FCCD489 + 2FCCD3882F5CCD822A00C87D2600FFFFFF00D3882F00CD822A00CD822ACCF5C8 + 7CFFF5C77BFFCD822ACCCB802966CD822A81CD822AAACD822AC5CD822ACCEEC7 + 7AFFCD822ACCCC812A5CC87D2600FFFFFF00C77C2500C77C2500C77C25CCF2C2 + 73FFECBB66FFC77C25CCCD8731D3DDA34CE8E2AD54F6E3AF55FDE3AE54FFDCA2 + 45FFECBF6AFFC77C25CCC77C2548FFFFFF00C0752000C0752000C07520CCECB7 + 51FFEBB54DFFD5983FDFE7AD43FBE3A22FFFE5A839FFE7AE43FFE7AF45FFE4A6 + 36FFEEBE5BFFC07520CCC0752048FFFFFF00B96E1B00B96E1B00B96E1BCCF2B9 + 40FFF2B83DFFEFB02EFEEEAB23FFE1A53BEFC9852CD9BD741FCFB96E1BCCF4BF + 4BFFB96E1BCCBA6F1C5CBE731F00FFFFFF00B2671600B2671600B26716CCF9BC + 31FFF7AD0BFFF7B115FFD5932AE4B26716AAB368173FB469170FB26716CCB267 + 16CCB368175CB96E1B00BE731F00FFFFFF00AC611100AC611100AC6111CCFFBD + 25FFFEB204FFE6A425EFAC6111AAAF641413B2671600B1661500AD621299AD62 + 125CB2671600B96E1B00BE731F00FFFFFF007D450A00A65B0D00A65B0DCCFFBC + 1EFFFFB70EFFBE7817D9A75C0E3FA75C0E0059340B0059330B00AC611100AC61 + 110059340B000000000000000000FFFFFF000000000079400700A05508CCFFBB + 18FFFFB813FFA75D0BCFA055080F291603000000000000000000000000000000 + 0000000000000000000000000000FFFFFF000000000A000000189B5005CCFFBC + 1CFFFFBB19FF9B5005CC0000001A0000001900000016000000130000000E0000 + 000A000000050000000200000000FFFFFF00000000130000002F723A02A6974C + 02CC974C02CC723A02A600000033000000320000002C000000250000001C0000 + 00130000000A0000000400000000000000000000000000000000000000000000 + 000000000000000203011A699B401C6DA2400002030100000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000100082131022AA4F2CF2AA5F3CF0925380200000100000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000203001B70A75228A4F4FD28A4F4FD1C75AD5200020300000000000000 + 0000000000000000000000000000000000000000000000000000000000000001 + 0100071F2E0226A0EFCD26A3F3FE26A3F3FE26A1F0CD08243502000101000000 + 0000000000000000000000000000000102000001020000020301000204010414 + 1F021C7EBD6725A0F0FD25A1F1FE25A2F2FE25A0F0FD1D81C267041621020002 + 04010002030100010200000102000F456820145C8B4A1973AC6F1E89CF93229C + EAC0239EEEFC239FEFFE24A0F0FF24A0F0FF239FEFFE239EEEFC229CEBC01E8A + D0931973AD6F145D8D4A0F4669202294DED7219DECFC219EEDFD219EEEFE219E + EEFE219EEEFE229EEEFE229EEEFF229EEEFF229EEEFE219EEEFE219EEEFE219E + EEFE219EEDFD219DECFC2294DED70F3D5B1F2093DCD91F9CEBFE209CECFE209D + EDFF209DEDFF209DEDFF209DEDFF209DEDFF209DEDFF209DEDFF209DEDFF209C + ECFE1F9CEBFE2093DCD91041611F000203000E38551B1E90D9D51D9AE9FE1E9A + EAFE1E9BEBFF1E9BEBFF1E9BEBFF1E9BEBFF1E9BEBFF1E9BEBFF1E9AEAFE1D9A + E9FE1E91DAD50F3C591B0002030000000000000102000C354F191C91DCDD1C98 + E8FE1C99E9FF1C99E9FF1C99E9FF1C99E9FF1C99E9FF1C99E9FF1C98E8FE1C92 + DCDD0D3A55190001020000000000000000000000000000020401146EA6791A96 + E6FE1B97E7FF1B97E7FF1B97E7FF1B97E7FF1B97E7FF1B97E7FF1A96E6FE1572 + AD790002040100000000000000000000000000000000000203011270AC7C1894 + E4FD1995E5FF1995E5FF1995E5FF1995E5FF1995E5FF1995E5FF1894E4FD1374 + B37C0002030100000000000000000000000000000000000203011486D0A71692 + E2FE1792E2FE1792E2FE1792E2FE1792E2FE1792E2FE1792E2FE1692E2FE158A + D5A7000305010000000000000000000000000000000002111A01148EDDD11590 + E0FE1490DFFD158AD5F01474B2981473B198158AD5F01490DFFD1590E0FE148E + DDD1021521010000000000000000000000000000000005273E06138DDBF51489 + D5F41472AE8D09314C160004060100030501092F48161371AC8D1489D5F4138D + DBF5062B4406000000000000000000000000000001000621330B126BA4870B39 + 561F0006090100010100000000000000000000010100000508010A37531F126B + A3870624380B00000100000000004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004D4D4D004E4E4E019A9A9A409D9D9D404E4E4E014D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004D4D4D0064646402C6C6C6CFC6C6C6CF686868024D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004E4E4E009F9F9F52C6C6C6FDC6C6C6FDA3A3A3524E4E4E004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D0063636302C3C3C3CDC5C5C5FEC5C5C5FEC3C3C3CD666666024D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004E4E4E014E4E4E015B5B + 5B02AAAAAA67C3C3C3FDC3C3C3FEC4C4C4FEC3C3C3FDACACAC675D5D5D024E4E + 4E014E4E4E014D4D4D004D4D4D00808080209090904AA1A1A16FB2B2B293C0C0 + C0C0C1C1C1FCC2C2C2FEC3C3C3FFC3C3C3FFC2C2C2FEC1C1C1FCC0C0C0C0B3B3 + B393A2A2A26F9292924A80808020BABABAD7C1C1C1FCC1C1C1FDC1C1C1FEC1C1 + C1FEC1C1C1FEC1C1C1FEC1C1C1FFC1C1C1FFC1C1C1FEC1C1C1FEC1C1C1FEC1C1 + C1FEC1C1C1FDC1C1C1FCBABABAD77979791FB9B9B9D9C0C0C0FEC0C0C0FEC1C1 + C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC0C0 + C0FEC0C0C0FEB9B9B9D97C7C7C1F4E4E4E007676761BB7B7B7D5BFBFBFFEBFBF + BFFEBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFEBFBF + BFFEB8B8B8D57979791B4E4E4E004D4D4D004D4D4D0074747419B8B8B8DDBDBD + BDFEBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBDBDBDFEB8B8 + B8DD767676194D4D4D004D4D4D004D4D4D004D4D4D004E4E4E019E9E9E79BCBC + BCFEBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBCBCBCFEA1A1 + A1794E4E4E014D4D4D004D4D4D004D4D4D004D4D4D004E4E4E01A0A0A07CBABA + BAFDBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBABABAFDA3A3 + A37C4E4E4E014D4D4D004D4D4D004D4D4D004D4D4D004E4E4E01B1B1B1A7B9B9 + B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB3B3 + B3A74F4F4F014D4D4D004D4D4D004D4D4D004D4D4D0058585801B6B6B6D1B8B8 + B8FEB8B8B8FDB3B3B3F0A3A3A398A2A2A298B3B3B3F0B8B8B8FDB8B8B8FEB6B6 + B6D15C5C5C014D4D4D004D4D4D004D4D4D004D4D4D006A6A6A06B6B6B6F5B3B3 + B3F4A1A1A18D717171164F4F4F014F4F4F0170707016A0A0A08DB3B3B3F4B6B6 + B6F56D6D6D064D4D4D004D4D4D004D4D4D004D4D4D006565650B9C9C9C877676 + 761F515151014D4D4D004D4D4D004D4D4D004D4D4D00505050017575751F9C9C + 9C876767670B4D4D4D004D4D4D00000000000000000000000000000000000000 + 000000000000000203011A699B401A699B404E4E4E014D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D00000000000000000000000000000000000000 + 000000000100082031022BA4F1CF2BA4F1CF686868024D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D00000000000000000000000000000000000000 + 0000000203001A6FA6522BA5F3FD2BA5F3FDA3A3A3524E4E4E004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D00000000000000000000000000000000000001 + 0100061F2E0225A0EECD2BA4F2FE2BA4F2FEC3C3C3CD666666024D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D00000102000001020000020301000204010414 + 1F021C7DBD6724A0F0FD2AA3F2FE2AA3F2FEC3C3C3FDACACAC675D5D5D024E4E + 4E014E4E4E014D4D4D004D4D4D000F456820135C8B4A1872AC6F1E89CE93229C + EAC0229EEEFC229FEFFE28A1F0FF28A1F0FFC2C2C2FEC1C1C1FCC0C0C0C0B3B3 + B393A2A2A26F9292924A808080202193DDD7209CEBFC209DECFD209DEDFE209D + EDFE219DEDFE219EEEFE26A0EEFF26A0EEFFC1C1C1FEC1C1C1FEC1C1C1FEC1C1 + C1FEC1C1C1FDC1C1C1FCBABABAD70F3D5B1F1F92DBD91F9BEAFE1F9BEBFE1F9C + ECFF1F9CECFF209CECFF249EECFF249EECFFC1C1C1FFC1C1C1FFC1C1C1FFC0C0 + C0FEC0C0C0FEB9B9B9D97C7C7C1F000203000D38551B1E90D9D51D99E8FE1E99 + E9FE1E9AEAFF1E9AEAFF239CEAFF239CEAFFBFBFBFFFBFBFBFFFBFBFBFFEBFBF + BFFEB8B8B8D57979791B4E4E4E0000000000000102000C354F191C91DCDD1B98 + E8FE1C98E8FF1C98E8FF219AE8FF219AE8FFBEBEBEFFBEBEBEFFBDBDBDFEB8B8 + B8DD767676194D4D4D004D4D4D00000000000000000000020401146EA6791996 + E6FE1A97E7FF1A97E7FF1F98E6FF1F98E6FFBDBDBDFFBDBDBDFFBCBCBCFEA1A1 + A1794E4E4E014D4D4D004D4D4D000000000000000000000203011270AC7C1894 + E4FD1895E5FF1995E5FF1D97E4FF1D97E4FFBBBBBBFFBBBBBBFFBABABAFDA3A3 + A37C4E4E4E014D4D4D004D4D4D000000000000000000000203011486D0A71692 + E2FE1792E2FE1792E2FE1893E2FE1893E2FEB9B9B9FEB9B9B9FEB9B9B9FEB3B3 + B3A74F4F4F014D4D4D004D4D4D00000000000000000002111A01148EDDD11590 + E0FE1490DFFD158AD5F01575B2981575B298B3B3B3F0B8B8B8FDB8B8B8FEB6B6 + B6D15C5C5C014D4D4D004D4D4D00000000000000000005273E06138DDBF5148A + D5F41472AE8D09314C16000406010004060170707016A0A0A08DB3B3B3F4B6B6 + B6F56D6D6D064D4D4D004D4D4D0000000000000001000621330B126BA4870B39 + 561F000609010001010000000000000000004D4D4D00505050017575751F9C9C + 9C876767670B4D4D4D004D4D4D00000000000000000000000000000000000000 + 000000000000030100019B4C1A40A2511C400301000100000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000101000031180802F2782ACFF3782ACF381C090201010000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000003010000A7521B52F47828FDF47828FDAD541C5203010000000000000000 + 0000000000000000000000000000000000000000000000000000000000000100 + 00002E160702EF7526CDF37626FEF37626FEF07526CD35190802010000000000 + 0000000000000000000000000000020100000201000003010001040200011F0F + 0402BD5B1C67F07525FDF17525FEF27525FEF07525FDC25E1D67210F04020402 + 000103010001020100000201000068320F208B43144AAC52196FCF641E93EA70 + 22C0EE7323FCEF7323FEF07424FFF07424FFEF7323FEEE7323FCEB7122C0D064 + 1E93AD53196F8D44144A69320F20DE6C22D7EC7021FCED7021FDEE7121FEEE71 + 21FEEE7121FEEE7222FEEE7222FFEE7222FFEE7222FEEE7121FEEE7121FEEE71 + 21FEED7021FDEC7021FCDE6C22D75B2D0F1FDC6920D9EB6E1FFEEC7020FEED70 + 20FFED7020FFED7020FFED7020FFED7020FFED7020FFED7020FFED7020FFEC70 + 20FEEB6E1FFEDC6920D96130101F03010000552B0E1BD9671ED5E96C1DFEEA6E + 1EFEEB6E1EFFEB6E1EFFEB6E1EFFEB6E1EFFEB6E1EFFEB6E1EFFEA6E1EFEE96C + 1DFEDA671ED5592C0F1B0301000000000000020100004F260C19DC671CDDE86C + 1CFEE96C1CFFE96C1CFFE96C1CFFE96C1CFFE96C1CFFE96C1CFFE86C1CFEDC66 + 1CDD55280D190201000000000000000000000000000004020001A64C1479E66A + 1AFEE76B1BFFE76B1BFFE76B1BFFE76B1BFFE76B1BFFE76B1BFFE66A1AFEAD50 + 1579040200010000000000000000000000000000000003010001AC4E127CE468 + 18FDE56919FFE56919FFE56919FFE56919FFE56919FFE56919FFE46818FDB352 + 137C030100010000000000000000000000000000000003010001D05E14A7E266 + 16FEE26717FEE26717FEE26717FEE26717FEE26717FEE26717FEE26616FED560 + 15A705020001000000000000000000000000000000001A0B0201DD6314D1E065 + 15FEDF6314FDD56015F0B2521498B1521498D56015F0DF6314FDE06515FEDD63 + 14D1210E0201000000000000000000000000000000003E1C0506DB6113F5D560 + 14F4AE50148D4C240916060200010502000148220916AC4E138DD56014F4DB61 + 13F5441F0606000000000000000000000000010100003318060BA44B12875628 + 0B1F09030001010000000000000000000000010000000803000153260A1FA34A + 1287381A060B01010000000000004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004D4D4D004E4E4E019A9A9A409D9D9D404E4E4E014D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004D4D4D0064646402C6C6C6CFC6C6C6CF686868024D4D4D004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D004E4E4E009F9F9F52C6C6C6FDC6C6C6FDA3A3A3524E4E4E004D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D + 4D0063636302C3C3C3CDC5C5C5FEC5C5C5FEC3C3C3CD666666024D4D4D004D4D + 4D004D4D4D004D4D4D004D4D4D004D4D4D004D4D4D004E4E4E014E4E4E015B5B + 5B02AAAAAA67C3C3C3FDC3C3C3FEC4C4C4FEC3C3C3FDACACAC675D5D5D024E4E + 4E014E4E4E014D4D4D004D4D4D00808080209090904AA1A1A16FB2B2B293C0C0 + C0C0C1C1C1FCC2C2C2FEC3C3C3FFC3C3C3FFC2C2C2FEC1C1C1FCC0C0C0C0B3B3 + B393A2A2A26F9292924A80808020BABABAD7C1C1C1FCC1C1C1FDC1C1C1FEC1C1 + C1FEC1C1C1FEC1C1C1FEC1C1C1FFC1C1C1FFC1C1C1FEC1C1C1FEC1C1C1FEC1C1 + C1FEC1C1C1FDC1C1C1FCBABABAD77979791FB9B9B9D9C0C0C0FEC0C0C0FEC1C1 + C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC1C1C1FFC0C0 + C0FEC0C0C0FEB9B9B9D97C7C7C1F4E4E4E007676761BB7B7B7D5BFBFBFFEBFBF + BFFEBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFEBFBF + BFFEB8B8B8D57979791B4E4E4E004D4D4D004D4D4D0074747419B8B8B8DDBDBD + BDFEBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBEBEBEFFBDBDBDFEB8B8 + B8DD767676194D4D4D004D4D4D004D4D4D004D4D4D004E4E4E019E9E9E79BCBC + BCFEBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBDBDBDFFBCBCBCFEA1A1 + A1794E4E4E014D4D4D004D4D4D004D4D4D004D4D4D004E4E4E01A0A0A07CBABA + BAFDBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBBBBBBFFBABABAFDA3A3 + A37C4E4E4E014D4D4D004D4D4D004D4D4D004D4D4D004E4E4E01B1B1B1A7B9B9 + B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB9B9B9FEB3B3 + B3A74F4F4F014D4D4D004D4D4D004D4D4D004D4D4D0058585801B6B6B6D1B8B8 + B8FEB8B8B8FDB3B3B3F0A3A3A398A2A2A298B3B3B3F0B8B8B8FDB8B8B8FEB6B6 + B6D15C5C5C014D4D4D004D4D4D004D4D4D004D4D4D006A6A6A06B6B6B6F5B3B3 + B3F4A1A1A18D717171164F4F4F014F4F4F0170707016A0A0A08DB3B3B3F4B6B6 + B6F56D6D6D064D4D4D004D4D4D004D4D4D004D4D4D006565650B9C9C9C877676 + 761F515151014D4D4D004D4D4D004D4D4D004D4D4D00505050017575751F9C9C + 9C876767670B4D4D4D004D4D4D00FFFFFF00DD790000FFE8DD00FFE8DD00FFE8 + DD00DD790080E08417FFE69537FFEBA658FFEEB06FFFEEB06FFFEBA658FFE695 + 37FFE08417FFDD7900BFFFFFFF00FFFFFF00DB780000FFE8DD00FFE8DD00FFE8 + DD00DB7800FFFFE8DDFFFFE8DDFFFFE8DDFFFFE8DDFFFFE8DDFFFFE8DDFFF6CC + A6FFDB7800FFDB780000FFFFFF00FFFFFF00D8770000FFE1CF00FFE1CF00D877 + 0080ECAD68FFFFE1CFFFFFE1CFFFFFE1CFFFFFE1CFFFFFE1CFFFF5C79BFFD877 + 00FFFFE1CF00D8770000FFFFFF00FFFFFF00D5760000FFD9BB00FFD9BB00D576 + 00FFFFD9BBFFFFD9BBFFFFD9BBFFFFD9BBFFFFD9BBFFF4BF8CFFD57600FFFFD9 + BB00FFD9BB00D5760000FFFFFF00FFFFFF00D2760000FFCEA400D2760080E9A2 + 52FFFFCEA4FFFFCEA4FFFFCEA4FFFFCEA4FFF4B87BFFD27600FFFFCEA400FFCE + A400FFCEA400D2760000FFFFFF00FFFFFF00CE740000FFC28A00CE7400FFFFC2 + 8AFFFFC28AFFFFC28AFFFFC28AFFF3AE67FFDA8823FFCE7400FFCE7400FFCE74 + 00FFCE7400FFCE7400BFFFFFFF00FFFFFF00CA730000CA730080E59638FFFFB7 + 6FFFFFB76FFFFFB76FFFFFCFA6FFFFE8DDFFFFE8DDFFFFE8DDFFFFE8DDFFF2CB + A6FFCA7300FFCA730000FFFFFF00FFFFFF00C6720000C67200FFF29633FFF297 + 33FFF49939FFFAA347FFFEA850FFFEA850FFFBA449FFFAA246FFF19C3EFFC672 + 00FFFFA95300C6720000FFFFFF00FFFFFF00C1700080E0871DFFEE8C1CFFEE8C + 1CFFEE8C1CFFEA8615FFE37F0BFFDD7900FFE5810EFFEF922BFFC17000FFFF9E + 3900FF9E3900C1700000FFFFFF00FFFFFF00BD6F00BFBD6F00FFBD6F00FFBD6F + 00FFBD6F00FFCE7809FFE27D05FFE8810BFFEE8919FFBD6F00FFFF932200FF93 + 2200FF932200BD6F0000FFFFFF00FFFFFF00B96E0000FF8A0E00FF840000FF84 + 0000B96E0080DC7B07FFEB8006FFED820AFFB96E00FFFF840000FF8A0E00FF8A + 0E00FF8A0E00B96E0000FFFFFF00FFFFFF00B56C0000FF840000FF840000FF84 + 0000B56C00FFEE7E00FFEC7E00FFB56C00FFDD790000DD790000FF840000FF84 + 0000FF840000B56C0000FFFFFF00FFFFFF00B26B0000FF840000FF840000B26B + 0080D97800FFEC7E00FFB26B00FFFF840000FF840000FF840000FF840000FF84 + 0000FF840000B26B0000FFFFFF00FFFFFF00AF6A0000FF840000FF840000AF6A + 00FFEB7D00FFAF6A00FFFF840000FF840000FF840000FF840000FF840000FF84 + 0000FF840000AF6A0000FFFFFF00FFFFFF00AC690000AC690000AC690080AC69 + 00FFAC6900FFAC690000AC690000AC690000AC690000AC690000AC690000AC69 + 0000AC690000AC690000FFFFFF00FFFFFF00AA690000AA690000AA6900BFAA69 + 00FFAA690000AA690000AA690000AA690000AA690000AA690000AA690000AA69 + 0000AA690000AA690000FFFFFF00 } end - object SD: TSaveDialog - DefaultExt = '.opkman' - Filter = '*.opkman|*.opkman' - Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail] - left = 41 - top = 83 - end - object OD: TOpenDialog - DefaultExt = '.opkman' - Filter = '*.opkman|*.opkman' - left = 88 - top = 84 - end end diff --git a/components/onlinepackagemanager/opkman_createrepositoryfrm.pas b/components/onlinepackagemanager/opkman_createrepositoryfrm.pas index 31768ece6a..67c0e48c44 100644 --- a/components/onlinepackagemanager/opkman_createrepositoryfrm.pas +++ b/components/onlinepackagemanager/opkman_createrepositoryfrm.pas @@ -28,14 +28,14 @@ unit opkman_createrepositoryfrm; interface uses - Classes, SysUtils, FileUtil, + Classes, SysUtils, FileUtil, fpjson, // LCL Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Buttons, // LazUtils - LazFileUtils, + LazFileUtils, LazUTF8, // OpkMan - opkman_VirtualTrees; + opkman_VirtualTrees, opkman_serializablepackages; type @@ -51,9 +51,9 @@ type { TCreateRepositoryFrm } TCreateRepositoryFrm = class(TForm) - bAdd: TButton; bCancel: TButton; - bDelete: TButton; + bAdd: TBitBtn; + bDelete: TBitBtn; bOpen: TButton; bCreate: TButton; imTree: TImageList; @@ -73,10 +73,13 @@ type FVSTPackages: TVirtualStringTree; FVSTDetails: TVirtualStringTree; FRepository: TRepository; + FSerializablePackages: TSerializablePackages; procedure EnableDisableButtons(const AEnable: Boolean); procedure ShowHideControls(const AType: Integer); - function LoadRepository(const AFileName: String; out AErrMsg: String): Boolean; - function SaveRepository(const AFileName: String; out AErrMsg: String): Boolean; + function LoadRepository(const AFileName: String): Boolean; + function SaveRepository(const AFileName: String): Boolean; + procedure PopulatePackageTree; + function GetDisplayString(const AStr: String): String; procedure VSTPackagesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; {%H-}Column: TColumnIndex; {%H-}TextType: TVSTTextType; var CellText: String); procedure VSTPackagesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; @@ -105,22 +108,16 @@ var implementation -uses opkman_common, opkman_const, opkman_options, opkman_serializablepackages, - opkman_repositorydetailsfrm; +uses opkman_common, opkman_const, opkman_options, opkman_repositorydetailsfrm; {$R *.lfm} { TCreateRepositoryFrm } type - PMetaData = ^TMetaData; - TMetaData = record - FDataType: Integer; - FName: String; - end; - - PDetails = ^TDetails; - TDetails = record + PData = ^TData; + TData = record + FRepository: TRepository; FPackageRelativePath: String; FPackageBaseDir: String; FFullPath: String; @@ -128,6 +125,10 @@ type FName: String; FDisplayName: String; FPackageType: TPackageType; + FRepositoryFileName: String; + FRepositoryFileSize: Int64; + FRepositoryFileHash: String; + FRepositoryDate: TDate; FAuthor: String; FDescription: String; FLicense: String; @@ -158,15 +159,11 @@ begin EnableDisableButtons(True); ShowHideControls(0); - //continue - EnableDisableButtons(False); - pnMessage.Caption := 'Not yet implemented!'; - pnMessage.Visible := True; - + FSerializablePackages := TSerializablePackages.Create; FVSTPackages := TVirtualStringTree.Create(nil); with FVSTPackages do begin - NodeDataSize := SizeOf(TMetaData); + NodeDataSize := SizeOf(TData); Parent := pnPackages; Align := alClient; Images := imTree; @@ -202,7 +199,7 @@ begin FVSTDetails := TVirtualStringTree.Create(nil); with FVSTDetails do begin - NodeDataSize := SizeOf(TDetails); + NodeDataSize := SizeOf(TData); Parent := pnDetails; Align := alClient; Images := imTree; @@ -238,12 +235,14 @@ begin end; procedure TCreateRepositoryFrm.bCreateClick(Sender: TObject); +label + ShowFormAgain; var - ErrMsg: String; RepositoryDetailsFrm: TRepositoryDetailsFrm; begin RepositoryDetailsFrm := TRepositoryDetailsFrm.Create(Self); try + ShowFormAgain: RepositoryDetailsFrm.ShowModal; if RepositoryDetailsFrm.ModalResult = mrOk then begin @@ -252,8 +251,19 @@ begin FRepository.FDescription := RepositoryDetailsFrm.mDescription.Text; if SD.Execute then begin - if not SaveRepository(SD.FileName, ErrMsg) then - MessageDlgEx(ErrMsg, mtError, [mbOk], Self); + if SaveRepository(SD.FileName) then + begin + if RepositoryDetailsFrm.Address <> '' then + Options.RemoteRepository.Add(RepositoryDetailsFrm.Address); + if LoadRepository(SD.FileName) then + begin + PopulatePackageTree; + ShowHideControls(2); + EnableDisableButtons(True); + end; + end + else + GoTo ShowFormAgain; end; end; finally @@ -262,18 +272,23 @@ begin end; procedure TCreateRepositoryFrm.bOpenClick(Sender: TObject); -var - ErrMsg: String; begin if OD.Execute then - if not LoadRepository(OD.FileName, ErrMsg) then - MessageDlgEx(ErrMsg, mtError, [mbOk], Self); + begin + if LoadRepository(OD.FileName) then + begin + PopulatePackageTree; + ShowHideControls(2); + EnableDisableButtons(True); + end + end end; procedure TCreateRepositoryFrm.FormDestroy(Sender: TObject); begin FVSTPackages.Free; FVSTDetails.Free; + FSerializablePackages.Free end; procedure TCreateRepositoryFrm.pnButtonsResize(Sender: TObject); @@ -283,12 +298,24 @@ begin end; procedure TCreateRepositoryFrm.EnableDisableButtons(const AEnable: Boolean); +var + Node: PVirtualNode; + Data: PData; begin bOpen.Enabled := AEnable; bCreate.Enabled := AEnable; bAdd.Enabled := AEnable and FileExists(Trim(FRepository.FPath)); - bDelete.Enabled := AEnable and FileExists(Trim(FRepository.FPath)) and (FVSTPackages.RootNodeCount > 0); bCancel.Enabled := AEnable; + bDelete.Enabled := False; + if Assigned(FVSTPackages) then + begin + Node := FVSTPackages.GetFirstSelected; + if Node <> nil then + begin + Data := FVSTPackages.GetNodeData(Node); + bDelete.Enabled := AEnable and FileExists(Trim(FRepository.FPath)) and (Data^.FDataType = 1); + end + end; end; procedure TCreateRepositoryFrm.ShowHideControls(const AType: Integer); @@ -312,14 +339,14 @@ begin end; end; -function TCreateRepositoryFrm.LoadRepository(const AFileName: String; - out AErrMsg: String): Boolean; +function TCreateRepositoryFrm.LoadRepository(const AFileName: String): Boolean; var FS: TFileStream; procedure ReadString(out AString: String); var Len: Integer; begin + Len := 0; FS.Read(Len, SizeOf(Integer)); SetLength(AString, Len div SizeOf(Char)); FS.Read(Pointer(AString)^, Len); @@ -333,25 +360,22 @@ begin ReadString(FRepository.FAddress); ReadString(FRepository.FDescription); FRepository.FPath := AFileName; + Result := FileExists(AppendPathDelim(ExtractFilePath(AFileName)) + cRemoteJSONFile); + if not Result then + MessageDlgEx(Format(rsCreateRepositoryFrm_Error1, [rsCreateRepositoryFrm_Error2]), mtError, [mbOk], Self); except on E: Exception do - begin - AErrMsg := Format(rsCreateRepositoryFrm_Error1, [E.Message]); - Exit; - end; + MessageDlgEx(Format(rsCreateRepositoryFrm_Error1, [E.Message]), mtError, [mbOk], Self); end; - Result := FileExists(AppendPathDelim(ExtractFilePath(AFileName)) + cRemoteJSONFile); - if not Result then - AErrMsg := Format(rsCreateRepositoryFrm_Error1, [rsCreateRepositoryFrm_Error2]) finally FS.Free; end; end; -function TCreateRepositoryFrm.SaveRepository(const AFileName: String; - out AErrMsg: String): Boolean; +function TCreateRepositoryFrm.SaveRepository(const AFileName: String): Boolean; var FS: TFileStream; + FHandle: THandle; procedure WriteString(const AString: String); var Len: Integer; @@ -362,35 +386,151 @@ var end; begin Result := False; + if not IsDirectoryEmpty(ExtractFilePath(AFileName)) then + begin + if MessageDlgEx(Format(rsCreateRepositoryFrm_Info1, [ExtractFilePath(AFileName)]), mtConfirmation, [mbYes, mbNo], Self) = mrNo then + begin + Result := False; + Exit; + end; + end; + + if not DirectoryIsWritable(ExtractFilePath(AFileName)) then + begin + MessageDlgEx(Format(rsCreateRepositoryFrm_Info1, [ExtractFilePath(AFileName)]), mtConfirmation, [mbOk], Self); + Result := False; + Exit; + end; + FS := TFileStream.Create(AFileName, fmCreate or fmOpenWrite or fmShareDenyWrite); try try WriteString(FRepository.FName); WriteString(FRepository.FAddress); WriteString(FRepository.FDescription); - Result := True; + FHandle := FileCreate(ExtractFilePath(AFileName) + cRemoteJSONFile); + if fHandle <> THandle(-1) then + begin + Result := True; + FileClose(FHandle); + end; except on E: Exception do - begin - AErrMsg := Format(rsCreateRepositoryFrm_Error3, [E.Message]); - Exit; - end; + MessageDlgEx(Format(rsCreateRepositoryFrm_Error3, [E.Message]), mtError, [mbOk], Self); end; finally FS.Free; end; end; +procedure TCreateRepositoryFrm.PopulatePackageTree; +var + RootNode, Node, ChildNode: PVirtualNode; + RootData, Data, ChildData: PData; + JSON: TJSONStringType; + Ms: TMemoryStream; + i, j: Integer; + MetaPackage: TMetaPackage; + LazarusPackage: TLazarusPackage; +begin + + FVSTPackages.Clear; + + //add repository(DataType = 0) + RootNode := FVSTPackages.AddChild(nil); + RootData := FVSTPackages.GetNodeData(RootNode); + RootData^.FName := FRepository.FName; + RootData^.FDataType := 0; + + if FileExists(ExtractFilePath(FRepository.FPath) + cRemoteJSONFile) then + begin + Ms := TMemoryStream.Create; + try + Ms.LoadFromFile(ExtractFilePath(FRepository.FPath) + cRemoteJSONFile); + if Ms.Size > 0 then + begin + Ms.Position := 0; + SetLength(JSON, MS.Size); + MS.Read(Pointer(JSON)^, Length(JSON)); + FSerializablePackages.JSONToPackages(JSON); + for I := 0 to FSerializablePackages.Count - 1 do + begin + MetaPackage := TMetaPackage(FSerializablePackages.Items[I]); + Node := FVSTPackages.AddChild(RootNode); + Data := FVSTPackages.GetNodeData(Node); + if Trim(MetaPackage.DisplayName) <> '' then + Data^.FName := MetaPackage.DisplayName + else + Data^.FName := MetaPackage.Name; + Data^.FCategory := MetaPackage.Category; + Data^.FRepositoryFileName := MetaPackage.RepositoryFileName; + Data^.FRepositoryFileSize := MetaPackage.RepositoryFileSize; + Data^.FRepositoryFileHash := MetaPackage.RepositoryFileHash; + Data^.FRepositoryDate := MetaPackage.RepositoryDate; + Data^.FHomePageURL := MetaPackage.HomePageURL; + Data^.FDownloadURL := MetaPackage.DownloadURL; + Data^.FDataType := 1; + for J := 0 to MetaPackage.LazarusPackages.Count - 1 do + begin + LazarusPackage := TLazarusPackage(MetaPackage.LazarusPackages.Items[J]); + ChildNode := FVSTPackages.AddChild(Node); + ChildData := FVSTPackages.GetNodeData(ChildNode); + ChildData^.FName := LazarusPackage.Name; + ChildData^.FVersionAsString := LazarusPackage.VersionAsString; + ChildData^.FDescription := LazarusPackage.Description; + ChildData^.FAuthor := LazarusPackage.Author; + ChildData^.FLazCompatibility := LazarusPackage.LazCompatibility; + ChildData^.FFPCCompatibility := LazarusPackage.FPCCompatibility; + ChildData^.FSupportedWidgetSet := LazarusPackage.SupportedWidgetSet; + ChildData^.FPackageType := LazarusPackage.PackageType; + ChildData^.FLicense := LazarusPackage.License; + ChildData^.FDependenciesAsString := LazarusPackage.DependenciesAsString; + ChildData^.FDataType := 2; + end; + end; + end; + finally + Ms.Free; + end; + end; + if RootNode <> nil then + begin + FVSTPackages.Selected[RootNode] := True; + FVSTPackages.FocusedNode := RootNode; + FVSTPackages.Expanded[RootNode] := True; + end; +end; + +function TCreateRepositoryFrm.GetDisplayString(const AStr: String): String; +var + SL: TStringList; + I: Integer; +begin + Result := ''; + SL := TStringList.Create; + try + SL.Text := AStr; + for I := 0 to SL.Count - 1 do + if Result = '' then + Result := SL.Strings[I] + else + Result := Result + ' ' + SL.Strings[I]; + finally + SL.Free; + end; +end; + procedure TCreateRepositoryFrm.VSTPackagesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: String); var - Data: PMetaData; + Data: PData; begin Data := FVSTPackages.GetNodeData(Node); case Data^.FDataType of 0: CellText := FRepository.FName; 1: CellText := Data^.FName; + 2: CellText := Data^.FName; end; end; @@ -398,7 +538,7 @@ procedure TCreateRepositoryFrm.VSTPackagesGetImageIndex(Sender: TBaseVirtualTree Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); var - Data: PMetaData; + Data: PData; begin Data := FVSTPackages.GetNodeData(Node); ImageIndex := Data^.FDataType; @@ -431,8 +571,8 @@ end; procedure TCreateRepositoryFrm.VSTPackagesCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); var - Data1: PMetaData; - Data2: PMetaData; + Data1: PData; + Data2: PData; begin Data1 := Sender.GetNodeData(Node1); Data2 := Sender.GetNodeData(Node2); @@ -448,14 +588,122 @@ end; procedure TCreateRepositoryFrm.VSTPackagesFocusChanged( Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); +var + Data: PData; + DetailNode: PVirtualNode; + DetailData: PData; begin - // + if Node = nil then + Exit; + + FVSTDetails.Clear; + Data := FVSTPackages.GetNodeData(Node); + case Data^.FDataType of + 0: begin + //address + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FDataType := 0; + DetailData^.FRepository.FAddress := FRepository.FAddress; + //description + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FDataType := 1; + DetailData^.FRepository.FDescription := FRepository.FDescription; + end; + 1: begin + //add category(DataType = 12) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FCategory := Data^.FCategory; + DetailData^.FDataType := 12; + //add Repository Filename(DataType = 13) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FRepositoryFileName := Data^.FRepositoryFileName; + DetailData^.FDataType := 13; + //add Repository Filesize(DataType = 14) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FRepositoryFileSize := Data^.FRepositoryFileSize; + DetailData^.FDataType := 14; + //add Repository Hash(DataType = 15) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FRepositoryFileHash := Data^.FRepositoryFileHash; + DetailData^.FDataType := 15; + //add Repository Date(DataType = 16) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FRepositoryDate := Data^.FRepositoryDate; + DetailData^.FDataType := 16; + FVSTDetails.Expanded[DetailNode] := True; + //add HomePageURL(DataType = 17) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FHomePageURL := Data^.FHomePageURL; + DetailData^.FDataType := 17; + //add DownloadURL(DataType = 18) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FDownloadURL := Data^.FDownloadURL; + DetailData^.FDataType := 18; + end; + 2: begin + //add description(DataType = 2) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FVersionAsString := Data^.FVersionAsString; + DetailData^.FDataType := 2; + //add description(DataType = 3) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FDescription := Data^.FDescription; + DetailData^.FDataType := 3; + //add author(DataType = 4) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FAuthor := Data^.FAuthor; + DetailData^.FDataType := 4; + //add lazcompatibility(DataType = 5) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FLazCompatibility := Data^.FLazCompatibility; + DetailData^.FDataType := 5; + //add fpccompatibility(DataType = 6) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FFPCCompatibility := Data^.FFPCCompatibility; + DetailData^.FDataType := 6; + //add widgetset(DataType = 7) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FSupportedWidgetSet := Data^.FSupportedWidgetSet; + DetailData^.FDataType := 7; + //add packagetype(DataType = 8) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FPackageType := Data^.FPackageType; + DetailData^.FDataType := 8; + //add license(DataType = 9) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FLicense := Data^.FLicense; + DetailData^.FDataType := 9; + //add dependencies(DataType = 10) + DetailNode := FVSTDetails.AddChild(nil); + DetailData := FVSTDetails.GetNodeData(DetailNode); + DetailData^.FDependenciesAsString := Data^.FDependenciesAsString; + DetailData^.FDataType := 10; + end; + end; + EnableDisableButtons(True); end; procedure TCreateRepositoryFrm.VSTPackagesFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var - Data: PMetaData; + Data: PData; begin Data := FVSTPackages.GetNodeData(Node); Finalize(Data^); @@ -464,21 +712,135 @@ end; procedure TCreateRepositoryFrm.VSTDetailsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: String); +var + PackageNode: PVirtualNode; + PackageData: PData; + DetailData: PData; begin + if TextType <> ttNormal then + Exit; + PackageNode := FVSTPackages.GetFirstSelected; + if PackageNode = nil then + Exit; + PackageData := FVSTPackages.GetNodeData(PackageNode); + case PackageData^.FDataType of + 0: begin + DetailData := FVSTDetails.GetNodeData(Node); + case DetailData^.FDataType of + 0: if Column = 0 then + CellText := rsCreateRepositoryFrm_RepositoryAddress + else + CellText := DetailData^.FRepository.FAddress; + 1: if Column = 0 then + CellText := rsCreateRepositoryFrm_RepositoryDescription + else + CellText := DetailData^.FRepository.FDescription; + end; + end; + 1: begin + DetailData := FVSTDetails.GetNodeData(Node); + case DetailData^.FDataType of + 12: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Category + else + CellText := DetailData^.FCategory; + 13: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_RepositoryFilename + else + CellText := DetailData^.FRepositoryFileName; + 14: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_RepositoryFileSize + else + CellText := FormatSize(DetailData^.FRepositoryFileSize); + 15: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_RepositoryFileHash + else + CellText := DetailData^.FRepositoryFileHash; + 16: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_RepositoryFileDate + else + CellText := FormatDateTime('YYYY.MM.DD', DetailData^.FRepositoryDate); + 17: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_HomePageURL + else + CellText := DetailData^.FHomePageURL; + 18: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_DownloadURL + else + CellText := DetailData^.FDownloadURL; + end; + end; + 2: begin + DetailData := FVSTDetails.GetNodeData(Node); + case DetailData^.FDataType of + 2: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Version + else + CellText := DetailData^.FVersionAsString; + 3: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Description + else + CellText := GetDisplayString(DetailData^.FDescription); + 4: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Author + else + CellText := DetailData^.FAuthor; + 5: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_LazCompatibility + else + CellText := DetailData^.FLazCompatibility; + 6: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_FPCCompatibility + else + CellText := DetailData^.FFPCCompatibility; + 7: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_SupportedWidgetsets + else + CellText := DetailData^.FSupportedWidgetSet; + 8: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Packagetype + else + case DetailData^.FPackageType of + ptRunAndDesignTime: CellText := rsMainFrm_VSTText_PackageType0; + ptDesignTime: CellText := rsMainFrm_VSTText_PackageType1; + ptRunTime: CellText := rsMainFrm_VSTText_PackageType2; + ptRunTimeOnly: CellText := rsMainFrm_VSTText_PackageType3; + end; + 9: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_License + else + CellText := GetDisplayString(DetailData^.FLicense); + 10: if Column = 0 then + CellText := rsCreateRepositoryFrm_VSTText_Dependecies + else + CellText := DetailData^.FDependenciesAsString; + + end; + end; + end; end; procedure TCreateRepositoryFrm.VSTDetailsGetImageIndex( Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); +var + Data: PData; begin - + if Column = 0 then + begin + Data := FVSTDetails.GetNodeData(Node); + ImageIndex := Data^.FDataType; + end; end; procedure TCreateRepositoryFrm.VSTDetailsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); +var + Data: PData; begin - + Data := FVSTPackages.GetNodeData(Node); + Finalize(Data^); end; end. diff --git a/components/onlinepackagemanager/opkman_repositories.lfm b/components/onlinepackagemanager/opkman_repositories.lfm index 477b92939c..4ba551e8cf 100644 --- a/components/onlinepackagemanager/opkman_repositories.lfm +++ b/components/onlinepackagemanager/opkman_repositories.lfm @@ -11,6 +11,7 @@ object RepositoriesFrm: TRepositoriesFrm OnDestroy = FormDestroy PopupMode = pmExplicit Position = poOwnerFormCenter + LCLVersion = '1.9.0.0' object pnBottom: TPanel Left = 460 Height = 321 diff --git a/components/onlinepackagemanager/opkman_repositories.pas b/components/onlinepackagemanager/opkman_repositories.pas index 5f0a8223b8..d213f4eeaf 100644 --- a/components/onlinepackagemanager/opkman_repositories.pas +++ b/components/onlinepackagemanager/opkman_repositories.pas @@ -68,6 +68,7 @@ type procedure VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure PopulateTree; procedure EnableDisableButtons; + function IsDuplicateRepository(const AAddress: String; const AUniqueID: Integer): Boolean; public end; @@ -84,6 +85,7 @@ type FAddress: string; FType: Integer; FImageIndex: Integer; + FUniqueID: Integer; end; { TRepositoriesFrm } @@ -157,17 +159,22 @@ begin Value := InputBox(rsRepositories_InputBox_Caption0, rsRepositories_InputBox_Text, ''); if Value <> '' then begin - Node := FVST.AddChild(nil); - Data := FVST.GetNodeData(Node); - Data^.FAddress := Trim(Value); - Data^.FAddress := FixProtocol(Data^.FAddress); - if Data^.FAddress[Length(Data^.FAddress)] <> '/' then - Data^.FAddress := Data^.FAddress + '/'; - Data^.FType := 1; - Data^.FImageIndex := 0; - FVST.Selected[Node] := True; - FVST.FocusedNode := Node; - FVST.SortTree(0, FSortDir); + if Trim(Value[Length(Value)]) <> '/' then + Value := Trim(Value) + '/'; + if not IsDuplicateRepository(Value, -1) then + begin + Node := FVST.AddChild(nil); + Data := FVST.GetNodeData(Node); + Data^.FAddress := Trim(Value); + Data^.FAddress := FixProtocol(Data^.FAddress); + Data^.FType := 1; + Data^.FImageIndex := 0; + FVST.Selected[Node] := True; + FVST.FocusedNode := Node; + FVST.SortTree(0, FSortDir); + end + else + MessageDlgEx(Format(rsRepositories_Info1, [value]), mtInformation, [mbOk], Self); end; end; 1: begin @@ -178,12 +185,19 @@ begin Value := InputBox(rsRepositories_InputBox_Caption1, rsRepositories_InputBox_Text, Data^.FAddress); if Value <> '' then begin - Data^.FAddress := Trim(Value); - Data^.FAddress := FixProtocol(Data^.FAddress); - if Data^.FAddress[Length(Data^.FAddress)] <> '/' then - Data^.FAddress := Data^.FAddress + '/'; - FVST.ReinitNode(Node, False); - FVST.RepaintNode(Node); + if Trim(Value[Length(Value)]) <> '/' then + Value := Trim(Value) + '/'; + if not IsDuplicateRepository(Value, Data^.FUniqueID) then + begin + Data^.FAddress := Trim(Value); + Data^.FAddress := FixProtocol(Data^.FAddress); + if Data^.FAddress[Length(Data^.FAddress)] <> '/' then + Data^.FAddress := Data^.FAddress + '/'; + FVST.ReinitNode(Node, False); + FVST.RepaintNode(Node); + end + else + MessageDlgEx(Format(rsRepositories_Info1, [value]), mtInformation, [mbOk], Self); end; FVST.SortTree(0, FSortDir); end; @@ -343,18 +357,41 @@ begin bDelete.Enabled := SelData^.FType > 0; end; +function TRepositoriesFrm.IsDuplicateRepository(const AAddress: String; + const AUniqueID: Integer): Boolean; +var + Node: PVirtualNode; + Data: PData; +begin + Result := False; + Node := FVST.GetFirst; + while Assigned(Node) do + begin + Data := FVST.GetNodeData(Node); + if (UpperCase(Data^.FAddress) = UpperCase(AAddress)) and (Data^.FUniqueID <> AUniqueID) then + begin + Result := True; + Break; + end; + Node := FVST.GetNext(Node); + end; +end; + procedure TRepositoriesFrm.PopulateTree; var I: Integer; Node: PVirtualNode; Data: PData; + UniqueID: Integer; begin if Trim(Options.RemoteRepositoryTmp.Text) = '' then Options.RemoteRepositoryTmp.Text := Options.RemoteRepository.Text; + UniqueID := 0; for I := 0 to Options.RemoteRepositoryTmp.Count - 1 do begin if Trim(Options.RemoteRepositoryTmp.Strings[I]) <> '' then begin + Inc(UniqueID); Node := FVST.AddChild(nil); Data := FVST.GetNodeData(Node); Data^.FAddress := Options.RemoteRepositoryTmp.Strings[I]; @@ -363,6 +400,7 @@ begin else Data^.FType := 1; Data^.FImageIndex := 0; + Data^.FUniqueID := UniqueID; end; end; FVST.SortTree(0, opkman_VirtualTrees.sdAscending); diff --git a/components/onlinepackagemanager/opkman_repositorydetailsfrm.lfm b/components/onlinepackagemanager/opkman_repositorydetailsfrm.lfm index 9ccefac458..e96645a358 100644 --- a/components/onlinepackagemanager/opkman_repositorydetailsfrm.lfm +++ b/components/onlinepackagemanager/opkman_repositorydetailsfrm.lfm @@ -2,11 +2,11 @@ object RepositoryDetailsFrm: TRepositoryDetailsFrm Left = 389 Height = 315 Top = 243 - Width = 387 + Width = 398 Anchors = [akTop, akLeft, akBottom] Caption = 'Repository details' ClientHeight = 315 - ClientWidth = 387 + ClientWidth = 398 Constraints.MinHeight = 315 Constraints.MinWidth = 300 OnCreate = FormCreate @@ -17,29 +17,34 @@ object RepositoryDetailsFrm: TRepositoryDetailsFrm Left = 0 Height = 35 Top = 280 - Width = 387 + Width = 398 Align = alBottom BevelOuter = bvNone ClientHeight = 35 - ClientWidth = 387 + ClientWidth = 398 TabOrder = 3 object bOk: TButton - Left = 217 + Left = 228 Height = 25 Top = 4 Width = 75 Anchors = [akTop, akRight] Caption = 'Ok' + OnClick = bOkClick + ParentShowHint = False + ShowHint = True TabOrder = 0 end object bCancel: TButton - Left = 294 + Left = 305 Height = 25 Top = 4 Width = 75 Anchors = [akTop, akRight] Caption = 'Cancel' ModalResult = 2 + ParentShowHint = False + ShowHint = True TabOrder = 1 end end @@ -55,9 +60,11 @@ object RepositoryDetailsFrm: TRepositoryDetailsFrm Left = 19 Height = 23 Top = 31 - Width = 350 + Width = 357 Anchors = [akTop, akLeft, akRight] - TabOrder = 1 + ParentShowHint = False + ShowHint = True + TabOrder = 0 end object lbAddress: TLabel Left = 19 @@ -71,33 +78,41 @@ object RepositoryDetailsFrm: TRepositoryDetailsFrm Left = 18 Height = 23 Top = 87 - Width = 351 + Width = 358 Anchors = [akTop, akLeft, akRight] - TabOrder = 0 + OnChange = edAddressChange + ParentShowHint = False + ShowHint = True + TabOrder = 1 end object lbDescription: TLabel Left = 19 Height = 15 - Top = 126 + Top = 130 Width = 118 Caption = 'Repository description' ParentColor = False end object mDescription: TMemo Left = 19 - Height = 81 - Top = 141 - Width = 350 + Height = 108 + Top = 148 + Width = 357 Anchors = [akTop, akLeft, akRight, akBottom] + ParentShowHint = False + ShowHint = True TabOrder = 2 end - object cbAddToRepositories: TCheckBox - Left = 19 - Height = 19 - Top = 232 - Width = 175 - Anchors = [akTop] - Caption = 'Add to available repositoy list' - TabOrder = 4 + object lbOF2: TLabel + Left = 380 + Height = 15 + Top = 36 + Width = 5 + Anchors = [akTop, akRight] + Caption = '*' + Font.Color = clRed + Font.Style = [fsBold] + ParentColor = False + ParentFont = False end end diff --git a/components/onlinepackagemanager/opkman_repositorydetailsfrm.pas b/components/onlinepackagemanager/opkman_repositorydetailsfrm.pas index a4591883cb..2b9fb0ed77 100644 --- a/components/onlinepackagemanager/opkman_repositorydetailsfrm.pas +++ b/components/onlinepackagemanager/opkman_repositorydetailsfrm.pas @@ -15,33 +15,92 @@ type TRepositoryDetailsFrm = class(TForm) bOk: TButton; bCancel: TButton; - cbAddToRepositories: TCheckBox; edName: TEdit; edAddress: TEdit; lbName: TLabel; lbAddress: TLabel; lbDescription: TLabel; + lbOF2: TLabel; mDescription: TMemo; pnButtons: TPanel; + procedure bOkClick(Sender: TObject); + procedure edAddressChange(Sender: TObject); procedure FormCreate(Sender: TObject); private - + FAddress: String; + function IsDuplicateRepository(const AAddress: String): Boolean; public - + property Address: String read FAddress; end; var RepositoryDetailsFrm: TRepositoryDetailsFrm; implementation - +uses opkman_const, opkman_common, opkman_options; {$R *.lfm} { TRepositoryDetailsFrm } procedure TRepositoryDetailsFrm.FormCreate(Sender: TObject); begin + Caption := rsRepositoryDetails_Caption; + lbName.Caption := rsRepositoryDetails_lbName_Caption; + edName.Hint := rsRepositoryDetails_edName_Hint; + lbAddress.Caption := rsRepositoryDetails_lbAddress_Caption; + edAddress.Hint := rsRepositoryDetails_edAddress_Hint; + lbDescription.Caption := rsRepositoryDetails_lbDescription_Caption; + mDescription.Hint := rsRepositoryDetails_mDescription_Hint; + bOk.Caption := rsRepositoryDetails_bOk_Caption; + bOk.Hint := rsRepositoryDetails_bOk_Hint; + bCancel.Caption := rsRepositoryDetails_bCancel_Caption; + bCancel.Hint := rsRepositoryDetails_bCancel_Hint; + FAddress := ''; +end; +function TRepositoryDetailsFrm.IsDuplicateRepository(const AAddress: String): Boolean; +var + I: Integer; +begin + Result := False; + for I := 0 to Options.RemoteRepository.Count - 1 do + begin + if UpperCase(Options.RemoteRepository.Strings[I]) = UpperCase(AAddress) then + begin + Result := True; + Break; + end; + end; +end; + +procedure TRepositoryDetailsFrm.bOkClick(Sender: TObject); +begin + if Trim(edName.Text) = '' then + begin + MessageDlgEx(rsRepositoryDetails_Info1, mtInformation, [mbOk], Self); + edName.SetFocus; + Exit; + end; + if (Trim(edAddress.Text) <> '') and (edAddress.Font.Color <> clGray) then + begin + FAddress := Trim(edAddress.Text); + if FAddress[Length(FAddress)] <> '/' then + FAddress := FAddress + '/'; + if IsDuplicateRepository(FAddress) then + begin + if MessageDlgEx(Format(rsRepositoryDetails_Info3, [FAddress]), mtInformation, [mbYes, mbNo], Self) = mrNo then + begin + edAddress.SetFocus; + Exit; + end; + end; + end; + ModalResult := mrOk; +end; + +procedure TRepositoryDetailsFrm.edAddressChange(Sender: TObject); +begin + edAddress.Font.Color := clDefault; end; end.