├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── App.xojo_code ├── Build Automation.xojo_code ├── CODE_OF_CONDUCT.md ├── Classes ├── AddOn.xojo_code ├── Aircraft │ ├── Aircraft.xojo_code │ └── AircraftFolder.xojo_code ├── AptDatParseThread.xojo_code ├── CSL │ └── CSL.xojo_code ├── ExtendedCheckBox.xojo_code ├── Group.xojo_code ├── Plugins │ ├── Plugin.xojo_code │ └── PythonInterfacePlugin.xojo_code ├── Preferences.xojo_code ├── Scenery │ ├── Airport.xojo_code │ ├── AirportDataSceneryObject.xojo_code │ ├── CustomSceneryPackage.xojo_code │ ├── DSF.xojo_code │ ├── ENV.xojo_code │ ├── LatLongPoint.xojo_code │ ├── LibrarySceneryObject.xojo_code │ ├── LocationalSceneryObject.xojo_code │ └── SceneryObject.xojo_code ├── UnzipThread.xojo_code └── XPlaneFolderItem.xojo_code ├── Databases ├── dbMain.rsd └── dbMain.xojo_code ├── FileTypes1.xojo_filetypeset ├── Images ├── add.png ├── aircraft.png ├── aircraft_alpha.png ├── airports.png ├── circle_alpha.png ├── delete.png ├── disk.png ├── folder.png ├── folder_alpha.png ├── globe.png ├── globe_alpha.png ├── icon.png ├── information.png ├── org_logo.png ├── plugin.png ├── plugin_alpha.png ├── warning.png ├── warning_alpha.png ├── worldmap.png └── worldmap2.png ├── Interfaces ├── AddonInterface.xojo_code └── FolderTraversalCallbackInterface.xojo_code ├── LICENSE ├── MenuBar1.xojo_menu ├── Modules ├── Utilities.xojo_code └── XMLDictionary.xojo_code ├── README.md ├── VersionInfo ├── devreleasenotes.html ├── devversion.txt ├── releasenotes.css ├── releasenotes.html └── version.txt ├── Windows ├── wndAbout.xojo_window ├── wndCreateFolder.xojo_window ├── wndCreateGroup.xojo_window ├── wndDebug.xojo_window ├── wndInstallSceneryPackage.xojo_window ├── wndLogin.xojo_window ├── wndMain.xojo_window ├── wndNewVersion.xojo_window └── wndPreferences.xojo_window ├── XAddonManager.xojo_project ├── XAddonManager.xojo_resources ├── ZipPackage ├── 3rdParty │ └── clsCRC16.xojo_code ├── RemoveWhenUsingEinhugurPlugin │ ├── IStreamReader.xojo_code │ └── IStreamWriter.xojo_code ├── StreamSupport │ ├── FileReader.xojo_code │ ├── FileWriter.xojo_code │ ├── RsrcForkReader.xojo_code │ ├── RsrcForkWriter.xojo_code │ ├── SeqDataInputStream.xojo_code │ ├── SeqDataOutputStream.xojo_code │ ├── StringReader.xojo_code │ ├── StringWriter.xojo_code │ └── SymlinkReader.xojo_code ├── ZLibClasses │ ├── ZLibDeflator.xojo_code │ ├── ZLibInflator.xojo_code │ ├── ZLibStream.xojo_code │ └── ZLibStreamException.xojo_code ├── ZipArchive.xojo_code ├── ZipConfig.xojo_code ├── ZipEntry.xojo_code ├── ZipExtractor.xojo_code ├── ZipFolderItem.xojo_code ├── ZipSnapshots.xojo_code └── ZipSupport │ ├── Private │ ├── ZipArchiveBase.xojo_binary_code │ ├── ZipArchiveData.xojo_binary_code │ ├── ZipEntryBase.xojo_binary_code │ └── ZipFolderItemBase.xojo_binary_code │ ├── TTsFolderItem.xojo_code │ ├── ZipBinaryStreamReader.xojo_code │ ├── ZipBinaryStreamWriter.xojo_code │ ├── ZipExtraField.xojo_code │ ├── ZipProgressNotifier.xojo_code │ └── ZipSeqOutputStream.xojo_code ├── doc ├── future_ideas.txt └── release_howto.txt ├── icon.png └── scripts ├── packageall.sh ├── packagelinux.sh ├── packagemac.sh └── packagewin.sh /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: aussig 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Environment (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Version [e.g. 22] 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature request 6 | assignees: aussig 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .XAddonManager.xojo_uistate 2 | Builds - XAddonManager.xojo_project 3 | XAddonManager-*.zip 4 | -------------------------------------------------------------------------------- /Build Automation.xojo_code: -------------------------------------------------------------------------------- 1 | #tag BuildAutomation 2 | Begin BuildStepList Linux 3 | Begin BuildProjectStep Build 4 | End 5 | End 6 | Begin BuildStepList Mac OS X 7 | Begin BuildProjectStep Build 8 | End 9 | End 10 | Begin BuildStepList Windows 11 | Begin BuildProjectStep Build 12 | End 13 | End 14 | #tag EndBuildAutomation 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at austin@opensceneryx.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /Classes/Aircraft/AircraftFolder.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class AircraftFolder 3 | Inherits AddOn 4 | #tag Method, Flags = &h0 5 | Sub displayDetails(iconCanvas as Canvas) 6 | iconCanvas.backdrop = new Picture(1, 1, 1) 7 | 8 | End Sub 9 | #tag EndMethod 10 | 11 | #tag Method, Flags = &h0 12 | Sub expandListBoxEntry(listBox as ListBox, clickedRow as Integer) 13 | // Part of the AddonInterface interface. 14 | super.expandListBoxEntry(listBox, clickedRow) 15 | 16 | dim i as integer 17 | 18 | for i = 1 to me.pFolderItem.count 19 | dim folderItem as FolderItem = me.pFolderItem.Item(i) 20 | 21 | if Aircraft.isValid(folderItem) then 22 | // It's a valid Aircraft 23 | dim aircraft as new Aircraft(folderItem.Name, folderItem, true, App.pXPlaneFolder) 24 | aircraft.populateListBoxEntry(listBox) 25 | elseif AircraftFolder.isValid(folderItem) then 26 | // It's a valid AircraftFolder 27 | dim aircraftFolder as new AircraftFolder(folderItem.Name, folderItem, true, App.pXPlaneFolder) 28 | aircraftFolder.populateListBoxEntry(listBox) 29 | else 30 | // Don't display anything else 31 | End if 32 | Next 33 | 34 | End Sub 35 | #tag EndMethod 36 | 37 | #tag Method, Flags = &h0 38 | Shared Function isValid(folderItem as FolderItem) As boolean 39 | if AddOn.isValid(folderItem) = false then return false 40 | 41 | // It's a valid aircraft container folder if it's a directory and not a special aircraft subfolder 42 | // We have to omit special folders in case we are inside an aircraft folder that has multiple .acf files 43 | 44 | return folderItem.Directory _ 45 | and folderItem.name <> "airfoils" _ 46 | and folderItem.name <> "cockpit" _ 47 | and folderItem.name <> "objects" _ 48 | and folderItem.name <> "plugins" _ 49 | and folderItem.name <> "sounds" _ 50 | and folderItem.name <> "weapons" 51 | 52 | End Function 53 | #tag EndMethod 54 | 55 | #tag Method, Flags = &h0 56 | Sub populateListBoxEntry(listBox as ListBox) 57 | // Part of the AddonInterface interface. 58 | super.populateListBoxEntry(listBox, true) 59 | 60 | listBox.RowPicture(listBox.LastIndex) = imgFolder 61 | End Sub 62 | #tag EndMethod 63 | 64 | 65 | #tag ViewBehavior 66 | #tag ViewProperty 67 | Name="Index" 68 | Visible=true 69 | Group="ID" 70 | InitialValue="-2147483648" 71 | Type="Integer" 72 | #tag EndViewProperty 73 | #tag ViewProperty 74 | Name="Left" 75 | Visible=true 76 | Group="Position" 77 | InitialValue="0" 78 | Type="Integer" 79 | #tag EndViewProperty 80 | #tag ViewProperty 81 | Name="Name" 82 | Visible=true 83 | Group="ID" 84 | Type="String" 85 | #tag EndViewProperty 86 | #tag ViewProperty 87 | Name="pEnabled" 88 | Group="Behavior" 89 | InitialValue="true" 90 | Type="Boolean" 91 | #tag EndViewProperty 92 | #tag ViewProperty 93 | Name="pName" 94 | Group="Behavior" 95 | Type="String" 96 | EditorType="MultiLineEditor" 97 | #tag EndViewProperty 98 | #tag ViewProperty 99 | Name="Super" 100 | Visible=true 101 | Group="ID" 102 | Type="String" 103 | #tag EndViewProperty 104 | #tag ViewProperty 105 | Name="Top" 106 | Visible=true 107 | Group="Position" 108 | InitialValue="0" 109 | Type="Integer" 110 | #tag EndViewProperty 111 | #tag EndViewBehavior 112 | End Class 113 | #tag EndClass 114 | -------------------------------------------------------------------------------- /Classes/AptDatParseThread.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class AptDatParseThread 3 | Inherits Thread 4 | #tag Event 5 | Sub Run() 6 | pXPlaneFolderItem.pAirportData = new AirportDataSceneryObject(pAptDatFolderItem) 7 | 8 | End Sub 9 | #tag EndEvent 10 | 11 | 12 | #tag Method, Flags = &h1000 13 | Sub Constructor(xPlaneFolderItem as XPlaneFolderItem, aptDatFolderItem as FolderItem) 14 | pXPlaneFolderItem = xPlaneFolderItem 15 | pAptDatFolderItem = aptDatFolderItem 16 | End Sub 17 | #tag EndMethod 18 | 19 | 20 | #tag Property, Flags = &h21 21 | Private pAptDatFolderItem As FolderItem 22 | #tag EndProperty 23 | 24 | #tag Property, Flags = &h21 25 | Private pXPlaneFolderItem As XPlaneFolderItem 26 | #tag EndProperty 27 | 28 | 29 | #tag ViewBehavior 30 | #tag ViewProperty 31 | Name="Index" 32 | Visible=true 33 | Group="ID" 34 | Type="Integer" 35 | EditorType="Integer" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Name" 39 | Visible=true 40 | Group="ID" 41 | Type="String" 42 | EditorType="String" 43 | #tag EndViewProperty 44 | #tag ViewProperty 45 | Name="Priority" 46 | Visible=true 47 | Group="Behavior" 48 | InitialValue="5" 49 | Type="Integer" 50 | #tag EndViewProperty 51 | #tag ViewProperty 52 | Name="StackSize" 53 | Visible=true 54 | Group="Behavior" 55 | InitialValue="0" 56 | Type="Integer" 57 | #tag EndViewProperty 58 | #tag ViewProperty 59 | Name="Super" 60 | Visible=true 61 | Group="ID" 62 | Type="String" 63 | EditorType="String" 64 | #tag EndViewProperty 65 | #tag EndViewBehavior 66 | End Class 67 | #tag EndClass 68 | -------------------------------------------------------------------------------- /Classes/CSL/CSL.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class CSL 3 | Inherits AddOn 4 | #tag Method, Flags = &h0 5 | Shared Function checkXPlaneFolder(folderItem as FolderItem) As Boolean 6 | return folderItem <> nil _ 7 | and folderItem.child("Resources").exists _ 8 | and folderItem.child("Resources").child("plugins").exists _ 9 | and folderItem.child("Resources").child("plugins").child("X-Ivap Resources").exists _ 10 | and folderItem.child("Resources").child("plugins").child("X-Ivap Resources").child("CSL").exists 11 | 12 | End Function 13 | #tag EndMethod 14 | 15 | #tag Method, Flags = &h0 16 | Sub enable(enable as boolean) 17 | if enable <> pEnabled then 18 | super.enable(enable) 19 | 20 | dim destinationParent as FolderItem = CSL.getRootFolder(enable) 21 | dim swapDestinationParent as FolderItem = CSL.getRootFolder(not enable) 22 | 23 | moveItem(enable, destinationParent, swapDestinationParent) 24 | end if 25 | End Sub 26 | #tag EndMethod 27 | 28 | #tag Method, Flags = &h0 29 | Shared Function getRootFolder(enabledVersion as boolean = true) As FolderItem 30 | if (enabledVersion) then 31 | return App.pXPlaneFolder.child("Resources").child("plugins").child("X-Ivap Resources").child("CSL") 32 | else 33 | return App.pXPlaneFolder.child("Resources").child("plugins").child("X-Ivap Resources").child("CSL (disabled)") 34 | end if 35 | End Function 36 | #tag EndMethod 37 | 38 | #tag Method, Flags = &h0 39 | Shared Sub initialiseXPlaneFolder() 40 | // Only create the disabled folder if there is already a CSL folder 41 | if CSL.checkXPlaneFolder(App.pXPlaneFolder) then 42 | dim disabledFolder as FolderItem 43 | 44 | disabledFolder = CSL.getRootFolder(false) 45 | if (not disabledFolder.exists) then 46 | disabledFolder.createAsFolder() 47 | end if 48 | end if 49 | End Sub 50 | #tag EndMethod 51 | 52 | #tag Method, Flags = &h0 53 | Shared Sub install(folderItem as FolderItem) 54 | // Check whether an item with the same name exists first 55 | if CSL.getRootFolder().child(folderItem.name).exists or CSL.getRootFolder(false).child(folderItem.name).exists then 56 | dim parameters() as string = array(folderItem.name) 57 | dim result as Integer = App.displayMessage(App.processParameterizedString(wndMain.kErrorItemWithSameNameExists, parameters), "", MessageDialog.GraphicCaution, App.kOk, "", "", wndMain) 58 | return 59 | end if 60 | 61 | // Move the folder 62 | folderItem.moveFileTo(CSL.getRootFolder()) 63 | 64 | End Sub 65 | #tag EndMethod 66 | 67 | #tag Method, Flags = &h0 68 | Shared Function isValid(folderItem as FolderItem) As boolean 69 | if Addon.isValid(folderItem) = false then return false 70 | 71 | // It's a valid CSL if it's a directory and contains a 'xsb_aircraft.txt' file 72 | if not folderItem.Directory then return false 73 | 74 | dim i as integer 75 | for i = 1 to folderItem.count 76 | if folderItem.trueItem(i).name = "xsb_aircraft.txt" then return true 77 | next 78 | 79 | return false 80 | 81 | End Function 82 | #tag EndMethod 83 | 84 | 85 | #tag Property, Flags = &h0 86 | Shared pAddonClassEnabled As Boolean = true 87 | #tag EndProperty 88 | 89 | 90 | #tag ViewBehavior 91 | #tag ViewProperty 92 | Name="Index" 93 | Visible=true 94 | Group="ID" 95 | InitialValue="-2147483648" 96 | Type="Integer" 97 | #tag EndViewProperty 98 | #tag ViewProperty 99 | Name="Left" 100 | Visible=true 101 | Group="Position" 102 | InitialValue="0" 103 | Type="Integer" 104 | #tag EndViewProperty 105 | #tag ViewProperty 106 | Name="Name" 107 | Visible=true 108 | Group="ID" 109 | Type="String" 110 | #tag EndViewProperty 111 | #tag ViewProperty 112 | Name="pEnabled" 113 | Group="Behavior" 114 | InitialValue="true" 115 | Type="Boolean" 116 | #tag EndViewProperty 117 | #tag ViewProperty 118 | Name="pName" 119 | Group="Behavior" 120 | Type="String" 121 | EditorType="MultiLineEditor" 122 | #tag EndViewProperty 123 | #tag ViewProperty 124 | Name="Super" 125 | Visible=true 126 | Group="ID" 127 | Type="String" 128 | #tag EndViewProperty 129 | #tag ViewProperty 130 | Name="Top" 131 | Visible=true 132 | Group="Position" 133 | InitialValue="0" 134 | Type="Integer" 135 | #tag EndViewProperty 136 | #tag EndViewBehavior 137 | End Class 138 | #tag EndClass 139 | -------------------------------------------------------------------------------- /Classes/ExtendedCheckBox.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class ExtendedCheckBox 3 | Inherits CheckBox 4 | #tag Method, Flags = &h0 5 | Sub setValue(value as boolean, triggerAction as boolean) 6 | pTriggerAction = triggerAction 7 | me.value = value 8 | pTriggerAction = true 9 | End Sub 10 | #tag EndMethod 11 | 12 | 13 | #tag Property, Flags = &h0 14 | pTriggerAction As boolean = true 15 | #tag EndProperty 16 | 17 | 18 | #tag ViewBehavior 19 | #tag ViewProperty 20 | Name="Transparent" 21 | Visible=true 22 | Group="Appearance" 23 | InitialValue="False" 24 | Type="Boolean" 25 | EditorType="Boolean" 26 | #tag EndViewProperty 27 | #tag ViewProperty 28 | Name="AutoDeactivate" 29 | Visible=true 30 | Group="Appearance" 31 | InitialValue="True" 32 | Type="Boolean" 33 | #tag EndViewProperty 34 | #tag ViewProperty 35 | Name="Bold" 36 | Visible=true 37 | Group="Font" 38 | Type="Boolean" 39 | #tag EndViewProperty 40 | #tag ViewProperty 41 | Name="Caption" 42 | Visible=true 43 | Group="Appearance" 44 | InitialValue="Untitled" 45 | Type="String" 46 | #tag EndViewProperty 47 | #tag ViewProperty 48 | Name="DataField" 49 | Visible=true 50 | Group="Database Binding" 51 | Type="String" 52 | EditorType="DataField" 53 | #tag EndViewProperty 54 | #tag ViewProperty 55 | Name="DataSource" 56 | Visible=true 57 | Group="Database Binding" 58 | Type="String" 59 | EditorType="DataSource" 60 | #tag EndViewProperty 61 | #tag ViewProperty 62 | Name="Enabled" 63 | Visible=true 64 | Group="Appearance" 65 | InitialValue="True" 66 | Type="Boolean" 67 | #tag EndViewProperty 68 | #tag ViewProperty 69 | Name="Height" 70 | Visible=true 71 | Group="Position" 72 | InitialValue="20" 73 | Type="Integer" 74 | #tag EndViewProperty 75 | #tag ViewProperty 76 | Name="HelpTag" 77 | Visible=true 78 | Group="Appearance" 79 | Type="String" 80 | EditorType="MultiLineEditor" 81 | #tag EndViewProperty 82 | #tag ViewProperty 83 | Name="Index" 84 | Visible=true 85 | Group="ID" 86 | Type="Integer" 87 | EditorType="Integer" 88 | #tag EndViewProperty 89 | #tag ViewProperty 90 | Name="InitialParent" 91 | Type="String" 92 | #tag EndViewProperty 93 | #tag ViewProperty 94 | Name="Italic" 95 | Visible=true 96 | Group="Font" 97 | Type="Boolean" 98 | #tag EndViewProperty 99 | #tag ViewProperty 100 | Name="Left" 101 | Visible=true 102 | Group="Position" 103 | Type="Integer" 104 | #tag EndViewProperty 105 | #tag ViewProperty 106 | Name="LockBottom" 107 | Visible=true 108 | Group="Position" 109 | Type="Boolean" 110 | #tag EndViewProperty 111 | #tag ViewProperty 112 | Name="LockLeft" 113 | Visible=true 114 | Group="Position" 115 | Type="Boolean" 116 | #tag EndViewProperty 117 | #tag ViewProperty 118 | Name="LockRight" 119 | Visible=true 120 | Group="Position" 121 | Type="Boolean" 122 | #tag EndViewProperty 123 | #tag ViewProperty 124 | Name="LockTop" 125 | Visible=true 126 | Group="Position" 127 | Type="Boolean" 128 | #tag EndViewProperty 129 | #tag ViewProperty 130 | Name="Name" 131 | Visible=true 132 | Group="ID" 133 | Type="String" 134 | EditorType="String" 135 | #tag EndViewProperty 136 | #tag ViewProperty 137 | Name="pTriggerAction" 138 | Group="Behavior" 139 | InitialValue="true" 140 | Type="boolean" 141 | #tag EndViewProperty 142 | #tag ViewProperty 143 | Name="State" 144 | Visible=true 145 | Group="Initial State" 146 | InitialValue="0" 147 | Type="CheckedStates" 148 | EditorType="Enum" 149 | #tag EnumValues 150 | "0 - Unchecked" 151 | "1 - Checked" 152 | "2 - Indeterminate" 153 | #tag EndEnumValues 154 | #tag EndViewProperty 155 | #tag ViewProperty 156 | Name="Super" 157 | Visible=true 158 | Group="ID" 159 | Type="String" 160 | EditorType="String" 161 | #tag EndViewProperty 162 | #tag ViewProperty 163 | Name="TabIndex" 164 | Visible=true 165 | Group="Position" 166 | InitialValue="0" 167 | Type="Integer" 168 | #tag EndViewProperty 169 | #tag ViewProperty 170 | Name="TabPanelIndex" 171 | Group="Position" 172 | InitialValue="0" 173 | Type="Integer" 174 | #tag EndViewProperty 175 | #tag ViewProperty 176 | Name="TabStop" 177 | Visible=true 178 | Group="Position" 179 | InitialValue="True" 180 | Type="Boolean" 181 | #tag EndViewProperty 182 | #tag ViewProperty 183 | Name="TextFont" 184 | Visible=true 185 | Group="Font" 186 | InitialValue="System" 187 | Type="String" 188 | #tag EndViewProperty 189 | #tag ViewProperty 190 | Name="TextSize" 191 | Visible=true 192 | Group="Font" 193 | InitialValue="0" 194 | Type="Single" 195 | #tag EndViewProperty 196 | #tag ViewProperty 197 | Name="TextUnit" 198 | Visible=true 199 | Group="Font" 200 | InitialValue="0" 201 | Type="FontUnits" 202 | EditorType="Enum" 203 | #tag EnumValues 204 | "0 - Default" 205 | "1 - Pixel" 206 | "2 - Point" 207 | "3 - Inch" 208 | "4 - Millimeter" 209 | #tag EndEnumValues 210 | #tag EndViewProperty 211 | #tag ViewProperty 212 | Name="Top" 213 | Visible=true 214 | Group="Position" 215 | Type="Integer" 216 | #tag EndViewProperty 217 | #tag ViewProperty 218 | Name="Underline" 219 | Visible=true 220 | Group="Font" 221 | Type="Boolean" 222 | #tag EndViewProperty 223 | #tag ViewProperty 224 | Name="Value" 225 | Visible=true 226 | Group="Initial State" 227 | Type="Boolean" 228 | #tag EndViewProperty 229 | #tag ViewProperty 230 | Name="Visible" 231 | Visible=true 232 | Group="Appearance" 233 | InitialValue="True" 234 | Type="Boolean" 235 | #tag EndViewProperty 236 | #tag ViewProperty 237 | Name="Width" 238 | Visible=true 239 | Group="Position" 240 | InitialValue="100" 241 | Type="Integer" 242 | #tag EndViewProperty 243 | #tag EndViewBehavior 244 | End Class 245 | #tag EndClass 246 | -------------------------------------------------------------------------------- /Classes/Group.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Group 3 | #tag Method, Flags = &h0 4 | Sub Constructor(name as String, xPlaneFolder as XPlaneFolderItem) 5 | pName = name 6 | pXPlaneFolder = xPlaneFolder 7 | 8 | me.loadState() 9 | End Sub 10 | #tag EndMethod 11 | 12 | #tag Method, Flags = &h0 13 | Shared Sub deleteGroup(groupName as String, xPlaneFolder as XPlaneFolderItem) 14 | xPlaneFolder.deletePreferencesDictionary(kPreferencesKey, groupName) 15 | End Sub 16 | #tag EndMethod 17 | 18 | #tag Method, Flags = &h0 19 | Sub getAddonState(window as wndMain) 20 | dim i as Integer 21 | 22 | pSceneryPackages = new Dictionary() 23 | pPlugins = new Dictionary() 24 | pCSLs = new Dictionary() 25 | 26 | for i = 0 to window.lstCustomSceneryPackages.listCount - 1 27 | dim customSceneryPackage as CustomSceneryPackage = window.lstCustomSceneryPackages.cellTag(i, 0) 28 | pSceneryPackages.value(customSceneryPackage.pName) = customSceneryPackage.pEnabled 29 | next 30 | 31 | for i = 0 to window.lstPlugins.listCount - 1 32 | dim plugin as Plugin = window.lstPlugins.cellTag(i, 0) 33 | pPlugins.value(plugin.pName) = plugin.pEnabled 34 | next 35 | 36 | if CSL.pAddonClassEnabled then 37 | for i = 0 to window.lstCSLs.listCount - 1 38 | dim csl as CSL = window.lstCSLs.cellTag(i, 0) 39 | pCSLs.value(csl.pName) = csl.pEnabled 40 | next 41 | end if 42 | End Sub 43 | #tag EndMethod 44 | 45 | #tag Method, Flags = &h0 46 | Shared Function getGroups(xPlaneFolder as XPlaneFolderItem) As Group() 47 | dim groupsContainerDictionary as Dictionary = xPlaneFolder.getPreferencesContainerDictionary(kPreferencesKey) 48 | dim i as Integer 49 | dim result() as Group 50 | 51 | for each key as string in groupsContainerDictionary.keys() 52 | dim group as Group = new Group(key, xPlaneFolder) 53 | result.append(group) 54 | next 55 | 56 | return result 57 | End Function 58 | #tag EndMethod 59 | 60 | #tag Method, Flags = &h21 61 | Private Sub loadState() 62 | // The individual addon's Dictionary is always stored using the addon name as the key 63 | dim groupDictionary as Dictionary = pXPlaneFolder.getPreferencesDictionary(kPreferencesKey, me.pName) 64 | 65 | me.retrieveStateFromDictionary(groupDictionary) 66 | 67 | End Sub 68 | #tag EndMethod 69 | 70 | #tag Method, Flags = &h0 71 | Sub populatePopupMenuEntry(popupMenu as PopupMenu) 72 | popupMenu.AddRow(pName) 73 | popupMenu.rowTag(popupMenu.listCount - 1) = me 74 | 75 | End Sub 76 | #tag EndMethod 77 | 78 | #tag Method, Flags = &h1 79 | Protected Sub retrieveStateFromDictionary(state as Dictionary) 80 | // Set up the state of the class from a Dictionary 81 | 82 | if (not state.hasKey(kPreferencesKeyCSLs)) then state.value(kPreferencesKeyCSLs) = new Dictionary() 83 | pCSLs = state.value(kPreferencesKeyCSLs) 84 | 85 | if (not state.hasKey(kPreferencesKeyPlugins)) then state.value(kPreferencesKeyPlugins) = new Dictionary() 86 | pPlugins = state.value(kPreferencesKeyPlugins) 87 | 88 | if (not state.hasKey(kPreferencesKeySceneryPackages)) then state.value(kPreferencesKeySceneryPackages) = new Dictionary() 89 | pSceneryPackages = state.value(kPreferencesKeySceneryPackages) 90 | 91 | End Sub 92 | #tag EndMethod 93 | 94 | #tag Method, Flags = &h0 95 | Sub saveState() 96 | // The individual addon's Dictionary is always stored using the addon name as the key 97 | dim groupDictionary as Dictionary = pXPlaneFolder.getPreferencesDictionary(kPreferencesKey, me.pName) 98 | 99 | me.storeStateToDictionary(groupDictionary) 100 | 101 | End Sub 102 | #tag EndMethod 103 | 104 | #tag Method, Flags = &h0 105 | Sub setAddonState(window as wndMain) 106 | dim i as Integer 107 | 108 | for i = 0 to window.lstCustomSceneryPackages.listCount - 1 109 | dim customSceneryPackage as CustomSceneryPackage = window.lstCustomSceneryPackages.cellTag(i, 0) 110 | if (pSceneryPackages.hasKey(customSceneryPackage.pName)) then customSceneryPackage.enable(pSceneryPackages.value(customSceneryPackage.pName)) 111 | next 112 | 113 | for i = 0 to window.lstPlugins.listCount - 1 114 | dim plugin as Plugin = window.lstPlugins.cellTag(i, 0) 115 | if (pPlugins.hasKey(plugin.pName)) then plugin.enable(pPlugins.value(plugin.pName)) 116 | next 117 | 118 | if CSL.pAddonClassEnabled then 119 | for i = 0 to window.lstCSLs.listCount - 1 120 | dim csl as CSL = window.lstCSLs.cellTag(i, 0) 121 | if (pCSLs.hasKey(csl.pName)) then csl.enable(pCSLs.value(csl.pName)) 122 | next 123 | end if 124 | End Sub 125 | #tag EndMethod 126 | 127 | #tag Method, Flags = &h1 128 | Protected Sub storeStateToDictionary(state as Dictionary) 129 | // Store the state for the group in a Dictionary 130 | 131 | state.value(kPreferencesKeyCSLs) = pCSLs 132 | state.value(kPreferencesKeyPlugins) = pPlugins 133 | state.value(kPreferencesKeySceneryPackages) = pSceneryPackages 134 | 135 | End Sub 136 | #tag EndMethod 137 | 138 | 139 | #tag Property, Flags = &h1 140 | Protected pCSLs As Dictionary 141 | #tag EndProperty 142 | 143 | #tag Property, Flags = &h0 144 | pDirty As Boolean = false 145 | #tag EndProperty 146 | 147 | #tag Property, Flags = &h0 148 | pName As String 149 | #tag EndProperty 150 | 151 | #tag Property, Flags = &h1 152 | Protected pPlugins As Dictionary 153 | #tag EndProperty 154 | 155 | #tag Property, Flags = &h1 156 | Protected pSceneryPackages As Dictionary 157 | #tag EndProperty 158 | 159 | #tag Property, Flags = &h1 160 | Protected pXPlaneFolder As XPlaneFolderItem 161 | #tag EndProperty 162 | 163 | 164 | #tag Constant, Name = kPreferencesKey, Type = String, Dynamic = False, Default = \"groups", Scope = Private 165 | #tag EndConstant 166 | 167 | #tag Constant, Name = kPreferencesKeyCSLs, Type = String, Dynamic = False, Default = \"csls", Scope = Private 168 | #tag EndConstant 169 | 170 | #tag Constant, Name = kPreferencesKeyPlugins, Type = String, Dynamic = False, Default = \"plugins", Scope = Private 171 | #tag EndConstant 172 | 173 | #tag Constant, Name = kPreferencesKeySceneryPackages, Type = String, Dynamic = False, Default = \"scenery_packages", Scope = Private 174 | #tag EndConstant 175 | 176 | 177 | #tag ViewBehavior 178 | #tag ViewProperty 179 | Name="Index" 180 | Visible=true 181 | Group="ID" 182 | InitialValue="-2147483648" 183 | Type="Integer" 184 | #tag EndViewProperty 185 | #tag ViewProperty 186 | Name="Left" 187 | Visible=true 188 | Group="Position" 189 | InitialValue="0" 190 | Type="Integer" 191 | #tag EndViewProperty 192 | #tag ViewProperty 193 | Name="Name" 194 | Visible=true 195 | Group="ID" 196 | Type="String" 197 | #tag EndViewProperty 198 | #tag ViewProperty 199 | Name="pDirty" 200 | Group="Behavior" 201 | InitialValue="false" 202 | Type="Boolean" 203 | #tag EndViewProperty 204 | #tag ViewProperty 205 | Name="pName" 206 | Group="Behavior" 207 | Type="String" 208 | EditorType="MultiLineEditor" 209 | #tag EndViewProperty 210 | #tag ViewProperty 211 | Name="Super" 212 | Visible=true 213 | Group="ID" 214 | Type="String" 215 | #tag EndViewProperty 216 | #tag ViewProperty 217 | Name="Top" 218 | Visible=true 219 | Group="Position" 220 | InitialValue="0" 221 | Type="Integer" 222 | #tag EndViewProperty 223 | #tag EndViewBehavior 224 | End Class 225 | #tag EndClass 226 | -------------------------------------------------------------------------------- /Classes/Plugins/Plugin.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Plugin 3 | Inherits AddOn 4 | #tag Method, Flags = &h0 5 | Shared Function checkXPlaneFolder(folderItem as FolderItem) As Boolean 6 | return folderItem <> nil and folderItem.child("Resources").exists and folderItem.child("Resources").child("plugins").exists 7 | End Function 8 | #tag EndMethod 9 | 10 | #tag Method, Flags = &h0 11 | Sub enable(enable as boolean) 12 | if enable <> pEnabled then 13 | super.enable(enable) 14 | 15 | dim destinationParent as FolderItem = Plugin.getRootFolder(enable) 16 | dim swapDestinationParent as FolderItem = Plugin.getRootFolder(not enable) 17 | 18 | moveItem(enable, destinationParent, swapDestinationParent) 19 | end if 20 | End Sub 21 | #tag EndMethod 22 | 23 | #tag Method, Flags = &h0 24 | Shared Function getInstance(name as String, folderItem as FolderItem, enabled as Boolean, xPlaneFolder as XPlaneFolderItem) As Plugin 25 | // Creates an instance of a Plugin. Detects special plugin subclasses and will return one of those if applicable. 26 | if (PythonInterfacePlugin.isValid(folderItem)) then 27 | return new PythonInterfacePlugin(name, folderItem, enabled, xPlaneFolder) 28 | else 29 | return new Plugin(name, folderItem, enabled, xPlaneFolder) 30 | end if 31 | End Function 32 | #tag EndMethod 33 | 34 | #tag Method, Flags = &h0 35 | Shared Function getRootFolder(enabledVersion as boolean = true) As FolderItem 36 | if (enabledVersion) then 37 | return App.pXPlaneFolder.child("Resources").child("plugins") 38 | else 39 | return App.pXPlaneFolder.child("Resources").child("plugins (disabled)") 40 | end if 41 | 42 | End Function 43 | #tag EndMethod 44 | 45 | #tag Method, Flags = &h0 46 | Shared Sub initialiseXPlaneFolder() 47 | dim disabledFolder as FolderItem 48 | 49 | disabledFolder = Plugin.getRootFolder(false) 50 | if (not disabledFolder.exists) then 51 | disabledFolder.createAsFolder() 52 | end if 53 | 54 | End Sub 55 | #tag EndMethod 56 | 57 | #tag Method, Flags = &h0 58 | Shared Sub install(folderItem as FolderItem) 59 | // We are passed the actual plugin (be it a file or a folder containing a fat plugin). However, we need to install 60 | // everything in the PARENT folder so that we grab any additional resources that may be needed by the plugin 61 | dim i as integer 62 | 63 | dim parentFolderItem as FolderItem = folderItem.Parent 64 | 65 | // Check whether any items with the same names exist first 66 | for i = 1 to parentFolderItem.count 67 | dim subItem as FolderItem = parentFolderItem.trueItem(i) 68 | if Plugin.getRootFolder().child(subItem.name).exists or Plugin.getRootFolder(false).child(subItem.name).exists then 69 | dim parameters() as string = array(subItem.name) 70 | dim result as Integer = App.displayMessage(App.processParameterizedString(wndMain.kErrorItemWithSameNameExists, parameters), "", MessageDialog.GraphicCaution, App.kOk, "", "", wndMain) 71 | return 72 | end if 73 | next 74 | 75 | // Copy the files and folders 76 | for i = 1 to parentFolderItem.count 77 | parentFolderItem.trueItem(i).copyFileTo(Plugin.getRootFolder()) 78 | next 79 | // And delete 80 | parentFolderItem.delete() 81 | End Sub 82 | #tag EndMethod 83 | 84 | #tag Method, Flags = &h0 85 | Shared Function isValid(folderItem as FolderItem) As boolean 86 | if Addon.isValid(folderItem) = false then return false 87 | 88 | // Check for a fat plugin 89 | if folderItem.Directory and ((TargetMacOS and folderItem.child("mac.xpl").exists) or (TargetLinux and folderItem.child("lin.xpl").exists) or (TargetWin32 and folderItem.child("win.xpl").exists)) then 90 | return true 91 | end if 92 | 93 | // If not fat, then it must have a file extension 94 | if folderItem.name.right(4) <> ".xpl" then return false 95 | 96 | // Only Mac could be a directory 97 | if folderItem.Directory and not TargetMacOS then return false 98 | 99 | dim pluginFolderItem as FolderItem 100 | if folderItem.Directory then 101 | // Mac plugin that is a folder (Mac Package) 102 | if (folderItem.child("Contents").exists()) then 103 | pluginFolderItem = folderItem.child("Contents").child("MacOS").item(1) 104 | else 105 | return false 106 | end if 107 | else 108 | // A simple file 109 | pluginFolderItem = folderItem 110 | end if 111 | 112 | if pluginFolderItem = nil then return false 113 | 114 | dim bs as BinaryStream = BinaryStream.open(pluginFolderItem, false) 115 | if bs = nil then return false 116 | 117 | dim header as String = Utilities.binToHex(bs.Read(8), "") 118 | 119 | if TargetMacOS then 120 | return header = kMacHeader 121 | elseif TargetLinux then 122 | return header = kLinuxHeader 123 | elseif TargetWin32 then 124 | return header = kWindowsHeader 125 | else 126 | return false 127 | end if 128 | End Function 129 | #tag EndMethod 130 | 131 | #tag Method, Flags = &h0 132 | Sub populateListBoxEntry(listBox as ListBox, addAsFolder as boolean = false) 133 | // Part of the AddonInterface interface. 134 | super.populateListBoxEntry(listBox, addAsFolder) 135 | 136 | listBox.RowPicture(listBox.LastIndex) = imgPlugin 137 | End Sub 138 | #tag EndMethod 139 | 140 | 141 | #tag Constant, Name = kLinuxHeader, Type = String, Dynamic = False, Default = \"7F454C4601010100", Scope = Public 142 | #tag EndConstant 143 | 144 | #tag Constant, Name = kMacHeader, Type = String, Dynamic = False, Default = \"CAFEBABE00000002", Scope = Public 145 | #tag EndConstant 146 | 147 | #tag Constant, Name = kWindowsHeader, Type = String, Dynamic = False, Default = \"4D5A900003000000", Scope = Public 148 | #tag EndConstant 149 | 150 | 151 | #tag ViewBehavior 152 | #tag ViewProperty 153 | Name="Index" 154 | Visible=true 155 | Group="ID" 156 | InitialValue="-2147483648" 157 | Type="Integer" 158 | #tag EndViewProperty 159 | #tag ViewProperty 160 | Name="Left" 161 | Visible=true 162 | Group="Position" 163 | InitialValue="0" 164 | Type="Integer" 165 | #tag EndViewProperty 166 | #tag ViewProperty 167 | Name="Name" 168 | Visible=true 169 | Group="ID" 170 | Type="String" 171 | #tag EndViewProperty 172 | #tag ViewProperty 173 | Name="pEnabled" 174 | Group="Behavior" 175 | InitialValue="true" 176 | Type="Boolean" 177 | #tag EndViewProperty 178 | #tag ViewProperty 179 | Name="pName" 180 | Group="Behavior" 181 | Type="String" 182 | EditorType="MultiLineEditor" 183 | #tag EndViewProperty 184 | #tag ViewProperty 185 | Name="Super" 186 | Visible=true 187 | Group="ID" 188 | Type="String" 189 | #tag EndViewProperty 190 | #tag ViewProperty 191 | Name="Top" 192 | Visible=true 193 | Group="Position" 194 | InitialValue="0" 195 | Type="Integer" 196 | #tag EndViewProperty 197 | #tag EndViewBehavior 198 | End Class 199 | #tag EndClass 200 | -------------------------------------------------------------------------------- /Classes/Plugins/PythonInterfacePlugin.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class PythonInterfacePlugin 3 | Inherits Plugin 4 | #tag Method, Flags = &h0 5 | Sub Constructor(name as String, folderItem as FolderItem, enabled as Boolean, xPlaneFolder as XPlaneFolderItem) 6 | // Calling the overridden superclass constructor. 7 | super.Constructor(name, folderItem, enabled, xPlaneFolder) 8 | 9 | dim i as integer 10 | dim pythonScriptsFolderItem as FolderItem = Plugin.getRootFolder().child(kScriptsFolderItemName) 11 | 12 | if (pythonScriptsFolderItem.exists()) then 13 | dim regex as new RegEx 14 | dim match as RegExMatch 15 | 16 | // Pattern for finding Python scripts 17 | regex.SearchPattern = kRegexScriptFilename 18 | 19 | for i = 1 to pythonScriptsFolderItem.count 20 | dim scriptFolderItem as FolderItem = pythonScriptsFolderItem.Item(i) 21 | 22 | match = regex.search(scriptFolderItem.name) 23 | if match = nil then continue 24 | pScripts.append(match.subExpressionString(1)) 25 | next 26 | end if 27 | 28 | 29 | End Sub 30 | #tag EndMethod 31 | 32 | #tag Method, Flags = &h0 33 | Sub expandListBoxEntry(listBox as ListBox, clickedRow as integer) 34 | // Part of the AddonInterface interface. 35 | super.expandListBoxEntry(listBox, clickedRow) 36 | 37 | dim i as integer 38 | 39 | // Show the list of scripts 40 | for i = 0 to ubound(pScripts) 41 | listBox.AddRow(pScripts(i)) 42 | listBox.cellTag(listBox.lastIndex, 0) = me 43 | // Remove the check box 44 | listBox.cellType(listBox.lastIndex, 1) = ListBox.TypeNormal 45 | next 46 | 47 | 48 | End Sub 49 | #tag EndMethod 50 | 51 | #tag Method, Flags = &h0 52 | Shared Function isValid(folderItem as FolderItem) As Boolean 53 | return left(folderItem.name, len(kFolderItemName)) = kFolderItemName 54 | End Function 55 | #tag EndMethod 56 | 57 | #tag Method, Flags = &h0 58 | Sub populateListBoxEntry(listBox as ListBox, addAsFolder as boolean = false) 59 | // Part of the AddonInterface interface. 60 | super.populateListBoxEntry(listBox, true) 61 | End Sub 62 | #tag EndMethod 63 | 64 | 65 | #tag Property, Flags = &h0 66 | pScripts() As String 67 | #tag EndProperty 68 | 69 | 70 | #tag Constant, Name = kFolderItemName, Type = String, Dynamic = False, Default = \"PythonInterface", Scope = Private 71 | #tag EndConstant 72 | 73 | #tag Constant, Name = kRegexScriptFilename, Type = String, Dynamic = False, Default = \"^PI_(.*).py$", Scope = Private 74 | #tag EndConstant 75 | 76 | #tag Constant, Name = kScriptsFolderItemName, Type = String, Dynamic = False, Default = \"PythonScripts", Scope = Private 77 | #tag EndConstant 78 | 79 | 80 | #tag ViewBehavior 81 | #tag ViewProperty 82 | Name="Index" 83 | Visible=true 84 | Group="ID" 85 | InitialValue="-2147483648" 86 | Type="Integer" 87 | #tag EndViewProperty 88 | #tag ViewProperty 89 | Name="Left" 90 | Visible=true 91 | Group="Position" 92 | InitialValue="0" 93 | Type="Integer" 94 | #tag EndViewProperty 95 | #tag ViewProperty 96 | Name="Name" 97 | Visible=true 98 | Group="ID" 99 | Type="String" 100 | #tag EndViewProperty 101 | #tag ViewProperty 102 | Name="pEnabled" 103 | Group="Behavior" 104 | InitialValue="true" 105 | Type="Boolean" 106 | #tag EndViewProperty 107 | #tag ViewProperty 108 | Name="pName" 109 | Group="Behavior" 110 | Type="String" 111 | EditorType="MultiLineEditor" 112 | #tag EndViewProperty 113 | #tag ViewProperty 114 | Name="Super" 115 | Visible=true 116 | Group="ID" 117 | Type="String" 118 | #tag EndViewProperty 119 | #tag ViewProperty 120 | Name="Top" 121 | Visible=true 122 | Group="Position" 123 | InitialValue="0" 124 | Type="Integer" 125 | #tag EndViewProperty 126 | #tag EndViewBehavior 127 | End Class 128 | #tag EndClass 129 | -------------------------------------------------------------------------------- /Classes/Preferences.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Preferences 3 | #tag Method, Flags = &h0 4 | Sub Constructor() 5 | pDictionary = new Dictionary 6 | 7 | load() 8 | 9 | // Check for old preferences format and automatically convert to new 10 | if (pDictionary.hasKey("XPlanePath")) then upgradePreferences() 11 | 12 | End Sub 13 | #tag EndMethod 14 | 15 | #tag Method, Flags = &h21 16 | Private Function getBoolean(key as String) As Boolean 17 | // Return a Boolean. Create it if it doesn't exist. 18 | if (not pDictionary.hasKey(key)) then pDictionary.value(key) = false 19 | return pDictionary.value(key) 20 | 21 | End Function 22 | #tag EndMethod 23 | 24 | #tag Method, Flags = &h21 25 | Private Function getDictionary(key as string) As Dictionary 26 | // Return a Dictionary. Create it if it doesn't exist. 27 | if (not pDictionary.hasKey(key)) then pDictionary.value(key) = new Dictionary() 28 | return pDictionary.value(key) 29 | 30 | End Function 31 | #tag EndMethod 32 | 33 | #tag Method, Flags = &h0 34 | Function getLastXPlaneFolder() As string 35 | return getString(kKeyLastXPlaneFolder) 36 | End Function 37 | #tag EndMethod 38 | 39 | #tag Method, Flags = &h21 40 | Private Function getString(key as string) As String 41 | // Return a String. Create it if it doesn't exist. 42 | if (not pDictionary.hasKey(key)) then pDictionary.value(key) = "" 43 | return pDictionary.value(key) 44 | 45 | End Function 46 | #tag EndMethod 47 | 48 | #tag Method, Flags = &h0 49 | Function getXPlaneFolderDictionary(xPlanePath as String) As Dictionary 50 | // Return a Dictionary containing all the preferences for a particular XPlane® folder. 51 | // Create a new one if it doesn't exist yet 52 | // We don't initialise any of the contents here because that is done dynamically as items are requested. 53 | // This helps to future-proof the preferences structure 54 | 55 | dim xPlaneFoldersDictionary as Dictionary = getDictionary(kKeyXPlaneFolders) 56 | 57 | if (not xPlaneFoldersDictionary.hasKey(xPlanePath)) then xPlaneFoldersDictionary.value(xPlanePath) = new Dictionary() 58 | return xPlaneFoldersDictionary.value(xPlanePath) 59 | End Function 60 | #tag EndMethod 61 | 62 | #tag Method, Flags = &h0 63 | Function getXPlanePaths() As String() 64 | // Get all the XPlane folder paths we know about in the preferences. See the class notes for a description of the 65 | // preferences structure. 66 | 67 | dim xPlaneFoldersDictionary as Dictionary = getDictionary(kKeyXPlaneFolders) 68 | 69 | dim paths() as String 70 | dim keys() as variant = xPlaneFoldersDictionary.keys() 71 | 72 | for each key as String in keys 73 | paths.append(key) 74 | next 75 | 76 | return paths 77 | End Function 78 | #tag EndMethod 79 | 80 | #tag Method, Flags = &h0 81 | Function isAirportSearchEnabled() As boolean 82 | return getBoolean(kKeyAirportSearchEnabled) 83 | End Function 84 | #tag EndMethod 85 | 86 | #tag Method, Flags = &h21 87 | Private Sub load() 88 | dim prefsFile as FolderItem = SpecialFolder.Preferences.Child(App.kApplicationName + ".plist") 89 | if (prefsFile.exists()) then 90 | dim result as Boolean = pDictionary.loadXML(prefsFile) 91 | end if 92 | End Sub 93 | #tag EndMethod 94 | 95 | #tag Method, Flags = &h0 96 | Sub save() 97 | dim prefsFile as FolderItem = SpecialFolder.Preferences.Child(App.kApplicationName + ".plist") 98 | dim result as Boolean = pDictionary.saveXML(prefsFile, true) 99 | End Sub 100 | #tag EndMethod 101 | 102 | #tag Method, Flags = &h21 103 | Private Sub set(key as String, value as Variant) 104 | // Sets a preferences value. 105 | pDictionary.value(key) = value 106 | 107 | End Sub 108 | #tag EndMethod 109 | 110 | #tag Method, Flags = &h0 111 | Sub setAirportSearchEnabled(enabled as boolean) 112 | set(kKeyAirportSearchEnabled, enabled) 113 | End Sub 114 | #tag EndMethod 115 | 116 | #tag Method, Flags = &h0 117 | Sub setLastXPlaneFolder(folderPath as String) 118 | set(kKeyLastXPlaneFolder, folderPath) 119 | End Sub 120 | #tag EndMethod 121 | 122 | #tag Method, Flags = &h21 123 | Private Sub upgradePreferences() 124 | // The old format just used a flat top-level structure. 125 | dim oldPreferencesDictionary as Dictionary = pDictionary 126 | 127 | // Clear the preferences Dictionary 128 | pDictionary = new Dictionary() 129 | 130 | // Create an entry for the previous X-Plane folder 131 | setLastXPlaneFolder(oldPreferencesDictionary.value("XPlanePath")) 132 | 133 | // Create a Dictionary for the previous X-Plane folder 134 | dim xPlaneFolderDictionary as Dictionary = getXPlaneFolderDictionary(oldPreferencesDictionary.value("XPlanePath")) 135 | 136 | // Create the scenery packages dictionary inside the X-Plane Dictionary 137 | dim sceneryPackagesDictionary as new Dictionary() 138 | xPlaneFolderDictionary.value(CustomSceneryPackage.kPreferencesKey) = sceneryPackagesDictionary 139 | 140 | // All the old keys were used to determine whether scenery packages were shown on the map (except the 'XPlanePath' key ofc) 141 | dim keys() as variant = oldPreferencesDictionary.keys() 142 | for each key as String in keys 143 | if (key = "XPlanePath") then continue 144 | 145 | // Each old key starts with 'cpkg_show_' and is followed by the scenery package name. 146 | dim sceneryPackageDictionary as new Dictionary() 147 | sceneryPackageDictionary.value(CustomSceneryPackage.kPreferencesKeyShowOnMap) = oldPreferencesDictionary.value(key) 148 | sceneryPackagesDictionary.value(key.mid(11)) = sceneryPackageDictionary 149 | next 150 | 151 | 152 | End Sub 153 | #tag EndMethod 154 | 155 | 156 | #tag Note, Name = Structure of pDictionary 157 | 158 | 'xplane_folders' => Dictionary 159 | '/Applications/X-Plane' => Dictionary 160 | 'custom_scenery_packages' => Dictionary 161 | 'EGCV Sleap' => Dictionary 162 | 'show_on_map' => Boolean 163 | 'groups' => Dictionary 164 | 'last_xplane_folder' => String 165 | 'airport_search_enabled' => Boolean 166 | #tag EndNote 167 | 168 | 169 | #tag Property, Flags = &h21 170 | Private pDictionary As Dictionary 171 | #tag EndProperty 172 | 173 | 174 | #tag Constant, Name = kKeyAirportSearchEnabled, Type = String, Dynamic = False, Default = \"airport_search_enabled", Scope = Private 175 | #tag EndConstant 176 | 177 | #tag Constant, Name = kKeyLastXPlaneFolder, Type = String, Dynamic = False, Default = \"last_xplane_folder", Scope = Private 178 | #tag EndConstant 179 | 180 | #tag Constant, Name = kKeyXPlaneFolders, Type = String, Dynamic = False, Default = \"xplane_folders", Scope = Private 181 | #tag EndConstant 182 | 183 | 184 | #tag ViewBehavior 185 | #tag ViewProperty 186 | Name="Index" 187 | Visible=true 188 | Group="ID" 189 | InitialValue="-2147483648" 190 | Type="Integer" 191 | #tag EndViewProperty 192 | #tag ViewProperty 193 | Name="Left" 194 | Visible=true 195 | Group="Position" 196 | InitialValue="0" 197 | Type="Integer" 198 | #tag EndViewProperty 199 | #tag ViewProperty 200 | Name="Name" 201 | Visible=true 202 | Group="ID" 203 | Type="String" 204 | #tag EndViewProperty 205 | #tag ViewProperty 206 | Name="Super" 207 | Visible=true 208 | Group="ID" 209 | Type="String" 210 | #tag EndViewProperty 211 | #tag ViewProperty 212 | Name="Top" 213 | Visible=true 214 | Group="Position" 215 | InitialValue="0" 216 | Type="Integer" 217 | #tag EndViewProperty 218 | #tag EndViewBehavior 219 | End Class 220 | #tag EndClass 221 | -------------------------------------------------------------------------------- /Classes/Scenery/Airport.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class Airport 3 | #tag Method, Flags = &h0 4 | Sub Constructor(code as String, name as String, latitude as double, longitude as double) 5 | pCode = code 6 | pName = name 7 | pLatLong = new LatLongPoint(latitude, longitude) 8 | End Sub 9 | #tag EndMethod 10 | 11 | #tag Method, Flags = &h0 12 | Function getDistanceFrom(latitude as double, longitude as double) As double 13 | return pLatLong.getDistanceFrom(latitude, longitude) 14 | End Function 15 | #tag EndMethod 16 | 17 | 18 | #tag Property, Flags = &h0 19 | pCode As String 20 | #tag EndProperty 21 | 22 | #tag Property, Flags = &h0 23 | pLatLong As LatLongPoint 24 | #tag EndProperty 25 | 26 | #tag Property, Flags = &h0 27 | pName As String 28 | #tag EndProperty 29 | 30 | 31 | #tag ViewBehavior 32 | #tag ViewProperty 33 | Name="Index" 34 | Visible=true 35 | Group="ID" 36 | InitialValue="-2147483648" 37 | Type="Integer" 38 | #tag EndViewProperty 39 | #tag ViewProperty 40 | Name="Left" 41 | Visible=true 42 | Group="Position" 43 | InitialValue="0" 44 | Type="Integer" 45 | #tag EndViewProperty 46 | #tag ViewProperty 47 | Name="Name" 48 | Visible=true 49 | Group="ID" 50 | Type="String" 51 | #tag EndViewProperty 52 | #tag ViewProperty 53 | Name="pCode" 54 | Group="Behavior" 55 | Type="String" 56 | EditorType="MultiLineEditor" 57 | #tag EndViewProperty 58 | #tag ViewProperty 59 | Name="pName" 60 | Group="Behavior" 61 | Type="String" 62 | EditorType="MultiLineEditor" 63 | #tag EndViewProperty 64 | #tag ViewProperty 65 | Name="Super" 66 | Visible=true 67 | Group="ID" 68 | Type="String" 69 | #tag EndViewProperty 70 | #tag ViewProperty 71 | Name="Top" 72 | Visible=true 73 | Group="Position" 74 | InitialValue="0" 75 | Type="Integer" 76 | #tag EndViewProperty 77 | #tag EndViewBehavior 78 | End Class 79 | #tag EndClass 80 | -------------------------------------------------------------------------------- /Classes/Scenery/AirportDataSceneryObject.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class AirportDataSceneryObject 3 | Inherits SceneryObject 4 | #tag Method, Flags = &h0 5 | Sub Constructor(folderItem as FolderItem) 6 | // Calling the overridden superclass constructor. 7 | Super.Constructor(folderItem) 8 | 9 | dim tis as TextInputStream = TextInputStream.open(folderItem) 10 | tis.Encoding = Encodings.ISOLatin1 11 | 12 | dim rowFromFile as String 13 | dim versionRegex as new RegEx 14 | dim aptRegex as new RegEx 15 | dim rwyRegex as new RegEx 16 | dim match as RegExMatch 17 | dim fastMatchAptDatAirportLineLen as integer = lenB(kFastMatchAptDatAirportLine) 18 | pAirports = new Dictionary 19 | 20 | // 'I' / 'A' 21 | rowFromFile = tis.ReadLine 22 | 23 | // Search for version line 24 | versionRegex.SearchPattern = kRegexAptDatVersionLine 25 | do 26 | rowFromFile = tis.ReadLine 27 | 28 | match = versionRegex.search(rowFromFile) 29 | if match = nil then continue 30 | 31 | // Found the version line 32 | dim fileVersion as String = match.subExpressionString(1) 33 | 34 | aptRegex.SearchPattern = kRegexAptDatAirportLine 35 | if (val(fileVersion) >= 850) then 36 | rwyRegex.SearchPattern = kRegexAptDat850RunwayLine 37 | else 38 | rwyRegex.SearchPattern = kRegexAptDat715RunwayLine 39 | end if 40 | 41 | // Search for Airport lines 42 | do 43 | rowFromFile = tis.ReadLine 44 | 45 | // Fast string comparison before regex - this scans a lot of data and needs to be quick 46 | if (rowFromFile.LeftB(fastMatchAptDatAirportLineLen) <> kFastMatchAptDatAirportLine) then continue 47 | 48 | match = aptRegex.search(rowFromFile) 49 | if match = nil then continue 50 | 51 | // Found an airport line, search for a runway 52 | dim aptCode as string = match.subExpressionString(1) 53 | dim aptName as string = match.subExpressionString(2) 54 | 55 | do 56 | rowFromFile = tis.ReadLine 57 | 58 | match = rwyRegex.search(rowFromFile) 59 | if match = nil then continue 60 | 61 | // Found a runway line 62 | dim aptLat as double = val(match.subExpressionString(1)) 63 | dim aptLong as double = val(match.subExpressionString(2)) 64 | dim airport as Airport = new Airport(aptCode, aptName, aptLat, aptLong) 65 | pAirports.value(aptCode) = airport 66 | 67 | exit 68 | loop until tis.EOF 69 | 70 | loop until tis.EOF 71 | 72 | loop until tis.EOF 73 | 74 | tis.Close 75 | 76 | exception err as RegExException 77 | MsgBox err.message 78 | End Sub 79 | #tag EndMethod 80 | 81 | #tag Method, Flags = &h0 82 | Function findNearestAirports(latitude as double, longitude as double, maxRange as integer) As Airport() 83 | dim i as integer 84 | dim result() as Airport 85 | dim airports() as Variant = pAirports.values 86 | 87 | for i = 0 to ubound(airports) 88 | dim airport as Airport = Airport(airports(i)) 89 | if (airport.getDistanceFrom(latitude, longitude) <= maxRange) then 90 | result.append(airport) 91 | end if 92 | next 93 | 94 | return result 95 | End Function 96 | #tag EndMethod 97 | 98 | #tag Method, Flags = &h0 99 | Shared Function isAirportData(folderItem as FolderItem) As boolean 100 | return folderItem.name = "apt.dat" 101 | End Function 102 | #tag EndMethod 103 | 104 | 105 | #tag Property, Flags = &h0 106 | pAirports As Dictionary 107 | #tag EndProperty 108 | 109 | 110 | #tag Constant, Name = kFastMatchAptDatAirportLine, Type = String, Dynamic = False, Default = \"1 ", Scope = Private 111 | #tag EndConstant 112 | 113 | #tag Constant, Name = kRegexAptDat715RunwayLine, Type = String, Dynamic = False, Default = \"^\\s*10\\s+(-\?[0-9]+\\.[0-9]+)\\s+(-\?[0-9]+\\.[0-9]+)", Scope = Private 114 | #tag EndConstant 115 | 116 | #tag Constant, Name = kRegexAptDat850RunwayLine, Type = String, Dynamic = False, Default = \"^\\s*100\\s+[0-9]+(\?:\\.[0-9]+)\?\\s+[0-9]+\\s+[0-9]+\\s+[0-9]+(\?:\\.[0-9]+)\?\\s+[0-9]\\s+[0-9]\\s+[0-9]\\s+.*\?\\s+(-\?[0-9]+\\.[0-9]+)\\s+(-\?[0-9]+\\.[0-9]+)", Scope = Private 117 | #tag EndConstant 118 | 119 | #tag Constant, Name = kRegexAptDatAirportLine, Type = String, Dynamic = False, Default = \"^\\s*1\\s+[0-9]*\\s+[01]\\s+[01]\\s+(.*\?)\\s(.*)", Scope = Private 120 | #tag EndConstant 121 | 122 | #tag Constant, Name = kRegexAptDatVersionLine, Type = String, Dynamic = False, Default = \"^([0-9]+)\\s", Scope = Private 123 | #tag EndConstant 124 | 125 | 126 | #tag ViewBehavior 127 | #tag ViewProperty 128 | Name="Index" 129 | Visible=true 130 | Group="ID" 131 | InitialValue="-2147483648" 132 | Type="Integer" 133 | #tag EndViewProperty 134 | #tag ViewProperty 135 | Name="Left" 136 | Visible=true 137 | Group="Position" 138 | InitialValue="0" 139 | Type="Integer" 140 | #tag EndViewProperty 141 | #tag ViewProperty 142 | Name="Name" 143 | Visible=true 144 | Group="ID" 145 | Type="String" 146 | #tag EndViewProperty 147 | #tag ViewProperty 148 | Name="Super" 149 | Visible=true 150 | Group="ID" 151 | Type="String" 152 | #tag EndViewProperty 153 | #tag ViewProperty 154 | Name="Top" 155 | Visible=true 156 | Group="Position" 157 | InitialValue="0" 158 | Type="Integer" 159 | #tag EndViewProperty 160 | #tag EndViewBehavior 161 | End Class 162 | #tag EndClass 163 | -------------------------------------------------------------------------------- /Classes/Scenery/DSF.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class DSF 3 | Inherits LocationalSceneryObject 4 | #tag Method, Flags = &h0 5 | Shared Function isDSF(folderItem as FolderItem) As boolean 6 | return folderItem.name.right(4) = ".dsf" 7 | End Function 8 | #tag EndMethod 9 | 10 | 11 | #tag ViewBehavior 12 | #tag ViewProperty 13 | Name="Index" 14 | Visible=true 15 | Group="ID" 16 | InitialValue="-2147483648" 17 | Type="Integer" 18 | #tag EndViewProperty 19 | #tag ViewProperty 20 | Name="Left" 21 | Visible=true 22 | Group="Position" 23 | InitialValue="0" 24 | Type="Integer" 25 | #tag EndViewProperty 26 | #tag ViewProperty 27 | Name="Name" 28 | Visible=true 29 | Group="ID" 30 | Type="String" 31 | #tag EndViewProperty 32 | #tag ViewProperty 33 | Name="Super" 34 | Visible=true 35 | Group="ID" 36 | Type="String" 37 | #tag EndViewProperty 38 | #tag ViewProperty 39 | Name="Top" 40 | Visible=true 41 | Group="Position" 42 | InitialValue="0" 43 | Type="Integer" 44 | #tag EndViewProperty 45 | #tag EndViewBehavior 46 | End Class 47 | #tag EndClass 48 | -------------------------------------------------------------------------------- /Classes/Scenery/ENV.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class ENV 3 | Inherits LocationalSceneryObject 4 | #tag Method, Flags = &h0 5 | Shared Function isENV(folderItem as FolderItem) As boolean 6 | return folderItem.name.right(4) = ".env" 7 | End Function 8 | #tag EndMethod 9 | 10 | 11 | #tag ViewBehavior 12 | #tag ViewProperty 13 | Name="Index" 14 | Visible=true 15 | Group="ID" 16 | InitialValue="-2147483648" 17 | Type="Integer" 18 | #tag EndViewProperty 19 | #tag ViewProperty 20 | Name="Left" 21 | Visible=true 22 | Group="Position" 23 | InitialValue="0" 24 | Type="Integer" 25 | #tag EndViewProperty 26 | #tag ViewProperty 27 | Name="Name" 28 | Visible=true 29 | Group="ID" 30 | Type="String" 31 | #tag EndViewProperty 32 | #tag ViewProperty 33 | Name="Super" 34 | Visible=true 35 | Group="ID" 36 | Type="String" 37 | #tag EndViewProperty 38 | #tag ViewProperty 39 | Name="Top" 40 | Visible=true 41 | Group="Position" 42 | InitialValue="0" 43 | Type="Integer" 44 | #tag EndViewProperty 45 | #tag EndViewBehavior 46 | End Class 47 | #tag EndClass 48 | -------------------------------------------------------------------------------- /Classes/Scenery/LatLongPoint.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class LatLongPoint 3 | #tag Method, Flags = &h0 4 | Sub Constructor(latitude as Double, longitude as Double) 5 | pLatitude = latitude 6 | pLongitude = longitude 7 | 8 | End Sub 9 | #tag EndMethod 10 | 11 | #tag Method, Flags = &h0 12 | Function getDistanceFrom(latitude as double, longitude as double) As double 13 | return sqrt(abs(latitude - pLatitude) ^ 2 + abs(longitude - pLongitude) ^ 2) 14 | End Function 15 | #tag EndMethod 16 | 17 | 18 | #tag Property, Flags = &h0 19 | pLatitude As Double 20 | #tag EndProperty 21 | 22 | #tag Property, Flags = &h0 23 | pLongitude As Double 24 | #tag EndProperty 25 | 26 | 27 | #tag ViewBehavior 28 | #tag ViewProperty 29 | Name="Index" 30 | Visible=true 31 | Group="ID" 32 | InitialValue="-2147483648" 33 | Type="Integer" 34 | #tag EndViewProperty 35 | #tag ViewProperty 36 | Name="Left" 37 | Visible=true 38 | Group="Position" 39 | InitialValue="0" 40 | Type="Integer" 41 | #tag EndViewProperty 42 | #tag ViewProperty 43 | Name="Name" 44 | Visible=true 45 | Group="ID" 46 | Type="String" 47 | #tag EndViewProperty 48 | #tag ViewProperty 49 | Name="pLatitude" 50 | Group="Behavior" 51 | Type="Double" 52 | #tag EndViewProperty 53 | #tag ViewProperty 54 | Name="pLongitude" 55 | Group="Behavior" 56 | Type="Double" 57 | #tag EndViewProperty 58 | #tag ViewProperty 59 | Name="Super" 60 | Visible=true 61 | Group="ID" 62 | Type="String" 63 | #tag EndViewProperty 64 | #tag ViewProperty 65 | Name="Top" 66 | Visible=true 67 | Group="Position" 68 | InitialValue="0" 69 | Type="Integer" 70 | #tag EndViewProperty 71 | #tag EndViewBehavior 72 | End Class 73 | #tag EndClass 74 | -------------------------------------------------------------------------------- /Classes/Scenery/LibrarySceneryObject.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class LibrarySceneryObject 3 | Inherits SceneryObject 4 | #tag ViewBehavior 5 | #tag ViewProperty 6 | Name="Index" 7 | Visible=true 8 | Group="ID" 9 | InitialValue="-2147483648" 10 | Type="Integer" 11 | #tag EndViewProperty 12 | #tag ViewProperty 13 | Name="Left" 14 | Visible=true 15 | Group="Position" 16 | InitialValue="0" 17 | Type="Integer" 18 | #tag EndViewProperty 19 | #tag ViewProperty 20 | Name="Name" 21 | Visible=true 22 | Group="ID" 23 | Type="String" 24 | #tag EndViewProperty 25 | #tag ViewProperty 26 | Name="Super" 27 | Visible=true 28 | Group="ID" 29 | Type="String" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Top" 33 | Visible=true 34 | Group="Position" 35 | InitialValue="0" 36 | Type="Integer" 37 | #tag EndViewProperty 38 | #tag EndViewBehavior 39 | End Class 40 | #tag EndClass 41 | -------------------------------------------------------------------------------- /Classes/Scenery/LocationalSceneryObject.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class LocationalSceneryObject 3 | Inherits SceneryObject 4 | #tag Method, Flags = &h0 5 | Sub Constructor(folderItem as FolderItem) 6 | super.Constructor(folderItem) 7 | 8 | dim regex as new RegEx 9 | dim match as RegExMatch 10 | dim latitude, longitude as Double 11 | 12 | regex.SearchPattern = "(\+|-)([0-9]*)(\+|-)([0-9]*)\.(dsf|env)" 13 | 14 | match = regex.search(folderItem.name) 15 | 16 | if match <> nil then 17 | if match.subExpressionString(1) = "-" then 18 | latitude = -val(match.subExpressionString(2)) 19 | else 20 | latitude = val(match.subExpressionString(2)) 21 | end if 22 | 23 | if match.subExpressionString(3) = "-" then 24 | longitude = -val(match.subExpressionString(4)) 25 | else 26 | longitude = val(match.subExpressionString(4)) 27 | end if 28 | end if 29 | 30 | pLatLong = new LatLongPoint(latitude, longitude) 31 | 32 | exception err as RegExException 33 | MsgBox err.message 34 | End Sub 35 | #tag EndMethod 36 | 37 | #tag Method, Flags = &h0 38 | Function getDistanceFrom(latitude as double, longitude as double) As double 39 | return pLatLong.getDistanceFrom(latitude, longitude) 40 | End Function 41 | #tag EndMethod 42 | 43 | #tag Method, Flags = &h0 44 | Function getLatitude() As Double 45 | return pLatLong.pLatitude 46 | End Function 47 | #tag EndMethod 48 | 49 | #tag Method, Flags = &h0 50 | Function getLongitude() As Double 51 | return pLatLong.pLongitude 52 | End Function 53 | #tag EndMethod 54 | 55 | 56 | #tag Property, Flags = &h1 57 | Protected pLatLong As LatLongPoint 58 | #tag EndProperty 59 | 60 | 61 | #tag ViewBehavior 62 | #tag ViewProperty 63 | Name="Index" 64 | Visible=true 65 | Group="ID" 66 | InitialValue="-2147483648" 67 | Type="Integer" 68 | #tag EndViewProperty 69 | #tag ViewProperty 70 | Name="Left" 71 | Visible=true 72 | Group="Position" 73 | InitialValue="0" 74 | Type="Integer" 75 | #tag EndViewProperty 76 | #tag ViewProperty 77 | Name="Name" 78 | Visible=true 79 | Group="ID" 80 | Type="String" 81 | #tag EndViewProperty 82 | #tag ViewProperty 83 | Name="Super" 84 | Visible=true 85 | Group="ID" 86 | Type="String" 87 | #tag EndViewProperty 88 | #tag ViewProperty 89 | Name="Top" 90 | Visible=true 91 | Group="Position" 92 | InitialValue="0" 93 | Type="Integer" 94 | #tag EndViewProperty 95 | #tag EndViewBehavior 96 | End Class 97 | #tag EndClass 98 | -------------------------------------------------------------------------------- /Classes/Scenery/SceneryObject.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class SceneryObject 3 | #tag Method, Flags = &h0 4 | Sub Constructor(folderItem as FolderItem) 5 | pFolderItem = folderItem 6 | 7 | End Sub 8 | #tag EndMethod 9 | 10 | 11 | #tag Property, Flags = &h0 12 | pFolderItem As FolderItem 13 | #tag EndProperty 14 | 15 | 16 | #tag ViewBehavior 17 | #tag ViewProperty 18 | Name="Index" 19 | Visible=true 20 | Group="ID" 21 | InitialValue="-2147483648" 22 | Type="Integer" 23 | #tag EndViewProperty 24 | #tag ViewProperty 25 | Name="Left" 26 | Visible=true 27 | Group="Position" 28 | InitialValue="0" 29 | Type="Integer" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Name" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Super" 39 | Visible=true 40 | Group="ID" 41 | Type="String" 42 | #tag EndViewProperty 43 | #tag ViewProperty 44 | Name="Top" 45 | Visible=true 46 | Group="Position" 47 | InitialValue="0" 48 | Type="Integer" 49 | #tag EndViewProperty 50 | #tag EndViewBehavior 51 | End Class 52 | #tag EndClass 53 | -------------------------------------------------------------------------------- /Classes/UnzipThread.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class UnzipThread 3 | Inherits Thread 4 | #tag Event 5 | Sub Run() 6 | pExtractedFolderItem = Addon.extractZipToTemporaryLocation(pZipFolderItem) 7 | 8 | End Sub 9 | #tag EndEvent 10 | 11 | 12 | #tag Method, Flags = &h1000 13 | Sub init(folderItem as FolderItem) 14 | pZipFolderItem = folderItem 15 | pExtractedFolderItem = nil 16 | 17 | End Sub 18 | #tag EndMethod 19 | 20 | 21 | #tag Property, Flags = &h0 22 | pExtractedFolderItem As FolderItem 23 | #tag EndProperty 24 | 25 | #tag Property, Flags = &h0 26 | pZipFolderItem As FolderItem 27 | #tag EndProperty 28 | 29 | 30 | #tag ViewBehavior 31 | #tag ViewProperty 32 | Name="Index" 33 | Visible=true 34 | Group="ID" 35 | Type="Integer" 36 | EditorType="Integer" 37 | #tag EndViewProperty 38 | #tag ViewProperty 39 | Name="Name" 40 | Visible=true 41 | Group="ID" 42 | Type="String" 43 | EditorType="String" 44 | #tag EndViewProperty 45 | #tag ViewProperty 46 | Name="Priority" 47 | Visible=true 48 | Group="Behavior" 49 | InitialValue="5" 50 | Type="Integer" 51 | #tag EndViewProperty 52 | #tag ViewProperty 53 | Name="StackSize" 54 | Visible=true 55 | Group="Behavior" 56 | InitialValue="0" 57 | Type="Integer" 58 | #tag EndViewProperty 59 | #tag ViewProperty 60 | Name="Super" 61 | Visible=true 62 | Group="ID" 63 | Type="String" 64 | EditorType="String" 65 | #tag EndViewProperty 66 | #tag EndViewBehavior 67 | End Class 68 | #tag EndClass 69 | -------------------------------------------------------------------------------- /Classes/XPlaneFolderItem.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class 2 | Protected Class XPlaneFolderItem 3 | Inherits FolderItem 4 | #tag Method, Flags = &h0 5 | Sub Constructor(folderItem as FolderItem) 6 | super.FolderItem(folderItem) 7 | 8 | // Get the Dictionary in which to store and retrieve preferences for this x-plane folder. 9 | pPreferencesDictionary = App.pPreferences.getXPlaneFolderDictionary(folderItem.absolutePath) 10 | 11 | // Parse the X-Plane apt.dat 12 | dim aptDatFolderItem as FolderItem = folderItem.child("Resources").child("default scenery").child("default apt dat").child("Earth nav data").child("apt.dat") 13 | dim aptDatParseThread as AptDatParseThread = new AptDatParseThread(me, aptDatFolderItem) 14 | aptDatParseThread.run() 15 | App.pPreferences.setAirportSearchEnabled(true) 16 | 17 | exception e as NilObjectException 18 | // If the aptDat structure is not correct, this will be thrown 19 | msgbox("Cannot locate X-Plane default apt.dat file, search by airport code will be disabled") 20 | App.pPreferences.setAirportSearchEnabled(false) 21 | 22 | End Sub 23 | #tag EndMethod 24 | 25 | #tag Method, Flags = &h0 26 | Sub deletePreferencesDictionary(containerKey as String, key as String) 27 | // Delete a dictionary from within a container dictionary in our preferences dictionary. 28 | dim containerDictionary as Dictionary = getPreferencesContainerDictionary(containerKey) 29 | 30 | if (containerDictionary.hasKey(key)) then containerDictionary.remove(key) 31 | 32 | End Sub 33 | #tag EndMethod 34 | 35 | #tag Method, Flags = &h0 36 | Function getPreferencesContainerDictionary(containerKey as String) As Dictionary 37 | // Get a dictionary from our preferences dictionary. 38 | if (not pPreferencesDictionary.hasKey(containerKey)) then pPreferencesDictionary.value(containerKey) = new Dictionary() 39 | return pPreferencesDictionary.value(containerKey) 40 | 41 | End Function 42 | #tag EndMethod 43 | 44 | #tag Method, Flags = &h0 45 | Function getPreferencesDictionary(containerKey as String, key as String) As Dictionary 46 | // Get a dictionary from within a container dictionary in our preferences dictionary. If either the 47 | // container dictionary or the individual dictionary within it don't exist, then create them. 48 | dim containerDictionary as Dictionary = getPreferencesContainerDictionary(containerKey) 49 | 50 | if (not containerDictionary.hasKey(key)) then containerDictionary.value(key) = new Dictionary() 51 | return containerDictionary.value(key) 52 | 53 | End Function 54 | #tag EndMethod 55 | 56 | 57 | #tag Property, Flags = &h0 58 | pAirportData As AirportDataSceneryObject 59 | #tag EndProperty 60 | 61 | #tag Property, Flags = &h21 62 | Private pPreferencesDictionary As Dictionary 63 | #tag EndProperty 64 | 65 | 66 | #tag ViewBehavior 67 | #tag ViewProperty 68 | Name="NativePath" 69 | Group="Behavior" 70 | Type="String" 71 | EditorType="MultiLineEditor" 72 | #tag EndViewProperty 73 | #tag ViewProperty 74 | Name="Length" 75 | Group="Behavior" 76 | Type="Uint64" 77 | #tag EndViewProperty 78 | #tag ViewProperty 79 | Name="AbsolutePath" 80 | Group="Behavior" 81 | Type="String" 82 | EditorType="MultiLineEditor" 83 | #tag EndViewProperty 84 | #tag ViewProperty 85 | Name="Alias" 86 | Group="Behavior" 87 | InitialValue="0" 88 | Type="Boolean" 89 | #tag EndViewProperty 90 | #tag ViewProperty 91 | Name="Count" 92 | Group="Behavior" 93 | InitialValue="0" 94 | Type="Integer" 95 | #tag EndViewProperty 96 | #tag ViewProperty 97 | Name="Directory" 98 | Group="Behavior" 99 | InitialValue="0" 100 | Type="Boolean" 101 | #tag EndViewProperty 102 | #tag ViewProperty 103 | Name="DisplayName" 104 | Group="Behavior" 105 | Type="String" 106 | EditorType="MultiLineEditor" 107 | #tag EndViewProperty 108 | #tag ViewProperty 109 | Name="Exists" 110 | Group="Behavior" 111 | InitialValue="0" 112 | Type="Boolean" 113 | #tag EndViewProperty 114 | #tag ViewProperty 115 | Name="ExtensionVisible" 116 | Group="Behavior" 117 | InitialValue="0" 118 | Type="Boolean" 119 | #tag EndViewProperty 120 | #tag ViewProperty 121 | Name="Group" 122 | Group="Behavior" 123 | Type="String" 124 | EditorType="MultiLineEditor" 125 | #tag EndViewProperty 126 | #tag ViewProperty 127 | Name="Index" 128 | Visible=true 129 | Group="ID" 130 | InitialValue="-2147483648" 131 | Type="Integer" 132 | #tag EndViewProperty 133 | #tag ViewProperty 134 | Name="IsReadable" 135 | Group="Behavior" 136 | InitialValue="0" 137 | Type="Boolean" 138 | #tag EndViewProperty 139 | #tag ViewProperty 140 | Name="IsWriteable" 141 | Group="Behavior" 142 | InitialValue="0" 143 | Type="Boolean" 144 | #tag EndViewProperty 145 | #tag ViewProperty 146 | Name="LastErrorCode" 147 | Group="Behavior" 148 | InitialValue="0" 149 | Type="Integer" 150 | #tag EndViewProperty 151 | #tag ViewProperty 152 | Name="Left" 153 | Visible=true 154 | Group="Position" 155 | InitialValue="0" 156 | Type="Integer" 157 | #tag EndViewProperty 158 | #tag ViewProperty 159 | Name="Locked" 160 | Group="Behavior" 161 | InitialValue="0" 162 | Type="Boolean" 163 | #tag EndViewProperty 164 | #tag ViewProperty 165 | Name="MacCreator" 166 | Group="Behavior" 167 | Type="String" 168 | EditorType="MultiLineEditor" 169 | #tag EndViewProperty 170 | #tag ViewProperty 171 | Name="MacDirID" 172 | Group="Behavior" 173 | InitialValue="0" 174 | Type="Integer" 175 | #tag EndViewProperty 176 | #tag ViewProperty 177 | Name="MacType" 178 | Group="Behavior" 179 | Type="String" 180 | EditorType="MultiLineEditor" 181 | #tag EndViewProperty 182 | #tag ViewProperty 183 | Name="MacVRefNum" 184 | Group="Behavior" 185 | InitialValue="0" 186 | Type="Integer" 187 | #tag EndViewProperty 188 | #tag ViewProperty 189 | Name="Name" 190 | Visible=true 191 | Group="ID" 192 | Type="String" 193 | #tag EndViewProperty 194 | #tag ViewProperty 195 | Name="Owner" 196 | Group="Behavior" 197 | Type="String" 198 | EditorType="MultiLineEditor" 199 | #tag EndViewProperty 200 | #tag ViewProperty 201 | Name="ResourceForkLength" 202 | Group="Behavior" 203 | InitialValue="0" 204 | Type="Integer" 205 | #tag EndViewProperty 206 | #tag ViewProperty 207 | Name="ShellPath" 208 | Group="Behavior" 209 | Type="String" 210 | EditorType="MultiLineEditor" 211 | #tag EndViewProperty 212 | #tag ViewProperty 213 | Name="Super" 214 | Visible=true 215 | Group="ID" 216 | Type="String" 217 | #tag EndViewProperty 218 | #tag ViewProperty 219 | Name="Top" 220 | Visible=true 221 | Group="Position" 222 | InitialValue="0" 223 | Type="Integer" 224 | #tag EndViewProperty 225 | #tag ViewProperty 226 | Name="Type" 227 | Group="Behavior" 228 | Type="String" 229 | EditorType="MultiLineEditor" 230 | #tag EndViewProperty 231 | #tag ViewProperty 232 | Name="URLPath" 233 | Group="Behavior" 234 | Type="String" 235 | EditorType="MultiLineEditor" 236 | #tag EndViewProperty 237 | #tag ViewProperty 238 | Name="Visible" 239 | Group="Behavior" 240 | InitialValue="0" 241 | Type="Boolean" 242 | #tag EndViewProperty 243 | #tag EndViewBehavior 244 | End Class 245 | #tag EndClass 246 | -------------------------------------------------------------------------------- /Databases/dbMain.rsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Databases/dbMain.rsd -------------------------------------------------------------------------------- /Databases/dbMain.xojo_code: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Databases/dbMain.xojo_code -------------------------------------------------------------------------------- /FileTypes1.xojo_filetypeset: -------------------------------------------------------------------------------- 1 | #tag FileTypeSet 2 | #tag FileType 3 | CodeName=ApplicationZip 4 | Extension=.zip 5 | Flags=&h0 6 | MacCreator=SITx 7 | MacType=ZIP 8 | Name=application/zip 9 | UTI= 10 | UTIConformsTo= 11 | Description= 12 | MimeType= 13 | Imported=True 14 | #tag EndFileType 15 | 16 | #tag EndFileTypeSet 17 | -------------------------------------------------------------------------------- /Images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/add.png -------------------------------------------------------------------------------- /Images/aircraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/aircraft.png -------------------------------------------------------------------------------- /Images/aircraft_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/aircraft_alpha.png -------------------------------------------------------------------------------- /Images/airports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/airports.png -------------------------------------------------------------------------------- /Images/circle_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/circle_alpha.png -------------------------------------------------------------------------------- /Images/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/delete.png -------------------------------------------------------------------------------- /Images/disk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/disk.png -------------------------------------------------------------------------------- /Images/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/folder.png -------------------------------------------------------------------------------- /Images/folder_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/folder_alpha.png -------------------------------------------------------------------------------- /Images/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/globe.png -------------------------------------------------------------------------------- /Images/globe_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/globe_alpha.png -------------------------------------------------------------------------------- /Images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/icon.png -------------------------------------------------------------------------------- /Images/information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/information.png -------------------------------------------------------------------------------- /Images/org_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/org_logo.png -------------------------------------------------------------------------------- /Images/plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/plugin.png -------------------------------------------------------------------------------- /Images/plugin_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/plugin_alpha.png -------------------------------------------------------------------------------- /Images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/warning.png -------------------------------------------------------------------------------- /Images/warning_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/warning_alpha.png -------------------------------------------------------------------------------- /Images/worldmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/worldmap.png -------------------------------------------------------------------------------- /Images/worldmap2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/Images/worldmap2.png -------------------------------------------------------------------------------- /Interfaces/AddonInterface.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Protected Interface AddonInterface 3 | #tag Method, Flags = &h0 4 | Sub expandListBoxEntry(listBox as ListBox, clickedRow as Integer) 5 | 6 | End Sub 7 | #tag EndMethod 8 | 9 | #tag Method, Flags = &h0 10 | Sub populateListBoxEntry(listBox as ListBox, addAsFolder as Boolean) 11 | 12 | End Sub 13 | #tag EndMethod 14 | 15 | 16 | #tag ViewBehavior 17 | #tag ViewProperty 18 | Name="Index" 19 | Visible=true 20 | Group="ID" 21 | InitialValue="2147483648" 22 | Type="Integer" 23 | #tag EndViewProperty 24 | #tag ViewProperty 25 | Name="Left" 26 | Visible=true 27 | Group="Position" 28 | InitialValue="0" 29 | Type="Integer" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Name" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Super" 39 | Visible=true 40 | Group="ID" 41 | Type="String" 42 | #tag EndViewProperty 43 | #tag ViewProperty 44 | Name="Top" 45 | Visible=true 46 | Group="Position" 47 | InitialValue="0" 48 | Type="Integer" 49 | #tag EndViewProperty 50 | #tag EndViewBehavior 51 | End Interface 52 | #tag EndInterface 53 | -------------------------------------------------------------------------------- /Interfaces/FolderTraversalCallbackInterface.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface 2 | Protected Interface FolderTraversalCallbackInterface 3 | #tag Method, Flags = &h0 4 | Sub folderTraversalCallback(folderItem as FolderItem, data as variant) 5 | 6 | End Sub 7 | #tag EndMethod 8 | 9 | 10 | #tag ViewBehavior 11 | #tag ViewProperty 12 | Name="Index" 13 | Visible=true 14 | Group="ID" 15 | InitialValue="-2147483648" 16 | Type="Integer" 17 | #tag EndViewProperty 18 | #tag ViewProperty 19 | Name="Left" 20 | Visible=true 21 | Group="Position" 22 | InitialValue="0" 23 | Type="Integer" 24 | #tag EndViewProperty 25 | #tag ViewProperty 26 | Name="Name" 27 | Visible=true 28 | Group="ID" 29 | Type="String" 30 | #tag EndViewProperty 31 | #tag ViewProperty 32 | Name="Super" 33 | Visible=true 34 | Group="ID" 35 | Type="String" 36 | #tag EndViewProperty 37 | #tag ViewProperty 38 | Name="Top" 39 | Visible=true 40 | Group="Position" 41 | InitialValue="0" 42 | Type="Integer" 43 | #tag EndViewProperty 44 | #tag EndViewBehavior 45 | End Interface 46 | #tag EndInterface 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Austin Goudge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MenuBar1.xojo_menu: -------------------------------------------------------------------------------- 1 | #tag Menu 2 | Begin Menu MenuBar1 3 | Begin MenuItem FileMenu 4 | SpecialMenu = 0 5 | Text = "#App.kFile" 6 | Index = -2147483648 7 | AutoEnable = True 8 | Visible = True 9 | Begin MenuItem FileClose 10 | SpecialMenu = 0 11 | Text = "&Close" 12 | Index = -2147483648 13 | ShortcutKey = "W" 14 | Shortcut = "Cmd+W" 15 | MenuModifier = True 16 | AutoEnable = True 17 | Visible = True 18 | End 19 | Begin MenuItem UntitledSeparator 20 | SpecialMenu = 0 21 | Text = "-" 22 | Index = -2147483648 23 | AutoEnable = True 24 | Visible = True 25 | End 26 | Begin QuitMenuItem FileQuit 27 | SpecialMenu = 0 28 | Text = "#App.kFileQuit" 29 | Index = -2147483648 30 | ShortcutKey = "#App.kFileQuitShortcut" 31 | Shortcut = "#App.kFileQuitShortcut" 32 | AutoEnable = True 33 | Visible = True 34 | End 35 | End 36 | Begin MenuItem EditMenu 37 | SpecialMenu = 0 38 | Text = "#App.kEdit" 39 | Index = -2147483648 40 | AutoEnable = True 41 | Visible = True 42 | Begin MenuItem EditUndo 43 | SpecialMenu = 0 44 | Text = "#App.kEditUndo" 45 | Index = -2147483648 46 | ShortcutKey = "Z" 47 | Shortcut = "Cmd+Z" 48 | MenuModifier = True 49 | AutoEnable = True 50 | Visible = True 51 | End 52 | Begin MenuItem UntitledMenu1 53 | SpecialMenu = 0 54 | Text = "-" 55 | Index = -2147483648 56 | AutoEnable = True 57 | Visible = True 58 | End 59 | Begin MenuItem EditCut 60 | SpecialMenu = 0 61 | Text = "#App.kEditCut" 62 | Index = -2147483648 63 | ShortcutKey = "X" 64 | Shortcut = "Cmd+X" 65 | MenuModifier = True 66 | AutoEnable = True 67 | Visible = True 68 | End 69 | Begin MenuItem EditCopy 70 | SpecialMenu = 0 71 | Text = "#App.kEditCopy" 72 | Index = -2147483648 73 | ShortcutKey = "C" 74 | Shortcut = "Cmd+C" 75 | MenuModifier = True 76 | AutoEnable = True 77 | Visible = True 78 | End 79 | Begin MenuItem EditPaste 80 | SpecialMenu = 0 81 | Text = "#App.kEditPaste" 82 | Index = -2147483648 83 | ShortcutKey = "V" 84 | Shortcut = "Cmd+V" 85 | MenuModifier = True 86 | AutoEnable = True 87 | Visible = True 88 | End 89 | Begin MenuItem EditClear 90 | SpecialMenu = 0 91 | Text = "#App.kEditClear" 92 | Index = -2147483648 93 | AutoEnable = True 94 | Visible = True 95 | End 96 | Begin MenuItem UntitledMenu0 97 | SpecialMenu = 0 98 | Text = "-" 99 | Index = -2147483648 100 | AutoEnable = True 101 | Visible = True 102 | End 103 | Begin MenuItem EditSelectAll 104 | SpecialMenu = 0 105 | Text = "#App.kEditSelectAll" 106 | Index = -2147483648 107 | ShortcutKey = "A" 108 | Shortcut = "Cmd+A" 109 | MenuModifier = True 110 | AutoEnable = True 111 | Visible = True 112 | End 113 | Begin MenuItem UntitledSeparator0 114 | SpecialMenu = 0 115 | Text = "-" 116 | Index = -2147483648 117 | AutoEnable = True 118 | Visible = True 119 | End 120 | Begin PrefsMenuItem FilePreferences 121 | SpecialMenu = 0 122 | Text = "#App.kEditPreferences" 123 | Index = -2147483648 124 | ShortcutKey = "," 125 | Shortcut = "Cmd+," 126 | MenuModifier = True 127 | AutoEnable = True 128 | Visible = True 129 | End 130 | End 131 | Begin MenuItem ViewMenu 132 | SpecialMenu = 0 133 | Text = "View" 134 | Index = -2147483648 135 | AutoEnable = True 136 | Visible = True 137 | Begin MenuItem PlotNoneItem 138 | SpecialMenu = 0 139 | Text = "#App.kViewPlotNone" 140 | Index = -2147483648 141 | ShortcutKey = "n" 142 | Shortcut = "Cmd+Shift+n" 143 | MenuModifier = True 144 | AltMenuModifier = True 145 | AutoEnable = True 146 | Visible = True 147 | End 148 | Begin MenuItem PlotAllItem 149 | SpecialMenu = 0 150 | Text = "#App.kViewPlotAll" 151 | Index = -2147483648 152 | ShortcutKey = "a" 153 | Shortcut = "Cmd+Shift+a" 154 | MenuModifier = True 155 | AltMenuModifier = True 156 | AutoEnable = True 157 | Visible = True 158 | End 159 | Begin MenuItem PlotAirportsItem 160 | SpecialMenu = 0 161 | Text = "#App.kViewPlotAirports" 162 | Index = -2147483648 163 | ShortcutKey = "p" 164 | Shortcut = "Cmd+Shift+p" 165 | MenuModifier = True 166 | AltMenuModifier = True 167 | AutoEnable = True 168 | Visible = True 169 | End 170 | Begin MenuItem PlotSceneryItem 171 | SpecialMenu = 0 172 | Text = "#App.kViewPlotScenery" 173 | Index = -2147483648 174 | ShortcutKey = "s" 175 | Shortcut = "Cmd+Shift+s" 176 | MenuModifier = True 177 | AltMenuModifier = True 178 | AutoEnable = True 179 | Visible = True 180 | End 181 | End 182 | Begin MenuItem HelpMenu 183 | SpecialMenu = 0 184 | Text = "#App.kHelp" 185 | Index = -2147483648 186 | AutoEnable = True 187 | Visible = True 188 | Begin AppleMenuItem HelpAbout 189 | SpecialMenu = 0 190 | Text = "#App.kHelpAbout" 191 | Index = -2147483648 192 | AutoEnable = True 193 | Visible = True 194 | End 195 | Begin AppleMenuItem HelpAboutSeparator 196 | SpecialMenu = 0 197 | Text = "-" 198 | Index = -2147483648 199 | AutoEnable = True 200 | Visible = True 201 | End 202 | Begin MenuItem HelpUserGuide 203 | SpecialMenu = 0 204 | Text = "#App.kHelpUserGuide" 205 | Index = -2147483648 206 | AutoEnable = True 207 | Visible = True 208 | End 209 | End 210 | End 211 | #tag EndMenu 212 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XAddonManager 2 | The [X-Plane Flight Simulator](http://www.x-plane.com) supports three main types of addons developed by users: Custom Scenery, Aircraft and Plugins. This application is designed for both regular X-Plane flight simmers to manage their Addons and for developers to easily enable and disable Addons while testing. 3 | 4 | The program displays all your Custom Scenery Packages, Plugins and Aircraft, as well as your CSLs for flying online. 5 | 6 | **Custom Scenery Packages** are plotted on a world map for quick reference, you can click on the map to find the closest installed scenery package to where you clicked. The program tells you whether each package contains a library, Earth scenery, Mars scenery and airports. 7 | 8 | **Plugins** are simply listed, allowing easy enabling and disabling 9 | 10 | **Aircraft** are listed and the program tells you whether each has a 3d cockpit, airfoils, sounds, weapons, plugins and whether the aircraft is Goodway enabled. If an aircraft has an icon, this is also displayed. 11 | 12 | **CSLs** are simply listed, allowing easy enabling and disabling 13 | 14 | The program allows very easy installation of all types of addon - just download the zip file containing the Scenery Package, Plugin, Aircraft or CSL, click 'Install ...' and choose the zip file. XAddonManager does the rest. 15 | 16 | Full documentation is available in the [User Guide](https://github.com/aussig/XAddonManager/wiki/XAddonManager-User-Guide) 17 | -------------------------------------------------------------------------------- /VersionInfo/devreleasenotes.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |Release notes not currently available
" 210 | end if 211 | 212 | // Must create a temporary *file* to pass to the loadPage method. Only required for Macs. 213 | dim f as FolderItem = getTemporaryFolderItem() 214 | htmlReleaseNotes.LoadPage(html, f) 215 | 216 | 217 | End Sub 218 | #tag EndEvent 219 | #tag EndEvents 220 | -------------------------------------------------------------------------------- /Windows/wndPreferences.xojo_window: -------------------------------------------------------------------------------- 1 | #tag Window 2 | Begin Window wndPreferences 3 | BackColor = &cFFFFFF00 4 | Backdrop = 0 5 | CloseButton = True 6 | Compatibility = "" 7 | Composite = False 8 | Frame = 0 9 | FullScreen = False 10 | FullScreenButton= False 11 | HasBackColor = False 12 | Height = 139 13 | ImplicitInstance= True 14 | LiveResize = True 15 | MacProcID = 0 16 | MaxHeight = 32000 17 | MaximizeButton = False 18 | MaxWidth = 32000 19 | MenuBar = 0 20 | MenuBarVisible = True 21 | MinHeight = 64 22 | MinimizeButton = True 23 | MinWidth = 64 24 | Placement = 0 25 | Resizeable = True 26 | Title = "#kWindowTitle" 27 | Visible = True 28 | Width = 351 29 | Begin GroupBox GroupBox1 30 | AutoDeactivate = True 31 | Bold = False 32 | Caption = "X-Plane.org" 33 | Enabled = True 34 | Height = 73 35 | HelpTag = "" 36 | Index = -2147483648 37 | InitialParent = "" 38 | Italic = False 39 | Left = 20 40 | LockBottom = True 41 | LockedInPosition= False 42 | LockLeft = True 43 | LockRight = True 44 | LockTop = True 45 | Scope = 0 46 | TabIndex = 7 47 | TabPanelIndex = 0 48 | TabStop = True 49 | TextFont = "System" 50 | TextSize = 0.0 51 | TextUnit = 0 52 | Top = 14 53 | Transparent = True 54 | Underline = False 55 | Visible = True 56 | Width = 311 57 | Begin TextField txtUsername 58 | AcceptTabs = False 59 | Alignment = 0 60 | AutoDeactivate = True 61 | AutomaticallyCheckSpelling= False 62 | BackColor = &cFFFFFF 63 | Bold = False 64 | Border = True 65 | CueText = "" 66 | DataField = "" 67 | DataSource = "" 68 | Enabled = True 69 | Format = "" 70 | Height = 22 71 | HelpTag = "" 72 | Index = -2147483648 73 | InitialParent = "GroupBox1" 74 | Italic = False 75 | Left = 158 76 | LimitText = 0 77 | LockBottom = False 78 | LockedInPosition= False 79 | LockLeft = True 80 | LockRight = False 81 | LockTop = True 82 | Mask = "" 83 | Password = False 84 | ReadOnly = False 85 | Scope = 0 86 | TabIndex = 3 87 | TabPanelIndex = 0 88 | TabStop = True 89 | Text = "aussi" 90 | TextColor = &c000000 91 | TextFont = "System" 92 | TextSize = 0.0 93 | TextUnit = 0 94 | Top = 48 95 | Transparent = True 96 | Underline = False 97 | UseFocusRing = True 98 | Visible = True 99 | Width = 139 100 | End 101 | Begin Label StaticText4 102 | AutoDeactivate = True 103 | Bold = False 104 | DataField = "" 105 | DataSource = "" 106 | Enabled = True 107 | Height = 21 108 | HelpTag = "" 109 | Index = -2147483648 110 | InitialParent = "GroupBox1" 111 | Italic = False 112 | Left = 27 113 | LockBottom = False 114 | LockedInPosition= False 115 | LockLeft = True 116 | LockRight = False 117 | LockTop = True 118 | Multiline = False 119 | Scope = 0 120 | Selectable = False 121 | TabIndex = 4 122 | TabPanelIndex = 0 123 | TabStop = True 124 | Text = "#App.kUserName" 125 | TextAlign = 2 126 | TextColor = &c000000 127 | TextFont = "System" 128 | TextSize = 0.0 129 | TextUnit = 0 130 | Top = 49 131 | Transparent = False 132 | Underline = False 133 | Visible = True 134 | Width = 119 135 | End 136 | End 137 | Begin PushButton btnOk 138 | AutoDeactivate = True 139 | Bold = False 140 | ButtonStyle = "0" 141 | Cancel = False 142 | Caption = "#App.kOk" 143 | Default = True 144 | Enabled = True 145 | Height = 20 146 | HelpTag = "" 147 | Index = -2147483648 148 | InitialParent = "" 149 | Italic = False 150 | Left = 251 151 | LockBottom = True 152 | LockedInPosition= False 153 | LockLeft = False 154 | LockRight = True 155 | LockTop = False 156 | Scope = 0 157 | TabIndex = 6 158 | TabPanelIndex = 0 159 | TabStop = True 160 | TextFont = "System" 161 | TextSize = 0.0 162 | TextUnit = 0 163 | Top = 99 164 | Transparent = True 165 | Underline = False 166 | Visible = True 167 | Width = 80 168 | End 169 | Begin PushButton btnCancel 170 | AutoDeactivate = True 171 | Bold = False 172 | ButtonStyle = "0" 173 | Cancel = True 174 | Caption = "#App.kCancel" 175 | Default = False 176 | Enabled = True 177 | Height = 20 178 | HelpTag = "" 179 | Index = -2147483648 180 | InitialParent = "" 181 | Italic = False 182 | Left = 159 183 | LockBottom = True 184 | LockedInPosition= False 185 | LockLeft = False 186 | LockRight = True 187 | LockTop = False 188 | Scope = 0 189 | TabIndex = 8 190 | TabPanelIndex = 0 191 | TabStop = True 192 | TextFont = "System" 193 | TextSize = 0.0 194 | TextUnit = 0 195 | Top = 99 196 | Transparent = True 197 | Underline = False 198 | Visible = True 199 | Width = 80 200 | End 201 | End 202 | #tag EndWindow 203 | 204 | #tag WindowCode 205 | #tag Event 206 | Sub Open() 207 | dim parameters() as string = array(App.kApplicationName) 208 | me.title = App.processParameterizedString(kWindowTitle, parameters) 209 | End Sub 210 | #tag EndEvent 211 | 212 | 213 | #tag Constant, Name = kWindowTitle, Type = String, Dynamic = True, Default = \"${1} Preferences", Scope = Public 214 | #tag EndConstant 215 | 216 | 217 | #tag EndWindowCode 218 | 219 | #tag Events btnOk 220 | #tag Event 221 | Sub Action() 222 | 'if (chkRememberLogin.value) then 223 | 'dim salt as string = "antidisestablishmentarianism:-)" 224 | 'dim encryptedPassword as string = eCryptEncode(Encrypt(txtPassword.text + salt, "wibble", 0), 0, 255) 225 | ' 226 | 'msgBox(encryptedPassword) 227 | 'msgbox(Decrypt(eCryptDecode(encryptedPassword, 0, 255), "wibble", 0)) 228 | 'end if 229 | 230 | wndPreferences.close() 231 | End Sub 232 | #tag EndEvent 233 | #tag EndEvents 234 | #tag Events btnCancel 235 | #tag Event 236 | Sub Action() 237 | wndPreferences.close() 238 | End Sub 239 | #tag EndEvent 240 | #tag EndEvents 241 | -------------------------------------------------------------------------------- /XAddonManager.xojo_resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aussig/XAddonManager/a97c7361a21c42b38af201cd8920e6bd89b82c9d/XAddonManager.xojo_resources -------------------------------------------------------------------------------- /ZipPackage/3rdParty/clsCRC16.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class clsCRC16 #tag Method, Flags = &h0 Shared Function CCITT(mb as MemoryBlock, ofs as Integer, len as Integer) As UInt16 if mCCITT = nil then mCCITT = new clsCRC16 (&h1021) end if return mCCITT.CRC16 (mb.StringValue(ofs,len), 0, false, false, 0) End Function #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(intPolynomial as UInt16) table (intPolynomial) End Sub #tag EndMethod #tag Method, Flags = &h0 Function CRC16(strData as string, intInit as UInt16, blnRefin as boolean, blnRefout as boolean, intXORout as UInt16) As UInt16 dim intIndex as integer dim intLoop as integer dim intLen as integer dim intRCrc as integer dim strChars() as string intLen = lenb(strData) if blnRefin = true then strChars = splitb(strData, "") strData = "" for intLoop = 0 to intLen - 1 strData = strData + chrb(val("&b" + reflect(bin(ascb(strChars(intLoop))), 8))) next intLoop end if for intLoop = 1 to intLen intIndex = ((intInit \ 256) xor ascb(midb(strData, intLoop, 1))) and &hff intInit = crc16table(intIndex) xor (intInit * 256) intInit = intInit and &hffff next intLoop if blnRefout = false then return intInit xor intXorout else intRCrc = val("&b" + reflect(bin(intInit), 16)) return intRCrc xor intXorout end if End Function #tag EndMethod #tag Method, Flags = &h21 Private Function fill(strChr as string, intAmount as integer) As string dim intLoop as integer dim strOut as string for intLoop = 1 to intAmount strOut = strOut + strChr next intLoop return strOut End Function #tag EndMethod #tag Method, Flags = &h21 Private Function reflect(strBinary as string, intBits as integer) As string dim intLen as integer dim intLoop as integer dim strOut as string intLen = lenb(strBinary) strBinary = leftb(fill("0", intBits - 1), intBits - intLen) + strBinary for intLoop = 1 to intBits strOut = strOut + leftb(rightb(strBinary, intLoop), 1) next intLoop return strOut End Function #tag EndMethod #tag Method, Flags = &h21 Private Sub table(intPolynomial as Int32) dim intCrc as Int32 dim intTemp as Int32 for intLoop1 as integer = 0 to 255 intCrc = intLoop1 * 256 for intLoop2 as integer = 0 to 7 if ((intCrc and &h8000) > 0) then intTemp = intPolynomial else intTemp = 0 end if intCrc = (intCrc * 2) xor (intTemp) next intLoop2 crc16table(intLoop1) = intCrc and &hffff next intLoop1 End Sub #tag EndMethod #tag Note, Name = About CRC-16 Checksum adapation for REALbasic written by Eric D. Brown improved by Thomas Tempelmann See "CRC16 Catalogue" for possible checksum calls. ----------------------------------------------------------- CODE EXAMPLE: dim checksum as new clsCrc16 dim intCrc as integer dim strData as string strData = "123456789" intCrc = checksum.crc16(strData, &h8005, &h0, true, true, &h0) statictext1.text = left("000", 4 - len(hex(str(intCrc)))) + hex(str(intCrc)) //displays the CRC in 16-bit HEX (ie. 00FF) ----------------------------------------------------------- #tag EndNote #tag Note, Name = CRC16 Catalogue Name: ARC Alias(es): CRC-16; CRC-IBM; CRC-16/ARC; CRC-16/LHA Call: crc16({strData}, &h8005, &h0, true, true, &h0) Notes: N/A Name: CRC-16/AUG-2-CCITT Alias(es): CRC-16/SPI-FUJITSU Call: crc16({strData}, &h1021, &h84c0, false, false, &h0) Notes: Init value given as 0x1D0F but this is an augment prepended to the message. Not necessarily the algorithm used in FlexRay communications. Name: CRC-16/AUG-CCITT Alias(es): N/A Call: crc16({strData}, &h1021, &h1d0f, false, false, &h0) Notes: Init value is equivalent to an augment of 0xFFFF prepended to the message. Name: CRC-16/BT-CHIP Alias(es): N/A Call: crc16({strData}, &h1021, &hffff, true, false, &h0) Notes: Used to talk to an unidentified Bluetooth transceiver. Not necessarily the algorithm used in Bluetooth communications. For implementations that take a single Reflect parameter, specify True and manually reflect the result. Name: CRC-16/BUYPASS Alias(es): N/A Call: crc16({strData}, &h8005, &h0, false, false, &h0) Notes: Reported for the multi-threaded portion of the Buypass transaction processing network. Name: CRC-16/CCITT Alias(es): CRC-16/CITT; CRC-CCITT Call: crc16({strData}, &h1021, &hffff, false, false, &h0) Notes: For the ITU-T algorithm see X.25. Not the true CCITT algorithm according to Numeric Recipes, see KERMIT. Name: CRC-16/DNP Alias(es): N/A Call: crc16({strData}, &h3d65, &h0, true, true, &hffff) Notes: N/A Name: CRC-16/EN-13757 Alias(es): N/A Call: crc16({strData}, &h3d65, &h0, false, false, &hffff) Notes: N/A Name: CRC-16/I-CODE Alias(es): N/A Call: crc16({strData}, &h1021, &hffff, false, false, &hffff) Notes: Presented high byte first. Remainder = 0x1D0F Name: CRC-16/MCRF4XX Alias(es): N/A Call: crc16({strData}, &h1021, &hffff, true, true, &h0) Notes: Nibble oriented. For byte wide algorithms swap nibbles of each byte. CRC presented low nibble first. Name: CRC-16/USB Alias(es): N/A Call: crc16({strData}, &h8005, &hffff, true, true, &hffff) Notes: CRC appended low byte first. Remainder = 0x800D. Name: KERMIT Alias(es): CRC-16/CCITT-TRUE crc16({strData}, &h1021, &hffff, false, false, &h0) Call: crc16({strData}, &h1021, &h0, true, true, &h0) Notes: 'Same as' the CCITT algorithm according to Numeric Recipes. Name: MODBUS Alias(es): N/A Call: crc16({strData}, &h8005, &hffff, true, true, &h0) Notes: CRC presented low byte first. Name: X-25 Alias(es): CRC-16/IBM-SDLC; CRC-16/ISO-HDLC Call: crc16({strData}, &h1021, &hffff, true, true, &hffff) Notes: Remainder = 0xF0B8. Name: XMODEM Alias(es): ZMODEM; CRC-16/ACORN Call: crc16({strData}, &h1021, &h0, false, false, &h0) Notes: CRC presented MSB first. Remainder = 0x0000. Used in the MultiMediaCard interface. #tag EndNote #tag Property, Flags = &h21 Private crc16table(255) As int32 #tag EndProperty #tag Property, Flags = &h21 Private Shared mCCITT As clsCRC16 #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/RemoveWhenUsingEinhugurPlugin/IStreamReader.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface Protected Interface IStreamReader #tag Method, Flags = &h0 Function Read(amount as Integer) As String End Function #tag EndMethod #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Interface #tag EndInterface -------------------------------------------------------------------------------- /ZipPackage/RemoveWhenUsingEinhugurPlugin/IStreamWriter.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface Protected Interface IStreamWriter #tag Method, Flags = &h0 Sub Write(data as String) End Sub #tag EndMethod #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Interface #tag EndInterface -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/FileReader.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class FileReader Implements SeqDataInputStream #tag Method, Flags = &h0 Sub ClearError() me.error = false End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Close() if me.bs <> nil then me.bs.Close me.bs = nil end End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(f as FolderItem) // Constructor. // Pass a FolderItem to designate the file the stream should read from me.f = f End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() me.Close End Sub #tag EndMethod #tag Method, Flags = &h0 Function EOF() As Boolean return me.bs = nil or me.bs.EOF End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) if me.error then code = -1 msg = "open or read error" else code = 0 msg = "" end End Sub #tag EndMethod #tag Method, Flags = &h0 Function HadError() As Boolean return me.error End Function #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean if me.bs <> nil then return true end #if RBVersion >= 2012 me.bs = BinaryStream.Open(f, false) #else me.bs = f.OpenAsBinaryFile(false) #endif me.error = me.bs = nil return not me.error End Function #tag EndMethod #tag Method, Flags = &h0 Function Read(count As Integer) As String if me.bs = nil then raise new RuntimeException // did you forget to call Open()? end return me.bs.Read(count) End Function #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean dim newpos, pos, len as UInt64 if me.bs = nil then raise new RuntimeException // did you forget to call Open()? end pos = me.bs.Position len = me.bs.Length newpos = pos + count if newpos > len then // wants to skip more than available return false end me.bs.Position = newpos if me.bs.Position <> newpos then me.error = true end return not me.error End Function #tag EndMethod #tag Property, Flags = &h1 Protected bs As BinaryStream #tag EndProperty #tag Property, Flags = &h1 Protected error As Boolean #tag EndProperty #tag Property, Flags = &h1 Protected f As FolderItem #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/FileWriter.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class FileWriter Implements SeqDataOutputStream #tag Method, Flags = &h0 Sub ClearError() me.error = false End Sub #tag EndMethod #tag Method, Flags = &h0 Function Close() As Boolean if me.bs = nil then return true end if me.bs.Length <> me.written then if me.bs.Length <> mPreAllocated then me.error = true end if me.bs.Length = me.written end me.bs.Close me.bs = nil return not me.error End Function #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(f as FolderItem) // Constructor. // Pass a FolderItem to designate the file the stream should write to me.f = f End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() if me.Close then end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Flush() As Boolean if me.bs = nil then raise new RuntimeException // did you forget to call Open()? end bs.Flush if me.bs.Length <> me.written then me.error = true end return not me.error End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) if me.error then code = -1 msg = "open or write error" else code = 0 msg = "" end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean if me.bs <> nil then return true end if not f.exists then #if RBVersion >= 2012 me.bs = BinaryStream.Create(f) #else me.bs = f.CreateBinaryFile("") #endif else #if RBVersion >= 2012 me.bs = BinaryStream.Open(f, true) #else me.bs = f.OpenAsBinaryFile(true) #endif end if me.bs <> nil then me.bs.Length = 0 end me.error = (me.bs = nil) or (me.bs.Length > 0) return not me.error End Function #tag EndMethod #tag Method, Flags = &h0 Sub PreAllocate(count as UInt64) if me.bs = nil or count < 0 then raise new RuntimeException // did you forget to call Open()? end mPreAllocated = count if me.bs.Length < count then me.bs.Length = count end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean if me.bs = nil then raise new RuntimeException // did you forget to call Open()? end me.written = me.written + count if me.bs.Length < me.written then me.bs.Length = me.written end return true End Function #tag EndMethod #tag Method, Flags = &h0 Function Write(data As String) As Boolean if me.bs = nil then raise new RuntimeException // did you forget to call Open()? end me.written = me.written + LenB(data) me.bs.Write data return true End Function #tag EndMethod #tag Property, Flags = &h1 Protected bs As BinaryStream #tag EndProperty #tag Property, Flags = &h1 Protected error As Boolean #tag EndProperty #tag Property, Flags = &h1 Protected f As FolderItem #tag EndProperty #tag Property, Flags = &h21 Private mPreAllocated As Int64 #tag EndProperty #tag Property, Flags = &h1 Protected written As UInt64 #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/RsrcForkReader.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class RsrcForkReader Implements SeqDataInputStream #tag Method, Flags = &h21 Private Function addPtr(mb as MemoryBlock, ofs as Integer) As MemoryBlock dim helper as new MemoryBlock(8) helper.Ptr(0) = mb #if Target64Bit helper.UInt64Value(0) = helper.UInt64Value(0)+ofs #else helper.UInt32Value(0) = helper.UInt32Value(0)+ofs #endif return helper.Ptr(0) End Function #tag EndMethod #tag Method, Flags = &h0 Sub ClearError() me.errCode = 0 End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Close() #if TargetMacOS dim res as Integer Declare Function FSCloseFork Lib CarbonLibName (refNum as Integer) as Integer if me.refnum <> 0 then res = FSCloseFork(me.refnum) // we can quite safely ignore the result me.refnum = 0 end #endif End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(f as FolderItem) me.f = f End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() me.Close End Sub #tag EndMethod #tag Method, Flags = &h0 Function EOF() As Boolean return me.bytesRead >= me.length or me.refnum = 0 End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) code = me.errCode if me.errCode <> 0 then msg = "open or read error ("+Str(me.errCode)+")" else msg = "" end End Sub #tag EndMethod #tag Method, Flags = &h0 Function HadError() As Boolean return me.errCode <> 0 End Function #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean #if TargetMacOS Declare Sub FSGetResourceForkName Lib CarbonLibName (resourceForkName as Ptr) Declare Function FSOpenFork Lib CarbonLibName (FSRef as Ptr, forkNameLength as Integer, forkName as Ptr, permissions as Byte, ByRef forkRefNum as Int16) as Integer Declare Function FSCloseFork Lib CarbonLibName (refNum as Integer) as Integer declare function FSGetForkSize Lib CarbonLibName (forkRefNum as Integer, ByRef v as Int64) as Integer if me.refnum <> 0 then return true end me.ClearError me.refnum = 0 me.length = 0 me.bytesRead = 0 dim rsrcName as new MemoryBlock(512) FSGetResourceForkName (rsrcName) dim res as Integer dim fsref as MemoryBlock fsref = TTsFolderItem.FSRefOfFolderItem (f) if fsref <> nil then dim fileRef as Int16 res = FSOpenFork(fsref, rsrcName.Int16Value(0), addPtr(rsrcName,2), 0, fileRef) if res = 0 then dim len as Int64 res = FSGetForkSize (fileRef, len) if res = 0 then me.length = len me.refnum = fileRef return true end res = FSCloseFork(fileRef) end end me.errCode = res return false #endif End Function #tag EndMethod #tag Method, Flags = &h0 Function Read(count As Integer) As String #if TargetMacOS dim res, act, req as Integer dim mb as MemoryBlock declare function FSReadFork Lib CarbonLibName (forkRefNum as Integer, positionMode as Integer, positionOffset as Int64, requestCount as Integer, buffer as Ptr, ByRef actualCount as Integer) as Integer const fsAtMark = 0 const fsFromStart = 1 const fsFromLEOF = 2 const fsFromMark = 3 // don't read if there has been an error before if me.errCode <> 0 then return "" end if me.refnum = 0 then raise new RuntimeException // did you forget to call Open()? end // make sure we do not read more than what's left in the file req = count if me.bytesRead + req > me.length then req = me.length - me.bytesRead end if req <= 0 then return "" // EOF -- we've reached the end of file end mb = new MemoryBlock(req) // a buffer to read the data into temporarily if mb = nil then raise new OutOfMemoryException end mb.LittleEndian = false res = FSReadFork (me.refnum, fsFromMark, 0, req, mb, act) if res = 0 and act <> req then res = -1 // something went very wrong here, maybe due to a bug in this class end if res < 0 then me.errCode = res return "" end me.bytesRead = me.bytesRead + act return mb.StringValue(0,act) #endif End Function #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean #if TargetMacOS dim res, req as Integer declare function FSSetForkPosition Lib CarbonLibName (forkRefNum as Integer, positionMode as Integer, positionOffset as Int64) as Integer // don't continue if there has been an error before if me.errCode <> 0 then return false end if me.refnum = 0 then raise new RuntimeException // did you forget to call Open()? end // make sure we do not get behind the end of file req = count if me.bytesRead + req > me.length then // we would be behind the EOF - seek to EOF and return as failure res = FSSetForkPosition(me.refnum, 1, me.length) // seeks from start of file me.bytesRead = me.length return false end me.bytesRead = me.bytesRead + req res = FSSetForkPosition(me.refnum, 1, me.bytesRead) // seeks from start of file if res < 0 then me.errCode = res return false end return true #endif End Function #tag EndMethod #tag Property, Flags = &h1 Protected bytesRead As Integer #tag EndProperty #tag Property, Flags = &h1 Protected errCode As Integer #tag EndProperty #tag Property, Flags = &h1 Protected f As FolderItem #tag EndProperty #tag Property, Flags = &h1 Protected length As Integer #tag EndProperty #tag Property, Flags = &h1 Protected refnum As Integer #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/RsrcForkWriter.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class RsrcForkWriter Implements SeqDataOutputStream #tag Method, Flags = &h21 Private Function addPtr(mb as MemoryBlock, ofs as Integer) As MemoryBlock dim helper as new MemoryBlock(8) helper.Ptr(0) = mb #if Target64Bit helper.UInt64Value(0) = helper.UInt64Value(0)+ofs #else helper.UInt32Value(0) = helper.UInt32Value(0)+ofs #endif return helper.Ptr(0) End Function #tag EndMethod #tag Method, Flags = &h0 Sub ClearError() me.errCode = 0 End Sub #tag EndMethod #tag Method, Flags = &h0 Function Close() As Boolean #if TargetMacOS dim res as Integer Declare Function FSCloseFork Lib CarbonLibName (refNum as Integer) as Integer if me.refnum <> 0 then res = FSCloseFork(me.refnum) me.refnum = 0 end return me.errCode = 0 and res = 0 #endif End Function #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(f as FolderItem) me.f = f End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() if me.Close then end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Flush() As Boolean if me.refnum = 0 then raise new RuntimeException // did you forget to call Open()? end return me.errCode = 0 End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) code = me.errCode if me.errCode <> 0 then msg = "open or write error" else msg = "" end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean #if TargetMacOS Declare Sub FSGetResourceForkName Lib CarbonLibName (resourceForkName as Ptr) Declare Function FSOpenFork Lib CarbonLibName (FSRef as Ptr, forkNameLength as Integer, forkName as Ptr, permissions as Byte, ByRef forkRefNum as Int16) as Integer Declare Function FSCloseFork Lib CarbonLibName (refNum as Integer) as Integer declare function FSSetForkSize Lib CarbonLibName (forkRefNum as Integer, posMode as Integer, v as Int64) as Integer const fsAtMark = 0 const fsFromStart = 1 const fsFromLEOF = 2 const fsFromMark = 3 if me.refnum <> 0 then return true end me.ClearError me.refnum = 0 dim rsrcName as new MemoryBlock(512) FSGetResourceForkName (rsrcName) dim res as Integer dim fsref as MemoryBlock fsref = TTsFolderItem.FSRefOfFolderItem (f) if fsref <> nil then dim fileRef as Int16 res = FSOpenFork(fsref, rsrcName.Int16Value(0), addPtr(rsrcName,2), 0, fileRef) if res = 0 then res = FSSetForkSize(fileRef, fsFromStart, 0) if res = 0 then me.refnum = fileRef return true end res = FSCloseFork(fileRef) end end me.errCode = res return false #endif End Function #tag EndMethod #tag Method, Flags = &h0 Sub PreAllocate(count as UInt64) // here we could pre-allocate the length of the file #pragma unused count End Sub #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean #if TargetMacOS dim res as Integer, pos as Int64 declare function FSSetForkPosition Lib CarbonLibName (forkRefNum as Integer, positionMode as Integer, positionOffset as Int64) as Integer declare function FSGetForkPosition Lib CarbonLibName (forkRefNum as Integer, ByRef positionOffset as Int64) as Integer if me.errCode <> 0 then return false end if me.refnum = 0 then raise new RuntimeException // did you forget to call Open()? end res = FSGetForkPosition(me.refnum, pos) if res = 0 then res = FSSetForkPosition(me.refnum, 1, pos + count) if res = 0 then return true end end me.errCode = res return false #endif End Function #tag EndMethod #tag Method, Flags = &h0 Function Write(data As String) As Boolean #if TargetMacOS dim res, act, req as Integer dim mb as MemoryBlock Declare Function FSWriteFork Lib CarbonLibName (refNum as Integer, posMode as Integer, posOfs as Int64, req as Integer, buffPtr as Ptr, ByRef count as Integer) as Integer const fsAtMark = 0 const fsFromStart = 1 const fsFromLEOF = 2 const fsFromMark = 3 // don't write if there has been an error before if me.errCode <> 0 then return false end if me.refnum = 0 then raise new RuntimeException // did you forget to call Open()? end req = LenB(data) mb = new MemoryBlock(req) // a temp buffer to write the data from if mb = nil then raise new OutOfMemoryException end mb.StringValue(0,req) = data res = FSWriteFork (me.refnum, fsFromMark, 0, req, mb, act) if res = 0 and act <> req then res = -1 // something went very wrong here, maybe due to a bug in this class end if res < 0 then me.errCode = res return false end return true #endif End Function #tag EndMethod #tag Property, Flags = &h1 Protected errCode As Integer #tag EndProperty #tag Property, Flags = &h1 Protected f As FolderItem #tag EndProperty #tag Property, Flags = &h1 Protected refnum As Integer #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/SeqDataInputStream.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface Protected Interface SeqDataInputStream #tag Method, Flags = &h8 Sub ClearError() End Sub #tag EndMethod #tag Method, Flags = &h8 Sub Close() End Sub #tag EndMethod #tag Method, Flags = &h8 Function EOF() As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Sub GetErrorDescription(ByRef code as Integer, ByRef msg as String) End Sub #tag EndMethod #tag Method, Flags = &h8 Function HadError() As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Function Open() As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Function Read(count as Integer) As String End Function #tag EndMethod #tag Method, Flags = &h8 Function Skip(count as UInt64) As Boolean End Function #tag EndMethod #tag Note, Name = About This Interface defines functions for sequentially reading data from binary streams. While it currently only defines one string-reading function, it could well be extended to support reading of all of RB's data types, such as ReadBoolean, ReadPString, etc., just like the ones that the RB class BinaryStream contains. #tag EndNote #tag Note, Name = Documentation Open () as Boolean Shall be called once before any Read... calls. Shall return FALSE if an error condition has arised (but not if there is just no data to read because the stream is already empty). Shall return TRUE otherwise. Close () Shall be called after all Read... calls have been performed. Allows the called to close the stream. Read (count as Integer) as String Reads "count" bytes from the input stream and returns them as a string. If less than the requested amount of data is available, that lesser amount shall be returned. If an error has occured or if no more data is available, an empty string shall be returned. The caller is responsible for making sure that he has received as much data as expected, for instance by checking the length of the returned data with the LenB() function. If the amount is less than what was requested, then the caller should check whether it was due to an error or because no more data is available with the two functions EOF() and Error(). Skip (count as Integer) as Boolean Similar to Read, but does not return the amount of data that's been read or skipped. Returns TRUE if the skip was successful, FALSE if not as many bytes could be skipped, which means that it might have reached the end of the stream or that an error has occured. EOF () as Boolean Shall return TRUE if there is no more data available to read from the input stream. HadError () as Boolean Shall return TRUE if an error condition has arisen since any of the past calls to Open and Read, unless ClearError was called since an error had occured. GetErrorDescription (ByRef code as Integer, ByRef msg as String) If an error had occured since the call to Open, the called shall set 'code' to a non-zero value, and the 'msg' string to a descriptive message that could be shown to a user (for debugging, mostly). It is recommended to set 'code' to -1 to flag a "unspecific error". If no error condition exists, 'code' shall be set to 0 and 'msg' to an empty string. ClearError () Sets the error state to "no error" #tag EndNote #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Interface #tag EndInterface -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/SeqDataOutputStream.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Interface Protected Interface SeqDataOutputStream #tag Method, Flags = &h8 Sub ClearError() End Sub #tag EndMethod #tag Method, Flags = &h8 Function Close() As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Function Flush() As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Sub GetErrorDescription(ByRef code as Integer, ByRef msg as String) End Sub #tag EndMethod #tag Method, Flags = &h8 Function Open() As Boolean End Function #tag EndMethod #tag Method, Flags = &h0 Sub PreAllocate(count as UInt64) End Sub #tag EndMethod #tag Method, Flags = &h8 Function Skip(count as UInt64) As Boolean End Function #tag EndMethod #tag Method, Flags = &h8 Function Write(data as String) As Boolean End Function #tag EndMethod #tag Note, Name = About This Interface defines functions for sequentially writing data to binary streams. While it currently only defines one string-writing function, it could well be extended to support writing of all of RB's data types, such as WriteBoolean, WritePString, etc., just like the ones that the RB class BinaryStream contains. #tag EndNote #tag Note, Name = Documentation Open () as Boolean If output stream goes to a file, the file will be created if it does not exist. Shall be called once before any Write... calls. Shall return TRUE if writing can continue, or FALSE if the output stream can't be written to at all. Close () as Boolean Shall be called after all Write... calls have been performed. Allows the called to close the stream. The called should make a final check that the former writes were successful and return FALSE if it turns out that there was an error. Should return TRUE if it is assumed that all data was written successfully. Write (data as String) as Boolean Writes the string to the output stream. Returns FALSE if the write is known to be unsuccessful, otherwise TRUE. This means that the caller can't be 100% sure that the write was successful, but he should stop sendin more data as soon as this function returns FALSE. Skip (count as Integer) as Boolean Similar to Write(), this will advance by the given amount of bytes in the output stream, writing zeros or just changing the position without overwriting any data. This means that in the case of a random access file being the output of the stream, the skipped part may still contain formerly written random data. The file must be extended include the added amount, though. The returned Boolean value follows the same rules as in Write() Flush () as Boolean Writes any outstanding data and checks that all data has been written successfully - similar to Close, but without closing the stream. GetErrorDescription (ByRef code as Integer, ByRef msg as String) If an error had occured since the call to Open, the called shall set 'code' to a non-zero value, and the 'msg' string to a descriptive message that could be shown to a user (for debugging, mostly). It is recommended to set 'code' to -1 to flag a "unspecific error". If no error condition exists, 'code' shall be set to 0 and 'msg' to an empty string. ClearError () Sets the error state to "no error" #tag EndNote #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Interface #tag EndInterface -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/StringReader.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class StringReader Inherits FileReader #tag Method, Flags = &h1000 Sub Constructor(data as String) me.bs = new BinaryStream(data) End Sub #tag EndMethod #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/StringWriter.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class StringWriter Implements SeqDataOutputStream #tag Method, Flags = &h21 Private Sub allocSpace(space as Int64) if space > mBuffer.Size then dim sizeToAdd as Int64 = Max (mBuffer.Size \ 2, 65636) PreAllocate mBuffer.Size + sizeToAdd end if End Sub #tag EndMethod #tag Method, Flags = &h0 Sub ClearError() End Sub #tag EndMethod #tag Method, Flags = &h0 Function Close() As Boolean if not mOpened then return true end if mBuffer.Size <> mWritten then mBuffer.Size = mWritten end mOpened = false return true End Function #tag EndMethod #tag Method, Flags = &h0 Sub Constructor() // Constructor. mBuffer = new MemoryBlock(0) End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() call me.Close End Sub #tag EndMethod #tag Method, Flags = &h0 Function Flush() As Boolean return true End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) code = 0 msg = "" End Sub #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean mWritten = 0 mOpened = true return true End Function #tag EndMethod #tag Method, Flags = &h0 Sub PreAllocate(count as UInt64) if mBuffer.Size < count then mBuffer.Size = count end End Sub #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean if not mOpened then raise new RuntimeException // did you forget to call Open()? end mWritten = mWritten + count allocSpace mWritten return true End Function #tag EndMethod #tag Method, Flags = &h0 Function Write(data As String) As Boolean if not mOpened then raise new RuntimeException // did you forget to call Open()? end dim n as Int64 = LenB(data) dim newLen as Int64 = mWritten + n allocSpace newLen mBuffer.StringValue(mWritten,n) = data mWritten = newLen return true End Function #tag EndMethod #tag Method, Flags = &h0 Function WrittenData() As MemoryBlock return mBuffer End Function #tag EndMethod #tag Property, Flags = &h21 Private mBuffer As MemoryBlock #tag EndProperty #tag Property, Flags = &h21 Private mOpened As Boolean #tag EndProperty #tag Property, Flags = &h21 Private mWritten As UInt64 #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/StreamSupport/SymlinkReader.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class SymlinkReader Implements SeqDataInputStream #tag Method, Flags = &h0 Sub ClearError() me.error = false End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Close() mOpened = false mSymlinkData = nil End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(f as TTsFolderItem) // Constructor. // Pass a FolderItem to designate the file the stream should read from me.f = f End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() me.Close End Sub #tag EndMethod #tag Method, Flags = &h0 Function EOF() As Boolean return not mOpened or mReadOfs >= mSymlinkData.Size End Function #tag EndMethod #tag Method, Flags = &h0 Sub GetErrorDescription(ByRef code As Integer, ByRef msg As String) if me.error then code = -1 msg = "open or read error" else code = 0 msg = "" end End Sub #tag EndMethod #tag Method, Flags = &h0 Function HadError() As Boolean return me.error End Function #tag EndMethod #tag Method, Flags = &h0 Function Open() As Boolean if mOpened then return true end soft declare function readlink lib SystemLib (path as CString, outbuf as Ptr, bufsize as Integer) as Integer try dim res as Integer dim buf as new MemoryBlock(PATH_MAX) res = readlink (f.UnixPath, buf, buf.Size) if res >= 0 then mOpened = true mReadOfs = 0 mSymlinkData = buf.StringValue(0, res) else break end catch // oops, function not available? break end me.error = not mOpened return mOpened End Function #tag EndMethod #tag Method, Flags = &h0 Function Read(count As Integer) As String if not mOpened then raise new RuntimeException // did you forget to call Open()? end dim remain as Integer remain = mSymlinkData.Size - mReadOfs if count > remain then count = remain dim ofs as Integer ofs = mReadOfs mReadOfs = mReadOfs + count return mSymlinkData.StringValue (ofs, count) End Function #tag EndMethod #tag Method, Flags = &h0 Function Skip(count As UInt64) As Boolean if not mOpened then raise new RuntimeException // did you forget to call Open()? end dim newpos, len as UInt64 len = mSymlinkData.Size newpos = mReadOfs + count if newpos > len then // wants to skip more than available return false end mReadOfs = newpos return true End Function #tag EndMethod #tag Property, Flags = &h1 Protected error As Boolean #tag EndProperty #tag Property, Flags = &h1 Protected f As TTsFolderItem #tag EndProperty #tag Property, Flags = &h1 Protected mOpened As Boolean #tag EndProperty #tag Property, Flags = &h1 Protected mReadOfs As Integer #tag EndProperty #tag Property, Flags = &h1 Protected mSymlinkData As MemoryBlock #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/ZLibClasses/ZLibDeflator.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class ZLibDeflator Inherits ZLibStream Implements IStreamWriter #tag Method, Flags = &h0 Sub Constructor(writer as WriteProc, level as Integer = DEFAULT_COMPRESSION) super.Constructor(writer) soft declare function deflateInit_ lib libz_path (stream as Ptr, level as Integer, version as CString, stream_size as Integer) as Int32 soft declare function deflateInit2_ lib libz_path (stream as Ptr, level as Integer, method as Integer, windowBits as Integer, memLevel as Integer, strategy as Integer, version as CString, stream_size as Integer) as Int32 const MAX_WBITS = 15 const DEF_MEM_LEVEL = 8 const Z_DEFAULT_STRATEGY = 0 dim err as Integer #if true err = deflateInit_ (mStream, level, Version(), mStream.Size) #else // alternative with more options: err = deflateInit2_ (mStream, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, Version(), mStream.Size) #endif if err <> 0 then raise new ZLibStreamException (me, err) end End Sub #tag EndMethod #tag Method, Flags = &h0 Function CRC() As Integer return me.mCRC End Function #tag EndMethod #tag Method, Flags = &h0 Function Deflate(input as Ptr, len as UInt32, flush as FlushCode, ByRef hint as Variant) As Boolean soft declare function deflate lib libz_path (stream as Ptr, flush as Integer) as Int32 if mCalcCRC and len > 0 then mCRC = ZLibStream.CRC32(mCRC, input, len) end me.z_next_in = input me.z_avail_in = len dim result as Integer do me.z_next_out = mBuffer me.z_avail_out = mBuffer.Size result = deflate (mStream, Integer(flush)) if result = Z_STREAM_ERROR then raise new ZLibStreamException (me, result) end dim written as UInt32 = mBuffer.Size - me.z_avail_out if written > 0 then if not mWriter.Invoke (mBuffer, written, hint) then // cancelled return false end end loop until me.z_avail_out <> 0 if me.z_avail_in <> 0 then // Oops - not all input was consumed. This should never ever happen raise new ZLibStreamException (me, 101) end if flush = FlushCode.FINISH and result <> Z_STREAM_END then // Oops - stream was not completed. This should never ever happen raise new ZLibStreamException (me, 102) end return true End Function #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() if IsZLibAvailable(false) then soft declare sub deflateEnd lib libz_path (stream as Ptr) deflateEnd mStream end if End Sub #tag EndMethod #tag Method, Flags = &h0 Sub EnableCRCCalculation() mCalcCRC = true End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Finish() dim v as Variant call Deflate (nil, 0, FlushCode.FINISH, v) End Sub #tag EndMethod #tag Method, Flags = &h0 Function LastError() As Integer // Part of the IStreamWriter interface. End Function #tag EndMethod #tag Method, Flags = &h0 Sub Reset() soft declare sub deflateReset lib libz_path (stream as Ptr) deflateReset mStream super.Reset mCRC = 0 mCalcCRC = false End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Write(data as MemoryBlock) dim v as Variant call Deflate (data, data.Size, FlushCode.NO_FLUSH, v) End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Write(data as String) dim mb as MemoryBlock = data Write mb End Sub #tag EndMethod #tag Note, Name = About This class is used to compress data into zlib compression format #tag EndNote #tag Property, Flags = &h21 Private mCalcCRC As Boolean #tag EndProperty #tag Property, Flags = &h21 Private mCRC As UInt32 #tag EndProperty #tag Constant, Name = BEST_COMPRESSION, Type = Double, Dynamic = False, Default = \"9", Scope = Public #tag EndConstant #tag Constant, Name = BEST_SPEED, Type = Double, Dynamic = False, Default = \"1", Scope = Public #tag EndConstant #tag Constant, Name = DEFAULT_COMPRESSION, Type = Double, Dynamic = False, Default = \"-1", Scope = Public #tag EndConstant #tag Constant, Name = NO_COMPRESSION, Type = Double, Dynamic = False, Default = \"0", Scope = Public #tag EndConstant #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/ZLibClasses/ZLibInflator.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class ZLibInflator Inherits ZLibStream Implements IStreamReader #tag Method, Flags = &h0 Sub Constructor(reader as Readable) me.Constructor(WriteProc(nil)) mReader = reader mBuffer = nil // we're not using a pre-allocated buffer in this mode End Sub #tag EndMethod #tag Method, Flags = &h0 Sub Constructor(writer as WriteProc) super.Constructor(writer) soft declare function inflateInit_ lib libz_path (stream as Ptr, version as CString, stream_size as Integer) as Integer dim err as Integer err = inflateInit_ (mStream, Version(), mStream.Size) if err <> 0 then raise new ZLibStreamException (me, err) end End Sub #tag EndMethod #tag Method, Flags = &h0 Function CRC() As Integer return me.mCRC End Function #tag EndMethod #tag Method, Flags = &h0 Sub Destructor() if IsZLibAvailable(false) then soft declare sub inflateEnd lib libz_path (stream as Ptr) inflateEnd mStream end if End Sub #tag EndMethod #tag Method, Flags = &h0 Sub EnableCRCCalculation() mCalcCRC = true End Sub #tag EndMethod #tag Method, Flags = &h0 Function HadDataError() As Boolean return mDataError End Function #tag EndMethod #tag Method, Flags = &h0 Function Inflate(input as Ptr, len as UInt32, ByRef consumedOut as UInt32, ByRef finished as Boolean, ByRef hint as Variant) As Boolean // This function takes a specific amount of input data and attempts to uncompress all of it // It does NOT set either mDataError nor mFinished nor mCRC. soft declare function inflate lib libz_path (stream as Ptr, flush as Integer) as Integer dim result as Integer if len = 0 then consumedOut = 0 finished = false else me.z_next_in = input me.z_avail_in = len do me.z_next_out = mBuffer me.z_avail_out = mBuffer.Size result = inflate (mStream, 0) if result = Z_STREAM_ERROR then raise new ZLibStreamException (me, result) end dim written as UInt32 = mBuffer.Size - me.z_avail_out if written > 0 then if not mWriter.Invoke (mBuffer, written, hint) then // cancelled consumedOut = len - me.z_avail_in finished = false return false end end loop until me.z_avail_out <> 0 or result <> 0 consumedOut = len - me.z_avail_in finished = (result = Z_STREAM_END) end // if len > 0 else return finished or result = 0 End Function #tag EndMethod #tag Method, Flags = &h0 Function IsFinished() As Boolean return mFinished End Function #tag EndMethod #tag Method, Flags = &h0 Function LastError() As Integer // Part of the IStreamReader interface. if mDataError then return -1 end if End Function #tag EndMethod #tag Method, Flags = &h0 Function Read(amount as Integer) As String // Part of the IStreamReader interface. // This function returns a specific amount of uncompressed data dim mb as new MemoryBlock (amount) dim n as UInt32 = Read (mb, mb.Size) if n = mb.Size then return mb elseif n = 0 then return "" else return mb.StringValue(0,n) end End Function #tag EndMethod #tag Method, Flags = &h0 Function Read(readBuf as Ptr, amount as UInt32, chunkSize as UInt32 = 0) As UInt32 // This function returns a specific amount of uncompressed data soft declare function inflate lib libz_path (stream as Ptr, flush as Int32) as Int32 if chunkSize <= 0 then chunkSize = 4096 // could be increased for better performance, maybe end dim totalOutBefore as UInt32 = me.z_total_out dim result as Integer if amount > 0 then me.z_next_out = readBuf me.z_avail_out = amount do if me.z_avail_in = 0 then me.z_avail_in = chunkSize mBuffer = mReader.Read (me.z_avail_in) me.z_next_in = mBuffer end result = inflate (mStream, Integer(FlushCode.SYNC_FLUSH)) if result = Z_STREAM_ERROR then raise new ZLibStreamException (me, result) end loop until me.z_avail_out = 0 or result <> 0 if result < 0 and result <> Z_DATA_ERROR then break end // if len > 0 else if result = Z_STREAM_END then mFinished = true elseif result = Z_DATA_ERROR then mFinished = true mDataError = true end amount = me.z_total_out - totalOutBefore if mCalcCRC and amount > 0 then mCRC = ZLibStream.CRC32(mCRC, readBuf, amount) end return amount End Function #tag EndMethod #tag Method, Flags = &h0 Sub Reset() soft declare sub inflateReset lib libz_path (stream as Ptr) inflateReset mStream super.Reset mFinished = false mDataError = false mCalcCRC = false mCRC = 0 End Sub #tag EndMethod #tag Method, Flags = &h0 Function TotalIn() As UInt32 return me.z_total_in End Function #tag EndMethod #tag Note, Name = About This class is used to uncompress zlib-compressed data You can use it in either of two modes: 1. Use Read() to fetch pre-determined amounts of uncompressed data from a compressed stream. For this mode, use Constructor(Readable). 2. Use Inflate() to pass compressed data and have it passed to a Write function that was specified by using Constructor(WriteProc). Note: Inflate() and Read() can not be mixed! #tag EndNote #tag Property, Flags = &h21 Private mCalcCRC As Boolean #tag EndProperty #tag Property, Flags = &h21 Private mCRC As UInt32 #tag EndProperty #tag Property, Flags = &h21 Private mDataError As Boolean #tag EndProperty #tag Property, Flags = &h21 Private mFinished As Boolean #tag EndProperty #tag Property, Flags = &h21 Private mReader As Readable #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/ZLibClasses/ZLibStreamException.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Class Protected Class ZLibStreamException Inherits RuntimeException #tag Method, Flags = &h0 Sub Constructor(fromStream as ZLibStream, errorCode as Integer) mStream = fromStream mErrorCode = errorCode dim msg as String if mStream <> nil then break msg = mStream.Message() else break msg = "zlib missing" System.DebugLog "ZLibStreamException: zlib missing" end if if errorCode <> 0 then if msg <> "" then msg = msg + ", " end if msg = msg + "Code "+Str(errorCode,"-#") end if me.Message = msg End Sub #tag EndMethod #tag Property, Flags = &h21 Private mErrorCode As Integer #tag EndProperty #tag Property, Flags = &h21 Private mStream As ZLibStream #tag EndProperty #tag ViewBehavior #tag ViewProperty Name="ErrorNumber" Group="Behavior" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Left" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag ViewProperty Name="Message" Group="Behavior" Type="String" EditorType="MultiLineEditor" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Reason" Group="Behavior" Type="Text" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" Type="String" #tag EndViewProperty #tag ViewProperty Name="Top" Visible=true Group="Position" InitialValue="0" Type="Integer" #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass -------------------------------------------------------------------------------- /ZipPackage/ZipConfig.xojo_code: -------------------------------------------------------------------------------- 1 | #tag Module Protected Module ZipConfig #tag Method, Flags = &h1 Protected Function CRC16(mb as MemoryBlock, size as Integer) As UInt16 #if HaveEinhugurPlugin // Using the "e-CryptIt Engine" plugin, see