diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index a7184f71b..000000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-# These are supported funding model platforms
-
-# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-github: lakritzator
-patreon: # Replace with a single Patreon username
-open_collective: greenshot
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-custom: https://getgreenshot.org/support/
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 1f5ca2f11..000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: ''
-assignees: ''
-
----
-
-This GitHub repository is for developers, if you want to report a bug for Greenshot as a user please do so in our JIRA issue system here: https://greenshot.atlassian.net/projects/BUGS/issues/filter=allopenissues
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Example steps to reproduce the behavior:
-1. Capture '....'
-2. Open Editor
-3. Add a line
-4. Resize
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Versions (please complete the following information):**
- - Greenshot version
- - Windows version
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/developer-bug-report.md b/.github/ISSUE_TEMPLATE/developer-bug-report.md
deleted file mode 100644
index 1ffa7da1e..000000000
--- a/.github/ISSUE_TEMPLATE/developer-bug-report.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-name: Developer Bug report
-about: Create a bug report to help us improve our code
-title: ''
-labels: ''
-assignees: ''
-
----
-
-This GitHub repository is for developers, if you want to report a bug for Greenshot as a user please do so in our JIRA issue system here: https://greenshot.atlassian.net/projects/BUGS/issues/filter=allopenissues
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Example steps to reproduce the behavior:
-1. Capture '....'
-2. Open Editor
-3. Add a line
-4. Resize
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Versions (please complete the following information):**
- - Greenshot version
- - Windows version
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/developer-feature-request.md b/.github/ISSUE_TEMPLATE/developer-feature-request.md
deleted file mode 100644
index 883534a57..000000000
--- a/.github/ISSUE_TEMPLATE/developer-feature-request.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Developer feature request
-about: Suggest an technical idea for this project
-title: ''
-labels: ''
-assignees: ''
-
----
-
-This GitHub repository is for developers, if you want to request a feature for Greenshot as a user please do so in our JIRA issue system here: https://greenshot.atlassian.net/projects/FEATURE/issues/filter=allopenissues
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 64323a13d..000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: ''
-assignees: ''
-
----
-
-This GitHub repository is for developers, if you want to request a feature for Greenshot as a user please do so in our JIRA issue system here: https://greenshot.atlassian.net/projects/FEATURE/issues/filter=allopenissues
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/workflows/purge-cloudflare-cache.yml b/.github/workflows/purge-cloudflare-cache.yml
deleted file mode 100644
index a2d288faf..000000000
--- a/.github/workflows/purge-cloudflare-cache.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: Purge CloudFlare Cache
-
-on:
- page_build:
-
-jobs:
- purge_cache:
- runs-on: ubuntu-latest
- steps:
- - name: purge
- uses: jakejarvis/cloudflare-purge-action@master
- env:
- CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}
- CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 9a92223ed..000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-env:
- IS_RELEASE_BRANCH: ${{ startsWith(github.ref, 'refs/heads/release/') }}
- BRANCH_NAME: ${{ github.ref_name }}
-
-name: Build and Deploy
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'release/1.*'
- paths-ignore:
- - '.github/**'
- - '.gitignore'
- - '*.md'
- - 'LICENSE'
- - 'build-and-deploy.ps1'
-
-jobs:
- build:
- runs-on: windows-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- - name: Setup MSBuild
- uses: microsoft/setup-msbuild@v2
-
- - name: Set up .NET
- uses: actions/setup-dotnet@v4
- with:
- dotnet-version: '7.x'
-
- - name: Restore NuGet packages
- run: msbuild src/Greenshot.sln /p:Configuration=Release /restore /t:PrepareForBuild
- env:
- Box13_ClientId: ${{ secrets.Box13_ClientId }}
- Box13_ClientSecret: ${{ secrets.Box13_ClientSecret }}
- DropBox13_ClientId: ${{ secrets.DropBox13_ClientId }}
- DropBox13_ClientSecret: ${{ secrets.DropBox13_ClientSecret }}
- Flickr_ClientId: ${{ secrets.Flickr_ClientId }}
- Flickr_ClientSecret: ${{ secrets.Flickr_ClientSecret }}
- Imgur13_ClientId: ${{ secrets.Imgur13_ClientId }}
- Imgur13_ClientSecret: ${{ secrets.Imgur13_ClientSecret }}
- Photobucket_ClientId: ${{ secrets.Photobucket_ClientId }}
- Photobucket_ClientSecret: ${{ secrets.Photobucket_ClientSecret }}
- Picasa_ClientId: ${{ secrets.Picasa_ClientId }}
- Picasa_ClientSecret: ${{ secrets.Picasa_ClientSecret }}
-
- - name: Build and package
- run: msbuild src/Greenshot.sln /p:Configuration=Release /t:Rebuild /v:normal
- env:
- Box13_ClientId: ${{ secrets.Box13_ClientId }}
- Box13_ClientSecret: ${{ secrets.Box13_ClientSecret }}
- DropBox13_ClientId: ${{ secrets.DropBox13_ClientId }}
- DropBox13_ClientSecret: ${{ secrets.DropBox13_ClientSecret }}
- Flickr_ClientId: ${{ secrets.Flickr_ClientId }}
- Flickr_ClientSecret: ${{ secrets.Flickr_ClientSecret }}
- Imgur13_ClientId: ${{ secrets.Imgur13_ClientId }}
- Imgur13_ClientSecret: ${{ secrets.Imgur13_ClientSecret }}
- Photobucket_ClientId: ${{ secrets.Photobucket_ClientId }}
- Photobucket_ClientSecret: ${{ secrets.Photobucket_ClientSecret }}
- Picasa_ClientId: ${{ secrets.Picasa_ClientId }}
- Picasa_ClientSecret: ${{ secrets.Picasa_ClientSecret }}
-
- - name: Copy Files
- run: |
- mkdir -p ${{ github.workspace }}/artifacts
- cp installer/Greenshot-INSTALLER-*.exe ${{ github.workspace }}/artifacts/
-
- - name: Upload Artifact
- uses: actions/upload-artifact@v4
- with:
- name: drop
- path: ${{ github.workspace }}/artifacts
-
- deploy:
- runs-on: windows-latest
- needs: build
-
- steps:
-
- - name: Checkout repository
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- - name: Download build artifacts
- uses: actions/download-artifact@v4
- with:
- name: drop # Name of the artifact uploaded in previous steps
- path: drop # Local folder where artifacts are downloaded
-
- - name: Extract version from file name
- if: env.IS_RELEASE_BRANCH == 'true'
- id: version_from_filename
- run: |
- $file = Get-ChildItem drop -Filter "Greenshot-INSTALLER-*.exe" | Select-Object -First 1
- if (-not $file) {
- throw "No matching file found in 'drop' directory."
- }
- if ($file.Name -match "Greenshot-INSTALLER-([\d\.]+)(.*)\.exe") {
- echo "version=$($matches[1])" >> $Env:GITHUB_OUTPUT
- } else {
- throw "Version number could not be extracted from file name: $($file.Name)"
- }
- shell: pwsh
-
- - name: Set version from sanitized branch name
- if: env.IS_RELEASE_BRANCH != 'true'
- id: version_from_branchname
- run: |
- $branch = "${{ github.ref }}" -replace '^refs/heads/', ''
- $sanitized = $branch -replace '[^a-zA-Z0-9._-]', '_'
- echo "version=$sanitized" >> $Env:GITHUB_OUTPUT
- shell: pwsh
-
- - name: Set version info
- id: version_info
- run: |
- echo "version=${{ steps.version_from_filename.outputs.version || steps.version_from_branchname.outputs.version }}" >> $GITHUB_OUTPUT
- shell: bash
-
-
- - name: Create tag
- if: env.IS_RELEASE_BRANCH == 'true'
- run: |
- git config user.name "github-actions[bot]"
- git config user.email "github-actions[bot]@users.noreply.github.com"
- git tag -a "v${{ steps.version_info.outputs.version }}" -m "v${{ steps.version_info.outputs.version }}"
- git push origin "v${{ steps.version_info.outputs.version }}"
-
- - name: Rename installer for non-release branch
- if: env.IS_RELEASE_BRANCH != 'true'
- run: |
- branch="${BRANCH_NAME:-${GITHUB_REF#refs/heads/}}"
- sanitized=$(echo "$branch" | sed 's/[^a-zA-Z0-9._-]/_/g')
- mv drop/Greenshot-INSTALLER-*.exe "drop/Greenshot-INSTALLER-${sanitized}.exe"
- shell: bash
-
- - name: Create GitHub Release
- uses: softprops/action-gh-release@v2
- with:
- name: "Greenshot ${{ steps.version_info.outputs.version }} (continuous build)"
- tag_name: ${{ env.IS_RELEASE_BRANCH == 'true' && format('v{0}', steps.version_info.outputs.version) || env.BRANCH_NAME }}
- files: drop/*.exe
- generate_release_notes: true
- draft: ${{ env.IS_RELEASE_BRANCH != 'true' }}
- prerelease: true
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Trigger GitHub Pages rebuild
- shell: bash
- run: |
- curl -X POST \
- -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
- -H "Accept: application/vnd.github+json" \
- https://api.github.com/repos/${{ github.repository }}/pages/builds
-
diff --git a/.github/workflows/update-gh-pages.yml b/.github/workflows/update-gh-pages.yml
deleted file mode 100644
index ba45b70d1..000000000
--- a/.github/workflows/update-gh-pages.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Update GitHub Pages
-
-on:
- workflow_dispatch:
- release:
- types: [published, unpublished, created, edited, deleted, prereleased, released]
-
-jobs:
- update-gh-pages:
- runs-on: ubuntu-latest
- steps:
- - name: Trigger GitHub Pages rebuild
- shell: bash
- run: |
- curl -X POST \
- -H "Authorization: Bearer ${{ secrets.GH_PAGES_TOKEN }}" \
- -H "Accept: application/vnd.github+json" \
- https://api.github.com/repos/${{ github.repository }}/pages/builds
diff --git a/.gitignore b/.gitignore
index 7e96d5501..3321bd633 100644
--- a/.gitignore
+++ b/.gitignore
@@ -209,11 +209,3 @@ FakesAssemblies/
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
-
-# Greenshot credentials files
-*.credentials.cs
-
-# Rider files
-.idea
-
-/installer/Greenshot-INSTALLER-*.exe
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
deleted file mode 100644
index 638637e24..000000000
--- a/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Contributor Covenant Code of Conduct
-
-## Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
-
-## Scope
-
-This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at getgreenshot@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
-
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index abf5e0f03..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,18 +0,0 @@
-The general rule we follow is "use Visual Studio defaults".
-
-1. We use [Allman style](http://en.wikipedia.org/wiki/Indent_style#Allman_style) braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and it must not be nested in other statement blocks that use braces (See issue [381](https://github.com/dotnet/corefx/issues/381) for examples).
-2. We use four spaces of indentation (no tabs).
-3. We use `_camelCase` for internal and private fields and use `readonly` where possible. Prefix instance fields with `_`, static fields with `s_` and thread static fields with `t_`. When used on static fields, `readonly` should come after `static` (e.g. `static readonly` not `readonly static`).
-4. We avoid `this.` unless absolutely necessary.
-5. We always specify the visibility, even if it's the default (e.g. `private string _foo` not `string _foo`). Visibility should be the first modifier (e.g. `public abstract` not `abstract public`).
-6. Namespace imports should be specified at the top of the file, *outside* of `namespace` declarations and should be sorted alphabetically.
-7. Avoid more than one empty line at any time. For example, do not have two blank lines between members of a type.
-8. Avoid spurious free spaces. For example avoid `if (someVar == 0)...`, where the dots mark the spurious free spaces. Consider enabling "View White Space (Ctrl+E, S)" if using Visual Studio, to aid detection.
-9. If a file happens to differ in style from these guidelines (e.g. private members are named `m_member` rather than `_member`), the existing style in that file takes precedence.
-10. We only use `var` when it's obvious what the variable type is (e.g. `var stream = new FileStream(...)` not `var stream = OpenStandardInput()`).
-11. We use language keywords instead of BCL types (e.g. `int, string, float` instead of `Int32, String, Single`, etc) for both type references as well as method calls (e.g. `int.Parse` instead of `Int32.Parse`). See issue [391](https://github.com/dotnet/corefx/issues/391) for examples.
-12. We use PascalCasing to name all our constant local variables and fields. The only exception is for interop code where the constant value should exactly match the name and value of the code you are calling via interop.
-13. We use ```nameof(...)``` instead of ```"..."``` whenever possible and relevant.
-14. Fields should be specified at the top within type declarations.
-15. When including non-ASCII characters in the source code use Unicode escape sequences (\uXXXX) instead of literal characters. Literal non-ASCII characters occasionally get garbled by a tool or editor.
-16. Do not use labels (e.g. for goto).
diff --git a/CommonProject.properties b/CommonProject.properties
new file mode 100644
index 000000000..db6e37df8
--- /dev/null
+++ b/CommonProject.properties
@@ -0,0 +1,34 @@
+
+
+
+ 1685
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ 4096
+ Full
+ x86
+ Off
+
+
+ 1685
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ 4096
+ Full
+ AnyCPU
+ Off
+
+
+ 1685
+ bin\Release\
+ true
+ 4096
+ pdbonly
+ AnyCPU
+ Off
+
+
diff --git a/src/Greenshot.sln b/Greenshot.sln
similarity index 50%
rename from src/Greenshot.sln
rename to Greenshot.sln
index b71e79bd3..b76fba9a6 100644
--- a/src/Greenshot.sln
+++ b/Greenshot.sln
@@ -1,183 +1,196 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.7.34009.444
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
- ProjectSection(ProjectDependencies) = postProject
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB} = {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}
- {19FEEF09-313F-43C7-819D-F1BCA782B08B} = {19FEEF09-313F-43C7-819D-F1BCA782B08B}
- {9801F62C-540F-4BFE-9211-6405DEDE563B} = {9801F62C-540F-4BFE-9211-6405DEDE563B}
- {9C0ECC4C-7807-4111-916A-4F57BB29788A} = {9C0ECC4C-7807-4111-916A-4F57BB29788A}
- {C3052651-598A-44E2-AAB3-2E41311D50F9} = {C3052651-598A-44E2-AAB3-2E41311D50F9}
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E} = {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}
- {697CF066-9077-4F22-99D9-D989CCE7282B} = {697CF066-9077-4F22-99D9-D989CCE7282B}
- {47F23C86-604E-4CC3-8767-B3D4088F30BB} = {47F23C86-604E-4CC3-8767-B3D4088F30BB}
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} = {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} = {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0}
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Base", "Greenshot.Base\Greenshot.Base.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.ExternalCommand", "Greenshot.Plugin.ExternalCommand\Greenshot.Plugin.ExternalCommand.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Confluence", "Greenshot.Plugin.Confluence\Greenshot.Plugin.Confluence.csproj", "{C3052651-598A-44E2-AAB3-2E41311D50F9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Imgur", "Greenshot.Plugin.Imgur\Greenshot.Plugin.Imgur.csproj", "{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Jira", "Greenshot.Plugin.Jira\Greenshot.Plugin.Jira.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Box", "Greenshot.Plugin.Box\Greenshot.Plugin.Box.csproj", "{697CF066-9077-4F22-99D9-D989CCE7282B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Dropbox", "Greenshot.Plugin.Dropbox\Greenshot.Plugin.Dropbox.csproj", "{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Flickr", "Greenshot.Plugin.Flickr\Greenshot.Plugin.Flickr.csproj", "{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.GooglePhotos", "Greenshot.Plugin.GooglePhotos\Greenshot.Plugin.GooglePhotos.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Office", "Greenshot.Plugin.Office\Greenshot.Plugin.Office.csproj", "{92599C09-FF29-4ABD-B6E6-C48ECD781BAB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Photobucket", "Greenshot.Plugin.Photobucket\Greenshot.Plugin.Photobucket.csproj", "{9C0ECC4C-7807-4111-916A-4F57BB29788A}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.Win10", "Greenshot.Plugin.Win10\Greenshot.Plugin.Win10.csproj", "{9801F62C-540F-4BFE-9211-6405DEDE563B}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82987F1E-D7E6-4C44-B934-981D366E4672}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- ..\azure-pipelines.yml = ..\azure-pipelines.yml
- Directory.Build.props = Directory.Build.props
- Directory.Build.targets = Directory.Build.targets
- ..\.github\workflows\release.yml = ..\.github\workflows\release.yml
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Editor", "Greenshot.Editor\Greenshot.Editor.csproj", "{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|x86.ActiveCfg = Debug|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|x86.Build.0 = Debug|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|Any CPU.Build.0 = Release|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|x86.ActiveCfg = Release|Any CPU
- {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|x86.Build.0 = Release|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|x86.ActiveCfg = Debug|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|x86.Build.0 = Debug|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|Any CPU.Build.0 = Release|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|x86.ActiveCfg = Release|Any CPU
- {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|x86.Build.0 = Release|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|x86.Build.0 = Debug|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.Build.0 = Release|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|x86.ActiveCfg = Release|Any CPU
- {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|x86.Build.0 = Release|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|x86.Build.0 = Debug|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.Build.0 = Release|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|x86.ActiveCfg = Release|Any CPU
- {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|x86.Build.0 = Release|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|x86.ActiveCfg = Debug|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|x86.Build.0 = Debug|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|Any CPU.Build.0 = Release|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|x86.ActiveCfg = Release|Any CPU
- {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|x86.Build.0 = Release|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|x86.Build.0 = Debug|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.Build.0 = Release|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|x86.ActiveCfg = Release|Any CPU
- {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|x86.Build.0 = Release|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|x86.Build.0 = Debug|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|Any CPU.Build.0 = Release|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|x86.ActiveCfg = Release|Any CPU
- {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|x86.Build.0 = Release|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|x86.ActiveCfg = Debug|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|x86.Build.0 = Debug|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|Any CPU.Build.0 = Release|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|x86.ActiveCfg = Release|Any CPU
- {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|x86.Build.0 = Release|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|x86.ActiveCfg = Debug|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|x86.Build.0 = Debug|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|Any CPU.Build.0 = Release|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|x86.ActiveCfg = Release|Any CPU
- {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|x86.Build.0 = Release|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|x86.Build.0 = Debug|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|Any CPU.Build.0 = Release|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|x86.ActiveCfg = Release|Any CPU
- {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|x86.Build.0 = Release|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|x86.Build.0 = Debug|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Any CPU.Build.0 = Release|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|x86.ActiveCfg = Release|Any CPU
- {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|x86.Build.0 = Release|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|x86.ActiveCfg = Debug|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|x86.Build.0 = Debug|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Any CPU.Build.0 = Release|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.ActiveCfg = Release|Any CPU
- {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.Build.0 = Release|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.Build.0 = Debug|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Any CPU.Build.0 = Release|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.ActiveCfg = Release|Any CPU
- {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.Build.0 = Release|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Debug|x86.ActiveCfg = Debug|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Debug|x86.Build.0 = Debug|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|Any CPU.Build.0 = Release|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.ActiveCfg = Release|Any CPU
- {148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {970967C0-60BE-4F70-9332-9ACC04B93A15}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotExternalCommandPlugin", "GreenshotExternalCommandPlugin\GreenshotExternalCommandPlugin.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotConfluencePlugin", "GreenshotConfluencePlugin\GreenshotConfluencePlugin.csproj", "{C3052651-598A-44E2-AAB3-2E41311D50F9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotImgurPlugin", "GreenshotImgurPlugin\GreenshotImgurPlugin.csproj", "{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotJiraPlugin", "GreenshotJiraPlugin\GreenshotJiraPlugin.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRPlugin", "GreenshotOCRPlugin\GreenshotOCRPlugin.csproj", "{C6988EE8-2FEE-4349-9F09-F9628A0D8965}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRCommand", "GreenshotOCRCommand\GreenshotOCRCommand.csproj", "{D61E6ECE-E0B6-4467-B492-F08A06BA8F02}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965} = {C6988EE8-2FEE-4349-9F09-F9628A0D8965}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotBoxPlugin", "GreenshotBoxPlugin\GreenshotBoxPlugin.csproj", "{697CF066-9077-4F22-99D9-D989CCE7282B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotDropboxPlugin", "GreenshotDropboxPlugin\GreenshotDropboxPlugin.csproj", "{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotFlickrPlugin", "GreenshotFlickrPlugin\GreenshotFlickrPlugin.csproj", "{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPicasaPlugin", "GreenshotPicasaPlugin\GreenshotPicasaPlugin.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOfficePlugin", "GreenshotOfficePlugin\GreenshotOfficePlugin.csproj", "{92599C09-FF29-4ABD-B6E6-C48ECD781BAB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPhotobucketPlugin", "GreenshotPhotobucketPlugin\GreenshotPhotobucketPlugin.csproj", "{9C0ECC4C-7807-4111-916A-4F57BB29788A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotWin10Plugin", "GreenshotWin10Plugin\GreenshotWin10Plugin.csproj", "{9801F62C-540F-4BFE-9211-6405DEDE563B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|x86.ActiveCfg = Debug|x86
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Debug|x86.Build.0 = Debug|x86
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}.Release|x86.ActiveCfg = Release|x86
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|x86.ActiveCfg = Debug|x86
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Debug|x86.Build.0 = Debug|x86
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}.Release|x86.ActiveCfg = Release|x86
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|x86.ActiveCfg = Debug|x86
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Debug|x86.Build.0 = Debug|x86
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}.Release|x86.ActiveCfg = Release|x86
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|x86.ActiveCfg = Debug|x86
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Debug|x86.Build.0 = Debug|x86
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}.Release|x86.ActiveCfg = Release|x86
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|x86.ActiveCfg = Debug|x86
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Debug|x86.Build.0 = Debug|x86
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|Any CPU.Build.0 = Release|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}.Release|x86.ActiveCfg = Release|x86
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|x86.ActiveCfg = Debug|x86
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Debug|x86.Build.0 = Debug|x86
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|x86.ActiveCfg = Release|x86
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|x86.ActiveCfg = Debug|x86
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|x86.Build.0 = Debug|x86
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|x86.ActiveCfg = Release|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.Build.0 = Debug|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.ActiveCfg = Debug|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.Build.0 = Debug|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|Any CPU.ActiveCfg = Release|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|Any CPU.Build.0 = Release|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|x86.ActiveCfg = Release|x86
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|x86.Build.0 = Release|x86
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|x86.ActiveCfg = Debug|x86
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|x86.Build.0 = Debug|x86
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {697CF066-9077-4F22-99D9-D989CCE7282B}.Release|x86.ActiveCfg = Release|x86
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|x86.ActiveCfg = Debug|x86
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Debug|x86.Build.0 = Debug|x86
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}.Release|x86.ActiveCfg = Release|x86
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|x86.ActiveCfg = Debug|x86
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Debug|x86.Build.0 = Debug|x86
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}.Release|x86.ActiveCfg = Release|x86
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|x86.ActiveCfg = Debug|x86
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Debug|x86.Build.0 = Debug|x86
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}.Release|x86.ActiveCfg = Release|x86
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|x86.ActiveCfg = Debug|x86
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Debug|x86.Build.0 = Debug|x86
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|x86.ActiveCfg = Release|x86
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}.Release|x86.Build.0 = Release|x86
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|x86.ActiveCfg = Debug|x86
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Debug|x86.Build.0 = Debug|x86
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.ActiveCfg = Release|x86
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.Build.0 = Release|x86
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.Build.0 = Debug|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.ActiveCfg = Release|Any CPU
+ {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Greenshot/App.config b/Greenshot/App.config
new file mode 100644
index 000000000..163c4c3a2
--- /dev/null
+++ b/Greenshot/App.config
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs b/Greenshot/AssemblyInfo.cs
similarity index 62%
rename from src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs
rename to Greenshot/AssemblyInfo.cs
index 231ca594d..efd0f77c8 100644
--- a/src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs
+++ b/Greenshot/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,20 +16,29 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
-
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyDescription("A plugin to upload images to Photobucket")]
-[assembly: AssemblyPluginIdentifier("Photobucket Plugin")]
+[assembly: AssemblyTitle("Greenshot")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Greenshot")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/Greenshot/Configuration/EditorConfiguration.cs b/Greenshot/Configuration/EditorConfiguration.cs
new file mode 100644
index 000000000..2a95136d3
--- /dev/null
+++ b/Greenshot/Configuration/EditorConfiguration.cs
@@ -0,0 +1,150 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+using Greenshot.Drawing.Fields;
+using GreenshotPlugin.UnmanagedHelpers;
+using Greenshot.IniFile;
+using GreenshotPlugin.Effects;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Configuration {
+ ///
+ /// Description of CoreConfiguration.
+ ///
+ [IniSection("Editor", Description="Greenshot editor configuration")]
+ public class EditorConfiguration : IniSection {
+ [IniProperty("RecentColors", Separator="|", Description="Last used colors")]
+ public List RecentColors { get; set; }
+
+ [IniProperty("LastFieldValue", Separator="|", Description="Field values, make sure the last used settings are re-used")]
+ public Dictionary LastUsedFieldValues { get; set; }
+
+ [IniProperty("MatchSizeToCapture", Description="Match the editor window size to the capture", DefaultValue="True")]
+ public bool MatchSizeToCapture { get; set; }
+ [IniProperty("WindowPlacementFlags", Description="Placement flags", DefaultValue="0")]
+ public WindowPlacementFlags WindowPlacementFlags { get; set; }
+ [IniProperty("WindowShowCommand", Description="Show command", DefaultValue="Normal")]
+ public ShowWindowCommand ShowWindowCommand { get; set; }
+ [IniProperty("WindowMinPosition", Description="Position of minimized window", DefaultValue="-1,-1")]
+ public Point WindowMinPosition { get; set; }
+ [IniProperty("WindowMaxPosition", Description="Position of maximized window", DefaultValue="-1,-1")]
+ public Point WindowMaxPosition { get; set; }
+ [IniProperty("WindowNormalPosition", Description="Position of normal window", DefaultValue="100,100,400,400")]
+ public Rectangle WindowNormalPosition { get; set; }
+ [IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")]
+ public bool ReuseEditor { get; set; }
+ [IniProperty("FreehandSensitivity", Description = "The smaller this number, the less smoothing is used. Decrease for detailed drawing, e.g. when using a pen. Increase for smoother lines. e.g. when you want to draw a smooth line.", DefaultValue = "3")]
+ public int FreehandSensitivity { get; set; }
+ [IniProperty("SuppressSaveDialogAtClose", Description="Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue="False")]
+ public bool SuppressSaveDialogAtClose { get; set; }
+
+ [IniProperty("DropShadowEffectSettings", Description = "Settings for the drop shadow effect.")]
+ public DropShadowEffect DropShadowEffectSettings { get; set; }
+
+ [IniProperty("TornEdgeEffectSettings", Description = "Settings for the torn edge effect.")]
+ public TornEdgeEffect TornEdgeEffectSettings { get; set; }
+
+ public override void AfterLoad() {
+ base.AfterLoad();
+ if (RecentColors == null) {
+ RecentColors = new List();
+ }
+ }
+
+ /// Type of the class for which to create the field
+ /// FieldType of the field to construct
+ ///
+ /// a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope
+ public IField CreateField(Type requestingType, IFieldType fieldType, object preferredDefaultValue)
+ {
+ string requestingTypeName = requestingType.Name;
+ string requestedField = requestingTypeName + "." + fieldType.Name;
+ object fieldValue = preferredDefaultValue;
+
+ // Check if the configuration exists
+ if (LastUsedFieldValues == null) {
+ LastUsedFieldValues = new Dictionary();
+ }
+
+ // Check if settings for the requesting type exist, if not create!
+ if (LastUsedFieldValues.ContainsKey(requestedField)) {
+ // Check if a value is set (not null)!
+ if (LastUsedFieldValues[requestedField] != null) {
+ fieldValue = LastUsedFieldValues[requestedField];
+ } else {
+ // Overwrite null value
+ LastUsedFieldValues[requestedField] = fieldValue;
+ }
+ } else {
+ LastUsedFieldValues.Add(requestedField, fieldValue);
+ }
+ return new Field(fieldType, requestingType)
+ {
+ Value = fieldValue
+ };
+ }
+
+ public void UpdateLastFieldValue(IField field)
+ {
+ string requestedField = field.Scope + "." + field.FieldType.Name;
+ // Check if the configuration exists
+ if (LastUsedFieldValues == null) {
+ LastUsedFieldValues = new Dictionary();
+ }
+ // check if settings for the requesting type exist, if not create!
+ if (LastUsedFieldValues.ContainsKey(requestedField)) {
+ LastUsedFieldValues[requestedField] = field.Value;
+ } else {
+ LastUsedFieldValues.Add(requestedField, field.Value);
+ }
+ }
+
+ public void ResetEditorPlacement()
+ {
+ WindowNormalPosition = new Rectangle(100, 100, 400, 400);
+ WindowMaxPosition = new Point(-1,-1);
+ WindowMinPosition = new Point(-1, -1);
+ WindowPlacementFlags = 0;
+ ShowWindowCommand = ShowWindowCommand.Normal;
+ }
+
+ public WindowPlacement GetEditorPlacement() {
+ WindowPlacement placement = WindowPlacement.Default;
+ placement.NormalPosition = new RECT(WindowNormalPosition);
+ placement.MaxPosition = new POINT(WindowMaxPosition);
+ placement.MinPosition = new POINT(WindowMinPosition);
+ placement.ShowCmd = ShowWindowCommand;
+ placement.Flags = WindowPlacementFlags;
+ return placement;
+ }
+
+ public void SetEditorPlacement(WindowPlacement placement) {
+ WindowNormalPosition = placement.NormalPosition.ToRectangle();
+ WindowMaxPosition = placement.MaxPosition.ToPoint();
+ WindowMinPosition = placement.MinPosition.ToPoint();
+ ShowWindowCommand = placement.ShowCmd;
+ WindowPlacementFlags = placement.Flags;
+ }
+ }
+}
diff --git a/Greenshot/Configuration/LanguageKeys.cs b/Greenshot/Configuration/LanguageKeys.cs
new file mode 100644
index 000000000..c2280f2f4
--- /dev/null
+++ b/Greenshot/Configuration/LanguageKeys.cs
@@ -0,0 +1,243 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace Greenshot.Configuration {
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ public enum LangKey {
+ none,
+ about_bugs,
+ about_donations,
+ about_host,
+ about_icons,
+ about_license,
+ about_title,
+ about_translation,
+ application_title,
+ bugreport_cancel,
+ bugreport_info,
+ bugreport_title,
+ clipboard_error,
+ clipboard_inuse,
+ colorpicker_alpha,
+ colorpicker_apply,
+ colorpicker_blue,
+ colorpicker_green,
+ colorpicker_htmlcolor,
+ colorpicker_recentcolors,
+ colorpicker_red,
+ colorpicker_title,
+ colorpicker_transparent,
+ config_unauthorizedaccess_write,
+ contextmenu_about,
+ contextmenu_capturearea,
+ contextmenu_captureclipboard,
+ contextmenu_capturefullscreen,
+ contextmenu_capturefullscreen_all,
+ contextmenu_capturefullscreen_left,
+ contextmenu_capturefullscreen_top,
+ contextmenu_capturefullscreen_right,
+ contextmenu_capturefullscreen_bottom,
+ contextmenu_capturelastregion,
+ contextmenu_capturewindow,
+ contextmenu_donate,
+ contextmenu_exit,
+ contextmenu_help,
+ contextmenu_openfile,
+ contextmenu_quicksettings,
+ contextmenu_settings,
+ contextmenu_captureie,
+ contextmenu_openrecentcapture,
+ editor_align_bottom,
+ editor_align_center,
+ editor_align_horizontal,
+ editor_align_middle,
+ editor_align_left,
+ editor_align_right,
+ editor_align_top,
+ editor_align_vertical,
+ editor_arrange,
+ editor_arrowheads,
+ editor_arrowheads_both,
+ editor_arrowheads_end,
+ editor_arrowheads_none,
+ editor_arrowheads_start,
+ editor_backcolor,
+ editor_blur_radius,
+ editor_bold,
+ editor_brightness,
+ editor_cancel,
+ editor_clipboardfailed,
+ editor_close,
+ editor_close_on_save,
+ editor_close_on_save_title,
+ editor_confirm,
+ editor_copyimagetoclipboard,
+ editor_copypathtoclipboard,
+ editor_copytoclipboard,
+ editor_crop,
+ editor_cursortool,
+ editor_cuttoclipboard,
+ editor_deleteelement,
+ editor_downonelevel,
+ editor_downtobottom,
+ editor_drawarrow,
+ editor_drawellipse,
+ editor_drawhighlighter,
+ editor_drawline,
+ editor_drawfreehand,
+ editor_drawrectangle,
+ editor_drawtextbox,
+ editor_duplicate,
+ editor_edit,
+ editor_email,
+ editor_file,
+ editor_fontsize,
+ editor_forecolor,
+ editor_highlight_area,
+ editor_highlight_grayscale,
+ editor_highlight_mode,
+ editor_highlight_text,
+ editor_highlight_magnify,
+ editor_pixel_size,
+ editor_imagesaved,
+ editor_italic,
+ editor_load_objects,
+ editor_magnification_factor,
+ editor_match_capture_size,
+ editor_obfuscate,
+ editor_obfuscate_blur,
+ editor_obfuscate_mode,
+ editor_obfuscate_pixelize,
+ editor_object,
+ editor_opendirinexplorer,
+ editor_pastefromclipboard,
+ editor_preview_quality,
+ editor_print,
+ editor_save,
+ editor_save_objects,
+ editor_saveas,
+ editor_selectall,
+ editor_senttoprinter,
+ editor_shadow,
+ editor_torn_edge,
+ editor_border,
+ editor_grayscale,
+ editor_effects,
+ editor_storedtoclipboard,
+ editor_thickness,
+ editor_title,
+ editor_uponelevel,
+ editor_uptotop,
+ editor_autocrop,
+ editor_undo,
+ editor_redo,
+ editor_insertwindow,
+ editor_resetsize,
+ error,
+ error_multipleinstances,
+ error_nowriteaccess,
+ error_openfile,
+ error_openlink,
+ error_save,
+ error_save_invalid_chars,
+ help_title,
+ jpegqualitydialog_choosejpegquality,
+ qualitydialog_dontaskagain,
+ qualitydialog_title,
+ settings_reducecolors,
+ print_error,
+ printoptions_allowcenter,
+ printoptions_allowenlarge,
+ printoptions_allowrotate,
+ printoptions_allowshrink,
+ printoptions_colors,
+ printoptions_dontaskagain,
+ printoptions_pagelayout,
+ printoptions_printcolor,
+ printoptions_printgrayscale,
+ printoptions_printmonochrome,
+ printoptions_timestamp,
+ printoptions_inverted,
+ printoptions_title,
+ quicksettings_destination_file,
+ settings_alwaysshowqualitydialog,
+ settings_alwaysshowprintoptionsdialog,
+ settings_applicationsettings,
+ settings_autostartshortcut,
+ settings_capture,
+ settings_capture_mousepointer,
+ settings_capture_windows_interactive,
+ settings_copypathtoclipboard,
+ settings_destination,
+ settings_destination_clipboard,
+ settings_destination_editor,
+ settings_destination_email,
+ settings_destination_file,
+ settings_destination_fileas,
+ settings_destination_printer,
+ settings_destination_picker,
+ settings_editor,
+ settings_filenamepattern,
+ settings_general,
+ settings_iecapture,
+ settings_jpegquality,
+ settings_qualitysettings,
+ settings_language,
+ settings_message_filenamepattern,
+ settings_output,
+ settings_playsound,
+ settings_plugins,
+ settings_plugins_name,
+ settings_plugins_version,
+ settings_plugins_createdby,
+ settings_plugins_dllpath,
+ settings_preferredfilesettings,
+ settings_primaryimageformat,
+ settings_printer,
+ settings_printoptions,
+ settings_registerhotkeys,
+ settings_showflashlight,
+ settings_storagelocation,
+ settings_title,
+ settings_tooltip_filenamepattern,
+ settings_tooltip_language,
+ settings_tooltip_primaryimageformat,
+ settings_tooltip_registerhotkeys,
+ settings_tooltip_storagelocation,
+ settings_visualization,
+ settings_shownotify,
+ settings_waittime,
+ settings_windowscapture,
+ settings_window_capture_mode,
+ settings_network,
+ settings_checkperiod,
+ settings_usedefaultproxy,
+ tooltip_firststart,
+ warning,
+ warning_hotkeys,
+ hotkeys,
+ wait_ie_capture,
+ update_found,
+ exported_to
+ }
+}
diff --git a/Greenshot/Controls/BindableToolStripButton.cs b/Greenshot/Controls/BindableToolStripButton.cs
new file mode 100644
index 000000000..7c1c50b85
--- /dev/null
+++ b/Greenshot/Controls/BindableToolStripButton.cs
@@ -0,0 +1,49 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+
+namespace Greenshot.Controls {
+ ///
+ /// Description of BindableToolStripButton.
+ ///
+ public class BindableToolStripButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ public BindableToolStripButton()
+ {
+ CheckedChanged += BindableToolStripButton_CheckedChanged;
+ }
+
+ private void BindableToolStripButton_CheckedChanged(object sender, EventArgs e)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Checked"));
+ }
+ }
+}
diff --git a/Greenshot/Controls/BindableToolStripComboBox.cs b/Greenshot/Controls/BindableToolStripComboBox.cs
new file mode 100644
index 000000000..d0f706260
--- /dev/null
+++ b/Greenshot/Controls/BindableToolStripComboBox.cs
@@ -0,0 +1,49 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+
+namespace Greenshot.Controls {
+ ///
+ /// A simple ToolStripComboBox implementing INotifyPropertyChanged for data binding
+ ///
+ public class BindableToolStripComboBox : ToolStripComboBox, INotifyPropertyChanged, IGreenshotLanguageBindable {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ public BindableToolStripComboBox()
+ {
+ SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
+ }
+
+ private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedItem"));
+ }
+ }
+}
diff --git a/Greenshot/Controls/BindableToolStripDropDownButton.cs b/Greenshot/Controls/BindableToolStripDropDownButton.cs
new file mode 100644
index 000000000..da638d481
--- /dev/null
+++ b/Greenshot/Controls/BindableToolStripDropDownButton.cs
@@ -0,0 +1,70 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+
+namespace Greenshot.Controls {
+ ///
+ /// A simple ToolStripDropDownButton implementing INotifyPropertyChanged for data binding.
+ /// Also, when a DropDownItem is selected, the DropDownButton adopts its Tag and Image.
+ /// The selected tag can be accessed via SelectedTag property.
+ ///
+ public class BindableToolStripDropDownButton : ToolStripDropDownButton, INotifyPropertyChanged, IGreenshotLanguageBindable {
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ public object SelectedTag {
+ get { if(Tag==null && DropDownItems.Count>0) Tag=DropDownItems[0].Tag; return Tag; }
+ set { AdoptFromTag(value); }
+ }
+
+ protected override void OnDropDownItemClicked(ToolStripItemClickedEventArgs e) {
+ ToolStripItem clickedItem = e.ClickedItem;
+ if(Tag == null || !Tag.Equals(clickedItem.Tag)) {
+ Tag = clickedItem.Tag;
+ Image = clickedItem.Image;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedTag"));
+ }
+ base.OnDropDownItemClicked(e);
+ }
+
+ private void AdoptFromTag(object tag) {
+ if(Tag == null || !Tag.Equals(tag)) {
+ Tag = tag;
+ foreach(ToolStripItem item in DropDownItems) {
+ if(item.Tag != null && item.Tag.Equals(tag)) {
+ Image = item.Image;
+ break;
+ }
+ }
+ Tag = tag;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedTag"));
+ }
+ }
+ }
+}
diff --git a/Greenshot/Controls/ColorButton.cs b/Greenshot/Controls/ColorButton.cs
new file mode 100644
index 000000000..a08f0afab
--- /dev/null
+++ b/Greenshot/Controls/ColorButton.cs
@@ -0,0 +1,89 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+
+namespace Greenshot.Controls {
+ ///
+ /// Description of ColorButton.
+ ///
+ public class ColorButton : Button, IGreenshotLanguageBindable {
+ public event PropertyChangedEventHandler PropertyChanged;
+ private Color _selectedColor = Color.White;
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ public ColorButton() {
+ Click += ColorButtonClick;
+ }
+
+ public Color SelectedColor {
+ get {return _selectedColor;}
+ set {
+ _selectedColor = value;
+
+ Brush brush;
+ if(value != Color.Transparent) {
+ brush = new SolidBrush(value);
+ } else {
+ brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray);
+ }
+
+ if (Image != null) {
+ using (Graphics graphics = Graphics.FromImage(Image)) {
+ graphics.FillRectangle(brush, new Rectangle(4,17,16,3));
+ }
+ }
+
+ // cleanup GDI Object
+ brush.Dispose();
+ Invalidate();
+ }
+ }
+
+ private void ColorButtonClick(object sender, EventArgs e) {
+ var colorDialog = new ColorDialog
+ {
+ Color = SelectedColor
+ };
+ // Using the parent to make sure the dialog doesn't show on another window
+ colorDialog.ShowDialog(Parent.Parent);
+ if (colorDialog.DialogResult == DialogResult.Cancel)
+ {
+ return;
+ }
+ if (colorDialog.Color.Equals(SelectedColor))
+ {
+ return;
+ }
+ SelectedColor = colorDialog.Color;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor"));
+ }
+ }
+}
diff --git a/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs b/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs
new file mode 100644
index 000000000..d3e8b5db2
--- /dev/null
+++ b/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs
@@ -0,0 +1,45 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Greenshot.Controls {
+ ///
+ /// ToolStripProfessionalRenderer which draws the Check correctly when the icons are larger
+ ///
+ public class ContextMenuToolStripProfessionalRenderer : ToolStripProfessionalRenderer {
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static Image _scaledCheckbox;
+
+ protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) {
+ if (_scaledCheckbox == null || _scaledCheckbox.Size != CoreConfig.IconSize) {
+ _scaledCheckbox?.Dispose();
+ _scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, CoreConfig.IconSize.Width, CoreConfig.IconSize.Height, null);
+ }
+ Rectangle old = e.ImageRectangle;
+ ToolStripItemImageRenderEventArgs clone = new ToolStripItemImageRenderEventArgs(e.Graphics, e.Item, _scaledCheckbox, new Rectangle(old.X, 0, old.Width, old.Height));
+ base.OnRenderItemCheck(clone);
+ }
+ }
+}
diff --git a/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs b/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs
new file mode 100644
index 000000000..bbf59f368
--- /dev/null
+++ b/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs
@@ -0,0 +1,67 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Greenshot.Controls {
+ ///
+ /// Prevent having a gradient background in the toolstrip, and the overflow button
+ /// See: http://stackoverflow.com/a/16926979
+ ///
+ internal class CustomProfessionalColorTable : ProfessionalColorTable {
+ public override Color ToolStripGradientBegin {
+ get { return SystemColors.Control; }
+ }
+ public override Color ToolStripGradientMiddle {
+ get { return SystemColors.Control; }
+ }
+ public override Color ToolStripGradientEnd {
+ get { return SystemColors.Control; }
+ }
+ public override Color OverflowButtonGradientBegin {
+ get { return SystemColors.Control; }
+ }
+ public override Color OverflowButtonGradientMiddle {
+ get { return SystemColors.Control; }
+ }
+ public override Color OverflowButtonGradientEnd {
+ get { return SystemColors.Control; }
+ }
+ }
+
+ ///
+ /// ToolStripProfessionalRenderer without having a visual artifact
+ /// See: http://stackoverflow.com/a/16926979 and http://stackoverflow.com/a/13418840
+ ///
+ public class CustomToolStripProfessionalRenderer : ToolStripProfessionalRenderer {
+ public CustomToolStripProfessionalRenderer() : base(new CustomProfessionalColorTable()) {
+ RoundedEdges = false;
+ }
+ ///
+ /// By overriding the OnRenderToolStripBorder we can make the ToolStrip without border
+ ///
+ ///
+ protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) {
+ // Don't draw a border
+ }
+ }
+}
diff --git a/Greenshot/Controls/FontFamilyComboBox.cs b/Greenshot/Controls/FontFamilyComboBox.cs
new file mode 100644
index 000000000..53a89111a
--- /dev/null
+++ b/Greenshot/Controls/FontFamilyComboBox.cs
@@ -0,0 +1,121 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Greenshot.Controls {
+ ///
+ /// ToolStripComboBox containing installed font families,
+ /// implementing INotifyPropertyChanged for data binding
+ ///
+ public class FontFamilyComboBox : ToolStripComboBox, INotifyPropertyChanged {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public FontFamily FontFamily {
+ get { return (FontFamily)SelectedItem; }
+ set {
+ if (!SelectedItem.Equals(value)) {
+ SelectedItem = value;
+ }
+ }
+ }
+
+ public FontFamilyComboBox()
+ {
+ if (ComboBox != null)
+ {
+ ComboBox.DataSource = FontFamily.Families;
+ ComboBox.DisplayMember = "Name";
+ SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
+ ComboBox.DrawMode = DrawMode.OwnerDrawFixed;
+ ComboBox.DrawItem += ComboBox_DrawItem;
+ }
+ }
+
+ private void ComboBox_DrawItem(object sender, DrawItemEventArgs e) {
+ // DrawBackground handles drawing the background (i.e,. hot-tracked v. not)
+ // It uses the system colors (Bluish, and and white, by default)
+ // same as calling e.Graphics.FillRectangle ( SystemBrushes.Highlight, e.Bounds );
+ e.DrawBackground();
+
+ if (e.Index > -1) {
+ FontFamily fontFamily = Items[e.Index] as FontFamily;
+ FontStyle fontStyle = FontStyle.Regular;
+ if (fontFamily != null && !fontFamily.IsStyleAvailable(FontStyle.Regular)) {
+ if (fontFamily.IsStyleAvailable(FontStyle.Bold)) {
+ fontStyle = FontStyle.Bold;
+ } else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) {
+ fontStyle = FontStyle.Italic;
+ } else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout)) {
+ fontStyle = FontStyle.Strikeout;
+ } else if (fontFamily.IsStyleAvailable(FontStyle.Underline)) {
+ fontStyle = FontStyle.Underline;
+ }
+ }
+ try {
+ if (fontFamily != null)
+ {
+ DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name);
+ }
+ } catch {
+ // If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular'
+ if (fontFamily != null)
+ {
+ DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name);
+ }
+ }
+ }
+ // Uncomment this if you actually like the way the focus rectangle looks
+ //e.DrawFocusRectangle ();
+ }
+
+ ///
+ /// Helper method to draw the string
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text) {
+ using (Font font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel)) {
+ // Make sure the text is visible by centering it in the line
+ using (StringFormat stringFormat = new StringFormat()) {
+ stringFormat.LineAlignment = StringAlignment.Center;
+ graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
+ }
+ }
+ }
+
+ private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (PropertyChanged != null) {
+ PropertyChanged(this, new PropertyChangedEventArgs("Text"));
+ PropertyChanged(this, new PropertyChangedEventArgs("FontFamily"));
+ PropertyChanged(this, new PropertyChangedEventArgs("SelectedIndex"));
+ PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
+
+ }
+ }
+ }
+}
diff --git a/Greenshot/Controls/MenuStripEx.cs b/Greenshot/Controls/MenuStripEx.cs
new file mode 100644
index 000000000..b8f1ab264
--- /dev/null
+++ b/Greenshot/Controls/MenuStripEx.cs
@@ -0,0 +1,61 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+
+namespace Greenshot.Controls {
+ ///
+ /// This is an extension of the default MenuStrip and allows us to click it even when the form doesn't have focus.
+ /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx
+ ///
+ public class MenuStripEx : MenuStrip {
+ private const int WM_MOUSEACTIVATE = 0x21;
+
+ private enum NativeConstants : uint {
+ MA_ACTIVATE = 1,
+ MA_ACTIVATEANDEAT = 2,
+ }
+
+ private bool _clickThrough;
+ ///
+ /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
+ ///
+ ///
+ /// Default value is false, which is the same behavior provided by the base ToolStrip class.
+ ///
+ public bool ClickThrough {
+ get {
+ return _clickThrough;
+ }
+
+ set {
+ _clickThrough = value;
+ }
+ }
+
+ protected override void WndProc(ref Message m) {
+ base.WndProc(ref m);
+ if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) {
+ m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Controls/NonJumpingPanel.cs b/Greenshot/Controls/NonJumpingPanel.cs
new file mode 100644
index 000000000..8a4747adf
--- /dev/null
+++ b/Greenshot/Controls/NonJumpingPanel.cs
@@ -0,0 +1,54 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/
+ ///
+ public class NonJumpingPanel : Panel {
+ protected override Point ScrollToControl(Control activeControl) {
+ // Returning the current location prevents the panel from
+ // scrolling to the active control when the panel loses and regains focus
+ return DisplayRectangle.Location;
+ }
+
+ ///
+ /// Add horizontal scrolling to the panel, when using the wheel and the shift key is pressed
+ ///
+ /// MouseEventArgs
+ protected override void OnMouseWheel(MouseEventArgs e)
+ {
+ if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)
+ {
+ VScroll = false;
+ base.OnMouseWheel(e);
+ VScroll = true;
+ }
+ else
+ {
+ base.OnMouseWheel(e);
+ }
+ }
+ }
+}
diff --git a/Greenshot/Controls/Pipette.cs b/Greenshot/Controls/Pipette.cs
new file mode 100644
index 000000000..662b30931
--- /dev/null
+++ b/Greenshot/Controls/Pipette.cs
@@ -0,0 +1,177 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using Greenshot.Forms;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace Greenshot.Controls {
+ ///
+ /// This code was supplied by Hi-Coder as a patch for Greenshot
+ /// Needed some modifications to be stable.
+ ///
+ public sealed class Pipette : Label, IMessageFilter, IDisposable {
+ private MovableShowColorForm _movableShowColorForm;
+ private bool _dragging;
+ private Cursor _cursor;
+ private readonly Bitmap _image;
+ private const int VkEsc = 27;
+
+ public event EventHandler PipetteUsed;
+
+ public Pipette() {
+ BorderStyle = BorderStyle.FixedSingle;
+ _dragging = false;
+ _image = (Bitmap)new ComponentResourceManager(typeof(ColorDialog)).GetObject("pipette.Image");
+ Image = _image;
+ _cursor = CreateCursor(_image, 1, 14);
+ _movableShowColorForm = new MovableShowColorForm();
+ Application.AddMessageFilter(this);
+ }
+
+ ///
+ /// Create a cursor from the supplied bitmap & hotspot coordinates
+ ///
+ /// Bitmap to create an icon from
+ /// Hotspot X coordinate
+ /// Hotspot Y coordinate
+ /// Cursor
+ private static Cursor CreateCursor(Bitmap bitmap, int hotspotX, int hotspotY) {
+ using (SafeIconHandle iconHandle = new SafeIconHandle( bitmap.GetHicon())) {
+ IconInfo iconInfo;
+ User32.GetIconInfo(iconHandle, out iconInfo);
+ iconInfo.xHotspot = hotspotX;
+ iconInfo.yHotspot = hotspotY;
+ iconInfo.fIcon = false;
+ var icon = User32.CreateIconIndirect(ref iconInfo);
+ return new Cursor(icon);
+ }
+ }
+
+ ///
+ /// The bulk of the clean-up code is implemented in Dispose(bool)
+ ///
+ public new void Dispose() {
+ Dispose(true);
+ }
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ ///
+ /// When disposing==true all non-managed resources should be freed too!
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (_cursor != null) {
+ _cursor.Dispose();
+ }
+ _movableShowColorForm?.Dispose();
+ }
+ _movableShowColorForm = null;
+ _cursor = null;
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// Handle the mouse down on the Pipette "label", we take the capture and move the zoomer to the current location
+ ///
+ /// MouseEventArgs
+ protected override void OnMouseDown(MouseEventArgs e) {
+ if (e.Button == MouseButtons.Left) {
+ User32.SetCapture(Handle);
+ _movableShowColorForm.MoveTo(PointToScreen(new Point(e.X, e.Y)));
+ }
+ base.OnMouseDown(e);
+ }
+
+ ///
+ /// Handle the mouse up on the Pipette "label", we release the capture and fire the PipetteUsed event
+ ///
+ /// MouseEventArgs
+ protected override void OnMouseUp(MouseEventArgs e) {
+ if (e.Button == MouseButtons.Left)
+ {
+ //Release Capture should consume MouseUp when canceled with the escape key
+ User32.ReleaseCapture();
+ PipetteUsed?.Invoke(this, new PipetteUsedArgs(_movableShowColorForm.color));
+ }
+ base.OnMouseUp(e);
+ }
+
+ ///
+ /// Handle the mouse Move event, we move the ColorUnderCursor to the current location.
+ ///
+ /// MouseEventArgs
+ protected override void OnMouseMove(MouseEventArgs e) {
+ if (_dragging) {
+ //display the form on the right side of the cursor by default;
+ Point zp = PointToScreen(new Point(e.X, e.Y));
+ _movableShowColorForm.MoveTo(zp);
+ }
+ base.OnMouseMove(e);
+ }
+
+ ///
+ /// Handle the MouseCaptureChanged event
+ ///
+ ///
+ protected override void OnMouseCaptureChanged(EventArgs e) {
+ if (Capture) {
+ _dragging = true;
+ Image = null;
+ Cursor c = _cursor;
+ Cursor = c;
+ _movableShowColorForm.Visible = true;
+ } else {
+ _dragging = false;
+ Image = _image;
+ Cursor = Cursors.Arrow;
+ _movableShowColorForm.Visible = false;
+ }
+ Update();
+ base.OnMouseCaptureChanged(e);
+ }
+
+ #region IMessageFilter Members
+
+ public bool PreFilterMessage(ref Message m) {
+ if (_dragging) {
+ if (m.Msg == (int)WindowsMessages.WM_CHAR) {
+ if ((int)m.WParam == VkEsc) {
+ User32.ReleaseCapture();
+ }
+ }
+ }
+ return false;
+ }
+
+ #endregion
+ }
+
+ public class PipetteUsedArgs : EventArgs {
+ public Color Color;
+
+ public PipetteUsedArgs(Color c) {
+ Color = c;
+ }
+ }
+}
diff --git a/Greenshot/Controls/ToolStripColorButton.cs b/Greenshot/Controls/ToolStripColorButton.cs
new file mode 100644
index 000000000..8f5acd7d9
--- /dev/null
+++ b/Greenshot/Controls/ToolStripColorButton.cs
@@ -0,0 +1,87 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+
+namespace Greenshot.Controls {
+ public class ToolStripColorButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ private Color _selectedColor = Color.Transparent;
+
+ public ToolStripColorButton() {
+ Click+= ColorButtonClick;
+ }
+
+ public Color SelectedColor {
+ get {return _selectedColor;}
+ set {
+ _selectedColor = value;
+
+ Brush brush;
+ if(value != Color.Transparent) {
+ brush = new SolidBrush(value);
+ } else {
+ brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray);
+ }
+
+ if (Image != null) {
+ using (Graphics graphics = Graphics.FromImage(Image)) {
+ graphics.FillRectangle(brush, new Rectangle(0,13,16,3));
+ }
+ }
+
+ // cleanup GDI Object
+ brush.Dispose();
+ Invalidate();
+ }
+ }
+
+ private void ColorButtonClick(object sender, EventArgs e) {
+ var colorDialog = new ColorDialog
+ {
+ Color = SelectedColor
+ };
+ // Using the parent to make sure the dialog doesn't show on another window
+ colorDialog.ShowDialog(Parent.Parent);
+ if (colorDialog.DialogResult == DialogResult.Cancel)
+ {
+ return;
+ }
+ if (colorDialog.Color.Equals(SelectedColor))
+ {
+ return;
+ }
+ SelectedColor = colorDialog.Color;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor"));
+ }
+ }
+}
diff --git a/Greenshot/Controls/ToolStripEx.cs b/Greenshot/Controls/ToolStripEx.cs
new file mode 100644
index 000000000..1298db21f
--- /dev/null
+++ b/Greenshot/Controls/ToolStripEx.cs
@@ -0,0 +1,62 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+
+namespace Greenshot.Controls {
+ ///
+ /// This is an extension of the default ToolStrip and allows us to click it even when the form doesn't have focus.
+ /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx
+ ///
+ internal class ToolStripEx : ToolStrip {
+ private const int WM_MOUSEACTIVATE = 0x21;
+
+ private enum NativeConstants : uint {
+ MA_ACTIVATE = 1,
+ MA_ACTIVATEANDEAT = 2,
+ }
+
+ private bool _clickThrough;
+ ///
+ /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
+ ///
+ ///
+ /// Default value is false, which is the same behavior provided by the base ToolStrip class.
+ ///
+
+ public bool ClickThrough {
+ get {
+ return _clickThrough;
+ }
+
+ set {
+ _clickThrough = value;
+ }
+ }
+
+ protected override void WndProc(ref Message m) {
+ base.WndProc(ref m);
+ if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) {
+ m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Controls/ToolStripNumericUpDown.cs b/Greenshot/Controls/ToolStripNumericUpDown.cs
new file mode 100644
index 000000000..f683f7c9b
--- /dev/null
+++ b/Greenshot/Controls/ToolStripNumericUpDown.cs
@@ -0,0 +1,79 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Windows.Forms.Design;
+
+namespace Greenshot.Controls {
+
+ [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
+ public class ToolStripNumericUpDown : ToolStripControlHost, INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public ToolStripNumericUpDown() : base(new NumericUpDown())
+ {
+ }
+
+ public NumericUpDown NumericUpDown => Control as NumericUpDown;
+
+ public decimal Value
+ {
+ get { return NumericUpDown.Value; }
+ set { NumericUpDown.Value = value;}
+ }
+ public decimal Minimum {
+ get { return NumericUpDown.Minimum; }
+ set { NumericUpDown.Minimum = value; }
+ }
+
+ public decimal Maximum {
+ get { return NumericUpDown.Maximum; }
+ set { NumericUpDown.Maximum = value; }
+ }
+
+ public decimal Increment {
+ get { return NumericUpDown.Increment; }
+ set { NumericUpDown.Increment = value; }
+ }
+
+ public int DecimalPlaces {
+ get { return NumericUpDown.DecimalPlaces; }
+ set { NumericUpDown.DecimalPlaces = value; }
+ }
+
+
+ protected override void OnSubscribeControlEvents(Control control) {
+ base.OnSubscribeControlEvents(control);
+ NumericUpDown.ValueChanged += _valueChanged;
+ }
+ protected override void OnUnsubscribeControlEvents(Control control) {
+ base.OnUnsubscribeControlEvents(control);
+ NumericUpDown.ValueChanged -= _valueChanged;
+ }
+
+ private void _valueChanged(object sender, EventArgs e)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
+ }
+ }
+}
diff --git a/Greenshot/Destinations/ClipboardDestination.cs b/Greenshot/Destinations/ClipboardDestination.cs
new file mode 100644
index 000000000..147571e78
--- /dev/null
+++ b/Greenshot/Destinations/ClipboardDestination.cs
@@ -0,0 +1,78 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of ClipboardDestination.
+ ///
+ public class ClipboardDestination : AbstractDestination {
+ public const string DESIGNATION = "Clipboard";
+
+ public override string Designation {
+ get {
+ return DESIGNATION;
+ }
+ }
+
+ public override string Description {
+ get {
+ return Language.GetString(LangKey.settings_destination_clipboard);
+ }
+ }
+ public override int Priority {
+ get {
+ return 2;
+ }
+ }
+
+ public override Keys EditorShortcutKeys {
+ get {
+ return Keys.Control | Keys.Shift | Keys.C;
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return GreenshotResources.getImage("Clipboard.Image");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ try {
+ ClipboardHelper.SetClipboardData(surface);
+ exportInformation.ExportMade = true;
+ } catch (Exception) {
+ // TODO: Change to general logic in ProcessExport
+ surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetString(LangKey.editor_clipboardfailed));
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/Greenshot/Destinations/EditorDestination.cs b/Greenshot/Destinations/EditorDestination.cs
new file mode 100644
index 000000000..ab66cd04e
--- /dev/null
+++ b/Greenshot/Destinations/EditorDestination.cs
@@ -0,0 +1,137 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of EditorDestination.
+ ///
+ public class EditorDestination : AbstractDestination {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(EditorDestination));
+ private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection();
+ public const string DESIGNATION = "Editor";
+ private readonly IImageEditor editor;
+ private static readonly Image greenshotIcon = GreenshotResources.getGreenshotIcon().ToBitmap();
+
+ public EditorDestination() {
+ }
+
+ public EditorDestination(IImageEditor editor) {
+ this.editor = editor;
+ }
+
+ public override string Designation {
+ get {
+ return DESIGNATION;
+ }
+ }
+
+ public override string Description {
+ get {
+ if (editor == null) {
+ return Language.GetString(LangKey.settings_destination_editor);
+ }
+ return Language.GetString(LangKey.settings_destination_editor) + " - " + editor.CaptureDetails.Title;
+ }
+ }
+
+ public override int Priority {
+ get {
+ return 1;
+ }
+ }
+
+ public override bool IsDynamic {
+ get {
+ return true;
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return greenshotIcon;
+ }
+ }
+
+ public override IEnumerable DynamicDestinations() {
+ foreach (IImageEditor someEditor in ImageEditorForm.Editors) {
+ yield return new EditorDestination(someEditor);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ // Make sure we collect the garbage before opening the screenshot
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ bool modified = surface.Modified;
+ if (editor == null) {
+ if (editorConfiguration.ReuseEditor) {
+ foreach(IImageEditor openedEditor in ImageEditorForm.Editors) {
+ if (!openedEditor.Surface.Modified) {
+ openedEditor.Surface = surface;
+ exportInformation.ExportMade = true;
+ break;
+ }
+ }
+ }
+ if (!exportInformation.ExportMade) {
+ try {
+ ImageEditorForm editorForm = new ImageEditorForm(surface, !surface.Modified); // Output made??
+
+ if (!string.IsNullOrEmpty(captureDetails.Filename)) {
+ editorForm.SetImagePath(captureDetails.Filename);
+ }
+ editorForm.Show();
+ editorForm.Activate();
+ LOG.Debug("Finished opening Editor");
+ exportInformation.ExportMade = true;
+ } catch (Exception e) {
+ LOG.Error(e);
+ exportInformation.ErrorMessage = e.Message;
+ }
+ }
+ } else {
+ try {
+ using (Image image = surface.GetImageForExport()) {
+ editor.Surface.AddImageContainer(image, 10, 10);
+ }
+ exportInformation.ExportMade = true;
+ } catch (Exception e) {
+ LOG.Error(e);
+ exportInformation.ErrorMessage = e.Message;
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ // Workaround for the modified flag when using the editor.
+ surface.Modified = modified;
+ return exportInformation;
+ }
+ }
+}
diff --git a/Greenshot/Destinations/EmailDestination.cs b/Greenshot/Destinations/EmailDestination.cs
new file mode 100644
index 000000000..5c6b7e013
--- /dev/null
+++ b/Greenshot/Destinations/EmailDestination.cs
@@ -0,0 +1,94 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using Greenshot.Helpers;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of EmailDestination.
+ ///
+ public class EmailDestination : AbstractDestination {
+ private static readonly Image MailIcon = GreenshotResources.getImage("Email.Image");
+ private static bool _isActiveFlag;
+ private static string _mapiClient;
+ public const string DESIGNATION = "EMail";
+
+ static EmailDestination() {
+ // Logic to decide what email implementation we use
+ if (EmailConfigHelper.HasMapi()) {
+ _isActiveFlag = true;
+ _mapiClient = EmailConfigHelper.GetMapiClient();
+ if (!string.IsNullOrEmpty(_mapiClient)) {
+ // Active as we have a mapi client, can be disabled later
+ _isActiveFlag = true;
+ }
+ }
+ }
+
+ public override string Designation => DESIGNATION;
+
+ public override string Description {
+ get {
+ // Make sure there is some kind of "mail" name
+ if (_mapiClient == null) {
+ _mapiClient = Language.GetString(LangKey.editor_email);
+ }
+ return _mapiClient;
+ }
+ }
+
+ public override int Priority => 3;
+
+ public override bool IsActive {
+ get {
+ if (_isActiveFlag) {
+ // Disable if the office plugin is installed and the client is outlook
+ // TODO: Change this! It always creates an exception, as the plugin has not been loaded the type is not there :(
+ Type outlookdestination = Type.GetType("GreenshotOfficePlugin.OutlookDestination,GreenshotOfficePlugin");
+ if (outlookdestination != null) {
+ if (_mapiClient.ToLower().Contains("microsoft outlook")) {
+ _isActiveFlag = false;
+ }
+ }
+ }
+ return base.IsActive && _isActiveFlag;
+ }
+ }
+
+ public override Keys EditorShortcutKeys => Keys.Control | Keys.E;
+
+ public override Image DisplayIcon => MailIcon;
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ MapiMailMessage.SendImage(surface, captureDetails);
+ exportInformation.ExportMade = true;
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Greenshot/Destinations/FileDestination.cs b/Greenshot/Destinations/FileDestination.cs
new file mode 100644
index 000000000..daada3f41
--- /dev/null
+++ b/Greenshot/Destinations/FileDestination.cs
@@ -0,0 +1,141 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.IniFile;
+using GreenshotPlugin.Controls;
+using log4net;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of FileSaveAsDestination.
+ ///
+ public class FileDestination : AbstractDestination {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(FileDestination));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ public const string DESIGNATION = "FileNoDialog";
+
+ public override string Designation => DESIGNATION;
+
+ public override string Description => Language.GetString(LangKey.quicksettings_destination_file);
+
+ public override int Priority => 0;
+
+ public override Keys EditorShortcutKeys => Keys.Control | Keys.S;
+
+ public override Image DisplayIcon => GreenshotResources.getImage("Save.Image");
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ bool outputMade;
+ bool overwrite;
+ string fullPath;
+ // Get output settings from the configuration
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
+
+ if (captureDetails?.Filename != null) {
+ // As we save a pre-selected file, allow to overwrite.
+ overwrite = true;
+ Log.InfoFormat("Using previous filename");
+ fullPath = captureDetails.Filename;
+ outputSettings.Format = ImageOutput.FormatForFilename(fullPath);
+ } else {
+ fullPath = CreateNewFilename(captureDetails);
+ // As we generate a file, the configuration tells us if we allow to overwrite
+ overwrite = CoreConfig.OutputFileAllowOverwrite;
+ }
+ if (CoreConfig.OutputFilePromptQuality) {
+ QualityDialog qualityDialog = new QualityDialog(outputSettings);
+ qualityDialog.ShowDialog();
+ }
+
+ // Catching any exception to prevent that the user can't write in the directory.
+ // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642
+ try {
+ ImageOutput.Save(surface, fullPath, overwrite, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
+ outputMade = true;
+ } catch (ArgumentException ex1) {
+ // Our generated filename exists, display 'save-as'
+ Log.InfoFormat("Not overwriting: {0}", ex1.Message);
+ // when we don't allow to overwrite present a new SaveWithDialog
+ fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
+ outputMade = fullPath != null;
+ } catch (Exception ex2) {
+ Log.Error("Error saving screenshot!", ex2);
+ // Show the problem
+ MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error));
+ // when save failed we present a SaveWithDialog
+ fullPath = ImageOutput.SaveWithDialog(surface, captureDetails);
+ outputMade = fullPath != null;
+ }
+ // Don't overwrite filename if no output is made
+ if (outputMade) {
+ exportInformation.ExportMade = true;
+ exportInformation.Filepath = fullPath;
+ if (captureDetails != null)
+ {
+ captureDetails.Filename = fullPath;
+ }
+ CoreConfig.OutputFileAsFullpath = fullPath;
+ }
+
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+
+ private static string CreateNewFilename(ICaptureDetails captureDetails) {
+ string fullPath;
+ Log.InfoFormat("Creating new filename");
+ string pattern = CoreConfig.OutputFileFilenamePattern;
+ if (string.IsNullOrEmpty(pattern)) {
+ pattern = "greenshot ${capturetime}";
+ }
+ string filename = FilenameHelper.GetFilenameFromPattern(pattern, CoreConfig.OutputFileFormat, captureDetails);
+ CoreConfig.ValidateAndCorrectOutputFilePath();
+ string filepath = FilenameHelper.FillVariables(CoreConfig.OutputFilePath, false);
+ try {
+ fullPath = Path.Combine(filepath, filename);
+ } catch (ArgumentException) {
+ // configured filename or path not valid, show error message...
+ Log.InfoFormat("Generated path or filename not valid: {0}, {1}", filepath, filename);
+
+ MessageBox.Show(Language.GetString(LangKey.error_save_invalid_chars), Language.GetString(LangKey.error));
+ // ... lets get the pattern fixed....
+ var dialogResult = new SettingsForm().ShowDialog();
+ if (dialogResult == DialogResult.OK) {
+ // ... OK -> then try again:
+ fullPath = CreateNewFilename(captureDetails);
+ } else {
+ // ... cancelled.
+ fullPath = null;
+ }
+
+ }
+ return fullPath;
+ }
+ }
+}
diff --git a/Greenshot/Destinations/FileWithDialogDestination.cs b/Greenshot/Destinations/FileWithDialogDestination.cs
new file mode 100644
index 000000000..a33332cca
--- /dev/null
+++ b/Greenshot/Destinations/FileWithDialogDestination.cs
@@ -0,0 +1,82 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.IniFile;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of FileWithDialog.
+ ///
+ public class FileWithDialogDestination : AbstractDestination {
+ private static readonly CoreConfiguration conf = IniConfig.GetIniSection();
+ public const string DESIGNATION = "FileDialog";
+
+ public override string Designation {
+ get {
+ return DESIGNATION;
+ }
+ }
+
+ public override string Description {
+ get {
+ return Language.GetString(LangKey.settings_destination_fileas);
+ }
+ }
+
+ public override int Priority {
+ get {
+ return 0;
+ }
+ }
+
+ public override Keys EditorShortcutKeys {
+ get {
+ return Keys.Control | Keys.Shift | Keys.S;
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return GreenshotResources.getImage("Save.Image");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ // Bug #2918756 don't overwrite path if SaveWithDialog returns null!
+ var savedTo = ImageOutput.SaveWithDialog(surface, captureDetails);
+ if (savedTo != null) {
+ exportInformation.ExportMade = true;
+ exportInformation.Filepath = savedTo;
+ captureDetails.Filename = savedTo;
+ conf.OutputFileAsFullpath = savedTo;
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/Greenshot/Destinations/PickerDestination.cs b/Greenshot/Destinations/PickerDestination.cs
new file mode 100644
index 000000000..6a7fc29be
--- /dev/null
+++ b/Greenshot/Destinations/PickerDestination.cs
@@ -0,0 +1,65 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.Helpers;
+
+namespace Greenshot.Destinations {
+ ///
+ /// The PickerDestination shows a context menu with all possible destinations, so the user can "pick" one
+ ///
+ public class PickerDestination : AbstractDestination {
+ public const string DESIGNATION = "Picker";
+
+ public override string Designation => DESIGNATION;
+
+ public override string Description => Language.GetString(LangKey.settings_destination_picker);
+
+ public override int Priority => 1;
+
+
+ ///
+ /// Export the capture with the destination picker
+ ///
+ /// Did the user select this destination?
+ /// Surface to export
+ /// Details of the capture
+ /// true if export was made
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ List destinations = new List();
+ foreach(IDestination destination in DestinationHelper.GetAllDestinations()) {
+ if ("Picker".Equals(destination.Designation)) {
+ continue;
+ }
+ if (!destination.IsActive) {
+ continue;
+ }
+ destinations.Add(destination);
+ }
+
+ // No Processing, this is done in the selected destination (if anything was selected)
+ return ShowPickerMenu(true, surface, captureDetails, destinations);
+ }
+ }
+}
diff --git a/Greenshot/Destinations/PrinterDestination.cs b/Greenshot/Destinations/PrinterDestination.cs
new file mode 100644
index 000000000..8fa0c5f2e
--- /dev/null
+++ b/Greenshot/Destinations/PrinterDestination.cs
@@ -0,0 +1,143 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Printing;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.Helpers;
+
+namespace Greenshot.Destinations {
+ ///
+ /// Description of PrinterDestination.
+ ///
+ public class PrinterDestination : AbstractDestination {
+ public const string DESIGNATION = "Printer";
+ public readonly string printerName;
+
+ public PrinterDestination() {
+ }
+
+ public PrinterDestination(string printerName) {
+ this.printerName = printerName;
+ }
+ public override string Designation {
+ get {
+ return DESIGNATION;
+ }
+ }
+
+ public override string Description {
+ get {
+ if (printerName != null) {
+ return Language.GetString(LangKey.settings_destination_printer) + " - " + printerName;
+ }
+ return Language.GetString(LangKey.settings_destination_printer);
+ }
+ }
+
+ public override int Priority {
+ get {
+ return 2;
+ }
+ }
+
+ public override Keys EditorShortcutKeys {
+ get {
+ return Keys.Control | Keys.P;
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return GreenshotResources.getImage("Printer.Image");
+ }
+ }
+
+ public override bool IsDynamic {
+ get {
+ return true;
+ }
+ }
+
+ ///
+ /// Create destinations for all the installed printers
+ ///
+ /// IEnumerable of IDestination
+ public override IEnumerable DynamicDestinations() {
+ PrinterSettings settings = new PrinterSettings();
+ string defaultPrinter = settings.PrinterName;
+ List printers = new List();
+
+ foreach (string printer in PrinterSettings.InstalledPrinters) {
+ printers.Add(printer);
+ }
+ printers.Sort(delegate(string p1, string p2) {
+ if(defaultPrinter.Equals(p1)) {
+ return -1;
+ }
+ if(defaultPrinter.Equals(p2)) {
+ return 1;
+ }
+ return p1.CompareTo(p2);
+ });
+ foreach(string printer in printers) {
+ yield return new PrinterDestination(printer);
+ }
+ }
+
+ ///
+ /// Export the capture to the printer
+ ///
+ ///
+ ///
+ ///
+ /// ExportInformation
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ PrinterSettings printerSettings;
+ if (!string.IsNullOrEmpty(printerName)) {
+ using (PrintHelper printHelper = new PrintHelper(surface, captureDetails)) {
+ printerSettings = printHelper.PrintTo(printerName);
+ }
+ } else if (!manuallyInitiated) {
+ PrinterSettings settings = new PrinterSettings();
+ using (PrintHelper printHelper = new PrintHelper(surface, captureDetails)) {
+ printerSettings = printHelper.PrintTo(settings.PrinterName);
+ }
+ } else {
+ using (PrintHelper printHelper = new PrintHelper(surface, captureDetails)) {
+ printerSettings = printHelper.PrintWithDialog();
+ }
+ }
+ if (printerSettings != null) {
+ exportInformation.ExportMade = true;
+ }
+
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Adorners/AbstractAdorner.cs b/Greenshot/Drawing/Adorners/AbstractAdorner.cs
new file mode 100644
index 000000000..886abf937
--- /dev/null
+++ b/Greenshot/Drawing/Adorners/AbstractAdorner.cs
@@ -0,0 +1,146 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin.Drawing;
+using Greenshot.Plugin.Drawing.Adorners;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing.Adorners
+{
+ public class AbstractAdorner : IAdorner
+ {
+ public virtual EditStatus EditStatus { get; protected set; } = EditStatus.IDLE;
+
+ protected Size _size = new Size(4, 4);
+
+ public AbstractAdorner(IDrawableContainer owner)
+ {
+ Owner = owner;
+ }
+
+ ///
+ /// Returns the cursor for when the mouse is over the adorner
+ ///
+ public virtual Cursor Cursor
+ {
+ get
+ {
+ return Cursors.SizeAll;
+ }
+ }
+
+ public virtual IDrawableContainer Owner
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Test if the point is inside the adorner
+ ///
+ ///
+ ///
+ public virtual bool HitTest(Point point)
+ {
+ Rectangle hitBounds = Bounds;
+ hitBounds.Inflate(3, 3);
+ return hitBounds.Contains(point);
+ }
+
+ ///
+ /// Handle the mouse down
+ ///
+ ///
+ ///
+ public virtual void MouseDown(object sender, MouseEventArgs mouseEventArgs)
+ {
+ }
+
+ ///
+ /// Handle the mouse move
+ ///
+ ///
+ ///
+ public virtual void MouseMove(object sender, MouseEventArgs mouseEventArgs)
+ {
+ }
+
+ ///
+ /// Handle the mouse up
+ ///
+ ///
+ ///
+ public virtual void MouseUp(object sender, MouseEventArgs mouseEventArgs)
+ {
+ EditStatus = EditStatus.IDLE;
+ }
+
+ ///
+ /// Return the location of the adorner
+ ///
+ public virtual Point Location
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Return the bounds of the Adorner
+ ///
+ public virtual Rectangle Bounds
+ {
+ get
+ {
+ Point location = Location;
+ return new Rectangle(location.X - (_size.Width / 2), location.Y - (_size.Height / 2), _size.Width, _size.Height);
+ }
+ }
+
+ ///
+ /// The adorner is active if the edit status is not idle or undrawn
+ ///
+ public virtual bool IsActive
+ {
+ get
+ {
+ return EditStatus != EditStatus.IDLE && EditStatus != EditStatus.UNDRAWN;
+ }
+ }
+
+ ///
+ /// Draw the adorner
+ ///
+ /// PaintEventArgs
+ public virtual void Paint(PaintEventArgs paintEventArgs)
+ {
+ }
+
+ ///
+ /// We ignore the Transform, as the coordinates are directly bound to those of the owner
+ ///
+ ///
+ public virtual void Transform(Matrix matrix)
+ {
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Adorners/MoveAdorner.cs b/Greenshot/Drawing/Adorners/MoveAdorner.cs
new file mode 100644
index 000000000..6e0aed9c7
--- /dev/null
+++ b/Greenshot/Drawing/Adorners/MoveAdorner.cs
@@ -0,0 +1,164 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing.Adorners
+{
+ ///
+ /// This is the adorner for the line based containers
+ ///
+ public class MoveAdorner : AbstractAdorner
+ {
+ private Rectangle _boundsBeforeResize = Rectangle.Empty;
+ private RectangleF _boundsAfterResize = RectangleF.Empty;
+
+ public Positions Position { get; private set; }
+
+ public MoveAdorner(IDrawableContainer owner, Positions position) : base(owner)
+ {
+ Position = position;
+ }
+
+ ///
+ /// Returns the cursor for when the mouse is over the adorner
+ ///
+ public override Cursor Cursor => Cursors.SizeAll;
+
+ ///
+ /// Handle the mouse down
+ ///
+ ///
+ ///
+ public override void MouseDown(object sender, MouseEventArgs mouseEventArgs)
+ {
+ EditStatus = EditStatus.RESIZING;
+ _boundsBeforeResize = new Rectangle(Owner.Left, Owner.Top, Owner.Width, Owner.Height);
+ _boundsAfterResize = _boundsBeforeResize;
+ }
+
+ ///
+ /// Handle the mouse move
+ ///
+ ///
+ ///
+ public override void MouseMove(object sender, MouseEventArgs mouseEventArgs)
+ {
+ if (EditStatus != EditStatus.RESIZING)
+ {
+ return;
+ }
+ Owner.Invalidate();
+ Owner.MakeBoundsChangeUndoable(false);
+
+ // reset "workbench" rectangle to current bounds
+ _boundsAfterResize.X = _boundsBeforeResize.X;
+ _boundsAfterResize.Y = _boundsBeforeResize.Y;
+ _boundsAfterResize.Width = _boundsBeforeResize.Width;
+ _boundsAfterResize.Height = _boundsBeforeResize.Height;
+
+ // calculate scaled rectangle
+ ScaleHelper.Scale(ref _boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), ScaleHelper.GetScaleOptions());
+
+ // apply scaled bounds to this DrawableContainer
+ Owner.ApplyBounds(_boundsAfterResize);
+
+ Owner.Invalidate();
+ }
+
+ ///
+ /// Return the location of the adorner
+ ///
+ public override Point Location {
+ get
+ {
+ int x = 0,y = 0;
+ switch (Position)
+ {
+ case Positions.TopLeft:
+ x = Owner.Left;
+ y = Owner.Top;
+ break;
+ case Positions.BottomLeft:
+ x = Owner.Left;
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.MiddleLeft:
+ x = Owner.Left;
+ y = Owner.Top + (Owner.Height / 2);
+ break;
+ case Positions.TopCenter:
+ x = Owner.Left + (Owner.Width / 2);
+ y = Owner.Top;
+ break;
+ case Positions.BottomCenter:
+ x = Owner.Left + (Owner.Width / 2);
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.TopRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top;
+ break;
+ case Positions.BottomRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.MiddleRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top + (Owner.Height / 2);
+ break;
+ }
+ return new Point(x, y);
+ }
+ }
+
+ ///
+ /// Draw the adorner
+ ///
+ /// PaintEventArgs
+ public override void Paint(PaintEventArgs paintEventArgs)
+ {
+ Graphics targetGraphics = paintEventArgs.Graphics;
+
+ var bounds = Bounds;
+ GraphicsState state = targetGraphics.Save();
+
+ targetGraphics.SmoothingMode = SmoothingMode.None;
+ targetGraphics.CompositingMode = CompositingMode.SourceCopy;
+ targetGraphics.PixelOffsetMode = PixelOffsetMode.Half;
+ targetGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+
+ try
+ {
+ targetGraphics.FillRectangle(Brushes.Black, bounds.X, bounds.Y, bounds.Width, bounds.Height);
+ }
+ catch
+ {
+ // Ignore, BUG-2065
+ }
+ targetGraphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Adorners/ResizeAdorner.cs b/Greenshot/Drawing/Adorners/ResizeAdorner.cs
new file mode 100644
index 000000000..55635e098
--- /dev/null
+++ b/Greenshot/Drawing/Adorners/ResizeAdorner.cs
@@ -0,0 +1,184 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing.Adorners
+{
+ ///
+ /// This is the default "legacy" gripper adorner, not the one used for the tail in the speech-bubble
+ ///
+ public class ResizeAdorner : AbstractAdorner
+ {
+ private Rectangle _boundsBeforeResize = Rectangle.Empty;
+ private RectangleF _boundsAfterResize = RectangleF.Empty;
+
+ public Positions Position { get; private set; }
+
+ public ResizeAdorner(IDrawableContainer owner, Positions position) : base(owner)
+ {
+ Position = position;
+ }
+
+ ///
+ /// Returns the cursor for when the mouse is over the adorner
+ ///
+ public override Cursor Cursor
+ {
+ get
+ {
+ bool isNotSwitched = Owner.Width >= 0;
+ if (Owner.Height < 0)
+ {
+ isNotSwitched = !isNotSwitched;
+ }
+ switch (Position)
+ {
+ case Positions.TopLeft:
+ case Positions.BottomRight:
+ return isNotSwitched ? Cursors.SizeNWSE : Cursors.SizeNESW;
+ case Positions.TopRight:
+ case Positions.BottomLeft:
+ return isNotSwitched ? Cursors.SizeNESW : Cursors.SizeNWSE;
+ case Positions.MiddleLeft:
+ case Positions.MiddleRight:
+ return Cursors.SizeWE;
+ case Positions.TopCenter:
+ case Positions.BottomCenter:
+ return Cursors.SizeNS;
+ default:
+ return Cursors.SizeAll;
+ }
+ }
+ }
+
+ ///
+ /// Handle the mouse down
+ ///
+ ///
+ ///
+ public override void MouseDown(object sender, MouseEventArgs mouseEventArgs)
+ {
+ EditStatus = EditStatus.RESIZING;
+ _boundsBeforeResize = new Rectangle(Owner.Left, Owner.Top, Owner.Width, Owner.Height);
+ _boundsAfterResize = _boundsBeforeResize;
+ }
+
+ ///
+ /// Handle the mouse move
+ ///
+ ///
+ ///
+ public override void MouseMove(object sender, MouseEventArgs mouseEventArgs)
+ {
+ if (EditStatus != EditStatus.RESIZING)
+ {
+ return;
+ }
+ Owner.Invalidate();
+ Owner.MakeBoundsChangeUndoable(false);
+
+ // reset "workbench" rectangle to current bounds
+ _boundsAfterResize.X = _boundsBeforeResize.X;
+ _boundsAfterResize.Y = _boundsBeforeResize.Y;
+ _boundsAfterResize.Width = _boundsBeforeResize.Width;
+ _boundsAfterResize.Height = _boundsBeforeResize.Height;
+
+ // calculate scaled rectangle
+ ScaleHelper.Scale(ref _boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), ScaleHelper.GetScaleOptions());
+
+ // apply scaled bounds to this DrawableContainer
+ Owner.ApplyBounds(_boundsAfterResize);
+
+ Owner.Invalidate();
+ }
+
+ ///
+ /// Return the location of the adorner
+ ///
+ public override Point Location {
+ get
+ {
+ int x = 0,y = 0;
+ switch (Position)
+ {
+ case Positions.TopLeft:
+ x = Owner.Left;
+ y = Owner.Top;
+ break;
+ case Positions.BottomLeft:
+ x = Owner.Left;
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.MiddleLeft:
+ x = Owner.Left;
+ y = Owner.Top + (Owner.Height / 2);
+ break;
+ case Positions.TopCenter:
+ x = Owner.Left + (Owner.Width / 2);
+ y = Owner.Top;
+ break;
+ case Positions.BottomCenter:
+ x = Owner.Left + (Owner.Width / 2);
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.TopRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top;
+ break;
+ case Positions.BottomRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top + Owner.Height;
+ break;
+ case Positions.MiddleRight:
+ x = Owner.Left + Owner.Width;
+ y = Owner.Top + (Owner.Height / 2);
+ break;
+ }
+ return new Point(x, y);
+ }
+ }
+
+ ///
+ /// Draw the adorner
+ ///
+ /// PaintEventArgs
+ public override void Paint(PaintEventArgs paintEventArgs)
+ {
+ Graphics targetGraphics = paintEventArgs.Graphics;
+
+ var bounds = Bounds;
+ GraphicsState state = targetGraphics.Save();
+
+ targetGraphics.SmoothingMode = SmoothingMode.None;
+ targetGraphics.CompositingMode = CompositingMode.SourceCopy;
+ targetGraphics.PixelOffsetMode = PixelOffsetMode.Half;
+ targetGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+
+ targetGraphics.FillRectangle(Brushes.Black, bounds.X, bounds.Y, bounds.Width , bounds.Height);
+ targetGraphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Adorners/TargetAdorner.cs b/Greenshot/Drawing/Adorners/TargetAdorner.cs
new file mode 100644
index 000000000..92c51b5b9
--- /dev/null
+++ b/Greenshot/Drawing/Adorners/TargetAdorner.cs
@@ -0,0 +1,118 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin.Drawing;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing.Adorners
+{
+ ///
+ /// This implements the special "gripper" for the Speech-Bubble tail
+ ///
+ public class TargetAdorner : AbstractAdorner
+ {
+
+ public TargetAdorner(IDrawableContainer owner, Point location) : base(owner)
+ {
+ Location = location;
+ }
+
+ ///
+ /// Handle the mouse down
+ ///
+ ///
+ ///
+ public override void MouseDown(object sender, MouseEventArgs mouseEventArgs)
+ {
+ EditStatus = EditStatus.MOVING;
+ }
+
+ ///
+ /// Handle the mouse move
+ ///
+ ///
+ ///
+ public override void MouseMove(object sender, MouseEventArgs mouseEventArgs)
+ {
+ if (EditStatus != EditStatus.MOVING)
+ {
+ return;
+ }
+
+ Owner.Invalidate();
+ Point newGripperLocation = new Point(mouseEventArgs.X, mouseEventArgs.Y);
+ Rectangle surfaceBounds = new Rectangle(0, 0, Owner.Parent.Width, Owner.Parent.Height);
+ // Check if gripper inside the parent (surface), if not we need to move it inside
+ // This was made for BUG-1682
+ if (!surfaceBounds.Contains(newGripperLocation))
+ {
+ if (newGripperLocation.X > surfaceBounds.Right)
+ {
+ newGripperLocation.X = surfaceBounds.Right - 5;
+ }
+ if (newGripperLocation.X < surfaceBounds.Left)
+ {
+ newGripperLocation.X = surfaceBounds.Left;
+ }
+ if (newGripperLocation.Y > surfaceBounds.Bottom)
+ {
+ newGripperLocation.Y = surfaceBounds.Bottom - 5;
+ }
+ if (newGripperLocation.Y < surfaceBounds.Top)
+ {
+ newGripperLocation.Y = surfaceBounds.Top;
+ }
+ }
+
+ Location = newGripperLocation;
+ Owner.Invalidate();
+ }
+
+ ///
+ /// Draw the adorner
+ ///
+ /// PaintEventArgs
+ public override void Paint(PaintEventArgs paintEventArgs)
+ {
+ Graphics targetGraphics = paintEventArgs.Graphics;
+
+ var bounds = Bounds;
+ targetGraphics.FillRectangle(Brushes.Green, bounds.X, bounds.Y, bounds.Width, bounds.Height);
+ }
+
+ ///
+ /// Made sure this adorner is transformed
+ ///
+ /// Matrix
+ public override void Transform(Matrix matrix)
+ {
+ if (matrix == null)
+ {
+ return;
+ }
+ Point[] points = new[] { Location };
+ matrix.TransformPoints(points);
+ Location = points[0];
+ }
+ }
+}
diff --git a/Greenshot/Drawing/ArrowContainer.cs b/Greenshot/Drawing/ArrowContainer.cs
new file mode 100644
index 000000000..e79475c6d
--- /dev/null
+++ b/Greenshot/Drawing/ArrowContainer.cs
@@ -0,0 +1,140 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of LineContainer.
+ ///
+ [Serializable()]
+ public class ArrowContainer : LineContainer {
+ public enum ArrowHeadCombination { NONE, START_POINT, END_POINT, BOTH };
+
+ private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6);
+
+ public ArrowContainer(Surface parent) : base(parent) {
+ }
+
+ ///
+ /// Do not use the base, just override so we have our own defaults
+ ///
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.ARROWHEADS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
+ AddField(GetType(), FieldType.SHADOW, true);
+ AddField(GetType(), FieldType.ARROWHEADS, ArrowHeadCombination.END_POINT);
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+
+ if (lineThickness > 0 ) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ ArrowHeadCombination heads = (ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS);
+ if (lineThickness > 0) {
+ if (shadow) {
+ //draw shadow first
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = 1;
+ while (currentStep <= steps) {
+ using (Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) {
+ SetArrowHeads(heads, shadowCapPen);
+
+ graphics.DrawLine(shadowCapPen,
+ Left + currentStep,
+ Top + currentStep,
+ Left + currentStep + Width,
+ Top + currentStep + Height);
+
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+
+ }
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ SetArrowHeads(heads, pen);
+ graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
+ }
+ }
+ }
+ }
+
+ private void SetArrowHeads(ArrowHeadCombination heads, Pen pen) {
+ if ( heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.START_POINT ) {
+ pen.CustomStartCap = ARROW_CAP;
+ }
+ if ( heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.END_POINT ) {
+ pen.CustomEndCap = ARROW_CAP;
+ }
+ }
+
+ public override Rectangle DrawingBounds {
+ get {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(Color.White)) {
+ pen.Width = lineThickness;
+ SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen);
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddLine(Left, Top, Left + Width, Top + Height);
+ using (Matrix matrix = new Matrix()) {
+ Rectangle drawingBounds = Rectangle.Round(path.GetBounds(matrix, pen));
+ drawingBounds.Inflate(2, 2);
+ return drawingBounds;
+ }
+ }
+ }
+ }
+ return Rectangle.Empty;
+ }
+ }
+
+ public override bool ClickableAt(int x, int y) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(Color.White)) {
+ pen.Width = lineThickness;
+ SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen);
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddLine(Left, Top, Left + Width, Top + Height);
+ return path.IsOutlineVisible(x, y, pen);
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/CropContainer.cs b/Greenshot/Drawing/CropContainer.cs
new file mode 100644
index 000000000..1eb22d151
--- /dev/null
+++ b/Greenshot/Drawing/CropContainer.cs
@@ -0,0 +1,91 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+using System.Runtime.Serialization;
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of CropContainer.
+ ///
+ public class CropContainer : DrawableContainer {
+ public CropContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.FLAGS, FieldFlag.CONFIRMABLE);
+ }
+
+ public override void Invalidate() {
+ _parent?.Invalidate();
+ }
+
+ ///
+ /// We need to override the DrawingBound, return a rectangle in the size of the image, to make sure this element is always draw
+ /// (we create a transparent brown over the complete picture)
+ ///
+ public override Rectangle DrawingBounds => new Rectangle(0,0,_parent?.Width??0, _parent?.Height ?? 0);
+
+ public override void Draw(Graphics g, RenderMode rm) {
+ if (_parent == null)
+ {
+ return;
+ }
+ using (Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100))) {
+ Rectangle cropRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ Rectangle selectionRect = new Rectangle(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1);
+
+ DrawSelectionBorder(g, selectionRect);
+
+ // top
+ g.FillRectangle(cropBrush, new Rectangle(0, 0, _parent.Width, cropRectangle.Top));
+ // left
+ g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
+ // right
+ g.FillRectangle(cropBrush, new Rectangle(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, _parent.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
+ // bottom
+ g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top + cropRectangle.Height, _parent.Width, _parent.Height - (cropRectangle.Top + cropRectangle.Height)));
+ }
+ }
+
+ public override bool HasContextMenu {
+ get {
+ // No context menu for the CropContainer
+ return false;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/CursorContainer.cs b/Greenshot/Drawing/CursorContainer.cs
new file mode 100644
index 000000000..b1f67fd24
--- /dev/null
+++ b/Greenshot/Drawing/CursorContainer.cs
@@ -0,0 +1,115 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+using Greenshot.Plugin.Drawing;
+using System.Drawing.Drawing2D;
+using log4net;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of CursorContainer.
+ ///
+ [Serializable]
+ public class CursorContainer : DrawableContainer, ICursorContainer {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(CursorContainer));
+
+ protected Cursor cursor;
+
+ public CursorContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ public CursorContainer(Surface parent, string filename) : this(parent) {
+ Load(filename);
+ }
+
+ public Cursor Cursor {
+ set {
+ if (cursor != null) {
+ cursor.Dispose();
+ }
+ // Clone cursor (is this correct??)
+ cursor = new Cursor(value.CopyHandle());
+ Width = value.Size.Width;
+ Height = value.Size.Height;
+ }
+ get { return cursor; }
+ }
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ /// When disposing==true all non-managed resources should be freed too!
+ ///
+ ///
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (cursor != null) {
+ cursor.Dispose();
+ }
+ }
+ cursor = null;
+ base.Dispose(disposing);
+ }
+
+ public void Load(string filename) {
+ if (!File.Exists(filename)) {
+ return;
+ }
+ using (Cursor fileCursor = new Cursor(filename)) {
+ Cursor = fileCursor;
+ LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
+ }
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ if (cursor == null) {
+ return;
+ }
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.CompositingQuality = CompositingQuality.Default;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ cursor.DrawStretched(graphics, Bounds);
+ }
+
+ public override Size DefaultSize {
+ get {
+ return cursor.Size;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/DrawableContainer.cs b/Greenshot/Drawing/DrawableContainer.cs
new file mode 100644
index 000000000..92c3a92d7
--- /dev/null
+++ b/Greenshot/Drawing/DrawableContainer.cs
@@ -0,0 +1,607 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Configuration;
+using Greenshot.Drawing.Adorners;
+using Greenshot.Drawing.Fields;
+using Greenshot.Drawing.Filters;
+using Greenshot.Helpers;
+using Greenshot.IniFile;
+using Greenshot.Memento;
+using Greenshot.Plugin;
+using Greenshot.Plugin.Drawing;
+using Greenshot.Plugin.Drawing.Adorners;
+using GreenshotPlugin.Interfaces.Drawing;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing
+{
+ ///
+ /// represents a rectangle, ellipse, label or whatever. Can contain filters, too.
+ /// serializable for clipboard support
+ /// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
+ /// OnPropertyChanged whenever a public property has been changed.
+ ///
+ [Serializable]
+ public abstract class DrawableContainer : AbstractFieldHolderWithChildren, IDrawableContainer {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(DrawableContainer));
+ protected static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection();
+ private const int M11 = 0;
+ private const int M22 = 3;
+
+ [OnDeserialized]
+ private void OnDeserializedInit(StreamingContext context)
+ {
+ _adorners = new List();
+ OnDeserialized(context);
+ }
+
+ ///
+ /// Override to implement your own deserialization logic, like initializing properties which are not serialized
+ ///
+ ///
+ protected virtual void OnDeserialized(StreamingContext streamingContext)
+ {
+ }
+
+ protected EditStatus _defaultEditMode = EditStatus.DRAWING;
+ public EditStatus DefaultEditMode {
+ get {
+ return _defaultEditMode;
+ }
+ }
+
+ ///
+ /// The public accessible Dispose
+ /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
+ ///
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (!disposing) {
+ return;
+ }
+ _parent?.FieldAggregator?.UnbindElement(this);
+ }
+
+ ~DrawableContainer() {
+ Dispose(false);
+ }
+
+ [NonSerialized]
+ private PropertyChangedEventHandler _propertyChanged;
+ public event PropertyChangedEventHandler PropertyChanged {
+ add { _propertyChanged += value; }
+ remove{ _propertyChanged -= value; }
+ }
+
+ public IList Filters {
+ get {
+ List ret = new List();
+ foreach(IFieldHolder c in Children) {
+ if (c is IFilter) {
+ ret.Add(c as IFilter);
+ }
+ }
+ return ret;
+ }
+ }
+
+ [NonSerialized]
+ internal Surface _parent;
+ public ISurface Parent {
+ get { return _parent; }
+ set { SwitchParent((Surface)value); }
+ }
+
+ [NonSerialized]
+ private TargetAdorner _targetAdorner;
+ public TargetAdorner TargetAdorner {
+ get {
+ return _targetAdorner;
+ }
+ }
+
+ [NonSerialized]
+ private bool _selected;
+ public bool Selected {
+ get {return _selected;}
+ set {
+ _selected = value;
+ OnPropertyChanged("Selected");
+ }
+ }
+
+ [NonSerialized]
+ private EditStatus _status = EditStatus.UNDRAWN;
+ public EditStatus Status {
+ get {
+ return _status;
+ }
+ set {
+ _status = value;
+ }
+ }
+
+
+ private int left;
+ public int Left {
+ get { return left; }
+ set {
+ if (value == left) {
+ return;
+ }
+ left = value;
+ }
+ }
+
+ private int top;
+ public int Top {
+ get { return top; }
+ set {
+ if (value == top) {
+ return;
+ }
+ top = value;
+ }
+ }
+
+ private int width;
+ public int Width {
+ get { return width; }
+ set {
+ if (value == width) {
+ return;
+ }
+ width = value;
+ }
+ }
+
+ private int height;
+ public int Height {
+ get { return height; }
+ set {
+ if (value == height) {
+ return;
+ }
+ height = value;
+ }
+ }
+
+ public Point Location {
+ get {
+ return new Point(left, top);
+ }
+ set {
+ left = value.X;
+ top = value.Y;
+ }
+ }
+
+ public Size Size {
+ get {
+ return new Size(width, height);
+ }
+ set {
+ width = value.Width;
+ height = value.Height;
+ }
+ }
+
+ ///
+ /// List of available Adorners
+ ///
+ [NonSerialized]
+ private IList _adorners = new List();
+ public IList Adorners
+ {
+ get
+ {
+ return _adorners;
+ }
+ }
+
+ [NonSerialized]
+ // will store current bounds of this DrawableContainer before starting a resize
+ protected Rectangle _boundsBeforeResize = Rectangle.Empty;
+
+ [NonSerialized]
+ // "workbench" rectangle - used for calculating bounds during resizing (to be applied to this DrawableContainer afterwards)
+ protected RectangleF _boundsAfterResize = RectangleF.Empty;
+
+ public Rectangle Bounds {
+ get { return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); }
+ set {
+ Left = Round(value.Left);
+ Top = Round(value.Top);
+ Width = Round(value.Width);
+ Height = Round(value.Height);
+ }
+ }
+
+ public virtual void ApplyBounds(RectangleF newBounds) {
+ Left = Round(newBounds.Left);
+ Top = Round(newBounds.Top);
+ Width = Round(newBounds.Width);
+ Height = Round(newBounds.Height);
+ }
+
+ public DrawableContainer(Surface parent) {
+ InitializeFields();
+ _parent = parent;
+ }
+
+ public void Add(IFilter filter) {
+ AddChild(filter);
+ }
+
+ public void Remove(IFilter filter) {
+ RemoveChild(filter);
+ }
+
+ private static int Round(float f) {
+ if(float.IsPositiveInfinity(f) || f>int.MaxValue/2) return int.MaxValue/2;
+ if (float.IsNegativeInfinity(f) || f
+ /// Initialize a target gripper
+ ///
+ protected void InitAdorner(Color gripperColor, Point location) {
+ _targetAdorner = new TargetAdorner(this, location);
+ Adorners.Add(_targetAdorner);
+ }
+
+ ///
+ /// Create the default adorners for a rectangle based container
+ ///
+
+ protected void CreateDefaultAdorners() {
+ if (Adorners.Count > 0)
+ {
+ LOG.Warn("Adorners are already defined!");
+ }
+ // Create the GripperAdorners
+ Adorners.Add(new ResizeAdorner(this, Positions.TopLeft));
+ Adorners.Add(new ResizeAdorner(this, Positions.TopCenter));
+ Adorners.Add(new ResizeAdorner(this, Positions.TopRight));
+ Adorners.Add(new ResizeAdorner(this, Positions.BottomLeft));
+ Adorners.Add(new ResizeAdorner(this, Positions.BottomCenter));
+ Adorners.Add(new ResizeAdorner(this, Positions.BottomRight));
+ Adorners.Add(new ResizeAdorner(this, Positions.MiddleLeft));
+ Adorners.Add(new ResizeAdorner(this, Positions.MiddleRight));
+ }
+
+ public bool hasFilters {
+ get {
+ return Filters.Count > 0;
+ }
+ }
+
+ public abstract void Draw(Graphics graphics, RenderMode renderMode);
+
+ public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode, Rectangle clipRectangle) {
+ if (Children.Count > 0) {
+ if (Status != EditStatus.IDLE) {
+ DrawSelectionBorder(graphics, Bounds);
+ } else {
+ if (clipRectangle.Width != 0 && clipRectangle.Height != 0) {
+ foreach(IFilter filter in Filters) {
+ if (filter.Invert) {
+ filter.Apply(graphics, bmp, Bounds, renderMode);
+ } else {
+ Rectangle drawingRect = new Rectangle(Bounds.Location, Bounds.Size);
+ drawingRect.Intersect(clipRectangle);
+ if(filter is MagnifierFilter) {
+ // quick&dirty bugfix, because MagnifierFilter behaves differently when drawn only partially
+ // what we should actually do to resolve this is add a better magnifier which is not that special
+ filter.Apply(graphics, bmp, Bounds, renderMode);
+ } else {
+ filter.Apply(graphics, bmp, drawingRect, renderMode);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ Draw(graphics, renderMode);
+ }
+
+ public virtual bool Contains(int x, int y) {
+ return Bounds.Contains(x , y);
+ }
+
+ public virtual bool ClickableAt(int x, int y) {
+ Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ r.Inflate(5, 5);
+ return r.Contains(x, y);
+ }
+
+ protected void DrawSelectionBorder(Graphics g, Rectangle rect) {
+ using (Pen pen = new Pen(Color.MediumSeaGreen)) {
+ pen.DashPattern = new float[]{1,2};
+ pen.Width = 1;
+ g.DrawRectangle(pen, rect);
+ }
+ }
+
+
+ public void ResizeTo(int width, int height, int anchorPosition) {
+ Width = width;
+ Height = height;
+ }
+
+ ///
+ /// Make a following bounds change on this drawablecontainer undoable!
+ ///
+ /// true means allow the moves to be merged
+ public void MakeBoundsChangeUndoable(bool allowMerge) {
+ _parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge);
+ }
+
+ public void MoveBy(int dx, int dy) {
+ Left += dx;
+ Top += dy;
+ }
+
+ ///
+ /// A handler for the MouseDown, used if you don't want the surface to handle this for you
+ ///
+ /// current mouse x
+ /// current mouse y
+ /// true if the event is handled, false if the surface needs to handle it
+ public virtual bool HandleMouseDown(int x, int y) {
+ Left = _boundsBeforeResize.X = x;
+ Top = _boundsBeforeResize.Y = y;
+ return true;
+ }
+
+ ///
+ /// A handler for the MouseMove, used if you don't want the surface to handle this for you
+ ///
+ /// current mouse x
+ /// current mouse y
+ /// true if the event is handled, false if the surface needs to handle it
+ public virtual bool HandleMouseMove(int x, int y) {
+ Invalidate();
+
+ // reset "workrbench" rectangle to current bounds
+ _boundsAfterResize.X = _boundsBeforeResize.Left;
+ _boundsAfterResize.Y = _boundsBeforeResize.Top;
+ _boundsAfterResize.Width = x - _boundsAfterResize.Left;
+ _boundsAfterResize.Height = y - _boundsAfterResize.Top;
+
+ ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor());
+
+ // apply scaled bounds to this DrawableContainer
+ ApplyBounds(_boundsAfterResize);
+
+ Invalidate();
+ return true;
+ }
+
+ ///
+ /// A handler for the MouseUp
+ ///
+ /// current mouse x
+ /// current mouse y
+ public virtual void HandleMouseUp(int x, int y) {
+ }
+
+ protected virtual void SwitchParent(Surface newParent) {
+ if (newParent == Parent)
+ {
+ return;
+ }
+ _parent?.FieldAggregator?.UnbindElement(this);
+
+ _parent = newParent;
+ foreach(IFilter filter in Filters) {
+ filter.Parent = this;
+ }
+ }
+
+ protected void OnPropertyChanged(string propertyName) {
+ if (_propertyChanged != null) {
+ _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ Invalidate();
+ }
+ }
+
+ ///
+ /// This method will be called before a field is changes.
+ /// Using this makes it possible to invalidate the object as is before changing.
+ ///
+ /// The field to be changed
+ /// The new value
+ public virtual void BeforeFieldChange(IField fieldToBeChanged, object newValue) {
+ _parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
+ Invalidate();
+ }
+
+ ///
+ /// Handle the field changed event, this should invalidate the correct bounds (e.g. when shadow comes or goes more pixels!)
+ ///
+ ///
+ ///
+ public void HandleFieldChanged(object sender, FieldChangedEventArgs e) {
+ LOG.DebugFormat("Field {0} changed", e.Field.FieldType);
+ if (Equals(e.Field.FieldType, FieldType.SHADOW)) {
+ accountForShadowChange = true;
+ }
+ }
+
+ ///
+ /// Retrieve the Y scale from the matrix
+ ///
+ ///
+ ///
+ public static float CalculateScaleY(Matrix matrix) {
+ return matrix.Elements[M22];
+ }
+
+ ///
+ /// Retrieve the X scale from the matrix
+ ///
+ ///
+ ///
+ public static float CalculateScaleX(Matrix matrix) {
+ return matrix.Elements[M11];
+ }
+
+ ///
+ /// Retrieve the rotation angle from the matrix
+ ///
+ ///
+ ///
+ public static int CalculateAngle(Matrix matrix) {
+ const int M11 = 0;
+ const int M21 = 2;
+ var radians = Math.Atan2(matrix.Elements[M21], matrix.Elements[M11]);
+ return (int)-Math.Round(radians * 180 / Math.PI);
+ }
+
+ ///
+ /// This method is called on a DrawableContainers when:
+ /// 1) The capture on the surface is modified in such a way, that the elements would not be placed correctly.
+ /// 2) Currently not implemented: an element needs to be moved, scaled or rotated.
+ /// This basis implementation makes sure the coordinates of the element, including the TargetGripper, is correctly rotated/scaled/translated.
+ /// But this implementation doesn't take care of any changes to the content!!
+ ///
+ ///
+ public virtual void Transform(Matrix matrix) {
+ if (matrix == null) {
+ return;
+ }
+ Point topLeft = new Point(Left, Top);
+ Point bottomRight = new Point(Left + Width, Top + Height);
+ Point[] points = new[] { topLeft, bottomRight };
+ matrix.TransformPoints(points);
+
+ Left = points[0].X;
+ Top = points[0].Y;
+ Width = points[1].X - points[0].X;
+ Height = points[1].Y - points[0].Y;
+
+ }
+
+ protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() {
+ return ScaleHelper.ShapeAngleRoundBehavior.Instance;
+ }
+
+ public virtual bool HasContextMenu {
+ get {
+ return true;
+ }
+ }
+
+ public virtual bool HasDefaultSize {
+ get {
+ return false;
+ }
+ }
+
+ public virtual Size DefaultSize {
+ get {
+ throw new NotSupportedException("Object doesn't have a default size");
+ }
+ }
+
+ ///
+ /// Allows to override the initializing of the fields, so we can actually have our own defaults
+ ///
+ protected virtual void InitializeFields() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Greenshot/Drawing/DrawableContainerList.cs b/Greenshot/Drawing/DrawableContainerList.cs
new file mode 100644
index 000000000..849cf5ddc
--- /dev/null
+++ b/Greenshot/Drawing/DrawableContainerList.cs
@@ -0,0 +1,586 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Configuration;
+using Greenshot.Memento;
+using Greenshot.Plugin;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces.Drawing;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers.
+ ///
+ [Serializable]
+ public class DrawableContainerList : List, IDrawableContainerList
+ {
+ private static readonly ComponentResourceManager EditorFormResources = new ComponentResourceManager(typeof(ImageEditorForm));
+
+ public Guid ParentID {
+ get;
+ private set;
+ }
+
+ public DrawableContainerList() {
+ }
+
+ public DrawableContainerList(Guid parentId) {
+ ParentID = parentId;
+ }
+
+ public EditStatus Status {
+ get {
+ return this[Count-1].Status;
+ }
+ set {
+ foreach (var dc in this) {
+ dc.Status = value;
+ }
+ }
+ }
+
+ public List AsIDrawableContainerList() {
+ List interfaceList = new List();
+ foreach(IDrawableContainer container in this) {
+ interfaceList.Add(container);
+ }
+ return interfaceList;
+ }
+
+ ///
+ /// Gets or sets the selection status of the elements.
+ /// If several elements are in the list, true is only returned when all elements are selected.
+ ///
+ public bool Selected {
+ get {
+ bool ret = true;
+ foreach(var dc in this) {
+ ret &= dc.Selected;
+ }
+ return ret;
+ }
+ set {
+ foreach(var dc in this) {
+ dc.Selected = value;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the parent control of the elements in the list.
+ /// If there are several elements, the parent control of the last added is returned.
+ ///
+ public ISurface Parent {
+ get {
+ if (Count > 0) {
+ return this[Count-1].Parent;
+ }
+ return null;
+ }
+ set {
+ ParentID = value?.ID ?? Guid.NewGuid();
+ foreach (var drawableContainer in this) {
+ var dc = (DrawableContainer) drawableContainer;
+ dc.Parent = value;
+ }
+ }
+ }
+
+ ///
+ /// Make a following bounds change on this containerlist undoable!
+ ///
+ /// true means allow the moves to be merged
+ public void MakeBoundsChangeUndoable(bool allowMerge) {
+ if (Count > 0 && Parent != null)
+ {
+ var clone = new DrawableContainerList();
+ clone.AddRange(this);
+ Parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(clone), allowMerge);
+ }
+ }
+
+ ///
+ /// Apply matrix to all elements
+ ///
+ public void Transform(Matrix matrix) {
+ // Track modifications
+ bool modified = false;
+ Invalidate();
+ foreach (var dc in this) {
+ dc.Transform(matrix);
+ modified = true;
+ }
+ // Invalidate after
+ Invalidate();
+ // If we moved something, tell the surface it's modified!
+ if (modified) {
+ Parent.Modified = true;
+ }
+ }
+
+ ///
+ /// Moves all elements in the list by the given amount of pixels.
+ ///
+ /// pixels to move horizontally
+ /// pixels to move vertically
+ public void MoveBy(int dx, int dy) {
+ // Track modifications
+ bool modified = false;
+
+ // Invalidate before moving, otherwise the old locations aren't refreshed
+ Invalidate();
+ foreach(var dc in this) {
+ dc.Left += dx;
+ dc.Top += dy;
+ modified = true;
+ }
+ // Invalidate after
+ Invalidate();
+
+ // If we moved something, tell the surface it's modified!
+ if (modified) {
+ Parent.Modified = true;
+ }
+ }
+
+ ///
+ /// Indicates whether on of the elements is clickable at the given location
+ ///
+ /// x coordinate to be checked
+ /// y coordinate to be checked
+ /// true if one of the elements in the list is clickable at the given location, false otherwise
+ public bool ClickableAt(int x, int y) {
+ bool ret = false;
+ foreach(var dc in this) {
+ ret |= dc.ClickableAt(x, y);
+ }
+ return ret;
+ }
+
+ ///
+ /// retrieves the topmost element being clickable at the given location
+ ///
+ /// x coordinate to be checked
+ /// y coordinate to be checked
+ /// the topmost element from the list being clickable at the given location, null if there is no clickable element
+ public IDrawableContainer ClickableElementAt(int x, int y) {
+ for (int i=Count-1; i>=0; i--) {
+ if (this[i].ClickableAt(x,y)) {
+ return this[i];
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Dispatches OnDoubleClick to all elements in the list.
+ ///
+ public void OnDoubleClick() {
+ foreach(var drawableContainer in this) {
+ var dc = (DrawableContainer) drawableContainer;
+ dc.OnDoubleClick();
+ }
+ }
+
+ ///
+ /// Check if there are any intersecting filters, if so we need to redraw more
+ ///
+ ///
+ /// true if an filter intersects
+ public bool HasIntersectingFilters(Rectangle clipRectangle) {
+ foreach(var dc in this) {
+ if (dc.DrawingBounds.IntersectsWith(clipRectangle) && dc.hasFilters && dc.Status == EditStatus.IDLE) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Check if any of the drawableContainers are inside the rectangle
+ ///
+ ///
+ ///
+ public bool IntersectsWith(Rectangle clipRectangle) {
+ foreach(var dc in this) {
+ if (dc.DrawingBounds.IntersectsWith(clipRectangle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Triggers all elements in the list ot be redrawn.
+ ///
+ /// the to the bitmap related Graphics object
+ /// Bitmap to draw
+ /// the rendermode in which the element is to be drawn
+ ///
+ public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle) {
+ if (Parent == null)
+ {
+ return;
+ }
+ foreach (var drawableContainer in this)
+ {
+ var dc = (DrawableContainer)drawableContainer;
+ if (dc.Parent == null)
+ {
+ continue;
+ }
+ if (dc.DrawingBounds.IntersectsWith(clipRectangle))
+ {
+ dc.DrawContent(g, bitmap, renderMode, clipRectangle);
+ }
+ }
+ }
+
+ ///
+ /// Pass the field changed event to all elements in the list
+ ///
+ ///
+ ///
+ public void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e) {
+ foreach(var drawableContainer in this) {
+ var dc = (DrawableContainer) drawableContainer;
+ dc.HandleFieldChanged(sender, e);
+ }
+ }
+
+ ///
+ /// Invalidate the bounds of all the DC's in this list
+ ///
+ public void Invalidate() {
+ if (Parent == null)
+ {
+ return;
+ }
+ Rectangle region = Rectangle.Empty;
+ foreach (var dc in this)
+ {
+ region = Rectangle.Union(region, dc.DrawingBounds);
+ }
+ Parent.Invalidate(region);
+ }
+ ///
+ /// Indicates whether the given list of elements can be pulled up,
+ /// i.e. whether there is at least one unselected element higher in hierarchy
+ ///
+ /// list of elements to pull up
+ /// true if the elements could be pulled up
+ public bool CanPullUp(IDrawableContainerList elements) {
+ if (elements.Count == 0 || elements.Count == Count) {
+ return false;
+ }
+ foreach(var element in elements) {
+ if (IndexOf(element) < Count - elements.Count) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Pulls one or several elements up one level in hierarchy (z-index).
+ ///
+ /// list of elements to pull up
+ public void PullElementsUp(IDrawableContainerList elements) {
+ for(int i=Count-1; i>=0; i--) {
+ var dc = this[i];
+ if (!elements.Contains(dc)) {
+ continue;
+ }
+ if (Count > i+1 && !elements.Contains(this[i+1])) {
+ SwapElements(i,i+1);
+ }
+ }
+ }
+
+ ///
+ /// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index).
+ ///
+ /// of elements to pull to top
+ public void PullElementsToTop(IDrawableContainerList elements)
+ {
+ var dcs = ToArray();
+ foreach (var dc in dcs)
+ {
+ if (!elements.Contains(dc)) {
+ continue;
+ }
+ Remove(dc);
+ Add(dc);
+ Parent.Modified = true;
+ }
+ }
+
+ ///
+ /// Indicates whether the given list of elements can be pushed down,
+ /// i.e. whether there is at least one unselected element lower in hierarchy
+ ///
+ /// list of elements to push down
+ /// true if the elements could be pushed down
+ public bool CanPushDown(IDrawableContainerList elements) {
+ if (elements.Count == 0 || elements.Count == Count) {
+ return false;
+ }
+ foreach(var element in elements) {
+ if (IndexOf(element) >= elements.Count) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Pushes one or several elements down one level in hierarchy (z-index).
+ ///
+ /// list of elements to push down
+ public void PushElementsDown(IDrawableContainerList elements) {
+ for(int i=0; i0) && !elements.Contains(this[i-1])) {
+ SwapElements(i,i-1);
+ }
+ }
+ }
+
+ ///
+ /// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index).
+ ///
+ /// of elements to push to bottom
+ public void PushElementsToBottom(IDrawableContainerList elements) {
+ var dcs = ToArray();
+ for(int i=dcs.Length-1; i>=0; i--) {
+ var dc = dcs[i];
+ if (!elements.Contains(dc)) {
+ continue;
+ }
+ Remove(dc);
+ Insert(0, dc);
+ Parent.Modified = true;
+ }
+ }
+
+ ///
+ /// swaps two elements in hierarchy (z-index),
+ /// checks both indices to be in range
+ ///
+ /// index of the 1st element
+ /// index of the 2nd element
+ private void SwapElements(int index1, int index2) {
+ if (index1 < 0 || index1 >= Count || index2 < 0 || index2 >= Count || index1 == index2) {
+ return;
+ }
+ var dc = this[index1];
+ this[index1] = this[index2];
+ this[index2] = dc;
+ Parent.Modified = true;
+ }
+
+ ///
+ /// Add items to a context menu for the selected item
+ ///
+ ///
+ ///
+ public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface) {
+ bool push = surface.Elements.CanPushDown(this);
+ bool pull = surface.Elements.CanPullUp(this);
+
+ ToolStripMenuItem item;
+
+ // Pull "up"
+ if (pull) {
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_uptotop));
+ item.Click += delegate {
+ surface.Elements.PullElementsToTop(this);
+ surface.Elements.Invalidate();
+ };
+ menu.Items.Add(item);
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_uponelevel));
+ item.Click += delegate {
+ surface.Elements.PullElementsUp(this);
+ surface.Elements.Invalidate();
+ };
+ menu.Items.Add(item);
+ }
+ // Push "down"
+ if (push) {
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_downtobottom));
+ item.Click += delegate {
+ surface.Elements.PushElementsToBottom(this);
+ surface.Elements.Invalidate();
+ };
+ menu.Items.Add(item);
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_downonelevel));
+ item.Click += delegate {
+ surface.Elements.PushElementsDown(this);
+ surface.Elements.Invalidate();
+ };
+ menu.Items.Add(item);
+ }
+
+ // Duplicate
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_duplicate));
+ item.Click += delegate {
+ IDrawableContainerList dcs = this.Clone();
+ dcs.Parent = surface;
+ dcs.MoveBy(10, 10);
+ surface.AddElements(dcs);
+ surface.DeselectAllElements();
+ surface.SelectElements(dcs);
+ };
+ menu.Items.Add(item);
+
+ // Copy
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_copytoclipboard))
+ {
+ Image = (Image) EditorFormResources.GetObject("copyToolStripMenuItem.Image")
+ };
+ item.Click += delegate {
+ ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this);
+ };
+ menu.Items.Add(item);
+
+ // Cut
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_cuttoclipboard))
+ {
+ Image = (Image) EditorFormResources.GetObject("btnCut.Image")
+ };
+ item.Click += delegate {
+ ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this);
+ surface.RemoveElements(this);
+ };
+ menu.Items.Add(item);
+
+ // Delete
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_deleteelement));
+ item.Image = (Image)EditorFormResources.GetObject("removeObjectToolStripMenuItem.Image");
+ item.Click += delegate {
+ surface.RemoveElements(this);
+ };
+ menu.Items.Add(item);
+
+ // Reset
+ bool canReset = false;
+ foreach (var drawableContainer in this)
+ {
+ var container = (DrawableContainer)drawableContainer;
+ if (container.HasDefaultSize)
+ {
+ canReset = true;
+ }
+ }
+ if (canReset) {
+ item = new ToolStripMenuItem(Language.GetString(LangKey.editor_resetsize));
+ //item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image")));
+ item.Click += delegate {
+ MakeBoundsChangeUndoable(false);
+ foreach (var drawableContainer in this) {
+ var container = (DrawableContainer) drawableContainer;
+ if (!container.HasDefaultSize) {
+ continue;
+ }
+ Size defaultSize = container.DefaultSize;
+ container.MakeBoundsChangeUndoable(false);
+ container.Width = defaultSize.Width;
+ container.Height = defaultSize.Height;
+ }
+ surface.Invalidate();
+ };
+ menu.Items.Add(item);
+ }
+ }
+
+ public virtual void ShowContextMenu(MouseEventArgs e, ISurface surface)
+ {
+ if (!(surface is Surface))
+ {
+ return;
+ }
+ bool hasMenu = false;
+ foreach (var drawableContainer in this) {
+ var container = (DrawableContainer) drawableContainer;
+ if (!container.HasContextMenu) {
+ continue;
+ }
+ hasMenu = true;
+ break;
+ }
+ if (hasMenu) {
+ ContextMenuStrip menu = new ContextMenuStrip();
+ AddContextMenuItems(menu, surface);
+ if (menu.Items.Count > 0) {
+ // TODO: cast should be somehow avoided
+ menu.Show((Surface)surface, e.Location);
+ while (true) {
+ if (menu.Visible) {
+ Application.DoEvents();
+ Thread.Sleep(100);
+ } else {
+ menu.Dispose();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ #region IDisposable Support
+ private bool _disposedValue; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ foreach (var drawableContainer in this)
+ {
+ drawableContainer.Dispose();
+ }
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ }
+ #endregion
+ }
+}
diff --git a/Greenshot/Drawing/EllipseContainer.cs b/Greenshot/Drawing/EllipseContainer.cs
new file mode 100644
index 000000000..a2bc4b6ee
--- /dev/null
+++ b/Greenshot/Drawing/EllipseContainer.cs
@@ -0,0 +1,147 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of EllipseContainer.
+ ///
+ [Serializable()]
+ public class EllipseContainer : DrawableContainer {
+ public EllipseContainer(Surface parent) : base(parent) {
+ CreateDefaultAdorners();
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
+ AddField(GetType(), FieldType.SHADOW, true);
+ }
+
+ public override void Draw(Graphics graphics, RenderMode renderMode) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ DrawEllipse(rect, graphics, renderMode, lineThickness, lineColor, fillColor, shadow);
+ }
+
+ ///
+ /// This allows another container to draw an ellipse
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DrawEllipse(Rectangle rect, Graphics graphics, RenderMode renderMode, int lineThickness, Color lineColor, Color fillColor, bool shadow) {
+ bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
+ // draw shadow before anything else
+ if (shadow && (lineVisible || Colors.IsVisible(fillColor))) {
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = lineVisible ? 1 : 0;
+ while (currentStep <= steps) {
+ using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
+ shadowPen.Width = lineVisible ? lineThickness : 1;
+ Rectangle shadowRect = GuiRectangle.GetGuiRectangle(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height);
+ graphics.DrawEllipse(shadowPen, shadowRect);
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+ //draw the original shape
+ if (Colors.IsVisible(fillColor)) {
+ using (Brush brush = new SolidBrush(fillColor)) {
+ graphics.FillEllipse(brush, rect);
+ }
+ }
+ if (lineVisible) {
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ graphics.DrawEllipse(pen, rect);
+ }
+ }
+ }
+
+ public override bool Contains(int x, int y) {
+ return EllipseContains(this, x, y);
+ }
+
+ ///
+ /// Allow the code to be used externally
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool EllipseContains(DrawableContainer caller, int x, int y) {
+ double xDistanceFromCenter = x - (caller.Left + caller.Width / 2);
+ double yDistanceFromCenter = y - (caller.Top + caller.Height / 2);
+ // ellipse: x^2/a^2 + y^2/b^2 = 1
+ return Math.Pow(xDistanceFromCenter, 2) / Math.Pow(caller.Width / 2, 2) + Math.Pow(yDistanceFromCenter, 2) / Math.Pow(caller.Height / 2, 2) < 1;
+ }
+
+ public override bool ClickableAt(int x, int y) {
+
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ return EllipseClickableAt(rect, lineThickness, fillColor, x, y);
+ }
+
+ public static bool EllipseClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) {
+ // If we clicked inside the rectangle and it's visible we are clickable at.
+ if (!Color.Transparent.Equals(fillColor)) {
+ if (rect.Contains(x, y)) {
+ return true;
+ }
+ }
+
+ // check the rest of the lines
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(Color.White, lineThickness)) {
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddEllipse(rect);
+ return path.IsOutlineVisible(x, y, pen);
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Fields/AbstractFieldHolder.cs b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs
new file mode 100644
index 000000000..6be20aa92
--- /dev/null
+++ b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs
@@ -0,0 +1,202 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Runtime.Serialization;
+
+using Greenshot.Configuration;
+using Greenshot.IniFile;
+using log4net;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing.Fields
+{
+ ///
+ /// Basic IFieldHolder implementation, providing access to a set of fields
+ ///
+ [Serializable]
+ public abstract class AbstractFieldHolder : IFieldHolder
+ {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(AbstractFieldHolder));
+ private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection();
+ [NonSerialized]
+ private readonly IDictionary _handlers = new Dictionary();
+
+ ///
+ /// called when a field's value has changed
+ ///
+ [NonSerialized]
+ private FieldChangedEventHandler _fieldChanged;
+
+ public event FieldChangedEventHandler FieldChanged
+ {
+ add { _fieldChanged += value; }
+ remove { _fieldChanged -= value; }
+ }
+
+ // we keep two Collections of our fields, dictionary for quick access, list for serialization
+ // this allows us to use default serialization
+ [NonSerialized]
+ private IDictionary _fieldsByType = new Dictionary();
+ private readonly IList fields = new List();
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ _fieldsByType = new Dictionary();
+ // listen to changing properties
+ foreach (var field in fields)
+ {
+ field.PropertyChanged += delegate {
+ _fieldChanged?.Invoke(this, new FieldChangedEventArgs(field));
+ };
+ _fieldsByType[field.FieldType] = field;
+ }
+ }
+
+ public void AddField(Type requestingType, IFieldType fieldType, object fieldValue)
+ {
+ AddField(EditorConfig.CreateField(requestingType, fieldType, fieldValue));
+ }
+
+ public virtual void AddField(IField field)
+ {
+ fields.Add(field);
+ if (_fieldsByType == null)
+ {
+ return;
+ }
+
+ if (_fieldsByType.ContainsKey(field.FieldType))
+ {
+ if (LOG.IsDebugEnabled)
+ {
+ LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType());
+ }
+ }
+
+ _fieldsByType[field.FieldType] = field;
+
+ _handlers[field] = (sender, args) =>
+ {
+ _fieldChanged?.Invoke(this, new FieldChangedEventArgs(field));
+ };
+ field.PropertyChanged += _handlers[field];
+ }
+
+ public void RemoveField(IField field)
+ {
+ fields.Remove(field);
+ _fieldsByType.Remove(field.FieldType);
+ field.PropertyChanged -= _handlers[field];
+ _handlers.Remove(field);
+ }
+
+ public IList GetFields()
+ {
+ return fields;
+ }
+
+
+ public IField GetField(IFieldType fieldType)
+ {
+ try
+ {
+ return _fieldsByType[fieldType];
+ }
+ catch (KeyNotFoundException e)
+ {
+ throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
+ }
+ }
+
+ public object GetFieldValue(IFieldType fieldType)
+ {
+ return GetField(fieldType)?.Value;
+ }
+
+ #region convenience methods to save us some casts outside
+ public string GetFieldValueAsString(IFieldType fieldType)
+ {
+ return Convert.ToString(GetFieldValue(fieldType));
+ }
+
+ public int GetFieldValueAsInt(IFieldType fieldType)
+ {
+ return Convert.ToInt32(GetFieldValue(fieldType));
+ }
+
+ public decimal GetFieldValueAsDecimal(IFieldType fieldType)
+ {
+ return Convert.ToDecimal(GetFieldValue(fieldType));
+ }
+
+ public double GetFieldValueAsDouble(IFieldType fieldType)
+ {
+ return Convert.ToDouble(GetFieldValue(fieldType));
+ }
+
+ public float GetFieldValueAsFloat(IFieldType fieldType)
+ {
+ return Convert.ToSingle(GetFieldValue(fieldType));
+ }
+
+ public bool GetFieldValueAsBool(IFieldType fieldType)
+ {
+ return Convert.ToBoolean(GetFieldValue(fieldType));
+ }
+
+ public Color GetFieldValueAsColor(IFieldType fieldType, Color defaultColor = default(Color))
+ {
+ return (Color)(GetFieldValue(fieldType) ?? defaultColor);
+ }
+ #endregion
+
+ public bool HasField(IFieldType fieldType)
+ {
+ return _fieldsByType.ContainsKey(fieldType);
+ }
+
+ public bool HasFieldValue(IFieldType fieldType)
+ {
+ return HasField(fieldType) && _fieldsByType[fieldType].HasValue;
+ }
+
+ public void SetFieldValue(IFieldType fieldType, object value)
+ {
+ try
+ {
+ _fieldsByType[fieldType].Value = value;
+ }
+ catch (KeyNotFoundException e)
+ {
+ throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
+ }
+ }
+
+ protected void OnFieldChanged(object sender, FieldChangedEventArgs e)
+ {
+ _fieldChanged?.Invoke(sender, e);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs b/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs
new file mode 100644
index 000000000..e76626b2c
--- /dev/null
+++ b/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs
@@ -0,0 +1,146 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Interfaces.Drawing;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing.Fields
+{
+ ///
+ /// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder,
+ /// but has a List of IFieldHolder for children.
+ /// Field values are passed to and from children as well.
+ ///
+ [Serializable]
+ public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder
+ {
+ [NonSerialized]
+ private readonly FieldChangedEventHandler _fieldChangedEventHandler;
+
+ [NonSerialized]
+ private EventHandler childrenChanged;
+ public event EventHandler ChildrenChanged
+ {
+ add { childrenChanged += value; }
+ remove { childrenChanged -= value; }
+ }
+
+ public List Children = new List();
+
+ public AbstractFieldHolderWithChildren()
+ {
+ _fieldChangedEventHandler = OnFieldChanged;
+ }
+
+ [OnDeserialized()]
+ private void OnDeserialized(StreamingContext context)
+ {
+ // listen to changing properties
+ foreach (IFieldHolder fieldHolder in Children)
+ {
+ fieldHolder.FieldChanged += _fieldChangedEventHandler;
+ }
+ childrenChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public void AddChild(IFieldHolder fieldHolder)
+ {
+ Children.Add(fieldHolder);
+ fieldHolder.FieldChanged += _fieldChangedEventHandler;
+ childrenChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public void RemoveChild(IFieldHolder fieldHolder)
+ {
+ Children.Remove(fieldHolder);
+ fieldHolder.FieldChanged -= _fieldChangedEventHandler;
+ childrenChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public new IList GetFields()
+ {
+ var ret = new List();
+ ret.AddRange(base.GetFields());
+ foreach (IFieldHolder fh in Children)
+ {
+ ret.AddRange(fh.GetFields());
+ }
+ return ret;
+ }
+
+ public new IField GetField(IFieldType fieldType)
+ {
+ IField ret = null;
+ if (base.HasField(fieldType))
+ {
+ ret = base.GetField(fieldType);
+ }
+ else
+ {
+ foreach (IFieldHolder fh in Children)
+ {
+ if (fh.HasField(fieldType))
+ {
+ ret = fh.GetField(fieldType);
+ break;
+ }
+ }
+ }
+ if (ret == null)
+ {
+ throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType());
+ }
+ return ret;
+ }
+
+ public new bool HasField(IFieldType fieldType)
+ {
+ bool ret = base.HasField(fieldType);
+ if (!ret)
+ {
+ foreach (IFieldHolder fh in Children)
+ {
+ if (fh.HasField(fieldType))
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
+ public new bool HasFieldValue(IFieldType fieldType)
+ {
+ IField f = GetField(fieldType);
+ return f != null && f.HasValue;
+ }
+
+ public new void SetFieldValue(IFieldType fieldType, object value)
+ {
+ IField f = GetField(fieldType);
+ if (f != null) f.Value = value;
+ }
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs b/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs
new file mode 100644
index 000000000..fd86f07b1
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs
@@ -0,0 +1,46 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Basic IBindingConverter implementation
+ ///
+ public abstract class AbstractBindingConverter : IBindingConverter
+ {
+ public object convert(object o) {
+ if(o == null) {
+ return null;
+ }
+ if(o is T1) {
+ return convert((T1)o);
+ }
+ if(o is T2) {
+ return convert((T2)o);
+ }
+ throw new ArgumentException("Cannot handle argument of type "+o.GetType());
+ }
+
+ protected abstract T2 convert(T1 o);
+ protected abstract T1 convert(T2 o);
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs b/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs
new file mode 100644
index 000000000..69aa3feae
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs
@@ -0,0 +1,158 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Reflection;
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Bidirectional binding of properties of two INotifyPropertyChanged instances.
+ /// This implementation synchronizes null values, too. If you do not want this
+ /// behavior (e.g. when binding to a
+ ///
+ public class BidirectionalBinding {
+ private readonly INotifyPropertyChanged _controlObject;
+ private readonly INotifyPropertyChanged _fieldObject;
+ private readonly string _controlPropertyName;
+ private readonly string _fieldPropertyName;
+ private bool _updatingControl;
+ private bool _updatingField;
+ private IBindingConverter _converter;
+ private readonly IBindingValidator _validator;
+
+ ///
+ /// Whether or not null values are passed on to the other object.
+ ///
+ protected bool AllowSynchronizeNull = true;
+
+ ///
+ /// Bind properties of two objects bidirectionally
+ ///
+ /// Object containing 1st property to bind
+ /// Property of 1st object to bind
+ /// Object containing 2nd property to bind
+ /// Property of 2nd object to bind
+ public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName) {
+ _controlObject = controlObject;
+ _fieldObject = fieldObject;
+ _controlPropertyName = controlPropertyName;
+ _fieldPropertyName = fieldPropertyName;
+
+ _controlObject.PropertyChanged += ControlPropertyChanged;
+ _fieldObject.PropertyChanged += FieldPropertyChanged;
+ }
+
+ ///
+ /// Bind properties of two objects bidirectionally, converting the values using a converter
+ ///
+ /// Object containing 1st property to bind
+ /// Property of 1st object to bind
+ /// Object containing 2nd property to bind
+ /// Property of 2nd object to bind
+ /// taking care of converting the synchronized value to the correct target format and back
+ public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) {
+ _converter = converter;
+ }
+
+ ///
+ /// Bind properties of two objects bidirectionally, converting the values using a converter.
+ /// Synchronization can be intercepted by adding a validator.
+ ///
+ /// Object containing 1st property to bind
+ /// Property of 1st object to bind
+ /// Object containing 2nd property to bind
+ /// Property of 2nd object to bind
+ /// validator to intercept synchronization if the value does not match certain criteria
+ public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) {
+ _validator = validator;
+ }
+
+ ///
+ /// Bind properties of two objects bidirectionally, converting the values using a converter.
+ /// Synchronization can be intercepted by adding a validator.
+ ///
+ /// Object containing 1st property to bind
+ /// Property of 1st object to bind
+ /// Object containing 2nd property to bind
+ /// Property of 2nd object to bind
+ /// taking care of converting the synchronized value to the correct target format and back
+ /// validator to intercept synchronization if the value does not match certain criteria
+ public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter) {
+ _validator = validator;
+ }
+
+ public void ControlPropertyChanged(object sender, PropertyChangedEventArgs e) {
+ if (!_updatingControl && e.PropertyName.Equals(_controlPropertyName)) {
+ _updatingField = true;
+ Synchronize(_controlObject, _controlPropertyName, _fieldObject, _fieldPropertyName);
+ _updatingField = false;
+ }
+ }
+
+ public void FieldPropertyChanged(object sender, PropertyChangedEventArgs e) {
+ if (!_updatingField && e.PropertyName.Equals(_fieldPropertyName)) {
+ _updatingControl = true;
+ Synchronize(_fieldObject, _fieldPropertyName, _controlObject, _controlPropertyName);
+ _updatingControl = false;
+ }
+ }
+
+ private void Synchronize(INotifyPropertyChanged sourceObject, string sourceProperty, INotifyPropertyChanged targetObject, string targetProperty) {
+ PropertyInfo targetPropertyInfo = ResolvePropertyInfo(targetObject, targetProperty);
+ PropertyInfo sourcePropertyInfo = ResolvePropertyInfo(sourceObject, sourceProperty);
+
+ if (sourcePropertyInfo != null && targetPropertyInfo != null && targetPropertyInfo.CanWrite) {
+ object bValue = sourcePropertyInfo.GetValue(sourceObject, null);
+ if (_converter != null && bValue != null) {
+ bValue = _converter.convert(bValue);
+ }
+ try {
+ if (_validator == null || _validator.validate(bValue)) {
+ targetPropertyInfo.SetValue(targetObject, bValue, null);
+ }
+ } catch (Exception e) {
+ throw new MemberAccessException("Could not set property '"+targetProperty+"' to '"+bValue+"' ["+(bValue?.GetType().Name ?? "")+"] on "+targetObject+". Probably other type than expected, IBindingCoverter to the rescue.", e);
+ }
+
+ }
+ }
+
+ private static PropertyInfo ResolvePropertyInfo(object obj, string property) {
+ PropertyInfo ret = null;
+ string[] properties = property.Split(".".ToCharArray());
+ for(int i=0; i .
+ */
+using System;
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Converts decimal to double (%) and vice versa, e.g. 95f to 0.95d
+ ///
+ public class DecimalDoublePercentageConverter : AbstractBindingConverter
+ {
+ private static DecimalDoublePercentageConverter uniqueInstance;
+
+ private DecimalDoublePercentageConverter() {}
+
+ protected override decimal convert(double o) {
+ return Convert.ToDecimal(o)*100;
+ }
+
+ protected override double convert(decimal o) {
+ return Convert.ToDouble(o)/100;
+ }
+
+ public static DecimalDoublePercentageConverter GetInstance() {
+ if(uniqueInstance == null) uniqueInstance = new DecimalDoublePercentageConverter();
+ return uniqueInstance;
+ }
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs b/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs
new file mode 100644
index 000000000..1a9ce5de4
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Converts decimal to float and vice versa.
+ ///
+ public class DecimalFloatConverter : AbstractBindingConverter
+ {
+ private static DecimalFloatConverter uniqueInstance;
+
+ private DecimalFloatConverter() {}
+
+ protected override decimal convert(float o) {
+ return Convert.ToDecimal(o);
+ }
+
+ protected override float convert(decimal o) {
+ return Convert.ToInt16(o);
+ }
+
+ public static DecimalFloatConverter GetInstance() {
+ if(uniqueInstance == null) uniqueInstance = new DecimalFloatConverter();
+ return uniqueInstance;
+ }
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs b/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs
new file mode 100644
index 000000000..07b131088
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Converts decimal to int and vice versa.
+ ///
+ public class DecimalIntConverter : AbstractBindingConverter
+ {
+ private static DecimalIntConverter uniqueInstance;
+
+ private DecimalIntConverter() {}
+
+ protected override decimal convert(int o) {
+ return Convert.ToDecimal(o);
+ }
+
+ protected override int convert(decimal o) {
+ return Convert.ToInt16(o);
+ }
+
+ public static DecimalIntConverter GetInstance() {
+ if(uniqueInstance == null) uniqueInstance = new DecimalIntConverter();
+ return uniqueInstance;
+ }
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs b/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs
new file mode 100644
index 000000000..0811d9550
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Drawing.Fields.Binding {
+
+ ///
+ /// Interface for a bidirectional converter, for use with BidirectionalBinding.
+ /// convert(object) implementation must deal with both directions.
+ /// see DecimalIntConverter
+ ///
+ public interface IBindingConverter {
+ object convert(object o);
+ }
+
+}
diff --git a/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs b/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs
new file mode 100644
index 000000000..ad0ac6215
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs
@@ -0,0 +1,34 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Drawing.Fields.Binding {
+
+ ///
+ /// Interface for a bidirectional validator, for use with BidirectionalBinding.
+ /// Useful if you do not want to synchronize values which would be illegal on
+ /// one of the bound objects (e.g. null value on some form components)
+ /// see NotNullValidator
+ ///
+ public interface IBindingValidator {
+ bool validate(object o);
+ }
+
+}
diff --git a/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs b/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs
new file mode 100644
index 000000000..971ae7b20
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Drawing.Fields.Binding {
+ ///
+ /// Validates a value not to be null.
+ ///
+ public class NotNullValidator : IBindingValidator {
+ private static NotNullValidator uniqueInstance;
+
+ private NotNullValidator() {
+ }
+
+ public bool validate(object o) {
+ return o != null;
+ }
+
+ public static NotNullValidator GetInstance() {
+ if(uniqueInstance == null) uniqueInstance = new NotNullValidator();
+ return uniqueInstance;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Fields/Field.cs b/Greenshot/Drawing/Fields/Field.cs
new file mode 100644
index 000000000..f6434b73a
--- /dev/null
+++ b/Greenshot/Drawing/Fields/Field.cs
@@ -0,0 +1,131 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Interfaces.Drawing;
+using System;
+using System.ComponentModel;
+
+namespace Greenshot.Drawing.Fields
+{
+ ///
+ /// Represents a single field of a drawable element, i.e.
+ /// line thickness of a rectangle.
+ ///
+ [Serializable]
+ public class Field : IField
+ {
+ [field: NonSerialized]
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private object _myValue;
+ public object Value
+ {
+ get
+ {
+ return _myValue;
+ }
+ set
+ {
+ if (!Equals(_myValue, value))
+ {
+ _myValue = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
+ }
+ }
+ }
+ public IFieldType FieldType
+ {
+ get;
+ set;
+ }
+ public string Scope
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Constructs a new Field instance, usually you should be using FieldFactory
+ /// to create Fields.
+ ///
+ /// FieldType of the Field to be created
+ /// The scope to which the value of this Field is relevant.
+ /// Depending on the scope the Field's value may be shared for other elements
+ /// containing the same FieldType for defaulting to the last used value.
+ /// When scope is set to a Type (e.g. typeof(RectangleContainer)), its value
+ /// should not be reused for FieldHolders of another Type (e.g. typeof(EllipseContainer))
+ ///
+ public Field(IFieldType fieldType, Type scope)
+ {
+ FieldType = fieldType;
+ Scope = scope.Name;
+ }
+ public Field(IFieldType fieldType, string scope)
+ {
+ FieldType = fieldType;
+ Scope = scope;
+ }
+ public Field(IFieldType fieldType)
+ {
+ FieldType = fieldType;
+ }
+ ///
+ /// Returns true if this field holds a value other than null.
+ ///
+ public bool HasValue => Value != null;
+
+ ///
+ /// Creates a flat clone of this Field. The fields value itself is not cloned.
+ ///
+ ///
+ public Field Clone()
+ {
+ return new Field(FieldType, Scope) {Value = Value};
+ }
+
+ public override int GetHashCode()
+ {
+ int hashCode = 0;
+ unchecked
+ {
+ hashCode += 1000000009 * FieldType.GetHashCode();
+ if (Scope != null)
+ hashCode += 1000000021 * Scope.GetHashCode();
+ }
+ return hashCode;
+ }
+
+ public override bool Equals(object obj)
+ {
+ var other = obj as Field;
+ if (other == null)
+ {
+ return false;
+ }
+ return FieldType == other.FieldType && Equals(Scope, other.Scope);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[Field FieldType={1} Value={0} Scope={2}]", _myValue, FieldType, Scope);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Fields/FieldAggregator.cs b/Greenshot/Drawing/Fields/FieldAggregator.cs
new file mode 100644
index 000000000..3eb2f8bac
--- /dev/null
+++ b/Greenshot/Drawing/Fields/FieldAggregator.cs
@@ -0,0 +1,225 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using Greenshot.Configuration;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Interfaces.Drawing;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Greenshot.Drawing.Fields
+{
+ ///
+ /// Represents the current set of properties for the editor.
+ /// When one of EditorProperties' properties is updated, the change will be promoted
+ /// to all bound elements.
+ /// * If an element is selected:
+ /// This class represents the element's properties
+ /// * I n>1 elements are selected:
+ /// This class represents the properties of all elements.
+ /// Properties that do not apply for ALL selected elements are null (or 0 respectively)
+ /// If the property values of the selected elements differ, the value of the last bound element wins.
+ ///
+ [Serializable]
+ public sealed class FieldAggregator : AbstractFieldHolder
+ {
+
+ private readonly IDrawableContainerList _boundContainers;
+ private bool _internalUpdateRunning;
+
+ private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection();
+
+ public FieldAggregator(ISurface parent)
+ {
+ foreach (var fieldType in FieldType.Values)
+ {
+ var field = new Field(fieldType, GetType());
+ AddField(field);
+ }
+ _boundContainers = new DrawableContainerList
+ {
+ Parent = parent
+ };
+ }
+
+ public override void AddField(IField field)
+ {
+ base.AddField(field);
+ field.PropertyChanged += OwnPropertyChanged;
+ }
+
+ public void BindElements(IDrawableContainerList dcs)
+ {
+ foreach (var dc in dcs)
+ {
+ BindElement(dc);
+ }
+ }
+
+ public void BindElement(IDrawableContainer dc)
+ {
+ DrawableContainer container = dc as DrawableContainer;
+ if (container == null || _boundContainers.Contains(container))
+ {
+ return;
+ }
+ _boundContainers.Add(container);
+ container.ChildrenChanged += delegate {
+ UpdateFromBoundElements();
+ };
+ UpdateFromBoundElements();
+ }
+
+ public void BindAndUpdateElement(IDrawableContainer dc)
+ {
+ UpdateElement(dc);
+ BindElement(dc);
+ }
+
+ public void UpdateElement(IDrawableContainer dc)
+ {
+ DrawableContainer container = dc as DrawableContainer;
+ if (container == null)
+ {
+ return;
+ }
+ _internalUpdateRunning = true;
+ foreach (var field in GetFields())
+ {
+ if (container.HasField(field.FieldType) && field.HasValue)
+ {
+ //if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value);
+ container.SetFieldValue(field.FieldType, field.Value);
+ }
+ }
+ _internalUpdateRunning = false;
+ }
+
+ public void UnbindElement(IDrawableContainer dc)
+ {
+ if (_boundContainers.Contains(dc))
+ {
+ _boundContainers.Remove(dc);
+ UpdateFromBoundElements();
+ }
+ }
+
+ public void Clear()
+ {
+ ClearFields();
+ _boundContainers.Clear();
+ UpdateFromBoundElements();
+ }
+
+ ///
+ /// sets all field values to null, however does not remove fields
+ ///
+ private void ClearFields()
+ {
+ _internalUpdateRunning = true;
+ foreach (var field in GetFields())
+ {
+ field.Value = null;
+ }
+ _internalUpdateRunning = false;
+ }
+
+ ///
+ /// Updates this instance using the respective fields from the bound elements.
+ /// Fields that do not apply to every bound element are set to null, or 0 respectively.
+ /// All other fields will be set to the field value of the least bound element.
+ ///
+ private void UpdateFromBoundElements()
+ {
+ ClearFields();
+ _internalUpdateRunning = true;
+ foreach (var field in FindCommonFields())
+ {
+ SetFieldValue(field.FieldType, field.Value);
+ }
+ _internalUpdateRunning = false;
+ }
+
+ private IList FindCommonFields()
+ {
+ IList returnFields = null;
+ if (_boundContainers.Count > 0)
+ {
+ // take all fields from the least selected container...
+ DrawableContainer leastSelectedContainer = _boundContainers[_boundContainers.Count - 1] as DrawableContainer;
+ if (leastSelectedContainer != null)
+ {
+ returnFields = leastSelectedContainer.GetFields();
+ for (int i = 0; i < _boundContainers.Count - 1; i++)
+ {
+ DrawableContainer dc = _boundContainers[i] as DrawableContainer;
+ if (dc != null)
+ {
+ IList fieldsToRemove = new List();
+ foreach (IField field in returnFields)
+ {
+ // ... throw out those that do not apply to one of the other containers
+ if (!dc.HasField(field.FieldType))
+ {
+ fieldsToRemove.Add(field);
+ }
+ }
+ foreach (var field in fieldsToRemove)
+ {
+ returnFields.Remove(field);
+ }
+ }
+ }
+ }
+ }
+ return returnFields ?? new List();
+ }
+
+ public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea)
+ {
+ IField field = (IField)sender;
+ if (_internalUpdateRunning || field.Value == null)
+ {
+ return;
+ }
+ foreach (var drawableContainer1 in _boundContainers.ToList())
+ {
+ var drawableContainer = (DrawableContainer) drawableContainer1;
+ if (!drawableContainer.HasField(field.FieldType))
+ {
+ continue;
+ }
+ IField drawableContainerField = drawableContainer.GetField(field.FieldType);
+ // Notify before change, so we can e.g. invalidate the area
+ drawableContainer.BeforeFieldChange(drawableContainerField, field.Value);
+
+ drawableContainerField.Value = field.Value;
+ // update last used from DC field, so that scope is honored
+ EditorConfig.UpdateLastFieldValue(drawableContainerField);
+ }
+ }
+
+ }
+}
diff --git a/Greenshot/Drawing/Fields/FieldType.cs b/Greenshot/Drawing/Fields/FieldType.cs
new file mode 100644
index 000000000..d99af3759
--- /dev/null
+++ b/Greenshot/Drawing/Fields/FieldType.cs
@@ -0,0 +1,123 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using GreenshotPlugin.Interfaces.Drawing;
+using System;
+
+namespace Greenshot.Drawing.Fields
+{
+ ///
+ /// Defines all FieldTypes + their default value.
+ /// (The additional value is why this is not an enum)
+ ///
+ [Serializable]
+ public class FieldType : IFieldType
+ {
+
+ public static readonly IFieldType ARROWHEADS = new FieldType("ARROWHEADS");
+ public static readonly IFieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS");
+ public static readonly IFieldType BRIGHTNESS = new FieldType("BRIGHTNESS");
+ public static readonly IFieldType FILL_COLOR = new FieldType("FILL_COLOR");
+ public static readonly IFieldType FONT_BOLD = new FieldType("FONT_BOLD");
+ public static readonly IFieldType FONT_FAMILY = new FieldType("FONT_FAMILY");
+ public static readonly IFieldType FONT_ITALIC = new FieldType("FONT_ITALIC");
+ public static readonly IFieldType FONT_SIZE = new FieldType("FONT_SIZE");
+ public static readonly IFieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT");
+ public static readonly IFieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT");
+ public static readonly IFieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR");
+ public static readonly IFieldType LINE_COLOR = new FieldType("LINE_COLOR");
+ public static readonly IFieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS");
+ public static readonly IFieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR");
+ public static readonly IFieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE");
+ public static readonly IFieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY");
+ public static readonly IFieldType SHADOW = new FieldType("SHADOW");
+ public static readonly IFieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE");
+ public static readonly IFieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT");
+ public static readonly IFieldType FLAGS = new FieldType("FLAGS");
+
+ public static IFieldType[] Values = {
+ ARROWHEADS,
+ BLUR_RADIUS,
+ BRIGHTNESS,
+ FILL_COLOR,
+ FONT_BOLD,
+ FONT_FAMILY,
+ FONT_ITALIC,
+ FONT_SIZE,
+ TEXT_HORIZONTAL_ALIGNMENT,
+ TEXT_VERTICAL_ALIGNMENT,
+ HIGHLIGHT_COLOR,
+ LINE_COLOR,
+ LINE_THICKNESS,
+ MAGNIFICATION_FACTOR,
+ PIXEL_SIZE,
+ PREVIEW_QUALITY,
+ SHADOW,
+ PREPARED_FILTER_OBFUSCATE,
+ PREPARED_FILTER_HIGHLIGHT,
+ FLAGS
+ };
+
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ private FieldType(string name)
+ {
+ Name = name;
+ }
+ public override string ToString()
+ {
+ return Name;
+ }
+ public override int GetHashCode()
+ {
+ int hashCode = 0;
+ unchecked
+ {
+ if (Name != null)
+ hashCode += 1000000009 * Name.GetHashCode();
+ }
+ return hashCode;
+ }
+
+ public override bool Equals(object obj)
+ {
+ FieldType other = obj as FieldType;
+ if (other == null)
+ {
+ return false;
+ }
+ return Equals(Name, other.Name);
+ }
+
+ public static bool operator ==(FieldType a, FieldType b)
+ {
+ return Equals(a, b);
+ }
+
+ public static bool operator !=(FieldType a, FieldType b)
+ {
+ return !Equals(a, b);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Fields/IFieldHolder.cs b/Greenshot/Drawing/Fields/IFieldHolder.cs
new file mode 100644
index 000000000..063ca48d7
--- /dev/null
+++ b/Greenshot/Drawing/Fields/IFieldHolder.cs
@@ -0,0 +1,53 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+
+namespace Greenshot.Drawing.Fields {
+ ///
+ /// Any element holding Fields must provide access to it.
+ /// AbstractFieldHolder is the basic implementation.
+ /// If you need the fieldHolder to have child fieldHolders,
+ /// you should consider using IFieldHolderWithChildren.
+ ///
+ public interface IFieldHolder {
+
+ event FieldChangedEventHandler FieldChanged;
+
+ void AddField(Field field);
+ void RemoveField(Field field);
+ List GetFields();
+ Field GetField(FieldType fieldType);
+ bool HasField(FieldType fieldType);
+ void SetFieldValue(FieldType fieldType, object value);
+ }
+
+ ///
+ /// Extended fieldHolder which has fieldHolder children.
+ /// Implementations should pass field values to and from
+ /// their children.
+ /// AbstractFieldHolderWithChildren is the basic implementation.
+ ///
+ public interface IFieldHolderWithChildren : IFieldHolder {
+ void AddChild(IFieldHolder fieldHolder);
+ void RemoveChild(IFieldHolder fieldHolder);
+ }
+}
diff --git a/Greenshot/Drawing/FilterContainer.cs b/Greenshot/Drawing/FilterContainer.cs
new file mode 100644
index 000000000..b69af0a53
--- /dev/null
+++ b/Greenshot/Drawing/FilterContainer.cs
@@ -0,0 +1,98 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing {
+ ///
+ /// empty container for filter-only elements
+ ///
+ [Serializable()]
+ public abstract class FilterContainer : DrawableContainer {
+
+ public enum PreparedFilterMode {OBFUSCATE, HIGHLIGHT};
+ public enum PreparedFilter {BLUR, PIXELIZE, TEXT_HIGHTLIGHT, AREA_HIGHLIGHT, GRAYSCALE, MAGNIFICATION};
+
+ public PreparedFilter Filter {
+ get { return (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); }
+ }
+
+ public FilterContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 0);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.SHADOW, false);
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
+ if (lineVisible) {
+ graphics.SmoothingMode = SmoothingMode.HighSpeed;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ //draw shadow first
+ if (shadow) {
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = lineVisible ? 1 : 0;
+ while (currentStep <= steps) {
+ using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) {
+ Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height);
+ graphics.DrawRectangle(shadowPen, shadowRect);
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ graphics.DrawRectangle(pen, rect);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/AbstractFilter.cs b/Greenshot/Drawing/Filters/AbstractFilter.cs
new file mode 100644
index 000000000..d9e8806ac
--- /dev/null
+++ b/Greenshot/Drawing/Filters/AbstractFilter.cs
@@ -0,0 +1,80 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Drawing;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Drawing.Filters {
+ ///
+ /// Graphical filter which can be added to DrawableContainer.
+ /// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
+ /// OnPropertyChanged whenever a public property has been changed.
+ ///
+ [Serializable]
+ public abstract class AbstractFilter : AbstractFieldHolder, IFilter {
+
+ [NonSerialized]
+ private PropertyChangedEventHandler propertyChanged;
+ public event PropertyChangedEventHandler PropertyChanged {
+ add { propertyChanged += value; }
+ remove{ propertyChanged -= value; }
+ }
+
+ private bool invert;
+ public bool Invert {
+ get {
+ return invert;
+ }
+ set {
+ invert = value;
+ OnPropertyChanged("Invert");
+ }
+ }
+
+ protected DrawableContainer parent;
+ public DrawableContainer Parent {
+ get {
+ return parent;
+ }
+ set {
+ parent = value;
+ }
+ }
+
+ public AbstractFilter(DrawableContainer parent) {
+ this.parent = parent;
+ }
+
+ public DrawableContainer GetParent() {
+ return parent;
+ }
+
+ public abstract void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode);
+
+ protected void OnPropertyChanged(string propertyName)
+ {
+ propertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/BlurFilter.cs b/Greenshot/Drawing/Filters/BlurFilter.cs
new file mode 100644
index 000000000..f9b2c843c
--- /dev/null
+++ b/Greenshot/Drawing/Filters/BlurFilter.cs
@@ -0,0 +1,66 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Drawing.Filters {
+ [Serializable]
+ public class BlurFilter : AbstractFilter {
+ public double previewQuality;
+ public double PreviewQuality {
+ get { return previewQuality; }
+ set { previewQuality = value; OnPropertyChanged("PreviewQuality"); }
+ }
+
+ public BlurFilter(DrawableContainer parent) : base(parent) {
+ AddField(GetType(), FieldType.BLUR_RADIUS, 3);
+ AddField(GetType(), FieldType.PREVIEW_QUALITY, 1.0d);
+ }
+
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+ if (applyRect.Width == 0 || applyRect.Height == 0) {
+ return;
+ }
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ if (GDIplus.IsBlurPossible(blurRadius)) {
+ GDIplus.DrawWithBlur(graphics, applyBitmap, applyRect, null, null, blurRadius, false);
+ } else {
+ using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
+ ImageHelper.ApplyBoxBlur(fastBitmap, blurRadius);
+ fastBitmap.DrawTo(graphics, applyRect);
+ }
+ }
+ graphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/BrightnessFilter.cs b/Greenshot/Drawing/Filters/BrightnessFilter.cs
new file mode 100644
index 000000000..b5154f783
--- /dev/null
+++ b/Greenshot/Drawing/Filters/BrightnessFilter.cs
@@ -0,0 +1,64 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Drawing.Filters {
+ [Serializable()]
+ public class BrightnessFilter : AbstractFilter {
+
+ public BrightnessFilter(DrawableContainer parent) : base(parent) {
+ AddField(GetType(), FieldType.BRIGHTNESS, 0.9d);
+ }
+
+ ///
+ /// Implements the Apply code for the Brightness Filet
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+
+ if (applyRect.Width == 0 || applyRect.Height == 0) {
+ // nothing to do
+ return;
+ }
+
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ float brightness = GetFieldValueAsFloat(FieldType.BRIGHTNESS);
+ using (ImageAttributes ia = ImageHelper.CreateAdjustAttributes(brightness, 1f, 1f)) {
+ graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
+ }
+ graphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/GrayscaleFilter.cs b/Greenshot/Drawing/Filters/GrayscaleFilter.cs
new file mode 100644
index 000000000..c6318dc22
--- /dev/null
+++ b/Greenshot/Drawing/Filters/GrayscaleFilter.cs
@@ -0,0 +1,64 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+
+namespace Greenshot.Drawing.Filters {
+ ///
+ /// Description of GrayscaleFilter.
+ ///
+ [Serializable()]
+ public class GrayscaleFilter : AbstractFilter {
+ public GrayscaleFilter(DrawableContainer parent) : base(parent) {
+ }
+
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+
+ if (applyRect.Width == 0 || applyRect.Height == 0) {
+ // nothing to do
+ return;
+ }
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ ColorMatrix grayscaleMatrix = new ColorMatrix(new[] {
+ new[] {.3f, .3f, .3f, 0, 0},
+ new[] {.59f, .59f, .59f, 0, 0},
+ new[] {.11f, .11f, .11f, 0, 0},
+ new float[] {0, 0, 0, 1, 0},
+ new float[] {0, 0, 0, 0, 1}
+ });
+ using (ImageAttributes ia = new ImageAttributes()) {
+ ia.SetColorMatrix(grayscaleMatrix);
+ graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
+ }
+ graphics.Restore(state);
+
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/HighlightFilter.cs b/Greenshot/Drawing/Filters/HighlightFilter.cs
new file mode 100644
index 000000000..41248b01f
--- /dev/null
+++ b/Greenshot/Drawing/Filters/HighlightFilter.cs
@@ -0,0 +1,68 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Drawing.Filters {
+ [Serializable()]
+ public class HighlightFilter : AbstractFilter {
+ public HighlightFilter(DrawableContainer parent) : base(parent) {
+ AddField(GetType(), FieldType.FILL_COLOR, Color.Yellow);
+ }
+
+ ///
+ /// Implements the Apply code for the Brightness Filet
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+
+ if (applyRect.Width == 0 || applyRect.Height == 0) {
+ // nothing to do
+ return;
+ }
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
+ Color highlightColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ for (int y = fastBitmap.Top; y < fastBitmap.Bottom; y++) {
+ for (int x = fastBitmap.Left; x < fastBitmap.Right; x++) {
+ Color color = fastBitmap.GetColorAt(x, y);
+ color = Color.FromArgb(color.A, Math.Min(highlightColor.R, color.R), Math.Min(highlightColor.G, color.G), Math.Min(highlightColor.B, color.B));
+ fastBitmap.SetColorAt(x, y, color);
+ }
+ }
+ fastBitmap.DrawTo(graphics, applyRect.Location);
+ }
+ graphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/IFilter.cs b/Greenshot/Drawing/Filters/IFilter.cs
new file mode 100644
index 000000000..74895d582
--- /dev/null
+++ b/Greenshot/Drawing/Filters/IFilter.cs
@@ -0,0 +1,35 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing.Filters
+{
+ public interface IFilter : INotifyPropertyChanged, IFieldHolder {
+ DrawableContainer Parent {get; set; }
+ void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode);
+ DrawableContainer GetParent();
+ bool Invert {get; set;}
+ }
+}
diff --git a/Greenshot/Drawing/Filters/MagnifierFilter.cs b/Greenshot/Drawing/Filters/MagnifierFilter.cs
new file mode 100644
index 000000000..e0b69c263
--- /dev/null
+++ b/Greenshot/Drawing/Filters/MagnifierFilter.cs
@@ -0,0 +1,61 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Drawing.Filters {
+ [Serializable]
+ public class MagnifierFilter : AbstractFilter {
+ public MagnifierFilter(DrawableContainer parent) : base(parent) {
+ AddField(GetType(), FieldType.MAGNIFICATION_FACTOR, 2);
+ }
+
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+
+ if (applyRect.Width == 0 || applyRect.Height == 0) {
+ // nothing to do
+ return;
+ }
+ int magnificationFactor = GetFieldValueAsInt(FieldType.MAGNIFICATION_FACTOR);
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ graphics.SmoothingMode = SmoothingMode.None;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ int halfWidth = rect.Width / 2;
+ int halfHeight = rect.Height / 2;
+ int newWidth = rect.Width / magnificationFactor;
+ int newHeight = rect.Height / magnificationFactor;
+ Rectangle source = new Rectangle(rect.X + halfWidth - newWidth / 2, rect.Y + halfHeight - newHeight / 2, newWidth, newHeight);
+ graphics.DrawImage(applyBitmap, rect, source, GraphicsUnit.Pixel);
+ graphics.Restore(state);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Filters/PixelizationFilter.cs b/Greenshot/Drawing/Filters/PixelizationFilter.cs
new file mode 100644
index 000000000..5e4727af8
--- /dev/null
+++ b/Greenshot/Drawing/Filters/PixelizationFilter.cs
@@ -0,0 +1,84 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Drawing.Filters {
+ [Serializable()]
+ public class PixelizationFilter : AbstractFilter {
+
+ public PixelizationFilter(DrawableContainer parent) : base(parent) {
+ AddField(GetType(), FieldType.PIXEL_SIZE, 5);
+ }
+
+ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
+ int pixelSize = GetFieldValueAsInt(FieldType.PIXEL_SIZE);
+ ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+ if (pixelSize <= 1 || rect.Width == 0 || rect.Height == 0) {
+ // Nothing to do
+ return;
+ }
+ if (rect.Width < pixelSize) {
+ pixelSize = rect.Width;
+ }
+ if (rect.Height < pixelSize) {
+ pixelSize = rect.Height;
+ }
+ using (IFastBitmap dest = FastBitmap.CreateCloneOf(applyBitmap, rect)) {
+ using (IFastBitmap src = FastBitmap.Create(applyBitmap, rect)) {
+ List colors = new List();
+ int halbPixelSize = pixelSize / 2;
+ for (int y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize) {
+ for (int x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize) {
+ colors.Clear();
+ for (int yy = y; yy < y + pixelSize; yy++) {
+ if (yy >= src.Top && yy < src.Bottom) {
+ for (int xx = x; xx < x + pixelSize; xx++) {
+ if (xx >= src.Left && xx < src.Right) {
+ colors.Add(src.GetColorAt(xx, yy));
+ }
+ }
+ }
+ }
+ Color currentAvgColor = Colors.Mix(colors);
+ for (int yy = y; yy <= y + pixelSize; yy++) {
+ if (yy >= src.Top && yy < src.Bottom) {
+ for (int xx = x; xx <= x + pixelSize; xx++) {
+ if (xx >= src.Left && xx < src.Right) {
+ dest.SetColorAt(xx, yy, currentAvgColor);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ dest.DrawTo(graphics, rect.Location);
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/FreehandContainer.cs b/Greenshot/Drawing/FreehandContainer.cs
new file mode 100644
index 000000000..ccff8a690
--- /dev/null
+++ b/Greenshot/Drawing/FreehandContainer.cs
@@ -0,0 +1,286 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of PathContainer.
+ ///
+ [Serializable]
+ public class FreehandContainer : DrawableContainer {
+ private static readonly float [] PointOffset = {0.5f, 0.25f, 0.75f};
+
+ [NonSerialized]
+ private readonly object _freehandPathLock = new object();
+
+ [NonSerialized]
+ private GraphicsPath freehandPath = new GraphicsPath();
+ private Rectangle myBounds = Rectangle.Empty;
+ private Point lastMouse = Point.Empty;
+ private readonly List capturePoints = new List();
+ private bool isRecalculated;
+
+ ///
+ /// Constructor
+ ///
+ public FreehandContainer(Surface parent) : base(parent) {
+ Width = parent.Width;
+ Height = parent.Height;
+ Top = 0;
+ Left = 0;
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 3);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ }
+
+ public override void Transform(Matrix matrix) {
+ Point[] points = capturePoints.ToArray();
+
+ matrix.TransformPoints(points);
+ capturePoints.Clear();
+ capturePoints.AddRange(points);
+ RecalculatePath();
+ }
+
+ protected override void OnDeserialized(StreamingContext context) {
+ RecalculatePath();
+ }
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ ///
+ /// When disposing==true all non-managed resources should be freed too!
+ protected override void Dispose(bool disposing) {
+ base.Dispose(disposing);
+ if (disposing)
+ {
+ freehandPath?.Dispose();
+ }
+ freehandPath = null;
+ }
+
+ ///
+ /// Called from Surface (the parent) when the drawing begins (mouse-down)
+ ///
+ /// true if the surface doesn't need to handle the event
+ public override bool HandleMouseDown(int mouseX, int mouseY) {
+ lastMouse = new Point(mouseX, mouseY);
+ capturePoints.Add(lastMouse);
+ return true;
+ }
+
+ ///
+ /// Called from Surface (the parent) if a mouse move is made while drawing
+ ///
+ /// true if the surface doesn't need to handle the event
+ public override bool HandleMouseMove(int mouseX, int mouseY) {
+ Point previousPoint = capturePoints[capturePoints.Count-1];
+
+ if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2*EditorConfig.FreehandSensitivity) {
+ capturePoints.Add(new Point(mouseX, mouseY));
+ }
+ if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) < EditorConfig.FreehandSensitivity)
+ {
+ return true;
+ }
+ //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)});
+ lastMouse = new Point(mouseX, mouseY);
+ lock (_freehandPathLock)
+ {
+ freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY));
+ // Only re-calculate the bounds & redraw when we added something to the path
+ myBounds = Rectangle.Round(freehandPath.GetBounds());
+ }
+
+ Invalidate();
+ return true;
+ }
+
+ ///
+ /// Called when the surface finishes drawing the element
+ ///
+ public override void HandleMouseUp(int mouseX, int mouseY) {
+ // Make sure we don't loose the ending point
+ if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) {
+ capturePoints.Add(new Point(mouseX, mouseY));
+ }
+ RecalculatePath();
+ }
+
+ ///
+ /// Here we recalculate the freehand path by smoothing out the lines with Beziers.
+ ///
+ private void RecalculatePath() {
+ lock (_freehandPathLock)
+ {
+ isRecalculated = true;
+ // Dispose the previous path, if we have one
+ freehandPath?.Dispose();
+ freehandPath = new GraphicsPath();
+
+ // Here we can put some cleanup... like losing all the uninteresting points.
+ if (capturePoints.Count >= 3)
+ {
+ int index = 0;
+ while ((capturePoints.Count - 1) % 3 != 0)
+ {
+ // duplicate points, first at 50% than 25% than 75%
+ capturePoints.Insert((int)(capturePoints.Count * PointOffset[index]), capturePoints[(int)(capturePoints.Count * PointOffset[index++])]);
+ }
+ freehandPath.AddBeziers(capturePoints.ToArray());
+ }
+ else if (capturePoints.Count == 2)
+ {
+ freehandPath.AddLine(capturePoints[0], capturePoints[1]);
+ }
+
+ // Recalculate the bounds
+ myBounds = Rectangle.Round(freehandPath.GetBounds());
+
+ }
+
+ }
+
+ ///
+ /// Do the drawing of the freehand "stroke"
+ ///
+ ///
+ ///
+ public override void Draw(Graphics graphics, RenderMode renderMode) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ using (var pen = new Pen(lineColor)) {
+ pen.Width = lineThickness;
+ if (!(pen.Width > 0))
+ {
+ return;
+ }
+ // Make sure the lines are nicely rounded
+ pen.EndCap = LineCap.Round;
+ pen.StartCap = LineCap.Round;
+ pen.LineJoin = LineJoin.Round;
+ // Move to where we need to draw
+ graphics.TranslateTransform(Left, Top);
+ lock (_freehandPathLock)
+ {
+ if (isRecalculated && Selected && renderMode == RenderMode.EDIT)
+ {
+ DrawSelectionBorder(graphics, pen, freehandPath);
+ }
+ graphics.DrawPath(pen, freehandPath);
+ }
+
+ // Move back, otherwise everything is shifted
+ graphics.TranslateTransform(-Left,-Top);
+ }
+ }
+
+ ///
+ /// Draw a selectionborder around the freehand path
+ ///
+ /// Graphics
+ /// Pen
+ /// GraphicsPath
+ protected static void DrawSelectionBorder(Graphics graphics, Pen linePen, GraphicsPath path) {
+ using (var selectionPen = (Pen) linePen.Clone()) {
+ using (var selectionPath = (GraphicsPath)path.Clone()) {
+ selectionPen.Width += 5;
+ selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen);
+ graphics.DrawPath(selectionPen, selectionPath);
+ selectionPath.Widen(selectionPen);
+ selectionPen.DashPattern = new float[]{2,2};
+ selectionPen.Color = Color.LightSeaGreen;
+ selectionPen.Width = 1;
+ graphics.DrawPath(selectionPen, selectionPath);
+ }
+ }
+ }
+
+ ///
+ /// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds...
+ ///
+ public override Rectangle DrawingBounds {
+ get {
+ if (!myBounds.IsEmpty) {
+ int lineThickness = Math.Max(10, GetFieldValueAsInt(FieldType.LINE_THICKNESS));
+ int safetymargin = 10;
+ return new Rectangle(myBounds.Left + Left - (safetymargin+lineThickness), myBounds.Top + Top - (safetymargin+lineThickness), myBounds.Width + 2*(lineThickness+safetymargin), myBounds.Height + 2*(lineThickness+safetymargin));
+ }
+ return new Rectangle(0, 0, _parent?.Width??0, _parent?.Height?? 0);
+ }
+ }
+
+ ///
+ /// FreehandContainer are regarded equal if they are of the same type and their paths are equal.
+ ///
+ /// object
+ /// bool
+ public override bool Equals(object obj) {
+ bool ret = false;
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+ var other = obj as FreehandContainer;
+ if (other != null && Equals(freehandPath, other.freehandPath)) {
+ ret = true;
+ }
+ return ret;
+ }
+
+ public override int GetHashCode() {
+ lock (_freehandPathLock)
+ {
+ return freehandPath?.GetHashCode() ?? 0;
+ }
+ }
+
+ public override bool ClickableAt(int x, int y) {
+ bool returnValue = base.ClickableAt(x, y);
+ if (returnValue) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ using (var pen = new Pen(Color.White)) {
+ pen.Width = lineThickness + 10;
+ lock (_freehandPathLock)
+ {
+ returnValue = freehandPath.IsOutlineVisible(x - Left, y - Top, pen);
+ }
+ }
+ }
+ return returnValue;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/HighlightContainer.cs b/Greenshot/Drawing/HighlightContainer.cs
new file mode 100644
index 000000000..82a352469
--- /dev/null
+++ b/Greenshot/Drawing/HighlightContainer.cs
@@ -0,0 +1,97 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Runtime.Serialization;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Drawing.Filters;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of ObfuscateContainer.
+ ///
+ [Serializable]
+ public class HighlightContainer : FilterContainer {
+ public HighlightContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ ///
+ /// Use settings from base, extend with our own field
+ ///
+ protected override void InitializeFields() {
+ base.InitializeFields();
+ AddField(GetType(), FieldType.PREPARED_FILTER_HIGHLIGHT, PreparedFilter.TEXT_HIGHTLIGHT);
+ }
+
+ protected override void OnDeserialized(StreamingContext context)
+ {
+ Init();
+ }
+
+ private void Init() {
+ FieldChanged += HighlightContainer_OnFieldChanged;
+ ConfigurePreparedFilters();
+ }
+
+ protected void HighlightContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) {
+ if (!sender.Equals(this)) {
+ return;
+ }
+ if (Equals(e.Field.FieldType, FieldType.PREPARED_FILTER_HIGHLIGHT)) {
+ ConfigurePreparedFilters();
+ }
+ }
+
+ private void ConfigurePreparedFilters() {
+ PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT);
+ while(Filters.Count>0) {
+ Remove(Filters[0]);
+ }
+ switch(preset) {
+ case PreparedFilter.TEXT_HIGHTLIGHT:
+ Add(new HighlightFilter(this));
+ break;
+ case PreparedFilter.AREA_HIGHLIGHT:
+ var brightnessFilter = new BrightnessFilter(this)
+ {
+ Invert = true
+ };
+ Add(brightnessFilter);
+ var blurFilter = new BlurFilter(this)
+ {
+ Invert = true
+ };
+ Add(blurFilter);
+ break;
+ case PreparedFilter.GRAYSCALE:
+ AbstractFilter f = new GrayscaleFilter(this);
+ f.Invert = true;
+ Add(f);
+ break;
+ case PreparedFilter.MAGNIFICATION:
+ Add(new MagnifierFilter(this));
+ break;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/IconContainer.cs b/Greenshot/Drawing/IconContainer.cs
new file mode 100644
index 000000000..2277bd48a
--- /dev/null
+++ b/Greenshot/Drawing/IconContainer.cs
@@ -0,0 +1,104 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.IO;
+using Greenshot.Plugin.Drawing;
+using System.Drawing.Drawing2D;
+using log4net;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of IconContainer.
+ ///
+ [Serializable]
+ public class IconContainer : DrawableContainer, IIconContainer {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer));
+
+ protected Icon icon;
+
+ public IconContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ public IconContainer(Surface parent, string filename) : base(parent) {
+ Load(filename);
+ }
+
+ public Icon Icon {
+ set {
+ icon?.Dispose();
+ icon = (Icon)value.Clone();
+ Width = value.Width;
+ Height = value.Height;
+ }
+ get { return icon; }
+ }
+
+ /**
+ * This Dispose is called from the Dispose and the Destructor.
+ * When disposing==true all non-managed resources should be freed too!
+ */
+ protected override void Dispose(bool disposing) {
+ if (disposing)
+ {
+ icon?.Dispose();
+ }
+ icon = null;
+ base.Dispose(disposing);
+ }
+
+ public void Load(string filename) {
+ if (File.Exists(filename)) {
+ using (Icon fileIcon = new Icon(filename)) {
+ Icon = fileIcon;
+ Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
+ }
+ }
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ if (icon != null) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.CompositingQuality = CompositingQuality.Default;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.DrawIcon(icon, Bounds);
+ }
+ }
+
+ public override bool HasDefaultSize => true;
+
+ public override Size DefaultSize => icon.Size;
+ }
+}
diff --git a/Greenshot/Drawing/ImageContainer.cs b/Greenshot/Drawing/ImageContainer.cs
new file mode 100644
index 000000000..ab8d4e541
--- /dev/null
+++ b/Greenshot/Drawing/ImageContainer.cs
@@ -0,0 +1,228 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.IO;
+using Greenshot.Drawing.Fields;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using System.Drawing.Drawing2D;
+using log4net;
+using System.Runtime.Serialization;
+using GreenshotPlugin.Effects;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of BitmapContainer.
+ ///
+ [Serializable]
+ public class ImageContainer : DrawableContainer, IImageContainer {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ImageContainer));
+
+ private Image image;
+
+ ///
+ /// This is the shadow version of the bitmap, rendered once to save performance
+ /// Do not serialize, as the shadow is recreated from the original bitmap if it's not available
+ ///
+ [NonSerialized]
+ private Image _shadowBitmap;
+
+ ///
+ /// This is the offset for the shadow version of the bitmap
+ /// Do not serialize, as the offset is recreated
+ ///
+ [NonSerialized]
+ private Point _shadowOffset = new Point(-1, -1);
+
+ public ImageContainer(Surface parent, string filename) : this(parent) {
+ Load(filename);
+ }
+
+ public ImageContainer(Surface parent) : base(parent) {
+ FieldChanged += BitmapContainer_OnFieldChanged;
+ Init();
+ }
+
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.SHADOW, false);
+ }
+
+ protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) {
+ if (sender.Equals(this)) {
+ if (FieldType.SHADOW.Equals(e.Field.FieldType)) {
+ ChangeShadowField();
+ }
+ }
+ }
+
+ public void ChangeShadowField() {
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ if (shadow) {
+ CheckShadow(true);
+ Width = _shadowBitmap.Width;
+ Height = _shadowBitmap.Height;
+ Left = Left - _shadowOffset.X;
+ Top = Top - _shadowOffset.Y;
+ } else {
+ Width = image.Width;
+ Height = image.Height;
+ if (_shadowBitmap != null) {
+ Left = Left + _shadowOffset.X;
+ Top = Top + _shadowOffset.Y;
+ }
+ }
+ }
+
+ public Image Image {
+ set {
+ // Remove all current bitmaps
+ DisposeImage();
+ DisposeShadow();
+ image = ImageHelper.Clone(value);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ CheckShadow(shadow);
+ if (!shadow) {
+ Width = image.Width;
+ Height = image.Height;
+ } else {
+ Width = _shadowBitmap.Width;
+ Height = _shadowBitmap.Height;
+ Left = Left - _shadowOffset.X;
+ Top = Top - _shadowOffset.Y;
+ }
+ }
+ get { return image; }
+ }
+
+ ///
+ /// The bulk of the clean-up code is implemented in Dispose(bool)
+ /// This Dispose is called from the Dispose and the Destructor.
+ /// When disposing==true all non-managed resources should be freed too!
+ ///
+ ///
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ DisposeImage();
+ DisposeShadow();
+ }
+ base.Dispose(disposing);
+ }
+
+ private void DisposeImage() {
+ image?.Dispose();
+ image = null;
+ }
+ private void DisposeShadow() {
+ _shadowBitmap?.Dispose();
+ _shadowBitmap = null;
+ }
+
+
+
+ ///
+ /// Make sure the content is also transformed.
+ ///
+ ///
+ public override void Transform(Matrix matrix) {
+ int rotateAngle = CalculateAngle(matrix);
+ // we currently assume only one transformation has been made.
+ if (rotateAngle != 0) {
+ Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle);
+ DisposeShadow();
+ using (var tmpMatrix = new Matrix()) {
+ using (image)
+ {
+ image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix);
+ }
+ }
+ }
+ base.Transform(matrix);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void Load(string filename) {
+ if (!File.Exists(filename))
+ {
+ return;
+ }
+ // Always make sure ImageHelper.LoadBitmap results are disposed some time,
+ // as we close the bitmap internally, we need to do it afterwards
+ using (var tmpImage = ImageHelper.LoadImage(filename)) {
+ Image = tmpImage;
+ }
+ Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
+ }
+
+ ///
+ /// This checks if a shadow is already generated
+ ///
+ ///
+ private void CheckShadow(bool shadow) {
+ if (shadow && _shadowBitmap == null) {
+ using (var matrix = new Matrix()) {
+ _shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix);
+ }
+ }
+ }
+
+ ///
+ /// Draw the actual container to the graphics object
+ ///
+ ///
+ ///
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ if (image != null) {
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ if (shadow) {
+ CheckShadow(true);
+ graphics.DrawImage(_shadowBitmap, Bounds);
+ } else {
+ graphics.DrawImage(image, Bounds);
+ }
+ }
+ }
+
+ public override bool HasDefaultSize => true;
+
+ public override Size DefaultSize => image.Size;
+ }
+}
diff --git a/Greenshot/Drawing/LineContainer.cs b/Greenshot/Drawing/LineContainer.cs
new file mode 100644
index 000000000..c443f64fc
--- /dev/null
+++ b/Greenshot/Drawing/LineContainer.cs
@@ -0,0 +1,114 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Serialization;
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using Greenshot.Drawing.Adorners;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of LineContainer.
+ ///
+ [Serializable()]
+ public class LineContainer : DrawableContainer {
+ public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10;
+
+ public LineContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.SHADOW, true);
+ }
+
+ protected override void OnDeserialized(StreamingContext context)
+ {
+ Init();
+ }
+
+ protected void Init() {
+ Adorners.Add(new MoveAdorner(this, Positions.TopLeft));
+ Adorners.Add(new MoveAdorner(this, Positions.BottomRight));
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+
+ if (lineThickness > 0) {
+ if (shadow) {
+ //draw shadow first
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = 1;
+ while (currentStep <= steps) {
+ using (Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness)) {
+ graphics.DrawLine(shadowCapPen,
+ Left + currentStep,
+ Top + currentStep,
+ Left + currentStep + Width,
+ Top + currentStep + Height);
+
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
+ }
+ }
+ }
+
+ public override bool ClickableAt(int x, int y) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) +5;
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(Color.White)) {
+ pen.Width = lineThickness;
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddLine(Left, Top, Left + Width, Top + Height);
+ return path.IsOutlineVisible(x, y, pen);
+ }
+ }
+ }
+ return false;
+ }
+
+ protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() {
+ return ScaleHelper.LineAngleRoundBehavior.Instance;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/ObfuscateContainer.cs b/Greenshot/Drawing/ObfuscateContainer.cs
new file mode 100644
index 000000000..ec3b0d734
--- /dev/null
+++ b/Greenshot/Drawing/ObfuscateContainer.cs
@@ -0,0 +1,76 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Runtime.Serialization;
+using Greenshot.Drawing.Fields;
+using Greenshot.Drawing.Filters;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Description of ObfuscateContainer.
+ ///
+ [Serializable]
+ public class ObfuscateContainer : FilterContainer {
+ public ObfuscateContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ protected override void InitializeFields() {
+ base.InitializeFields();
+ AddField(GetType(), FieldType.PREPARED_FILTER_OBFUSCATE, PreparedFilter.PIXELIZE);
+ }
+
+ protected override void OnDeserialized(StreamingContext context)
+ {
+ Init();
+ }
+
+ private void Init() {
+ FieldChanged += ObfuscateContainer_OnFieldChanged;
+ ConfigurePreparedFilters();
+ CreateDefaultAdorners();
+ }
+
+ protected void ObfuscateContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) {
+ if(sender.Equals(this)) {
+ if(Equals(e.Field.FieldType, FieldType.PREPARED_FILTER_OBFUSCATE)) {
+ ConfigurePreparedFilters();
+ }
+ }
+ }
+
+ private void ConfigurePreparedFilters() {
+ PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE);
+ while(Filters.Count>0) {
+ Remove(Filters[0]);
+ }
+ switch(preset) {
+ case PreparedFilter.BLUR:
+ Add(new BlurFilter(this));
+ break;
+ case PreparedFilter.PIXELIZE:
+ Add(new PixelizationFilter(this));
+ break;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Positions.cs b/Greenshot/Drawing/Positions.cs
new file mode 100644
index 000000000..8ed2611bf
--- /dev/null
+++ b/Greenshot/Drawing/Positions.cs
@@ -0,0 +1,38 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Drawing
+{
+ ///
+ /// Position
+ ///
+ public enum Positions : int
+ {
+ TopLeft = 0,
+ TopCenter = 1,
+ TopRight = 2,
+ MiddleRight = 3,
+ BottomRight = 4,
+ BottomCenter = 5,
+ BottomLeft = 6,
+ MiddleLeft = 7
+ }
+}
diff --git a/Greenshot/Drawing/RectangleContainer.cs b/Greenshot/Drawing/RectangleContainer.cs
new file mode 100644
index 000000000..92261ca7e
--- /dev/null
+++ b/Greenshot/Drawing/RectangleContainer.cs
@@ -0,0 +1,156 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing {
+ ///
+ /// Represents a rectangular shape on the Surface
+ ///
+ [Serializable]
+ public class RectangleContainer : DrawableContainer {
+
+ public RectangleContainer(Surface parent) : base(parent) {
+ Init();
+ }
+
+ ///
+ /// Do some logic to make sure all field are initiated correctly
+ ///
+ /// StreamingContext
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
+ AddField(GetType(), FieldType.SHADOW, true);
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR, Color.Red);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR, Color.Transparent);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ DrawRectangle(rect, graphics, rm, lineThickness, lineColor, fillColor, shadow);
+ }
+
+ ///
+ /// This method can also be used from other containers, if the right values are passed!
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DrawRectangle(Rectangle rect, Graphics graphics, RenderMode rm, int lineThickness, Color lineColor, Color fillColor, bool shadow) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+
+ bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
+ if (shadow && (lineVisible || Colors.IsVisible(fillColor))) {
+ //draw shadow first
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = lineVisible ? 1 : 0;
+ while (currentStep <= steps) {
+ using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
+ shadowPen.Width = lineVisible ? lineThickness : 1;
+ Rectangle shadowRect = GuiRectangle.GetGuiRectangle(
+ rect.Left + currentStep,
+ rect.Top + currentStep,
+ rect.Width,
+ rect.Height);
+ graphics.DrawRectangle(shadowPen, shadowRect);
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+
+
+ if (Colors.IsVisible(fillColor)) {
+ using (Brush brush = new SolidBrush(fillColor)) {
+ graphics.FillRectangle(brush, rect);
+ }
+ }
+
+ graphics.SmoothingMode = SmoothingMode.HighSpeed;
+ if (lineVisible) {
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ graphics.DrawRectangle(pen, rect);
+ }
+ }
+
+ }
+ public override bool ClickableAt(int x, int y) {
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+
+ return RectangleClickableAt(rect, lineThickness, fillColor, x, y);
+ }
+
+
+ public static bool RectangleClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) {
+
+ // If we clicked inside the rectangle and it's visible we are clickable at.
+ if (!Color.Transparent.Equals(fillColor)) {
+ if (rect.Contains(x,y)) {
+ return true;
+ }
+ }
+
+ // check the rest of the lines
+ if (lineThickness > 0) {
+ using (Pen pen = new Pen(Color.White, lineThickness)) {
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddRectangle(rect);
+ return path.IsOutlineVisible(x, y, pen);
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/Greenshot/Drawing/RoundedRectangle.cs b/Greenshot/Drawing/RoundedRectangle.cs
new file mode 100644
index 000000000..54553ac37
--- /dev/null
+++ b/Greenshot/Drawing/RoundedRectangle.cs
@@ -0,0 +1,135 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Drawing {
+ ///
+ /// TODO: currently this is only used in the capture form, we might move this code directly to there!
+ ///
+ public abstract class RoundedRectangle {
+ [Flags]
+ public enum RectangleCorners {
+ None = 0, TopLeft = 1, TopRight = 2,
+ BottomLeft = 4, BottomRight = 8,
+ All = TopLeft | TopRight | BottomLeft | BottomRight
+ }
+
+ public static GraphicsPath Create2(int x, int y, int width, int height, int radius) {
+ GraphicsPath gp = new GraphicsPath();
+ gp.AddLine(x + radius, y, x + width - radius * 2, y); // Line
+ gp.AddArc(x + width - radius * 2, y, radius * 2, radius * 2, 270, 90); // Corner
+ gp.AddLine(x + width, y + radius, x + width, y + height - radius * 2); // Line
+ gp.AddArc(x + width - radius * 2, y + height - radius * 2, radius * 2, radius * 2, 0, 90); // Corner
+ gp.AddLine(x + width - radius * 2, y + height, x + radius, y + height); // Line
+ gp.AddArc(x, y + height - radius * 2, radius * 2, radius * 2, 90, 90); // Corner
+ gp.AddLine(x, y + height - radius * 2, x, y + radius); // Line
+ gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner
+ gp.CloseFigure();
+
+ return gp;
+ }
+
+ public static GraphicsPath Create(int x, int y, int width, int height, int radius, RectangleCorners corners) {
+ int xw = x + width;
+ int yh = y + height;
+ int xwr = xw - radius;
+ int yhr = yh - radius;
+ int xr = x + radius;
+ int yr = y + radius;
+ int r2 = radius * 2;
+ int xwr2 = xw - r2;
+ int yhr2 = yh - r2;
+
+ GraphicsPath p = new GraphicsPath();
+ p.StartFigure();
+
+ //Top Left Corner
+ if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft) {
+ p.AddArc(x, y, r2, r2, 180, 90);
+ } else {
+ p.AddLine(x, yr, x, y);
+ p.AddLine(x, y, xr, y);
+ }
+
+ //Top Edge
+ p.AddLine(xr, y, xwr, y);
+
+ //Top Right Corner
+ if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight) {
+ p.AddArc(xwr2, y, r2, r2, 270, 90);
+ } else {
+ p.AddLine(xwr, y, xw, y);
+ p.AddLine(xw, y, xw, yr);
+ }
+
+ //Right Edge
+ p.AddLine(xw, yr, xw, yhr);
+
+ //Bottom Right Corner
+ if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight) {
+ p.AddArc(xwr2, yhr2, r2, r2, 0, 90);
+ } else {
+ p.AddLine(xw, yhr, xw, yh);
+ p.AddLine(xw, yh, xwr, yh);
+ }
+
+ //Bottom Edge
+ p.AddLine(xwr, yh, xr, yh);
+
+ //Bottom Left Corner
+ if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft) {
+ p.AddArc(x, yhr2, r2, r2, 90, 90);
+ } else {
+ p.AddLine(xr, yh, x, yh);
+ p.AddLine(x, yh, x, yhr);
+ }
+
+ //Left Edge
+ p.AddLine(x, yhr, x, yr);
+
+ p.CloseFigure();
+ return p;
+ }
+
+ public static GraphicsPath Create(Rectangle rect, int radius, RectangleCorners corners) {
+ return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, corners);
+ }
+
+ public static GraphicsPath Create(int x, int y, int width, int height, int radius) {
+ return Create(x, y, width, height, radius, RectangleCorners.All);
+ }
+
+ public static GraphicsPath Create(Rectangle rect, int radius) {
+ return Create(rect.X, rect.Y, rect.Width, rect.Height, radius);
+ }
+
+ public static GraphicsPath Create(int x, int y, int width, int height) {
+ return Create(x, y, width, height, 5);
+ }
+
+ public static GraphicsPath Create(Rectangle rect) {
+ return Create(rect.X, rect.Y, rect.Width, rect.Height);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/SpeechbubbleContainer.cs b/Greenshot/Drawing/SpeechbubbleContainer.cs
new file mode 100644
index 000000000..0cdfb91c1
--- /dev/null
+++ b/Greenshot/Drawing/SpeechbubbleContainer.cs
@@ -0,0 +1,341 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Runtime.Serialization;
+
+namespace Greenshot.Drawing
+{
+ ///
+ /// Description of SpeechbubbleContainer.
+ ///
+ [Serializable]
+ public class SpeechbubbleContainer : TextContainer {
+
+ private Point _initialGripperPoint;
+
+ #region TargetGripper serializing code
+ // Only used for serializing the TargetGripper location
+ private Point _storedTargetGripperLocation;
+
+ ///
+ /// Store the current location of the target gripper
+ ///
+ ///
+ [OnSerializing]
+ private void SetValuesOnSerializing(StreamingContext context) {
+ if (TargetAdorner != null) {
+ _storedTargetGripperLocation = TargetAdorner.Location;
+ }
+ }
+
+ ///
+ /// Restore the target gripper
+ ///
+ /// StreamingContext
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ InitAdorner(Color.Green, _storedTargetGripperLocation);
+ }
+ #endregion
+
+ public SpeechbubbleContainer(Surface parent)
+ : base(parent) {
+ }
+
+ ///
+ /// We set our own field values
+ ///
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Blue);
+ AddField(GetType(), FieldType.SHADOW, false);
+ AddField(GetType(), FieldType.FONT_ITALIC, false);
+ AddField(GetType(), FieldType.FONT_BOLD, true);
+ AddField(GetType(), FieldType.FILL_COLOR, Color.White);
+ AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
+ AddField(GetType(), FieldType.FONT_SIZE, 20f);
+ AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center);
+ AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center);
+ }
+
+ ///
+ /// Called from Surface (the _parent) when the drawing begins (mouse-down)
+ ///
+ /// true if the surface doesn't need to handle the event
+ public override bool HandleMouseDown(int mouseX, int mouseY) {
+ if (TargetAdorner == null) {
+ _initialGripperPoint = new Point(mouseX, mouseY);
+ InitAdorner(Color.Green, new Point(mouseX, mouseY));
+ }
+ return base.HandleMouseDown(mouseX, mouseY);
+ }
+
+ ///
+ /// Overriding the HandleMouseMove will help us to make sure the tail is always visible.
+ /// Should fix BUG-1682
+ ///
+ ///
+ ///
+ /// base.HandleMouseMove
+ public override bool HandleMouseMove(int x, int y) {
+ bool returnValue = base.HandleMouseMove(x, y);
+
+ bool leftAligned = _boundsAfterResize.Right - _boundsAfterResize.Left >= 0;
+ bool topAligned = _boundsAfterResize.Bottom - _boundsAfterResize.Top >= 0;
+
+ int xOffset = leftAligned ? -20 : 20;
+ int yOffset = topAligned ? -20 : 20;
+
+ Point newGripperLocation = _initialGripperPoint;
+ newGripperLocation.Offset(xOffset, yOffset);
+
+ if (TargetAdorner.Location != newGripperLocation) {
+ Invalidate();
+ TargetAdorner.Location = newGripperLocation;
+ Invalidate();
+ }
+ return returnValue;
+ }
+
+ ///
+ /// The DrawingBound should be so close as possible to the shape, so we don't invalidate to much.
+ ///
+ public override Rectangle DrawingBounds {
+ get {
+ if (Status != EditStatus.UNDRAWN) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ int inflateValue = lineThickness + 2 + (shadow ? 6 : 0);
+ using (GraphicsPath tailPath = CreateTail()) {
+ return Rectangle.Inflate(Rectangle.Union(Rectangle.Round(tailPath.GetBounds(new Matrix(), pen)), GuiRectangle.GetGuiRectangle(Left, Top, Width, Height)), inflateValue, inflateValue);
+ }
+ }
+ }
+ return Rectangle.Empty;
+ }
+ }
+
+ ///
+ /// Helper method to create the bubble GraphicsPath, so we can also calculate the bounds
+ ///
+ ///
+ ///
+ private GraphicsPath CreateBubble(int lineThickness) {
+ GraphicsPath bubble = new GraphicsPath();
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ Rectangle bubbleRect = GuiRectangle.GetGuiRectangle(0, 0, rect.Width, rect.Height);
+ // adapt corner radius to small rectangle dimensions
+ int smallerSideLength = Math.Min(bubbleRect.Width, bubbleRect.Height);
+ int cornerRadius = Math.Min(30, smallerSideLength / 2 - lineThickness);
+ if (cornerRadius > 0) {
+ bubble.AddArc(bubbleRect.X, bubbleRect.Y, cornerRadius, cornerRadius, 180, 90);
+ bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y, cornerRadius, cornerRadius, 270, 90);
+ bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
+ bubble.AddArc(bubbleRect.X, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
+ } else {
+ bubble.AddRectangle(bubbleRect);
+ }
+ bubble.CloseAllFigures();
+ using (Matrix bubbleMatrix = new Matrix()) {
+ bubbleMatrix.Translate(rect.Left, rect.Top);
+ bubble.Transform(bubbleMatrix);
+ }
+ return bubble;
+ }
+
+ ///
+ /// Helper method to create the tail of the bubble, so we can also calculate the bounds
+ ///
+ ///
+ private GraphicsPath CreateTail() {
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetAdorner.Location.X, TargetAdorner.Location.Y);
+ int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20;
+
+ // This should fix a problem with the tail being to wide
+ tailWidth = Math.Min(Math.Abs(rect.Width) / 2, tailWidth);
+ tailWidth = Math.Min(Math.Abs(rect.Height) / 2, tailWidth);
+
+ GraphicsPath tail = new GraphicsPath();
+ tail.AddLine(-tailWidth, 0, tailWidth, 0);
+ tail.AddLine(tailWidth, 0, 0, -tailLength);
+ tail.CloseFigure();
+
+ int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetAdorner.Location.X, TargetAdorner.Location.Y);
+
+ using (Matrix tailMatrix = new Matrix()) {
+ tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
+ tailMatrix.Rotate(tailAngle);
+ tail.Transform(tailMatrix);
+ }
+
+ return tail;
+ }
+
+ ///
+ /// This is to draw the actual container
+ ///
+ ///
+ ///
+ public override void Draw(Graphics graphics, RenderMode renderMode) {
+ if (TargetAdorner == null) {
+ return;
+ }
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
+
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+
+ bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ if (Selected && renderMode == RenderMode.EDIT) {
+ DrawSelectionBorder(graphics, rect);
+ }
+
+ GraphicsPath bubble = CreateBubble(lineThickness);
+
+ GraphicsPath tail = CreateTail();
+
+ //draw shadow first
+ if (shadow && (lineVisible || Colors.IsVisible(fillColor))) {
+ const int basealpha = 100;
+ int alpha = basealpha;
+ const int steps = 5;
+ int currentStep = lineVisible ? 1 : 0;
+ using (Matrix shadowMatrix = new Matrix())
+ using (GraphicsPath bubbleClone = (GraphicsPath)bubble.Clone())
+ using (GraphicsPath tailClone = (GraphicsPath)tail.Clone()) {
+ shadowMatrix.Translate(1, 1);
+ while (currentStep <= steps) {
+ using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
+ shadowPen.Width = lineVisible ? lineThickness : 1;
+ tailClone.Transform(shadowMatrix);
+ graphics.DrawPath(shadowPen, tailClone);
+ bubbleClone.Transform(shadowMatrix);
+ graphics.DrawPath(shadowPen, bubbleClone);
+ }
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+
+ GraphicsState state = graphics.Save();
+ // draw the tail border where the bubble is not visible
+ using (Region clipRegion = new Region(bubble)) {
+ graphics.SetClip(clipRegion, CombineMode.Exclude);
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ graphics.DrawPath(pen, tail);
+ }
+ }
+ graphics.Restore(state);
+
+ if (Colors.IsVisible(fillColor)) {
+ //draw the bubbleshape
+ state = graphics.Save();
+ using (Brush brush = new SolidBrush(fillColor)) {
+ graphics.FillPath(brush, bubble);
+ }
+ graphics.Restore(state);
+ }
+
+ if (lineVisible) {
+ //draw the bubble border
+ state = graphics.Save();
+ // Draw bubble where the Tail is not visible.
+ using (Region clipRegion = new Region(tail)) {
+ graphics.SetClip(clipRegion, CombineMode.Exclude);
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ //pen.EndCap = pen.StartCap = LineCap.Round;
+ graphics.DrawPath(pen, bubble);
+ }
+ }
+ graphics.Restore(state);
+ }
+
+ if (Colors.IsVisible(fillColor)) {
+ // Draw the tail border
+ state = graphics.Save();
+ using (Brush brush = new SolidBrush(fillColor)) {
+ graphics.FillPath(brush, tail);
+ }
+ graphics.Restore(state);
+ }
+
+ // cleanup the paths
+ bubble.Dispose();
+ tail.Dispose();
+
+ // Draw the text
+ DrawText(graphics, rect, lineThickness, lineColor, shadow, StringFormat, Text, Font);
+ }
+
+ public override bool Contains(int x, int y) {
+ if (base.Contains(x, y)) {
+ return true;
+ }
+ Point clickedPoint = new Point(x, y);
+ if (Status != EditStatus.UNDRAWN) {
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ using (Pen pen = new Pen(lineColor, lineThickness)) {
+ using (GraphicsPath bubblePath = CreateBubble(lineThickness)) {
+ bubblePath.Widen(pen);
+ if (bubblePath.IsVisible(clickedPoint)) {
+ return true;
+ }
+ }
+ using (GraphicsPath tailPath = CreateTail()) {
+ tailPath.Widen(pen);
+ if (tailPath.IsVisible(clickedPoint)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public override bool ClickableAt(int x, int y) {
+ return Contains(x,y);
+ }
+ }
+}
diff --git a/Greenshot/Drawing/StepLabelContainer.cs b/Greenshot/Drawing/StepLabelContainer.cs
new file mode 100644
index 000000000..5994bf617
--- /dev/null
+++ b/Greenshot/Drawing/StepLabelContainer.cs
@@ -0,0 +1,231 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Plugin.Drawing;
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Runtime.Serialization;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Drawing {
+ ///
+ /// This is an enumerated label, every single StepLabelContainer shows the number of the order it was created.
+ /// To make sure that deleting recalculates, we check the location before every draw.
+ ///
+ [Serializable]
+ public sealed class StepLabelContainer : DrawableContainer {
+ [NonSerialized]
+ private StringFormat _stringFormat = new StringFormat();
+
+ private readonly bool _drawAsRectangle = false;
+
+ private float fontSize = 16;
+
+ public StepLabelContainer(Surface parent) : base(parent) {
+ parent.AddStepLabel(this);
+ InitContent();
+ Init();
+ }
+
+ private void Init()
+ {
+ CreateDefaultAdorners();
+ }
+
+ #region Number serializing
+ // Used to store the number of this label, so when deserializing it can be placed back to the StepLabels list in the right location
+ private int _number;
+ // Used to store the counter start of the Surface, as the surface is NOT stored.
+ private int _counterStart = 1;
+ public int Number {
+ get {
+ return _number;
+ }
+ set {
+ _number = value;
+ }
+ }
+
+ ///
+ /// Retrieve the counter before serializing
+ ///
+ ///
+ [OnSerializing]
+ private void SetValuesOnSerializing(StreamingContext context) {
+ if (Parent != null) {
+ Number = ((Surface)Parent).CountStepLabels(this);
+ _counterStart = ((Surface) Parent).CounterStart;
+ }
+ }
+ #endregion
+
+ ///
+ /// Restore values that don't serialize
+ ///
+ ///
+ protected override void OnDeserialized(StreamingContext context)
+ {
+ Init();
+ _stringFormat = new StringFormat
+ {
+ Alignment = StringAlignment.Center,
+ LineAlignment = StringAlignment.Center
+ };
+
+ }
+
+ ///
+ /// Add the StepLabel to the parent
+ ///
+ ///
+ protected override void SwitchParent(Surface newParent) {
+ if (newParent == Parent)
+ {
+ return;
+ }
+ ((Surface) Parent)?.RemoveStepLabel(this);
+ base.SwitchParent(newParent);
+ if (newParent == null)
+ {
+ return;
+ }
+ // Make sure the counter start is restored (this unfortunately happens multiple times... -> hack)
+ newParent.CounterStart = _counterStart;
+ newParent.AddStepLabel(this);
+ }
+
+ public override Size DefaultSize => new Size(30, 30);
+
+ public override bool InitContent() {
+ _defaultEditMode = EditStatus.IDLE;
+ _stringFormat.Alignment = StringAlignment.Center;
+ _stringFormat.LineAlignment = StringAlignment.Center;
+
+ // Set defaults
+ Width = DefaultSize.Width;
+ Height = DefaultSize.Height;
+
+ return true;
+ }
+
+ ///
+ /// This makes it possible for the label to be placed exactly in the middle of the pointer.
+ ///
+ public override bool HandleMouseDown(int mouseX, int mouseY) {
+ return base.HandleMouseDown(mouseX - Width / 2, mouseY - Height / 2);
+ }
+
+ ///
+ /// We set our own field values
+ ///
+ protected override void InitializeFields() {
+ AddField(GetType(), FieldType.FILL_COLOR, Color.DarkRed);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.White);
+ AddField(GetType(), FieldType.FLAGS, FieldFlag.COUNTER);
+ }
+
+ ///
+ /// Make sure this element is no longer referenced from the surface
+ ///
+ protected override void Dispose(bool disposing) {
+ base.Dispose(disposing);
+ if (!disposing) {
+ return;
+ }
+ ((Surface) Parent)?.RemoveStepLabel(this);
+ if (_stringFormat == null)
+ {
+ return;
+ }
+ _stringFormat.Dispose();
+ _stringFormat = null;
+ }
+
+ public override bool HandleMouseMove(int x, int y) {
+ Invalidate();
+ Left = x - Width / 2;
+ Top = y - Height / 2;
+ Invalidate();
+ return true;
+ }
+
+ ///
+ /// Make sure the size of the font is scaled
+ ///
+ ///
+ public override void Transform(Matrix matrix) {
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ int widthBefore = rect.Width;
+ int heightBefore = rect.Height;
+
+ // Transform this container
+ base.Transform(matrix);
+ rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ int widthAfter = rect.Width;
+ int heightAfter = rect.Height;
+ float factor = ((float)widthAfter / widthBefore + (float)heightAfter / heightBefore) / 2;
+
+ fontSize *= factor;
+ }
+
+ ///
+ /// Override the parent, calculate the label number, than draw
+ ///
+ ///
+ ///
+ public override void Draw(Graphics graphics, RenderMode rm) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
+ string text = ((Surface)Parent).CountStepLabels(this).ToString();
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ if (_drawAsRectangle) {
+ RectangleContainer.DrawRectangle(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
+ } else {
+ EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
+ }
+ using (FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name)) {
+ using (Font font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel)) {
+ TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font);
+ }
+ }
+ }
+
+ public override bool ClickableAt(int x, int y) {
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ if (_drawAsRectangle) {
+ return RectangleContainer.RectangleClickableAt(rect, 0, fillColor, x, y);
+ } else {
+ return EllipseContainer.EllipseClickableAt(rect, 0, fillColor, x, y);
+ }
+ }
+ }
+}
diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs
new file mode 100644
index 000000000..e8b90026d
--- /dev/null
+++ b/Greenshot/Drawing/Surface.cs
@@ -0,0 +1,2112 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Configuration;
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.IniFile;
+using Greenshot.Memento;
+using Greenshot.Plugin;
+using Greenshot.Plugin.Drawing;
+using Greenshot.Plugin.Drawing.Adorners;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces.Drawing;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Windows.Forms;
+using GreenshotPlugin.Effects;
+
+namespace Greenshot.Drawing
+{
+ ///
+ /// Description of Surface.
+ ///
+ public sealed class Surface : Control, ISurface, INotifyPropertyChanged
+ {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(Surface));
+ public static int Count;
+ private static readonly CoreConfiguration conf = IniConfig.GetIniSection();
+
+ // Property to identify the Surface ID
+ private Guid _uniqueId = Guid.NewGuid();
+
+ ///
+ /// This value is used to start counting the step labels
+ ///
+ private int _counterStart = 1;
+
+ ///
+ /// The GUID of the surface
+ ///
+ public Guid ID
+ {
+ get
+ {
+ return _uniqueId;
+ }
+ set
+ {
+ _uniqueId = value;
+ }
+ }
+
+ ///
+ /// Event handlers (do not serialize!)
+ ///
+ [NonSerialized]
+ private PropertyChangedEventHandler _propertyChanged;
+ public event PropertyChangedEventHandler PropertyChanged
+ {
+ add
+ {
+ _propertyChanged += value;
+ }
+ remove
+ {
+ _propertyChanged -= value;
+ }
+ }
+
+ [NonSerialized]
+ private SurfaceElementEventHandler _movingElementChanged;
+ public event SurfaceElementEventHandler MovingElementChanged
+ {
+ add
+ {
+ _movingElementChanged += value;
+ }
+ remove
+ {
+ _movingElementChanged -= value;
+ }
+ }
+
+ [NonSerialized]
+ private SurfaceDrawingModeEventHandler _drawingModeChanged;
+ public event SurfaceDrawingModeEventHandler DrawingModeChanged
+ {
+ add
+ {
+ _drawingModeChanged += value;
+ }
+ remove
+ {
+ _drawingModeChanged -= value;
+ }
+ }
+ [NonSerialized]
+ private SurfaceSizeChangeEventHandler _surfaceSizeChanged;
+ public event SurfaceSizeChangeEventHandler SurfaceSizeChanged
+ {
+ add
+ {
+ _surfaceSizeChanged += value;
+ }
+ remove
+ {
+ _surfaceSizeChanged -= value;
+ }
+ }
+ [NonSerialized]
+ private SurfaceMessageEventHandler _surfaceMessage;
+ public event SurfaceMessageEventHandler SurfaceMessage
+ {
+ add
+ {
+ _surfaceMessage += value;
+ }
+ remove
+ {
+ _surfaceMessage -= value;
+ }
+ }
+
+ ///
+ /// inUndoRedo makes sure we don't undo/redo while in a undo/redo action
+ ///
+ [NonSerialized]
+ private bool _inUndoRedo;
+
+ ///
+ /// Make only one surfacemove cycle undoable, see SurfaceMouseMove
+ ///
+ [NonSerialized]
+ private bool _isSurfaceMoveMadeUndoable;
+
+ ///
+ /// Undo/Redo stacks, should not be serialized as the file would be way to big
+ ///
+ [NonSerialized]
+ private readonly Stack _undoStack = new Stack();
+ [NonSerialized]
+ private readonly Stack _redoStack = new Stack();
+
+ ///
+ /// Last save location, do not serialize!
+ ///
+ [NonSerialized]
+ private string _lastSaveFullPath;
+
+ ///
+ /// current drawing mode, do not serialize!
+ ///
+ [NonSerialized]
+ private DrawingModes _drawingMode = DrawingModes.None;
+
+ ///
+ /// the keyslocked flag helps with focus issues
+ ///
+ [NonSerialized]
+ private bool _keysLocked;
+
+ ///
+ /// Location of the mouse-down (it "starts" here), do not serialize
+ ///
+ [NonSerialized]
+ private Point _mouseStart = Point.Empty;
+
+ ///
+ /// are we in a mouse down, do not serialize
+ ///
+ [NonSerialized]
+ private bool _mouseDown;
+
+ ///
+ /// The selected element for the mouse down, do not serialize
+ ///
+ [NonSerialized]
+ private IDrawableContainer _mouseDownElement;
+
+ ///
+ /// all selected elements, do not serialize
+ ///
+ [NonSerialized]
+ private readonly IDrawableContainerList selectedElements;
+
+ ///
+ /// the element we are drawing with, do not serialize
+ ///
+ [NonSerialized]
+ private IDrawableContainer _drawingElement;
+
+ ///
+ /// the element we want to draw with (not yet drawn), do not serialize
+ ///
+ [NonSerialized]
+ private IDrawableContainer _undrawnElement;
+
+ ///
+ /// the cropcontainer, when cropping this is set, do not serialize
+ ///
+ [NonSerialized]
+ private IDrawableContainer _cropContainer;
+
+ ///
+ /// the brush which is used for transparent backgrounds, set by the editor, do not serialize
+ ///
+ [NonSerialized]
+ private Brush _transparencyBackgroundBrush;
+
+ ///
+ /// The buffer is only for drawing on it when using filters (to supply access)
+ /// This saves a lot of "create new bitmap" commands
+ /// Should not be serialized, as it's generated.
+ /// The actual bitmap is in the paintbox...
+ /// TODO: Check if this buffer is still needed!
+ ///
+ [NonSerialized]
+ private Bitmap _buffer;
+
+ ///
+ /// all stepLabels for the surface, needed with serialization
+ ///
+ private readonly List _stepLabels = new List();
+
+ public void AddStepLabel(StepLabelContainer stepLabel)
+ {
+ if (!_stepLabels.Contains(stepLabel))
+ {
+ _stepLabels.Add(stepLabel);
+ }
+ }
+
+ public void RemoveStepLabel(StepLabelContainer stepLabel)
+ {
+ _stepLabels.Remove(stepLabel);
+ }
+
+ ///
+ /// The start value of the counter objects
+ ///
+ public int CounterStart
+ {
+ get { return _counterStart; }
+ set
+ {
+ if (_counterStart == value)
+ {
+ return;
+ }
+
+ _counterStart = value;
+ Invalidate();
+ _propertyChanged?.Invoke(this, new PropertyChangedEventArgs("CounterStart"));
+ }
+ }
+
+ ///
+ /// Count all the VISIBLE steplabels in the surface, up to the supplied one
+ ///
+ /// can be null, if not the counting stops here
+ /// number of steplabels before the supplied container
+ public int CountStepLabels(IDrawableContainer stopAtContainer)
+ {
+ int number = CounterStart;
+ foreach (var possibleThis in _stepLabels)
+ {
+ if (possibleThis.Equals(stopAtContainer))
+ {
+ break;
+ }
+ if (IsOnSurface(possibleThis))
+ {
+ number++;
+ }
+ }
+ return number;
+ }
+
+ ///
+ /// all elements on the surface, needed with serialization
+ ///
+ private readonly IDrawableContainerList _elements;
+
+ ///
+ /// all elements on the surface, needed with serialization
+ ///
+ private FieldAggregator _fieldAggregator;
+
+ ///
+ /// the cursor container, needed with serialization as we need a direct acces to it.
+ ///
+ private IDrawableContainer _cursorContainer;
+
+ ///
+ /// the modified flag specifies if the surface has had modifications after the last export.
+ /// Initial state is modified, as "it's not saved"
+ /// After serialization this should actually be "false" (the surface came from a stream)
+ /// For now we just serialize it...
+ ///
+ private bool _modified = true;
+
+ ///
+ /// The image is the actual captured image, needed with serialization
+ ///
+ private Image _image;
+ public Image Image
+ {
+ get
+ {
+ return _image;
+ }
+ set
+ {
+ _image = value;
+ Size = _image.Size;
+ }
+ }
+
+ ///
+ /// The field aggregator is that which is used to have access to all the fields inside the currently selected elements.
+ /// e.g. used to decided if and which line thickness is shown when multiple elements are selected.
+ ///
+ public FieldAggregator FieldAggregator
+ {
+ get
+ {
+ return _fieldAggregator;
+ }
+ set
+ {
+ _fieldAggregator = value;
+ }
+ }
+
+ ///
+ /// The cursor container has it's own accessor so we can find and remove this (when needed)
+ ///
+ public IDrawableContainer CursorContainer => _cursorContainer;
+
+ ///
+ /// A simple getter to ask if this surface has a cursor
+ ///
+ public bool HasCursor => _cursorContainer != null;
+
+ ///
+ /// A simple helper method to remove the cursor from the surface
+ ///
+ public void RemoveCursor()
+ {
+ RemoveElement(_cursorContainer);
+ _cursorContainer = null;
+ }
+
+ ///
+ /// The brush which is used to draw the transparent background
+ ///
+ public Brush TransparencyBackgroundBrush
+ {
+ get
+ {
+ return _transparencyBackgroundBrush;
+ }
+ set
+ {
+ _transparencyBackgroundBrush = value;
+ }
+ }
+
+ ///
+ /// Are the keys on this surface locked?
+ ///
+ public bool KeysLocked
+ {
+ get
+ {
+ return _keysLocked;
+ }
+ set
+ {
+ _keysLocked = value;
+ }
+ }
+
+ ///
+ /// Is this surface modified? This is only true if the surface has not been exported.
+ ///
+ public bool Modified
+ {
+ get
+ {
+ return _modified;
+ }
+ set
+ {
+ _modified = value;
+ }
+ }
+
+ ///
+ /// The DrawingMode property specifies the mode for drawing, more or less the element type.
+ ///
+ public DrawingModes DrawingMode
+ {
+ get { return _drawingMode; }
+ set
+ {
+ _drawingMode = value;
+ if (_drawingModeChanged != null)
+ {
+ SurfaceDrawingModeEventArgs eventArgs = new SurfaceDrawingModeEventArgs
+ {
+ DrawingMode = _drawingMode
+ };
+ _drawingModeChanged.Invoke(this, eventArgs);
+ }
+ DeselectAllElements();
+ CreateUndrawnElement();
+ }
+ }
+
+ ///
+ /// Property for accessing the last save "full" path
+ ///
+ public string LastSaveFullPath
+ {
+ get
+ {
+ return _lastSaveFullPath;
+ }
+ set
+ {
+ _lastSaveFullPath = value;
+ }
+ }
+
+ ///
+ /// Property for accessing the URL to which the surface was recently uploaded
+ ///
+ public string UploadUrl
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Property for accessing the capture details
+ ///
+ public ICaptureDetails CaptureDetails { get; set; }
+
+ ///
+ /// Base Surface constructor
+ ///
+ public Surface()
+ {
+ _fieldAggregator = new FieldAggregator(this);
+ Count++;
+ _elements = new DrawableContainerList(_uniqueId);
+ selectedElements = new DrawableContainerList(_uniqueId);
+ LOG.Debug("Creating surface!");
+ MouseDown += SurfaceMouseDown;
+ MouseUp += SurfaceMouseUp;
+ MouseMove += SurfaceMouseMove;
+ MouseDoubleClick += SurfaceDoubleClick;
+ Paint += SurfacePaint;
+ AllowDrop = true;
+ DragDrop += OnDragDrop;
+ DragEnter += OnDragEnter;
+ // bind selected & elements to this, otherwise they can't inform of modifications
+ selectedElements.Parent = this;
+ _elements.Parent = this;
+ // Make sure we are visible
+ Visible = true;
+ TabStop = false;
+ // Enable double buffering
+ DoubleBuffered = true;
+ SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.ContainerControl | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true);
+ }
+
+ ///
+ /// Private method, the current image is disposed the new one will stay.
+ ///
+ /// The new image
+ /// true if the old image needs to be disposed, when using undo this should not be true!!
+ private void SetImage(Image newImage, bool dispose)
+ {
+ // Dispose
+ if (_image != null && dispose)
+ {
+ _image.Dispose();
+ }
+
+ // Set new values
+ Image = newImage;
+ Size = newImage.Size;
+
+ _modified = true;
+ }
+
+ ///
+ /// Surface constructor with an image
+ ///
+ ///
+ public Surface(Image newImage) : this()
+ {
+ LOG.DebugFormat("Got image with dimensions {0} and format {1}", newImage.Size, newImage.PixelFormat);
+ SetImage(newImage, true);
+ }
+
+ ///
+ /// Surface contructor with a capture
+ ///
+ ///
+ public Surface(ICapture capture) : this(capture.Image)
+ {
+ // check if cursor is captured, and visible
+ if (capture.Cursor != null && capture.CursorVisible)
+ {
+ Rectangle cursorRect = new Rectangle(capture.CursorLocation, capture.Cursor.Size);
+ Rectangle captureRect = new Rectangle(Point.Empty, capture.Image.Size);
+ // check if cursor is on the capture, otherwise we leave it out.
+ if (cursorRect.IntersectsWith(captureRect))
+ {
+ _cursorContainer = AddIconContainer(capture.Cursor, capture.CursorLocation.X, capture.CursorLocation.Y);
+ SelectElement(_cursorContainer);
+ }
+ }
+ // Make sure the image is NOT disposed, we took the reference directly into ourselves
+ ((Capture)capture).NullImage();
+
+ CaptureDetails = capture.CaptureDetails;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Count--;
+ LOG.Debug("Disposing surface!");
+ if (_buffer != null)
+ {
+ _buffer.Dispose();
+ _buffer = null;
+ }
+ if (_transparencyBackgroundBrush != null)
+ {
+ _transparencyBackgroundBrush.Dispose();
+ _transparencyBackgroundBrush = null;
+ }
+
+ // Cleanup undo/redo stacks
+ while (_undoStack != null && _undoStack.Count > 0)
+ {
+ _undoStack.Pop().Dispose();
+ }
+ while (_redoStack != null && _redoStack.Count > 0)
+ {
+ _redoStack.Pop().Dispose();
+ }
+ foreach (IDrawableContainer container in _elements)
+ {
+ container.Dispose();
+ }
+ if (_undrawnElement != null)
+ {
+ _undrawnElement.Dispose();
+ _undrawnElement = null;
+ }
+ if (_cropContainer != null)
+ {
+ _cropContainer.Dispose();
+ _cropContainer = null;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// Undo the last action
+ ///
+ public void Undo()
+ {
+ if (_undoStack.Count > 0)
+ {
+ _inUndoRedo = true;
+ IMemento top = _undoStack.Pop();
+ _redoStack.Push(top.Restore());
+ _inUndoRedo = false;
+ }
+ }
+
+ ///
+ /// Undo an undo (=redo)
+ ///
+ public void Redo()
+ {
+ if (_redoStack.Count > 0)
+ {
+ _inUndoRedo = true;
+ IMemento top = _redoStack.Pop();
+ _undoStack.Push(top.Restore());
+ _inUndoRedo = false;
+ }
+ }
+
+ ///
+ /// Returns if the surface can do a undo
+ ///
+ public bool CanUndo => _undoStack.Count > 0;
+
+ ///
+ /// Returns if the surface can do a redo
+ ///
+ public bool CanRedo => _redoStack.Count > 0;
+
+ ///
+ /// Get the language key for the undo action
+ ///
+ public LangKey UndoActionLanguageKey => LangKey.none;
+
+ ///
+ /// Get the language key for redo action
+ ///
+ public LangKey RedoActionLanguageKey => LangKey.none;
+
+ ///
+ /// Make an action undo-able
+ ///
+ /// The memento implementing the undo
+ /// Allow changes to be merged
+ public void MakeUndoable(IMemento memento, bool allowMerge)
+ {
+ if (_inUndoRedo)
+ {
+ throw new InvalidOperationException("Invoking do within an undo/redo action.");
+ }
+ if (memento != null)
+ {
+ bool allowPush = true;
+ if (_undoStack.Count > 0 && allowMerge)
+ {
+ // Check if merge is possible
+ allowPush = !_undoStack.Peek().Merge(memento);
+ }
+ if (allowPush)
+ {
+ // Clear the redo-stack and dispose
+ while (_redoStack.Count > 0)
+ {
+ _redoStack.Pop().Dispose();
+ }
+ _undoStack.Push(memento);
+ }
+ }
+ }
+
+ ///
+ /// This saves the elements of this surface to a stream.
+ /// Is used to save a template of the complete surface
+ ///
+ ///
+ ///
+ public long SaveElementsToStream(Stream streamWrite)
+ {
+ long bytesWritten = 0;
+ try
+ {
+ long lengtBefore = streamWrite.Length;
+ BinaryFormatter binaryWrite = new BinaryFormatter();
+ binaryWrite.Serialize(streamWrite, _elements);
+ bytesWritten = streamWrite.Length - lengtBefore;
+ }
+ catch (Exception e)
+ {
+ LOG.Error("Error serializing elements to stream.", e);
+ }
+ return bytesWritten;
+ }
+
+ ///
+ /// This loads elements from a stream, among others this is used to load a surface.
+ ///
+ ///
+ public void LoadElementsFromStream(Stream streamRead)
+ {
+ try
+ {
+ BinaryFormatter binaryRead = new BinaryFormatter();
+ IDrawableContainerList loadedElements = (IDrawableContainerList)binaryRead.Deserialize(streamRead);
+ loadedElements.Parent = this;
+ // Make sure the steplabels are sorted accoring to their number
+ _stepLabels.Sort((p1, p2) => p1.Number.CompareTo(p2.Number));
+ DeselectAllElements();
+ AddElements(loadedElements);
+ SelectElements(loadedElements);
+ FieldAggregator.BindElements(loadedElements);
+ }
+ catch (Exception e)
+ {
+ LOG.Error("Error serializing elements from stream.", e);
+ }
+ }
+
+ ///
+ /// This is called from the DrawingMode setter, which is not very correct...
+ /// But here an element is created which is not yet draw, thus "undrawnElement".
+ /// The element is than used while drawing on the surface.
+ ///
+ private void CreateUndrawnElement()
+ {
+ if (_undrawnElement != null)
+ {
+ FieldAggregator.UnbindElement(_undrawnElement);
+ }
+ switch (DrawingMode)
+ {
+ case DrawingModes.Rect:
+ _undrawnElement = new RectangleContainer(this);
+ break;
+ case DrawingModes.Ellipse:
+ _undrawnElement = new EllipseContainer(this);
+ break;
+ case DrawingModes.Text:
+ _undrawnElement = new TextContainer(this);
+ break;
+ case DrawingModes.SpeechBubble:
+ _undrawnElement = new SpeechbubbleContainer(this);
+ break;
+ case DrawingModes.StepLabel:
+ _undrawnElement = new StepLabelContainer(this);
+ break;
+ case DrawingModes.Line:
+ _undrawnElement = new LineContainer(this);
+ break;
+ case DrawingModes.Arrow:
+ _undrawnElement = new ArrowContainer(this);
+ break;
+ case DrawingModes.Highlight:
+ _undrawnElement = new HighlightContainer(this);
+ break;
+ case DrawingModes.Obfuscate:
+ _undrawnElement = new ObfuscateContainer(this);
+ break;
+ case DrawingModes.Crop:
+ _cropContainer = new CropContainer(this);
+ _undrawnElement = _cropContainer;
+ break;
+ case DrawingModes.Bitmap:
+ _undrawnElement = new ImageContainer(this);
+ break;
+ case DrawingModes.Path:
+ _undrawnElement = new FreehandContainer(this);
+ break;
+ case DrawingModes.None:
+ _undrawnElement = null;
+ break;
+ }
+ if (_undrawnElement != null)
+ {
+ FieldAggregator.BindElement(_undrawnElement);
+ }
+ }
+
+ #region Plugin interface implementations
+ public IImageContainer AddImageContainer(Image image, int x, int y)
+ {
+ ImageContainer bitmapContainer = new ImageContainer(this)
+ {
+ Image = image,
+ Left = x,
+ Top = y
+ };
+ AddElement(bitmapContainer);
+ return bitmapContainer;
+ }
+
+ public IImageContainer AddImageContainer(string filename, int x, int y)
+ {
+ ImageContainer bitmapContainer = new ImageContainer(this);
+ bitmapContainer.Load(filename);
+ bitmapContainer.Left = x;
+ bitmapContainer.Top = y;
+ AddElement(bitmapContainer);
+ return bitmapContainer;
+ }
+ public IIconContainer AddIconContainer(Icon icon, int x, int y)
+ {
+ IconContainer iconContainer = new IconContainer(this)
+ {
+ Icon = icon,
+ Left = x,
+ Top = y
+ };
+ AddElement(iconContainer);
+ return iconContainer;
+ }
+ public IIconContainer AddIconContainer(string filename, int x, int y)
+ {
+ IconContainer iconContainer = new IconContainer(this);
+ iconContainer.Load(filename);
+ iconContainer.Left = x;
+ iconContainer.Top = y;
+ AddElement(iconContainer);
+ return iconContainer;
+ }
+ public ICursorContainer AddCursorContainer(Cursor cursor, int x, int y)
+ {
+ CursorContainer cursorContainer = new CursorContainer(this)
+ {
+ Cursor = cursor,
+ Left = x,
+ Top = y
+ };
+ AddElement(cursorContainer);
+ return cursorContainer;
+ }
+ public ICursorContainer AddCursorContainer(string filename, int x, int y)
+ {
+ CursorContainer cursorContainer = new CursorContainer(this);
+ cursorContainer.Load(filename);
+ cursorContainer.Left = x;
+ cursorContainer.Top = y;
+ AddElement(cursorContainer);
+ return cursorContainer;
+ }
+
+ public ITextContainer AddTextContainer(string text, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, FontFamily family, float size, bool italic, bool bold, bool shadow, int borderSize, Color color, Color fillColor)
+ {
+ TextContainer textContainer = new TextContainer(this) {Text = text};
+ textContainer.SetFieldValue(FieldType.FONT_FAMILY, family.Name);
+ textContainer.SetFieldValue(FieldType.FONT_BOLD, bold);
+ textContainer.SetFieldValue(FieldType.FONT_ITALIC, italic);
+ textContainer.SetFieldValue(FieldType.FONT_SIZE, size);
+ textContainer.SetFieldValue(FieldType.FILL_COLOR, fillColor);
+ textContainer.SetFieldValue(FieldType.LINE_COLOR, color);
+ textContainer.SetFieldValue(FieldType.LINE_THICKNESS, borderSize);
+ textContainer.SetFieldValue(FieldType.SHADOW, shadow);
+ // Make sure the Text fits
+ textContainer.FitToText();
+ // Align to Surface
+ textContainer.AlignToParent(horizontalAlignment, verticalAlignment);
+
+ //AggregatedProperties.UpdateElement(textContainer);
+ AddElement(textContainer);
+ return textContainer;
+ }
+ #endregion
+
+ #region DragDrop
+
+ private void OnDragEnter(object sender, DragEventArgs e)
+ {
+ if (LOG.IsDebugEnabled)
+ {
+ LOG.Debug("DragEnter got following formats: ");
+ foreach (string format in ClipboardHelper.GetFormats(e.Data))
+ {
+ LOG.Debug(format);
+ }
+ }
+ if ((e.AllowedEffect & DragDropEffects.Copy) != DragDropEffects.Copy)
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ else
+ {
+ if (ClipboardHelper.ContainsImage(e.Data) || ClipboardHelper.ContainsFormat(e.Data, "DragImageBits"))
+ {
+ e.Effect = DragDropEffects.Copy;
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ }
+ }
+
+ ///
+ /// Handle the drag/drop
+ ///
+ ///
+ ///
+ private void OnDragDrop(object sender, DragEventArgs e)
+ {
+ Point mouse = PointToClient(new Point(e.X, e.Y));
+ if (e.Data.GetDataPresent("Text"))
+ {
+ string possibleUrl = ClipboardHelper.GetText(e.Data);
+ // Test if it's an url and try to download the image so we have it in the original form
+ if (possibleUrl != null && possibleUrl.StartsWith("http"))
+ {
+ using (Image image = NetworkHelper.DownloadImage(possibleUrl))
+ {
+ if (image != null)
+ {
+ AddImageContainer(image, mouse.X, mouse.Y);
+ return;
+ }
+ }
+ }
+ }
+
+ foreach (Image image in ClipboardHelper.GetImages(e.Data))
+ {
+ AddImageContainer(image, mouse.X, mouse.Y);
+ mouse.Offset(10, 10);
+ image.Dispose();
+ }
+ }
+
+ #endregion
+
+ ///
+ /// Auto crop the image
+ ///
+ /// true if cropped
+ public bool AutoCrop()
+ {
+ Rectangle cropRectangle;
+ using (Image tmpImage = GetImageForExport())
+ {
+ cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference);
+ }
+ if (!IsCropPossible(ref cropRectangle))
+ {
+ return false;
+ }
+ DeselectAllElements();
+ // Maybe a bit obscure, but the following line creates a drop container
+ // It's available as "undrawnElement"
+ DrawingMode = DrawingModes.Crop;
+ _undrawnElement.Left = cropRectangle.X;
+ _undrawnElement.Top = cropRectangle.Y;
+ _undrawnElement.Width = cropRectangle.Width;
+ _undrawnElement.Height = cropRectangle.Height;
+ _undrawnElement.Status = EditStatus.UNDRAWN;
+ AddElement(_undrawnElement);
+ SelectElement(_undrawnElement);
+ _drawingElement = null;
+ _undrawnElement = null;
+ return true;
+ }
+
+ ///
+ /// A simple clear
+ ///
+ /// The color for the background
+ public void Clear(Color newColor)
+ {
+ //create a blank bitmap the same size as original
+ Bitmap newBitmap = ImageHelper.CreateEmptyLike(Image, Color.Empty);
+ if (newBitmap != null)
+ {
+ // Make undoable
+ MakeUndoable(new SurfaceBackgroundChangeMemento(this, null), false);
+ SetImage(newBitmap, false);
+ Invalidate();
+ }
+ }
+
+ ///
+ /// Apply a bitmap effect to the surface
+ ///
+ ///
+ public void ApplyBitmapEffect(IEffect effect)
+ {
+ BackgroundForm backgroundForm = new BackgroundForm("Effect", "Please wait");
+ backgroundForm.Show();
+ Application.DoEvents();
+ try
+ {
+ Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
+ Matrix matrix = new Matrix();
+ Image newImage = ImageHelper.ApplyEffect(Image, effect, matrix);
+ if (newImage != null)
+ {
+ // Make sure the elements move according to the offset the effect made the bitmap move
+ _elements.Transform(matrix);
+ // Make undoable
+ MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
+ SetImage(newImage, false);
+ Invalidate();
+ if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size)))
+ {
+ _surfaceSizeChanged(this, null);
+ }
+ }
+ else
+ {
+ // clean up matrix, as it hasn't been used in the undo stack.
+ matrix.Dispose();
+ }
+ }
+ finally
+ {
+ // Always close the background form
+ backgroundForm.CloseDialog();
+ }
+ }
+
+ ///
+ /// check if a crop is possible
+ ///
+ ///
+ /// true if this is possible
+ public bool IsCropPossible(ref Rectangle cropRectangle)
+ {
+ cropRectangle = GuiRectangle.GetGuiRectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, cropRectangle.Height);
+ if (cropRectangle.Left < 0)
+ {
+ cropRectangle = new Rectangle(0, cropRectangle.Top, cropRectangle.Width + cropRectangle.Left, cropRectangle.Height);
+ }
+ if (cropRectangle.Top < 0)
+ {
+ cropRectangle = new Rectangle(cropRectangle.Left, 0, cropRectangle.Width, cropRectangle.Height + cropRectangle.Top);
+ }
+ if (cropRectangle.Left + cropRectangle.Width > Width)
+ {
+ cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, Width - cropRectangle.Left, cropRectangle.Height);
+ }
+ if (cropRectangle.Top + cropRectangle.Height > Height)
+ {
+ cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, Height - cropRectangle.Top);
+ }
+ if (cropRectangle.Height > 0 && cropRectangle.Width > 0)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Use to send any registered SurfaceMessageEventHandler a message, e.g. used for the notification area
+ ///
+ /// Who send
+ /// Type of message
+ /// Message itself
+ public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message)
+ {
+ if (_surfaceMessage != null)
+ {
+ var eventArgs = new SurfaceMessageEventArgs
+ {
+ Message = message,
+ MessageType = messageType,
+ Surface = this
+ };
+ _surfaceMessage(source, eventArgs);
+ }
+ }
+
+ ///
+ /// Crop the surface
+ ///
+ ///
+ ///
+ public bool ApplyCrop(Rectangle cropRectangle)
+ {
+ if (IsCropPossible(ref cropRectangle))
+ {
+ Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
+ Bitmap tmpImage;
+ // Make sure we have information, this this fails
+ try
+ {
+ tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare);
+ }
+ catch (Exception ex)
+ {
+ ex.Data.Add("CropRectangle", cropRectangle);
+ ex.Data.Add("Width", Image.Width);
+ ex.Data.Add("Height", Image.Height);
+ ex.Data.Add("Pixelformat", Image.PixelFormat);
+ throw;
+ }
+
+ Matrix matrix = new Matrix();
+ matrix.Translate(-cropRectangle.Left, -cropRectangle.Top, MatrixOrder.Append);
+ // Make undoable
+ MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
+
+ // Do not dispose otherwise we can't undo the image!
+ SetImage(tmpImage, false);
+ _elements.Transform(matrix);
+ if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size)))
+ {
+ _surfaceSizeChanged(this, null);
+ }
+ Invalidate();
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// The background here is the captured image.
+ /// This is called from the SurfaceBackgroundChangeMemento.
+ ///
+ ///
+ ///
+ public void UndoBackgroundChange(Image previous, Matrix matrix)
+ {
+ SetImage(previous, false);
+ if (matrix != null)
+ {
+ _elements.Transform(matrix);
+ }
+ _surfaceSizeChanged?.Invoke(this, null);
+ Invalidate();
+ }
+ ///
+ /// Check if an adorner was "hit", and change the cursor if so
+ ///
+ /// MouseEventArgs
+ /// IAdorner
+ private IAdorner FindActiveAdorner(MouseEventArgs mouseEventArgs)
+ {
+ foreach (IDrawableContainer drawableContainer in selectedElements)
+ {
+ foreach (IAdorner adorner in drawableContainer.Adorners)
+ {
+
+ if (adorner.IsActive || adorner.HitTest(mouseEventArgs.Location))
+ {
+ if (adorner.Cursor != null)
+ {
+ Cursor = adorner.Cursor;
+ }
+ return adorner;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// This event handler is called when someone presses the mouse on a surface.
+ ///
+ ///
+ ///
+ private void SurfaceMouseDown(object sender, MouseEventArgs e)
+ {
+
+ // Handle Adorners
+ var adorner = FindActiveAdorner(e);
+ if (adorner != null)
+ {
+ adorner.MouseDown(sender, e);
+ return;
+ }
+
+ _mouseStart = e.Location;
+
+ // check contextmenu
+ if (e.Button == MouseButtons.Right)
+ {
+ IDrawableContainerList selectedList = null;
+ if (selectedElements != null && selectedElements.Count > 0)
+ {
+ selectedList = selectedElements;
+ }
+ else
+ {
+ // Single element
+ IDrawableContainer rightClickedContainer = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y);
+ if (rightClickedContainer != null)
+ {
+ selectedList = new DrawableContainerList(ID) {rightClickedContainer};
+ }
+ }
+ if (selectedList != null && selectedList.Count > 0)
+ {
+ selectedList.ShowContextMenu(e, this);
+ }
+ return;
+ }
+
+ _mouseDown = true;
+ _isSurfaceMoveMadeUndoable = false;
+
+ if (_cropContainer != null && ((_undrawnElement == null) || (_undrawnElement != null && DrawingMode != DrawingModes.Crop)))
+ {
+ RemoveElement(_cropContainer, false);
+ _cropContainer = null;
+ _drawingElement = null;
+ }
+
+ if (_drawingElement == null && DrawingMode != DrawingModes.None)
+ {
+ if (_undrawnElement == null)
+ {
+ DeselectAllElements();
+ if (_undrawnElement == null)
+ {
+ CreateUndrawnElement();
+ }
+ }
+ _drawingElement = _undrawnElement;
+ // if a new element has been drawn, set location and register it
+ if (_drawingElement != null)
+ {
+ if (_undrawnElement != null)
+ {
+ _drawingElement.Status = _undrawnElement.DefaultEditMode;
+ }
+ if (!_drawingElement.HandleMouseDown(_mouseStart.X, _mouseStart.Y))
+ {
+ _drawingElement.Left = _mouseStart.X;
+ _drawingElement.Top = _mouseStart.Y;
+ }
+ AddElement(_drawingElement);
+ _drawingElement.Selected = true;
+ }
+ _undrawnElement = null;
+ }
+ else
+ {
+ // check whether an existing element was clicked
+ // we save mouse down element separately from selectedElements (checked on mouse up),
+ // since it could be moved around before it is actually selected
+ _mouseDownElement = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y);
+
+ if (_mouseDownElement != null)
+ {
+ _mouseDownElement.Status = EditStatus.MOVING;
+ }
+ }
+ }
+
+ ///
+ /// This event handle is called when the mouse button is unpressed
+ ///
+ ///
+ ///
+ private void SurfaceMouseUp(object sender, MouseEventArgs e)
+ {
+
+ // Handle Adorners
+ var adorner = FindActiveAdorner(e);
+ if (adorner != null)
+ {
+ adorner.MouseUp(sender, e);
+ return;
+ }
+
+ Point currentMouse = new Point(e.X, e.Y);
+
+ _elements.Status = EditStatus.IDLE;
+ if (_mouseDownElement != null)
+ {
+ _mouseDownElement.Status = EditStatus.IDLE;
+ }
+ _mouseDown = false;
+ _mouseDownElement = null;
+ if (DrawingMode == DrawingModes.None)
+ {
+ // check whether an existing element was clicked
+ IDrawableContainer element = _elements.ClickableElementAt(currentMouse.X, currentMouse.Y);
+ bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift;
+ if (element != null)
+ {
+ element.Invalidate();
+ bool alreadySelected = selectedElements.Contains(element);
+ if (shiftModifier)
+ {
+ if (alreadySelected)
+ {
+ DeselectElement(element);
+ }
+ else
+ {
+ SelectElement(element);
+ }
+ }
+ else
+ {
+ if (!alreadySelected)
+ {
+ DeselectAllElements();
+ SelectElement(element);
+ }
+ }
+ }
+ else if (!shiftModifier)
+ {
+ DeselectAllElements();
+ }
+ }
+
+ if (selectedElements.Count > 0)
+ {
+ selectedElements.Invalidate();
+ selectedElements.Selected = true;
+ }
+
+ if (_drawingElement != null)
+ {
+ if (!_drawingElement.InitContent())
+ {
+ _elements.Remove(_drawingElement);
+ _drawingElement.Invalidate();
+ }
+ else
+ {
+ _drawingElement.HandleMouseUp(currentMouse.X, currentMouse.Y);
+ _drawingElement.Invalidate();
+ if (Math.Abs(_drawingElement.Width) < 5 && Math.Abs(_drawingElement.Height) < 5)
+ {
+ _drawingElement.Width = 25;
+ _drawingElement.Height = 25;
+ }
+ SelectElement(_drawingElement);
+ _drawingElement.Selected = true;
+ }
+ _drawingElement = null;
+ }
+ }
+
+ ///
+ /// This event handler is called when the mouse moves over the surface
+ ///
+ ///
+ ///
+ private void SurfaceMouseMove(object sender, MouseEventArgs e)
+ {
+ // Handle Adorners
+ var adorner = FindActiveAdorner(e);
+ if (adorner != null)
+ {
+ adorner.MouseMove(sender, e);
+ return;
+ }
+
+ Point currentMouse = e.Location;
+
+ Cursor = DrawingMode != DrawingModes.None ? Cursors.Cross : Cursors.Default;
+
+ if (_mouseDown)
+ {
+ if (_mouseDownElement != null)
+ { // an element is currently dragged
+ _mouseDownElement.Invalidate();
+ selectedElements.Invalidate();
+ // Move the element
+ if (_mouseDownElement.Selected)
+ {
+ if (!_isSurfaceMoveMadeUndoable)
+ {
+ // Only allow one undoable per mouse-down/move/up "cycle"
+ _isSurfaceMoveMadeUndoable = true;
+ selectedElements.MakeBoundsChangeUndoable(false);
+ }
+ // dragged element has been selected before -> move all
+ selectedElements.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
+ }
+ else
+ {
+ if (!_isSurfaceMoveMadeUndoable)
+ {
+ // Only allow one undoable per mouse-down/move/up "cycle"
+ _isSurfaceMoveMadeUndoable = true;
+ _mouseDownElement.MakeBoundsChangeUndoable(false);
+ }
+ // dragged element is not among selected elements -> just move dragged one
+ _mouseDownElement.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
+ }
+ _mouseStart = currentMouse;
+ _mouseDownElement.Invalidate();
+ _modified = true;
+ }
+ else if (_drawingElement != null)
+ {
+ _drawingElement.HandleMouseMove(currentMouse.X, currentMouse.Y);
+ _modified = true;
+ }
+ }
+ }
+
+ ///
+ /// This event handler is called when the surface is double clicked.
+ ///
+ ///
+ ///
+ private void SurfaceDoubleClick(object sender, MouseEventArgs e)
+ {
+ selectedElements.OnDoubleClick();
+ selectedElements.Invalidate();
+ }
+
+ ///
+ /// Privately used to get the rendered image with all the elements on it.
+ ///
+ ///
+ ///
+ private Image GetImage(RenderMode renderMode)
+ {
+ // Generate a copy of the original image with a dpi equal to the default...
+ Bitmap clone = ImageHelper.Clone(_image, PixelFormat.DontCare);
+ // otherwise we would have a problem drawing the image to the surface... :(
+ using (Graphics graphics = Graphics.FromImage(clone))
+ {
+ // Do not set the following, the containers need to decide themselves
+ //graphics.SmoothingMode = SmoothingMode.HighQuality;
+ //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ //graphics.CompositingQuality = CompositingQuality.HighQuality;
+ //graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ _elements.Draw(graphics, clone, renderMode, new Rectangle(Point.Empty, clone.Size));
+ }
+ return clone;
+ }
+
+ ///
+ /// This returns the image "result" of this surface, with all the elements rendered on it.
+ ///
+ ///
+ public Image GetImageForExport()
+ {
+ return GetImage(RenderMode.EXPORT);
+ }
+
+ ///
+ /// This is the event handler for the Paint Event, try to draw as little as possible!
+ ///
+ ///
+ /// PaintEventArgs
+ private void SurfacePaint(object sender, PaintEventArgs paintEventArgs)
+ {
+ Graphics targetGraphics = paintEventArgs.Graphics;
+ Rectangle clipRectangle = paintEventArgs.ClipRectangle;
+ if (Rectangle.Empty.Equals(clipRectangle))
+ {
+ LOG.Debug("Empty cliprectangle??");
+ return;
+ }
+
+ if (_elements.HasIntersectingFilters(clipRectangle))
+ {
+ if (_buffer != null)
+ {
+ if (_buffer.Width != Image.Width || _buffer.Height != Image.Height || _buffer.PixelFormat != Image.PixelFormat)
+ {
+ _buffer.Dispose();
+ _buffer = null;
+ }
+ }
+ if (_buffer == null)
+ {
+ _buffer = ImageHelper.CreateEmpty(Image.Width, Image.Height, Image.PixelFormat, Color.Empty, Image.HorizontalResolution, Image.VerticalResolution);
+ LOG.DebugFormat("Created buffer with size: {0}x{1}", Image.Width, Image.Height);
+ }
+ // Elements might need the bitmap, so we copy the part we need
+ using (Graphics graphics = Graphics.FromImage(_buffer))
+ {
+ // do not set the following, the containers need to decide this themselves!
+ //graphics.SmoothingMode = SmoothingMode.HighQuality;
+ //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ //graphics.CompositingQuality = CompositingQuality.HighQuality;
+ //graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ DrawBackground(graphics, clipRectangle);
+ graphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
+ graphics.SetClip(targetGraphics);
+ _elements.Draw(graphics, _buffer, RenderMode.EDIT, clipRectangle);
+ }
+ targetGraphics.DrawImage(_buffer, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
+ }
+ else
+ {
+ DrawBackground(targetGraphics, clipRectangle);
+ targetGraphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
+ _elements.Draw(targetGraphics, null, RenderMode.EDIT, clipRectangle);
+ }
+
+ // No clipping for the adorners
+ targetGraphics.ResetClip();
+ // Draw adorners last
+ foreach (var drawableContainer in selectedElements)
+ {
+ foreach (var adorner in drawableContainer.Adorners)
+ {
+ adorner.Paint(paintEventArgs);
+ }
+ }
+ }
+
+ private void DrawBackground(Graphics targetGraphics, Rectangle clipRectangle)
+ {
+ // check if we need to draw the checkerboard
+ if (Image.IsAlphaPixelFormat(Image.PixelFormat) && _transparencyBackgroundBrush != null)
+ {
+ targetGraphics.FillRectangle(_transparencyBackgroundBrush, clipRectangle);
+ }
+ else
+ {
+ targetGraphics.Clear(BackColor);
+ }
+ }
+
+ ///
+ /// Draw a checkboard when capturing with transparency
+ ///
+ /// PaintEventArgs
+ protected override void OnPaintBackground(PaintEventArgs e)
+ {
+ }
+
+ ///
+ /// Add a new element to the surface
+ ///
+ /// the new element
+ /// true if the adding should be undoable
+ /// true if invalidate needs to be called
+ public void AddElement(IDrawableContainer element, bool makeUndoable = true, bool invalidate = true)
+ {
+ _elements.Add(element);
+ DrawableContainer container = element as DrawableContainer;
+ if (container != null)
+ {
+ container.FieldChanged += element_FieldChanged;
+ }
+ element.Parent = this;
+ if (element.Status == EditStatus.UNDRAWN)
+ {
+ element.Status = EditStatus.IDLE;
+ }
+ if (element.Selected)
+ {
+ // Use false, as the element is invalidated when invalidate == true anyway
+ SelectElement(element, false);
+ }
+ if (invalidate)
+ {
+ element.Invalidate();
+ }
+ if (makeUndoable)
+ {
+ MakeUndoable(new AddElementMemento(this, element), false);
+ }
+ _modified = true;
+ }
+
+ ///
+ /// Remove the list of elements
+ ///
+ /// IDrawableContainerList
+ /// flag specifying if the remove needs to be undoable
+ public void RemoveElements(IDrawableContainerList elementsToRemove, bool makeUndoable = true)
+ {
+ // fix potential issues with iterating a changing list
+ DrawableContainerList cloned = new DrawableContainerList();
+ cloned.AddRange(elementsToRemove);
+ if (makeUndoable)
+ {
+ MakeUndoable(new DeleteElementsMemento(this, cloned), false);
+ }
+ SuspendLayout();
+ foreach (var drawableContainer in cloned)
+ {
+ RemoveElement(drawableContainer, false, false, false);
+ }
+ ResumeLayout();
+ Invalidate();
+ if (_movingElementChanged != null)
+ {
+ SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs {Elements = cloned};
+ _movingElementChanged(this, eventArgs);
+ }
+ }
+
+ ///
+ /// Remove an element of the elements list
+ ///
+ /// Element to remove
+ /// flag specifying if the remove needs to be undoable
+ /// flag specifying if an surface invalidate needs to be called
+ /// false to skip event generation
+ public void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable = true, bool invalidate = true, bool generateEvents = true)
+ {
+ DeselectElement(elementToRemove, generateEvents);
+ _elements.Remove(elementToRemove);
+ DrawableContainer element = elementToRemove as DrawableContainer;
+ if (element != null)
+ {
+ element.FieldChanged -= element_FieldChanged;
+ }
+ if (elementToRemove != null)
+ {
+ elementToRemove.Parent = null;
+ }
+ // Do not dispose, the memento should!! element.Dispose();
+ if (invalidate)
+ {
+ Invalidate();
+ }
+ if (makeUndoable)
+ {
+ MakeUndoable(new DeleteElementMemento(this, elementToRemove), false);
+ }
+ _modified = true;
+ }
+
+ ///
+ /// Add the supplied elements to the surface
+ ///
+ /// DrawableContainerList
+ /// true if the adding should be undoable
+ public void AddElements(IDrawableContainerList elementsToAdd, bool makeUndoable = true)
+ {
+ // fix potential issues with iterating a changing list
+ DrawableContainerList cloned = new DrawableContainerList();
+ cloned.AddRange(elementsToAdd);
+ if (makeUndoable)
+ {
+ MakeUndoable(new AddElementsMemento(this, cloned), false);
+ }
+ SuspendLayout();
+ foreach (var element in cloned)
+ {
+ element.Selected = true;
+ AddElement(element, false, false);
+ }
+ ResumeLayout();
+ Invalidate();
+ }
+
+ ///
+ /// Returns if this surface has selected elements
+ ///
+ ///
+ public bool HasSelectedElements => (selectedElements != null && selectedElements.Count > 0);
+
+ ///
+ /// Remove all the selected elements
+ ///
+ public void RemoveSelectedElements()
+ {
+ if (HasSelectedElements)
+ {
+ // As RemoveElement will remove the element from the selectedElements list we need to copy the element to another list.
+ RemoveElements(selectedElements);
+ if (_movingElementChanged != null)
+ {
+ SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs();
+ _movingElementChanged(this, eventArgs);
+ }
+ }
+ }
+
+ ///
+ /// Cut the selected elements from the surface to the clipboard
+ ///
+ public void CutSelectedElements()
+ {
+ if (HasSelectedElements)
+ {
+ ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
+ RemoveSelectedElements();
+ }
+ }
+
+ ///
+ /// Copy the selected elements to the clipboard
+ ///
+ public void CopySelectedElements()
+ {
+ if (HasSelectedElements)
+ {
+ ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
+ }
+ }
+
+ ///
+ /// This method is called to confirm/cancel "confirmable" elements, like the crop-container.
+ /// Called when pressing enter or using the "check" in the editor.
+ ///
+ ///
+ public void ConfirmSelectedConfirmableElements(bool confirm)
+ {
+ // create new collection so that we can iterate safely (selectedElements might change due with confirm/cancel)
+ List selectedDCs = new List(selectedElements);
+ foreach (IDrawableContainer dc in selectedDCs)
+ {
+ if (dc.Equals(_cropContainer))
+ {
+ DrawingMode = DrawingModes.None;
+ // No undo memento for the cropcontainer itself, only for the effect
+ RemoveElement(_cropContainer, false);
+ if (confirm)
+ {
+ ApplyCrop(_cropContainer.Bounds);
+ }
+ _cropContainer.Dispose();
+ _cropContainer = null;
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Paste all the elements that are on the clipboard
+ ///
+ public void PasteElementFromClipboard()
+ {
+ IDataObject clipboard = ClipboardHelper.GetDataObject();
+
+ var formats = ClipboardHelper.GetFormats(clipboard);
+ if (formats == null || formats.Count == 0)
+ {
+ return;
+ }
+ if (LOG.IsDebugEnabled)
+ {
+ LOG.Debug("List of clipboard formats available for pasting:");
+ foreach (string format in formats)
+ {
+ LOG.Debug("\tgot format: " + format);
+ }
+ }
+
+ if (formats.Contains(typeof(IDrawableContainerList).FullName))
+ {
+ IDrawableContainerList dcs = (IDrawableContainerList)ClipboardHelper.GetFromDataObject(clipboard, typeof(IDrawableContainerList));
+ if (dcs != null)
+ {
+ // Make element(s) only move 10,10 if the surface is the same
+ bool isSameSurface = (dcs.ParentID == _uniqueId);
+ dcs.Parent = this;
+ var moveOffset = isSameSurface ? new Point(10, 10) : Point.Empty;
+ // Here a fix for bug #1475, first calculate the bounds of the complete IDrawableContainerList
+ Rectangle drawableContainerListBounds = Rectangle.Empty;
+ foreach (var element in dcs)
+ {
+ drawableContainerListBounds = drawableContainerListBounds == Rectangle.Empty ? element.DrawingBounds : Rectangle.Union(drawableContainerListBounds, element.DrawingBounds);
+ }
+ // And find a location inside the target surface to paste to
+ bool containersCanFit = drawableContainerListBounds.Width < Bounds.Width && drawableContainerListBounds.Height < Bounds.Height;
+ if (!containersCanFit)
+ {
+ Point containersLocation = drawableContainerListBounds.Location;
+ containersLocation.Offset(moveOffset);
+ if (!Bounds.Contains(containersLocation))
+ {
+ // Easy fix for same surface
+ moveOffset = isSameSurface ? new Point(-10, -10) : new Point(-drawableContainerListBounds.Location.X + 10, -drawableContainerListBounds.Location.Y + 10);
+ }
+ }
+ else
+ {
+ Rectangle moveContainerListBounds = drawableContainerListBounds;
+ moveContainerListBounds.Offset(moveOffset);
+ // check if the element is inside
+ if (!Bounds.Contains(moveContainerListBounds))
+ {
+ // Easy fix for same surface
+ if (isSameSurface)
+ {
+ moveOffset = new Point(-10, -10);
+ }
+ else
+ {
+ // For different surface, which is most likely smaller
+ int offsetX = 0;
+ int offsetY = 0;
+ if (drawableContainerListBounds.Right > Bounds.Right)
+ {
+ offsetX = Bounds.Right - drawableContainerListBounds.Right;
+ // Correction for the correction
+ if (drawableContainerListBounds.Left + offsetX < 0)
+ {
+ offsetX += Math.Abs(drawableContainerListBounds.Left + offsetX);
+ }
+ }
+ if (drawableContainerListBounds.Bottom > Bounds.Bottom)
+ {
+ offsetY = Bounds.Bottom - drawableContainerListBounds.Bottom;
+ // Correction for the correction
+ if (drawableContainerListBounds.Top + offsetY < 0)
+ {
+ offsetY += Math.Abs(drawableContainerListBounds.Top + offsetY);
+ }
+ }
+ moveOffset = new Point(offsetX, offsetY);
+ }
+ }
+ }
+ dcs.MoveBy(moveOffset.X, moveOffset.Y);
+ AddElements(dcs);
+ FieldAggregator.BindElements(dcs);
+ DeselectAllElements();
+ SelectElements(dcs);
+ }
+ }
+ else if (ClipboardHelper.ContainsImage(clipboard))
+ {
+ int x = 10;
+ int y = 10;
+
+ // FEATURE-995: Added a check for the current mouse cursor location, to paste the image on that location.
+ var mousePositionOnControl = PointToClient(MousePosition);
+ if (ClientRectangle.Contains(mousePositionOnControl))
+ {
+ x = mousePositionOnControl.X;
+ y = mousePositionOnControl.Y;
+ }
+
+ foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard))
+ {
+ if (clipboardImage != null)
+ {
+ DeselectAllElements();
+ IImageContainer container = AddImageContainer(clipboardImage as Bitmap, x, y);
+ SelectElement(container);
+ clipboardImage.Dispose();
+ x += 10;
+ y += 10;
+ }
+ }
+ }
+ else if (ClipboardHelper.ContainsText(clipboard))
+ {
+ string text = ClipboardHelper.GetText(clipboard);
+ if (text != null)
+ {
+ DeselectAllElements();
+ ITextContainer textContainer = AddTextContainer(text, HorizontalAlignment.Center, VerticalAlignment.CENTER,
+ FontFamily.GenericSansSerif, 12f, false, false, false, 2, Color.Black, Color.Transparent);
+ SelectElement(textContainer);
+ }
+ }
+ }
+
+ ///
+ /// Duplicate all the selecteded elements
+ ///
+ public void DuplicateSelectedElements()
+ {
+ LOG.DebugFormat("Duplicating {0} selected elements", selectedElements.Count);
+ IDrawableContainerList dcs = selectedElements.Clone();
+ dcs.Parent = this;
+ dcs.MoveBy(10, 10);
+ AddElements(dcs);
+ DeselectAllElements();
+ SelectElements(dcs);
+ }
+
+ ///
+ /// Deselect the specified element
+ ///
+ /// IDrawableContainerList
+ /// false to skip event generation
+ public void DeselectElement(IDrawableContainer container, bool generateEvents = true)
+ {
+ container.Selected = false;
+ selectedElements.Remove(container);
+ FieldAggregator.UnbindElement(container);
+ if (generateEvents && _movingElementChanged != null)
+ {
+ var eventArgs = new SurfaceElementEventArgs {Elements = selectedElements};
+ _movingElementChanged(this, eventArgs);
+ }
+ }
+
+ ///
+ /// Deselect the specified elements
+ ///
+ /// IDrawableContainerList
+ public void DeselectElements(IDrawableContainerList elements)
+ {
+ if (elements.Count == 0)
+ {
+ return;
+ }
+ while (elements.Count > 0)
+ {
+ var element = elements[0];
+ DeselectElement(element, false);
+ }
+ if (_movingElementChanged != null)
+ {
+ SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs
+ {
+ Elements = selectedElements
+ };
+ _movingElementChanged(this, eventArgs);
+ }
+ Invalidate();
+ }
+
+ ///
+ /// Deselect all the selected elements
+ ///
+ public void DeselectAllElements()
+ {
+ DeselectElements(selectedElements);
+ }
+
+ ///
+ /// Select the supplied element
+ ///
+ ///
+ /// false to skip invalidation
+ /// false to skip event generation
+ public void SelectElement(IDrawableContainer container, bool invalidate = true, bool generateEvents = true)
+ {
+ if (!selectedElements.Contains(container))
+ {
+ selectedElements.Add(container);
+ container.Selected = true;
+ FieldAggregator.BindElement(container);
+ if (generateEvents && _movingElementChanged != null)
+ {
+ SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs
+ {
+ Elements = selectedElements
+ };
+ _movingElementChanged(this, eventArgs);
+ }
+ if (invalidate)
+ {
+ container.Invalidate();
+ }
+ }
+ }
+
+ ///
+ /// Select all elements, this is called when Ctrl+A is pressed
+ ///
+ public void SelectAllElements()
+ {
+ SelectElements(_elements);
+ }
+
+ ///
+ /// Select the supplied elements
+ ///
+ ///
+ public void SelectElements(IDrawableContainerList elements)
+ {
+ SuspendLayout();
+ foreach (var drawableContainer in elements)
+ {
+ var element = (DrawableContainer) drawableContainer;
+ SelectElement(element, false, false);
+ }
+ if (_movingElementChanged != null)
+ {
+ SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs {Elements = selectedElements};
+ _movingElementChanged(this, eventArgs);
+ }
+ ResumeLayout();
+ Invalidate();
+ }
+
+ ///
+ /// Process key presses on the surface, this is called from the editor (and NOT an override from the Control)
+ ///
+ /// Keys
+ /// false if no keys were processed
+ public bool ProcessCmdKey(Keys k)
+ {
+ if (selectedElements.Count > 0)
+ {
+ bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift;
+ int px = shiftModifier ? 10 : 1;
+ Point moveBy = Point.Empty;
+
+ switch (k)
+ {
+ case Keys.Left:
+ case Keys.Left | Keys.Shift:
+ moveBy = new Point(-px, 0);
+ break;
+ case Keys.Up:
+ case Keys.Up | Keys.Shift:
+ moveBy = new Point(0, -px);
+ break;
+ case Keys.Right:
+ case Keys.Right | Keys.Shift:
+ moveBy = new Point(px, 0);
+ break;
+ case Keys.Down:
+ case Keys.Down | Keys.Shift:
+ moveBy = new Point(0, px);
+ break;
+ case Keys.PageUp:
+ PullElementsUp();
+ break;
+ case Keys.PageDown:
+ PushElementsDown();
+ break;
+ case Keys.Home:
+ PullElementsToTop();
+ break;
+ case Keys.End:
+ PushElementsToBottom();
+ break;
+ case Keys.Enter:
+ ConfirmSelectedConfirmableElements(true);
+ break;
+ case Keys.Escape:
+ ConfirmSelectedConfirmableElements(false);
+ break;
+ /*case Keys.Delete:
+ RemoveSelectedElements();
+ break;*/
+ default:
+ return false;
+ }
+ if (!Point.Empty.Equals(moveBy))
+ {
+ selectedElements.MakeBoundsChangeUndoable(true);
+ selectedElements.MoveBy(moveBy.X, moveBy.Y);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Property for accessing the elements on the surface
+ ///
+ public IDrawableContainerList Elements => _elements;
+
+ ///
+ /// pulls selected elements up one level in hierarchy
+ ///
+ public void PullElementsUp()
+ {
+ _elements.PullElementsUp(selectedElements);
+ _elements.Invalidate();
+ }
+
+ ///
+ /// pushes selected elements up to top in hierarchy
+ ///
+ public void PullElementsToTop()
+ {
+ _elements.PullElementsToTop(selectedElements);
+ _elements.Invalidate();
+ }
+
+ ///
+ /// pushes selected elements down one level in hierarchy
+ ///
+ public void PushElementsDown()
+ {
+ _elements.PushElementsDown(selectedElements);
+ _elements.Invalidate();
+ }
+
+ ///
+ /// pushes selected elements down to bottom in hierarchy
+ ///
+ public void PushElementsToBottom()
+ {
+ _elements.PushElementsToBottom(selectedElements);
+ _elements.Invalidate();
+ }
+
+ ///
+ /// indicates whether the selected elements could be pulled up in hierarchy
+ ///
+ /// true if selected elements could be pulled up, false otherwise
+ public bool CanPullSelectionUp()
+ {
+ return _elements.CanPullUp(selectedElements);
+ }
+
+ ///
+ /// indicates whether the selected elements could be pushed down in hierarchy
+ ///
+ /// true if selected elements could be pushed down, false otherwise
+ public bool CanPushSelectionDown()
+ {
+ return _elements.CanPushDown(selectedElements);
+ }
+
+ public void element_FieldChanged(object sender, FieldChangedEventArgs e)
+ {
+ selectedElements.HandleFieldChangedEvent(sender, e);
+ }
+
+ public bool IsOnSurface(IDrawableContainer container)
+ {
+ return _elements.Contains(container);
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Drawing/TextContainer.cs b/Greenshot/Drawing/TextContainer.cs
similarity index 70%
rename from src/Greenshot.Editor/Drawing/TextContainer.cs
rename to Greenshot/Drawing/TextContainer.cs
index a49fd4bee..d352aa056 100644
--- a/src/Greenshot.Editor/Drawing/TextContainer.cs
+++ b/Greenshot/Drawing/TextContainer.cs
@@ -1,695 +1,628 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Drawing.Text;
-using System.Runtime.Serialization;
-using System.Windows.Forms;
-using Dapplo.Windows.Common.Extensions;
-using Dapplo.Windows.Common.Structs;
-using Greenshot.Base.Core;
-using Greenshot.Base.Interfaces;
-using Greenshot.Base.Interfaces.Drawing;
-using Greenshot.Editor.Drawing.Fields;
-using Greenshot.Editor.Memento;
-
-namespace Greenshot.Editor.Drawing
-{
- ///
- /// Represents a textbox (extends RectangleContainer for border/background support
- ///
- [Serializable]
- public class TextContainer : RectangleContainer, ITextContainer
- {
- // If makeUndoable is true the next text-change will make the change undoable.
- // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack
- // Although the name is wrong, we can't change it due to file serialization
- // ReSharper disable once InconsistentNaming
- private bool makeUndoable;
- [NonSerialized] private Font _font;
- public Font Font => _font;
-
- [NonSerialized] private TextBox _textBox;
-
- ///
- /// The StringFormat object is not serializable!!
- ///
- [NonSerialized] private StringFormat _stringFormat = new StringFormat();
-
- public StringFormat StringFormat => _stringFormat;
-
- // Although the name is wrong, we can't change it due to file serialization
- // ReSharper disable once InconsistentNaming
- private string text;
-
- // there is a binding on the following property!
- public string Text
- {
- get => text;
- set => ChangeText(value, true);
- }
-
- internal void ChangeText(string newText, bool allowUndoable)
- {
- if ((text != null || newText == null) && string.Equals(text, newText)) return;
-
- if (makeUndoable && allowUndoable && IsUndoable)
- {
- makeUndoable = false;
- _parent.MakeUndoable(new TextChangeMemento(this), false);
- }
-
- text = newText;
- OnPropertyChanged("Text");
- }
-
- public TextContainer(ISurface parent) : base(parent)
- {
- Init();
- }
-
- protected override void InitializeFields()
- {
- AddField(GetType(), FieldType.LINE_THICKNESS, 2);
- AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
- AddField(GetType(), FieldType.SHADOW, true);
- AddField(GetType(), FieldType.FONT_ITALIC, false);
- AddField(GetType(), FieldType.FONT_BOLD, false);
- AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
- AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
- AddField(GetType(), FieldType.FONT_SIZE, 11f);
- AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center);
- AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center);
- }
-
- ///
- /// Do some logic to make sure all field are initiated correctly
- ///
- /// StreamingContext
- protected override void OnDeserialized(StreamingContext streamingContext)
- {
- base.OnDeserialized(streamingContext);
- Init();
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_font != null)
- {
- _font.Dispose();
- _font = null;
- }
-
- if (_stringFormat != null)
- {
- _stringFormat.Dispose();
- _stringFormat = null;
- }
-
- if (_textBox != null)
- {
- _textBox.Dispose();
- _textBox = null;
- }
- }
-
- base.Dispose(disposing);
- }
-
- private void Init()
- {
- _stringFormat = new StringFormat
- {
- Trimming = StringTrimming.EllipsisWord
- };
-
- CreateTextBox();
-
- UpdateFormat();
- UpdateTextBoxFormat();
-
- PropertyChanged += TextContainer_PropertyChanged;
- FieldChanged += TextContainer_FieldChanged;
- }
-
- protected override void SwitchParent(ISurface newParent)
- {
- if (InternalParent != null)
- {
- InternalParent.SizeChanged -= Parent_SizeChanged;
- }
-
- base.SwitchParent(newParent);
- if (InternalParent != null)
- {
- InternalParent.SizeChanged += Parent_SizeChanged;
- }
- }
-
- private void Parent_SizeChanged(object sender, EventArgs e)
- {
- UpdateTextBoxPosition();
- UpdateTextBoxFont();
- }
-
- public override void ApplyBounds(NativeRectFloat newBounds)
- {
- base.ApplyBounds(newBounds);
- UpdateTextBoxPosition();
- }
-
- public override void Invalidate()
- {
- base.Invalidate();
- if (_textBox != null && _textBox.Visible)
- {
- _textBox.Invalidate();
- }
- }
-
- public void FitToText()
- {
- Size textSize = TextRenderer.MeasureText(text, _font);
- int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
- Width = textSize.Width + lineThickness;
- Height = textSize.Height + lineThickness;
- }
-
- private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (_textBox == null)
- {
- return;
- }
-
- if (_textBox.Visible)
- {
- _textBox.Invalidate();
- }
-
- UpdateTextBoxPosition();
- UpdateTextBoxFormat();
- if (e.PropertyName.Equals("Selected"))
- {
- if (!Selected && _textBox.Visible)
- {
- HideTextBox();
- }
- else if (Selected && Status == EditStatus.DRAWING)
- {
- ShowTextBox();
- }
- else if (InternalParent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible)
- {
- // Fix (workaround) for BUG-1698
- InternalParent.KeysLocked = true;
- }
- }
-
- if (_textBox.Visible)
- {
- _textBox.Invalidate();
- }
- }
-
- private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e)
- {
- if (_textBox == null)
- {
- return;
- }
-
- if (_textBox.Visible)
- {
- _textBox.Invalidate();
- }
-
- // Only dispose the font, and re-create it, when a font field has changed.
- if (e.Field.FieldType.Name.StartsWith("FONT"))
- {
- if (_font != null)
- {
- _font.Dispose();
- _font = null;
- }
-
- UpdateFormat();
- }
- else
- {
- UpdateAlignment();
- }
-
- UpdateTextBoxFormat();
-
- if (_textBox.Visible)
- {
- _textBox.Invalidate();
- }
- }
-
- public override void OnDoubleClick()
- {
- ShowTextBox();
- }
-
- private void CreateTextBox()
- {
- _textBox = new TextBox
- {
- ImeMode = ImeMode.On,
- Multiline = true,
- AcceptsTab = true,
- AcceptsReturn = true,
- BorderStyle = BorderStyle.None,
- Visible = false,
- Font = new Font(FontFamily.GenericSansSerif, 1) // just need something non-default here
- };
-
- _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged);
- _textBox.LostFocus += TextBox_LostFocus;
- _textBox.KeyDown += textBox_KeyDown;
- }
-
- private void ShowTextBox()
- {
- if (InternalParent != null)
- {
- InternalParent.KeysLocked = true;
- InternalParent.Controls.Add(_textBox);
- }
-
- EnsureTextBoxContrast();
- if (_textBox != null)
- {
- _textBox.Show();
- _textBox.Focus();
- }
- }
-
- ///
- /// Makes textbox background dark if text color is very bright
- ///
- private void EnsureTextBoxContrast()
- {
- if (_textBox == null)
- {
- return;
- }
-
- Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR);
- if (lc.R > 203 && lc.G > 203 && lc.B > 203)
- {
- _textBox.BackColor = Color.FromArgb(51, 51, 51);
- }
- else
- {
- _textBox.BackColor = Color.White;
- }
- }
-
- private void HideTextBox()
- {
- InternalParent?.Focus();
- _textBox?.Hide();
- if (InternalParent == null)
- {
- return;
- }
-
- InternalParent.KeysLocked = false;
- if (_textBox != null)
- {
- InternalParent.Controls.Remove(_textBox);
- }
- }
-
- ///
- /// Make sure the size of the font is scaled
- ///
- ///
- public override void Transform(Matrix matrix)
- {
- var rect = new NativeRect(Left, Top, Width, Height).Normalize();
- int pixelsBefore = rect.Width * rect.Height;
-
- // Transform this container
- base.Transform(matrix);
- rect = new NativeRect(Left, Top, Width, Height).Normalize();
-
- int pixelsAfter = rect.Width * rect.Height;
- float factor = pixelsAfter / (float) pixelsBefore;
-
- float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
- fontSize *= factor;
- SetFieldValue(FieldType.FONT_SIZE, fontSize);
- UpdateFormat();
- }
-
- private Font CreateFont(string fontFamilyName, bool fontBold, bool fontItalic, float fontSize)
- {
- FontStyle fontStyle = FontStyle.Regular;
-
- bool hasStyle = false;
- using var fontFamily = new FontFamily(fontFamilyName);
- bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold);
- if (fontBold && boldAvailable)
- {
- fontStyle |= FontStyle.Bold;
- hasStyle = true;
- }
-
- bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic);
- if (fontItalic && italicAvailable)
- {
- fontStyle |= FontStyle.Italic;
- hasStyle = true;
- }
-
- if (!hasStyle)
- {
- bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular);
- if (regularAvailable)
- {
- fontStyle = FontStyle.Regular;
- }
- else
- {
- if (boldAvailable)
- {
- fontStyle = FontStyle.Bold;
- }
- else if (italicAvailable)
- {
- fontStyle = FontStyle.Italic;
- }
- }
- }
-
- return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel);
- }
-
- ///
- /// Generate the Font-Formal so we can draw correctly
- ///
- protected void UpdateFormat()
- {
- if (_textBox == null)
- {
- return;
- }
-
- string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY);
- bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD);
- bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC);
- float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
- try
- {
- var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize);
- _font?.Dispose();
- _font = newFont;
- }
- catch (Exception ex)
- {
- // Problem, try again with the default
- try
- {
- fontFamily = FontFamily.GenericSansSerif.Name;
- SetFieldValue(FieldType.FONT_FAMILY, fontFamily);
- var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize);
- _font?.Dispose();
- _font = newFont;
- }
- catch (Exception)
- {
- // When this happens... the PC is broken
- ex.Data.Add("fontFamilyName", fontFamily);
- ex.Data.Add("fontBold", fontBold);
- ex.Data.Add("fontItalic", fontItalic);
- ex.Data.Add("fontSize", fontSize);
- throw ex;
- }
- }
-
- UpdateTextBoxFont();
-
- UpdateAlignment();
- }
-
- private void UpdateAlignment()
- {
- _stringFormat.Alignment = (StringAlignment) GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
- _stringFormat.LineAlignment = (StringAlignment) GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
- }
-
- ///
- /// Set TextBox font according to the TextContainer font and the parent zoom factor.
- ///
- private void UpdateTextBoxFont()
- {
- if (_textBox == null || _font == null)
- {
- return;
- }
-
- var textBoxFontScale = _parent?.ZoomFactor ?? Fraction.Identity;
-
- var newFont = new Font(
- _font.FontFamily,
- _font.Size * textBoxFontScale,
- _font.Style,
- GraphicsUnit.Pixel
- );
- _textBox.Font.Dispose();
- _textBox.Font = newFont;
- }
-
- ///
- /// This will align the textbox exactly to the inner size of the element
- /// is a bit of a hack, but for now it seems to work...
- ///
- private void UpdateTextBoxPosition()
- {
- if (_textBox == null || Parent == null)
- {
- return;
- }
-
- int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
-
- int lineWidth = (int) Math.Floor(lineThickness / 2d);
- int correction = (lineThickness + 1) % 2;
- if (lineThickness <= 1)
- {
- lineWidth = 1;
- correction = -1;
- }
-
- var absRectangle = new NativeRect(Left, Top, Width, Height).Normalize();
- var displayRectangle = Parent.ToSurfaceCoordinates(absRectangle);
- _textBox.Left = displayRectangle.X + lineWidth;
- _textBox.Top = displayRectangle.Y + lineWidth;
- if (lineThickness <= 1)
- {
- lineWidth = 0;
- }
-
- _textBox.Width = displayRectangle.Width - 2 * lineWidth + correction;
- _textBox.Height = displayRectangle.Height - 2 * lineWidth + correction;
- }
-
- ///
- /// Set TextBox text align and fore color according to field values.
- ///
- private void UpdateTextBoxFormat()
- {
- if (_textBox == null)
- {
- return;
- }
-
- var alignment = (StringAlignment) GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
- switch (alignment)
- {
- case StringAlignment.Near:
- _textBox.TextAlign = HorizontalAlignment.Left;
- break;
- case StringAlignment.Far:
- _textBox.TextAlign = HorizontalAlignment.Right;
- break;
- case StringAlignment.Center:
- _textBox.TextAlign = HorizontalAlignment.Center;
- break;
- }
-
- var lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
- _textBox.ForeColor = lineColor;
- }
-
- private void textBox_KeyDown(object sender, KeyEventArgs e)
- {
- // ESC and Enter/Return (w/o Shift) hide text editor
- if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None))
- {
- HideTextBox();
- e.SuppressKeyPress = true;
- }
-
- if (e.Control && !e.Alt && e.KeyCode == Keys.A)
- {
- _textBox.SelectAll();
- }
-
- // Added for FEATURE-1064
- if (e.KeyCode == Keys.Back && e.Control)
- {
- e.SuppressKeyPress = true;
- int selStart = _textBox.SelectionStart;
- while (selStart > 0 && _textBox.Text.Substring(selStart - 1, 1) == " ")
- {
- selStart--;
- }
-
- int prevSpacePos = -1;
- if (selStart != 0)
- {
- prevSpacePos = _textBox.Text.LastIndexOf(' ', selStart - 1);
- }
-
- _textBox.Select(prevSpacePos + 1, _textBox.SelectionStart - prevSpacePos - 1);
- _textBox.SelectedText = string.Empty;
- }
- }
-
- private void TextBox_LostFocus(object sender, EventArgs e)
- {
- // next change will be made undoable
- makeUndoable = true;
- HideTextBox();
- }
-
- public override void Draw(Graphics graphics, RenderMode rm)
- {
- base.Draw(graphics, rm);
-
- graphics.SmoothingMode = SmoothingMode.HighQuality;
- graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
- graphics.CompositingQuality = CompositingQuality.HighQuality;
- graphics.PixelOffsetMode = PixelOffsetMode.None;
- graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
-
- var rect = new NativeRect(Left, Top, Width, Height).Normalize();
- if (Selected && rm == RenderMode.EDIT)
- {
- DrawSelectionBorder(graphics, rect);
- }
-
- if (string.IsNullOrEmpty(text))
- {
- return;
- }
-
- // we only draw the shadow if there is no background
- bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
- Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
- int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
- Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
- bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty);
-
- DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font);
- }
-
- ///
- /// This method can be used from other containers
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void DrawText(Graphics graphics, NativeRect drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text,
- Font font)
- {
-#if DEBUG
- Debug.Assert(font != null);
-#else
- if (font == null)
- {
- return;
- }
-#endif
- int textOffset = lineThickness > 0 ? (int) Math.Ceiling(lineThickness / 2d) : 0;
- // draw shadow before anything else
- if (drawShadow)
- {
- int basealpha = 100;
- int alpha = basealpha;
- int steps = 5;
- int currentStep = 1;
- while (currentStep <= steps)
- {
- int offset = currentStep;
- NativeRect shadowRect = new NativeRect(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height).Normalize();
- if (lineThickness > 0)
- {
- shadowRect = shadowRect.Inflate(-textOffset, -textOffset);
- }
- using Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100));
- graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat);
-
- currentStep++;
- alpha -= basealpha / steps;
- }
- }
-
- if (lineThickness > 0)
- {
- drawingRectange = drawingRectange.Inflate(-textOffset, -textOffset);
- }
- using (Brush fontBrush = new SolidBrush(fontColor))
- {
- if (stringFormat != null)
- {
- graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat);
- }
- else
- {
- graphics.DrawString(text, font, fontBrush, drawingRectange);
- }
- }
- }
-
- public override bool ClickableAt(int x, int y)
- {
- var r = new NativeRect(Left, Top, Width, Height).Normalize().Inflate(5, 5);
- return r.Contains(x, y);
- }
- }
-}
\ No newline at end of file
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing.Fields;
+using Greenshot.Helpers;
+using Greenshot.Memento;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Interfaces.Drawing;
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Runtime.Serialization;
+using System.Windows.Forms;
+
+namespace Greenshot.Drawing
+{
+ ///
+ /// Represents a textbox (extends RectangleContainer for border/background support
+ ///
+ [Serializable]
+ public class TextContainer : RectangleContainer, ITextContainer
+ {
+ // If makeUndoable is true the next text-change will make the change undoable.
+ // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack
+ // Although the name is wrong, we can't change it due to file serialization
+ // ReSharper disable once InconsistentNaming
+ private bool makeUndoable;
+ [NonSerialized]
+ private Font _font;
+ public Font Font => _font;
+
+ [NonSerialized]
+ private TextBox _textBox;
+
+ ///
+ /// The StringFormat object is not serializable!!
+ ///
+ [NonSerialized]
+ private StringFormat _stringFormat = new StringFormat();
+
+ public StringFormat StringFormat => _stringFormat;
+
+ // Although the name is wrong, we can't change it due to file serialization
+ // ReSharper disable once InconsistentNaming
+ private string text;
+ // there is a binding on the following property!
+ public string Text
+ {
+ get { return text; }
+ set
+ {
+ ChangeText(value, true);
+ }
+ }
+
+ internal void ChangeText(string newText, bool allowUndoable)
+ {
+ if ((text == null && newText != null) || !string.Equals(text, newText))
+ {
+ if (makeUndoable && allowUndoable)
+ {
+ makeUndoable = false;
+ _parent.MakeUndoable(new TextChangeMemento(this), false);
+ }
+ text = newText;
+ OnPropertyChanged("Text");
+ }
+ }
+
+ public TextContainer(Surface parent) : base(parent)
+ {
+ Init();
+ }
+
+ protected override void InitializeFields()
+ {
+ AddField(GetType(), FieldType.LINE_THICKNESS, 2);
+ AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
+ AddField(GetType(), FieldType.SHADOW, true);
+ AddField(GetType(), FieldType.FONT_ITALIC, false);
+ AddField(GetType(), FieldType.FONT_BOLD, false);
+ AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
+ AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
+ AddField(GetType(), FieldType.FONT_SIZE, 11f);
+ AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center);
+ AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center);
+ }
+
+ ///
+ /// Do some logic to make sure all field are initiated correctly
+ ///
+ /// StreamingContext
+ protected override void OnDeserialized(StreamingContext streamingContext)
+ {
+ base.OnDeserialized(streamingContext);
+ Init();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_font != null)
+ {
+ _font.Dispose();
+ _font = null;
+ }
+ if (_stringFormat != null)
+ {
+ _stringFormat.Dispose();
+ _stringFormat = null;
+ }
+ if (_textBox != null)
+ {
+ _textBox.Dispose();
+ _textBox = null;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ private void Init()
+ {
+ _stringFormat = new StringFormat
+ {
+ Trimming = StringTrimming.EllipsisWord
+ };
+
+ CreateTextBox();
+
+ UpdateFormat();
+ UpdateTextBoxFormat();
+
+ PropertyChanged += TextContainer_PropertyChanged;
+ FieldChanged += TextContainer_FieldChanged;
+ }
+
+
+ public override void Invalidate()
+ {
+ base.Invalidate();
+ if (_textBox != null && _textBox.Visible)
+ {
+ _textBox.Invalidate();
+ }
+ }
+
+ public void FitToText()
+ {
+ Size textSize = TextRenderer.MeasureText(text, _font);
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Width = textSize.Width + lineThickness;
+ Height = textSize.Height + lineThickness;
+ }
+
+ private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+
+ if (_textBox.Visible)
+ {
+ _textBox.Invalidate();
+ }
+
+ UpdateTextBoxPosition();
+ UpdateTextBoxFormat();
+ if (e.PropertyName.Equals("Selected"))
+ {
+ if (!Selected && _textBox.Visible)
+ {
+ HideTextBox();
+ }
+ else if (Selected && Status == EditStatus.DRAWING)
+ {
+ ShowTextBox();
+ }
+ else if (_parent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible)
+ {
+ // Fix (workaround) for BUG-1698
+ _parent.KeysLocked = true;
+ }
+ }
+ if (_textBox.Visible)
+ {
+ _textBox.Invalidate();
+ }
+ }
+
+ private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e)
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+ if (_textBox.Visible)
+ {
+ _textBox.Invalidate();
+ }
+ // Only dispose the font, and re-create it, when a font field has changed.
+ if (e.Field.FieldType.Name.StartsWith("FONT"))
+ {
+ if (_font != null)
+ {
+ _font.Dispose();
+ _font = null;
+ }
+ UpdateFormat();
+ }
+ else
+ {
+ UpdateAlignment();
+ }
+ UpdateTextBoxFormat();
+
+ if (_textBox.Visible)
+ {
+ _textBox.Invalidate();
+ }
+ }
+
+ public override void OnDoubleClick()
+ {
+ ShowTextBox();
+ }
+
+ private void CreateTextBox()
+ {
+ _textBox = new TextBox
+ {
+ ImeMode = ImeMode.On,
+ Multiline = true,
+ AcceptsTab = true,
+ AcceptsReturn = true,
+ BorderStyle = BorderStyle.None,
+ Visible = false
+ };
+
+ _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged);
+ _textBox.LostFocus += textBox_LostFocus;
+ _textBox.KeyDown += textBox_KeyDown;
+ }
+
+ private void ShowTextBox()
+ {
+ if (_parent != null)
+ {
+ _parent.KeysLocked = true;
+ _parent.Controls.Add(_textBox);
+ }
+ EnsureTextBoxContrast();
+ if (_textBox != null)
+ {
+ _textBox.Show();
+ _textBox.Focus();
+ }
+ }
+
+ ///
+ /// Makes textbox background dark if text color is very bright
+ ///
+ private void EnsureTextBoxContrast()
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+ Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ if (lc.R > 203 && lc.G > 203 && lc.B > 203)
+ {
+ _textBox.BackColor = Color.FromArgb(51, 51, 51);
+ }
+ else
+ {
+ _textBox.BackColor = Color.White;
+ }
+ }
+
+ private void HideTextBox()
+ {
+ _parent.Focus();
+ _textBox?.Hide();
+ _parent.KeysLocked = false;
+ _parent.Controls.Remove(_textBox);
+ }
+
+ ///
+ /// Make sure the size of the font is scaled
+ ///
+ ///
+ public override void Transform(Matrix matrix)
+ {
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ int pixelsBefore = rect.Width * rect.Height;
+
+ // Transform this container
+ base.Transform(matrix);
+ rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+
+ int pixelsAfter = rect.Width * rect.Height;
+ float factor = pixelsAfter / (float)pixelsBefore;
+
+ float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
+ fontSize *= factor;
+ SetFieldValue(FieldType.FONT_SIZE, fontSize);
+ UpdateFormat();
+ }
+
+ private Font CreateFont(string fontFamilyName, bool fontBold, bool fontItalic, float fontSize)
+ {
+ FontStyle fontStyle = FontStyle.Regular;
+
+ bool hasStyle = false;
+ using (var fontFamily = new FontFamily(fontFamilyName))
+ {
+ bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold);
+ if (fontBold && boldAvailable)
+ {
+ fontStyle |= FontStyle.Bold;
+ hasStyle = true;
+ }
+
+ bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic);
+ if (fontItalic && italicAvailable)
+ {
+ fontStyle |= FontStyle.Italic;
+ hasStyle = true;
+ }
+
+ if (!hasStyle)
+ {
+ bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular);
+ if (regularAvailable)
+ {
+ fontStyle = FontStyle.Regular;
+ }
+ else
+ {
+ if (boldAvailable)
+ {
+ fontStyle = FontStyle.Bold;
+ }
+ else if (italicAvailable)
+ {
+ fontStyle = FontStyle.Italic;
+ }
+ }
+ }
+ return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel);
+ }
+ }
+
+ ///
+ /// Generate the Font-Formal so we can draw correctly
+ ///
+ protected void UpdateFormat()
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+ string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY);
+ bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD);
+ bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC);
+ float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
+ try
+ {
+ var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize);
+ _font?.Dispose();
+ _font = newFont;
+ _textBox.Font = _font;
+ }
+ catch (Exception ex)
+ {
+ // Problem, try again with the default
+ try
+ {
+ fontFamily = FontFamily.GenericSansSerif.Name;
+ SetFieldValue(FieldType.FONT_FAMILY, fontFamily);
+ var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize);
+ _font?.Dispose();
+ _font = newFont;
+ _textBox.Font = _font;
+ }
+ catch (Exception)
+ {
+ // When this happens... the PC is broken
+ ex.Data.Add("fontFamilyName", fontFamily);
+ ex.Data.Add("fontBold", fontBold);
+ ex.Data.Add("fontItalic", fontItalic);
+ ex.Data.Add("fontSize", fontSize);
+ throw ex;
+ }
+ }
+
+ UpdateAlignment();
+ }
+
+ private void UpdateAlignment()
+ {
+ _stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
+ _stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
+ }
+
+ ///
+ /// This will create the textbox exactly to the inner size of the element
+ /// is a bit of a hack, but for now it seems to work...
+ ///
+ private void UpdateTextBoxPosition()
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+
+ int lineWidth = (int)Math.Floor(lineThickness / 2d);
+ int correction = (lineThickness + 1) % 2;
+ if (lineThickness <= 1)
+ {
+ lineWidth = 1;
+ correction = -1;
+ }
+ Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ _textBox.Left = absRectangle.Left + lineWidth;
+ _textBox.Top = absRectangle.Top + lineWidth;
+ if (lineThickness <= 1)
+ {
+ lineWidth = 0;
+ }
+ _textBox.Width = absRectangle.Width - 2 * lineWidth + correction;
+ _textBox.Height = absRectangle.Height - 2 * lineWidth + correction;
+ }
+
+ public override void ApplyBounds(RectangleF newBounds)
+ {
+ base.ApplyBounds(newBounds);
+ UpdateTextBoxPosition();
+ }
+
+ private void UpdateTextBoxFormat()
+ {
+ if (_textBox == null)
+ {
+ return;
+ }
+ var alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
+ switch (alignment)
+ {
+ case StringAlignment.Near:
+ _textBox.TextAlign = HorizontalAlignment.Left;
+ break;
+ case StringAlignment.Far:
+ _textBox.TextAlign = HorizontalAlignment.Right;
+ break;
+ case StringAlignment.Center:
+ _textBox.TextAlign = HorizontalAlignment.Center;
+ break;
+ }
+
+ var lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ _textBox.ForeColor = lineColor;
+ }
+
+ private void textBox_KeyDown(object sender, KeyEventArgs e)
+ {
+ // ESC and Enter/Return (w/o Shift) hide text editor
+ if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None))
+ {
+ HideTextBox();
+ e.SuppressKeyPress = true;
+ }
+
+ if (e.Control && e.KeyCode == Keys.A)
+ {
+ _textBox.SelectAll();
+ }
+ // Added for FEATURE-1064
+ if (e.KeyCode == Keys.Back && e.Control)
+ {
+ e.SuppressKeyPress = true;
+ int selStart = _textBox.SelectionStart;
+ while (selStart > 0 && _textBox.Text.Substring(selStart - 1, 1) == " ")
+ {
+ selStart--;
+ }
+ int prevSpacePos = -1;
+ if (selStart != 0)
+ {
+ prevSpacePos = _textBox.Text.LastIndexOf(' ', selStart - 1);
+ }
+ _textBox.Select(prevSpacePos + 1, _textBox.SelectionStart - prevSpacePos - 1);
+ _textBox.SelectedText = "";
+ }
+ }
+
+ private void textBox_LostFocus(object sender, EventArgs e)
+ {
+ // next change will be made undoable
+ makeUndoable = true;
+ HideTextBox();
+ }
+
+ public override void Draw(Graphics graphics, RenderMode rm)
+ {
+ base.Draw(graphics, rm);
+
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
+
+ Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ if (Selected && rm == RenderMode.EDIT)
+ {
+ DrawSelectionBorder(graphics, rect);
+ }
+
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ // we only draw the shadow if there is no background
+ bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
+ Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
+ int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
+ Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
+ bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty);
+
+ DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font);
+ }
+
+ ///
+ /// This method can be used from other containers
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font)
+ {
+#if DEBUG
+ Debug.Assert(font != null);
+#else
+ if (font == null)
+ {
+ return;
+ }
+#endif
+ int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0;
+ // draw shadow before anything else
+ if (drawShadow)
+ {
+ int basealpha = 100;
+ int alpha = basealpha;
+ int steps = 5;
+ int currentStep = 1;
+ while (currentStep <= steps)
+ {
+ int offset = currentStep;
+ Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height);
+ if (lineThickness > 0)
+ {
+ shadowRect.Inflate(-textOffset, -textOffset);
+ }
+ using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100)))
+ {
+ graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat);
+ currentStep++;
+ alpha = alpha - basealpha / steps;
+ }
+ }
+ }
+
+ if (lineThickness > 0)
+ {
+ drawingRectange.Inflate(-textOffset, -textOffset);
+ }
+ using (Brush fontBrush = new SolidBrush(fontColor))
+ {
+ if (stringFormat != null)
+ {
+ graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat);
+ }
+ else
+ {
+ graphics.DrawString(text, font, fontBrush, drawingRectange);
+ }
+ }
+ }
+
+ public override bool ClickableAt(int x, int y)
+ {
+ Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
+ r.Inflate(5, 5);
+ return r.Contains(x, y);
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/AboutForm.Designer.cs b/Greenshot/Forms/AboutForm.Designer.cs
similarity index 73%
rename from src/Greenshot/Forms/AboutForm.Designer.cs
rename to Greenshot/Forms/AboutForm.Designer.cs
index 1dbdbdc2d..66c86ac20 100644
--- a/src/Greenshot/Forms/AboutForm.Designer.cs
+++ b/Greenshot/Forms/AboutForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,15 +16,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-using System.Windows.Forms;
-using Greenshot.Base.Controls;
-using Greenshot.Base.Core;
-using Greenshot.Helpers;
+using System.Reflection;
-namespace Greenshot.Forms {
+namespace Greenshot {
partial class AboutForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -51,28 +48,26 @@ namespace Greenshot.Forms {
///
private void InitializeComponent() {
this.lblTitle = new System.Windows.Forms.Label();
- this.lblLicense = new GreenshotLabel();
- this.lblHost = new GreenshotLabel();
+ this.lblLicense = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.lblHost = new GreenshotPlugin.Controls.GreenshotLabel();
this.linkLblLicense = new System.Windows.Forms.LinkLabel();
this.linkLblHost = new System.Windows.Forms.LinkLabel();
this.linkLblBugs = new System.Windows.Forms.LinkLabel();
- this.lblBugs = new GreenshotLabel();
+ this.lblBugs = new GreenshotPlugin.Controls.GreenshotLabel();
this.linkLblDonations = new System.Windows.Forms.LinkLabel();
- this.lblDonations = new GreenshotLabel();
+ this.lblDonations = new GreenshotPlugin.Controls.GreenshotLabel();
this.linkLblIcons = new System.Windows.Forms.LinkLabel();
- this.lblIcons = new GreenshotLabel();
+ this.lblIcons = new GreenshotPlugin.Controls.GreenshotLabel();
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
- this.lblTranslation = new GreenshotLabel();
+ this.lblTranslation = new GreenshotPlugin.Controls.GreenshotLabel();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// lblTitle
//
- var fontsize = (this.DeviceDpi / 96) * lblTitle.Font.Size;
- this.lblTitle.AutoSize = true;
- this.lblTitle.Font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSansSerif, fontsize, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.lblTitle.Location = new System.Drawing.Point(108, 12);
+ this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblTitle.Location = new System.Drawing.Point(108, 12);
this.lblTitle.Name = "lblTitle";
this.lblTitle.Size = new System.Drawing.Size(263, 19);
this.lblTitle.TabIndex = 2;
@@ -101,7 +96,7 @@ namespace Greenshot.Forms {
this.linkLblLicense.Size = new System.Drawing.Size(369, 23);
this.linkLblLicense.TabIndex = 5;
this.linkLblLicense.TabStop = true;
- this.linkLblLicense.Text = "https://www.gnu.org/licenses/gpl.html";
+ this.linkLblLicense.Text = "http://www.gnu.org/licenses/gpl.html";
this.linkLblLicense.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
//
// linkLblHost
@@ -121,9 +116,8 @@ namespace Greenshot.Forms {
this.linkLblBugs.Size = new System.Drawing.Size(465, 23);
this.linkLblBugs.TabIndex = 8;
this.linkLblBugs.TabStop = true;
- this.linkLblBugs.Text = "https://getgreenshot.org/tickets";
- this.linkLblBugs.Tag = "https://getgreenshot.org/tickets/?version=" + EnvironmentInfo.GetGreenshotVersion(true);
- this.linkLblBugs.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
+ this.linkLblBugs.Text = "http://getgreenshot.org/tickets/?version=" + Assembly.GetEntryAssembly().GetName().Version;
+ this.linkLblBugs.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
//
// lblBugs
//
@@ -140,9 +134,8 @@ namespace Greenshot.Forms {
this.linkLblDonations.Size = new System.Drawing.Size(465, 23);
this.linkLblDonations.TabIndex = 10;
this.linkLblDonations.TabStop = true;
- this.linkLblDonations.Text = "https://getgreenshot.org/support";
- this.linkLblDonations.Tag = "https://getgreenshot.org/support/?version=" + EnvironmentInfo.GetGreenshotVersion(true);
- this.linkLblDonations.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
+ this.linkLblDonations.Text = "http://getgreenshot.org/support/?version=" + Assembly.GetEntryAssembly().GetName().Version;
+ this.linkLblDonations.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
//
// lblDonations
//
@@ -159,7 +152,7 @@ namespace Greenshot.Forms {
this.linkLblIcons.Size = new System.Drawing.Size(279, 23);
this.linkLblIcons.TabIndex = 12;
this.linkLblIcons.TabStop = true;
- this.linkLblIcons.Text = "https://p.yusukekamiyamane.com";
+ this.linkLblIcons.Text = "http://p.yusukekamiyamane.com";
this.linkLblIcons.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
//
// lblIcons
@@ -177,10 +170,9 @@ namespace Greenshot.Forms {
this.linkLabel1.Size = new System.Drawing.Size(130, 23);
this.linkLabel1.TabIndex = 13;
this.linkLabel1.TabStop = true;
- this.linkLabel1.Text = "https://getgreenshot.org";
+ this.linkLabel1.Text = "http://getgreenshot.org";
this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.TopRight;
- this.linkLabel1.Tag = "https://getgreenshot.org/?version=" + EnvironmentInfo.GetGreenshotVersion(true);
- this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
+ this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked);
//
// pictureBox1
//
@@ -190,7 +182,6 @@ namespace Greenshot.Forms {
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox1.TabIndex = 14;
this.pictureBox1.TabStop = false;
- this.pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
//
// lblTranslation
//
@@ -202,11 +193,8 @@ namespace Greenshot.Forms {
//
// AboutForm
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- //this.AutoScaleDimensions = new System.Drawing.SizeF(96, 96);
- //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
-
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(530, 293);
this.Controls.Add(this.lblTranslation);
this.Controls.Add(this.pictureBox1);
@@ -242,11 +230,11 @@ namespace Greenshot.Forms {
private System.Windows.Forms.LinkLabel linkLblIcons;
private System.Windows.Forms.Label lblTitle;
private System.Windows.Forms.PictureBox pictureBox1;
- private GreenshotLabel lblTranslation;
- private GreenshotLabel lblHost;
- private GreenshotLabel lblDonations;
- private GreenshotLabel lblBugs;
- private GreenshotLabel lblIcons;
- private GreenshotLabel lblLicense;
+ private GreenshotPlugin.Controls.GreenshotLabel lblTranslation;
+ private GreenshotPlugin.Controls.GreenshotLabel lblHost;
+ private GreenshotPlugin.Controls.GreenshotLabel lblDonations;
+ private GreenshotPlugin.Controls.GreenshotLabel lblBugs;
+ private GreenshotPlugin.Controls.GreenshotLabel lblIcons;
+ private GreenshotPlugin.Controls.GreenshotLabel lblLicense;
}
}
diff --git a/Greenshot/Forms/AboutForm.cs b/Greenshot/Forms/AboutForm.cs
new file mode 100644
index 000000000..68f2d48a5
--- /dev/null
+++ b/Greenshot/Forms/AboutForm.cs
@@ -0,0 +1,340 @@
+/*
+* Greenshot - a free and open source screenshot tool
+* Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+*
+* For more information see: http://getgreenshot.org/
+* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 1 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*/
+
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Windows.Forms;
+using System.IO;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Collections.Generic;
+using System.Drawing.Drawing2D;
+
+using Greenshot.Helpers;
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using System.Security.Permissions;
+using log4net;
+
+namespace Greenshot {
+ ///
+ /// The about form
+ ///
+ public partial class AboutForm : AnimatingBaseForm {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(AboutForm));
+ private Bitmap _bitmap;
+ private readonly ColorAnimator _backgroundAnimation;
+ private readonly IList _pixels = new List();
+ private readonly IList _colorFlow = new List();
+ private readonly IList _pixelColors = new List();
+ private readonly Random _rand = new Random();
+ private readonly Color _backColor = Color.FromArgb(61, 61, 61);
+ private readonly Color _pixelColor = Color.FromArgb(138, 255, 0);
+
+ // Variables used for the color-cycle
+ private int _waitFrames;
+ private int _colorIndex;
+ private int _scrollCount;
+ private bool _hasAnimationsLeft;
+
+ // Variables are used to define the location of the dots
+ private const int w = 13;
+ private const int p1 = 7;
+ private const int p2 = p1 + w;
+ private const int p3 = p2 + w;
+ private const int p4 = p3 + w;
+ private const int p5 = p4 + w;
+ private const int p6 = p5 + w;
+ private const int p7 = p6 + w;
+
+ ///
+ /// The location of every dot in the "G"
+ ///
+ private readonly List gSpots = new List() {
+ // Top row
+ new Point(p2, p1), // 0
+ new Point(p3, p1), // 1
+ new Point(p4, p1), // 2
+ new Point(p5, p1), // 3
+ new Point(p6, p1), // 4
+
+ // Second row
+ new Point(p1, p2), // 5
+ new Point(p2, p2), // 6
+
+ // Third row
+ new Point(p1, p3), // 7
+ new Point(p2, p3), // 8
+
+ // Fourth row
+ new Point(p1, p4), // 9
+ new Point(p2, p4), // 10
+ new Point(p5, p4), // 11
+ new Point(p6, p4), // 12
+ new Point(p7, p4), // 13
+
+ // Fifth row
+ new Point(p1, p5), // 14
+ new Point(p2, p5), // 15
+ new Point(p6, p5), // 16
+ new Point(p7, p5), // 17
+
+ // Sixth row
+ new Point(p1, p6), // 18
+ new Point(p2, p6), // 19
+ new Point(p3, p6), // 20
+ new Point(p4, p6), // 21
+ new Point(p5, p6), // 22
+ new Point(p6, p6) // 23
+ };
+
+ // 0 1 2 3 4
+ // 5 6
+ // 7 8
+ // 9 10 11 12 13
+ // 14 15 16 17
+ // 18 19 20 21 22 23
+
+ // The order in which we draw the dots & flow the collors.
+ private readonly List flowOrder = new List() { 4, 3, 2, 1, 0, 5, 6, 7, 8, 9, 10, 14, 15, 18, 19, 20, 21, 22, 23, 16, 17, 13, 12, 11 };
+
+ ///
+ /// Cleanup all the allocated resources
+ ///
+ private void Cleanup(object sender, EventArgs e) {
+ if (_bitmap != null) {
+ _bitmap.Dispose();
+ _bitmap = null;
+ }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public AboutForm() {
+ // Make sure our resources are removed again.
+ Disposed += Cleanup;
+ FormClosing += Cleanup;
+
+ // Enable animation for this form, when we don't set this the timer doesn't start as soon as the form is loaded.
+ EnableAnimation = true;
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+
+ // Only use double-buffering when we are NOT in a Terminal Server session
+ DoubleBuffered = !IsTerminalServerSession;
+
+ // Use the self drawn image, first we create the background to be the backcolor (as we animate from this)
+ _bitmap = ImageHelper.CreateEmpty(90, 90, PixelFormat.Format24bppRgb, BackColor, 96, 96);
+ pictureBox1.Image = _bitmap;
+ Version v = Assembly.GetExecutingAssembly().GetName().Version;
+
+ // Format is like this: AssemblyVersion("Major.Minor.Build.Revision")]
+ lblTitle.Text = "Greenshot " + v.Major + "." + v.Minor + "." + v.Build + " Build " + v.Revision + (IniConfig.IsPortable ? " Portable" : "") + (" (" + OsInfo.Bits) + " bit)";
+
+ //Random rand = new Random();
+
+ // Number of frames the pixel animation takes
+ int frames = FramesForMillis(2000);
+ // The number of frames the color-cycle waits before it starts
+ _waitFrames = FramesForMillis(6000);
+
+ // Every pixel is created after pixelWaitFrames frames, which is increased in the loop.
+ int pixelWaitFrames = FramesForMillis(2000);
+ // Create pixels
+ for (int index = 0; index < gSpots.Count; index++) {
+ // Read the pixels in the order of the flow
+ Point gSpot = gSpots[flowOrder[index]];
+ // Create the animation, first we do nothing (on the final destination)
+ RectangleAnimator pixelAnimation;
+
+ // Make the pixel grom from the middle, if this offset isn't used it looks like it's shifted
+ int offset = (w - 2) / 2;
+
+ // If the optimize for Terminal Server is set we make the animation without much ado
+ if (IsTerminalServerSession) {
+ // No animation
+ pixelAnimation = new RectangleAnimator(new Rectangle(gSpot.X, gSpot.Y, w - 2, w - 2), new Rectangle(gSpot.X, gSpot.Y, w - 2, w - 2), 1, EasingType.Cubic, EasingMode.EaseIn);
+ } else {
+ // Create the animation, first we do nothing (on the final destination)
+ Rectangle standingStill = new Rectangle(gSpot.X + offset, gSpot.Y + offset, 0, 0);
+ pixelAnimation = new RectangleAnimator(standingStill, standingStill, pixelWaitFrames, EasingType.Quintic, EasingMode.EaseIn);
+ // And than we size to the wanted size.
+ pixelAnimation.QueueDestinationLeg(new Rectangle(gSpot.X, gSpot.Y, w - 2, w - 2), frames);
+ }
+ // Increase the wait frames
+ pixelWaitFrames += FramesForMillis(100);
+ // Add to the list of to be animated pixels
+ _pixels.Add(pixelAnimation);
+ // Add a color to the list for this pixel.
+ _pixelColors.Add(_pixelColor);
+ }
+ // Make sure the frame "loop" knows we have to animate
+ _hasAnimationsLeft = true;
+
+ // Pixel Color cycle colors, here we use a pre-animated loop which stores the values.
+ ColorAnimator pixelColorAnimator = new ColorAnimator(_pixelColor, Color.FromArgb(255, 255, 255), 6, EasingType.Quadratic, EasingMode.EaseIn);
+ pixelColorAnimator.QueueDestinationLeg(_pixelColor, 6, EasingType.Quadratic, EasingMode.EaseOut);
+ do {
+ _colorFlow.Add(pixelColorAnimator.Current);
+ pixelColorAnimator.Next();
+ } while (pixelColorAnimator.HasNext);
+
+ // color animation for the background
+ _backgroundAnimation = new ColorAnimator(BackColor, _backColor, FramesForMillis(5000), EasingType.Linear, EasingMode.EaseIn);
+ }
+
+ ///
+ /// This is called when a link is clicked
+ ///
+ ///
+ ///
+ private void LinkLabelClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+ LinkLabel linkLabel = sender as LinkLabel;
+ if (linkLabel != null) {
+ try {
+ linkLabel.LinkVisited = true;
+ Process.Start(linkLabel.Text);
+ } catch (Exception) {
+ MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, linkLabel.Text), Language.GetString(LangKey.error));
+ }
+ }
+ }
+
+ ///
+ /// Called from the AnimatingForm, for every frame
+ ///
+ protected override void Animate() {
+ if (_bitmap == null) {
+ return;
+ }
+ if (!IsTerminalServerSession) {
+ // Color cycle
+ if (_waitFrames != 0) {
+ _waitFrames--;
+ // Check if there is something else to do, if not we return so we don't occupy the CPU
+ if (!_hasAnimationsLeft) {
+ return;
+ }
+ } else if (_scrollCount < _pixelColors.Count + _colorFlow.Count) {
+ // Scroll colors, the scrollCount is the amount of pixels + the amount of colors to cycle.
+ for (int index = _pixelColors.Count - 1; index > 0; index--) {
+ _pixelColors[index] = _pixelColors[index - 1];
+ }
+ // Keep adding from the colors to cycle until there is nothing left
+ if (_colorIndex < _colorFlow.Count) {
+ _pixelColors[0] = _colorFlow[_colorIndex++];
+ }
+ _scrollCount++;
+ } else {
+ // Reset values, wait X time for the next one
+ _waitFrames = FramesForMillis(3000 + _rand.Next(35000));
+ _colorIndex = 0;
+ _scrollCount = 0;
+ // Check if there is something else to do, if not we return so we don't occupy the CPU
+ if (!_hasAnimationsLeft) {
+ return;
+ }
+ }
+ } else if (!_hasAnimationsLeft) {
+ return;
+ }
+
+ // Draw the "G"
+ using (Graphics graphics = Graphics.FromImage(_bitmap)) {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ graphics.Clear(_backgroundAnimation.Next());
+
+ graphics.TranslateTransform(2, -2);
+ graphics.RotateTransform(20);
+
+ using (SolidBrush brush = new SolidBrush(_pixelColor)) {
+ int index = 0;
+ // We asume there is nothing to animate in the next Animate loop
+ _hasAnimationsLeft = false;
+ // Pixels of the G
+ foreach (RectangleAnimator pixel in _pixels) {
+ brush.Color = _pixelColors[index++];
+ graphics.FillEllipse(brush, pixel.Current);
+ // If a pixel still has frames left, the hasAnimationsLeft will be true
+ _hasAnimationsLeft = _hasAnimationsLeft | pixel.HasNext;
+ pixel.Next();
+ }
+ }
+ }
+ pictureBox1.Invalidate();
+ }
+
+ ///
+ /// CmdKey handler
+ ///
+ ///
+ ///
+ ///
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
+ try {
+ switch (keyData) {
+ case Keys.Escape:
+ DialogResult = DialogResult.Cancel;
+ break;
+ case Keys.E:
+ MessageBox.Show(EnvironmentInfo.EnvironmentToString(true));
+ break;
+ case Keys.L:
+ try {
+ if (File.Exists(MainForm.LogFileLocation)) {
+ using (Process.Start("\"" + MainForm.LogFileLocation + "\"")) {
+ // nothing to do, just using dispose to cleanup
+ }
+ } else {
+ MessageBox.Show("Greenshot can't find the logfile, it should have been here: " + MainForm.LogFileLocation);
+ }
+ } catch (Exception) {
+ MessageBox.Show("Couldn't open the greenshot.log, it's located here: " + MainForm.LogFileLocation, "Error opening greeenshot.log", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
+ }
+ break;
+ case Keys.I:
+ try {
+ using (Process.Start("\"" + IniConfig.ConfigLocation + "\"")) {
+ }
+ } catch (Exception) {
+ MessageBox.Show("Couldn't open the greenshot.ini, it's located here: " + IniConfig.ConfigLocation, "Error opening greeenshot.ini", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
+ }
+ break;
+ default:
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+ } catch (Exception ex) {
+ LOG.Error(string.Format("Error handling key '{0}'", keyData), ex);
+ }
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Greenshot/Forms/AnimatingBaseForm.cs b/Greenshot/Forms/AnimatingBaseForm.cs
new file mode 100644
index 000000000..c97780417
--- /dev/null
+++ b/Greenshot/Forms/AnimatingBaseForm.cs
@@ -0,0 +1,30 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace Greenshot {
+ ///
+ /// This class is only here to help in the Designer mode, so it's clear where the language files are
+ ///
+ public class AnimatingBaseForm : AnimatingForm {
+ }
+}
diff --git a/Greenshot/Forms/BaseForm.cs b/Greenshot/Forms/BaseForm.cs
new file mode 100644
index 000000000..532f42bc9
--- /dev/null
+++ b/Greenshot/Forms/BaseForm.cs
@@ -0,0 +1,30 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace Greenshot {
+ ///
+ /// This class is only here to help in the Designer mode, so it's clear where the language files are
+ ///
+ public class BaseForm : GreenshotForm {
+ }
+}
diff --git a/src/Greenshot/Forms/BugReportForm.Designer.cs b/Greenshot/Forms/BugReportForm.Designer.cs
similarity index 87%
rename from src/Greenshot/Forms/BugReportForm.Designer.cs
rename to Greenshot/Forms/BugReportForm.Designer.cs
index 74787d03c..48d06fdc1 100644
--- a/src/Greenshot/Forms/BugReportForm.Designer.cs
+++ b/Greenshot/Forms/BugReportForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,11 +16,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
namespace Greenshot.Forms {
partial class BugReportForm {
///
@@ -49,9 +46,9 @@ namespace Greenshot.Forms {
///
private void InitializeComponent()
{
- this.labelBugReportInfo = new GreenshotLabel();
+ this.labelBugReportInfo = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBoxDescription = new System.Windows.Forms.TextBox();
- this.btnClose = new GreenshotButton();
+ this.btnClose = new GreenshotPlugin.Controls.GreenshotButton();
this.linkLblBugs = new System.Windows.Forms.LinkLabel();
this.SuspendLayout();
//
@@ -94,7 +91,7 @@ namespace Greenshot.Forms {
this.linkLblBugs.Size = new System.Drawing.Size(465, 23);
this.linkLblBugs.TabIndex = 9;
this.linkLblBugs.TabStop = true;
- this.linkLblBugs.Text = "https://getgreenshot.org/tickets/";
+ this.linkLblBugs.Text = "http://getgreenshot.org/tickets/";
this.linkLblBugs.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLblBugsLinkClicked);
//
// BugReportForm
@@ -115,8 +112,8 @@ namespace Greenshot.Forms {
}
private System.Windows.Forms.LinkLabel linkLblBugs;
- private GreenshotButton btnClose;
+ private GreenshotPlugin.Controls.GreenshotButton btnClose;
private System.Windows.Forms.TextBox textBoxDescription;
- private GreenshotLabel labelBugReportInfo;
+ private GreenshotPlugin.Controls.GreenshotLabel labelBugReportInfo;
}
}
diff --git a/Greenshot/Forms/BugReportForm.cs b/Greenshot/Forms/BugReportForm.cs
new file mode 100644
index 000000000..9cf72b968
--- /dev/null
+++ b/Greenshot/Forms/BugReportForm.cs
@@ -0,0 +1,54 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Diagnostics;
+using System.Windows.Forms;
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Forms {
+ public partial class BugReportForm : BaseForm {
+ private BugReportForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ ToFront = true;
+ }
+
+ public BugReportForm(string bugText) : this() {
+ textBoxDescription.Text = bugText;
+ }
+
+ private void LinkLblBugsLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+ openLink((LinkLabel)sender);
+ }
+
+ private void openLink(LinkLabel link) {
+ try {
+ link.LinkVisited = true;
+ Process.Start(link.Text);
+ } catch (Exception) {
+ MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, link.Text), Language.GetString(LangKey.error));
+ }
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/CaptureForm.Designer.cs b/Greenshot/Forms/CaptureForm.Designer.cs
similarity index 85%
rename from src/Greenshot/Forms/CaptureForm.Designer.cs
rename to Greenshot/Forms/CaptureForm.Designer.cs
index c6aaf8daa..5ec1d8903 100644
--- a/src/Greenshot/Forms/CaptureForm.Designer.cs
+++ b/Greenshot/Forms/CaptureForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
namespace Greenshot.Forms {
partial class CaptureForm {
@@ -55,8 +55,8 @@ namespace Greenshot.Forms {
//
// CaptureForm
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(0, 0);
this.Cursor = System.Windows.Forms.Cursors.Cross;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs
new file mode 100644
index 000000000..7af509c03
--- /dev/null
+++ b/Greenshot/Forms/CaptureForm.cs
@@ -0,0 +1,862 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing;
+using Greenshot.Helpers;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Globalization;
+using System.Security.Permissions;
+using System.Windows.Forms;
+
+namespace Greenshot.Forms {
+ ///
+ /// The capture form is used to select a part of the capture
+ ///
+ public sealed partial class CaptureForm : AnimatingForm {
+ private enum FixMode {None, Initiated, Horizontal, Vertical};
+
+ private static readonly ILog Log = LogManager.GetLogger(typeof(CaptureForm));
+ private static readonly CoreConfiguration Conf = IniConfig.GetIniSection();
+ private static readonly Brush GreenOverlayBrush = new SolidBrush(Color.FromArgb(50, Color.MediumSeaGreen));
+ private static readonly Pen OverlayPen = new Pen(Color.FromArgb(50, Color.Black));
+ private static CaptureForm _currentForm;
+ private static readonly Brush BackgroundBrush;
+
+ ///
+ /// Initialize the background brush
+ ///
+ static CaptureForm() {
+ Image backgroundForTransparency = GreenshotResources.getImage("Checkerboard.Image");
+ BackgroundBrush = new TextureBrush(backgroundForTransparency, WrapMode.Tile);
+ }
+
+ private int _mX;
+ private int _mY;
+ private Point _mouseMovePos = Point.Empty;
+ private Point _cursorPos;
+ private CaptureMode _captureMode;
+ private readonly List _windows;
+ private WindowDetails _selectedCaptureWindow;
+ private bool _mouseDown;
+ private Rectangle _captureRect = Rectangle.Empty;
+ private readonly ICapture _capture;
+ private Point _previousMousePos = Point.Empty;
+ private FixMode _fixMode = FixMode.None;
+ private RectangleAnimator _windowAnimator;
+ private RectangleAnimator _zoomAnimator;
+ private readonly bool _isZoomerTransparent = Conf.ZoomerOpacity < 1;
+ private bool _isCtrlPressed;
+ private bool _showDebugInfo;
+
+ ///
+ /// Property to access the selected capture rectangle
+ ///
+ public Rectangle CaptureRectangle => _captureRect;
+
+ ///
+ /// Property to access the used capture mode
+ ///
+ public CaptureMode UsedCaptureMode => _captureMode;
+
+ ///
+ /// Get the selected window
+ ///
+ public WindowDetails SelectedCaptureWindow => _selectedCaptureWindow;
+
+ ///
+ /// This should prevent childs to draw backgrounds
+ ///
+ protected override CreateParams CreateParams {
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ get {
+ CreateParams createParams = base.CreateParams;
+ createParams.ExStyle |= 0x02000000;
+ return createParams;
+ }
+ }
+
+ private void ClosedHandler(object sender, EventArgs e) {
+ _currentForm = null;
+ Log.Debug("Remove CaptureForm from currentForm");
+ }
+
+ private void ClosingHandler(object sender, EventArgs e) {
+ Log.Debug("Closing captureform");
+ WindowDetails.UnregisterIgnoreHandle(Handle);
+ }
+
+ ///
+ /// This creates the capture form
+ ///
+ ///
+ ///
+ public CaptureForm(ICapture capture, List windows) {
+ if (_currentForm != null) {
+ Log.Warn("Found currentForm, Closing already opened CaptureForm");
+ _currentForm.Close();
+ _currentForm = null;
+ Application.DoEvents();
+ }
+ _currentForm = this;
+
+ // Enable the AnimatingForm
+ EnableAnimation = true;
+
+ // clean up
+ FormClosed += ClosedHandler;
+
+ _capture = capture;
+ _windows = windows;
+ _captureMode = capture.CaptureDetails.CaptureMode;
+
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ // Only double-buffer when we are not in a TerminalServerSession
+ DoubleBuffered = !IsTerminalServerSession;
+ Text = "Greenshot capture form";
+
+ // Make sure we never capture the captureform
+ WindowDetails.RegisterIgnoreHandle(Handle);
+ // Unregister at close
+ FormClosing += ClosingHandler;
+
+ // set cursor location
+ _cursorPos = WindowCapture.GetCursorLocationRelativeToScreenBounds();
+
+ // Initialize the animations, the window capture zooms out from the cursor to the window under the cursor
+ if (_captureMode == CaptureMode.Window) {
+ _windowAnimator = new RectangleAnimator(new Rectangle(_cursorPos, Size.Empty), _captureRect, FramesForMillis(700), EasingType.Quintic, EasingMode.EaseOut);
+ }
+
+ // Set the zoomer animation
+ InitializeZoomer(Conf.ZoomerEnabled);
+
+ SuspendLayout();
+ Bounds = capture.ScreenBounds;
+ ResumeLayout();
+
+ // Fix missing focus
+ ToFront = true;
+ TopMost = true;
+ }
+
+ ///
+ /// Create an animation for the zoomer, depending on if it's active or not.
+ ///
+ private void InitializeZoomer(bool isOn) {
+ if (isOn) {
+ // Initialize the zoom with a invalid position
+ _zoomAnimator = new RectangleAnimator(Rectangle.Empty, new Rectangle(int.MaxValue, int.MaxValue, 0, 0), FramesForMillis(1000), EasingType.Quintic, EasingMode.EaseOut);
+ VerifyZoomAnimation(_cursorPos, false);
+ }
+ else
+ {
+ _zoomAnimator?.ChangeDestination(new Rectangle(Point.Empty, Size.Empty), FramesForMillis(1000));
+ }
+ }
+
+ #region key handling
+
+ private void CaptureFormKeyUp(object sender, KeyEventArgs e) {
+ switch(e.KeyCode) {
+ case Keys.ShiftKey:
+ _fixMode = FixMode.None;
+ break;
+ case Keys.ControlKey:
+ _isCtrlPressed = false;
+ break;
+ }
+ }
+
+ ///
+ /// Handle the key down event
+ ///
+ ///
+ ///
+ private void CaptureFormKeyDown(object sender, KeyEventArgs e) {
+ int step = _isCtrlPressed ? 10 : 1;
+
+ switch (e.KeyCode) {
+ case Keys.Up:
+ Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y - step);
+ break;
+ case Keys.Down:
+ Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + step);
+ break;
+ case Keys.Left:
+ Cursor.Position = new Point(Cursor.Position.X - step, Cursor.Position.Y);
+ break;
+ case Keys.Right:
+ Cursor.Position = new Point(Cursor.Position.X + step, Cursor.Position.Y);
+ break;
+ case Keys.ShiftKey:
+ // Fixmode
+ if (_fixMode == FixMode.None) {
+ _fixMode = FixMode.Initiated;
+ }
+ break;
+ case Keys.ControlKey:
+ _isCtrlPressed = true;
+ break;
+ case Keys.Escape:
+ // Cancel
+ DialogResult = DialogResult.Cancel;
+ break;
+ case Keys.M:
+ // Toggle mouse cursor
+ _capture.CursorVisible = !_capture.CursorVisible;
+ Invalidate();
+ break;
+ //// TODO: Enable when the screen capture code works reliable
+ //case Keys.V:
+ // // Video
+ // if (capture.CaptureDetails.CaptureMode != CaptureMode.Video) {
+ // capture.CaptureDetails.CaptureMode = CaptureMode.Video;
+ // } else {
+ // capture.CaptureDetails.CaptureMode = captureMode;
+ // }
+ // Invalidate();
+ // break;
+ case Keys.Z:
+ if (_captureMode == CaptureMode.Region) {
+ // Toggle zoom
+ Conf.ZoomerEnabled = !Conf.ZoomerEnabled;
+ InitializeZoomer(Conf.ZoomerEnabled);
+ Invalidate();
+ }
+ break;
+ case Keys.D:
+ if (_captureMode == CaptureMode.Window)
+ {
+ // Toggle debug
+ _showDebugInfo = !_showDebugInfo;
+ Invalidate();
+ }
+ break;
+ case Keys.Space:
+ // Toggle capture mode
+ switch (_captureMode) {
+ case CaptureMode.Region:
+ // Set the window capture mode
+ _captureMode = CaptureMode.Window;
+ // "Fade out" Zoom
+ InitializeZoomer(false);
+ // "Fade in" window
+ _windowAnimator = new RectangleAnimator(new Rectangle(_cursorPos, Size.Empty), _captureRect, FramesForMillis(700), EasingType.Quintic, EasingMode.EaseOut);
+ _captureRect = Rectangle.Empty;
+ Invalidate();
+ break;
+ case CaptureMode.Window:
+ // Set the region capture mode
+ _captureMode = CaptureMode.Region;
+ // "Fade out" window
+ _windowAnimator.ChangeDestination(new Rectangle(_cursorPos, Size.Empty), FramesForMillis(700));
+ // Fade in zoom
+ InitializeZoomer(Conf.ZoomerEnabled);
+ _captureRect = Rectangle.Empty;
+ Invalidate();
+ break;
+ }
+ _selectedCaptureWindow = null;
+ OnMouseMove(this, new MouseEventArgs(MouseButtons.None, 0, Cursor.Position.X, Cursor.Position.Y, 0));
+ break;
+ case Keys.Return:
+ // Confirm
+ if (_captureMode == CaptureMode.Window) {
+ DialogResult = DialogResult.OK;
+ } else if (!_mouseDown) {
+ HandleMouseDown();
+ } else if (_mouseDown) {
+ HandleMouseUp();
+ }
+ break;
+ case Keys.F:
+ ToFront = !ToFront;
+ TopMost = !TopMost;
+ break;
+ }
+ }
+ #endregion
+
+ #region events
+ ///
+ /// The mousedown handler of the capture form
+ ///
+ ///
+ ///
+ private void OnMouseDown(object sender, MouseEventArgs e) {
+ if (e.Button == MouseButtons.Left) {
+ HandleMouseDown();
+ }
+ }
+
+ private void HandleMouseDown() {
+ Point tmpCursorLocation = WindowCapture.GetCursorLocationRelativeToScreenBounds();
+ _mX = tmpCursorLocation.X;
+ _mY = tmpCursorLocation.Y;
+ _mouseDown = true;
+ OnMouseMove(this, null);
+ Invalidate();
+ }
+
+ private void HandleMouseUp() {
+ // If the mouse goes up we set down to false (nice logic!)
+ _mouseDown = false;
+ // Check if anything is selected
+ if (_captureMode == CaptureMode.Window && _selectedCaptureWindow != null) {
+ // Go and process the capture
+ DialogResult = DialogResult.OK;
+ } else if (_captureRect.Height > 0 && _captureRect.Width > 0) {
+ // correct the GUI width to real width if Region mode
+ if (_captureMode == CaptureMode.Region) {
+ _captureRect.Width += 1;
+ _captureRect.Height += 1;
+ }
+ // Go and process the capture
+ DialogResult = DialogResult.OK;
+ } else {
+ Invalidate();
+ }
+
+ }
+
+ ///
+ /// The mouse up handler of the capture form
+ ///
+ ///
+ ///
+ private void OnMouseUp(object sender, MouseEventArgs e) {
+ if (_mouseDown) {
+ HandleMouseUp();
+ }
+ }
+
+ ///
+ /// This method is used to "fix" the mouse coordinates when keeping shift/ctrl pressed
+ ///
+ ///
+ ///
+ private Point FixMouseCoordinates(Point currentMouse) {
+ if (_fixMode == FixMode.Initiated) {
+ if (_previousMousePos.X != currentMouse.X) {
+ _fixMode = FixMode.Vertical;
+ } else if (_previousMousePos.Y != currentMouse.Y) {
+ _fixMode = FixMode.Horizontal;
+ }
+ } else if (_fixMode == FixMode.Vertical) {
+ currentMouse = new Point(currentMouse.X, _previousMousePos.Y);
+ } else if (_fixMode == FixMode.Horizontal) {
+ currentMouse = new Point(_previousMousePos.X, currentMouse.Y);
+ }
+ _previousMousePos = currentMouse;
+ return currentMouse;
+ }
+
+ ///
+ /// The mouse move handler of the capture form
+ ///
+ ///
+ ///
+ private void OnMouseMove(object sender, MouseEventArgs e) {
+ // Make sure the mouse coordinates are fixed, when pressing shift
+ _mouseMovePos = FixMouseCoordinates(User32.GetCursorLocation());
+ _mouseMovePos = WindowCapture.GetLocationRelativeToScreenBounds(_mouseMovePos);
+ }
+
+ ///
+ /// Helper method to simplify check
+ ///
+ ///
+ ///
+ private bool IsAnimating(IAnimator animator) {
+ if (animator == null) {
+ return false;
+ }
+ return animator.HasNext;
+ }
+
+ ///
+ /// update the frame, this only invalidates
+ ///
+ protected override void Animate() {
+ Point lastPos = _cursorPos;
+ _cursorPos = _mouseMovePos;
+
+ if (_selectedCaptureWindow != null && lastPos.Equals(_cursorPos) && !IsAnimating(_zoomAnimator) && !IsAnimating(_windowAnimator)) {
+ return;
+ }
+
+ WindowDetails lastWindow = _selectedCaptureWindow;
+ bool horizontalMove = false;
+ bool verticalMove = false;
+
+ if (lastPos.X != _cursorPos.X) {
+ horizontalMove = true;
+ }
+ if (lastPos.Y != _cursorPos.Y) {
+ verticalMove = true;
+ }
+
+ if (_captureMode == CaptureMode.Region && _mouseDown) {
+ _captureRect = GuiRectangle.GetGuiRectangle(_cursorPos.X, _cursorPos.Y, _mX - _cursorPos.X, _mY - _cursorPos.Y);
+ }
+
+ // Iterate over the found windows and check if the current location is inside a window
+ Point cursorPosition = Cursor.Position;
+ _selectedCaptureWindow = null;
+ lock (_windows) {
+ foreach (var window in _windows) {
+ if (!window.Contains(cursorPosition))
+ {
+ continue;
+ }
+ // Only go over the children if we are in window mode
+ _selectedCaptureWindow = CaptureMode.Window == _captureMode ? window.FindChildUnderPoint(cursorPosition) : window;
+ break;
+ }
+ }
+
+ if (_selectedCaptureWindow != null && !_selectedCaptureWindow.Equals(lastWindow)) {
+ _capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
+ _capture.CaptureDetails.AddMetaData("windowtitle", _selectedCaptureWindow.Text);
+ if (_captureMode == CaptureMode.Window) {
+ // Here we want to capture the window which is under the mouse
+ _captureRect = _selectedCaptureWindow.WindowRectangle;
+ // As the ClientRectangle is not in Bitmap coordinates, we need to correct.
+ _captureRect.Offset(-_capture.ScreenBounds.Location.X, -_capture.ScreenBounds.Location.Y);
+ }
+ }
+
+ Rectangle invalidateRectangle;
+ if (_mouseDown && (_captureMode != CaptureMode.Window)) {
+ int x1 = Math.Min(_mX, lastPos.X);
+ int x2 = Math.Max(_mX, lastPos.X);
+ int y1 = Math.Min(_mY, lastPos.Y);
+ int y2 = Math.Max(_mY, lastPos.Y);
+ x1= Math.Min(x1, _cursorPos.X);
+ x2= Math.Max(x2, _cursorPos.X);
+ y1= Math.Min(y1, _cursorPos.Y);
+ y2= Math.Max(y2, _cursorPos.Y);
+
+ // Safety correction
+ x2 += 2;
+ y2 += 2;
+
+ // Here we correct for text-size
+
+ // Calculate the size
+ int textForWidth = Math.Max(Math.Abs(_mX - _cursorPos.X), Math.Abs(_mX - lastPos.X));
+ int textForHeight = Math.Max(Math.Abs(_mY - _cursorPos.Y), Math.Abs(_mY - lastPos.Y));
+
+ using (Font rulerFont = new Font(FontFamily.GenericSansSerif, 8)) {
+ Size measureWidth = TextRenderer.MeasureText(textForWidth.ToString(CultureInfo.InvariantCulture), rulerFont);
+ x1 -= measureWidth.Width + 15;
+
+ Size measureHeight = TextRenderer.MeasureText(textForHeight.ToString(CultureInfo.InvariantCulture), rulerFont);
+ y1 -= measureHeight.Height + 10;
+ }
+ invalidateRectangle = new Rectangle(x1,y1, x2-x1, y2-y1);
+ Invalidate(invalidateRectangle);
+ } else if (_captureMode != CaptureMode.Window) {
+ if (!IsTerminalServerSession) {
+ Rectangle allScreenBounds = WindowCapture.GetScreenBounds();
+ allScreenBounds.Location = WindowCapture.GetLocationRelativeToScreenBounds(allScreenBounds.Location);
+ if (verticalMove) {
+ // Before
+ invalidateRectangle = GuiRectangle.GetGuiRectangle(allScreenBounds.Left, lastPos.Y - 2, Width + 2, 45);
+ Invalidate(invalidateRectangle);
+ // After
+ invalidateRectangle = GuiRectangle.GetGuiRectangle(allScreenBounds.Left, _cursorPos.Y - 2, Width + 2, 45);
+ Invalidate(invalidateRectangle);
+ }
+ if (horizontalMove) {
+ // Before
+ invalidateRectangle = GuiRectangle.GetGuiRectangle(lastPos.X - 2, allScreenBounds.Top, 75, Height + 2);
+ Invalidate(invalidateRectangle);
+ // After
+ invalidateRectangle = GuiRectangle.GetGuiRectangle(_cursorPos.X - 2, allScreenBounds.Top, 75, Height + 2);
+ Invalidate(invalidateRectangle);
+ }
+ }
+ } else {
+ if (_selectedCaptureWindow != null && !_selectedCaptureWindow.Equals(lastWindow)) {
+ // Window changes, make new animation from current to target
+ _windowAnimator.ChangeDestination(_captureRect, FramesForMillis(700));
+ }
+ }
+ // always animate the Window area through to the last frame, so we see the fade-in/out untill the end
+ // Using a safety "offset" to make sure the text is invalidated too
+ const int safetySize = 30;
+ // Check if the animation needs to be drawn
+ if (IsAnimating(_windowAnimator)) {
+ invalidateRectangle = _windowAnimator.Current;
+ invalidateRectangle.Inflate(safetySize, safetySize);
+ Invalidate(invalidateRectangle);
+ invalidateRectangle = _windowAnimator.Next();
+ invalidateRectangle.Inflate(safetySize, safetySize);
+ Invalidate(invalidateRectangle);
+ // Check if this was the last of the windows animations in the normal region capture.
+ if (_captureMode != CaptureMode.Window && !IsAnimating(_windowAnimator)) {
+ Invalidate();
+ }
+ }
+
+ if (_zoomAnimator != null && (IsAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) {
+ // Make sure we invalidate the old zoom area
+ invalidateRectangle = _zoomAnimator.Current;
+ invalidateRectangle.Offset(lastPos);
+ Invalidate(invalidateRectangle);
+ // Only verify if we are really showing the zoom, not the outgoing animation
+ if (Conf.ZoomerEnabled && _captureMode != CaptureMode.Window) {
+ VerifyZoomAnimation(_cursorPos, false);
+ }
+ // The following logic is not needed, next always returns the current if there are no frames left
+ // but it makes more sense if we want to change something in the logic
+ invalidateRectangle = IsAnimating(_zoomAnimator) ? _zoomAnimator.Next() : _zoomAnimator.Current;
+ invalidateRectangle.Offset(_cursorPos);
+ Invalidate(invalidateRectangle);
+ }
+ // Force update "now"
+ Update();
+ }
+
+ ///
+ /// This makes sure there is no background painted, as we have complete "paint" control it doesn't make sense to do otherwise.
+ ///
+ ///
+ protected override void OnPaintBackground(PaintEventArgs pevent) {
+ }
+
+ ///
+ /// Checks if the Zoom area can move there where it wants to go, change direction if not.
+ ///
+ /// preferred destination location for the zoom area
+ /// false to try to find a location which is neither out of screen bounds nor intersects with the selected rectangle
+ private void VerifyZoomAnimation(Point pos, bool allowZoomOverCaptureRect) {
+ Rectangle screenBounds = Screen.GetBounds(MousePosition);
+ // convert to be relative to top left corner of all screen bounds
+ screenBounds.Location = WindowCapture.GetLocationRelativeToScreenBounds(screenBounds.Location);
+ int relativeZoomSize = Math.Min(screenBounds.Width, screenBounds.Height) / 5;
+ // Make sure the final size is a plural of 4, this makes it look better
+ relativeZoomSize = relativeZoomSize - relativeZoomSize % 4;
+ Size zoomSize = new Size(relativeZoomSize, relativeZoomSize);
+ Point zoomOffset = new Point(20, 20);
+
+ Rectangle targetRectangle = _zoomAnimator.Final;
+ targetRectangle.Offset(pos);
+ if (!screenBounds.Contains(targetRectangle) || (!allowZoomOverCaptureRect && _captureRect.IntersectsWith(targetRectangle))) {
+ Point destinationLocation = Point.Empty;
+ Rectangle tl = new Rectangle(pos.X - (zoomOffset.X + zoomSize.Width), pos.Y - (zoomOffset.Y + zoomSize.Height), zoomSize.Width, zoomSize.Height);
+ Rectangle tr = new Rectangle(pos.X + zoomOffset.X, pos.Y - (zoomOffset.Y + zoomSize.Height), zoomSize.Width, zoomSize.Height);
+ Rectangle bl = new Rectangle(pos.X - (zoomOffset.X + zoomSize.Width), pos.Y + zoomOffset.Y, zoomSize.Width, zoomSize.Height);
+ Rectangle br = new Rectangle(pos.X + zoomOffset.X, pos.Y + zoomOffset.Y, zoomSize.Width, zoomSize.Height);
+ if (screenBounds.Contains(br) && (allowZoomOverCaptureRect || !_captureRect.IntersectsWith(br))) {
+ destinationLocation = new Point(zoomOffset.X, zoomOffset.Y);
+ } else if (screenBounds.Contains(bl) && (allowZoomOverCaptureRect || !_captureRect.IntersectsWith(bl))) {
+ destinationLocation = new Point(-zoomOffset.X - zoomSize.Width, zoomOffset.Y);
+ } else if (screenBounds.Contains(tr) && (allowZoomOverCaptureRect || !_captureRect.IntersectsWith(tr))) {
+ destinationLocation = new Point(zoomOffset.X, -zoomOffset.Y - zoomSize.Width);
+ } else if (screenBounds.Contains(tl) && (allowZoomOverCaptureRect || !_captureRect.IntersectsWith(tl))) {
+ destinationLocation = new Point(-zoomOffset.X - zoomSize.Width, -zoomOffset.Y - zoomSize.Width);
+ }
+ if (destinationLocation == Point.Empty && !allowZoomOverCaptureRect) {
+ VerifyZoomAnimation(pos, true);
+ } else {
+ _zoomAnimator.ChangeDestination(new Rectangle(destinationLocation, zoomSize));
+ }
+ }
+ }
+
+ ///
+ /// Draw the zoomed area
+ ///
+ ///
+ ///
+ ///
+ private void DrawZoom(Graphics graphics, Rectangle sourceRectangle, Rectangle destinationRectangle) {
+ if (_capture.Image == null) {
+ return;
+ }
+ ImageAttributes attributes;
+
+ if (_isZoomerTransparent) {
+ //create a color matrix object to change the opacy
+ ColorMatrix opacyMatrix = new ColorMatrix
+ {
+ Matrix33 = Conf.ZoomerOpacity
+ };
+ attributes = new ImageAttributes();
+ attributes.SetColorMatrix(opacyMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
+ } else {
+ attributes = null;
+ }
+
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.CompositingQuality = CompositingQuality.HighSpeed;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ using (GraphicsPath path = new GraphicsPath()) {
+ path.AddEllipse(destinationRectangle);
+ graphics.SetClip(path);
+ if (!_isZoomerTransparent) {
+ graphics.FillRectangle(BackgroundBrush, destinationRectangle);
+ graphics.DrawImage(_capture.Image, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel);
+ } else {
+ graphics.DrawImage(_capture.Image, destinationRectangle, sourceRectangle.X, sourceRectangle.Y, sourceRectangle.Width, sourceRectangle.Height, GraphicsUnit.Pixel, attributes);
+ }
+ }
+ int alpha = (int)(255 * Conf.ZoomerOpacity);
+ Color opacyWhite = Color.FromArgb(alpha, 255, 255, 255);
+ Color opacyBlack = Color.FromArgb(alpha, 0, 0, 0);
+
+ // Draw the circle around the zoomer
+ using (Pen pen = new Pen(opacyWhite, 2)) {
+ graphics.DrawEllipse(pen, destinationRectangle);
+ }
+
+ // Make sure we don't have a pixeloffsetmode/smoothingmode when drawing the crosshair
+ graphics.SmoothingMode = SmoothingMode.None;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+
+ // Calculate some values
+ int pixelThickness = destinationRectangle.Width / sourceRectangle.Width;
+ int halfWidth = destinationRectangle.Width / 2;
+ int halfWidthEnd = destinationRectangle.Width / 2 - pixelThickness / 2;
+ int halfHeight = destinationRectangle.Height / 2;
+ int halfHeightEnd = destinationRectangle.Height / 2 - pixelThickness / 2;
+
+ int drawAtHeight = destinationRectangle.Y + halfHeight;
+ int drawAtWidth = destinationRectangle.X + halfWidth;
+ int padding = pixelThickness;
+
+ // Pen to draw
+ using (Pen pen = new Pen(opacyBlack, pixelThickness)) {
+ // Draw the croshair-lines
+ // Vertical top to middle
+ graphics.DrawLine(pen, drawAtWidth, destinationRectangle.Y + padding, drawAtWidth, destinationRectangle.Y + halfHeightEnd - padding);
+ // Vertical middle + 1 to bottom
+ graphics.DrawLine(pen, drawAtWidth, destinationRectangle.Y + halfHeightEnd + 2 * padding, drawAtWidth, destinationRectangle.Y + destinationRectangle.Width - padding);
+ // Horizontal left to middle
+ graphics.DrawLine(pen, destinationRectangle.X + padding, drawAtHeight, destinationRectangle.X + halfWidthEnd - padding, drawAtHeight);
+ // Horizontal middle + 1 to right
+ graphics.DrawLine(pen, destinationRectangle.X + halfWidthEnd + 2 * padding, drawAtHeight, destinationRectangle.X + destinationRectangle.Width - padding, drawAtHeight);
+
+ // Fix offset for drawing the white rectangle around the crosshair-lines
+ drawAtHeight -= pixelThickness / 2;
+ drawAtWidth -= pixelThickness / 2;
+ // Fix off by one error with the DrawRectangle
+ pixelThickness -= 1;
+ // Change the color and the pen width
+ pen.Color = opacyWhite;
+ pen.Width = 1;
+ // Vertical top to middle
+ graphics.DrawRectangle(pen, drawAtWidth, destinationRectangle.Y + padding, pixelThickness, halfHeightEnd - 2 * padding - 1);
+ // Vertical middle + 1 to bottom
+ graphics.DrawRectangle(pen, drawAtWidth, destinationRectangle.Y + halfHeightEnd + 2 * padding, pixelThickness, halfHeightEnd - 2 * padding - 1);
+ // Horizontal left to middle
+ graphics.DrawRectangle(pen, destinationRectangle.X + padding, drawAtHeight, halfWidthEnd - 2 * padding - 1, pixelThickness);
+ // Horizontal middle + 1 to right
+ graphics.DrawRectangle(pen, destinationRectangle.X + halfWidthEnd + 2 * padding, drawAtHeight, halfWidthEnd - 2 * padding - 1, pixelThickness);
+ }
+ attributes?.Dispose();
+ }
+
+ ///
+ /// Paint the actual visible parts
+ ///
+ ///
+ ///
+ private void OnPaint(object sender, PaintEventArgs e) {
+ Graphics graphics = e.Graphics;
+ Rectangle clipRectangle = e.ClipRectangle;
+ //graphics.BitBlt((Bitmap)buffer, Point.Empty);
+ graphics.DrawImageUnscaled(_capture.Image, Point.Empty);
+ // Only draw Cursor if it's (partly) visible
+ if (_capture.Cursor != null && _capture.CursorVisible && clipRectangle.IntersectsWith(new Rectangle(_capture.CursorLocation, _capture.Cursor.Size))) {
+ graphics.DrawIcon(_capture.Cursor, _capture.CursorLocation.X, _capture.CursorLocation.Y);
+ }
+
+ if (_mouseDown || _captureMode == CaptureMode.Window || IsAnimating(_windowAnimator)) {
+ _captureRect.Intersect(new Rectangle(Point.Empty, _capture.ScreenBounds.Size)); // crop what is outside the screen
+
+ var fixedRect = IsAnimating(_windowAnimator) ? _windowAnimator.Current : _captureRect;
+
+ // TODO: enable when the screen capture code works reliable
+ //if (capture.CaptureDetails.CaptureMode == CaptureMode.Video) {
+ // graphics.FillRectangle(RedOverlayBrush, fixedRect);
+ //} else {
+ graphics.FillRectangle(GreenOverlayBrush, fixedRect);
+ //}
+ graphics.DrawRectangle(OverlayPen, fixedRect);
+
+ // rulers
+ const int dist = 8;
+
+ string captureWidth;
+ string captureHeight;
+ // The following fixes the very old incorrect size information bug
+ if (_captureMode == CaptureMode.Window) {
+ captureWidth = _captureRect.Width.ToString(CultureInfo.InvariantCulture);
+ captureHeight = _captureRect.Height.ToString(CultureInfo.InvariantCulture);
+ } else {
+ captureWidth = (_captureRect.Width + 1).ToString(CultureInfo.InvariantCulture);
+ captureHeight = (_captureRect.Height + 1).ToString(CultureInfo.InvariantCulture);
+ }
+ using (Font rulerFont = new Font(FontFamily.GenericSansSerif, 8)) {
+ Size measureWidth = TextRenderer.MeasureText(captureWidth, rulerFont);
+ Size measureHeight = TextRenderer.MeasureText(captureHeight, rulerFont);
+ int hSpace = measureWidth.Width + 3;
+ int vSpace = measureHeight.Height + 3;
+ Brush bgBrush = new SolidBrush(Color.FromArgb(200, 217, 240, 227));
+ Pen rulerPen = new Pen(Color.SeaGreen);
+
+ // horizontal ruler
+ if (fixedRect.Width > hSpace + 3) {
+ using (GraphicsPath p = RoundedRectangle.Create2(
+ fixedRect.X + (fixedRect.Width / 2 - hSpace / 2) + 3,
+ fixedRect.Y - dist - 7,
+ measureWidth.Width - 3,
+ measureWidth.Height,
+ 3)) {
+ graphics.FillPath(bgBrush, p);
+ graphics.DrawPath(rulerPen, p);
+ graphics.DrawString(captureWidth, rulerFont, rulerPen.Brush, fixedRect.X + (fixedRect.Width / 2 - hSpace / 2) + 3, fixedRect.Y - dist - 7);
+ graphics.DrawLine(rulerPen, fixedRect.X, fixedRect.Y - dist, fixedRect.X + (fixedRect.Width / 2 - hSpace / 2), fixedRect.Y - dist);
+ graphics.DrawLine(rulerPen, fixedRect.X + fixedRect.Width / 2 + hSpace / 2, fixedRect.Y - dist, fixedRect.X + fixedRect.Width, fixedRect.Y - dist);
+ graphics.DrawLine(rulerPen, fixedRect.X, fixedRect.Y - dist - 3, fixedRect.X, fixedRect.Y - dist + 3);
+ graphics.DrawLine(rulerPen, fixedRect.X + fixedRect.Width, fixedRect.Y - dist - 3, fixedRect.X + fixedRect.Width, fixedRect.Y - dist + 3);
+ }
+ }
+
+ // vertical ruler
+ if (fixedRect.Height > vSpace + 3) {
+ using (GraphicsPath p = RoundedRectangle.Create2(
+ fixedRect.X - measureHeight.Width + 1,
+ fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2) + 2,
+ measureHeight.Width - 3,
+ measureHeight.Height - 1,
+ 3)) {
+ graphics.FillPath(bgBrush, p);
+ graphics.DrawPath(rulerPen, p);
+ graphics.DrawString(captureHeight, rulerFont, rulerPen.Brush, fixedRect.X - measureHeight.Width + 1, fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2) + 2);
+ graphics.DrawLine(rulerPen, fixedRect.X - dist, fixedRect.Y, fixedRect.X - dist, fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2));
+ graphics.DrawLine(rulerPen, fixedRect.X - dist, fixedRect.Y + fixedRect.Height / 2 + vSpace / 2, fixedRect.X - dist, fixedRect.Y + fixedRect.Height);
+ graphics.DrawLine(rulerPen, fixedRect.X - dist - 3, fixedRect.Y, fixedRect.X - dist + 3, fixedRect.Y);
+ graphics.DrawLine(rulerPen, fixedRect.X - dist - 3, fixedRect.Y + fixedRect.Height, fixedRect.X - dist + 3, fixedRect.Y + fixedRect.Height);
+ }
+ }
+
+ rulerPen.Dispose();
+ bgBrush.Dispose();
+ }
+
+ // Display size of selected rectangle
+ // Prepare the font and text.
+ using (Font sizeFont = new Font( FontFamily.GenericSansSerif, 12 )) {
+ // When capturing a Region we need to add 1 to the height/width for correction
+ string sizeText;
+ if (_captureMode == CaptureMode.Region) {
+ // correct the GUI width to real width for the shown size
+ sizeText = _captureRect.Width + 1 + " x " + (_captureRect.Height + 1);
+ } else {
+ sizeText = _captureRect.Width + " x " + _captureRect.Height;
+ }
+
+ // Calculate the scaled font size.
+ SizeF extent = graphics.MeasureString( sizeText, sizeFont );
+ float hRatio = _captureRect.Height / (extent.Height * 2);
+ float wRatio = _captureRect.Width / (extent.Width * 2);
+ float ratio = hRatio < wRatio ? hRatio : wRatio;
+ float newSize = sizeFont.Size * ratio;
+
+ if ( newSize >= 4 ) {
+ // Only show if 4pt or larger.
+ if (newSize > 20) {
+ newSize = 20;
+ }
+ // Draw the size.
+ using (Font newSizeFont = new Font(FontFamily.GenericSansSerif, newSize, FontStyle.Bold)) {
+ PointF sizeLocation = new PointF(fixedRect.X + _captureRect.Width / 2 - extent.Width / 2, fixedRect.Y + _captureRect.Height / 2 - newSizeFont.GetHeight() / 2);
+ graphics.DrawString(sizeText, newSizeFont, Brushes.LightSeaGreen, sizeLocation);
+
+ if (_showDebugInfo && _selectedCaptureWindow != null)
+ {
+ string title = $"#{_selectedCaptureWindow.Handle.ToInt64():X} - {(_selectedCaptureWindow.Text.Length > 0 ? _selectedCaptureWindow.Text : _selectedCaptureWindow.Process.ProcessName)}";
+ PointF debugLocation = new PointF(fixedRect.X, fixedRect.Y);
+ graphics.DrawString(title, sizeFont, Brushes.DarkOrange, debugLocation);
+ }
+ }
+ }
+ }
+ } else {
+ if (!IsTerminalServerSession) {
+ using (Pen pen = new Pen(Color.LightSeaGreen)) {
+ pen.DashStyle = DashStyle.Dot;
+ Rectangle screenBounds = _capture.ScreenBounds;
+ graphics.DrawLine(pen, _cursorPos.X, screenBounds.Y, _cursorPos.X, screenBounds.Height);
+ graphics.DrawLine(pen, screenBounds.X, _cursorPos.Y, screenBounds.Width, _cursorPos.Y);
+ }
+
+ string xy = _cursorPos.X + " x " + _cursorPos.Y;
+ using (Font f = new Font(FontFamily.GenericSansSerif, 8)) {
+ Size xySize = TextRenderer.MeasureText(xy, f);
+ using (GraphicsPath gp = RoundedRectangle.Create2(_cursorPos.X + 5, _cursorPos.Y + 5, xySize.Width - 3, xySize.Height, 3)) {
+ using (Brush bgBrush = new SolidBrush(Color.FromArgb(200, 217, 240, 227))) {
+ graphics.FillPath(bgBrush, gp);
+ }
+ using (Pen pen = new Pen(Color.SeaGreen)) {
+ graphics.DrawPath(pen, gp);
+ Point coordinatePosition = new Point(_cursorPos.X + 5, _cursorPos.Y + 5);
+ graphics.DrawString(xy, f, pen.Brush, coordinatePosition);
+ }
+ }
+ }
+ }
+ }
+
+ // Zoom
+ if (_zoomAnimator != null && (IsAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) {
+ const int zoomSourceWidth = 25;
+ const int zoomSourceHeight = 25;
+
+ Rectangle sourceRectangle = new Rectangle(_cursorPos.X - zoomSourceWidth / 2, _cursorPos.Y - zoomSourceHeight / 2, zoomSourceWidth, zoomSourceHeight);
+
+ Rectangle destinationRectangle = _zoomAnimator.Current;
+ destinationRectangle.Offset(_cursorPos);
+ DrawZoom(graphics, sourceRectangle, destinationRectangle);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/ColorDialog.Designer.cs b/Greenshot/Forms/ColorDialog.Designer.cs
similarity index 86%
rename from src/Greenshot.Editor/Forms/ColorDialog.Designer.cs
rename to Greenshot/Forms/ColorDialog.Designer.cs
index 0f9426a67..94dda653d 100644
--- a/src/Greenshot.Editor/Forms/ColorDialog.Designer.cs
+++ b/Greenshot/Forms/ColorDialog.Designer.cs
@@ -1,288 +1,284 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-using Greenshot.Editor.Controls;
-
-namespace Greenshot.Editor.Forms {
- public partial class ColorDialog {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ColorDialog));
- this.btnTransparent = new GreenshotButton();
- this.colorPanel = new System.Windows.Forms.Panel();
- this.labelHtmlColor = new GreenshotLabel();
- this.textBoxHtmlColor = new System.Windows.Forms.TextBox();
- this.labelRed = new GreenshotLabel();
- this.labelGreen = new GreenshotLabel();
- this.labelBlue = new GreenshotLabel();
- this.textBoxRed = new System.Windows.Forms.TextBox();
- this.textBoxGreen = new System.Windows.Forms.TextBox();
- this.textBoxBlue = new System.Windows.Forms.TextBox();
- this.labelRecentColors = new GreenshotLabel();
- this.textBoxAlpha = new System.Windows.Forms.TextBox();
- this.labelAlpha = new GreenshotLabel();
- this.btnApply = new GreenshotButton();
- this.pipette = new Pipette();
- this.SuspendLayout();
- //
- // btnTransparent
- //
- this.btnTransparent.BackColor = System.Drawing.Color.Transparent;
- this.btnTransparent.LanguageKey = "colorpicker_transparent";
- this.btnTransparent.Location = new System.Drawing.Point(210, 4);
- this.btnTransparent.Name = "btnTransparent";
- this.btnTransparent.Size = new System.Drawing.Size(78, 23);
- this.btnTransparent.TabIndex = 0;
- this.btnTransparent.TabStop = false;
- this.btnTransparent.Text = "Transparent";
- this.btnTransparent.UseVisualStyleBackColor = false;
- this.btnTransparent.Click += new System.EventHandler(this.BtnTransparentClick);
- //
- // colorPanel
- //
- this.colorPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.colorPanel.Location = new System.Drawing.Point(213, 30);
- this.colorPanel.Name = "colorPanel";
- this.colorPanel.Size = new System.Drawing.Size(33, 23);
- this.colorPanel.TabIndex = 1;
- //
- // labelHtmlColor
- //
- this.labelHtmlColor.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
- this.labelHtmlColor.LanguageKey = "colorpicker_htmlcolor";
- this.labelHtmlColor.Location = new System.Drawing.Point(210, 57);
- this.labelHtmlColor.Name = "labelHtmlColor";
- this.labelHtmlColor.Size = new System.Drawing.Size(78, 17);
- this.labelHtmlColor.TabIndex = 2;
- this.labelHtmlColor.Text = "HTML color";
- //
- // textBoxHtmlColor
- //
- this.textBoxHtmlColor.Location = new System.Drawing.Point(210, 71);
- this.textBoxHtmlColor.Name = "textBoxHtmlColor";
- this.textBoxHtmlColor.Size = new System.Drawing.Size(78, 20);
- this.textBoxHtmlColor.TabIndex = 1;
- this.textBoxHtmlColor.Click += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxHtmlColor.TextChanged += new System.EventHandler(this.TextBoxHexadecimalTextChanged);
- this.textBoxHtmlColor.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxHtmlColor.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
- //
- // labelRed
- //
- this.labelRed.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
- this.labelRed.LanguageKey = "colorpicker_red";
- this.labelRed.Location = new System.Drawing.Point(210, 98);
- this.labelRed.Name = "labelRed";
- this.labelRed.Size = new System.Drawing.Size(78, 18);
- this.labelRed.TabIndex = 4;
- this.labelRed.Text = "Red";
- //
- // labelGreen
- //
- this.labelGreen.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
- this.labelGreen.LanguageKey = "colorpicker_green";
- this.labelGreen.Location = new System.Drawing.Point(210, 122);
- this.labelGreen.Name = "labelGreen";
- this.labelGreen.Size = new System.Drawing.Size(78, 18);
- this.labelGreen.TabIndex = 5;
- this.labelGreen.Text = "Green";
- //
- // labelBlue
- //
- this.labelBlue.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
- this.labelBlue.LanguageKey = "colorpicker_blue";
- this.labelBlue.Location = new System.Drawing.Point(210, 146);
- this.labelBlue.Name = "labelBlue";
- this.labelBlue.Size = new System.Drawing.Size(78, 18);
- this.labelBlue.TabIndex = 6;
- this.labelBlue.Text = "Blue";
- //
- // textBoxRed
- //
- this.textBoxRed.Location = new System.Drawing.Point(258, 95);
- this.textBoxRed.Name = "textBoxRed";
- this.textBoxRed.Size = new System.Drawing.Size(30, 20);
- this.textBoxRed.TabIndex = 2;
- this.textBoxRed.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
- this.textBoxRed.Click += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxRed.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
- this.textBoxRed.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxRed.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
- //
- // textBoxGreen
- //
- this.textBoxGreen.Location = new System.Drawing.Point(258, 119);
- this.textBoxGreen.Name = "textBoxGreen";
- this.textBoxGreen.Size = new System.Drawing.Size(30, 20);
- this.textBoxGreen.TabIndex = 3;
- this.textBoxGreen.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
- this.textBoxGreen.Click += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxGreen.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
- this.textBoxGreen.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxGreen.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
- //
- // textBoxBlue
- //
- this.textBoxBlue.Location = new System.Drawing.Point(258, 143);
- this.textBoxBlue.Name = "textBoxBlue";
- this.textBoxBlue.Size = new System.Drawing.Size(30, 20);
- this.textBoxBlue.TabIndex = 4;
- this.textBoxBlue.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
- this.textBoxBlue.Click += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxBlue.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
- this.textBoxBlue.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxBlue.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
- //
- // labelRecentColors
- //
- this.labelRecentColors.LanguageKey = "colorpicker_recentcolors";
- this.labelRecentColors.Location = new System.Drawing.Point(3, 175);
- this.labelRecentColors.Name = "labelRecentColors";
- this.labelRecentColors.Size = new System.Drawing.Size(148, 13);
- this.labelRecentColors.TabIndex = 10;
- this.labelRecentColors.Text = "Recently used colors";
- //
- // textBoxAlpha
- //
- this.textBoxAlpha.Location = new System.Drawing.Point(258, 167);
- this.textBoxAlpha.Name = "textBoxAlpha";
- this.textBoxAlpha.Size = new System.Drawing.Size(30, 20);
- this.textBoxAlpha.TabIndex = 5;
- this.textBoxAlpha.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
- this.textBoxAlpha.Click += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxAlpha.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
- this.textBoxAlpha.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
- this.textBoxAlpha.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
- //
- // labelAlpha
- //
- this.labelAlpha.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
- this.labelAlpha.LanguageKey = "colorpicker_alpha";
- this.labelAlpha.Location = new System.Drawing.Point(210, 170);
- this.labelAlpha.Name = "labelAlpha";
- this.labelAlpha.Size = new System.Drawing.Size(78, 18);
- this.labelAlpha.TabIndex = 11;
- this.labelAlpha.Text = "Alpha";
- //
- // btnApply
- //
- this.btnApply.BackColor = System.Drawing.Color.Transparent;
- this.btnApply.LanguageKey = "colorpicker_apply";
- this.btnApply.Location = new System.Drawing.Point(210, 191);
- this.btnApply.Name = "btnApply";
- this.btnApply.Size = new System.Drawing.Size(78, 23);
- this.btnApply.TabIndex = 12;
- this.btnApply.TabStop = false;
- this.btnApply.Text = "Apply";
- this.btnApply.UseVisualStyleBackColor = false;
- this.btnApply.Click += new System.EventHandler(this.BtnApplyClick);
- //
- // pipette
- //
- this.pipette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.pipette.Cursor = System.Windows.Forms.Cursors.Arrow;
- this.pipette.Image = ((System.Drawing.Image)(resources.GetObject("pipette.Image")));
- this.pipette.Location = new System.Drawing.Point(255, 30);
- this.pipette.Name = "pipette";
- this.pipette.Size = new System.Drawing.Size(33, 23);
- this.pipette.TabIndex = 13;
- this.pipette.PipetteUsed += new System.EventHandler(this.PipetteUsed);
- //
- // ColorDialog
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(292, 218);
- this.Controls.Add(this.pipette);
- this.Controls.Add(this.btnApply);
- this.Controls.Add(this.textBoxAlpha);
- this.Controls.Add(this.labelAlpha);
- this.Controls.Add(this.labelRecentColors);
- this.Controls.Add(this.textBoxBlue);
- this.Controls.Add(this.textBoxGreen);
- this.Controls.Add(this.textBoxRed);
- this.Controls.Add(this.labelBlue);
- this.Controls.Add(this.labelGreen);
- this.Controls.Add(this.labelRed);
- this.Controls.Add(this.textBoxHtmlColor);
- this.Controls.Add(this.labelHtmlColor);
- this.Controls.Add(this.colorPanel);
- this.Controls.Add(this.btnTransparent);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.LanguageKey = "colorpicker_title";
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "ColorDialog";
- this.ShowIcon = false;
- this.ShowInTaskbar = false;
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.Text = "Color picker";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
- private GreenshotLabel labelRed;
- private GreenshotLabel labelGreen;
- private GreenshotLabel labelBlue;
- private System.Windows.Forms.TextBox textBoxHtmlColor;
- private GreenshotLabel labelRecentColors;
- private GreenshotLabel labelAlpha;
- private GreenshotLabel labelHtmlColor;
- private GreenshotButton btnApply;
- private System.Windows.Forms.TextBox textBoxAlpha;
- private System.Windows.Forms.TextBox textBoxRed;
- private System.Windows.Forms.TextBox textBoxGreen;
- private System.Windows.Forms.TextBox textBoxBlue;
- private System.Windows.Forms.Panel colorPanel;
- private GreenshotButton btnTransparent;
- private Pipette pipette;
-
-
-
-
-
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace Greenshot {
+ public partial class ColorDialog {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ColorDialog));
+ this.btnTransparent = new GreenshotPlugin.Controls.GreenshotButton();
+ this.colorPanel = new System.Windows.Forms.Panel();
+ this.labelHtmlColor = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textBoxHtmlColor = new System.Windows.Forms.TextBox();
+ this.labelRed = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelGreen = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelBlue = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textBoxRed = new System.Windows.Forms.TextBox();
+ this.textBoxGreen = new System.Windows.Forms.TextBox();
+ this.textBoxBlue = new System.Windows.Forms.TextBox();
+ this.labelRecentColors = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textBoxAlpha = new System.Windows.Forms.TextBox();
+ this.labelAlpha = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.btnApply = new GreenshotPlugin.Controls.GreenshotButton();
+ this.pipette = new Greenshot.Controls.Pipette();
+ this.SuspendLayout();
+ //
+ // btnTransparent
+ //
+ this.btnTransparent.BackColor = System.Drawing.Color.Transparent;
+ this.btnTransparent.LanguageKey = "colorpicker_transparent";
+ this.btnTransparent.Location = new System.Drawing.Point(210, 4);
+ this.btnTransparent.Name = "btnTransparent";
+ this.btnTransparent.Size = new System.Drawing.Size(78, 23);
+ this.btnTransparent.TabIndex = 0;
+ this.btnTransparent.TabStop = false;
+ this.btnTransparent.Text = "Transparent";
+ this.btnTransparent.UseVisualStyleBackColor = false;
+ this.btnTransparent.Click += new System.EventHandler(this.BtnTransparentClick);
+ //
+ // colorPanel
+ //
+ this.colorPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.colorPanel.Location = new System.Drawing.Point(213, 30);
+ this.colorPanel.Name = "colorPanel";
+ this.colorPanel.Size = new System.Drawing.Size(33, 23);
+ this.colorPanel.TabIndex = 1;
+ //
+ // labelHtmlColor
+ //
+ this.labelHtmlColor.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
+ this.labelHtmlColor.LanguageKey = "colorpicker_htmlcolor";
+ this.labelHtmlColor.Location = new System.Drawing.Point(210, 57);
+ this.labelHtmlColor.Name = "labelHtmlColor";
+ this.labelHtmlColor.Size = new System.Drawing.Size(78, 17);
+ this.labelHtmlColor.TabIndex = 2;
+ this.labelHtmlColor.Text = "HTML color";
+ //
+ // textBoxHtmlColor
+ //
+ this.textBoxHtmlColor.Location = new System.Drawing.Point(210, 71);
+ this.textBoxHtmlColor.Name = "textBoxHtmlColor";
+ this.textBoxHtmlColor.Size = new System.Drawing.Size(78, 20);
+ this.textBoxHtmlColor.TabIndex = 1;
+ this.textBoxHtmlColor.Click += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxHtmlColor.TextChanged += new System.EventHandler(this.TextBoxHexadecimalTextChanged);
+ this.textBoxHtmlColor.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxHtmlColor.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
+ //
+ // labelRed
+ //
+ this.labelRed.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
+ this.labelRed.LanguageKey = "colorpicker_red";
+ this.labelRed.Location = new System.Drawing.Point(210, 98);
+ this.labelRed.Name = "labelRed";
+ this.labelRed.Size = new System.Drawing.Size(78, 18);
+ this.labelRed.TabIndex = 4;
+ this.labelRed.Text = "Red";
+ //
+ // labelGreen
+ //
+ this.labelGreen.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
+ this.labelGreen.LanguageKey = "colorpicker_green";
+ this.labelGreen.Location = new System.Drawing.Point(210, 122);
+ this.labelGreen.Name = "labelGreen";
+ this.labelGreen.Size = new System.Drawing.Size(78, 18);
+ this.labelGreen.TabIndex = 5;
+ this.labelGreen.Text = "Green";
+ //
+ // labelBlue
+ //
+ this.labelBlue.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
+ this.labelBlue.LanguageKey = "colorpicker_blue";
+ this.labelBlue.Location = new System.Drawing.Point(210, 146);
+ this.labelBlue.Name = "labelBlue";
+ this.labelBlue.Size = new System.Drawing.Size(78, 18);
+ this.labelBlue.TabIndex = 6;
+ this.labelBlue.Text = "Blue";
+ //
+ // textBoxRed
+ //
+ this.textBoxRed.Location = new System.Drawing.Point(258, 95);
+ this.textBoxRed.Name = "textBoxRed";
+ this.textBoxRed.Size = new System.Drawing.Size(30, 20);
+ this.textBoxRed.TabIndex = 2;
+ this.textBoxRed.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this.textBoxRed.Click += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxRed.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
+ this.textBoxRed.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxRed.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
+ //
+ // textBoxGreen
+ //
+ this.textBoxGreen.Location = new System.Drawing.Point(258, 119);
+ this.textBoxGreen.Name = "textBoxGreen";
+ this.textBoxGreen.Size = new System.Drawing.Size(30, 20);
+ this.textBoxGreen.TabIndex = 3;
+ this.textBoxGreen.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this.textBoxGreen.Click += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxGreen.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
+ this.textBoxGreen.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxGreen.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
+ //
+ // textBoxBlue
+ //
+ this.textBoxBlue.Location = new System.Drawing.Point(258, 143);
+ this.textBoxBlue.Name = "textBoxBlue";
+ this.textBoxBlue.Size = new System.Drawing.Size(30, 20);
+ this.textBoxBlue.TabIndex = 4;
+ this.textBoxBlue.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this.textBoxBlue.Click += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxBlue.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
+ this.textBoxBlue.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxBlue.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
+ //
+ // labelRecentColors
+ //
+ this.labelRecentColors.LanguageKey = "colorpicker_recentcolors";
+ this.labelRecentColors.Location = new System.Drawing.Point(3, 175);
+ this.labelRecentColors.Name = "labelRecentColors";
+ this.labelRecentColors.Size = new System.Drawing.Size(148, 13);
+ this.labelRecentColors.TabIndex = 10;
+ this.labelRecentColors.Text = "Recently used colors";
+ //
+ // textBoxAlpha
+ //
+ this.textBoxAlpha.Location = new System.Drawing.Point(258, 167);
+ this.textBoxAlpha.Name = "textBoxAlpha";
+ this.textBoxAlpha.Size = new System.Drawing.Size(30, 20);
+ this.textBoxAlpha.TabIndex = 5;
+ this.textBoxAlpha.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this.textBoxAlpha.Click += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxAlpha.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged);
+ this.textBoxAlpha.GotFocus += new System.EventHandler(this.TextBoxGotFocus);
+ this.textBoxAlpha.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown);
+ //
+ // labelAlpha
+ //
+ this.labelAlpha.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World);
+ this.labelAlpha.LanguageKey = "colorpicker_alpha";
+ this.labelAlpha.Location = new System.Drawing.Point(210, 170);
+ this.labelAlpha.Name = "labelAlpha";
+ this.labelAlpha.Size = new System.Drawing.Size(78, 18);
+ this.labelAlpha.TabIndex = 11;
+ this.labelAlpha.Text = "Alpha";
+ //
+ // btnApply
+ //
+ this.btnApply.BackColor = System.Drawing.Color.Transparent;
+ this.btnApply.LanguageKey = "colorpicker_apply";
+ this.btnApply.Location = new System.Drawing.Point(210, 191);
+ this.btnApply.Name = "btnApply";
+ this.btnApply.Size = new System.Drawing.Size(78, 23);
+ this.btnApply.TabIndex = 12;
+ this.btnApply.TabStop = false;
+ this.btnApply.Text = "Apply";
+ this.btnApply.UseVisualStyleBackColor = false;
+ this.btnApply.Click += new System.EventHandler(this.BtnApplyClick);
+ //
+ // pipette
+ //
+ this.pipette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.pipette.Cursor = System.Windows.Forms.Cursors.Arrow;
+ this.pipette.Image = ((System.Drawing.Image)(resources.GetObject("pipette.Image")));
+ this.pipette.Location = new System.Drawing.Point(255, 30);
+ this.pipette.Name = "pipette";
+ this.pipette.Size = new System.Drawing.Size(33, 23);
+ this.pipette.TabIndex = 13;
+ this.pipette.PipetteUsed += new System.EventHandler(this.PipetteUsed);
+ //
+ // ColorDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.ClientSize = new System.Drawing.Size(292, 218);
+ this.Controls.Add(this.pipette);
+ this.Controls.Add(this.btnApply);
+ this.Controls.Add(this.textBoxAlpha);
+ this.Controls.Add(this.labelAlpha);
+ this.Controls.Add(this.labelRecentColors);
+ this.Controls.Add(this.textBoxBlue);
+ this.Controls.Add(this.textBoxGreen);
+ this.Controls.Add(this.textBoxRed);
+ this.Controls.Add(this.labelBlue);
+ this.Controls.Add(this.labelGreen);
+ this.Controls.Add(this.labelRed);
+ this.Controls.Add(this.textBoxHtmlColor);
+ this.Controls.Add(this.labelHtmlColor);
+ this.Controls.Add(this.colorPanel);
+ this.Controls.Add(this.btnTransparent);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.LanguageKey = "colorpicker_title";
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "ColorDialog";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.Text = "Color picker";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+ private GreenshotPlugin.Controls.GreenshotLabel labelRed;
+ private GreenshotPlugin.Controls.GreenshotLabel labelGreen;
+ private GreenshotPlugin.Controls.GreenshotLabel labelBlue;
+ private System.Windows.Forms.TextBox textBoxHtmlColor;
+ private GreenshotPlugin.Controls.GreenshotLabel labelRecentColors;
+ private GreenshotPlugin.Controls.GreenshotLabel labelAlpha;
+ private GreenshotPlugin.Controls.GreenshotLabel labelHtmlColor;
+ private GreenshotPlugin.Controls.GreenshotButton btnApply;
+ private System.Windows.Forms.TextBox textBoxAlpha;
+ private System.Windows.Forms.TextBox textBoxRed;
+ private System.Windows.Forms.TextBox textBoxGreen;
+ private System.Windows.Forms.TextBox textBoxBlue;
+ private System.Windows.Forms.Panel colorPanel;
+ private GreenshotPlugin.Controls.GreenshotButton btnTransparent;
+ private Greenshot.Controls.Pipette pipette;
+
+
+
+
+
+ }
+}
diff --git a/Greenshot/Forms/ColorDialog.cs b/Greenshot/Forms/ColorDialog.cs
new file mode 100644
index 000000000..5799e0351
--- /dev/null
+++ b/Greenshot/Forms/ColorDialog.cs
@@ -0,0 +1,244 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Configuration;
+using Greenshot.Controls;
+using Greenshot.IniFile;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Greenshot {
+ ///
+ /// Description of ColorDialog.
+ ///
+ public partial class ColorDialog : BaseForm {
+ private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection();
+
+ public ColorDialog() {
+ SuspendLayout();
+ InitializeComponent();
+ SuspendLayout();
+ CreateColorPalette(5, 5, 15, 15);
+ CreateLastUsedColorButtonRow(5, 190, 15, 15);
+ ResumeLayout();
+ UpdateRecentColorsButtonRow();
+ }
+
+ private readonly List _colorButtons = new List();
+ private readonly List _recentColorButtons = new List();
+ private readonly ToolTip _toolTip = new ToolTip();
+ private bool _updateInProgress;
+
+ public Color Color {
+ get { return colorPanel.BackColor; }
+ set { PreviewColor(value, this); }
+ }
+
+ #region user interface generation
+ private void CreateColorPalette(int x, int y, int w, int h) {
+ CreateColorButtonColumn(255, 0, 0, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255, 255 / 2, 0, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255, 255, 0, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255 / 2, 255, 0, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(0, 255, 0, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(0, 255, 255 / 2, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(0, 255, 255, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(0, 255 / 2, 255, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(0, 0, 255, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255 / 2, 0, 255, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255, 0, 255, x, y, w, h, 11);
+ x += w;
+ CreateColorButtonColumn(255, 0, 255 / 2, x, y, w, h, 11);
+ x += w + 5;
+ CreateColorButtonColumn(255 / 2, 255 / 2, 255 / 2, x, y, w, h, 11);
+
+ Controls.AddRange(_colorButtons.ToArray());
+ }
+
+ private void CreateColorButtonColumn(int red, int green, int blue, int x, int y, int w, int h, int shades) {
+ int shadedColorsNum = (shades - 1) / 2;
+ for (int i = 0; i <= shadedColorsNum; i++) {
+ _colorButtons.Add(CreateColorButton(red * i / shadedColorsNum, green * i / shadedColorsNum, blue * i / shadedColorsNum, x, y + i * h, w, h));
+ if (i > 0) _colorButtons.Add(CreateColorButton(red + (255 - red) * i / shadedColorsNum, green + (255 - green) * i / shadedColorsNum, blue + (255 - blue) * i / shadedColorsNum, x, y + (i + shadedColorsNum) * h, w, h));
+ }
+ }
+
+ private Button CreateColorButton(int red, int green, int blue, int x, int y, int w, int h) {
+ return CreateColorButton(Color.FromArgb(255, red, green, blue), x, y, w, h);
+ }
+
+ private Button CreateColorButton(Color color, int x, int y, int w, int h) {
+ Button b = new Button
+ {
+ BackColor = color,
+ FlatStyle = FlatStyle.Flat,
+ Location = new Point(x, y),
+ Size = new Size(w, h),
+ TabStop = false
+ };
+ b.FlatAppearance.BorderSize = 0;
+ b.Click += ColorButtonClick;
+ _toolTip.SetToolTip(b, ColorTranslator.ToHtml(color) + " | R:" + color.R + ", G:" + color.G + ", B:" + color.B);
+ return b;
+ }
+
+ private void CreateLastUsedColorButtonRow(int x, int y, int w, int h) {
+ for (int i = 0; i < 12; i++) {
+ Button b = CreateColorButton(Color.Transparent, x, y, w, h);
+ b.Enabled = false;
+ _recentColorButtons.Add(b);
+ x += w;
+ }
+ Controls.AddRange(_recentColorButtons.ToArray());
+ }
+ #endregion
+
+ #region update user interface
+ private void UpdateRecentColorsButtonRow() {
+ for (int i = 0; i < EditorConfig.RecentColors.Count && i < 12; i++) {
+ _recentColorButtons[i].BackColor = EditorConfig.RecentColors[i];
+ _recentColorButtons[i].Enabled = true;
+ }
+ }
+
+ private void PreviewColor(Color colorToPreview, Control trigger) {
+ _updateInProgress = true;
+ colorPanel.BackColor = colorToPreview;
+ if (trigger != textBoxHtmlColor) {
+ textBoxHtmlColor.Text = ColorTranslator.ToHtml(colorToPreview);
+ }
+ if (trigger != textBoxRed && trigger != textBoxGreen && trigger != textBoxBlue && trigger != textBoxAlpha) {
+ textBoxRed.Text = colorToPreview.R.ToString();
+ textBoxGreen.Text = colorToPreview.G.ToString();
+ textBoxBlue.Text = colorToPreview.B.ToString();
+ textBoxAlpha.Text = colorToPreview.A.ToString();
+ }
+ _updateInProgress = false;
+ }
+
+ private void AddToRecentColors(Color c) {
+ EditorConfig.RecentColors.Remove(c);
+ EditorConfig.RecentColors.Insert(0, c);
+ if (EditorConfig.RecentColors.Count > 12) {
+ EditorConfig.RecentColors.RemoveRange(12, EditorConfig.RecentColors.Count - 12);
+ }
+ UpdateRecentColorsButtonRow();
+ }
+ #endregion
+
+ #region textbox event handlers
+
+ private void TextBoxHexadecimalTextChanged(object sender, EventArgs e) {
+ if (_updateInProgress) {
+ return;
+ }
+ TextBox textBox = (TextBox)sender;
+ string text = textBox.Text.Replace("#", "");
+ int i;
+ Color c;
+ if (int.TryParse(text, NumberStyles.AllowHexSpecifier, Thread.CurrentThread.CurrentCulture, out i)) {
+ c = Color.FromArgb(i);
+ } else {
+ try
+ {
+ var knownColor = (KnownColor)Enum.Parse(typeof(KnownColor), text, true);
+ c = Color.FromKnownColor(knownColor);
+ } catch (Exception) {
+ return;
+ }
+ }
+ Color opaqueColor = Color.FromArgb(255, c.R, c.G, c.B);
+ PreviewColor(opaqueColor, textBox);
+ }
+
+ private void TextBoxRgbTextChanged(object sender, EventArgs e) {
+ if (_updateInProgress) {
+ return;
+ }
+ TextBox textBox = (TextBox)sender;
+ PreviewColor(Color.FromArgb(GetColorPartIntFromString(textBoxAlpha.Text), GetColorPartIntFromString(textBoxRed.Text), GetColorPartIntFromString(textBoxGreen.Text), GetColorPartIntFromString(textBoxBlue.Text)), textBox);
+ }
+
+ private void TextBoxGotFocus(object sender, EventArgs e) {
+ textBoxHtmlColor.SelectAll();
+ }
+
+ private void TextBoxKeyDown(object sender, KeyEventArgs e) {
+ if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) {
+ AddToRecentColors(colorPanel.BackColor);
+ }
+ }
+ #endregion
+
+ #region button event handlers
+
+ private void ColorButtonClick(object sender, EventArgs e) {
+ Button b = (Button)sender;
+ PreviewColor(b.BackColor, b);
+ }
+
+ private void BtnTransparentClick(object sender, EventArgs e) {
+ ColorButtonClick(sender, e);
+ }
+
+ private void BtnApplyClick(object sender, EventArgs e) {
+ DialogResult = DialogResult.OK;
+ Hide();
+ AddToRecentColors(colorPanel.BackColor);
+ }
+ #endregion
+
+ #region helper functions
+ private int GetColorPartIntFromString(string s) {
+ int ret;
+ int.TryParse(s, out ret);
+ if (ret < 0)
+ {
+ ret = 0;
+ }
+ else if (ret > 255)
+ {
+ ret = 255;
+ }
+ return ret;
+ }
+
+ #endregion
+
+ private void PipetteUsed(object sender, PipetteUsedArgs e) {
+ Color = e.Color;
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/ColorDialog.resx b/Greenshot/Forms/ColorDialog.resx
similarity index 95%
rename from src/Greenshot.Editor/Forms/ColorDialog.resx
rename to Greenshot/Forms/ColorDialog.resx
index 4de617878..da9eec254 100644
--- a/src/Greenshot.Editor/Forms/ColorDialog.resx
+++ b/Greenshot/Forms/ColorDialog.resx
@@ -1,135 +1,135 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABqklEQVQ4T6WTvUtCURiH34Mi
- Koo6CKI45HUT/4CgDwz8oMVFXLyGIVpDjTYkuDsoF6RPmtJKkIgKipYsCIoQihYXKxSCICjaGoTTe6R7
- uflBgcOPwz3wPL/3HM4FSikMkw6sVCphHPNCSE9auPf8kydCJuqEHNYIOakSMsXYjiClUPSFmVAUiHBb
- EOh7KkWPAC4lQb9mcY8J5HAzGKSP4TDdBrj+SzCGkkqTkHk2NmuWw+sAfklQBYDunAPUaLlMG4Qc9INX
- kZEERa8Xdvx+2A0EpJR8Pv4UJe1CoaeZwb8E2WwWcrkcCILQST6fd2YymeRS6SG9j5JGKEQ3AW7XAJZF
- eKBAhN8+v+p7V61jJimi5AMvbgVXDIiRjiBO0A2f3b9uud3u5IzRyOMEDA4MFKCES6fTCbGZwS6XK2G3
- 250RvR42ZM09E/A8D/F4PCaHOY6LWSwWzmq1wp8Cj8fjiMzOLbAzs2YEeZPJ5DCbzfAvgc1mi7L20Unv
- ok6ni2q12hGDwQCDBEV8nRWMdIkajWZapVLFMZxarQb8hn6CMkI3mDvMhVwwzO/8DbWQqn7YBXReAAAA
- AElFTkSuQmCC
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABqklEQVQ4T6WTvUtCURiH34Mi
+ Koo6CKI45HUT/4CgDwz8oMVFXLyGIVpDjTYkuDsoF6RPmtJKkIgKipYsCIoQihYXKxSCICjaGoTTe6R7
+ uflBgcOPwz3wPL/3HM4FSikMkw6sVCphHPNCSE9auPf8kydCJuqEHNYIOakSMsXYjiClUPSFmVAUiHBb
+ EOh7KkWPAC4lQb9mcY8J5HAzGKSP4TDdBrj+SzCGkkqTkHk2NmuWw+sAfklQBYDunAPUaLlMG4Qc9INX
+ kZEERa8Xdvx+2A0EpJR8Pv4UJe1CoaeZwb8E2WwWcrkcCILQST6fd2YymeRS6SG9j5JGKEQ3AW7XAJZF
+ eKBAhN8+v+p7V61jJimi5AMvbgVXDIiRjiBO0A2f3b9uud3u5IzRyOMEDA4MFKCES6fTCbGZwS6XK2G3
+ 250RvR42ZM09E/A8D/F4PCaHOY6LWSwWzmq1wp8Cj8fjiMzOLbAzs2YEeZPJ5DCbzfAvgc1mi7L20Unv
+ ok6ni2q12hGDwQCDBEV8nRWMdIkajWZapVLFMZxarQb8hn6CMkI3mDvMhVwwzO/8DbWQqn7YBXReAAAA
+ AElFTkSuQmCC
+
+
\ No newline at end of file
diff --git a/Greenshot/Forms/ColorPickerToolStripButton.cs b/Greenshot/Forms/ColorPickerToolStripButton.cs
new file mode 100644
index 000000000..f1160bd43
--- /dev/null
+++ b/Greenshot/Forms/ColorPickerToolStripButton.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows.Forms;
+using System.Diagnostics;
+
+namespace GreenShot
+{
+ public delegate void ColorPickerEventHandler(object o, ColorPickerEventArgs e);
+
+ public class ColorPickerToolStripButton : System.Windows.Forms.ToolStripButton
+ {
+ private Color color;
+ public Point Offset = new Point(0,0);
+ public event ColorPickerEventHandler ColorPicked;
+ private ColorDialog cd;
+
+
+ public ColorPickerToolStripButton()
+ {
+ cd = ColorDialog.GetInstance();
+ this.Click += new System.EventHandler(this.ToolStripButton1Click);
+ }
+
+ public Color Color {
+ set {color = value;this.Invalidate();}
+ get {return color;}
+ }
+
+ protected override void OnPaint (PaintEventArgs e) {
+ base.OnPaint(e);
+ if(color != null) {
+ // replace transparent color with selected color
+ Graphics g = e.Graphics;
+ //Graphics g = Graphics.FromImage(Image);
+ ColorMap[] colorMap = new ColorMap[1];
+ colorMap[0] = new ColorMap();
+ colorMap[0].OldColor = Color.Magenta;//this.ImageTransparentColor;
+ colorMap[0].NewColor = color;
+ ImageAttributes attr = new ImageAttributes();
+ attr.SetRemapTable(colorMap);
+ Rectangle rect = new Rectangle(0, 0, Image.Width, Image.Height);
+ // todo find a way to retrieve transparency offset automatically
+ // for now, we use the public variable Offset to define this manually
+ rect.Offset(Offset.X,Offset.Y);
+ //Image.
+ Debug.WriteLine("paint!"+this.Text+": "+color);
+ //ssif(color.Equals(Color.Transparent)) ((Bitmap)Image).MakeTransparent(Color.Magenta);
+ g.DrawImage(Image, rect, 0, 0, rect.Width, rect.Height, GraphicsUnit.Pixel, attr);
+ //this.Image.In
+
+ }
+ }
+
+ void ToolStripButton1Click(object sender, System.EventArgs e)
+ {
+ cd.ShowDialog(this.Owner);
+ Color = cd.Color;
+ if(ColorPicked != null) {
+ ColorPicked(this, new ColorPickerEventArgs(Color, cd.RecentColors));
+ }
+ }
+ }
+
+ public class ColorPickerEventArgs : System.EventArgs {
+ public Color Color;
+ public Color[] RecentColors;
+ public ColorPickerEventArgs(Color color, Color[] recentColors) {
+ Color = color;
+ RecentColors = recentColors;
+ }
+
+ }
+
+
+
+
+}
diff --git a/src/Greenshot.Editor/Forms/DropShadowSettingsForm.Designer.cs b/Greenshot/Forms/DropShadowSettingsForm.Designer.cs
similarity index 84%
rename from src/Greenshot.Editor/Forms/DropShadowSettingsForm.Designer.cs
rename to Greenshot/Forms/DropShadowSettingsForm.Designer.cs
index 41d9ab1d5..687a20be1 100644
--- a/src/Greenshot.Editor/Forms/DropShadowSettingsForm.Designer.cs
+++ b/Greenshot/Forms/DropShadowSettingsForm.Designer.cs
@@ -1,239 +1,240 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Editor.Forms {
- partial class DropShadowSettingsForm {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.thickness = new System.Windows.Forms.NumericUpDown();
- this.offsetX = new System.Windows.Forms.NumericUpDown();
- this.label3 = new System.Windows.Forms.Label();
- this.offsetY = new System.Windows.Forms.NumericUpDown();
- this.trackBar1 = new System.Windows.Forms.TrackBar();
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.labelDarkness = new GreenshotLabel();
- this.labelOffset = new GreenshotLabel();
- this.labelThickness = new GreenshotLabel();
- ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
- this.SuspendLayout();
- //
- // thickness
- //
- this.thickness.Location = new System.Drawing.Point(173, 7);
- this.thickness.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.thickness.Minimum = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.thickness.Name = "thickness";
- this.thickness.Size = new System.Drawing.Size(45, 20);
- this.thickness.TabIndex = 1;
- this.thickness.Value = new decimal(new int[] {
- 9,
- 0,
- 0,
- 0});
- //
- // offsetX
- //
- this.offsetX.Location = new System.Drawing.Point(102, 33);
- this.offsetX.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.offsetX.Minimum = new decimal(new int[] {
- 20,
- 0,
- 0,
- -2147483648});
- this.offsetX.Name = "offsetX";
- this.offsetX.Size = new System.Drawing.Size(45, 20);
- this.offsetX.TabIndex = 2;
- this.offsetX.Value = new decimal(new int[] {
- 1,
- 0,
- 0,
- -2147483648});
- //
- // label3
- //
- this.label3.Location = new System.Drawing.Point(153, 35);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(14, 13);
- this.label3.TabIndex = 5;
- this.label3.Text = "X";
- //
- // offsetY
- //
- this.offsetY.Location = new System.Drawing.Point(173, 33);
- this.offsetY.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.offsetY.Minimum = new decimal(new int[] {
- 20,
- 0,
- 0,
- -2147483648});
- this.offsetY.Name = "offsetY";
- this.offsetY.Size = new System.Drawing.Size(45, 20);
- this.offsetY.TabIndex = 3;
- this.offsetY.Value = new decimal(new int[] {
- 1,
- 0,
- 0,
- -2147483648});
- //
- // trackBar1
- //
- this.trackBar1.Location = new System.Drawing.Point(102, 59);
- this.trackBar1.Maximum = 40;
- this.trackBar1.Minimum = 1;
- this.trackBar1.Name = "trackBar1";
- this.trackBar1.Size = new System.Drawing.Size(116, 45);
- this.trackBar1.TabIndex = 4;
- this.trackBar1.Value = 40;
- //
- // buttonOK
- //
- this.buttonOK.LanguageKey = "OK";
- this.buttonOK.Location = new System.Drawing.Point(62, 110);
- this.buttonOK.Name = "buttonOK";
- this.buttonOK.Size = new System.Drawing.Size(75, 23);
- this.buttonOK.TabIndex = 11;
- this.buttonOK.UseVisualStyleBackColor = true;
- this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
- //
- // buttonCancel
- //
- this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.buttonCancel.LanguageKey = "CANCEL";
- this.buttonCancel.Location = new System.Drawing.Point(143, 110);
- this.buttonCancel.Name = "buttonCancel";
- this.buttonCancel.Size = new System.Drawing.Size(75, 23);
- this.buttonCancel.TabIndex = 12;
- this.buttonCancel.UseVisualStyleBackColor = true;
- //
- // labelDarkness
- //
- this.labelDarkness.LanguageKey = "editor_dropshadow_darkness";
- this.labelDarkness.Location = new System.Drawing.Point(12, 73);
- this.labelDarkness.Name = "labelDarkness";
- this.labelDarkness.Size = new System.Drawing.Size(92, 13);
- this.labelDarkness.TabIndex = 13;
- //
- // labelOffset
- //
- this.labelOffset.LanguageKey = "editor_dropshadow_offset";
- this.labelOffset.Location = new System.Drawing.Point(12, 35);
- this.labelOffset.Name = "labelOffset";
- this.labelOffset.Size = new System.Drawing.Size(75, 13);
- this.labelOffset.TabIndex = 14;
- //
- // labelThickness
- //
- this.labelThickness.LanguageKey = "editor_dropshadow_thickness";
- this.labelThickness.Location = new System.Drawing.Point(12, 9);
- this.labelThickness.Name = "labelThickness";
- this.labelThickness.Size = new System.Drawing.Size(94, 13);
- this.labelThickness.TabIndex = 15;
- //
- // DropShadowSettingsForm
- //
- this.AcceptButton = this.buttonOK;
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.CancelButton = this.buttonCancel;
- this.ClientSize = new System.Drawing.Size(230, 154);
- this.ControlBox = false;
- this.Controls.Add(this.labelThickness);
- this.Controls.Add(this.labelOffset);
- this.Controls.Add(this.labelDarkness);
- this.Controls.Add(this.buttonCancel);
- this.Controls.Add(this.buttonOK);
- this.Controls.Add(this.trackBar1);
- this.Controls.Add(this.offsetY);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.offsetX);
- this.Controls.Add(this.thickness);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
- this.LanguageKey = "editor_dropshadow_settings";
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "DropShadowSettingsForm";
- this.ShowIcon = false;
- ((System.ComponentModel.ISupportInitialize)(this.thickness)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetX)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetY)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.NumericUpDown thickness;
- private System.Windows.Forms.NumericUpDown offsetX;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.NumericUpDown offsetY;
- private System.Windows.Forms.TrackBar trackBar1;
- private GreenshotButton buttonOK;
- private GreenshotButton buttonCancel;
- private GreenshotLabel labelDarkness;
- private GreenshotLabel labelOffset;
- private GreenshotLabel labelThickness;
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace Greenshot.Forms {
+ partial class DropShadowSettingsForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.thickness = new System.Windows.Forms.NumericUpDown();
+ this.offsetX = new System.Windows.Forms.NumericUpDown();
+ this.label3 = new System.Windows.Forms.Label();
+ this.offsetY = new System.Windows.Forms.NumericUpDown();
+ this.trackBar1 = new System.Windows.Forms.TrackBar();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.labelDarkness = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelOffset = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelThickness = new GreenshotPlugin.Controls.GreenshotLabel();
+ ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // thickness
+ //
+ this.thickness.Location = new System.Drawing.Point(173, 7);
+ this.thickness.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.thickness.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.thickness.Name = "thickness";
+ this.thickness.Size = new System.Drawing.Size(45, 20);
+ this.thickness.TabIndex = 1;
+ this.thickness.Value = new decimal(new int[] {
+ 9,
+ 0,
+ 0,
+ 0});
+ //
+ // offsetX
+ //
+ this.offsetX.Location = new System.Drawing.Point(102, 33);
+ this.offsetX.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.offsetX.Minimum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ -2147483648});
+ this.offsetX.Name = "offsetX";
+ this.offsetX.Size = new System.Drawing.Size(45, 20);
+ this.offsetX.TabIndex = 2;
+ this.offsetX.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(153, 35);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(14, 13);
+ this.label3.TabIndex = 5;
+ this.label3.Text = "X";
+ //
+ // offsetY
+ //
+ this.offsetY.Location = new System.Drawing.Point(173, 33);
+ this.offsetY.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.offsetY.Minimum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ -2147483648});
+ this.offsetY.Name = "offsetY";
+ this.offsetY.Size = new System.Drawing.Size(45, 20);
+ this.offsetY.TabIndex = 3;
+ this.offsetY.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // trackBar1
+ //
+ this.trackBar1.Location = new System.Drawing.Point(102, 59);
+ this.trackBar1.Maximum = 40;
+ this.trackBar1.Minimum = 1;
+ this.trackBar1.Name = "trackBar1";
+ this.trackBar1.Size = new System.Drawing.Size(116, 45);
+ this.trackBar1.TabIndex = 4;
+ this.trackBar1.Value = 40;
+ //
+ // buttonOK
+ //
+ this.buttonOK.LanguageKey = "OK";
+ this.buttonOK.Location = new System.Drawing.Point(62, 110);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 23);
+ this.buttonOK.TabIndex = 11;
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.LanguageKey = "CANCEL";
+ this.buttonCancel.Location = new System.Drawing.Point(143, 110);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 12;
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // labelDarkness
+ //
+ this.labelDarkness.AutoSize = true;
+ this.labelDarkness.LanguageKey = "editor_dropshadow_darkness";
+ this.labelDarkness.Location = new System.Drawing.Point(12, 73);
+ this.labelDarkness.Name = "labelDarkness";
+ this.labelDarkness.Size = new System.Drawing.Size(92, 13);
+ this.labelDarkness.TabIndex = 13;
+ //
+ // labelOffset
+ //
+ this.labelOffset.AutoSize = true;
+ this.labelOffset.LanguageKey = "editor_dropshadow_offset";
+ this.labelOffset.Location = new System.Drawing.Point(12, 35);
+ this.labelOffset.Name = "labelOffset";
+ this.labelOffset.Size = new System.Drawing.Size(75, 13);
+ this.labelOffset.TabIndex = 14;
+ //
+ // labelThickness
+ //
+ this.labelThickness.AutoSize = true;
+ this.labelThickness.LanguageKey = "editor_dropshadow_thickness";
+ this.labelThickness.Location = new System.Drawing.Point(12, 9);
+ this.labelThickness.Name = "labelThickness";
+ this.labelThickness.Size = new System.Drawing.Size(94, 13);
+ this.labelThickness.TabIndex = 15;
+ //
+ // DropShadowSettingsForm
+ //
+ this.AcceptButton = this.buttonOK;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.buttonCancel;
+ this.ClientSize = new System.Drawing.Size(230, 154);
+ this.ControlBox = false;
+ this.Controls.Add(this.labelThickness);
+ this.Controls.Add(this.labelOffset);
+ this.Controls.Add(this.labelDarkness);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.Controls.Add(this.trackBar1);
+ this.Controls.Add(this.offsetY);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.offsetX);
+ this.Controls.Add(this.thickness);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.LanguageKey = "editor_dropshadow_settings";
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "DropShadowSettingsForm";
+ this.ShowIcon = false;
+ ((System.ComponentModel.ISupportInitialize)(this.thickness)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetX)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetY)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.NumericUpDown thickness;
+ private System.Windows.Forms.NumericUpDown offsetX;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.NumericUpDown offsetY;
+ private System.Windows.Forms.TrackBar trackBar1;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotLabel labelDarkness;
+ private GreenshotPlugin.Controls.GreenshotLabel labelOffset;
+ private GreenshotPlugin.Controls.GreenshotLabel labelThickness;
+ }
}
\ No newline at end of file
diff --git a/Greenshot/Forms/DropShadowSettingsForm.cs b/Greenshot/Forms/DropShadowSettingsForm.cs
new file mode 100644
index 000000000..fe06840d4
--- /dev/null
+++ b/Greenshot/Forms/DropShadowSettingsForm.cs
@@ -0,0 +1,53 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using GreenshotPlugin.Effects;
+
+namespace Greenshot.Forms {
+ public partial class DropShadowSettingsForm : BaseForm {
+ private readonly DropShadowEffect _effect;
+
+ public DropShadowSettingsForm(DropShadowEffect effect) {
+ _effect = effect;
+ InitializeComponent();
+ ShowSettings();
+ }
+
+ ///
+ /// Apply the settings from the effect to the view
+ ///
+ private void ShowSettings() {
+ trackBar1.Value = (int)(_effect.Darkness * 40);
+ offsetX.Value = _effect.ShadowOffset.X;
+ offsetY.Value = _effect.ShadowOffset.Y;
+ thickness.Value = _effect.ShadowSize;
+ }
+
+ private void ButtonOK_Click(object sender, EventArgs e) {
+ _effect.Darkness = trackBar1.Value / (float)40;
+ _effect.ShadowOffset = new Point((int)offsetX.Value, (int)offsetY.Value);
+ _effect.ShadowSize = (int)thickness.Value;
+ DialogResult = DialogResult.OK;
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/Greenshot/Forms/ImageEditorForm.Designer.cs
similarity index 71%
rename from src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs
rename to Greenshot/Forms/ImageEditorForm.Designer.cs
index c0a8f8a63..1bf498412 100644
--- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs
+++ b/Greenshot/Forms/ImageEditorForm.Designer.cs
@@ -1,2054 +1,1797 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-using Greenshot.Editor.Controls;
-using Greenshot.Editor.Drawing;
-
-namespace Greenshot.Editor.Forms {
- partial class ImageEditorForm {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
- private System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageEditorForm));
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- this.topToolStripContainer = new System.Windows.Forms.ToolStripContainer();
- this.statusStrip1 = new System.Windows.Forms.StatusStrip();
- this.dimensionsLabel = new System.Windows.Forms.ToolStripStatusLabel();
- this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
- this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
- this.panel1 = new NonJumpingPanel();
- this.toolsToolStrip = new ToolStripEx();
- this.btnCursor = new GreenshotToolStripButton();
- this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
- this.btnRect = new GreenshotToolStripButton();
- this.btnEllipse = new GreenshotToolStripButton();
- this.btnLine = new GreenshotToolStripButton();
- this.btnArrow = new GreenshotToolStripButton();
- this.btnFreehand = new GreenshotToolStripButton();
- this.btnText = new GreenshotToolStripButton();
- this.btnSpeechBubble = new GreenshotToolStripButton();
- this.btnStepLabel = new GreenshotToolStripButton();
- this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator();
- this.btnHighlight = new GreenshotToolStripButton();
- this.btnObfuscate = new GreenshotToolStripButton();
- this.toolStripSplitButton1 = new GreenshotToolStripDropDownButton();
- this.addBorderToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addDropshadowToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.tornEdgesToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.grayscaleToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.invertToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.btnResize = new GreenshotToolStripButton();
- this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
- this.btnCrop = new GreenshotToolStripButton();
- this.rotateCwToolstripButton = new GreenshotToolStripButton();
- this.rotateCcwToolstripButton = new GreenshotToolStripButton();
- this.menuStrip1 = new MenuStripEx();
- this.fileStripMenuItem = new GreenshotToolStripMenuItem();
- this.editToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.undoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.redoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator();
- this.cutToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.copyToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.pasteToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
- this.duplicateToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
- this.preferencesToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
- this.insert_window_toolstripmenuitem = new GreenshotToolStripMenuItem();
- this.objectToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addRectangleToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addEllipseToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.drawLineToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.drawArrowToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.drawFreehandToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addTextBoxToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addSpeechBubbleToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.addCounterToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
- this.selectAllToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.removeObjectToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
- this.arrangeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.upToTopToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.upOneLevelToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.downOneLevelToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.downToBottomToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.saveElementsToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.loadElementsToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.pluginToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.helpToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.helpToolStripMenuItem1 = new GreenshotToolStripMenuItem();
- this.aboutToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.destinationsToolStrip = new ToolStripEx();
- this.btnSave = new GreenshotToolStripButton();
- this.btnClipboard = new GreenshotToolStripButton();
- this.btnPrint = new GreenshotToolStripButton();
- this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
- this.btnDelete = new GreenshotToolStripButton();
- this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
- this.btnCut = new GreenshotToolStripButton();
- this.btnCopy = new GreenshotToolStripButton();
- this.btnPaste = new GreenshotToolStripButton();
- this.btnUndo = new System.Windows.Forms.ToolStripButton();
- this.btnRedo = new System.Windows.Forms.ToolStripButton();
- this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
- this.btnSettings = new GreenshotToolStripButton();
- this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator();
- this.btnHelp = new GreenshotToolStripButton();
- this.propertiesToolStrip = new ToolStripEx();
- this.obfuscateModeButton = new BindableToolStripDropDownButton();
- this.cropModeButton = new BindableToolStripDropDownButton();
- this.pixelizeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.blurToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.defaultCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.verticalCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.horizontalCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.autoCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.highlightModeButton = new BindableToolStripDropDownButton();
- this.textHighlightMenuItem = new GreenshotToolStripMenuItem();
- this.areaHighlightMenuItem = new GreenshotToolStripMenuItem();
- this.grayscaleHighlightMenuItem = new GreenshotToolStripMenuItem();
- this.magnifyMenuItem = new GreenshotToolStripMenuItem();
- this.btnFillColor = new ToolStripColorButton();
- this.btnLineColor = new ToolStripColorButton();
- this.lineThicknessLabel = new GreenshotToolStripLabel();
- this.lineThicknessUpDown = new ToolStripNumericUpDown();
- this.counterLabel = new GreenshotToolStripLabel();
- this.counterUpDown = new ToolStripNumericUpDown();
- this.fontFamilyComboBox = new FontFamilyComboBox();
- this.fontSizeLabel = new GreenshotToolStripLabel();
- this.fontSizeUpDown = new ToolStripNumericUpDown();
- this.fontBoldButton = new BindableToolStripButton();
- this.fontItalicButton = new BindableToolStripButton();
- this.textVerticalAlignmentButton = new BindableToolStripDropDownButton();
- this.alignTopToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.alignMiddleToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.alignBottomToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.blurRadiusLabel = new GreenshotToolStripLabel();
- this.blurRadiusUpDown = new ToolStripNumericUpDown();
- this.brightnessLabel = new GreenshotToolStripLabel();
- this.brightnessUpDown = new ToolStripNumericUpDown();
- this.previewQualityLabel = new GreenshotToolStripLabel();
- this.previewQualityUpDown = new ToolStripNumericUpDown();
- this.magnificationFactorLabel = new GreenshotToolStripLabel();
- this.magnificationFactorUpDown = new ToolStripNumericUpDown();
- this.pixelSizeLabel = new GreenshotToolStripLabel();
- this.pixelSizeUpDown = new ToolStripNumericUpDown();
- this.arrowHeadsLabel = new GreenshotToolStripLabel();
- this.arrowHeadsDropDownButton = new GreenshotToolStripDropDownButton();
- this.arrowHeadStartMenuItem = new GreenshotToolStripMenuItem();
- this.arrowHeadEndMenuItem = new GreenshotToolStripMenuItem();
- this.arrowHeadBothMenuItem = new GreenshotToolStripMenuItem();
- this.arrowHeadNoneMenuItem = new GreenshotToolStripMenuItem();
- this.shadowButton = new BindableToolStripButton();
- this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
- this.btnConfirm = new BindableToolStripButton();
- this.btnCancel = new BindableToolStripButton();
- this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator();
- this.closeToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.fileSavedStatusContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.copyPathMenuItem = new GreenshotToolStripMenuItem();
- this.openDirectoryMenuItem = new GreenshotToolStripMenuItem();
- this.textHorizontalAlignmentButton = new BindableToolStripDropDownButton();
- this.alignLeftToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.alignCenterToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.alignRightToolStripMenuItem = new GreenshotToolStripMenuItem();
- this.zoomMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.zoomInMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomOutMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomMenuSeparator1 = new System.Windows.Forms.ToolStripSeparator();
- this.zoomBestFitMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomMenuSeparator2 = new System.Windows.Forms.ToolStripSeparator();
- this.zoom25MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom50MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom66MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom75MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomMenuSeparator3 = new System.Windows.Forms.ToolStripSeparator();
- this.zoomActualSizeMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomMenuSeparator4 = new System.Windows.Forms.ToolStripSeparator();
- this.zoom200MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom300MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom400MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoom600MenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.zoomStatusDropDownBtn = new System.Windows.Forms.ToolStripDropDownButton();
- this.zoomMainMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.statusStripSpacer = new System.Windows.Forms.ToolStripStatusLabel();
- this.topToolStripContainer.BottomToolStripPanel.SuspendLayout();
- this.topToolStripContainer.ContentPanel.SuspendLayout();
- this.topToolStripContainer.LeftToolStripPanel.SuspendLayout();
- this.topToolStripContainer.TopToolStripPanel.SuspendLayout();
- this.topToolStripContainer.SuspendLayout();
- this.statusStrip1.SuspendLayout();
- this.tableLayoutPanel1.SuspendLayout();
- this.toolsToolStrip.SuspendLayout();
- this.menuStrip1.SuspendLayout();
- this.zoomMenuStrip.SuspendLayout();
- this.destinationsToolStrip.SuspendLayout();
- this.propertiesToolStrip.SuspendLayout();
- this.fileSavedStatusContextMenu.SuspendLayout();
- this.SuspendLayout();
- //
- // topToolStripContainer
- //
- this.topToolStripContainer.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.topToolStripContainer.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- //
- // topToolStripContainer.BottomToolStripPanel
- //
- this.topToolStripContainer.BottomToolStripPanel.Controls.Add(this.statusStrip1);
- //
- // topToolStripContainer.ContentPanel
- //
- this.topToolStripContainer.ContentPanel.AutoScroll = true;
- this.topToolStripContainer.ContentPanel.Controls.Add(this.tableLayoutPanel1);
- this.topToolStripContainer.ContentPanel.Size = new System.Drawing.Size(761, 385);
- this.topToolStripContainer.Dock = System.Windows.Forms.DockStyle.Fill;
- this.topToolStripContainer.LeftToolStripPanel.Join(this.toolsToolStrip,0);
- this.topToolStripContainer.Location = new System.Drawing.Point(0, 0);
- this.topToolStripContainer.Name = "toolStripContainer1";
- this.topToolStripContainer.Size = new System.Drawing.Size(785, 485);
- this.topToolStripContainer.TabIndex = 2;
- this.topToolStripContainer.Text = "toolStripContainer1";
- this.topToolStripContainer.TopToolStripPanel.Join(this.menuStrip1,0);
- this.topToolStripContainer.TopToolStripPanel.Join(this.destinationsToolStrip, 1);
- this.topToolStripContainer.TopToolStripPanel.Join(this.propertiesToolStrip, 2);
- //
- // statusStrip1
- //
- this.statusStrip1.Dock = System.Windows.Forms.DockStyle.None;
- this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.dimensionsLabel,
- this.statusLabel,
- this.statusStripSpacer,
- this.zoomStatusDropDownBtn});
- this.statusStrip1.Location = new System.Drawing.Point(0, 0);
- this.statusStrip1.Name = "statusStrip1";
- this.statusStrip1.Size = new System.Drawing.Size(785, 24);
- this.statusStrip1.TabIndex = 3;
- this.statusStrip1.Text = "statusStrip1";
- //
- // dimensionsLabel
- //
- this.dimensionsLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top)
- | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right)
- | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom)));
- this.dimensionsLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Sunken;
- this.dimensionsLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
- this.dimensionsLabel.Name = "dimensionsLabel";
- this.dimensionsLabel.Text = "123x321";
- //
- // statusLabel
- //
- this.statusLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top)
- | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right)
- | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom)));
- this.statusLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Sunken;
- this.statusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
- this.statusLabel.Name = "statusLabel";
- this.statusLabel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.StatusLabelClicked);
- //
- // tableLayoutPanel1
- //
- this.tableLayoutPanel1.BackColor = System.Drawing.SystemColors.Control;
- this.tableLayoutPanel1.ColumnCount = 1;
- this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0);
- this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
- this.tableLayoutPanel1.Name = "tableLayoutPanel1";
- this.tableLayoutPanel1.RowCount = 1;
- this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 385F));
- this.tableLayoutPanel1.Size = new System.Drawing.Size(761, 385);
- this.tableLayoutPanel1.TabIndex = 3;
- //
- // panel1
- //
- this.panel1.AutoScroll = true;
- this.panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
- this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
- this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.panel1.Location = new System.Drawing.Point(3, 3);
- this.panel1.Name = "panel1";
- this.panel1.Size = new System.Drawing.Size(755, 379);
- this.panel1.TabIndex = 2;
- //
- // toolsToolStrip
- //
- this.toolsToolStrip.ClickThrough = true;
- this.toolsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
- this.toolsToolStrip.Dock = System.Windows.Forms.DockStyle.None;
- this.toolsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
- this.toolsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
- this.toolsToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.btnCursor,
- this.toolStripSeparator1,
- this.btnRect,
- this.btnEllipse,
- this.btnLine,
- this.btnArrow,
- this.btnFreehand,
- this.btnText,
- this.btnSpeechBubble,
- this.btnStepLabel,
- this.toolStripSeparator14,
- this.btnHighlight,
- this.btnObfuscate,
- this.toolStripSplitButton1,
- this.toolStripSeparator13,
- this.btnCrop,
- this.rotateCwToolstripButton,
- this.rotateCcwToolstripButton,
- this.btnResize});
- this.toolsToolStrip.Name = "toolsToolStrip";
- this.toolsToolStrip.Stretch = true;
- this.toolsToolStrip.TabIndex = 0;
- this.toolsToolStrip.BackColor = System.Drawing.SystemColors.Control;
- this.toolsToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
- //
- // btnCursor
- //
- this.btnCursor.Checked = true;
- this.btnCursor.CheckOnClick = true;
- this.btnCursor.CheckState = System.Windows.Forms.CheckState.Checked;
- this.btnCursor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnCursor.Image = ((System.Drawing.Image)(resources.GetObject("btnCursor.Image")));
- this.btnCursor.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnCursor.LanguageKey = "editor_cursortool";
- this.btnCursor.Name = "btnCursor";
- this.btnCursor.Click += new System.EventHandler(this.BtnCursorClick);
- //
- // toolStripSeparator1
- //
- this.toolStripSeparator1.Name = "toolStripSeparator1";
- //
- // btnRect
- //
- this.btnRect.CheckOnClick = true;
- this.btnRect.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnRect.Image = ((System.Drawing.Image)(resources.GetObject("btnRect.Image")));
- this.btnRect.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnRect.LanguageKey = "editor_drawrectangle";
- this.btnRect.Name = "btnRect";
- this.btnRect.Click += new System.EventHandler(this.BtnRectClick);
- //
- // btnEllipse
- //
- this.btnEllipse.CheckOnClick = true;
- this.btnEllipse.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnEllipse.Image = ((System.Drawing.Image)(resources.GetObject("btnEllipse.Image")));
- this.btnEllipse.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnEllipse.LanguageKey = "editor_drawellipse";
- this.btnEllipse.Name = "btnEllipse";
- this.btnEllipse.Click += new System.EventHandler(this.BtnEllipseClick);
- //
- // btnLine
- //
- this.btnLine.CheckOnClick = true;
- this.btnLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnLine.Image = ((System.Drawing.Image)(resources.GetObject("btnLine.Image")));
- this.btnLine.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnLine.LanguageKey = "editor_drawline";
- this.btnLine.Name = "btnLine";
- this.btnLine.Click += new System.EventHandler(this.BtnLineClick);
- //
- // btnArrow
- //
- this.btnArrow.CheckOnClick = true;
- this.btnArrow.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnArrow.Image = ((System.Drawing.Image)(resources.GetObject("btnArrow.Image")));
- this.btnArrow.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnArrow.LanguageKey = "editor_drawarrow";
- this.btnArrow.Name = "btnArrow";
- this.btnArrow.Click += new System.EventHandler(this.BtnArrowClick);
- //
- // btnFreehand
- //
- this.btnFreehand.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnFreehand.Image = ((System.Drawing.Image)(resources.GetObject("btnFreehand.Image")));
- this.btnFreehand.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnFreehand.LanguageKey = "editor_drawfreehand";
- this.btnFreehand.Name = "btnFreehand";
- this.btnFreehand.Click += new System.EventHandler(this.BtnFreehandClick);
- //
- // btnText
- //
- this.btnText.CheckOnClick = true;
- this.btnText.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnText.Image = ((System.Drawing.Image)(resources.GetObject("btnText.Image")));
- this.btnText.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnText.LanguageKey = "editor_drawtextbox";
- this.btnText.Name = "btnText";
- this.btnText.Click += new System.EventHandler(this.BtnTextClick);
- //
- // btnSpeechBubble
- //
- this.btnSpeechBubble.CheckOnClick = true;
- this.btnSpeechBubble.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnSpeechBubble.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image")));
- this.btnSpeechBubble.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnSpeechBubble.LanguageKey = "editor_speechbubble";
- this.btnSpeechBubble.Name = "btnSpeechBubble";
- this.btnSpeechBubble.Click += new System.EventHandler(this.BtnSpeechBubbleClick);
- //
- // btnStepLabel
- //
- this.btnStepLabel.CheckOnClick = true;
- this.btnStepLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnStepLabel.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image")));
- this.btnStepLabel.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnStepLabel.LanguageKey = "editor_counter";
- this.btnStepLabel.Name = "btnStepLabel";
- this.btnStepLabel.Click += new System.EventHandler(this.BtnStepLabelClick);
- //
- // toolStripSeparator14
- //
- this.toolStripSeparator14.Name = "toolStripSeparator14";
- //
- // btnHighlight
- //
- this.btnHighlight.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnHighlight.Image = ((System.Drawing.Image)(resources.GetObject("btnHighlight.Image")));
- this.btnHighlight.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnHighlight.LanguageKey = "editor_drawhighlighter";
- this.btnHighlight.Name = "btnHighlight";
- this.btnHighlight.Click += new System.EventHandler(this.BtnHighlightClick);
- //
- // btnObfuscate
- //
- this.btnObfuscate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnObfuscate.Image = ((System.Drawing.Image)(resources.GetObject("btnObfuscate.Image")));
- this.btnObfuscate.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnObfuscate.LanguageKey = "editor_obfuscate";
- this.btnObfuscate.Name = "btnObfuscate";
- this.btnObfuscate.Click += new System.EventHandler(this.BtnObfuscateClick);
- //
- // toolStripSplitButton1
- //
- this.toolStripSplitButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.toolStripSplitButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.addBorderToolStripMenuItem,
- this.addDropshadowToolStripMenuItem,
- this.tornEdgesToolStripMenuItem,
- this.grayscaleToolStripMenuItem,
- this.invertToolStripMenuItem});
- this.toolStripSplitButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripSplitButton1.Image")));
- this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.toolStripSplitButton1.LanguageKey = "editor_effects";
- this.toolStripSplitButton1.Name = "toolStripSplitButton1";
- this.toolStripSplitButton1.ShowDropDownArrow = false;
- this.toolStripSplitButton1.Text = "toolStripSplitButton1";
- //
- // addBorderToolStripMenuItem
- //
- this.addBorderToolStripMenuItem.LanguageKey = "editor_border";
- this.addBorderToolStripMenuItem.Name = "addBorderToolStripMenuItem";
- this.addBorderToolStripMenuItem.Click += new System.EventHandler(this.AddBorderToolStripMenuItemClick);
- //
- // addDropshadowToolStripMenuItem
- //
- this.addDropshadowToolStripMenuItem.LanguageKey = "editor_image_shadow";
- this.addDropshadowToolStripMenuItem.Name = "addDropshadowToolStripMenuItem";
- this.addDropshadowToolStripMenuItem.MouseUp += AddDropshadowToolStripMenuItemMouseUp;
- //
- // tornEdgesToolStripMenuItem
- //
- this.tornEdgesToolStripMenuItem.LanguageKey = "editor_torn_edge";
- this.tornEdgesToolStripMenuItem.Name = "tornEdgesToolStripMenuItem";
- this.tornEdgesToolStripMenuItem.MouseUp += TornEdgesToolStripMenuItemMouseUp;
- //
- // grayscaleToolStripMenuItem
- //
- this.grayscaleToolStripMenuItem.LanguageKey = "editor_grayscale";
- this.grayscaleToolStripMenuItem.Name = "grayscaleToolStripMenuItem";
- this.grayscaleToolStripMenuItem.Click += new System.EventHandler(this.GrayscaleToolStripMenuItemClick);
- //
- // invertToolStripMenuItem
- //
- this.invertToolStripMenuItem.LanguageKey = "editor_invert";
- this.invertToolStripMenuItem.Name = "invertToolStripMenuItem";
- this.invertToolStripMenuItem.Click += new System.EventHandler(this.InvertToolStripMenuItemClick);
- //
- // btnResize
- //
- this.btnResize.Name = "btnResize";
- this.btnResize.Click += new System.EventHandler(this.BtnResizeClick);
- this.btnResize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnResize.Image = ((System.Drawing.Image)(resources.GetObject("btnResize.Image")));
- this.btnResize.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnResize.LanguageKey = "editor_resize";
- //
- // toolStripSeparator13
- //
- this.toolStripSeparator13.Name = "toolStripSeparator13";
- //
- // btnCrop
- //
- this.btnCrop.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnCrop.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
- this.btnCrop.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnCrop.LanguageKey = "editor_crop";
- this.btnCrop.Name = "btnCrop";
- this.btnCrop.Click += new System.EventHandler(this.BtnCropClick);
- //
- // rotateCwToolstripButton
- //
- this.rotateCwToolstripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.rotateCwToolstripButton.Image = ((System.Drawing.Image)(resources.GetObject("rotateCwToolstripButton.Image")));
- this.rotateCwToolstripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.rotateCwToolstripButton.LanguageKey = "editor_rotatecw";
- this.rotateCwToolstripButton.Name = "rotateCwToolstripButton";
- this.rotateCwToolstripButton.Click += new System.EventHandler(this.RotateCwToolstripButtonClick);
- //
- // rotateCcwToolstripButton
- //
- this.rotateCcwToolstripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.rotateCcwToolstripButton.Image = ((System.Drawing.Image)(resources.GetObject("rotateCcwToolstripButton.Image")));
- this.rotateCcwToolstripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.rotateCcwToolstripButton.LanguageKey = "editor_rotateccw";
- this.rotateCcwToolstripButton.Name = "rotateCcwToolstripButton";
- this.rotateCcwToolstripButton.Click += new System.EventHandler(this.RotateCcwToolstripButtonClick);
- //
- // menuStrip1
- //
- this.menuStrip1.ClickThrough = true;
- this.menuStrip1.ImageScalingSize = coreConfiguration.IconSize;
- this.menuStrip1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.menuStrip1.Stretch = true;
- this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.fileStripMenuItem,
- this.editToolStripMenuItem,
- this.objectToolStripMenuItem,
- this.pluginToolStripMenuItem,
- this.zoomMainMenuItem,
- this.helpToolStripMenuItem});
- this.menuStrip1.Name = "menuStrip1";
- this.menuStrip1.BackColor = System.Drawing.SystemColors.Control;
- this.menuStrip1.TabIndex = 1;
- //
- // fileStripMenuItem
- //
- this.fileStripMenuItem.LanguageKey = "editor_file";
- this.fileStripMenuItem.Name = "fileStripMenuItem";
- this.fileStripMenuItem.Size = new System.Drawing.Size(37, 20);
- this.fileStripMenuItem.Text = "File";
- this.fileStripMenuItem.DropDownOpening += new System.EventHandler(this.FileMenuDropDownOpening);
- // Fix for BUG-1653, the DropDownOpening is not called when there are no children.
- this.fileStripMenuItem.DropDownItems.Add(toolStripSeparator9);
- //
- // editToolStripMenuItem
- //
- this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.undoToolStripMenuItem,
- this.redoToolStripMenuItem,
- this.toolStripSeparator15,
- this.cutToolStripMenuItem,
- this.copyToolStripMenuItem,
- this.pasteToolStripMenuItem,
- this.toolStripSeparator4,
- this.duplicateToolStripMenuItem,
- this.toolStripSeparator12,
- this.preferencesToolStripMenuItem,
- this.toolStripSeparator5,
- this.insert_window_toolstripmenuitem});
- this.editToolStripMenuItem.LanguageKey = "editor_edit";
- this.editToolStripMenuItem.Name = "editToolStripMenuItem";
- this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
- this.editToolStripMenuItem.Text = "Edit";
- this.editToolStripMenuItem.Click += new System.EventHandler(this.EditToolStripMenuItemClick);
- //
- // undoToolStripMenuItem
- //
- this.undoToolStripMenuItem.Enabled = false;
- this.undoToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("undoToolStripMenuItem.Image")));
- this.undoToolStripMenuItem.Name = "undoToolStripMenuItem";
- this.undoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
- this.undoToolStripMenuItem.Text = "Undo";
- this.undoToolStripMenuItem.Click += new System.EventHandler(this.UndoToolStripMenuItemClick);
- //
- // redoToolStripMenuItem
- //
- this.redoToolStripMenuItem.Enabled = false;
- this.redoToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("redoToolStripMenuItem.Image")));
- this.redoToolStripMenuItem.Name = "redoToolStripMenuItem";
- this.redoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y)));
- this.redoToolStripMenuItem.Text = "Redo";
- this.redoToolStripMenuItem.Click += new System.EventHandler(this.RedoToolStripMenuItemClick);
- //
- // toolStripSeparator15
- //
- this.toolStripSeparator15.Name = "toolStripSeparator15";
- //
- // cutToolStripMenuItem
- //
- this.cutToolStripMenuItem.Enabled = false;
- this.cutToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cutToolStripMenuItem.Image")));
- this.cutToolStripMenuItem.LanguageKey = "editor_cuttoclipboard";
- this.cutToolStripMenuItem.Name = "cutToolStripMenuItem";
- this.cutToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
- this.cutToolStripMenuItem.Click += new System.EventHandler(this.CutToolStripMenuItemClick);
- //
- // copyToolStripMenuItem
- //
- this.copyToolStripMenuItem.Enabled = false;
- this.copyToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("copyToolStripMenuItem.Image")));
- this.copyToolStripMenuItem.LanguageKey = "editor_copytoclipboard";
- this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
- this.copyToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
- this.copyToolStripMenuItem.Click += new System.EventHandler(this.CopyToolStripMenuItemClick);
- //
- // pasteToolStripMenuItem
- //
- this.pasteToolStripMenuItem.Enabled = false;
- this.pasteToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pasteToolStripMenuItem.Image")));
- this.pasteToolStripMenuItem.LanguageKey = "editor_pastefromclipboard";
- this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem";
- this.pasteToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
- this.pasteToolStripMenuItem.Click += new System.EventHandler(this.PasteToolStripMenuItemClick);
- //
- // toolStripSeparator4
- //
- this.toolStripSeparator4.Name = "toolStripSeparator4";
- //
- // duplicateToolStripMenuItem
- //
- this.duplicateToolStripMenuItem.Enabled = false;
- this.duplicateToolStripMenuItem.LanguageKey = "editor_duplicate";
- this.duplicateToolStripMenuItem.Name = "duplicateToolStripMenuItem";
- this.duplicateToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D)));
- this.duplicateToolStripMenuItem.Click += new System.EventHandler(this.DuplicateToolStripMenuItemClick);
- //
- // toolStripSeparator12
- //
- this.toolStripSeparator12.Name = "toolStripSeparator12";
- //
- // preferencesToolStripMenuItem
- //
- this.preferencesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("preferencesToolStripMenuItem.Image")));
- this.preferencesToolStripMenuItem.LanguageKey = "contextmenu_settings";
- this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem";
- this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.PreferencesToolStripMenuItemClick);
- //
- // toolStripSeparator5
- //
- this.toolStripSeparator5.Name = "toolStripSeparator5";
- //
- // insert_window_toolstripmenuitem
- //
- this.insert_window_toolstripmenuitem.LanguageKey = "editor_insertwindow";
- this.insert_window_toolstripmenuitem.Name = "insert_window_toolstripmenuitem";
- this.insert_window_toolstripmenuitem.MouseEnter += new System.EventHandler(this.Insert_window_toolstripmenuitemMouseEnter);
- //
- // objectToolStripMenuItem
- //
- this.objectToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.addRectangleToolStripMenuItem,
- this.addEllipseToolStripMenuItem,
- this.drawLineToolStripMenuItem,
- this.drawArrowToolStripMenuItem,
- this.drawFreehandToolStripMenuItem,
- this.addTextBoxToolStripMenuItem,
- this.addSpeechBubbleToolStripMenuItem,
- this.addCounterToolStripMenuItem,
- this.toolStripSeparator8,
- this.selectAllToolStripMenuItem,
- this.removeObjectToolStripMenuItem,
- this.toolStripSeparator7,
- this.arrangeToolStripMenuItem,
- this.saveElementsToolStripMenuItem,
- this.loadElementsToolStripMenuItem});
- this.objectToolStripMenuItem.LanguageKey = "editor_object";
- this.objectToolStripMenuItem.Name = "objectToolStripMenuItem";
- this.objectToolStripMenuItem.Size = new System.Drawing.Size(54, 20);
- this.objectToolStripMenuItem.Text = "Object";
- //
- // addRectangleToolStripMenuItem
- //
- this.addRectangleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addRectangleToolStripMenuItem.Image")));
- this.addRectangleToolStripMenuItem.LanguageKey = "editor_drawrectangle";
- this.addRectangleToolStripMenuItem.Name = "addRectangleToolStripMenuItem";
- this.addRectangleToolStripMenuItem.Click += new System.EventHandler(this.AddRectangleToolStripMenuItemClick);
- //
- // addEllipseToolStripMenuItem
- //
- this.addEllipseToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addEllipseToolStripMenuItem.Image")));
- this.addEllipseToolStripMenuItem.LanguageKey = "editor_drawellipse";
- this.addEllipseToolStripMenuItem.Name = "addEllipseToolStripMenuItem";
- this.addEllipseToolStripMenuItem.Click += new System.EventHandler(this.AddEllipseToolStripMenuItemClick);
- //
- // drawLineToolStripMenuItem
- //
- this.drawLineToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawLineToolStripMenuItem.Image")));
- this.drawLineToolStripMenuItem.LanguageKey = "editor_drawline";
- this.drawLineToolStripMenuItem.Name = "drawLineToolStripMenuItem";
- this.drawLineToolStripMenuItem.Click += new System.EventHandler(this.DrawLineToolStripMenuItemClick);
- //
- // drawArrowToolStripMenuItem
- //
- this.drawArrowToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawArrowToolStripMenuItem.Image")));
- this.drawArrowToolStripMenuItem.LanguageKey = "editor_drawarrow";
- this.drawArrowToolStripMenuItem.Name = "drawArrowToolStripMenuItem";
- this.drawArrowToolStripMenuItem.Click += new System.EventHandler(this.DrawArrowToolStripMenuItemClick);
- //
- // drawFreehandToolStripMenuItem
- //
- this.drawFreehandToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawFreehandToolStripMenuItem.Image")));
- this.drawFreehandToolStripMenuItem.LanguageKey = "editor_drawfreehand";
- this.drawFreehandToolStripMenuItem.Name = "drawFreehandToolStripMenuItem";
- this.drawFreehandToolStripMenuItem.Click += new System.EventHandler(this.DrawFreehandToolStripMenuItemClick);
- //
- // addTextBoxToolStripMenuItem
- //
- this.addTextBoxToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addTextBoxToolStripMenuItem.Image")));
- this.addTextBoxToolStripMenuItem.LanguageKey = "editor_drawtextbox";
- this.addTextBoxToolStripMenuItem.Name = "addTextBoxToolStripMenuItem";
- this.addTextBoxToolStripMenuItem.Click += new System.EventHandler(this.AddTextBoxToolStripMenuItemClick);
- //
- // addSpeechBubbleToolStripMenuItem
- //
- this.addSpeechBubbleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image")));
- this.addSpeechBubbleToolStripMenuItem.LanguageKey = "editor_speechbubble";
- this.addSpeechBubbleToolStripMenuItem.Name = "addSpeechBubbleToolStripMenuItem";
- this.addSpeechBubbleToolStripMenuItem.Click += new System.EventHandler(this.AddSpeechBubbleToolStripMenuItemClick);
- //
- // addCounterToolStripMenuItem
- //
- this.addCounterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image")));
- this.addCounterToolStripMenuItem.LanguageKey = "editor_counter";
- this.addCounterToolStripMenuItem.Name = "addCounterToolStripMenuItem";
- this.addCounterToolStripMenuItem.Click += new System.EventHandler(this.AddCounterToolStripMenuItemClick);
- //
- // toolStripSeparator8
- //
- this.toolStripSeparator8.Name = "toolStripSeparator8";
- //
- // selectAllToolStripMenuItem
- //
- this.selectAllToolStripMenuItem.LanguageKey = "editor_selectall";
- this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem";
- this.selectAllToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
- this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.SelectAllToolStripMenuItemClick);
- //
- // removeObjectToolStripMenuItem
- //
- this.removeObjectToolStripMenuItem.Enabled = false;
- this.removeObjectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("removeObjectToolStripMenuItem.Image")));
- this.removeObjectToolStripMenuItem.LanguageKey = "editor_deleteelement";
- this.removeObjectToolStripMenuItem.Name = "removeObjectToolStripMenuItem";
- this.removeObjectToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Delete;
- this.removeObjectToolStripMenuItem.Click += new System.EventHandler(this.RemoveObjectToolStripMenuItemClick);
- //
- // toolStripSeparator7
- //
- this.toolStripSeparator7.Name = "toolStripSeparator7";
- //
- // arrangeToolStripMenuItem
- //
- this.arrangeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.upToTopToolStripMenuItem,
- this.upOneLevelToolStripMenuItem,
- this.downOneLevelToolStripMenuItem,
- this.downToBottomToolStripMenuItem});
- this.arrangeToolStripMenuItem.Enabled = false;
- this.arrangeToolStripMenuItem.LanguageKey = "editor_arrange";
- this.arrangeToolStripMenuItem.Name = "arrangeToolStripMenuItem";
- //
- // upToTopToolStripMenuItem
- //
- this.upToTopToolStripMenuItem.Enabled = false;
- this.upToTopToolStripMenuItem.LanguageKey = "editor_uptotop";
- this.upToTopToolStripMenuItem.Name = "upToTopToolStripMenuItem";
- this.upToTopToolStripMenuItem.ShortcutKeyDisplayString = "Home";
- this.upToTopToolStripMenuItem.Click += new System.EventHandler(this.UpToTopToolStripMenuItemClick);
- //
- // upOneLevelToolStripMenuItem
- //
- this.upOneLevelToolStripMenuItem.Enabled = false;
- this.upOneLevelToolStripMenuItem.LanguageKey = "editor_uponelevel";
- this.upOneLevelToolStripMenuItem.Name = "upOneLevelToolStripMenuItem";
- this.upOneLevelToolStripMenuItem.ShortcutKeyDisplayString = "PgUp";
- this.upOneLevelToolStripMenuItem.Click += new System.EventHandler(this.UpOneLevelToolStripMenuItemClick);
- //
- // downOneLevelToolStripMenuItem
- //
- this.downOneLevelToolStripMenuItem.Enabled = false;
- this.downOneLevelToolStripMenuItem.LanguageKey = "editor_downonelevel";
- this.downOneLevelToolStripMenuItem.Name = "downOneLevelToolStripMenuItem";
- this.downOneLevelToolStripMenuItem.ShortcutKeyDisplayString = "PgDn";
- this.downOneLevelToolStripMenuItem.Click += new System.EventHandler(this.DownOneLevelToolStripMenuItemClick);
- //
- // downToBottomToolStripMenuItem
- //
- this.downToBottomToolStripMenuItem.Enabled = false;
- this.downToBottomToolStripMenuItem.LanguageKey = "editor_downtobottom";
- this.downToBottomToolStripMenuItem.Name = "downToBottomToolStripMenuItem";
- this.downToBottomToolStripMenuItem.ShortcutKeyDisplayString = "End";
- this.downToBottomToolStripMenuItem.Click += new System.EventHandler(this.DownToBottomToolStripMenuItemClick);
- //
- // saveElementsToolStripMenuItem
- //
- this.saveElementsToolStripMenuItem.LanguageKey = "editor_save_objects";
- this.saveElementsToolStripMenuItem.Name = "saveElementsToolStripMenuItem";
- this.saveElementsToolStripMenuItem.Click += new System.EventHandler(this.SaveElementsToolStripMenuItemClick);
- //
- // loadElementsToolStripMenuItem
- //
- this.loadElementsToolStripMenuItem.LanguageKey = "editor_load_objects";
- this.loadElementsToolStripMenuItem.Name = "loadElementsToolStripMenuItem";
- this.loadElementsToolStripMenuItem.Click += new System.EventHandler(this.LoadElementsToolStripMenuItemClick);
- //
- // pluginToolStripMenuItem
- //
- this.pluginToolStripMenuItem.LanguageKey = "settings_plugins";
- this.pluginToolStripMenuItem.Name = "pluginToolStripMenuItem";
- this.pluginToolStripMenuItem.Text = "Plugins";
- this.pluginToolStripMenuItem.Visible = false;
- //
- // helpToolStripMenuItem
- //
- this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.helpToolStripMenuItem1,
- this.aboutToolStripMenuItem});
- this.helpToolStripMenuItem.LanguageKey = "contextmenu_help";
- this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
- this.helpToolStripMenuItem.Text = "Help";
- //
- // helpToolStripMenuItem1
- //
- this.helpToolStripMenuItem1.Image = ((System.Drawing.Image)(resources.GetObject("helpToolStripMenuItem1.Image")));
- this.helpToolStripMenuItem1.LanguageKey = "contextmenu_help";
- this.helpToolStripMenuItem1.Name = "helpToolStripMenuItem1";
- this.helpToolStripMenuItem1.ShortcutKeys = System.Windows.Forms.Keys.F1;
- this.helpToolStripMenuItem1.Click += new System.EventHandler(this.HelpToolStripMenuItem1Click);
- //
- // aboutToolStripMenuItem
- //
- this.aboutToolStripMenuItem.LanguageKey = "contextmenu_about";
- this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
- this.aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutToolStripMenuItemClick);
- //
- // destinationsToolStrip
- //
- this.destinationsToolStrip.ClickThrough = true;
- this.destinationsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
- this.destinationsToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
- this.destinationsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
- this.destinationsToolStrip.Name = "toolStrip1";
- this.destinationsToolStrip.Stretch = true;
- this.destinationsToolStrip.TabIndex = 0;
- this.destinationsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
- this.destinationsToolStrip.BackColor = System.Drawing.SystemColors.Control;
- this.destinationsToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
- this.destinationsToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.btnSave,
- this.btnClipboard,
- this.btnPrint,
- this.toolStripSeparator2,
- this.btnDelete,
- this.toolStripSeparator3,
- this.btnCut,
- this.btnCopy,
- this.btnPaste,
- this.btnUndo,
- this.btnRedo,
- this.toolStripSeparator6,
- this.btnSettings,
- this.toolStripSeparator11,
- this.toolStripSeparator16,
- this.btnHelp});
- //
- // btnSave
- //
- this.btnSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnSave.Image = ((System.Drawing.Image)(resources.GetObject("btnSave.Image")));
- this.btnSave.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnSave.LanguageKey = "editor_save";
- this.btnSave.Name = "btnSave";
- this.btnSave.Click += new System.EventHandler(this.BtnSaveClick);
- //
- // btnClipboard
- //
- this.btnClipboard.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnClipboard.Image = ((System.Drawing.Image)(resources.GetObject("btnClipboard.Image")));
- this.btnClipboard.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnClipboard.LanguageKey = "editor_copyimagetoclipboard";
- this.btnClipboard.Name = "btnClipboard";
- this.btnClipboard.Click += new System.EventHandler(this.BtnClipboardClick);
- //
- // btnPrint
- //
- this.btnPrint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnPrint.Image = ((System.Drawing.Image)(resources.GetObject("btnPrint.Image")));
- this.btnPrint.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnPrint.LanguageKey = "editor_print";
- this.btnPrint.Name = "btnPrint";
- this.btnPrint.Text = "Print";
- this.btnPrint.Click += new System.EventHandler(this.BtnPrintClick);
- //
- // toolStripSeparator2
- //
- this.toolStripSeparator2.Name = "toolStripSeparator2";
- //
- // btnDelete
- //
- this.btnDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnDelete.Enabled = false;
- this.btnDelete.Image = ((System.Drawing.Image)(resources.GetObject("btnDelete.Image")));
- this.btnDelete.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnDelete.LanguageKey = "editor_deleteelement";
- this.btnDelete.Name = "btnDelete";
- this.btnDelete.Click += new System.EventHandler(this.BtnDeleteClick);
- //
- // toolStripSeparator3
- //
- this.toolStripSeparator3.Name = "toolStripSeparator3";
- //
- // btnCut
- //
- this.btnCut.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnCut.Enabled = false;
- this.btnCut.Image = ((System.Drawing.Image)(resources.GetObject("btnCut.Image")));
- this.btnCut.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnCut.LanguageKey = "editor_cuttoclipboard";
- this.btnCut.Name = "btnCut";
- this.btnCut.Click += new System.EventHandler(this.BtnCutClick);
- //
- // btnCopy
- //
- this.btnCopy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnCopy.Enabled = false;
- this.btnCopy.Image = ((System.Drawing.Image)(resources.GetObject("btnCopy.Image")));
- this.btnCopy.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnCopy.LanguageKey = "editor_copytoclipboard";
- this.btnCopy.Name = "btnCopy";
- this.btnCopy.Click += new System.EventHandler(this.BtnCopyClick);
- //
- // btnPaste
- //
- this.btnPaste.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnPaste.Enabled = false;
- this.btnPaste.Image = ((System.Drawing.Image)(resources.GetObject("btnPaste.Image")));
- this.btnPaste.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnPaste.LanguageKey = "editor_pastefromclipboard";
- this.btnPaste.Name = "btnPaste";
- this.btnPaste.Click += new System.EventHandler(this.BtnPasteClick);
- //
- // btnUndo
- //
- this.btnUndo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnUndo.Enabled = false;
- this.btnUndo.Image = ((System.Drawing.Image)(resources.GetObject("btnUndo.Image")));
- this.btnUndo.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnUndo.Name = "btnUndo";
- this.btnUndo.Click += new System.EventHandler(this.BtnUndoClick);
- //
- // btnRedo
- //
- this.btnRedo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnRedo.Enabled = false;
- this.btnRedo.Image = ((System.Drawing.Image)(resources.GetObject("btnRedo.Image")));
- this.btnRedo.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnRedo.Name = "btnRedo";
- this.btnRedo.Click += new System.EventHandler(this.BtnRedoClick);
- //
- // toolStripSeparator6
- //
- this.toolStripSeparator6.Name = "toolStripSeparator6";
- //
- // btnSettings
- //
- this.btnSettings.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnSettings.Image = ((System.Drawing.Image)(resources.GetObject("btnSettings.Image")));
- this.btnSettings.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnSettings.LanguageKey = "contextmenu_settings";
- this.btnSettings.Name = "btnSettings";
- this.btnSettings.Click += new System.EventHandler(this.BtnSettingsClick);
- //
- // toolStripSeparator11
- //
- this.toolStripSeparator11.Name = "toolStripSeparator11";
- //
- // toolStripSeparator16
- //
- this.toolStripSeparator16.Name = "toolStripSeparator16";
- //
- // btnHelp
- //
- this.btnHelp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnHelp.Image = ((System.Drawing.Image)(resources.GetObject("btnHelp.Image")));
- this.btnHelp.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnHelp.LanguageKey = "contextmenu_help";
- this.btnHelp.Name = "btnHelp";
- this.btnHelp.Text = "Help";
- this.btnHelp.Click += new System.EventHandler(this.BtnHelpClick);
- //
- // propertiesToolStrip
- //
- this.propertiesToolStrip.ClickThrough = true;
- this.propertiesToolStrip.ImageScalingSize = coreConfiguration.IconSize;
- this.propertiesToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
- this.propertiesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
- this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.IconSize.Height + 10);
- this.propertiesToolStrip.Name = "propertiesToolStrip";
- this.propertiesToolStrip.Stretch = true;
- this.propertiesToolStrip.TabIndex = 2;
- this.propertiesToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
- this.propertiesToolStrip.BackColor = System.Drawing.SystemColors.Control;
- this.propertiesToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
- this.propertiesToolStrip.Paint += PropertiesToolStrip_Paint;
- this.propertiesToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.obfuscateModeButton,
- this.highlightModeButton,
- this.btnFillColor,
- this.btnLineColor,
- this.lineThicknessLabel,
- this.lineThicknessUpDown,
- this.fontFamilyComboBox,
- this.fontSizeLabel,
- this.fontSizeUpDown,
- this.fontBoldButton,
- this.fontItalicButton,
- this.textHorizontalAlignmentButton,
- this.textVerticalAlignmentButton,
- this.blurRadiusLabel,
- this.blurRadiusUpDown,
- this.brightnessLabel,
- this.brightnessUpDown,
- this.previewQualityLabel,
- this.previewQualityUpDown,
- this.magnificationFactorLabel,
- this.magnificationFactorUpDown,
- this.pixelSizeLabel,
- this.pixelSizeUpDown,
- this.arrowHeadsLabel,
- this.arrowHeadsDropDownButton,
- this.shadowButton,
- this.toolStripSeparator,
- this.toolStripSeparator10,
- this.btnConfirm,
- this.btnCancel,
- this.cropModeButton,
- this.counterLabel,
- this.counterUpDown});
- //
- // obfuscateModeButton
- //
- this.obfuscateModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.obfuscateModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.pixelizeToolStripMenuItem,
- this.blurToolStripMenuItem});
- this.obfuscateModeButton.Image = ((System.Drawing.Image)(resources.GetObject("obfuscateModeButton.Image")));
- this.obfuscateModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.obfuscateModeButton.LanguageKey = "editor_obfuscate_mode";
- this.obfuscateModeButton.Name = "obfuscateModeButton";
- this.obfuscateModeButton.SelectedTag = FilterContainer.PreparedFilter.BLUR;
- this.obfuscateModeButton.Tag = FilterContainer.PreparedFilter.BLUR;
- //
- this.obfuscateModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
- // pixelizeToolStripMenuItem
- //
- this.pixelizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pixelizeToolStripMenuItem.Image")));
- this.pixelizeToolStripMenuItem.LanguageKey = "editor_obfuscate_pixelize";
- this.pixelizeToolStripMenuItem.Name = "pixelizeToolStripMenuItem";
- this.pixelizeToolStripMenuItem.Tag = FilterContainer.PreparedFilter.PIXELIZE;
- //
- // blurToolStripMenuItem
- //
- this.blurToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("blurToolStripMenuItem.Image")));
- this.blurToolStripMenuItem.LanguageKey = "editor_obfuscate_blur";
- this.blurToolStripMenuItem.Name = "blurToolStripMenuItem";
- this.blurToolStripMenuItem.Tag = FilterContainer.PreparedFilter.BLUR;
-
- //
- // cropModeButton
- //
- this.cropModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.cropModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.defaultCropModeToolStripMenuItem,
- this.verticalCropModeToolStripMenuItem,
- this.horizontalCropModeToolStripMenuItem,
- this.autoCropModeToolStripMenuItem});
- this.cropModeButton.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
- this.cropModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.cropModeButton.LanguageKey = "editor_crop_mode";
- this.cropModeButton.Name = "cropModeButton";
- this.cropModeButton.SelectedTag = CropContainer.CropModes.Default;
- this.cropModeButton.Tag = CropContainer.CropModes.Default;
- this.cropModeButton.DropDownItemClicked += CropStyleDropDownItemClicked;
- //
- // defaultCropStyleToolStripMenuItem
- //
- this.defaultCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
- this.defaultCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_default";
- this.defaultCropModeToolStripMenuItem.Name = "defaultCropModeToolStripMenuItem";
- this.defaultCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Default;
-
- //
- // verticalCropStyleToolStripMenuItem
- //
- this.verticalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropVertical.Image")));
- this.verticalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_vertical";
- this.verticalCropModeToolStripMenuItem.Name = "verticalCropModeToolStripMenuItem";
- this.verticalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Vertical;
-
- //
- // horizontalCropStyleToolStripMenuItem
- //
- this.horizontalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropHorizontal.Image")));
- this.horizontalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_horizontal";
- this.horizontalCropModeToolStripMenuItem.Name = "horizontalCropModeToolStripMenuItem";
- this.horizontalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Horizontal;
-
- //
- // autoCropModeToolStripMenuItem
- //
- this.autoCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("AutoCrop.Image")));
- this.autoCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_auto";
- this.autoCropModeToolStripMenuItem.Name = "autoCropModeToolStripMenuItem";
- this.autoCropModeToolStripMenuItem.Tag = CropContainer.CropModes.AutoCrop;
-
- //
- // highlightModeButton
- //
- this.highlightModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.highlightModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.textHighlightMenuItem,
- this.areaHighlightMenuItem,
- this.grayscaleHighlightMenuItem,
- this.magnifyMenuItem});
- this.highlightModeButton.Image = ((System.Drawing.Image)(resources.GetObject("highlightModeButton.Image")));
- this.highlightModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.highlightModeButton.LanguageKey = "editor_highlight_mode";
- this.highlightModeButton.Name = "highlightModeButton";
- this.highlightModeButton.SelectedTag = FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
- this.highlightModeButton.Tag = FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
- this.highlightModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
- //
- // textHighlightMenuItem
- //
- this.textHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("textHighlightMenuItem.Image")));
- this.textHighlightMenuItem.LanguageKey = "editor_highlight_text";
- this.textHighlightMenuItem.Name = "textHighlightMenuItem";
- this.textHighlightMenuItem.Tag = FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
- //
- // areaHighlightMenuItem
- //
- this.areaHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("areaHighlightMenuItem.Image")));
- this.areaHighlightMenuItem.LanguageKey = "editor_highlight_area";
- this.areaHighlightMenuItem.Name = "areaHighlightMenuItem";
- this.areaHighlightMenuItem.Tag = FilterContainer.PreparedFilter.AREA_HIGHLIGHT;
- //
- // grayscaleHighlightMenuItem
- //
- this.grayscaleHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("grayscaleHighlightMenuItem.Image")));
- this.grayscaleHighlightMenuItem.LanguageKey = "editor_highlight_grayscale";
- this.grayscaleHighlightMenuItem.Name = "grayscaleHighlightMenuItem";
- this.grayscaleHighlightMenuItem.Tag = FilterContainer.PreparedFilter.GRAYSCALE;
- //
- // magnifyMenuItem
- //
- this.magnifyMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("magnifyMenuItem.Image")));
- this.magnifyMenuItem.LanguageKey = "editor_highlight_magnify";
- this.magnifyMenuItem.Name = "magnifyMenuItem";
- this.magnifyMenuItem.Tag = FilterContainer.PreparedFilter.MAGNIFICATION;
- //
- // btnFillColor
- //
- this.btnFillColor.BackColor = System.Drawing.Color.Transparent;
- this.btnFillColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnFillColor.Image = ((System.Drawing.Image)(resources.GetObject("btnFillColor.Image")));
- this.btnFillColor.LanguageKey = "editor_backcolor";
- this.btnFillColor.Name = "btnFillColor";
- this.btnFillColor.SelectedColor = System.Drawing.Color.Transparent;
- //
- // btnLineColor
- //
- this.btnLineColor.BackColor = System.Drawing.Color.Transparent;
- this.btnLineColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnLineColor.Image = ((System.Drawing.Image)(resources.GetObject("btnLineColor.Image")));
- this.btnLineColor.LanguageKey = "editor_forecolor";
- this.btnLineColor.Name = "btnLineColor";
- this.btnLineColor.SelectedColor = System.Drawing.Color.FromArgb(((int)(((byte)(203)))), ((int)(((byte)(222)))), ((int)(((byte)(250)))));
- //
- // counterLabel
- //
- this.counterLabel.LanguageKey = "editor_counter_startvalue";
- this.counterLabel.Name = "counterLabel";
- //
- // counterUpDown
- //
- this.counterUpDown.DecimalPlaces = 0;
- this.counterUpDown.Increment = 1;
- this.counterUpDown.Maximum = 100;
- this.counterUpDown.Minimum = 0;
- this.counterUpDown.Name = "counterUpDown";
- this.counterUpDown.Text = "1";
- this.counterUpDown.Value = 1;
- this.counterUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.counterUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // lineThicknessLabel
- //
- this.lineThicknessLabel.LanguageKey = "editor_thickness";
- this.lineThicknessLabel.Name = "lineThicknessLabel";
- //
- // lineThicknessUpDown
- //
- this.lineThicknessUpDown.DecimalPlaces = 0;
- this.lineThicknessUpDown.Increment = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.lineThicknessUpDown.Maximum = new decimal(new int[] {
- 100,
- 0,
- 0,
- 0});
- this.lineThicknessUpDown.Minimum = new decimal(new int[] {
- 0,
- 0,
- 0,
- 0});
- this.lineThicknessUpDown.Name = "lineThicknessUpDown";
- this.lineThicknessUpDown.Text = "0";
- this.lineThicknessUpDown.Value = new decimal(new int[] {
- 0,
- 0,
- 0,
- 0});
- this.lineThicknessUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.lineThicknessUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // fontFamilyComboBox
- //
- this.fontFamilyComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.fontFamilyComboBox.MaxDropDownItems = 20;
- this.fontFamilyComboBox.Name = "fontFamilyComboBox";
- this.fontFamilyComboBox.Size = new System.Drawing.Size(200, 20);
- this.fontFamilyComboBox.Text = "Aharoni";
- this.fontFamilyComboBox.Padding = new System.Windows.Forms.Padding(2,0,0,2);
- this.fontFamilyComboBox.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.fontFamilyComboBox.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- this.fontFamilyComboBox.PropertyChanged += FontPropertyChanged;
- //
- // fontSizeLabel
- //
- this.fontSizeLabel.LanguageKey = "editor_fontsize";
- this.fontSizeLabel.Name = "fontSizeLabel";
- //
- // fontSizeUpDown
- //
- this.fontSizeUpDown.DecimalPlaces = 0;
- this.fontSizeUpDown.Increment = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.fontSizeUpDown.Maximum = new decimal(new int[] {
- 500,
- 0,
- 0,
- 0});
- this.fontSizeUpDown.Minimum = new decimal(new int[] {
- 7,
- 0,
- 0,
- 0});
- this.fontSizeUpDown.Name = "fontSizeUpDown";
- this.fontSizeUpDown.Text = "12";
- this.fontSizeUpDown.Value = new decimal(new int[] {
- 12,
- 0,
- 0,
- 0});
- this.fontSizeUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.fontSizeUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // fontBoldButton
- //
- this.fontBoldButton.CheckOnClick = true;
- this.fontBoldButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.fontBoldButton.Image = ((System.Drawing.Image)(resources.GetObject("fontBoldButton.Image")));
- this.fontBoldButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.fontBoldButton.LanguageKey = "editor_bold";
- this.fontBoldButton.Name = "fontBoldButton";
- this.fontBoldButton.Text = "Bold";
- this.fontBoldButton.Click += new System.EventHandler(this.FontBoldButtonClick);
- //
- // fontItalicButton
- //
- this.fontItalicButton.CheckOnClick = true;
- this.fontItalicButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.fontItalicButton.Image = ((System.Drawing.Image)(resources.GetObject("fontItalicButton.Image")));
- this.fontItalicButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.fontItalicButton.LanguageKey = "editor_italic";
- this.fontItalicButton.Name = "fontItalicButton";
- this.fontItalicButton.Text = "Italic";
- this.fontItalicButton.Click += new System.EventHandler(this.FontItalicButtonClick);
- //
- // textVerticalAlignmentButton
- //
- this.textVerticalAlignmentButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.alignTopToolStripMenuItem,
- this.alignMiddleToolStripMenuItem,
- this.alignBottomToolStripMenuItem});
- this.textVerticalAlignmentButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.textVerticalAlignmentButton.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignMiddle.Image")));
- this.textVerticalAlignmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.textVerticalAlignmentButton.LanguageKey = "editor_align_vertical";
- this.textVerticalAlignmentButton.Name = "textVerticalAlignmentButton";
- this.textVerticalAlignmentButton.SelectedTag = System.Drawing.StringAlignment.Center;
- this.textVerticalAlignmentButton.Tag = System.Drawing.StringAlignment.Center;
- //
- // alignTopToolStripMenuItem
- //
- this.alignTopToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignTopToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignTop.Image")));
- this.alignTopToolStripMenuItem.LanguageKey = "editor_align_top";
- this.alignTopToolStripMenuItem.Name = "alignTopToolStripMenuItem";
- this.alignTopToolStripMenuItem.Tag = System.Drawing.StringAlignment.Near;
- //
- // alignMiddleToolStripMenuItem
- //
- this.alignMiddleToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignMiddleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignMiddle.Image")));
- this.alignMiddleToolStripMenuItem.LanguageKey = "editor_align_middle";
- this.alignMiddleToolStripMenuItem.Name = "alignMiddleToolStripMenuItem";
- this.alignMiddleToolStripMenuItem.Tag = System.Drawing.StringAlignment.Center;
- //
- // alignBottomToolStripMenuItem
- //
- this.alignBottomToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignBottomToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignBottom.Image")));
- this.alignBottomToolStripMenuItem.LanguageKey = "editor_align_bottom";
- this.alignBottomToolStripMenuItem.Name = "alignBottomToolStripMenuItem";
- this.alignBottomToolStripMenuItem.Tag = System.Drawing.StringAlignment.Far;
- //
- // blurRadiusLabel
- //
- this.blurRadiusLabel.LanguageKey = "editor_blur_radius";
- this.blurRadiusLabel.Name = "blurRadiusLabel";
- this.blurRadiusLabel.Text = "Blur radius";
- //
- // blurRadiusUpDown
- //
- this.blurRadiusUpDown.DecimalPlaces = 0;
- this.blurRadiusUpDown.Increment = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.blurRadiusUpDown.Maximum = new decimal(new int[] {
- 100,
- 0,
- 0,
- 0});
- this.blurRadiusUpDown.Minimum = new decimal(new int[] {
- 0,
- 0,
- 0,
- 0});
- this.blurRadiusUpDown.Name = "blurRadiusUpDown";
- this.blurRadiusUpDown.Text = "1";
- this.blurRadiusUpDown.Value = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.blurRadiusUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.blurRadiusUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // brightnessLabel
- //
- this.brightnessLabel.LanguageKey = "editor_brightness";
- this.brightnessLabel.Name = "brightnessLabel";
- this.brightnessLabel.Text = "Brightness";
- //
- // brightnessUpDown
- //
- this.brightnessUpDown.DecimalPlaces = 0;
- this.brightnessUpDown.Increment = new decimal(new int[] {
- 5,
- 0,
- 0,
- 0});
- this.brightnessUpDown.Maximum = new decimal(new int[] {
- 200,
- 0,
- 0,
- 0});
- this.brightnessUpDown.Minimum = new decimal(new int[] {
- 0,
- 0,
- 0,
- 0});
- this.brightnessUpDown.Name = "brightnessUpDown";
- this.brightnessUpDown.Text = "100";
- this.brightnessUpDown.Value = new decimal(new int[] {
- 100,
- 0,
- 0,
- 0});
- this.brightnessUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.brightnessUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // previewQualityLabel
- //
- this.previewQualityLabel.LanguageKey = "editor_preview_quality";
- this.previewQualityLabel.Name = "previewQualityLabel";
- this.previewQualityLabel.Text = "Preview quality";
- //
- // previewQualityUpDown
- //
- this.previewQualityUpDown.DecimalPlaces = 0;
- this.previewQualityUpDown.Increment = new decimal(new int[] {
- 10,
- 0,
- 0,
- 0});
- this.previewQualityUpDown.Maximum = new decimal(new int[] {
- 100,
- 0,
- 0,
- 0});
- this.previewQualityUpDown.Minimum = new decimal(new int[] {
- 10,
- 0,
- 0,
- 0});
- this.previewQualityUpDown.Name = "previewQualityUpDown";
- this.previewQualityUpDown.Text = "50";
- this.previewQualityUpDown.Value = new decimal(new int[] {
- 50,
- 0,
- 0,
- 0});
- this.previewQualityUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.previewQualityUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // magnificationFactorLabel
- //
- this.magnificationFactorLabel.LanguageKey = "editor_magnification_factor";
- this.magnificationFactorLabel.Name = "magnificationFactorLabel";
- this.magnificationFactorLabel.Tag = FilterContainer.PreparedFilter.MAGNIFICATION;
- //
- // magnificationFactorUpDown
- //
- this.magnificationFactorUpDown.DecimalPlaces = 0;
- this.magnificationFactorUpDown.Increment = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.magnificationFactorUpDown.Maximum = new decimal(new int[] {
- 8,
- 0,
- 0,
- 0});
- this.magnificationFactorUpDown.Minimum = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.magnificationFactorUpDown.Name = "magnificationFactorUpDown";
- this.magnificationFactorUpDown.Text = "2";
- this.magnificationFactorUpDown.Value = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.magnificationFactorUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.magnificationFactorUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // pixelSizeLabel
- //
- this.pixelSizeLabel.LanguageKey = "editor_pixel_size";
- this.pixelSizeLabel.Name = "pixelSizeLabel";
- //
- // pixelSizeUpDown
- //
- this.pixelSizeUpDown.DecimalPlaces = 0;
- this.pixelSizeUpDown.Increment = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.pixelSizeUpDown.Maximum = new decimal(new int[] {
- 100,
- 0,
- 0,
- 0});
- this.pixelSizeUpDown.Minimum = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.pixelSizeUpDown.Name = "pixelSizeUpDown";
- this.pixelSizeUpDown.Text = "5";
- this.pixelSizeUpDown.Value = new decimal(new int[] {
- 5,
- 0,
- 0,
- 0});
- this.pixelSizeUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
- this.pixelSizeUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
- //
- // arrowHeadsLabel
- //
- this.arrowHeadsLabel.LanguageKey = "editor_pixel_size";
- this.arrowHeadsLabel.Name = "arrowHeadsLabel";
- //
- // arrowHeadsDropDownButton
- //
- this.arrowHeadsDropDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.arrowHeadsDropDownButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.arrowHeadStartMenuItem,
- this.arrowHeadEndMenuItem,
- this.arrowHeadBothMenuItem,
- this.arrowHeadNoneMenuItem});
- this.arrowHeadsDropDownButton.Image = ((System.Drawing.Image)(resources.GetObject("arrowHeadsDropDownButton.Image")));
- this.arrowHeadsDropDownButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.arrowHeadsDropDownButton.LanguageKey = "editor_arrowheads";
- this.arrowHeadsDropDownButton.Name = "arrowHeadsDropDownButton";
- //
- // arrowHeadStartMenuItem
- //
- this.arrowHeadStartMenuItem.LanguageKey = "editor_arrowheads_start";
- this.arrowHeadStartMenuItem.Name = "arrowHeadStartMenuItem";
- this.arrowHeadStartMenuItem.Tag = ArrowContainer.ArrowHeadCombination.START_POINT;
- this.arrowHeadStartMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
- //
- // arrowHeadEndMenuItem
- //
- this.arrowHeadEndMenuItem.LanguageKey = "editor_arrowheads_end";
- this.arrowHeadEndMenuItem.Name = "arrowHeadEndMenuItem";
- this.arrowHeadEndMenuItem.Tag = ArrowContainer.ArrowHeadCombination.END_POINT;
- this.arrowHeadEndMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
- //
- // arrowHeadBothMenuItem
- //
- this.arrowHeadBothMenuItem.LanguageKey = "editor_arrowheads_both";
- this.arrowHeadBothMenuItem.Name = "arrowHeadBothMenuItem";
- this.arrowHeadBothMenuItem.Tag = ArrowContainer.ArrowHeadCombination.BOTH;
- this.arrowHeadBothMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
- //
- // arrowHeadNoneMenuItem
- //
- this.arrowHeadNoneMenuItem.LanguageKey = "editor_arrowheads_none";
- this.arrowHeadNoneMenuItem.Name = "arrowHeadNoneMenuItem";
- this.arrowHeadNoneMenuItem.Tag = ArrowContainer.ArrowHeadCombination.NONE;
- this.arrowHeadNoneMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
- //
- // shadowButton
- //
- this.shadowButton.CheckOnClick = true;
- this.shadowButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.shadowButton.Image = ((System.Drawing.Image)(resources.GetObject("shadowButton.Image")));
- this.shadowButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.shadowButton.LanguageKey = "editor_shadow";
- this.shadowButton.Name = "shadowButton";
- //
- // toolStripSeparator
- //
- this.toolStripSeparator.Name = "toolStripSeparator";
- //
- // toolStripSeparator10
- //
- this.toolStripSeparator10.Name = "toolStripSeparator10";
- //
- // btnConfirm
- //
- this.btnConfirm.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnConfirm.Image = ((System.Drawing.Image)(resources.GetObject("btnConfirm.Image")));
- this.btnConfirm.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnConfirm.LanguageKey = "editor_confirm";
- this.btnConfirm.Name = "btnConfirm";
- this.btnConfirm.Text = "Confirm";
- this.btnConfirm.Click += new System.EventHandler(this.BtnConfirmClick);
- //
- // btnCancel
- //
- this.btnCancel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.btnCancel.Image = ((System.Drawing.Image)(resources.GetObject("btnCancel.Image")));
- this.btnCancel.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.btnCancel.LanguageKey = "editor_cancel";
- this.btnCancel.Name = "btnCancel";
- this.btnCancel.Text = "Cancel";
- this.btnCancel.Click += new System.EventHandler(this.BtnCancelClick);
- //
- // toolStripSeparator9
- //
- this.toolStripSeparator9.Name = "toolStripSeparator9";
- //
- // closeToolStripMenuItem
- //
- this.closeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("closeToolStripMenuItem.Image")));
- this.closeToolStripMenuItem.LanguageKey = "editor_close";
- this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
- this.closeToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
- this.closeToolStripMenuItem.Click += new System.EventHandler(this.CloseToolStripMenuItemClick);
- //
- // fileSavedStatusContextMenu
- //
- this.fileSavedStatusContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.copyPathMenuItem,
- this.openDirectoryMenuItem});
- this.fileSavedStatusContextMenu.Name = "contextMenuStrip1";
- //
- // copyPathMenuItem
- //
- this.copyPathMenuItem.LanguageKey = "editor_copypathtoclipboard";
- this.copyPathMenuItem.Name = "copyPathMenuItem";
- this.copyPathMenuItem.Click += new System.EventHandler(this.CopyPathMenuItemClick);
- //
- // openDirectoryMenuItem
- //
- this.openDirectoryMenuItem.LanguageKey = "editor_opendirinexplorer";
- this.openDirectoryMenuItem.Name = "openDirectoryMenuItem";
- this.openDirectoryMenuItem.Click += new System.EventHandler(this.OpenDirectoryMenuItemClick);
- //
- // textHorizontalAlignmentButton
- //
- this.textHorizontalAlignmentButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.alignLeftToolStripMenuItem,
- this.alignCenterToolStripMenuItem,
- this.alignRightToolStripMenuItem});
- this.textHorizontalAlignmentButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
- this.textHorizontalAlignmentButton.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignCenter.Image")));
- this.textHorizontalAlignmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.textHorizontalAlignmentButton.LanguageKey = "editor_align_horizontal";
- this.textHorizontalAlignmentButton.Name = "textHorizontalAlignmentButton";
- this.textHorizontalAlignmentButton.SelectedTag = System.Drawing.StringAlignment.Center;
- this.textHorizontalAlignmentButton.Tag = System.Drawing.StringAlignment.Center;
- //
- // alignLeftToolStripMenuItem
- //
- this.alignLeftToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignLeftToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignLeft.Image")));
- this.alignLeftToolStripMenuItem.LanguageKey = "editor_align_left";
- this.alignLeftToolStripMenuItem.Name = "alignLeftToolStripMenuItem";
- this.alignLeftToolStripMenuItem.Tag = System.Drawing.StringAlignment.Near;
- //
- // alignCenterToolStripMenuItem
- //
- this.alignCenterToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignCenterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignCenter.Image")));
- this.alignCenterToolStripMenuItem.LanguageKey = "editor_align_center";
- this.alignCenterToolStripMenuItem.Name = "alignCenterToolStripMenuItem";
- this.alignCenterToolStripMenuItem.Tag = System.Drawing.StringAlignment.Center;
- //
- // alignRightToolStripMenuItem
- //
- this.alignRightToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
- this.alignRightToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignRight.Image")));
- this.alignRightToolStripMenuItem.LanguageKey = "editor_align_right";
- this.alignRightToolStripMenuItem.Name = "alignRightToolStripMenuItem";
- this.alignRightToolStripMenuItem.Tag = System.Drawing.StringAlignment.Far;
- //
- // zoomMainMenuItem
- //
- this.zoomMainMenuItem.DropDown = this.zoomMenuStrip;
- this.zoomMainMenuItem.Name = "zoomMainMenuItem";
- this.zoomMainMenuItem.Size = new System.Drawing.Size(51, 20);
- this.zoomMainMenuItem.Text = "Zoom";
- //
- // zoomMenuStrip
- //
- this.zoomMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.zoomInMenuItem,
- this.zoomOutMenuItem,
- this.zoomMenuSeparator1,
- this.zoomBestFitMenuItem,
- this.zoomMenuSeparator2,
- this.zoom25MenuItem,
- this.zoom50MenuItem,
- this.zoom66MenuItem,
- this.zoom75MenuItem,
- this.zoomMenuSeparator3,
- this.zoomActualSizeMenuItem,
- this.zoomMenuSeparator4,
- this.zoom200MenuItem,
- this.zoom300MenuItem,
- this.zoom400MenuItem,
- this.zoom600MenuItem});
- this.zoomMenuStrip.Name = "zoomMenuStrip";
- this.zoomMenuStrip.Size = new System.Drawing.Size(210, 292);
- //
- // zoomInMenuItem
- //
- this.zoomInMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("zoomInMenuItem.Image")));
- this.zoomInMenuItem.Name = "zoomInMenuItem";
- this.zoomInMenuItem.ShortcutKeyDisplayString = "Ctrl++";
- this.zoomInMenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoomInMenuItem.Text = "Zoom In";
- this.zoomInMenuItem.Click += new System.EventHandler(this.ZoomInMenuItemClick);
- //
- // zoomOutMenuItem
- //
- this.zoomOutMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("zoomOutMenuItem.Image")));
- this.zoomOutMenuItem.Name = "zoomOutMenuItem";
- this.zoomOutMenuItem.ShortcutKeyDisplayString = "Ctrl+-";
- this.zoomOutMenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoomOutMenuItem.Text = "Zoom Out";
- this.zoomOutMenuItem.Click += new System.EventHandler(this.ZoomOutMenuItemClick);
- //
- // zoomMenuSeparator1
- //
- this.zoomMenuSeparator1.Name = "zoomMenuSeparator1";
- this.zoomMenuSeparator1.Size = new System.Drawing.Size(206, 6);
- //
- // zoomBestFitMenuItem
- //
- this.zoomBestFitMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("zoomBestFitMenuItem.Image")));
- this.zoomBestFitMenuItem.Name = "zoomBestFitMenuItem";
- this.zoomBestFitMenuItem.ShortcutKeyDisplayString = "Ctrl+9";
- this.zoomBestFitMenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoomBestFitMenuItem.Text = "Best Fit";
- this.zoomBestFitMenuItem.Click += new System.EventHandler(this.ZoomBestFitMenuItemClick);
- //
- // zoomMenuSeparator2
- //
- this.zoomMenuSeparator2.Name = "zoomMenuSeparator2";
- this.zoomMenuSeparator2.Size = new System.Drawing.Size(206, 6);
- //
- // zoom25MenuItem
- //
- this.zoom25MenuItem.Name = "zoom25MenuItem";
- this.zoom25MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom25MenuItem.Tag = "1/4";
- this.zoom25MenuItem.Text = "25%";
- this.zoom25MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom50MenuItem
- //
- this.zoom50MenuItem.Name = "zoom50MenuItem";
- this.zoom50MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom50MenuItem.Tag = "1/2";
- this.zoom50MenuItem.Text = "50%";
- this.zoom50MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom66MenuItem
- //
- this.zoom66MenuItem.Name = "zoom66MenuItem";
- this.zoom66MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom66MenuItem.Tag = "2/3";
- this.zoom66MenuItem.Text = "66%";
- this.zoom66MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom75MenuItem
- //
- this.zoom75MenuItem.Name = "zoom75MenuItem";
- this.zoom75MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom75MenuItem.Tag = "3/4";
- this.zoom75MenuItem.Text = "75%";
- this.zoom75MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoomMenuSeparator3
- //
- this.zoomMenuSeparator3.Name = "zoomMenuSeparator3";
- this.zoomMenuSeparator3.Size = new System.Drawing.Size(206, 6);
- //
- // zoomActualSizeMenuItem
- //
- this.zoomActualSizeMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("zoomActualSizeMenuItem.Image")));
- this.zoomActualSizeMenuItem.Name = "zoomActualSizeMenuItem";
- this.zoomActualSizeMenuItem.ShortcutKeyDisplayString = "Ctrl+0";
- this.zoomActualSizeMenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoomActualSizeMenuItem.Tag = "1/1";
- this.zoomActualSizeMenuItem.Text = "100% - Actual Size";
- this.zoomActualSizeMenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoomMenuSeparator4
- //
- this.zoomMenuSeparator4.Name = "zoomMenuSeparator4";
- this.zoomMenuSeparator4.Size = new System.Drawing.Size(206, 6);
- //
- // zoom200MenuItem
- //
- this.zoom200MenuItem.Name = "zoom200MenuItem";
- this.zoom200MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom200MenuItem.Tag = "2/1";
- this.zoom200MenuItem.Text = "200%";
- this.zoom200MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom300MenuItem
- //
- this.zoom300MenuItem.Name = "zoom300MenuItem";
- this.zoom300MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom300MenuItem.Tag = "3/1";
- this.zoom300MenuItem.Text = "300%";
- this.zoom300MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom400MenuItem
- //
- this.zoom400MenuItem.Name = "zoom400MenuItem";
- this.zoom400MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom400MenuItem.Tag = "4/1";
- this.zoom400MenuItem.Text = "400%";
- this.zoom400MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // zoom600MenuItem
- //
- this.zoom600MenuItem.Name = "zoom600MenuItem";
- this.zoom600MenuItem.Size = new System.Drawing.Size(209, 22);
- this.zoom600MenuItem.Tag = "6/1";
- this.zoom600MenuItem.Text = "600%";
- this.zoom600MenuItem.Click += new System.EventHandler(this.ZoomSetValueMenuItemClick);
- //
- // statusStripSpacer
- //
- this.statusStripSpacer.Name = "statusStripSpacer";
- this.statusStripSpacer.Size = new System.Drawing.Size(599, 19);
- this.statusStripSpacer.Spring = true;
- //
- // zoomStatusDropDownBtn
- //
- this.zoomStatusDropDownBtn.DropDown = this.zoomMenuStrip;
- this.zoomStatusDropDownBtn.Image = ((System.Drawing.Image)(resources.GetObject("zoomStatusDropDownBtn.Image")));
- this.zoomStatusDropDownBtn.ImageTransparentColor = System.Drawing.Color.Magenta;
- this.zoomStatusDropDownBtn.Name = "zoomStatusDropDownBtn";
- this.zoomStatusDropDownBtn.Size = new System.Drawing.Size(64, 22);
- this.zoomStatusDropDownBtn.Text = "100%";
- //
- // ImageEditorForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(785, 485);
- this.Controls.Add(this.topToolStripContainer);
- this.KeyPreview = true;
- this.LanguageKey = "editor_title";
- this.Name = "ImageEditorForm";
- this.Activated += new System.EventHandler(this.ImageEditorFormActivated);
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImageEditorFormFormClosing);
- this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ImageEditorFormKeyDown);
- this.Resize += new System.EventHandler(this.ImageEditorFormResize);
- this.topToolStripContainer.BottomToolStripPanel.ResumeLayout(true);
- this.topToolStripContainer.ContentPanel.ResumeLayout(true);
- this.topToolStripContainer.LeftToolStripPanel.ResumeLayout(true);
- this.topToolStripContainer.TopToolStripPanel.ResumeLayout(true);
- this.topToolStripContainer.ResumeLayout(true);
- this.statusStrip1.ResumeLayout(true);
- this.tableLayoutPanel1.ResumeLayout(true);
- this.toolsToolStrip.ResumeLayout(true);
- this.zoomMenuStrip.ResumeLayout(false);
- this.menuStrip1.ResumeLayout(true);
- this.destinationsToolStrip.ResumeLayout(true);
- this.propertiesToolStrip.ResumeLayout(true);
- this.fileSavedStatusContextMenu.ResumeLayout(true);
- this.ResumeLayout(false);
- }
- private GreenshotToolStripMenuItem alignRightToolStripMenuItem;
- private GreenshotToolStripMenuItem alignCenterToolStripMenuItem;
- private GreenshotToolStripMenuItem alignLeftToolStripMenuItem;
- private BindableToolStripDropDownButton textHorizontalAlignmentButton;
- private GreenshotToolStripMenuItem alignMiddleToolStripMenuItem;
- private GreenshotToolStripMenuItem alignBottomToolStripMenuItem;
- private GreenshotToolStripMenuItem alignTopToolStripMenuItem;
- private BindableToolStripDropDownButton textVerticalAlignmentButton;
- private GreenshotToolStripMenuItem invertToolStripMenuItem;
- private GreenshotToolStripButton btnResize;
- private GreenshotToolStripMenuItem grayscaleToolStripMenuItem;
- private GreenshotToolStripButton rotateCcwToolstripButton;
- private GreenshotToolStripButton rotateCwToolstripButton;
- private GreenshotToolStripMenuItem addBorderToolStripMenuItem;
- private GreenshotToolStripMenuItem tornEdgesToolStripMenuItem;
- private GreenshotToolStripMenuItem addDropshadowToolStripMenuItem;
- private GreenshotToolStripDropDownButton toolStripSplitButton1;
- private System.Windows.Forms.ToolStripStatusLabel dimensionsLabel;
- private GreenshotToolStripMenuItem insert_window_toolstripmenuitem;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
- private GreenshotToolStripMenuItem grayscaleHighlightMenuItem;
- private GreenshotToolStripMenuItem areaHighlightMenuItem;
- private GreenshotToolStripMenuItem textHighlightMenuItem;
- private GreenshotToolStripMenuItem magnifyMenuItem;
- private GreenshotToolStripMenuItem arrowHeadStartMenuItem;
- private GreenshotToolStripMenuItem arrowHeadEndMenuItem;
- private GreenshotToolStripMenuItem arrowHeadBothMenuItem;
- private GreenshotToolStripMenuItem arrowHeadNoneMenuItem;
- private BindableToolStripButton btnCancel;
- private BindableToolStripButton btnConfirm;
- private GreenshotToolStripMenuItem selectAllToolStripMenuItem;
- private BindableToolStripDropDownButton highlightModeButton;
- private BindableToolStripDropDownButton cropModeButton;
- private GreenshotToolStripMenuItem defaultCropModeToolStripMenuItem;
- private GreenshotToolStripMenuItem verticalCropModeToolStripMenuItem;
- private GreenshotToolStripMenuItem horizontalCropModeToolStripMenuItem;
- private GreenshotToolStripMenuItem autoCropModeToolStripMenuItem;
- private GreenshotToolStripMenuItem pixelizeToolStripMenuItem;
- private GreenshotToolStripMenuItem blurToolStripMenuItem;
- private BindableToolStripDropDownButton obfuscateModeButton;
- private GreenshotToolStripButton btnHighlight;
- private GreenshotToolStripMenuItem loadElementsToolStripMenuItem;
- private GreenshotToolStripMenuItem saveElementsToolStripMenuItem;
- private FontFamilyComboBox fontFamilyComboBox;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator10;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator;
- private BindableToolStripButton shadowButton;
- private BindableToolStripButton fontItalicButton;
- private BindableToolStripButton fontBoldButton;
- private ToolStripNumericUpDown fontSizeUpDown;
- private GreenshotToolStripLabel fontSizeLabel;
- private ToolStripNumericUpDown brightnessUpDown;
- private GreenshotToolStripLabel brightnessLabel;
- private GreenshotToolStripMenuItem pluginToolStripMenuItem;
- private GreenshotToolStripDropDownButton arrowHeadsDropDownButton;
- private GreenshotToolStripLabel arrowHeadsLabel;
- private ToolStripNumericUpDown pixelSizeUpDown;
- private GreenshotToolStripLabel pixelSizeLabel;
- private ToolStripNumericUpDown magnificationFactorUpDown;
- private GreenshotToolStripLabel magnificationFactorLabel;
- private ToolStripNumericUpDown previewQualityUpDown;
- private GreenshotToolStripLabel previewQualityLabel;
- private ToolStripNumericUpDown blurRadiusUpDown;
- private GreenshotToolStripLabel blurRadiusLabel;
- private ToolStripEx propertiesToolStrip;
- private GreenshotToolStripLabel lineThicknessLabel;
- private ToolStripNumericUpDown lineThicknessUpDown;
- private GreenshotToolStripLabel counterLabel;
- private ToolStripNumericUpDown counterUpDown;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator14;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator15;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator16;
- private GreenshotToolStripButton btnFreehand;
- private GreenshotToolStripButton btnObfuscate;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator13;
- private GreenshotToolStripButton btnCrop;
- private GreenshotToolStripMenuItem openDirectoryMenuItem;
- private GreenshotToolStripMenuItem copyPathMenuItem;
- private System.Windows.Forms.ContextMenuStrip fileSavedStatusContextMenu;
- private GreenshotToolStripMenuItem downToBottomToolStripMenuItem;
- private GreenshotToolStripMenuItem upToTopToolStripMenuItem;
- private GreenshotToolStripMenuItem downOneLevelToolStripMenuItem;
- private GreenshotToolStripMenuItem upOneLevelToolStripMenuItem;
- private GreenshotToolStripMenuItem arrangeToolStripMenuItem;
- private GreenshotToolStripButton btnCursor;
- private ToolStripEx toolsToolStrip;
- private GreenshotToolStripButton btnArrow;
- private GreenshotToolStripMenuItem drawArrowToolStripMenuItem;
- private GreenshotToolStripMenuItem drawFreehandToolStripMenuItem;
- private GreenshotToolStripButton btnText;
- private GreenshotToolStripButton btnSpeechBubble;
- private GreenshotToolStripButton btnStepLabel;
- private GreenshotToolStripMenuItem drawLineToolStripMenuItem;
- private GreenshotToolStripButton btnLine;
- private GreenshotToolStripButton btnSettings;
- private GreenshotToolStripButton btnHelp;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator11;
- private GreenshotToolStripMenuItem aboutToolStripMenuItem;
- private GreenshotToolStripMenuItem helpToolStripMenuItem1;
- private GreenshotToolStripMenuItem helpToolStripMenuItem;
- private GreenshotToolStripMenuItem preferencesToolStripMenuItem;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator12;
- private GreenshotToolStripMenuItem closeToolStripMenuItem;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator9;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator8;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
- private GreenshotToolStripButton btnPrint;
- private GreenshotToolStripMenuItem duplicateToolStripMenuItem;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
- private GreenshotToolStripMenuItem fileStripMenuItem;
- private GreenshotToolStripMenuItem removeObjectToolStripMenuItem;
- private GreenshotToolStripMenuItem addTextBoxToolStripMenuItem;
- private GreenshotToolStripMenuItem addSpeechBubbleToolStripMenuItem;
- private GreenshotToolStripMenuItem addCounterToolStripMenuItem;
- private GreenshotToolStripMenuItem addEllipseToolStripMenuItem;
- private GreenshotToolStripMenuItem addRectangleToolStripMenuItem;
- private GreenshotToolStripMenuItem objectToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem;
- private GreenshotToolStripMenuItem pasteToolStripMenuItem;
- private GreenshotToolStripMenuItem copyToolStripMenuItem;
- private GreenshotToolStripMenuItem cutToolStripMenuItem;
- private GreenshotToolStripMenuItem editToolStripMenuItem;
- private MenuStripEx menuStrip1;
- private System.Windows.Forms.ToolStripStatusLabel statusLabel;
- private System.Windows.Forms.StatusStrip statusStrip1;
- private GreenshotToolStripButton btnCut;
- private GreenshotToolStripButton btnCopy;
- private GreenshotToolStripButton btnPaste;
- private System.Windows.Forms.ToolStripButton btnUndo;
- private System.Windows.Forms.ToolStripButton btnRedo;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
- private GreenshotToolStripButton btnClipboard;
- private GreenshotToolStripButton btnDelete;
- private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
- private GreenshotToolStripButton btnEllipse;
- private GreenshotToolStripButton btnSave;
- private GreenshotToolStripButton btnRect;
- private System.Windows.Forms.ToolStripContainer topToolStripContainer;
- private ToolStripEx destinationsToolStrip;
- private NonJumpingPanel panel1;
- private ToolStripColorButton btnFillColor;
- private ToolStripColorButton btnLineColor;
- private System.Windows.Forms.ContextMenuStrip zoomMenuStrip;
- private System.Windows.Forms.ToolStripMenuItem zoomInMenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoomOutMenuItem;
- private System.Windows.Forms.ToolStripSeparator zoomMenuSeparator1;
- private System.Windows.Forms.ToolStripMenuItem zoomBestFitMenuItem;
- private System.Windows.Forms.ToolStripSeparator zoomMenuSeparator2;
- private System.Windows.Forms.ToolStripMenuItem zoom25MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom50MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom66MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom75MenuItem;
- private System.Windows.Forms.ToolStripSeparator zoomMenuSeparator3;
- private System.Windows.Forms.ToolStripMenuItem zoomActualSizeMenuItem;
- private System.Windows.Forms.ToolStripSeparator zoomMenuSeparator4;
- private System.Windows.Forms.ToolStripMenuItem zoom200MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom300MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom400MenuItem;
- private System.Windows.Forms.ToolStripMenuItem zoom600MenuItem;
- private System.Windows.Forms.ToolStripDropDownButton zoomStatusDropDownBtn;
- private System.Windows.Forms.ToolStripMenuItem zoomMainMenuItem;
- private System.Windows.Forms.ToolStripStatusLabel statusStripSpacer;
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Controls;
+
+namespace Greenshot {
+ partial class ImageEditorForm {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+ private System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageEditorForm));
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ this.topToolStripContainer = new System.Windows.Forms.ToolStripContainer();
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.dimensionsLabel = new System.Windows.Forms.ToolStripStatusLabel();
+ this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.panel1 = new GreenshotPlugin.Controls.NonJumpingPanel();
+ this.toolsToolStrip = new Greenshot.Controls.ToolStripEx();
+ this.btnCursor = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnRect = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnEllipse = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnLine = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnArrow = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnFreehand = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnText = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnSpeechBubble = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnStepLabel = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnHighlight = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnObfuscate = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSplitButton1 = new GreenshotPlugin.Controls.GreenshotToolStripDropDownButton();
+ this.addBorderToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addDropshadowToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.tornEdgesToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.grayscaleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.invertToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.btnResize = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnCrop = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.rotateCwToolstripButton = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.rotateCcwToolstripButton = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.menuStrip1 = new Greenshot.Controls.MenuStripEx();
+ this.fileStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.editToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.undoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.redoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator();
+ this.cutToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.copyToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.pasteToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+ this.duplicateToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
+ this.preferencesToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
+ this.autoCropToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator();
+ this.insert_window_toolstripmenuitem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.objectToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addRectangleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addEllipseToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.drawLineToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.drawArrowToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.drawFreehandToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addTextBoxToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addSpeechBubbleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.addCounterToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
+ this.selectAllToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.removeObjectToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
+ this.arrangeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.upToTopToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.upOneLevelToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.downOneLevelToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.downToBottomToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.saveElementsToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.loadElementsToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.pluginToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.helpToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.helpToolStripMenuItem1 = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.aboutToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.destinationsToolStrip = new Greenshot.Controls.ToolStripEx();
+ this.btnSave = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnClipboard = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnPrint = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnDelete = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnCut = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnCopy = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnPaste = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.btnUndo = new System.Windows.Forms.ToolStripButton();
+ this.btnRedo = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnSettings = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
+ this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnHelp = new GreenshotPlugin.Controls.GreenshotToolStripButton();
+ this.propertiesToolStrip = new Greenshot.Controls.ToolStripEx();
+ this.obfuscateModeButton = new Greenshot.Controls.BindableToolStripDropDownButton();
+ this.pixelizeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.blurToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.highlightModeButton = new Greenshot.Controls.BindableToolStripDropDownButton();
+ this.textHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.areaHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.grayscaleHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.magnifyMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.btnFillColor = new Greenshot.Controls.ToolStripColorButton();
+ this.btnLineColor = new Greenshot.Controls.ToolStripColorButton();
+ this.lineThicknessLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.lineThicknessUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.counterLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.counterUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.fontFamilyComboBox = new Greenshot.Controls.FontFamilyComboBox();
+ this.fontSizeLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.fontSizeUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.fontBoldButton = new Greenshot.Controls.BindableToolStripButton();
+ this.fontItalicButton = new Greenshot.Controls.BindableToolStripButton();
+ this.textVerticalAlignmentButton = new Greenshot.Controls.BindableToolStripDropDownButton();
+ this.alignTopToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.alignMiddleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.alignBottomToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.blurRadiusLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.blurRadiusUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.brightnessLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.brightnessUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.previewQualityLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.previewQualityUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.magnificationFactorLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.magnificationFactorUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.pixelSizeLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.pixelSizeUpDown = new Greenshot.Controls.ToolStripNumericUpDown();
+ this.arrowHeadsLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel();
+ this.arrowHeadsDropDownButton = new GreenshotPlugin.Controls.GreenshotToolStripDropDownButton();
+ this.arrowHeadStartMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.arrowHeadEndMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.arrowHeadBothMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.arrowHeadNoneMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.shadowButton = new Greenshot.Controls.BindableToolStripButton();
+ this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
+ this.btnConfirm = new Greenshot.Controls.BindableToolStripButton();
+ this.btnCancel = new Greenshot.Controls.BindableToolStripButton();
+ this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator();
+ this.closeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.fileSavedStatusContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.copyPathMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.openDirectoryMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.textHorizontalAlignmentButton = new Greenshot.Controls.BindableToolStripDropDownButton();
+ this.alignLeftToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.alignCenterToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.alignRightToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.topToolStripContainer.BottomToolStripPanel.SuspendLayout();
+ this.topToolStripContainer.ContentPanel.SuspendLayout();
+ this.topToolStripContainer.LeftToolStripPanel.SuspendLayout();
+ this.topToolStripContainer.TopToolStripPanel.SuspendLayout();
+ this.topToolStripContainer.SuspendLayout();
+ this.statusStrip1.SuspendLayout();
+ this.tableLayoutPanel1.SuspendLayout();
+ this.toolsToolStrip.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.destinationsToolStrip.SuspendLayout();
+ this.propertiesToolStrip.SuspendLayout();
+ this.fileSavedStatusContextMenu.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // topToolStripContainer
+ //
+ this.topToolStripContainer.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.topToolStripContainer.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ //
+ // topToolStripContainer.BottomToolStripPanel
+ //
+ this.topToolStripContainer.BottomToolStripPanel.Controls.Add(this.statusStrip1);
+ //
+ // topToolStripContainer.ContentPanel
+ //
+ this.topToolStripContainer.ContentPanel.AutoScroll = true;
+ this.topToolStripContainer.ContentPanel.Controls.Add(this.tableLayoutPanel1);
+ this.topToolStripContainer.ContentPanel.Size = new System.Drawing.Size(761, 385);
+ this.topToolStripContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.topToolStripContainer.LeftToolStripPanel.Join(this.toolsToolStrip,0);
+ this.topToolStripContainer.Location = new System.Drawing.Point(0, 0);
+ this.topToolStripContainer.Name = "toolStripContainer1";
+ this.topToolStripContainer.Size = new System.Drawing.Size(785, 485);
+ this.topToolStripContainer.TabIndex = 2;
+ this.topToolStripContainer.Text = "toolStripContainer1";
+ this.topToolStripContainer.TopToolStripPanel.Join(this.menuStrip1,0);
+ this.topToolStripContainer.TopToolStripPanel.Join(this.destinationsToolStrip, 1);
+ this.topToolStripContainer.TopToolStripPanel.Join(this.propertiesToolStrip, 2);
+ //
+ // statusStrip1
+ //
+ this.statusStrip1.Dock = System.Windows.Forms.DockStyle.None;
+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.dimensionsLabel,
+ this.statusLabel});
+ this.statusStrip1.Location = new System.Drawing.Point(0, 0);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.Size = new System.Drawing.Size(785, 24);
+ this.statusStrip1.TabIndex = 3;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // dimensionsLabel
+ //
+ this.dimensionsLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top)
+ | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right)
+ | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom)));
+ this.dimensionsLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Sunken;
+ this.dimensionsLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.dimensionsLabel.Name = "dimensionsLabel";
+ this.dimensionsLabel.Text = "123x321";
+ //
+ // statusLabel
+ //
+ this.statusLabel.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top)
+ | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right)
+ | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom)));
+ this.statusLabel.BorderStyle = System.Windows.Forms.Border3DStyle.Sunken;
+ this.statusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.statusLabel.Name = "statusLabel";
+ this.statusLabel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.StatusLabelClicked);
+ //
+ // tableLayoutPanel1
+ //
+ this.tableLayoutPanel1.BackColor = System.Drawing.SystemColors.Control;
+ this.tableLayoutPanel1.ColumnCount = 1;
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0);
+ this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ this.tableLayoutPanel1.RowCount = 1;
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 385F));
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(761, 385);
+ this.tableLayoutPanel1.TabIndex = 3;
+ //
+ // panel1
+ //
+ this.panel1.AutoScroll = true;
+ this.panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+ this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(3, 3);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(755, 379);
+ this.panel1.TabIndex = 2;
+ //
+ // toolsToolStrip
+ //
+ this.toolsToolStrip.ClickThrough = true;
+ this.toolsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
+ this.toolsToolStrip.Dock = System.Windows.Forms.DockStyle.None;
+ this.toolsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.toolsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
+ this.toolsToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.btnCursor,
+ this.toolStripSeparator1,
+ this.btnRect,
+ this.btnEllipse,
+ this.btnLine,
+ this.btnArrow,
+ this.btnFreehand,
+ this.btnText,
+ this.btnSpeechBubble,
+ this.btnStepLabel,
+ this.toolStripSeparator14,
+ this.btnHighlight,
+ this.btnObfuscate,
+ this.toolStripSplitButton1,
+ this.toolStripSeparator13,
+ this.btnCrop,
+ this.rotateCwToolstripButton,
+ this.rotateCcwToolstripButton,
+ this.btnResize});
+ this.toolsToolStrip.Name = "toolsToolStrip";
+ this.toolsToolStrip.Stretch = true;
+ this.toolsToolStrip.TabIndex = 0;
+ this.toolsToolStrip.BackColor = System.Drawing.SystemColors.Control;
+ this.toolsToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
+ //
+ // btnCursor
+ //
+ this.btnCursor.Checked = true;
+ this.btnCursor.CheckOnClick = true;
+ this.btnCursor.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.btnCursor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnCursor.Image = ((System.Drawing.Image)(resources.GetObject("btnCursor.Image")));
+ this.btnCursor.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnCursor.LanguageKey = "editor_cursortool";
+ this.btnCursor.Name = "btnCursor";
+ this.btnCursor.Click += new System.EventHandler(this.BtnCursorClick);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ //
+ // btnRect
+ //
+ this.btnRect.CheckOnClick = true;
+ this.btnRect.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnRect.Image = ((System.Drawing.Image)(resources.GetObject("btnRect.Image")));
+ this.btnRect.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnRect.LanguageKey = "editor_drawrectangle";
+ this.btnRect.Name = "btnRect";
+ this.btnRect.Click += new System.EventHandler(this.BtnRectClick);
+ //
+ // btnEllipse
+ //
+ this.btnEllipse.CheckOnClick = true;
+ this.btnEllipse.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnEllipse.Image = ((System.Drawing.Image)(resources.GetObject("btnEllipse.Image")));
+ this.btnEllipse.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnEllipse.LanguageKey = "editor_drawellipse";
+ this.btnEllipse.Name = "btnEllipse";
+ this.btnEllipse.Click += new System.EventHandler(this.BtnEllipseClick);
+ //
+ // btnLine
+ //
+ this.btnLine.CheckOnClick = true;
+ this.btnLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnLine.Image = ((System.Drawing.Image)(resources.GetObject("btnLine.Image")));
+ this.btnLine.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnLine.LanguageKey = "editor_drawline";
+ this.btnLine.Name = "btnLine";
+ this.btnLine.Click += new System.EventHandler(this.BtnLineClick);
+ //
+ // btnArrow
+ //
+ this.btnArrow.CheckOnClick = true;
+ this.btnArrow.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnArrow.Image = ((System.Drawing.Image)(resources.GetObject("btnArrow.Image")));
+ this.btnArrow.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnArrow.LanguageKey = "editor_drawarrow";
+ this.btnArrow.Name = "btnArrow";
+ this.btnArrow.Click += new System.EventHandler(this.BtnArrowClick);
+ //
+ // btnFreehand
+ //
+ this.btnFreehand.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnFreehand.Image = ((System.Drawing.Image)(resources.GetObject("btnFreehand.Image")));
+ this.btnFreehand.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnFreehand.LanguageKey = "editor_drawfreehand";
+ this.btnFreehand.Name = "btnFreehand";
+ this.btnFreehand.Click += new System.EventHandler(this.BtnFreehandClick);
+ //
+ // btnText
+ //
+ this.btnText.CheckOnClick = true;
+ this.btnText.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnText.Image = ((System.Drawing.Image)(resources.GetObject("btnText.Image")));
+ this.btnText.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnText.LanguageKey = "editor_drawtextbox";
+ this.btnText.Name = "btnText";
+ this.btnText.Click += new System.EventHandler(this.BtnTextClick);
+ //
+ // btnSpeechBubble
+ //
+ this.btnSpeechBubble.CheckOnClick = true;
+ this.btnSpeechBubble.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnSpeechBubble.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image")));
+ this.btnSpeechBubble.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnSpeechBubble.LanguageKey = "editor_speechbubble";
+ this.btnSpeechBubble.Name = "btnSpeechBubble";
+ this.btnSpeechBubble.Click += new System.EventHandler(this.BtnSpeechBubbleClick);
+ //
+ // btnStepLabel
+ //
+ this.btnStepLabel.CheckOnClick = true;
+ this.btnStepLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnStepLabel.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image")));
+ this.btnStepLabel.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnStepLabel.LanguageKey = "editor_counter";
+ this.btnStepLabel.Name = "btnStepLabel";
+ this.btnStepLabel.Click += new System.EventHandler(this.BtnStepLabelClick);
+ //
+ // toolStripSeparator14
+ //
+ this.toolStripSeparator14.Name = "toolStripSeparator14";
+ //
+ // btnHighlight
+ //
+ this.btnHighlight.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnHighlight.Image = ((System.Drawing.Image)(resources.GetObject("btnHighlight.Image")));
+ this.btnHighlight.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnHighlight.LanguageKey = "editor_drawhighlighter";
+ this.btnHighlight.Name = "btnHighlight";
+ this.btnHighlight.Click += new System.EventHandler(this.BtnHighlightClick);
+ //
+ // btnObfuscate
+ //
+ this.btnObfuscate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnObfuscate.Image = ((System.Drawing.Image)(resources.GetObject("btnObfuscate.Image")));
+ this.btnObfuscate.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnObfuscate.LanguageKey = "editor_obfuscate";
+ this.btnObfuscate.Name = "btnObfuscate";
+ this.btnObfuscate.Click += new System.EventHandler(this.BtnObfuscateClick);
+ //
+ // toolStripSplitButton1
+ //
+ this.toolStripSplitButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.toolStripSplitButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addBorderToolStripMenuItem,
+ this.addDropshadowToolStripMenuItem,
+ this.tornEdgesToolStripMenuItem,
+ this.grayscaleToolStripMenuItem,
+ this.invertToolStripMenuItem});
+ this.toolStripSplitButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripSplitButton1.Image")));
+ this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.toolStripSplitButton1.LanguageKey = "editor_effects";
+ this.toolStripSplitButton1.Name = "toolStripSplitButton1";
+ this.toolStripSplitButton1.ShowDropDownArrow = false;
+ this.toolStripSplitButton1.Text = "toolStripSplitButton1";
+ //
+ // addBorderToolStripMenuItem
+ //
+ this.addBorderToolStripMenuItem.LanguageKey = "editor_border";
+ this.addBorderToolStripMenuItem.Name = "addBorderToolStripMenuItem";
+ this.addBorderToolStripMenuItem.Click += new System.EventHandler(this.AddBorderToolStripMenuItemClick);
+ //
+ // addDropshadowToolStripMenuItem
+ //
+ this.addDropshadowToolStripMenuItem.LanguageKey = "editor_image_shadow";
+ this.addDropshadowToolStripMenuItem.Name = "addDropshadowToolStripMenuItem";
+ this.addDropshadowToolStripMenuItem.MouseUp += AddDropshadowToolStripMenuItemMouseUp;
+ //
+ // tornEdgesToolStripMenuItem
+ //
+ this.tornEdgesToolStripMenuItem.LanguageKey = "editor_torn_edge";
+ this.tornEdgesToolStripMenuItem.Name = "tornEdgesToolStripMenuItem";
+ this.tornEdgesToolStripMenuItem.MouseUp += TornEdgesToolStripMenuItemMouseUp;
+ //
+ // grayscaleToolStripMenuItem
+ //
+ this.grayscaleToolStripMenuItem.LanguageKey = "editor_grayscale";
+ this.grayscaleToolStripMenuItem.Name = "grayscaleToolStripMenuItem";
+ this.grayscaleToolStripMenuItem.Click += new System.EventHandler(this.GrayscaleToolStripMenuItemClick);
+ //
+ // invertToolStripMenuItem
+ //
+ this.invertToolStripMenuItem.LanguageKey = "editor_invert";
+ this.invertToolStripMenuItem.Name = "invertToolStripMenuItem";
+ this.invertToolStripMenuItem.Click += new System.EventHandler(this.InvertToolStripMenuItemClick);
+ //
+ // btnResize
+ //
+ this.btnResize.Name = "btnResize";
+ this.btnResize.Click += new System.EventHandler(this.BtnResizeClick);
+ this.btnResize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnResize.Image = ((System.Drawing.Image)(resources.GetObject("btnResize.Image")));
+ this.btnResize.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnResize.LanguageKey = "editor_resize";
+ //
+ // toolStripSeparator13
+ //
+ this.toolStripSeparator13.Name = "toolStripSeparator13";
+ //
+ // btnCrop
+ //
+ this.btnCrop.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnCrop.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
+ this.btnCrop.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnCrop.LanguageKey = "editor_crop";
+ this.btnCrop.Name = "btnCrop";
+ this.btnCrop.Click += new System.EventHandler(this.BtnCropClick);
+ //
+ // rotateCwToolstripButton
+ //
+ this.rotateCwToolstripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.rotateCwToolstripButton.Image = ((System.Drawing.Image)(resources.GetObject("rotateCwToolstripButton.Image")));
+ this.rotateCwToolstripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.rotateCwToolstripButton.LanguageKey = "editor_rotatecw";
+ this.rotateCwToolstripButton.Name = "rotateCwToolstripButton";
+ this.rotateCwToolstripButton.Click += new System.EventHandler(this.RotateCwToolstripButtonClick);
+ //
+ // rotateCcwToolstripButton
+ //
+ this.rotateCcwToolstripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.rotateCcwToolstripButton.Image = ((System.Drawing.Image)(resources.GetObject("rotateCcwToolstripButton.Image")));
+ this.rotateCcwToolstripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.rotateCcwToolstripButton.LanguageKey = "editor_rotateccw";
+ this.rotateCcwToolstripButton.Name = "rotateCcwToolstripButton";
+ this.rotateCcwToolstripButton.Click += new System.EventHandler(this.RotateCcwToolstripButtonClick);
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.ClickThrough = true;
+ this.menuStrip1.ImageScalingSize = coreConfiguration.IconSize;
+ this.menuStrip1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.menuStrip1.Stretch = true;
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileStripMenuItem,
+ this.editToolStripMenuItem,
+ this.objectToolStripMenuItem,
+ this.pluginToolStripMenuItem,
+ this.helpToolStripMenuItem});
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.BackColor = System.Drawing.SystemColors.Control;
+ this.menuStrip1.TabIndex = 1;
+ //
+ // fileStripMenuItem
+ //
+ this.fileStripMenuItem.LanguageKey = "editor_file";
+ this.fileStripMenuItem.Name = "fileStripMenuItem";
+ this.fileStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileStripMenuItem.Text = "File";
+ this.fileStripMenuItem.DropDownOpening += new System.EventHandler(this.FileMenuDropDownOpening);
+ // Fix for BUG-1653, the DropDownOpening is not called when there are no children.
+ this.fileStripMenuItem.DropDownItems.Add(toolStripSeparator9);
+ //
+ // editToolStripMenuItem
+ //
+ this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.undoToolStripMenuItem,
+ this.redoToolStripMenuItem,
+ this.toolStripSeparator15,
+ this.cutToolStripMenuItem,
+ this.copyToolStripMenuItem,
+ this.pasteToolStripMenuItem,
+ this.toolStripSeparator4,
+ this.duplicateToolStripMenuItem,
+ this.toolStripSeparator12,
+ this.preferencesToolStripMenuItem,
+ this.toolStripSeparator5,
+ this.autoCropToolStripMenuItem,
+ this.toolStripSeparator17,
+ this.insert_window_toolstripmenuitem});
+ this.editToolStripMenuItem.LanguageKey = "editor_edit";
+ this.editToolStripMenuItem.Name = "editToolStripMenuItem";
+ this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
+ this.editToolStripMenuItem.Text = "Edit";
+ this.editToolStripMenuItem.Click += new System.EventHandler(this.EditToolStripMenuItemClick);
+ //
+ // undoToolStripMenuItem
+ //
+ this.undoToolStripMenuItem.Enabled = false;
+ this.undoToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("undoToolStripMenuItem.Image")));
+ this.undoToolStripMenuItem.Name = "undoToolStripMenuItem";
+ this.undoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
+ this.undoToolStripMenuItem.Text = "Undo";
+ this.undoToolStripMenuItem.Click += new System.EventHandler(this.UndoToolStripMenuItemClick);
+ //
+ // redoToolStripMenuItem
+ //
+ this.redoToolStripMenuItem.Enabled = false;
+ this.redoToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("redoToolStripMenuItem.Image")));
+ this.redoToolStripMenuItem.Name = "redoToolStripMenuItem";
+ this.redoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y)));
+ this.redoToolStripMenuItem.Text = "Redo";
+ this.redoToolStripMenuItem.Click += new System.EventHandler(this.RedoToolStripMenuItemClick);
+ //
+ // toolStripSeparator15
+ //
+ this.toolStripSeparator15.Name = "toolStripSeparator15";
+ //
+ // cutToolStripMenuItem
+ //
+ this.cutToolStripMenuItem.Enabled = false;
+ this.cutToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cutToolStripMenuItem.Image")));
+ this.cutToolStripMenuItem.LanguageKey = "editor_cuttoclipboard";
+ this.cutToolStripMenuItem.Name = "cutToolStripMenuItem";
+ this.cutToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
+ this.cutToolStripMenuItem.Click += new System.EventHandler(this.CutToolStripMenuItemClick);
+ //
+ // copyToolStripMenuItem
+ //
+ this.copyToolStripMenuItem.Enabled = false;
+ this.copyToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("copyToolStripMenuItem.Image")));
+ this.copyToolStripMenuItem.LanguageKey = "editor_copytoclipboard";
+ this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
+ this.copyToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
+ this.copyToolStripMenuItem.Click += new System.EventHandler(this.CopyToolStripMenuItemClick);
+ //
+ // pasteToolStripMenuItem
+ //
+ this.pasteToolStripMenuItem.Enabled = false;
+ this.pasteToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pasteToolStripMenuItem.Image")));
+ this.pasteToolStripMenuItem.LanguageKey = "editor_pastefromclipboard";
+ this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem";
+ this.pasteToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
+ this.pasteToolStripMenuItem.Click += new System.EventHandler(this.PasteToolStripMenuItemClick);
+ //
+ // toolStripSeparator4
+ //
+ this.toolStripSeparator4.Name = "toolStripSeparator4";
+ //
+ // duplicateToolStripMenuItem
+ //
+ this.duplicateToolStripMenuItem.Enabled = false;
+ this.duplicateToolStripMenuItem.LanguageKey = "editor_duplicate";
+ this.duplicateToolStripMenuItem.Name = "duplicateToolStripMenuItem";
+ this.duplicateToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D)));
+ this.duplicateToolStripMenuItem.Click += new System.EventHandler(this.DuplicateToolStripMenuItemClick);
+ //
+ // toolStripSeparator12
+ //
+ this.toolStripSeparator12.Name = "toolStripSeparator12";
+ //
+ // preferencesToolStripMenuItem
+ //
+ this.preferencesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("preferencesToolStripMenuItem.Image")));
+ this.preferencesToolStripMenuItem.LanguageKey = "contextmenu_settings";
+ this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem";
+ this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.PreferencesToolStripMenuItemClick);
+ //
+ // toolStripSeparator5
+ //
+ this.toolStripSeparator5.Name = "toolStripSeparator5";
+ //
+ // autoCropToolStripMenuItem
+ //
+ this.autoCropToolStripMenuItem.LanguageKey = "editor_autocrop";
+ this.autoCropToolStripMenuItem.Name = "autoCropToolStripMenuItem";
+ this.autoCropToolStripMenuItem.Click += new System.EventHandler(this.AutoCropToolStripMenuItemClick);
+ //
+ // toolStripSeparator17
+ //
+ this.toolStripSeparator17.Name = "toolStripSeparator17";
+ //
+ // insert_window_toolstripmenuitem
+ //
+ this.insert_window_toolstripmenuitem.LanguageKey = "editor_insertwindow";
+ this.insert_window_toolstripmenuitem.Name = "insert_window_toolstripmenuitem";
+ this.insert_window_toolstripmenuitem.MouseEnter += new System.EventHandler(this.Insert_window_toolstripmenuitemMouseEnter);
+ //
+ // objectToolStripMenuItem
+ //
+ this.objectToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addRectangleToolStripMenuItem,
+ this.addEllipseToolStripMenuItem,
+ this.drawLineToolStripMenuItem,
+ this.drawArrowToolStripMenuItem,
+ this.drawFreehandToolStripMenuItem,
+ this.addTextBoxToolStripMenuItem,
+ this.addSpeechBubbleToolStripMenuItem,
+ this.addCounterToolStripMenuItem,
+ this.toolStripSeparator8,
+ this.selectAllToolStripMenuItem,
+ this.removeObjectToolStripMenuItem,
+ this.toolStripSeparator7,
+ this.arrangeToolStripMenuItem,
+ this.saveElementsToolStripMenuItem,
+ this.loadElementsToolStripMenuItem});
+ this.objectToolStripMenuItem.LanguageKey = "editor_object";
+ this.objectToolStripMenuItem.Name = "objectToolStripMenuItem";
+ this.objectToolStripMenuItem.Size = new System.Drawing.Size(54, 20);
+ this.objectToolStripMenuItem.Text = "Object";
+ //
+ // addRectangleToolStripMenuItem
+ //
+ this.addRectangleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addRectangleToolStripMenuItem.Image")));
+ this.addRectangleToolStripMenuItem.LanguageKey = "editor_drawrectangle";
+ this.addRectangleToolStripMenuItem.Name = "addRectangleToolStripMenuItem";
+ this.addRectangleToolStripMenuItem.Click += new System.EventHandler(this.AddRectangleToolStripMenuItemClick);
+ //
+ // addEllipseToolStripMenuItem
+ //
+ this.addEllipseToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addEllipseToolStripMenuItem.Image")));
+ this.addEllipseToolStripMenuItem.LanguageKey = "editor_drawellipse";
+ this.addEllipseToolStripMenuItem.Name = "addEllipseToolStripMenuItem";
+ this.addEllipseToolStripMenuItem.Click += new System.EventHandler(this.AddEllipseToolStripMenuItemClick);
+ //
+ // drawLineToolStripMenuItem
+ //
+ this.drawLineToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawLineToolStripMenuItem.Image")));
+ this.drawLineToolStripMenuItem.LanguageKey = "editor_drawline";
+ this.drawLineToolStripMenuItem.Name = "drawLineToolStripMenuItem";
+ this.drawLineToolStripMenuItem.Click += new System.EventHandler(this.DrawLineToolStripMenuItemClick);
+ //
+ // drawArrowToolStripMenuItem
+ //
+ this.drawArrowToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawArrowToolStripMenuItem.Image")));
+ this.drawArrowToolStripMenuItem.LanguageKey = "editor_drawarrow";
+ this.drawArrowToolStripMenuItem.Name = "drawArrowToolStripMenuItem";
+ this.drawArrowToolStripMenuItem.Click += new System.EventHandler(this.DrawArrowToolStripMenuItemClick);
+ //
+ // drawFreehandToolStripMenuItem
+ //
+ this.drawFreehandToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("drawFreehandToolStripMenuItem.Image")));
+ this.drawFreehandToolStripMenuItem.LanguageKey = "editor_drawfreehand";
+ this.drawFreehandToolStripMenuItem.Name = "drawFreehandToolStripMenuItem";
+ this.drawFreehandToolStripMenuItem.Click += new System.EventHandler(this.DrawFreehandToolStripMenuItemClick);
+ //
+ // addTextBoxToolStripMenuItem
+ //
+ this.addTextBoxToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("addTextBoxToolStripMenuItem.Image")));
+ this.addTextBoxToolStripMenuItem.LanguageKey = "editor_drawtextbox";
+ this.addTextBoxToolStripMenuItem.Name = "addTextBoxToolStripMenuItem";
+ this.addTextBoxToolStripMenuItem.Click += new System.EventHandler(this.AddTextBoxToolStripMenuItemClick);
+ //
+ // addSpeechBubbleToolStripMenuItem
+ //
+ this.addSpeechBubbleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image")));
+ this.addSpeechBubbleToolStripMenuItem.LanguageKey = "editor_speechbubble";
+ this.addSpeechBubbleToolStripMenuItem.Name = "addSpeechBubbleToolStripMenuItem";
+ this.addSpeechBubbleToolStripMenuItem.Click += new System.EventHandler(this.AddSpeechBubbleToolStripMenuItemClick);
+ //
+ // addCounterToolStripMenuItem
+ //
+ this.addCounterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image")));
+ this.addCounterToolStripMenuItem.LanguageKey = "editor_counter";
+ this.addCounterToolStripMenuItem.Name = "addCounterToolStripMenuItem";
+ this.addCounterToolStripMenuItem.Click += new System.EventHandler(this.AddCounterToolStripMenuItemClick);
+ //
+ // toolStripSeparator8
+ //
+ this.toolStripSeparator8.Name = "toolStripSeparator8";
+ //
+ // selectAllToolStripMenuItem
+ //
+ this.selectAllToolStripMenuItem.LanguageKey = "editor_selectall";
+ this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem";
+ this.selectAllToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
+ this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.SelectAllToolStripMenuItemClick);
+ //
+ // removeObjectToolStripMenuItem
+ //
+ this.removeObjectToolStripMenuItem.Enabled = false;
+ this.removeObjectToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("removeObjectToolStripMenuItem.Image")));
+ this.removeObjectToolStripMenuItem.LanguageKey = "editor_deleteelement";
+ this.removeObjectToolStripMenuItem.Name = "removeObjectToolStripMenuItem";
+ this.removeObjectToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.Delete;
+ this.removeObjectToolStripMenuItem.Click += new System.EventHandler(this.RemoveObjectToolStripMenuItemClick);
+ //
+ // toolStripSeparator7
+ //
+ this.toolStripSeparator7.Name = "toolStripSeparator7";
+ //
+ // arrangeToolStripMenuItem
+ //
+ this.arrangeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.upToTopToolStripMenuItem,
+ this.upOneLevelToolStripMenuItem,
+ this.downOneLevelToolStripMenuItem,
+ this.downToBottomToolStripMenuItem});
+ this.arrangeToolStripMenuItem.Enabled = false;
+ this.arrangeToolStripMenuItem.LanguageKey = "editor_arrange";
+ this.arrangeToolStripMenuItem.Name = "arrangeToolStripMenuItem";
+ //
+ // upToTopToolStripMenuItem
+ //
+ this.upToTopToolStripMenuItem.Enabled = false;
+ this.upToTopToolStripMenuItem.LanguageKey = "editor_uptotop";
+ this.upToTopToolStripMenuItem.Name = "upToTopToolStripMenuItem";
+ this.upToTopToolStripMenuItem.ShortcutKeyDisplayString = "Home";
+ this.upToTopToolStripMenuItem.Click += new System.EventHandler(this.UpToTopToolStripMenuItemClick);
+ //
+ // upOneLevelToolStripMenuItem
+ //
+ this.upOneLevelToolStripMenuItem.Enabled = false;
+ this.upOneLevelToolStripMenuItem.LanguageKey = "editor_uponelevel";
+ this.upOneLevelToolStripMenuItem.Name = "upOneLevelToolStripMenuItem";
+ this.upOneLevelToolStripMenuItem.ShortcutKeyDisplayString = "PgUp";
+ this.upOneLevelToolStripMenuItem.Click += new System.EventHandler(this.UpOneLevelToolStripMenuItemClick);
+ //
+ // downOneLevelToolStripMenuItem
+ //
+ this.downOneLevelToolStripMenuItem.Enabled = false;
+ this.downOneLevelToolStripMenuItem.LanguageKey = "editor_downonelevel";
+ this.downOneLevelToolStripMenuItem.Name = "downOneLevelToolStripMenuItem";
+ this.downOneLevelToolStripMenuItem.ShortcutKeyDisplayString = "PgDn";
+ this.downOneLevelToolStripMenuItem.Click += new System.EventHandler(this.DownOneLevelToolStripMenuItemClick);
+ //
+ // downToBottomToolStripMenuItem
+ //
+ this.downToBottomToolStripMenuItem.Enabled = false;
+ this.downToBottomToolStripMenuItem.LanguageKey = "editor_downtobottom";
+ this.downToBottomToolStripMenuItem.Name = "downToBottomToolStripMenuItem";
+ this.downToBottomToolStripMenuItem.ShortcutKeyDisplayString = "End";
+ this.downToBottomToolStripMenuItem.Click += new System.EventHandler(this.DownToBottomToolStripMenuItemClick);
+ //
+ // saveElementsToolStripMenuItem
+ //
+ this.saveElementsToolStripMenuItem.LanguageKey = "editor_save_objects";
+ this.saveElementsToolStripMenuItem.Name = "saveElementsToolStripMenuItem";
+ this.saveElementsToolStripMenuItem.Click += new System.EventHandler(this.SaveElementsToolStripMenuItemClick);
+ //
+ // loadElementsToolStripMenuItem
+ //
+ this.loadElementsToolStripMenuItem.LanguageKey = "editor_load_objects";
+ this.loadElementsToolStripMenuItem.Name = "loadElementsToolStripMenuItem";
+ this.loadElementsToolStripMenuItem.Click += new System.EventHandler(this.LoadElementsToolStripMenuItemClick);
+ //
+ // pluginToolStripMenuItem
+ //
+ this.pluginToolStripMenuItem.LanguageKey = "settings_plugins";
+ this.pluginToolStripMenuItem.Name = "pluginToolStripMenuItem";
+ this.pluginToolStripMenuItem.Text = "Plugins";
+ this.pluginToolStripMenuItem.Visible = false;
+ //
+ // helpToolStripMenuItem
+ //
+ this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.helpToolStripMenuItem1,
+ this.aboutToolStripMenuItem});
+ this.helpToolStripMenuItem.LanguageKey = "contextmenu_help";
+ this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
+ this.helpToolStripMenuItem.Text = "Help";
+ //
+ // helpToolStripMenuItem1
+ //
+ this.helpToolStripMenuItem1.Image = ((System.Drawing.Image)(resources.GetObject("helpToolStripMenuItem1.Image")));
+ this.helpToolStripMenuItem1.LanguageKey = "contextmenu_help";
+ this.helpToolStripMenuItem1.Name = "helpToolStripMenuItem1";
+ this.helpToolStripMenuItem1.ShortcutKeys = System.Windows.Forms.Keys.F1;
+ this.helpToolStripMenuItem1.Click += new System.EventHandler(this.HelpToolStripMenuItem1Click);
+ //
+ // aboutToolStripMenuItem
+ //
+ this.aboutToolStripMenuItem.LanguageKey = "contextmenu_about";
+ this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
+ this.aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutToolStripMenuItemClick);
+ //
+ // destinationsToolStrip
+ //
+ this.destinationsToolStrip.ClickThrough = true;
+ this.destinationsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
+ this.destinationsToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.destinationsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.destinationsToolStrip.Name = "toolStrip1";
+ this.destinationsToolStrip.Stretch = true;
+ this.destinationsToolStrip.TabIndex = 0;
+ this.destinationsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
+ this.destinationsToolStrip.BackColor = System.Drawing.SystemColors.Control;
+ this.destinationsToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
+ this.destinationsToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.btnSave,
+ this.btnClipboard,
+ this.btnPrint,
+ this.toolStripSeparator2,
+ this.btnDelete,
+ this.toolStripSeparator3,
+ this.btnCut,
+ this.btnCopy,
+ this.btnPaste,
+ this.btnUndo,
+ this.btnRedo,
+ this.toolStripSeparator6,
+ this.btnSettings,
+ this.toolStripSeparator11,
+ this.toolStripSeparator16,
+ this.btnHelp});
+ //
+ // btnSave
+ //
+ this.btnSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnSave.Image = ((System.Drawing.Image)(resources.GetObject("btnSave.Image")));
+ this.btnSave.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnSave.LanguageKey = "editor_save";
+ this.btnSave.Name = "btnSave";
+ this.btnSave.Click += new System.EventHandler(this.BtnSaveClick);
+ //
+ // btnClipboard
+ //
+ this.btnClipboard.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnClipboard.Image = ((System.Drawing.Image)(resources.GetObject("btnClipboard.Image")));
+ this.btnClipboard.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnClipboard.LanguageKey = "editor_copyimagetoclipboard";
+ this.btnClipboard.Name = "btnClipboard";
+ this.btnClipboard.Click += new System.EventHandler(this.BtnClipboardClick);
+ //
+ // btnPrint
+ //
+ this.btnPrint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnPrint.Image = ((System.Drawing.Image)(resources.GetObject("btnPrint.Image")));
+ this.btnPrint.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnPrint.LanguageKey = "editor_print";
+ this.btnPrint.Name = "btnPrint";
+ this.btnPrint.Text = "Print";
+ this.btnPrint.Click += new System.EventHandler(this.BtnPrintClick);
+ //
+ // toolStripSeparator2
+ //
+ this.toolStripSeparator2.Name = "toolStripSeparator2";
+ //
+ // btnDelete
+ //
+ this.btnDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnDelete.Enabled = false;
+ this.btnDelete.Image = ((System.Drawing.Image)(resources.GetObject("btnDelete.Image")));
+ this.btnDelete.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnDelete.LanguageKey = "editor_deleteelement";
+ this.btnDelete.Name = "btnDelete";
+ this.btnDelete.Click += new System.EventHandler(this.BtnDeleteClick);
+ //
+ // toolStripSeparator3
+ //
+ this.toolStripSeparator3.Name = "toolStripSeparator3";
+ //
+ // btnCut
+ //
+ this.btnCut.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnCut.Enabled = false;
+ this.btnCut.Image = ((System.Drawing.Image)(resources.GetObject("btnCut.Image")));
+ this.btnCut.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnCut.LanguageKey = "editor_cuttoclipboard";
+ this.btnCut.Name = "btnCut";
+ this.btnCut.Click += new System.EventHandler(this.BtnCutClick);
+ //
+ // btnCopy
+ //
+ this.btnCopy.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnCopy.Enabled = false;
+ this.btnCopy.Image = ((System.Drawing.Image)(resources.GetObject("btnCopy.Image")));
+ this.btnCopy.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnCopy.LanguageKey = "editor_copytoclipboard";
+ this.btnCopy.Name = "btnCopy";
+ this.btnCopy.Click += new System.EventHandler(this.BtnCopyClick);
+ //
+ // btnPaste
+ //
+ this.btnPaste.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnPaste.Enabled = false;
+ this.btnPaste.Image = ((System.Drawing.Image)(resources.GetObject("btnPaste.Image")));
+ this.btnPaste.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnPaste.LanguageKey = "editor_pastefromclipboard";
+ this.btnPaste.Name = "btnPaste";
+ this.btnPaste.Click += new System.EventHandler(this.BtnPasteClick);
+ //
+ // btnUndo
+ //
+ this.btnUndo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnUndo.Enabled = false;
+ this.btnUndo.Image = ((System.Drawing.Image)(resources.GetObject("btnUndo.Image")));
+ this.btnUndo.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnUndo.Name = "btnUndo";
+ this.btnUndo.Click += new System.EventHandler(this.BtnUndoClick);
+ //
+ // btnRedo
+ //
+ this.btnRedo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnRedo.Enabled = false;
+ this.btnRedo.Image = ((System.Drawing.Image)(resources.GetObject("btnRedo.Image")));
+ this.btnRedo.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnRedo.Name = "btnRedo";
+ this.btnRedo.Click += new System.EventHandler(this.BtnRedoClick);
+ //
+ // toolStripSeparator6
+ //
+ this.toolStripSeparator6.Name = "toolStripSeparator6";
+ //
+ // btnSettings
+ //
+ this.btnSettings.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnSettings.Image = ((System.Drawing.Image)(resources.GetObject("btnSettings.Image")));
+ this.btnSettings.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnSettings.LanguageKey = "contextmenu_settings";
+ this.btnSettings.Name = "btnSettings";
+ this.btnSettings.Click += new System.EventHandler(this.BtnSettingsClick);
+ //
+ // toolStripSeparator11
+ //
+ this.toolStripSeparator11.Name = "toolStripSeparator11";
+ //
+ // toolStripSeparator16
+ //
+ this.toolStripSeparator16.Name = "toolStripSeparator16";
+ //
+ // btnHelp
+ //
+ this.btnHelp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnHelp.Image = ((System.Drawing.Image)(resources.GetObject("btnHelp.Image")));
+ this.btnHelp.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnHelp.LanguageKey = "contextmenu_help";
+ this.btnHelp.Name = "btnHelp";
+ this.btnHelp.Text = "Help";
+ this.btnHelp.Click += new System.EventHandler(this.BtnHelpClick);
+ //
+ // propertiesToolStrip
+ //
+ this.propertiesToolStrip.AutoSize = false;
+ this.propertiesToolStrip.ClickThrough = true;
+ this.propertiesToolStrip.ImageScalingSize = coreConfiguration.IconSize;
+ this.propertiesToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.propertiesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.IconSize.Height + 10);
+ this.propertiesToolStrip.Name = "propertiesToolStrip";
+ this.propertiesToolStrip.Stretch = true;
+ this.propertiesToolStrip.TabIndex = 2;
+ this.propertiesToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
+ this.propertiesToolStrip.BackColor = System.Drawing.SystemColors.Control;
+ this.propertiesToolStrip.OverflowButton.DropDown.BackColor = System.Drawing.SystemColors.Control;
+ this.propertiesToolStrip.Paint += PropertiesToolStrip_Paint;
+ this.propertiesToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.obfuscateModeButton,
+ this.highlightModeButton,
+ this.btnFillColor,
+ this.btnLineColor,
+ this.lineThicknessLabel,
+ this.lineThicknessUpDown,
+ this.fontFamilyComboBox,
+ this.fontSizeLabel,
+ this.fontSizeUpDown,
+ this.fontBoldButton,
+ this.fontItalicButton,
+ this.textHorizontalAlignmentButton,
+ this.textVerticalAlignmentButton,
+ this.blurRadiusLabel,
+ this.blurRadiusUpDown,
+ this.brightnessLabel,
+ this.brightnessUpDown,
+ this.previewQualityLabel,
+ this.previewQualityUpDown,
+ this.magnificationFactorLabel,
+ this.magnificationFactorUpDown,
+ this.pixelSizeLabel,
+ this.pixelSizeUpDown,
+ this.arrowHeadsLabel,
+ this.arrowHeadsDropDownButton,
+ this.shadowButton,
+ this.toolStripSeparator,
+ this.toolStripSeparator10,
+ this.btnConfirm,
+ this.btnCancel,
+ this.counterLabel,
+ this.counterUpDown});
+ //
+ // obfuscateModeButton
+ //
+ this.obfuscateModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.obfuscateModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.pixelizeToolStripMenuItem,
+ this.blurToolStripMenuItem});
+ this.obfuscateModeButton.Image = ((System.Drawing.Image)(resources.GetObject("obfuscateModeButton.Image")));
+ this.obfuscateModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.obfuscateModeButton.LanguageKey = "editor_obfuscate_mode";
+ this.obfuscateModeButton.Name = "obfuscateModeButton";
+ this.obfuscateModeButton.SelectedTag = Greenshot.Drawing.FilterContainer.PreparedFilter.BLUR;
+ this.obfuscateModeButton.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.BLUR;
+ //
+ // pixelizeToolStripMenuItem
+ //
+ this.pixelizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pixelizeToolStripMenuItem.Image")));
+ this.pixelizeToolStripMenuItem.LanguageKey = "editor_obfuscate_pixelize";
+ this.pixelizeToolStripMenuItem.Name = "pixelizeToolStripMenuItem";
+ this.pixelizeToolStripMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.PIXELIZE;
+ //
+ // blurToolStripMenuItem
+ //
+ this.blurToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("blurToolStripMenuItem.Image")));
+ this.blurToolStripMenuItem.LanguageKey = "editor_obfuscate_blur";
+ this.blurToolStripMenuItem.Name = "blurToolStripMenuItem";
+ this.blurToolStripMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.BLUR;
+ //
+ // highlightModeButton
+ //
+ this.highlightModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.highlightModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.textHighlightMenuItem,
+ this.areaHighlightMenuItem,
+ this.grayscaleHighlightMenuItem,
+ this.magnifyMenuItem});
+ this.highlightModeButton.Image = ((System.Drawing.Image)(resources.GetObject("highlightModeButton.Image")));
+ this.highlightModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.highlightModeButton.LanguageKey = "editor_highlight_mode";
+ this.highlightModeButton.Name = "highlightModeButton";
+ this.highlightModeButton.SelectedTag = Greenshot.Drawing.FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
+ this.highlightModeButton.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
+ //
+ // textHighlightMenuItem
+ //
+ this.textHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("textHighlightMenuItem.Image")));
+ this.textHighlightMenuItem.LanguageKey = "editor_highlight_text";
+ this.textHighlightMenuItem.Name = "textHighlightMenuItem";
+ this.textHighlightMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
+ //
+ // areaHighlightMenuItem
+ //
+ this.areaHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("areaHighlightMenuItem.Image")));
+ this.areaHighlightMenuItem.LanguageKey = "editor_highlight_area";
+ this.areaHighlightMenuItem.Name = "areaHighlightMenuItem";
+ this.areaHighlightMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.AREA_HIGHLIGHT;
+ //
+ // grayscaleHighlightMenuItem
+ //
+ this.grayscaleHighlightMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("grayscaleHighlightMenuItem.Image")));
+ this.grayscaleHighlightMenuItem.LanguageKey = "editor_highlight_grayscale";
+ this.grayscaleHighlightMenuItem.Name = "grayscaleHighlightMenuItem";
+ this.grayscaleHighlightMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.GRAYSCALE;
+ //
+ // magnifyMenuItem
+ //
+ this.magnifyMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("magnifyMenuItem.Image")));
+ this.magnifyMenuItem.LanguageKey = "editor_highlight_magnify";
+ this.magnifyMenuItem.Name = "magnifyMenuItem";
+ this.magnifyMenuItem.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.MAGNIFICATION;
+ //
+ // btnFillColor
+ //
+ this.btnFillColor.BackColor = System.Drawing.Color.Transparent;
+ this.btnFillColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnFillColor.Image = ((System.Drawing.Image)(resources.GetObject("btnFillColor.Image")));
+ this.btnFillColor.LanguageKey = "editor_backcolor";
+ this.btnFillColor.Name = "btnFillColor";
+ this.btnFillColor.SelectedColor = System.Drawing.Color.Transparent;
+ //
+ // btnLineColor
+ //
+ this.btnLineColor.BackColor = System.Drawing.Color.Transparent;
+ this.btnLineColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnLineColor.Image = ((System.Drawing.Image)(resources.GetObject("btnLineColor.Image")));
+ this.btnLineColor.LanguageKey = "editor_forecolor";
+ this.btnLineColor.Name = "btnLineColor";
+ this.btnLineColor.SelectedColor = System.Drawing.Color.FromArgb(((int)(((byte)(203)))), ((int)(((byte)(222)))), ((int)(((byte)(250)))));
+ //
+ // counterLabel
+ //
+ this.counterLabel.LanguageKey = "editor_counter_startvalue";
+ this.counterLabel.Name = "counterLabel";
+ //
+ // counterUpDown
+ //
+ this.counterUpDown.DecimalPlaces = 0;
+ this.counterUpDown.Increment = 1;
+ this.counterUpDown.Maximum = 100;
+ this.counterUpDown.Minimum = 0;
+ this.counterUpDown.Name = "counterUpDown";
+ this.counterUpDown.Text = "1";
+ this.counterUpDown.Value = 1;
+ this.counterUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.counterUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // lineThicknessLabel
+ //
+ this.lineThicknessLabel.LanguageKey = "editor_thickness";
+ this.lineThicknessLabel.Name = "lineThicknessLabel";
+ //
+ // lineThicknessUpDown
+ //
+ this.lineThicknessUpDown.DecimalPlaces = 0;
+ this.lineThicknessUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.lineThicknessUpDown.Maximum = new decimal(new int[] {
+ 100,
+ 0,
+ 0,
+ 0});
+ this.lineThicknessUpDown.Minimum = new decimal(new int[] {
+ 0,
+ 0,
+ 0,
+ 0});
+ this.lineThicknessUpDown.Name = "lineThicknessUpDown";
+ this.lineThicknessUpDown.Text = "0";
+ this.lineThicknessUpDown.Value = new decimal(new int[] {
+ 0,
+ 0,
+ 0,
+ 0});
+ this.lineThicknessUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.lineThicknessUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // fontFamilyComboBox
+ //
+ this.fontFamilyComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.fontFamilyComboBox.AutoSize = false;
+ this.fontFamilyComboBox.MaxDropDownItems = 20;
+ this.fontFamilyComboBox.Name = "fontFamilyComboBox";
+ this.fontFamilyComboBox.Size = new System.Drawing.Size(200, 20);
+ this.fontFamilyComboBox.Text = "Aharoni";
+ this.fontFamilyComboBox.Padding = new System.Windows.Forms.Padding(2,0,0,2);
+ this.fontFamilyComboBox.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.fontFamilyComboBox.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // fontSizeLabel
+ //
+ this.fontSizeLabel.LanguageKey = "editor_fontsize";
+ this.fontSizeLabel.Name = "fontSizeLabel";
+ //
+ // fontSizeUpDown
+ //
+ this.fontSizeUpDown.DecimalPlaces = 0;
+ this.fontSizeUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.fontSizeUpDown.Maximum = new decimal(new int[] {
+ 500,
+ 0,
+ 0,
+ 0});
+ this.fontSizeUpDown.Minimum = new decimal(new int[] {
+ 7,
+ 0,
+ 0,
+ 0});
+ this.fontSizeUpDown.Name = "fontSizeUpDown";
+ this.fontSizeUpDown.Text = "12";
+ this.fontSizeUpDown.Value = new decimal(new int[] {
+ 12,
+ 0,
+ 0,
+ 0});
+ this.fontSizeUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.fontSizeUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // fontBoldButton
+ //
+ this.fontBoldButton.CheckOnClick = true;
+ this.fontBoldButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.fontBoldButton.Image = ((System.Drawing.Image)(resources.GetObject("fontBoldButton.Image")));
+ this.fontBoldButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.fontBoldButton.LanguageKey = "editor_bold";
+ this.fontBoldButton.Name = "fontBoldButton";
+ this.fontBoldButton.Text = "Bold";
+ this.fontBoldButton.Click += new System.EventHandler(this.FontBoldButtonClick);
+ //
+ // fontItalicButton
+ //
+ this.fontItalicButton.CheckOnClick = true;
+ this.fontItalicButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.fontItalicButton.Image = ((System.Drawing.Image)(resources.GetObject("fontItalicButton.Image")));
+ this.fontItalicButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.fontItalicButton.LanguageKey = "editor_italic";
+ this.fontItalicButton.Name = "fontItalicButton";
+ this.fontItalicButton.Text = "Italic";
+ this.fontItalicButton.Click += new System.EventHandler(this.FontItalicButtonClick);
+ //
+ // textVerticalAlignmentButton
+ //
+ this.textVerticalAlignmentButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.alignTopToolStripMenuItem,
+ this.alignMiddleToolStripMenuItem,
+ this.alignBottomToolStripMenuItem});
+ this.textVerticalAlignmentButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.textVerticalAlignmentButton.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignMiddle.Image")));
+ this.textVerticalAlignmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.textVerticalAlignmentButton.LanguageKey = "editor_align_vertical";
+ this.textVerticalAlignmentButton.Name = "textVerticalAlignmentButton";
+ this.textVerticalAlignmentButton.SelectedTag = System.Drawing.StringAlignment.Center;
+ this.textVerticalAlignmentButton.Tag = System.Drawing.StringAlignment.Center;
+ //
+ // alignTopToolStripMenuItem
+ //
+ this.alignTopToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignTopToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignTop.Image")));
+ this.alignTopToolStripMenuItem.LanguageKey = "editor_align_top";
+ this.alignTopToolStripMenuItem.Name = "alignTopToolStripMenuItem";
+ this.alignTopToolStripMenuItem.Tag = System.Drawing.StringAlignment.Near;
+ //
+ // alignMiddleToolStripMenuItem
+ //
+ this.alignMiddleToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignMiddleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignMiddle.Image")));
+ this.alignMiddleToolStripMenuItem.LanguageKey = "editor_align_middle";
+ this.alignMiddleToolStripMenuItem.Name = "alignMiddleToolStripMenuItem";
+ this.alignMiddleToolStripMenuItem.Tag = System.Drawing.StringAlignment.Center;
+ //
+ // alignBottomToolStripMenuItem
+ //
+ this.alignBottomToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignBottomToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignBottom.Image")));
+ this.alignBottomToolStripMenuItem.LanguageKey = "editor_align_bottom";
+ this.alignBottomToolStripMenuItem.Name = "alignBottomToolStripMenuItem";
+ this.alignBottomToolStripMenuItem.Tag = System.Drawing.StringAlignment.Far;
+ //
+ // blurRadiusLabel
+ //
+ this.blurRadiusLabel.LanguageKey = "editor_blur_radius";
+ this.blurRadiusLabel.Name = "blurRadiusLabel";
+ this.blurRadiusLabel.Text = "Blur radius";
+ //
+ // blurRadiusUpDown
+ //
+ this.blurRadiusUpDown.DecimalPlaces = 0;
+ this.blurRadiusUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.blurRadiusUpDown.Maximum = new decimal(new int[] {
+ 100,
+ 0,
+ 0,
+ 0});
+ this.blurRadiusUpDown.Minimum = new decimal(new int[] {
+ 0,
+ 0,
+ 0,
+ 0});
+ this.blurRadiusUpDown.Name = "blurRadiusUpDown";
+ this.blurRadiusUpDown.Text = "1";
+ this.blurRadiusUpDown.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.blurRadiusUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.blurRadiusUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // brightnessLabel
+ //
+ this.brightnessLabel.LanguageKey = "editor_brightness";
+ this.brightnessLabel.Name = "brightnessLabel";
+ this.brightnessLabel.Text = "Brightness";
+ //
+ // brightnessUpDown
+ //
+ this.brightnessUpDown.DecimalPlaces = 0;
+ this.brightnessUpDown.Increment = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ this.brightnessUpDown.Maximum = new decimal(new int[] {
+ 200,
+ 0,
+ 0,
+ 0});
+ this.brightnessUpDown.Minimum = new decimal(new int[] {
+ 0,
+ 0,
+ 0,
+ 0});
+ this.brightnessUpDown.Name = "brightnessUpDown";
+ this.brightnessUpDown.Text = "100";
+ this.brightnessUpDown.Value = new decimal(new int[] {
+ 100,
+ 0,
+ 0,
+ 0});
+ this.brightnessUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.brightnessUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // previewQualityLabel
+ //
+ this.previewQualityLabel.LanguageKey = "editor_preview_quality";
+ this.previewQualityLabel.Name = "previewQualityLabel";
+ this.previewQualityLabel.Text = "Preview quality";
+ //
+ // previewQualityUpDown
+ //
+ this.previewQualityUpDown.DecimalPlaces = 0;
+ this.previewQualityUpDown.Increment = new decimal(new int[] {
+ 10,
+ 0,
+ 0,
+ 0});
+ this.previewQualityUpDown.Maximum = new decimal(new int[] {
+ 100,
+ 0,
+ 0,
+ 0});
+ this.previewQualityUpDown.Minimum = new decimal(new int[] {
+ 10,
+ 0,
+ 0,
+ 0});
+ this.previewQualityUpDown.Name = "previewQualityUpDown";
+ this.previewQualityUpDown.Text = "50";
+ this.previewQualityUpDown.Value = new decimal(new int[] {
+ 50,
+ 0,
+ 0,
+ 0});
+ this.previewQualityUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.previewQualityUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // magnificationFactorLabel
+ //
+ this.magnificationFactorLabel.LanguageKey = "editor_magnification_factor";
+ this.magnificationFactorLabel.Name = "magnificationFactorLabel";
+ this.magnificationFactorLabel.Tag = Greenshot.Drawing.FilterContainer.PreparedFilter.MAGNIFICATION;
+ //
+ // magnificationFactorUpDown
+ //
+ this.magnificationFactorUpDown.DecimalPlaces = 0;
+ this.magnificationFactorUpDown.Increment = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.magnificationFactorUpDown.Maximum = new decimal(new int[] {
+ 8,
+ 0,
+ 0,
+ 0});
+ this.magnificationFactorUpDown.Minimum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.magnificationFactorUpDown.Name = "magnificationFactorUpDown";
+ this.magnificationFactorUpDown.Text = "2";
+ this.magnificationFactorUpDown.Value = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.magnificationFactorUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.magnificationFactorUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // pixelSizeLabel
+ //
+ this.pixelSizeLabel.LanguageKey = "editor_pixel_size";
+ this.pixelSizeLabel.Name = "pixelSizeLabel";
+ //
+ // pixelSizeUpDown
+ //
+ this.pixelSizeUpDown.DecimalPlaces = 0;
+ this.pixelSizeUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.pixelSizeUpDown.Maximum = new decimal(new int[] {
+ 100,
+ 0,
+ 0,
+ 0});
+ this.pixelSizeUpDown.Minimum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.pixelSizeUpDown.Name = "pixelSizeUpDown";
+ this.pixelSizeUpDown.Text = "5";
+ this.pixelSizeUpDown.Value = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ this.pixelSizeUpDown.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
+ this.pixelSizeUpDown.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
+ //
+ // arrowHeadsLabel
+ //
+ this.arrowHeadsLabel.LanguageKey = "editor_pixel_size";
+ this.arrowHeadsLabel.Name = "arrowHeadsLabel";
+ //
+ // arrowHeadsDropDownButton
+ //
+ this.arrowHeadsDropDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.arrowHeadsDropDownButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.arrowHeadStartMenuItem,
+ this.arrowHeadEndMenuItem,
+ this.arrowHeadBothMenuItem,
+ this.arrowHeadNoneMenuItem});
+ this.arrowHeadsDropDownButton.Image = ((System.Drawing.Image)(resources.GetObject("arrowHeadsDropDownButton.Image")));
+ this.arrowHeadsDropDownButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.arrowHeadsDropDownButton.LanguageKey = "editor_arrowheads";
+ this.arrowHeadsDropDownButton.Name = "arrowHeadsDropDownButton";
+ //
+ // arrowHeadStartMenuItem
+ //
+ this.arrowHeadStartMenuItem.LanguageKey = "editor_arrowheads_start";
+ this.arrowHeadStartMenuItem.Name = "arrowHeadStartMenuItem";
+ this.arrowHeadStartMenuItem.Tag = Greenshot.Drawing.ArrowContainer.ArrowHeadCombination.START_POINT;
+ this.arrowHeadStartMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
+ //
+ // arrowHeadEndMenuItem
+ //
+ this.arrowHeadEndMenuItem.LanguageKey = "editor_arrowheads_end";
+ this.arrowHeadEndMenuItem.Name = "arrowHeadEndMenuItem";
+ this.arrowHeadEndMenuItem.Tag = Greenshot.Drawing.ArrowContainer.ArrowHeadCombination.END_POINT;
+ this.arrowHeadEndMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
+ //
+ // arrowHeadBothMenuItem
+ //
+ this.arrowHeadBothMenuItem.LanguageKey = "editor_arrowheads_both";
+ this.arrowHeadBothMenuItem.Name = "arrowHeadBothMenuItem";
+ this.arrowHeadBothMenuItem.Tag = Greenshot.Drawing.ArrowContainer.ArrowHeadCombination.BOTH;
+ this.arrowHeadBothMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
+ //
+ // arrowHeadNoneMenuItem
+ //
+ this.arrowHeadNoneMenuItem.LanguageKey = "editor_arrowheads_none";
+ this.arrowHeadNoneMenuItem.Name = "arrowHeadNoneMenuItem";
+ this.arrowHeadNoneMenuItem.Tag = Greenshot.Drawing.ArrowContainer.ArrowHeadCombination.NONE;
+ this.arrowHeadNoneMenuItem.Click += new System.EventHandler(this.ArrowHeadsToolStripMenuItemClick);
+ //
+ // shadowButton
+ //
+ this.shadowButton.CheckOnClick = true;
+ this.shadowButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.shadowButton.Image = ((System.Drawing.Image)(resources.GetObject("shadowButton.Image")));
+ this.shadowButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.shadowButton.LanguageKey = "editor_shadow";
+ this.shadowButton.Name = "shadowButton";
+ //
+ // toolStripSeparator
+ //
+ this.toolStripSeparator.Name = "toolStripSeparator";
+ //
+ // toolStripSeparator10
+ //
+ this.toolStripSeparator10.Name = "toolStripSeparator10";
+ //
+ // btnConfirm
+ //
+ this.btnConfirm.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnConfirm.Image = ((System.Drawing.Image)(resources.GetObject("btnConfirm.Image")));
+ this.btnConfirm.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnConfirm.LanguageKey = "editor_confirm";
+ this.btnConfirm.Name = "btnConfirm";
+ this.btnConfirm.Text = "Confirm";
+ this.btnConfirm.Click += new System.EventHandler(this.BtnConfirmClick);
+ //
+ // btnCancel
+ //
+ this.btnCancel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.btnCancel.Image = ((System.Drawing.Image)(resources.GetObject("btnCancel.Image")));
+ this.btnCancel.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.btnCancel.LanguageKey = "editor_cancel";
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Text = "Cancel";
+ this.btnCancel.Click += new System.EventHandler(this.BtnCancelClick);
+ //
+ // toolStripSeparator9
+ //
+ this.toolStripSeparator9.Name = "toolStripSeparator9";
+ //
+ // closeToolStripMenuItem
+ //
+ this.closeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("closeToolStripMenuItem.Image")));
+ this.closeToolStripMenuItem.LanguageKey = "editor_close";
+ this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
+ this.closeToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
+ this.closeToolStripMenuItem.Click += new System.EventHandler(this.CloseToolStripMenuItemClick);
+ //
+ // fileSavedStatusContextMenu
+ //
+ this.fileSavedStatusContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.copyPathMenuItem,
+ this.openDirectoryMenuItem});
+ this.fileSavedStatusContextMenu.Name = "contextMenuStrip1";
+ //
+ // copyPathMenuItem
+ //
+ this.copyPathMenuItem.LanguageKey = "editor_copypathtoclipboard";
+ this.copyPathMenuItem.Name = "copyPathMenuItem";
+ this.copyPathMenuItem.Click += new System.EventHandler(this.CopyPathMenuItemClick);
+ //
+ // openDirectoryMenuItem
+ //
+ this.openDirectoryMenuItem.LanguageKey = "editor_opendirinexplorer";
+ this.openDirectoryMenuItem.Name = "openDirectoryMenuItem";
+ this.openDirectoryMenuItem.Click += new System.EventHandler(this.OpenDirectoryMenuItemClick);
+ //
+ // textHorizontalAlignmentButton
+ //
+ this.textHorizontalAlignmentButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.alignLeftToolStripMenuItem,
+ this.alignCenterToolStripMenuItem,
+ this.alignRightToolStripMenuItem});
+ this.textHorizontalAlignmentButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.textHorizontalAlignmentButton.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignCenter.Image")));
+ this.textHorizontalAlignmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.textHorizontalAlignmentButton.LanguageKey = "editor_align_horizontal";
+ this.textHorizontalAlignmentButton.Name = "textHorizontalAlignmentButton";
+ this.textHorizontalAlignmentButton.SelectedTag = System.Drawing.StringAlignment.Center;
+ this.textHorizontalAlignmentButton.Tag = System.Drawing.StringAlignment.Center;
+ //
+ // alignLeftToolStripMenuItem
+ //
+ this.alignLeftToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignLeftToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignLeft.Image")));
+ this.alignLeftToolStripMenuItem.LanguageKey = "editor_align_left";
+ this.alignLeftToolStripMenuItem.Name = "alignLeftToolStripMenuItem";
+ this.alignLeftToolStripMenuItem.Tag = System.Drawing.StringAlignment.Near;
+ //
+ // alignCenterToolStripMenuItem
+ //
+ this.alignCenterToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignCenterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignCenter.Image")));
+ this.alignCenterToolStripMenuItem.LanguageKey = "editor_align_center";
+ this.alignCenterToolStripMenuItem.Name = "alignCenterToolStripMenuItem";
+ this.alignCenterToolStripMenuItem.Tag = System.Drawing.StringAlignment.Center;
+ //
+ // alignRightToolStripMenuItem
+ //
+ this.alignRightToolStripMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.ImageAndText;
+ this.alignRightToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnAlignRight.Image")));
+ this.alignRightToolStripMenuItem.LanguageKey = "editor_align_right";
+ this.alignRightToolStripMenuItem.Name = "alignRightToolStripMenuItem";
+ this.alignRightToolStripMenuItem.Tag = System.Drawing.StringAlignment.Far;
+ //
+ // ImageEditorForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.ClientSize = new System.Drawing.Size(785, 485);
+ this.Controls.Add(this.topToolStripContainer);
+ this.KeyPreview = true;
+ this.LanguageKey = "editor_title";
+ this.Name = "ImageEditorForm";
+ this.Activated += new System.EventHandler(this.ImageEditorFormActivated);
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImageEditorFormFormClosing);
+ this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ImageEditorFormKeyDown);
+ this.Resize += new System.EventHandler(this.ImageEditorFormResize);
+ this.topToolStripContainer.BottomToolStripPanel.ResumeLayout(true);
+ this.topToolStripContainer.ContentPanel.ResumeLayout(true);
+ this.topToolStripContainer.LeftToolStripPanel.ResumeLayout(true);
+ this.topToolStripContainer.TopToolStripPanel.ResumeLayout(true);
+ this.topToolStripContainer.ResumeLayout(true);
+ this.statusStrip1.ResumeLayout(true);
+ this.tableLayoutPanel1.ResumeLayout(true);
+ this.toolsToolStrip.ResumeLayout(true);
+ this.menuStrip1.ResumeLayout(true);
+ this.destinationsToolStrip.ResumeLayout(true);
+ this.propertiesToolStrip.ResumeLayout(true);
+ this.fileSavedStatusContextMenu.ResumeLayout(true);
+ this.ResumeLayout(false);
+ }
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignRightToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignCenterToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignLeftToolStripMenuItem;
+ private Greenshot.Controls.BindableToolStripDropDownButton textHorizontalAlignmentButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignMiddleToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignBottomToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignTopToolStripMenuItem;
+ private Greenshot.Controls.BindableToolStripDropDownButton textVerticalAlignmentButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem invertToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnResize;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem grayscaleToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton rotateCcwToolstripButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton rotateCwToolstripButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addBorderToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem tornEdgesToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addDropshadowToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripDropDownButton toolStripSplitButton1;
+ private System.Windows.Forms.ToolStripStatusLabel dimensionsLabel;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem insert_window_toolstripmenuitem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem grayscaleHighlightMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem areaHighlightMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem textHighlightMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem magnifyMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadStartMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadEndMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadBothMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadNoneMenuItem;
+ private Greenshot.Controls.BindableToolStripButton btnCancel;
+ private Greenshot.Controls.BindableToolStripButton btnConfirm;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem selectAllToolStripMenuItem;
+ private Greenshot.Controls.BindableToolStripDropDownButton highlightModeButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pixelizeToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem blurToolStripMenuItem;
+ private Greenshot.Controls.BindableToolStripDropDownButton obfuscateModeButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnHighlight;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem loadElementsToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem saveElementsToolStripMenuItem;
+ private Greenshot.Controls.FontFamilyComboBox fontFamilyComboBox;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator10;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator;
+ private Greenshot.Controls.BindableToolStripButton shadowButton;
+ private Greenshot.Controls.BindableToolStripButton fontItalicButton;
+ private Greenshot.Controls.BindableToolStripButton fontBoldButton;
+ private Greenshot.Controls.ToolStripNumericUpDown fontSizeUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel fontSizeLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown brightnessUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel brightnessLabel;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pluginToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripDropDownButton arrowHeadsDropDownButton;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel arrowHeadsLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown pixelSizeUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel pixelSizeLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown magnificationFactorUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel magnificationFactorLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown previewQualityUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel previewQualityLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown blurRadiusUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel blurRadiusLabel;
+ private Greenshot.Controls.ToolStripEx propertiesToolStrip;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel lineThicknessLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown lineThicknessUpDown;
+ private GreenshotPlugin.Controls.GreenshotToolStripLabel counterLabel;
+ private Greenshot.Controls.ToolStripNumericUpDown counterUpDown;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator14;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator15;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator16;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnFreehand;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnObfuscate;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator13;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnCrop;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem openDirectoryMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem copyPathMenuItem;
+ private System.Windows.Forms.ContextMenuStrip fileSavedStatusContextMenu;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem downToBottomToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem upToTopToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem downOneLevelToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem upOneLevelToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrangeToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnCursor;
+ private Greenshot.Controls.ToolStripEx toolsToolStrip;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnArrow;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawArrowToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawFreehandToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnText;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnSpeechBubble;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnStepLabel;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawLineToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnLine;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnSettings;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnHelp;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator11;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem aboutToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem helpToolStripMenuItem1;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem helpToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem preferencesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator12;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem closeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator9;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator8;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnPrint;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem duplicateToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem fileStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem removeObjectToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addTextBoxToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addSpeechBubbleToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addCounterToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addEllipseToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addRectangleToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem objectToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pasteToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem copyToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem cutToolStripMenuItem;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem editToolStripMenuItem;
+ private Greenshot.Controls.MenuStripEx menuStrip1;
+ private System.Windows.Forms.ToolStripStatusLabel statusLabel;
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnCut;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnCopy;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnPaste;
+ private System.Windows.Forms.ToolStripButton btnUndo;
+ private System.Windows.Forms.ToolStripButton btnRedo;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnClipboard;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnDelete;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnEllipse;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnSave;
+ private GreenshotPlugin.Controls.GreenshotToolStripButton btnRect;
+ private System.Windows.Forms.ToolStripContainer topToolStripContainer;
+ private Greenshot.Controls.ToolStripEx destinationsToolStrip;
+ private GreenshotPlugin.Controls.NonJumpingPanel panel1;
+ private Greenshot.Controls.ToolStripColorButton btnFillColor;
+ private Greenshot.Controls.ToolStripColorButton btnLineColor;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem autoCropToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator17;
+ }
+}
diff --git a/Greenshot/Forms/ImageEditorForm.cs b/Greenshot/Forms/ImageEditorForm.cs
new file mode 100644
index 000000000..9577772f9
--- /dev/null
+++ b/Greenshot/Forms/ImageEditorForm.cs
@@ -0,0 +1,1484 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.IO;
+using System.Threading;
+using System.Windows.Forms;
+using Greenshot.Configuration;
+using Greenshot.Destinations;
+using Greenshot.Drawing;
+using Greenshot.Drawing.Fields;
+using Greenshot.Drawing.Fields.Binding;
+using Greenshot.Forms;
+using Greenshot.Help;
+using Greenshot.Helpers;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Effects;
+using GreenshotPlugin.Interfaces.Drawing;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+
+namespace Greenshot {
+ ///
+ /// Description of ImageEditorForm.
+ ///
+ public partial class ImageEditorForm : BaseForm, IImageEditor {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ImageEditorForm));
+ private static readonly EditorConfiguration EditorConfiguration = IniConfig.GetIniSection();
+ private static readonly List IgnoreDestinations = new List { PickerDestination.DESIGNATION, EditorDestination.DESIGNATION };
+ private static readonly List EditorList = new List();
+
+ private Surface _surface;
+ private GreenshotToolStripButton[] _toolbarButtons;
+
+ private static readonly string[] SupportedClipboardFormats = {typeof(string).FullName, "Text", typeof(IDrawableContainerList).FullName};
+
+ private bool _originalBoldCheckState;
+ private bool _originalItalicCheckState;
+
+ // whether part of the editor controls are disabled depending on selected item(s)
+ private bool _controlsDisabledDueToConfirmable;
+
+ ///
+ /// An Implementation for the IImageEditor, this way Plugins have access to the HWND handles wich can be used with Win32 API calls.
+ ///
+ public IWin32Window WindowHandle => this;
+
+ public static List Editors {
+ get {
+ try {
+ EditorList.Sort((e1, e2) => string.Compare(e1.Surface.CaptureDetails.Title, e2.Surface.CaptureDetails.Title, StringComparison.Ordinal));
+ } catch(Exception ex) {
+ Log.Warn("Sorting of editors failed.", ex);
+ }
+ return EditorList;
+ }
+ }
+
+ public ImageEditorForm(ISurface iSurface, bool outputMade) {
+ EditorList.Add(this);
+
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ ManualLanguageApply = true;
+ InitializeComponent();
+
+ Load += delegate {
+ var thread = new Thread(AddDestinations)
+ {
+ Name = "add destinations"
+ };
+ thread.Start();
+ };
+
+ // Make sure the editor is placed on the same location as the last editor was on close
+ // But only if this still exists, else it will be reset (BUG-1812)
+ WindowPlacement editorWindowPlacement = EditorConfiguration.GetEditorPlacement();
+ Rectangle screenbounds = WindowCapture.GetScreenBounds();
+ if (!screenbounds.Contains(editorWindowPlacement.NormalPosition))
+ {
+ EditorConfiguration.ResetEditorPlacement();
+ }
+ // ReSharper disable once UnusedVariable
+ WindowDetails thisForm = new WindowDetails(Handle)
+ {
+ WindowPlacement = EditorConfiguration.GetEditorPlacement()
+ };
+
+ // init surface
+ Surface = iSurface;
+ // Intial "saved" flag for asking if the image needs to be save
+ _surface.Modified = !outputMade;
+
+ UpdateUi();
+
+ // Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it.
+ HideToolstripItems();
+ }
+
+ ///
+ /// Remove the current surface
+ ///
+ private void RemoveSurface() {
+ if (_surface == null)
+ {
+ return;
+ }
+ panel1.Controls.Remove(_surface);
+ _surface.Dispose();
+ _surface = null;
+ }
+
+ ///
+ /// Change the surface
+ ///
+ ///
+ private void SetSurface(ISurface newSurface) {
+ if (Surface != null && Surface.Modified) {
+ throw new ApplicationException("Surface modified");
+ }
+
+ RemoveSurface();
+
+ panel1.Height = 10;
+ panel1.Width = 10;
+ _surface = newSurface as Surface;
+ if (_surface != null)
+ {
+ panel1.Controls.Add(_surface);
+ }
+ Image backgroundForTransparency = GreenshotResources.getImage("Checkerboard.Image");
+ if (_surface != null)
+ {
+ _surface.TransparencyBackgroundBrush = new TextureBrush(backgroundForTransparency, WrapMode.Tile);
+
+ _surface.MovingElementChanged += delegate {
+ RefreshEditorControls();
+ };
+ _surface.DrawingModeChanged += surface_DrawingModeChanged;
+ _surface.SurfaceSizeChanged += SurfaceSizeChanged;
+ _surface.SurfaceMessage += SurfaceMessageReceived;
+ _surface.FieldAggregator.FieldChanged += FieldAggregatorFieldChanged;
+ SurfaceSizeChanged(Surface, null);
+
+ BindFieldControls();
+ RefreshEditorControls();
+ // Fix title
+ if (_surface?.CaptureDetails?.Title != null) {
+ Text = _surface.CaptureDetails.Title + " - " + Language.GetString(LangKey.editor_title);
+ }
+ }
+ Activate();
+ WindowDetails.ToForeground(Handle);
+ }
+
+ private void UpdateUi() {
+ // Disable access to the settings, for feature #3521446
+ preferencesToolStripMenuItem.Visible = !coreConfiguration.DisableSettings;
+ toolStripSeparator12.Visible = !coreConfiguration.DisableSettings;
+ toolStripSeparator11.Visible = !coreConfiguration.DisableSettings;
+ btnSettings.Visible = !coreConfiguration.DisableSettings;
+
+ // Make sure Double-buffer is enabled
+ SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
+
+ // resizing the panel is futile, since it is docked. however, it seems
+ // to fix the bug (?) with the vscrollbar not being able to shrink to
+ // a smaller size than the initial panel size (as set by the forms designer)
+ panel1.Height = 10;
+
+ fontFamilyComboBox.PropertyChanged += FontPropertyChanged;
+
+ obfuscateModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
+ highlightModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
+
+ _toolbarButtons = new[] { btnCursor, btnRect, btnEllipse, btnText, btnLine, btnArrow, btnFreehand, btnHighlight, btnObfuscate, btnCrop, btnStepLabel, btnSpeechBubble };
+ //toolbarDropDownButtons = new ToolStripDropDownButton[]{btnBlur, btnPixeliate, btnTextHighlighter, btnAreaHighlighter, btnMagnifier};
+
+ pluginToolStripMenuItem.Visible = pluginToolStripMenuItem.DropDownItems.Count > 0;
+
+ // Workaround: for the MouseWheel event which doesn't get to the panel
+ MouseWheel += PanelMouseWheel;
+
+ // Make sure the value is set correctly when starting
+ counterUpDown.Value = Surface.CounterStart;
+ ApplyLanguage();
+ }
+
+ ///
+ /// Workaround for having a border around the dropdown
+ /// See: http://stackoverflow.com/questions/9560812/change-border-of-toolstripcombobox-with-flat-style
+ ///
+ ///
+ ///
+ private void PropertiesToolStrip_Paint(object sender, PaintEventArgs e) {
+ using (Pen cbBorderPen = new Pen(SystemColors.ActiveBorder)) {
+ // Loop over all items in the propertiesToolStrip
+ foreach (ToolStripItem item in propertiesToolStrip.Items) {
+ ToolStripComboBox cb = item as ToolStripComboBox;
+ // Only ToolStripComboBox that are visible
+ if (cb == null || !cb.Visible) {
+ continue;
+ }
+ // Calculate the rectangle
+ if (cb.ComboBox != null)
+ {
+ Rectangle r = new Rectangle(cb.ComboBox.Location.X - 1, cb.ComboBox.Location.Y - 1, cb.ComboBox.Size.Width + 1, cb.ComboBox.Size.Height + 1);
+
+ // Draw the rectangle
+ e.Graphics.DrawRectangle(cbBorderPen, r);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Get all the destinations and display them in the file menu and the buttons
+ ///
+ private void AddDestinations() {
+ Invoke((MethodInvoker)delegate {
+ // Create export buttons
+ foreach(IDestination destination in DestinationHelper.GetAllDestinations()) {
+ if (destination.Priority <= 2) {
+ continue;
+ }
+ if (!destination.IsActive) {
+ continue;
+ }
+ if (destination.DisplayIcon == null) {
+ continue;
+ }
+ try {
+ AddDestinationButton(destination);
+ } catch (Exception addingException) {
+ Log.WarnFormat("Problem adding destination {0}", destination.Designation);
+ Log.Warn("Exception: ", addingException);
+ }
+ }
+ });
+ }
+
+ private void AddDestinationButton(IDestination toolstripDestination) {
+ if (toolstripDestination.IsDynamic) {
+ ToolStripSplitButton destinationButton = new ToolStripSplitButton
+ {
+ DisplayStyle = ToolStripItemDisplayStyle.Image,
+ Size = new Size(23, 22),
+ Text = toolstripDestination.Description,
+ Image = toolstripDestination.DisplayIcon
+ };
+ //ToolStripDropDownButton destinationButton = new ToolStripDropDownButton();
+
+ ToolStripMenuItem defaultItem = new ToolStripMenuItem(toolstripDestination.Description)
+ {
+ Tag = toolstripDestination,
+ Image = toolstripDestination.DisplayIcon
+ };
+ defaultItem.Click += delegate {
+ toolstripDestination.ExportCapture(true, _surface, _surface.CaptureDetails);
+ };
+
+ // The ButtonClick, this is for the icon, gets the current default item
+ destinationButton.ButtonClick += delegate {
+ toolstripDestination.ExportCapture(true, _surface, _surface.CaptureDetails);
+ };
+
+ // Generate the entries for the drop down
+ destinationButton.DropDownOpening += delegate
+ {
+ ClearItems(destinationButton.DropDownItems);
+ destinationButton.DropDownItems.Add(defaultItem);
+
+ List subDestinations = new List();
+ subDestinations.AddRange(toolstripDestination.DynamicDestinations());
+ if (subDestinations.Count > 0) {
+ subDestinations.Sort();
+ foreach(IDestination subDestination in subDestinations) {
+ IDestination closureFixedDestination = subDestination;
+ ToolStripMenuItem destinationMenuItem = new ToolStripMenuItem(closureFixedDestination.Description)
+ {
+ Tag = closureFixedDestination,
+ Image = closureFixedDestination.DisplayIcon
+ };
+ destinationMenuItem.Click += delegate {
+ closureFixedDestination.ExportCapture(true, _surface, _surface.CaptureDetails);
+ };
+ destinationButton.DropDownItems.Add(destinationMenuItem);
+ }
+ }
+ };
+
+ destinationsToolStrip.Items.Insert(destinationsToolStrip.Items.IndexOf(toolStripSeparator16), destinationButton);
+
+ } else {
+ ToolStripButton destinationButton = new ToolStripButton();
+ destinationsToolStrip.Items.Insert(destinationsToolStrip.Items.IndexOf(toolStripSeparator16), destinationButton);
+ destinationButton.DisplayStyle = ToolStripItemDisplayStyle.Image;
+ destinationButton.Size = new Size(23, 22);
+ destinationButton.Text = toolstripDestination.Description;
+ destinationButton.Image = toolstripDestination.DisplayIcon;
+ destinationButton.Click += delegate {
+ toolstripDestination.ExportCapture(true, _surface, _surface.CaptureDetails);
+ };
+ }
+ }
+
+ ///
+ /// According to some information I found, the clear doesn't work correctly when the shortcutkeys are set?
+ /// This helper method takes care of this.
+ ///
+ ///
+ private void ClearItems(ToolStripItemCollection items) {
+ foreach(var item in items) {
+ ToolStripMenuItem menuItem = item as ToolStripMenuItem;
+ if (menuItem != null && menuItem.ShortcutKeys != Keys.None) {
+ menuItem.ShortcutKeys = Keys.None;
+ }
+ }
+ items.Clear();
+ }
+
+ private void FileMenuDropDownOpening(object sender, EventArgs eventArgs) {
+ ClearItems(fileStripMenuItem.DropDownItems);
+
+ // Add the destinations
+ foreach(IDestination destination in DestinationHelper.GetAllDestinations()) {
+ if (IgnoreDestinations.Contains(destination.Designation)) {
+ continue;
+ }
+ if (!destination.IsActive) {
+ continue;
+ }
+
+ ToolStripMenuItem item = destination.GetMenuItem(true, null, DestinationToolStripMenuItemClick);
+ if (item != null) {
+ item.ShortcutKeys = destination.EditorShortcutKeys;
+ fileStripMenuItem.DropDownItems.Add(item);
+ }
+ }
+ // add the elements after the destinations
+ fileStripMenuItem.DropDownItems.Add(toolStripSeparator9);
+ fileStripMenuItem.DropDownItems.Add(closeToolStripMenuItem);
+ }
+
+ private delegate void SurfaceMessageReceivedThreadSafeDelegate(object sender, SurfaceMessageEventArgs eventArgs);
+ ///
+ /// This is the SufraceMessageEvent receiver which display a message in the status bar if the
+ /// surface is exported. It also updates the title to represent the filename, if there is one.
+ ///
+ ///
+ ///
+ private void SurfaceMessageReceived(object sender, SurfaceMessageEventArgs eventArgs) {
+ if (InvokeRequired) {
+ Invoke(new SurfaceMessageReceivedThreadSafeDelegate(SurfaceMessageReceived), sender, eventArgs);
+ } else {
+ string dateTime = DateTime.Now.ToLongTimeString();
+ // TODO: Fix that we only open files, like in the tooltip
+ switch (eventArgs.MessageType) {
+ case SurfaceMessageTyp.FileSaved:
+ // Put the event message on the status label and attach the context menu
+ UpdateStatusLabel(dateTime + " - " + eventArgs.Message, fileSavedStatusContextMenu);
+ // Change title
+ Text = eventArgs.Surface.LastSaveFullPath + " - " + Language.GetString(LangKey.editor_title);
+ break;
+ default:
+ // Put the event message on the status label
+ UpdateStatusLabel(dateTime + " - " + eventArgs.Message);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// This is called when the size of the surface chances, used for resizing and displaying the size information
+ ///
+ ///
+ ///
+ private void SurfaceSizeChanged(object sender, EventArgs e) {
+ if (EditorConfiguration.MatchSizeToCapture) {
+ // Set editor's initial size to the size of the surface plus the size of the chrome
+ Size imageSize = Surface.Image.Size;
+ Size currentFormSize = Size;
+ Size currentImageClientSize = panel1.ClientSize;
+ int minimumFormWidth = 650;
+ int minimumFormHeight = 530;
+ int newWidth = Math.Max(minimumFormWidth, currentFormSize.Width - currentImageClientSize.Width + imageSize.Width);
+ int newHeight = Math.Max(minimumFormHeight, currentFormSize.Height - currentImageClientSize.Height + imageSize.Height);
+ Size = new Size(newWidth, newHeight);
+ }
+ dimensionsLabel.Text = Surface.Image.Width + "x" + Surface.Image.Height;
+ ImageEditorFormResize(sender, new EventArgs());
+ }
+
+ public ISurface Surface {
+ get {
+ return _surface;
+ }
+ set {
+ SetSurface(value);
+ }
+ }
+
+ public void SetImagePath(string fullpath) {
+ // Check if the editor supports the format
+ if (fullpath != null && (fullpath.EndsWith(".ico") || fullpath.EndsWith(".wmf"))) {
+ fullpath = null;
+ }
+ _surface.LastSaveFullPath = fullpath;
+
+ if (fullpath == null) {
+ return;
+ }
+ UpdateStatusLabel(Language.GetFormattedString(LangKey.editor_imagesaved, fullpath), fileSavedStatusContextMenu);
+ Text = Path.GetFileName(fullpath) + " - " + Language.GetString(LangKey.editor_title);
+ }
+
+ private void surface_DrawingModeChanged(object source, SurfaceDrawingModeEventArgs eventArgs) {
+ switch (eventArgs.DrawingMode) {
+ case DrawingModes.None:
+ SetButtonChecked(btnCursor);
+ break;
+ case DrawingModes.Ellipse:
+ SetButtonChecked(btnEllipse);
+ break;
+ case DrawingModes.Rect:
+ SetButtonChecked(btnRect);
+ break;
+ case DrawingModes.Text:
+ SetButtonChecked(btnText);
+ break;
+ case DrawingModes.SpeechBubble:
+ SetButtonChecked(btnSpeechBubble);
+ break;
+ case DrawingModes.StepLabel:
+ SetButtonChecked(btnStepLabel);
+ break;
+ case DrawingModes.Line:
+ SetButtonChecked(btnLine);
+ break;
+ case DrawingModes.Arrow:
+ SetButtonChecked(btnArrow);
+ break;
+ case DrawingModes.Crop:
+ SetButtonChecked(btnCrop);
+ break;
+ case DrawingModes.Highlight:
+ SetButtonChecked(btnHighlight);
+ break;
+ case DrawingModes.Obfuscate:
+ SetButtonChecked(btnObfuscate);
+ break;
+ case DrawingModes.Path:
+ SetButtonChecked(btnFreehand);
+ break;
+ }
+ }
+
+ #region plugin interfaces
+
+ /**
+ * Interfaces for plugins, see GreenshotInterface for more details!
+ */
+
+ public Image GetImageForExport() {
+ return _surface.GetImageForExport();
+ }
+
+ public ICaptureDetails CaptureDetails => _surface.CaptureDetails;
+
+ public ToolStripMenuItem GetPluginMenuItem() {
+ return pluginToolStripMenuItem;
+ }
+
+ public ToolStripMenuItem GetFileMenuItem() {
+ return fileStripMenuItem;
+ }
+ #endregion
+
+ #region filesystem options
+
+ private void BtnSaveClick(object sender, EventArgs e) {
+ string destinationDesignation = FileDestination.DESIGNATION;
+ if (_surface.LastSaveFullPath == null) {
+ destinationDesignation = FileWithDialogDestination.DESIGNATION;
+ }
+ DestinationHelper.ExportCapture(true, destinationDesignation, _surface, _surface.CaptureDetails);
+ }
+
+ private void BtnClipboardClick(object sender, EventArgs e) {
+ DestinationHelper.ExportCapture(true, ClipboardDestination.DESIGNATION, _surface, _surface.CaptureDetails);
+ }
+
+ private void BtnPrintClick(object sender, EventArgs e) {
+ // The BeginInvoke is a solution for the printdialog not having focus
+ BeginInvoke((MethodInvoker) delegate {
+ DestinationHelper.ExportCapture(true, PrinterDestination.DESIGNATION, _surface, _surface.CaptureDetails);
+ });
+ }
+
+ private void CloseToolStripMenuItemClick(object sender, EventArgs e) {
+ Close();
+ }
+ #endregion
+
+ #region drawing options
+
+ private void BtnEllipseClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Ellipse;
+ RefreshFieldControls();
+ }
+
+ private void BtnCursorClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.None;
+ RefreshFieldControls();
+ }
+
+ private void BtnRectClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Rect;
+ RefreshFieldControls();
+ }
+
+ private void BtnTextClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Text;
+ RefreshFieldControls();
+ }
+
+ private void BtnSpeechBubbleClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.SpeechBubble;
+ RefreshFieldControls();
+ }
+
+ private void BtnStepLabelClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.StepLabel;
+ RefreshFieldControls();
+ }
+
+ private void BtnLineClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Line;
+ RefreshFieldControls();
+ }
+
+ private void BtnArrowClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Arrow;
+ RefreshFieldControls();
+ }
+
+ private void BtnCropClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Crop;
+ RefreshFieldControls();
+ }
+
+ private void BtnHighlightClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Highlight;
+ RefreshFieldControls();
+ }
+
+ private void BtnObfuscateClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Obfuscate;
+ RefreshFieldControls();
+ }
+
+ private void BtnFreehandClick(object sender, EventArgs e) {
+ _surface.DrawingMode = DrawingModes.Path;
+ RefreshFieldControls();
+ }
+
+ private void SetButtonChecked(ToolStripButton btn) {
+ UncheckAllToolButtons();
+ btn.Checked = true;
+ }
+
+ private void UncheckAllToolButtons() {
+ if (_toolbarButtons != null) {
+ foreach (GreenshotToolStripButton butt in _toolbarButtons) {
+ butt.Checked = false;
+ }
+ }
+ }
+
+ private void AddRectangleToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnRectClick(sender, e);
+ }
+
+ private void DrawFreehandToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnFreehandClick(sender, e);
+ }
+
+ private void AddEllipseToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnEllipseClick(sender, e);
+ }
+
+ private void AddTextBoxToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnTextClick(sender, e);
+ }
+
+ private void AddSpeechBubbleToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnSpeechBubbleClick(sender, e);
+ }
+
+ private void AddCounterToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnStepLabelClick(sender, e);
+ }
+
+ private void DrawLineToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnLineClick(sender, e);
+ }
+
+ private void DrawArrowToolStripMenuItemClick(object sender, EventArgs e) {
+ BtnArrowClick(sender, e);
+ }
+
+ private void RemoveObjectToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.RemoveSelectedElements();
+ }
+
+ private void BtnDeleteClick(object sender, EventArgs e) {
+ RemoveObjectToolStripMenuItemClick(sender, e);
+ }
+ #endregion
+
+ #region copy&paste options
+
+ private void CutToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.CutSelectedElements();
+ UpdateClipboardSurfaceDependencies();
+ }
+
+ private void BtnCutClick(object sender, EventArgs e) {
+ CutToolStripMenuItemClick(sender, e);
+ }
+
+ private void CopyToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.CopySelectedElements();
+ UpdateClipboardSurfaceDependencies();
+ }
+
+ private void BtnCopyClick(object sender, EventArgs e) {
+ CopyToolStripMenuItemClick(sender, e);
+ }
+
+ private void PasteToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.PasteElementFromClipboard();
+ UpdateClipboardSurfaceDependencies();
+ }
+
+ private void BtnPasteClick(object sender, EventArgs e) {
+ PasteToolStripMenuItemClick(sender, e);
+ }
+
+ private void UndoToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.Undo();
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void BtnUndoClick(object sender, EventArgs e) {
+ UndoToolStripMenuItemClick(sender, e);
+ }
+
+ private void RedoToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.Redo();
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void BtnRedoClick(object sender, EventArgs e) {
+ RedoToolStripMenuItemClick(sender, e);
+ }
+
+ private void DuplicateToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.DuplicateSelectedElements();
+ UpdateClipboardSurfaceDependencies();
+ }
+ #endregion
+
+ #region element properties
+
+ private void UpOneLevelToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.PullElementsUp();
+ }
+
+ private void DownOneLevelToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.PushElementsDown();
+ }
+
+ private void UpToTopToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.PullElementsToTop();
+ }
+
+ private void DownToBottomToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.PushElementsToBottom();
+ }
+
+
+ #endregion
+
+ #region help
+
+ private void HelpToolStripMenuItem1Click(object sender, EventArgs e) {
+ HelpFileLoader.LoadHelp();
+ }
+
+ private void AboutToolStripMenuItemClick(object sender, EventArgs e) {
+ MainForm.Instance.ShowAbout();
+ }
+
+ private void PreferencesToolStripMenuItemClick(object sender, EventArgs e) {
+ MainForm.Instance.ShowSetting();
+ }
+
+ private void BtnSettingsClick(object sender, EventArgs e) {
+ PreferencesToolStripMenuItemClick(sender, e);
+ }
+
+ private void BtnHelpClick(object sender, EventArgs e) {
+ HelpToolStripMenuItem1Click(sender, e);
+ }
+ #endregion
+
+ #region image editor event handlers
+
+ private void ImageEditorFormActivated(object sender, EventArgs e) {
+ UpdateClipboardSurfaceDependencies();
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void ImageEditorFormFormClosing(object sender, FormClosingEventArgs e) {
+ if (_surface.Modified && !EditorConfiguration.SuppressSaveDialogAtClose) {
+ // Make sure the editor is visible
+ WindowDetails.ToForeground(Handle);
+
+ MessageBoxButtons buttons = MessageBoxButtons.YesNoCancel;
+ // Dissallow "CANCEL" if the application needs to shutdown
+ if (e.CloseReason == CloseReason.ApplicationExitCall || e.CloseReason == CloseReason.WindowsShutDown || e.CloseReason == CloseReason.TaskManagerClosing) {
+ buttons = MessageBoxButtons.YesNo;
+ }
+ DialogResult result = MessageBox.Show(Language.GetString(LangKey.editor_close_on_save), Language.GetString(LangKey.editor_close_on_save_title), buttons, MessageBoxIcon.Question);
+ if (result.Equals(DialogResult.Cancel)) {
+ e.Cancel = true;
+ return;
+ }
+ if (result.Equals(DialogResult.Yes)) {
+ BtnSaveClick(sender,e);
+ // Check if the save was made, if not it was cancelled so we cancel the closing
+ if (_surface.Modified) {
+ e.Cancel = true;
+ return;
+ }
+ }
+ }
+ // persist our geometry string.
+ EditorConfiguration.SetEditorPlacement(new WindowDetails(Handle).WindowPlacement);
+ IniConfig.Save();
+
+ // remove from the editor list
+ EditorList.Remove(this);
+
+ _surface.Dispose();
+
+ GC.Collect();
+ if (coreConfiguration.MinimizeWorkingSetSize) {
+ PsAPI.EmptyWorkingSet();
+ }
+ }
+
+ private void ImageEditorFormKeyDown(object sender, KeyEventArgs e) {
+ // LOG.Debug("Got key event "+e.KeyCode + ", " + e.Modifiers);
+ // avoid conflict with other shortcuts and
+ // make sure there's no selected element claiming input focus
+ if(e.Modifiers.Equals(Keys.None) && !_surface.KeysLocked) {
+ switch(e.KeyCode) {
+ case Keys.Escape:
+ BtnCursorClick(sender, e);
+ break;
+ case Keys.R:
+ BtnRectClick(sender, e);
+ break;
+ case Keys.E:
+ BtnEllipseClick(sender, e);
+ break;
+ case Keys.L:
+ BtnLineClick(sender, e);
+ break;
+ case Keys.F:
+ BtnFreehandClick(sender, e);
+ break;
+ case Keys.A:
+ BtnArrowClick(sender, e);
+ break;
+ case Keys.T:
+ BtnTextClick(sender, e);
+ break;
+ case Keys.S:
+ BtnSpeechBubbleClick(sender, e);
+ break;
+ case Keys.I:
+ BtnStepLabelClick(sender, e);
+ break;
+ case Keys.H:
+ BtnHighlightClick(sender, e);
+ break;
+ case Keys.O:
+ BtnObfuscateClick(sender, e);
+ break;
+ case Keys.C:
+ BtnCropClick(sender, e);
+ break;
+ }
+ } else if (e.Modifiers.Equals(Keys.Control)) {
+ switch (e.KeyCode) {
+ case Keys.Z:
+ UndoToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.Y:
+ RedoToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.Q: // Dropshadow Ctrl + Q
+ AddDropshadowToolStripMenuItemMouseUp(sender, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
+ break;
+ case Keys.B: // Border Ctrl + B
+ AddBorderToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.T: // Torn edge Ctrl + T
+ TornEdgesToolStripMenuItemMouseUp(sender, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
+ break;
+ case Keys.I: // Invert Ctrl + I
+ InvertToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.G: // Grayscale Ctrl + G
+ GrayscaleToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.Delete: // Grayscale Ctrl + Delete
+ ClearToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.Oemcomma: // Rotate CCW Ctrl + ,
+ RotateCcwToolstripButtonClick(sender, e);
+ break;
+ case Keys.OemPeriod: // Rotate CW Ctrl + .
+ RotateCwToolstripButtonClick(sender, e);
+ break;
+ case Keys.Add: // Ctrl + +
+ case Keys.Oemplus: // Ctrl + +
+ EnlargeCanvasToolStripMenuItemClick(sender, e);
+ break;
+ case Keys.Subtract: // Ctrl + -
+ case Keys.OemMinus: // Ctrl + -
+ ShrinkCanvasToolStripMenuItemClick(sender, e);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// This is a "work-around" for the MouseWheel event which doesn't get to the panel
+ ///
+ ///
+ ///
+ private void PanelMouseWheel(object sender, MouseEventArgs e) {
+ panel1.Focus();
+ }
+ #endregion
+
+ #region key handling
+ protected override bool ProcessKeyPreview(ref Message msg) {
+ // disable default key handling if surface has requested a lock
+ if (!_surface.KeysLocked) {
+ return base.ProcessKeyPreview(ref msg);
+ }
+ return false;
+ }
+
+ protected override bool ProcessCmdKey(ref Message msg, Keys keys) {
+ // disable default key handling if surface has requested a lock
+ if (!_surface.KeysLocked) {
+
+ // Go through the destinations to check the EditorShortcut Keys
+ // this way the menu entries don't need to be enabled.
+ // This also fixes bugs #3526974 & #3527020
+ foreach (IDestination destination in DestinationHelper.GetAllDestinations()) {
+ if (IgnoreDestinations.Contains(destination.Designation)) {
+ continue;
+ }
+ if (!destination.IsActive) {
+ continue;
+ }
+
+ if (destination.EditorShortcutKeys == keys) {
+ destination.ExportCapture(true, _surface, _surface.CaptureDetails);
+ return true;
+ }
+ }
+ if (!_surface.ProcessCmdKey(keys)) {
+ return base.ProcessCmdKey(ref msg, keys);
+ }
+ }
+ return false;
+ }
+ #endregion
+
+ #region helpers
+
+ private void UpdateUndoRedoSurfaceDependencies() {
+ if (_surface == null) {
+ return;
+ }
+ bool canUndo = _surface.CanUndo;
+ btnUndo.Enabled = canUndo;
+ undoToolStripMenuItem.Enabled = canUndo;
+ string undoAction = "";
+ if (canUndo) {
+ if (_surface.UndoActionLanguageKey != LangKey.none) {
+ undoAction = Language.GetString(_surface.UndoActionLanguageKey);
+ }
+ }
+ string undoText = Language.GetFormattedString(LangKey.editor_undo, undoAction);
+ btnUndo.Text = undoText;
+ undoToolStripMenuItem.Text = undoText;
+
+ bool canRedo = _surface.CanRedo;
+ btnRedo.Enabled = canRedo;
+ redoToolStripMenuItem.Enabled = canRedo;
+ string redoAction = "";
+ if (canRedo) {
+ if (_surface.RedoActionLanguageKey != LangKey.none) {
+ redoAction = Language.GetString(_surface.RedoActionLanguageKey);
+ }
+ }
+ string redoText = Language.GetFormattedString(LangKey.editor_redo, redoAction);
+ btnRedo.Text = redoText;
+ redoToolStripMenuItem.Text = redoText;
+
+ }
+
+ private void UpdateClipboardSurfaceDependencies() {
+ if (_surface == null) {
+ return;
+ }
+ // check dependencies for the Surface
+ bool hasItems = _surface.HasSelectedElements;
+ bool actionAllowedForSelection = hasItems && !_controlsDisabledDueToConfirmable;
+
+ // buttons
+ btnCut.Enabled = actionAllowedForSelection;
+ btnCopy.Enabled = actionAllowedForSelection;
+ btnDelete.Enabled = actionAllowedForSelection;
+
+ // menus
+ removeObjectToolStripMenuItem.Enabled = actionAllowedForSelection;
+ copyToolStripMenuItem.Enabled = actionAllowedForSelection;
+ cutToolStripMenuItem.Enabled = actionAllowedForSelection;
+ duplicateToolStripMenuItem.Enabled = actionAllowedForSelection;
+
+ // check dependencies for the Clipboard
+ bool hasClipboard = ClipboardHelper.ContainsFormat(SupportedClipboardFormats) || ClipboardHelper.ContainsImage();
+ btnPaste.Enabled = hasClipboard && !_controlsDisabledDueToConfirmable;
+ pasteToolStripMenuItem.Enabled = hasClipboard && !_controlsDisabledDueToConfirmable;
+ }
+
+ #endregion
+
+ #region status label handling
+ private void UpdateStatusLabel(string text, ContextMenuStrip contextMenu = null) {
+ statusLabel.Text = text;
+ statusStrip1.ContextMenuStrip = contextMenu;
+ }
+
+ private void ClearStatusLabel() {
+ UpdateStatusLabel(null);
+ }
+
+ private void StatusLabelClicked(object sender, MouseEventArgs e) {
+ ToolStrip ss = (StatusStrip)((ToolStripStatusLabel)sender).Owner;
+ ss.ContextMenuStrip?.Show(ss, e.X, e.Y);
+ }
+
+ private void CopyPathMenuItemClick(object sender, EventArgs e) {
+ ClipboardHelper.SetClipboardData(_surface.LastSaveFullPath);
+ }
+
+ private void OpenDirectoryMenuItemClick(object sender, EventArgs e) {
+ ExplorerHelper.OpenInExplorer(_surface.LastSaveFullPath);
+ }
+ #endregion
+
+ private void BindFieldControls() {
+ // TODO: This is actually risky, if there are no references than the objects may be garbage collected
+ new BidirectionalBinding(btnFillColor, "SelectedColor", _surface.FieldAggregator.GetField(FieldType.FILL_COLOR), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(btnLineColor, "SelectedColor", _surface.FieldAggregator.GetField(FieldType.LINE_COLOR), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(lineThicknessUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.LINE_THICKNESS), "Value", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(blurRadiusUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.BLUR_RADIUS), "Value", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(magnificationFactorUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.MAGNIFICATION_FACTOR), "Value", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(pixelSizeUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.PIXEL_SIZE), "Value", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(brightnessUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.BRIGHTNESS), "Value", DecimalDoublePercentageConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(fontFamilyComboBox, "Text", _surface.FieldAggregator.GetField(FieldType.FONT_FAMILY), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(fontSizeUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.FONT_SIZE), "Value", DecimalFloatConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(fontBoldButton, "Checked", _surface.FieldAggregator.GetField(FieldType.FONT_BOLD), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(fontItalicButton, "Checked", _surface.FieldAggregator.GetField(FieldType.FONT_ITALIC), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(textHorizontalAlignmentButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.TEXT_HORIZONTAL_ALIGNMENT), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(textVerticalAlignmentButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.TEXT_VERTICAL_ALIGNMENT), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(shadowButton, "Checked", _surface.FieldAggregator.GetField(FieldType.SHADOW), "Value", NotNullValidator.GetInstance());
+ new BidirectionalBinding(previewQualityUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.PREVIEW_QUALITY), "Value", DecimalDoublePercentageConverter.GetInstance(), NotNullValidator.GetInstance());
+ new BidirectionalBinding(obfuscateModeButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.PREPARED_FILTER_OBFUSCATE), "Value");
+ new BidirectionalBinding(highlightModeButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.PREPARED_FILTER_HIGHLIGHT), "Value");
+ new BidirectionalBinding(counterUpDown, "Value", _surface, "CounterStart", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
+ }
+
+ ///
+ /// shows/hides field controls (2nd toolbar on top) depending on fields of selected elements
+ ///
+ private void RefreshFieldControls() {
+ propertiesToolStrip.SuspendLayout();
+ if(_surface.HasSelectedElements || _surface.DrawingMode != DrawingModes.None) {
+ FieldAggregator props = _surface.FieldAggregator;
+ btnFillColor.Visible = props.HasFieldValue(FieldType.FILL_COLOR);
+ btnLineColor.Visible = props.HasFieldValue(FieldType.LINE_COLOR);
+ lineThicknessLabel.Visible = lineThicknessUpDown.Visible = props.HasFieldValue(FieldType.LINE_THICKNESS);
+ blurRadiusLabel.Visible = blurRadiusUpDown.Visible = props.HasFieldValue(FieldType.BLUR_RADIUS);
+ previewQualityLabel.Visible = previewQualityUpDown.Visible = props.HasFieldValue(FieldType.PREVIEW_QUALITY);
+ magnificationFactorLabel.Visible = magnificationFactorUpDown.Visible = props.HasFieldValue(FieldType.MAGNIFICATION_FACTOR);
+ pixelSizeLabel.Visible = pixelSizeUpDown.Visible = props.HasFieldValue(FieldType.PIXEL_SIZE);
+ brightnessLabel.Visible = brightnessUpDown.Visible = props.HasFieldValue(FieldType.BRIGHTNESS);
+ arrowHeadsLabel.Visible = arrowHeadsDropDownButton.Visible = props.HasFieldValue(FieldType.ARROWHEADS);
+ fontFamilyComboBox.Visible = props.HasFieldValue(FieldType.FONT_FAMILY);
+ fontSizeLabel.Visible = fontSizeUpDown.Visible = props.HasFieldValue(FieldType.FONT_SIZE);
+ fontBoldButton.Visible = props.HasFieldValue(FieldType.FONT_BOLD);
+ fontItalicButton.Visible = props.HasFieldValue(FieldType.FONT_ITALIC);
+ textHorizontalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
+ textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
+ shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW);
+ counterLabel.Visible = counterUpDown.Visible = props.HasFieldValue(FieldType.FLAGS)
+ && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER;
+ btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS)
+ && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE;
+
+ obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE);
+ highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT);
+ } else {
+ HideToolstripItems();
+ }
+ propertiesToolStrip.ResumeLayout();
+ }
+
+ private void HideToolstripItems() {
+ foreach(ToolStripItem toolStripItem in propertiesToolStrip.Items) {
+ toolStripItem.Visible = false;
+ }
+ }
+
+ ///
+ /// refreshes all editor controls depending on selected elements and their fields
+ ///
+ private void RefreshEditorControls() {
+ int stepLabels = _surface.CountStepLabels(null);
+ Image icon;
+ if (stepLabels <= 20) {
+ icon = (Image)resources.GetObject($"btnStepLabel{stepLabels:00}.Image");
+ } else {
+ icon = (Image)resources.GetObject("btnStepLabel20+.Image");
+ }
+ btnStepLabel.Image = icon;
+ addCounterToolStripMenuItem.Image = icon;
+
+ FieldAggregator props = _surface.FieldAggregator;
+ // if a confirmable element is selected, we must disable most of the controls
+ // since we demand confirmation or cancel for confirmable element
+ if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE)
+ {
+ // disable most controls
+ if (!_controlsDisabledDueToConfirmable) {
+ ToolStripItemEndisabler.Disable(menuStrip1);
+ ToolStripItemEndisabler.Disable(destinationsToolStrip);
+ ToolStripItemEndisabler.Disable(toolsToolStrip);
+ ToolStripItemEndisabler.Enable(closeToolStripMenuItem);
+ ToolStripItemEndisabler.Enable(helpToolStripMenuItem);
+ ToolStripItemEndisabler.Enable(aboutToolStripMenuItem);
+ ToolStripItemEndisabler.Enable(preferencesToolStripMenuItem);
+ _controlsDisabledDueToConfirmable = true;
+ }
+ } else if(_controlsDisabledDueToConfirmable) {
+ // re-enable disabled controls, confirmable element has either been confirmed or cancelled
+ ToolStripItemEndisabler.Enable(menuStrip1);
+ ToolStripItemEndisabler.Enable(destinationsToolStrip);
+ ToolStripItemEndisabler.Enable(toolsToolStrip);
+ _controlsDisabledDueToConfirmable = false;
+ }
+
+ // en/disable controls depending on whether an element is selected at all
+ UpdateClipboardSurfaceDependencies();
+ UpdateUndoRedoSurfaceDependencies();
+
+ // en/disablearrage controls depending on hierarchy of selected elements
+ bool actionAllowedForSelection = _surface.HasSelectedElements && !_controlsDisabledDueToConfirmable;
+ bool push = actionAllowedForSelection && _surface.CanPushSelectionDown();
+ bool pull = actionAllowedForSelection && _surface.CanPullSelectionUp();
+ arrangeToolStripMenuItem.Enabled = push || pull;
+ if (arrangeToolStripMenuItem.Enabled) {
+ upToTopToolStripMenuItem.Enabled = pull;
+ upOneLevelToolStripMenuItem.Enabled = pull;
+ downToBottomToolStripMenuItem.Enabled = push;
+ downOneLevelToolStripMenuItem.Enabled = push;
+ }
+
+ // finally show/hide field controls depending on the fields of selected elements
+ RefreshFieldControls();
+ }
+
+
+ private void ArrowHeadsToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.FieldAggregator.GetField(FieldType.ARROWHEADS).Value = (ArrowContainer.ArrowHeadCombination)((ToolStripMenuItem)sender).Tag;
+ }
+
+ private void EditToolStripMenuItemClick(object sender, EventArgs e) {
+ UpdateClipboardSurfaceDependencies();
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void FontPropertyChanged(object sender, EventArgs e) {
+ // in case we forced another FontStyle before, reset it first.
+ if (fontBoldButton != null && _originalBoldCheckState != fontBoldButton.Checked)
+ {
+ fontBoldButton.Checked = _originalBoldCheckState;
+ }
+ if (fontItalicButton != null && _originalItalicCheckState != fontItalicButton.Checked)
+ {
+ fontItalicButton.Checked = _originalItalicCheckState;
+ }
+
+ var fontFamily = fontFamilyComboBox.FontFamily;
+
+ bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold);
+ if (fontBoldButton != null)
+ {
+ if (!boldAvailable)
+ {
+ _originalBoldCheckState = fontBoldButton.Checked;
+ fontBoldButton.Checked = false;
+ }
+ fontBoldButton.Enabled = boldAvailable;
+ }
+
+ bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic);
+ if (fontItalicButton != null)
+ {
+ if (!italicAvailable)
+ {
+ fontItalicButton.Checked = false;
+ }
+ fontItalicButton.Enabled = italicAvailable;
+ }
+
+ bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular);
+ if (regularAvailable)
+ {
+ return;
+ }
+ if (boldAvailable) {
+ if (fontBoldButton != null)
+ {
+ fontBoldButton.Checked = true;
+ }
+ } else if(italicAvailable) {
+ if (fontItalicButton != null)
+ {
+ fontItalicButton.Checked = true;
+ }
+ }
+ }
+
+ private void FieldAggregatorFieldChanged(object sender, FieldChangedEventArgs e) {
+ // in addition to selection, deselection of elements, we need to
+ // refresh toolbar if prepared filter mode is changed
+ if(Equals(e.Field.FieldType, FieldType.PREPARED_FILTER_HIGHLIGHT)) {
+ RefreshFieldControls();
+ }
+ }
+
+ private void FontBoldButtonClick(object sender, EventArgs e) {
+ _originalBoldCheckState = fontBoldButton.Checked;
+ }
+
+ private void FontItalicButtonClick(object sender, EventArgs e) {
+ _originalItalicCheckState = fontItalicButton.Checked;
+ }
+
+ private void ToolBarFocusableElementGotFocus(object sender, EventArgs e) {
+ _surface.KeysLocked = true;
+ }
+
+ private void ToolBarFocusableElementLostFocus(object sender, EventArgs e) {
+ _surface.KeysLocked = false;
+ }
+
+ private void SaveElementsToolStripMenuItemClick(object sender, EventArgs e) {
+ SaveFileDialog saveFileDialog = new SaveFileDialog
+ {
+ Filter = "Greenshot templates (*.gst)|*.gst",
+ FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(coreConfiguration.OutputFileFilenamePattern, _surface.CaptureDetails)
+ };
+ DialogResult dialogResult = saveFileDialog.ShowDialog();
+ if(dialogResult.Equals(DialogResult.OK)) {
+ using (Stream streamWrite = File.OpenWrite(saveFileDialog.FileName)) {
+ _surface.SaveElementsToStream(streamWrite);
+ }
+ }
+ }
+
+ private void LoadElementsToolStripMenuItemClick(object sender, EventArgs e) {
+ OpenFileDialog openFileDialog = new OpenFileDialog
+ {
+ Filter = "Greenshot templates (*.gst)|*.gst"
+ };
+ if (openFileDialog.ShowDialog() == DialogResult.OK) {
+ using (Stream streamRead = File.OpenRead(openFileDialog.FileName)) {
+ _surface.LoadElementsFromStream(streamRead);
+ }
+ _surface.Refresh();
+ }
+ }
+
+ private void DestinationToolStripMenuItemClick(object sender, EventArgs e) {
+ IDestination clickedDestination = null;
+ var control = sender as Control;
+ if (control != null) {
+ Control clickedControl = control;
+ if (clickedControl.ContextMenuStrip != null) {
+ clickedControl.ContextMenuStrip.Show(Cursor.Position);
+ return;
+ }
+ clickedDestination = (IDestination)clickedControl.Tag;
+ }
+ else
+ {
+ var item = sender as ToolStripMenuItem;
+ if (item != null) {
+ ToolStripMenuItem clickedMenuItem = item;
+ clickedDestination = (IDestination)clickedMenuItem.Tag;
+ }
+ }
+ ExportInformation exportInformation = clickedDestination?.ExportCapture(true, _surface, _surface.CaptureDetails);
+ if (exportInformation != null && exportInformation.ExportMade) {
+ _surface.Modified = false;
+ }
+ }
+
+ protected void FilterPresetDropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ RefreshFieldControls();
+ Invalidate(true);
+ }
+
+ private void SelectAllToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.SelectAllElements();
+ }
+
+
+ private void BtnConfirmClick(object sender, EventArgs e) {
+ _surface.ConfirmSelectedConfirmableElements(true);
+ RefreshFieldControls();
+ }
+
+ private void BtnCancelClick(object sender, EventArgs e) {
+ _surface.ConfirmSelectedConfirmableElements(false);
+ RefreshFieldControls();
+ }
+
+ private void Insert_window_toolstripmenuitemMouseEnter(object sender, EventArgs e) {
+ ToolStripMenuItem captureWindowMenuItem = (ToolStripMenuItem)sender;
+ MainForm.Instance.AddCaptureWindowMenuItems(captureWindowMenuItem, Contextmenu_window_Click);
+ }
+
+ private void Contextmenu_window_Click(object sender, EventArgs e) {
+ ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
+ try {
+ WindowDetails windowToCapture = (WindowDetails)clickedItem.Tag;
+ ICapture capture = new Capture();
+ using (Graphics graphics = Graphics.FromHwnd(Handle)) {
+ capture.CaptureDetails.DpiX = graphics.DpiY;
+ capture.CaptureDetails.DpiY = graphics.DpiY;
+ }
+ windowToCapture = CaptureHelper.SelectCaptureWindow(windowToCapture);
+ if (windowToCapture != null) {
+ capture = CaptureHelper.CaptureWindow(windowToCapture, capture, coreConfiguration.WindowCaptureMode);
+ if (capture?.CaptureDetails != null && capture.Image != null) {
+ ((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY);
+ _surface.AddImageContainer((Bitmap)capture.Image, 100, 100);
+ }
+ Activate();
+ WindowDetails.ToForeground(Handle);
+ }
+
+ capture?.Dispose();
+ } catch (Exception exception) {
+ Log.Error(exception);
+ }
+ }
+
+ private void AutoCropToolStripMenuItemClick(object sender, EventArgs e) {
+ if (_surface.AutoCrop()) {
+ RefreshFieldControls();
+ }
+ }
+
+ private void AddBorderToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.ApplyBitmapEffect(new BorderEffect());
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ ///
+ /// Added for FEATURE-919, increasing the canvas by 25 pixels in every direction.
+ ///
+ ///
+ ///
+ private void EnlargeCanvasToolStripMenuItemClick(object sender, EventArgs e)
+ {
+ _surface.ApplyBitmapEffect(new ResizeCanvasEffect(25, 25, 25, 25));
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ ///
+ /// Added for FEATURE-919, to make the capture as small as possible again.
+ ///
+ ///
+ ///
+ private void ShrinkCanvasToolStripMenuItemClick(object sender, EventArgs e)
+ {
+ Rectangle cropRectangle;
+ using (Image tmpImage = GetImageForExport())
+ {
+ cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, coreConfiguration.AutoCropDifference);
+ }
+ if (_surface.IsCropPossible(ref cropRectangle))
+ {
+ _surface.ApplyCrop(cropRectangle);
+ UpdateUndoRedoSurfaceDependencies();
+ }
+ }
+
+ ///
+ /// This is used when the dropshadow button is used
+ ///
+ ///
+ /// MouseEventArgs
+ private void AddDropshadowToolStripMenuItemMouseUp(object sender, MouseEventArgs e)
+ {
+ var dropShadowEffect = EditorConfiguration.DropShadowEffectSettings;
+ bool apply;
+ switch (e.Button)
+ {
+ case MouseButtons.Left:
+ apply = true;
+ break;
+ case MouseButtons.Right:
+ var result = new DropShadowSettingsForm(dropShadowEffect).ShowDialog(this);
+ apply = result == DialogResult.OK;
+ break;
+ default:
+ return;
+ }
+
+ if (apply)
+ {
+ _surface.ApplyBitmapEffect(dropShadowEffect);
+ UpdateUndoRedoSurfaceDependencies();
+ }
+ }
+
+
+ ///
+ /// Open the resize settings from, and resize if ok was pressed
+ ///
+ ///
+ ///
+ private void BtnResizeClick(object sender, EventArgs e) {
+ var resizeEffect = new ResizeEffect(_surface.Image.Width, _surface.Image.Height, true);
+ var result = new ResizeSettingsForm(resizeEffect).ShowDialog(this);
+ if (result == DialogResult.OK) {
+ _surface.ApplyBitmapEffect(resizeEffect);
+ UpdateUndoRedoSurfaceDependencies();
+ }
+ }
+
+ ///
+ /// This is used when the torn-edge button is used
+ ///
+ ///
+ /// MouseEventArgs
+ private void TornEdgesToolStripMenuItemMouseUp(object sender, MouseEventArgs e)
+ {
+ var tornEdgeEffect = EditorConfiguration.TornEdgeEffectSettings;
+ bool apply;
+ switch (e.Button)
+ {
+ case MouseButtons.Left:
+ apply = true;
+ break;
+ case MouseButtons.Right:
+ var result = new TornEdgeSettingsForm(tornEdgeEffect).ShowDialog(this);
+ apply = result == DialogResult.OK;
+ break;
+ default:
+ return;
+ }
+
+ if (apply)
+ {
+ _surface.ApplyBitmapEffect(tornEdgeEffect);
+ UpdateUndoRedoSurfaceDependencies();
+ }
+ }
+
+ private void GrayscaleToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.ApplyBitmapEffect(new GrayscaleEffect());
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void ClearToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.Clear(Color.Transparent);
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void RotateCwToolstripButtonClick(object sender, EventArgs e) {
+ _surface.ApplyBitmapEffect(new RotateEffect(90));
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void RotateCcwToolstripButtonClick(object sender, EventArgs e) {
+ _surface.ApplyBitmapEffect(new RotateEffect(270));
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void InvertToolStripMenuItemClick(object sender, EventArgs e) {
+ _surface.ApplyBitmapEffect(new InvertEffect());
+ UpdateUndoRedoSurfaceDependencies();
+ }
+
+ private void ImageEditorFormResize(object sender, EventArgs e) {
+ if (Surface?.Image == null || panel1 == null) {
+ return;
+ }
+ Size imageSize = Surface.Image.Size;
+ Size currentClientSize = panel1.ClientSize;
+ var canvas = Surface as Control;
+ Panel panel = (Panel) canvas?.Parent;
+ if (panel == null) {
+ return;
+ }
+ int offsetX = -panel.HorizontalScroll.Value;
+ int offsetY = -panel.VerticalScroll.Value;
+ if (currentClientSize.Width > imageSize.Width) {
+ canvas.Left = offsetX + (currentClientSize.Width - imageSize.Width) / 2;
+ } else {
+ canvas.Left = offsetX + 0;
+ }
+ if (currentClientSize.Height > imageSize.Height) {
+ canvas.Top = offsetY + (currentClientSize.Height - imageSize.Height) / 2;
+ } else {
+ canvas.Top = offsetY + 0;
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.resx b/Greenshot/Forms/ImageEditorForm.resx
similarity index 88%
rename from src/Greenshot.Editor/Forms/ImageEditorForm.resx
rename to Greenshot/Forms/ImageEditorForm.resx
index 1c5b104fd..88fd73b87 100644
--- a/src/Greenshot.Editor/Forms/ImageEditorForm.resx
+++ b/Greenshot/Forms/ImageEditorForm.resx
@@ -1,1119 +1,1029 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFMSURBVDhPY2BAAmFhYb4hISFayGIksQMCAjKKioqqyTYE
- aEDmfyDIz8+v8fX11SbJdpBiT0/PbJABIJCVlVVLsiFubm65MANAdEZGRr2rq6sO0S5xcnLKRzYAxE5J
- SWl0dnbWJcoQGxubQnQDQPz4+PhmoJweQUMsLS2LsRkAEouKimoxNzfHb4iJiUkpLgNA4uHh4W0GBgb6
- OF2ip6dXgWzAp0+fvjo4ONSDxGEYaEAUTgPU1dWrQAY8f/78fWdn50oQe+7cuTtVVVVx24psmoKCQh1I
- MzDq+oHs+PPnz9/58OHDNyMjo3wVFRV2goEoKSnZaG9vP1FGRkZXTExMHBhwM0CumDJlyl4pKSlDggYI
- CQkli4qKwp0L5AefOXPmHsgVsrKyhQQNQFfAxcUlAcwfs0GuAHpjMskGgDQICwv7AWNgKgcHhx02AwCj
- LeXNW0xBiwAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGhSURBVDhPY2CgFBiX7TEzLtuVA6KJNQtFj2HJ7tz///+f
- AdFGpTuiicHIehiMynZZGJTuyp+58+7Cl+++nyIGg9SC9ID0gl1tULIj7sW77yfvv/q6mxgMUgvSA/ey
- ftH2hKfvvx+/8/zTDmIwSC1ID9wAncKtiY9efzl688mnbcj48uMPG07cfrN4/+WXM3acfzZx85mnfSB8
- +u675SA9cAO08zYm33/x5dCVR+83g/C5ux/W7b3ycs7G008mrDv5tA+Cn8DxkRtvloL0wA3Qyt+cevvF
- lwPnH3zYAJLcePrplHUnnkxadwqIkWkQG4gPXX+9AqQHboB6zvr0q08/7tt75dXiDaeeTgPjE0+nYmCo
- 3JEbr1eB9MANUMtalwn01/b1p57MWnvyycwNaBgkBhMH0Ueuv1oH0gM3QDljdfbRG282Af06D4bXn3w6
- F4RBfHQ2UO1GkB6wAUppy50VUla0lC88u+Tw9TdbQBgYDpuRaZg4TAykFqQHpJdBOn5RLygpg2ip+MWl
- xGBkPQwiEXO8RcJnTwXRxGYmcvTgNBsAn7X331hK7TkAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIMSURBVDhPY2DAAYzL9pgZl+3KAdG41GAV1y/frmBUtsvb
- sGR37v///8+AaMOyXYkgMZAcTsPs6/ezGJbucvZtP5S55PDDSbP33F5iULwzb9rOOwsfv/m2ESQGkgOp
- AanFMMiwZIdH4fzzpY/fft31+M2XA/dffd2NjEFiIDmQGpBaFAN0inZoBHcfzXv86uuuO88/7QTiHTjw
- TpAakFqQHrghuoVbo7aeezITpOnW009b8WGQGpBakB6wAVp5m2y087eU9m++sfTqow+bkPH5e+/WHLnx
- asGOCy+mbjzztG/1ycddINy4/NIskB6QXpABFaDQBtEXHnxYD8Kn7rxbtePC8xkrjz3uWXnkIRivOPKw
- G4aR9TBo5qy31czZWNW+/uqS07ffrt1/5dXCVcceTVxx9FEfMl5+5FE/CIPEqpadnwPSA9IL9oZ69obE
- VUcfTN97+eWSFUcfTl5+9OEkXHjN8UfTF+671wfSAw9E9ez1uu6Ne8oOXX25dBVQAdCWadgwSO7QtZdL
- XBt2loL0oESlSsaa4Jj+gzVHgIYAAwzojYezQHj18cezQTRIDCQHUgNSi5GQjNNmssqnrQiwKNtY2b3u
- 4qSDV54vLJx7aolC8orWqoVnV4LEQHIgNSC1OJO0ROxCTam4RYlSsQvrJGMX9oFiCESDxEByJGUskYg5
- 3kA8DUSTpJEUxQBDDL1n/h9HZwAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADASURBVDhPYzAu22NmXLYrB0QzkAMMS3bn/v///wyIJkc/
- g1HZLguD4p15BqU7s3Qq94iTZQhIk2nJFgmDkh1xIJoyQ4q3xWtRYghIs07h1kSNgu2SZLsEpFknf3MS
- xYZoF2xK0ShYS75L1LM3SGnkbUwD0WR7B6RZPXtdBkWGqKavlFbLXJsFosl2CUizcvqaHIoMUUlZKyOf
- vLxBIXlFq1ziCheyXCMZu7APlHdANFkGiETM8QbiaSCaLAPQNQEAHzZMfWDTaNwAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADOSURBVDhPYzAu22NmXLYrB0QzkAMMS3bn/v///wyIJkc/
- g1HZLguD4p15BqU7s3Qq94iTZQhIk2nJFgmDkh1xIJoyQ4q3xWtRYghIs07h1kSNgu2SZLsEpFknf3MS
- xYZoF2xK0ShYS75L1LM3SGnkbUwD0WR7B6RZPXtdBswQ7fzNDSQbppq+Ulotc22Wdt7mXrIMANkI0qyc
- viYHRJPsApCtUNwnn7y8QSF5Ratc4goXkg0CaZCMXdgHyjsgmiwDRCLmeAPxNBBNlgHomgDCEFXWJ2yt
- cwAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHZSURBVDhPY2AgATxnYBDDqzy1aatuSssWf2yKnjIw2Dxk
- ZFx3npGxHachKU1bt6Q0bQlDVxAQEKDm4OCQ/6+09P8jd/eXaxgYXDAMSWnalpbavHVm6KpVzMiSMM1/
- //79v2bNmqurGBiOYHVBUvOWU0DbjZEl9y1lsN80i3HL9WNB//esMv7AycnZgdP5qfXbHiTX7xCCKYBp
- /vmi+v+VPX6vWvMZDuMPwOZt01Mat87IzMwUxNCcw3Y+Ozs7OC8vzystLY0LXyA21td4vlnYL/oWZPOJ
- PUE/Glwk/0K8t3VVavOWrSnN254DwysEqyELyxnk5lbx1L67m/Z/y0Kz9y25HFfq6+tZkBWntG1VAxq0
- Oq1+kwiKIf8ZGBj7sxmb/r87878ojHFBhj9DFS6npjZtW5HStF0bRb4thbHn2dVl/3OCGJdnBDB44guw
- 1KYtS5Jbt+mhq/mf7s+4KsWXAdVkNFWpLdslk5u3bsTwAjAaXwADqC2tZasJLtuBmriAzm8FqmvCTIn1
- 22SAoVue0rhtO9CJF4GhviCteVsF0K8JQHZcSvPWouSmbWuAqXV+Vv0WCZxeBIY6U0b9TjGgU72BthUC
- NbcDDe5Mad5ek9KyzYKEzEucUgDgY9pgutX3/gAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFZSURBVDhPY2CgBjAu2+NqVLYrihQM0gO326xqd9Lrj98u
- vvz4/RQxGKQWpAdugG31zuwX776f3Hn++Rq3hl31MAwSA2FkMZAakBhID9wAx9pdJa8/fj/nVL+zDCYI
- Yj99//04CKOLg9SC9MANcG/YFetav7PGpX6XBUwQZMPT11+OgjCybSA1ILUgPXjD37xqZ8KdF1/2XXv4
- aRuITXJkmZbujj504+XSQ9deLgGxSTbApHRX7OHrb5aBMIhNsgHmlbtSD117vRKEQWySDbCt2lFw+Mbr
- NSAMYpNkgHn+egWnmh3Vh6+92XAUiEFskBhRhiilrw1UTl+T07TiYvvuiy9W7r78YiWIDRIDyWEYIpe4
- wkUheUUriAZJKqQuz7/x9PPxCw8+7Dt2/c0WED5378NekBhIDsMAydiFff///z8DoiVjFpWRgsGGiUTM
- 8QbiaSCaKD+iKQIAuEYmAAjjsCcAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFZSURBVDhPY2CgBjAu2+NqVLYrihQM0gO326xqd9Lrj98u
- vvz4/RQxGKQWpAdugG31zuwX776f3Hn++Rq3hl31MAwSA2FkMZAakBhID9wAx9pdJa8/fj/nVL+zDCYI
- Yj99//04CKOLg9SC9MANcG/YFetav7PGpX6XBUwQZMPT11+OgjCybSA1ILUgPXjD37xqZ8KdF1/2XXv4
- aRuITXJkmZbujj504+XSQ9deLgGxSTbApHRX7OHrb5aBMIhNsgHmlbtSD117vRKEQWySDbCt2lFw+Mbr
- NSAMYpNkgHn+egWnmh3Vh6+92XAUiEFskBhRhiilrw1UTl+T07TiYvvuiy9W7r78YiWIDRIDyWEYIpe4
- wkUheUUriAZJKqQuz7/x9PPxCw8+7Dt2/c0WED5378NekBhIDsMAydiFff///z8DoiVjFpWRgsGGiUTM
- 8QbiaSCaKD+iKQIAuEYmAAjjsCcAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFRSURBVDhP1ZI/a8JQFMVPMFu3unVMCM3egkuHDkWEFgqF
- jq4ODoLgB3AsOETc3EQN+AeVuroUUeuQUXAQRVEEUfMVbt99bQqWDHHsg8chL/f8uPe8B/isePw163fu
- e3Y44ON4BAml/R6024EymRfabkGbDWi9Bq1WoOUStFiAZjPcn4BcF9TpmJTP31G7bUpAOv0sd6NhSkC9
- bsrvWs2k+Ryn3TGAO2i1rimVepIAVu6AdTQKS/U68AXkchFynEtKJmMSwMoA1uEwLNUDTKfIDga4+h2D
- M0gkHkSbOrEygJW3betyhGr1+1+lotN4jLdeD063i2LgoL3Cfh8xNvPIkwlc20YiMOSvuVyGUyrhJhDg
- n5pVVb01DOPdC+ysmUUwRigUKlqWRZqmfZ5rhmdWFKUrYGkBuAiUNheJVybv+cf8GNjoFTabcAoFONFo
- sDv+AmJ7C7hZF4QaAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIFSURBVDhPxZDdS1NhHID9ByLoJrrpIiGIMIy8MYVqrEhi
- FpWCSUmmrCFzjPzooo0ZtiAzyD4u1k1hMLEtLTUUtlKwhrD8yGmWpWPamDr6OuLa2Pa0991VtF37wu/m
- /J7nec85OTmbfspNJs1Zs1mbaWqsYbLthCdf/pTJdJks59y1QLYVwksHmpp0iWSSg7ehuB1Ud0HdAfpu
- 0Bh8VD8FowNuDoHdCz1TIHjhyUBJQ0NdLJFA15UCndA6CG0uePQODl0cpWMY7o2k5ZF5GF8CwQtPBo7p
- 9fpIPE7rwFucE6sMfYTBWfjwDfafeUVv6sZ+X1qeWIYvayB44cmASqczKLEYh1uqKW03Yh/zMR0E/3fY
- fdyJZyHKmP8Pk8sxPq/GCf5KInjhyUBxba3xRzTKjvNF7K3XUGKt486AA/fMLLvUz3g9F8KdmtGvYaaC
- CoGfUQQvPBkorKq6Eo5E2FZazvbTleRe0HLA0Ize9pjcoy8wPx/mwRsfnV4/vTMruBYUBC88GSioqGgM
- bWxQoLVRVP8EdXM3J6/3c8MxyZ4TbiwvP3HLtchDT4jO6d/0LEaRfMqTgX1lZVeD6+v/BDSWPlrs46mf
- 6KWxaw5LX4A29xr3PQq29zEELzwZ2KlSmVdS37SkKP9NYeV8xueCF54MbM3Pr9mSl2fNNEcuhci2E54M
- bPr5CzGs8HBMuX66AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAF0SURBVDhPY2DAAU5tYghHltq7jHEzLrUY4ruWMOgeXMm4
- CUQTrQmmcMschtgtsxh3vrub9h9Eg/gwOU9PTzUnJ6cCAwMDLbwGb5nPYLB0AsOh9VMYDNA1f/jw4b+q
- qmoNTgNOrYf4fVYrQyouzTIyMti9BrQ5dut8xh0gGskGPyD7AcxmmGacgbqomyEZXXNZWdl/oNhzRUVF
- woEaHh5+IDs7+395efl/EB0UFPTf2tr6v4mJyX8rK6v/bm5u/0NDQ/+npKT8z8/PP4ArLPxMTU1/vH37
- 9v+3b1//Hz165P/q1av/b9266//Jk1f+5+QUX8MXC2A/+/j4/MdtQMlNnDaDNKenp/9nZGT8GRcX97+k
- pOQ/yDCgi/57eXn9h8rtxmYA2OakpCRwgAENuIHHgKPoBoA1gzSANANxENCA83gMOI9sAFhzVFQUXDNU
- 8iYuA4DyKGHwABh16JpBZjzCY8AjZBdYwpyN5q9SIP8lDgySAwMASvXss8cC3BsAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHWSURBVDhPY2CAgv1JLBkHEpm7QTi57c0BmDjR9N5E5t6/
- N5f9/3Vl4f+4hmf/idYIs3l3ItOZX5cX/L+/se5/aPmd/zDXYKNBeuAWwGy+0uf6/8fFef8/n5j63zv3
- ItgluDBID9yA3QnM/SCbL3Y7/f9+bvb/u+uq/9snHv3/9dR0sGuQaRAbhEF64AaYhe85YBq++39ZWPzL
- L0DJdwf7/oP42PD9TfVgF+6KZZ6IEUYbI5lnfTo+5f+tVeX/dfw2YgQiSAzkwo9HJ/3fFsc8BcOAtZHM
- cz8cnvD/5a72/6ruazAMAImBvAdy4ZZo5ukYBqwKZ17w7kDv/2vLiv8ruazGMAAkBnLhm33d/0GuxTBg
- WSjjkjd7Ov8/2dzwX9l1HYYBILGbQO+BXAhyLYYBi4IZV7za2fb/ysI8oBe2YsUgFz7f3vI/1jnmHUiN
- mtsWRIqd78+49gVQ8gHQny+2Nf+/sigfhdb23f//+tIisAv3lRv8f7O74z9ID9wlE70Ydz3f2vT/3ppK
- rNgw+PR/kAsfbaj9v71Q+z9ILUgP3IA2Z8YpzQ6Mx3Bh88hrYFeBXDjFl+ktSB1ID9F5xjb+4f/XQBc8
- 29KIajOxJjglvzgAcx2yzQAGOo0BdV/WSAAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGdSURBVDhPY2AYMiCp9fWy6JZXkiQ5OLL64f/g4usOIE0g
- dmTVw0kEDXDPuKjumXPurFbOxT+uORcfeOVc/A/SBKIDCk69804/L43XEKuoA+vtEo6aghRZxRz475x8
- HOwCELtl3rULljEH8LvCIGibFzYbdPw2/b/68P0R46Ct7/S9N+N3BcSA/4za+Vs0tfM3g12g4rb6/4sP
- 365U9Z2+quK6Gr8rNLLXCWvmbvRPn3miUiNnQyrIACWXtf/vvPh84sLd98dUnde8U3XC4gr7+v0sytnr
- LO2qtmUtP3x/1vWHn46pZa3LBBmg7rnj//kHHw5eAuLS3kuX1Ty3o7pCPn25gmr6qoSKRafaj958s3Hr
- 2aer9l1+sVU5bVUuyAD9wBP/Vx17vGzCtltT9lx4scUw6MQ7/ZBj0gyioVN4JGMX+jtVbaneevrJ2lO3
- 3xzac+XVjm3nnm5etP/uCsmYRWUgAyyibv5fsvfp/i3nnm06eP3V7vrpT66YRd2YxCAUPjsIiOvw4CCQ
- AQ5Jz5Y5Jj//j4xBYgQT1uBXAAB4ctTtvOBX4gAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGcSURBVDhPY2AYdCC65ZVkUuvrZWQ7LLLq4aTI6of/QQYE
- F193gLGJMtA7/bx0QMGpd145F8EGgGjXnIsPtHIu/vHMOXfWPeOiOl6DLGMOTGqZd+2CVcwBsAHOyccd
- YGy7hKOmVlEH1uM0QN97s7Rx0NZ3Vx++P6LjtwlsADowCNrmhdMAFdfVk6r6Tl998eHbFRW31WADtPM3
- O2jnb9FkYPjPiNfpqk6bpVWd17y7cPf9sTsvPp9QclkLNkAjZ0Nq+swTlZq5G/01stcJ4zREzXP7pNLe
- S5cvPfhw8DwQq3vuABuglrUu8/rDT8eWH74/y65qW5Zy9jpL+/r9LCgG6YcckzYMOvFuz4UXWyZsuzVl
- 1bHHy/QDT4ANUE5blbvv8outW88+XXX05puNFYtOtaumr0qQT1+uADfELOrGpPrpT64cvP5q95ZzzzYt
- 2ft0v0XUTbABkjGLyhbtv7ti27mnm/dcebXj1O03h7aefrLWqWpLtWTsQn/R0Ck8DA5Jz5Y5Jj//j4xB
- YiADhMJnBwFxHR4cRFQCG9yKAPGK1O3Fnfm/AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE9jYKAG
- sJ/3cqb93BcxILOs5ryWAvJzHOa9XAYUOwPCYDZQDCSH1T7bmU/OQHGr49xn+9P3fHzcfOnn14l3/v0H
- YRAbJOa04Pl569lPfDEMsZz28MzMp///g+je67//t1349b/90u//XVf//O+4/Pt/y7lf/1vP//o/+d7f
- /24Ln16ymPoQ1RCT/ltnuq78BNr253/VoU//QeyQ1U/vgMRB2H/J0zvFe99/rz3y5f/E23/+20y7e95w
- 8nWEd/Q7r5xpO//1f9H2V/8n3P79H8Q36Lw8BeZUg64rUSCxrE0vvlfse/c/fuPzx/odV3LgXtFqOnum
- 78bP/02nPoExyDsgMc2ms+CABQGtpnNR9hOu3slc++R/0f43X7UazyyHG6BWfWymatXRM+gYJI4cYCD5
- uKX3/5cdePsfxIbLyefvV8jc9co+ePFtB7nifca4koZ88b4zwYvu/s/e+fI/iA1XJ523WdVv8d0Qt0UP
- crTqD1dIZm8yQjdEMmNrlG7j8TseSx7+D1nx4KtE1laEF0RS10oadp7ys1rxPNdl+aOJIsnrOkSS13jB
- DBFOXhMlkrL+jNvKp9+tVrz4b9Rz5rFQ8jpEIDKErmITTlrtbLHlQ67W6g8THNa+3KTZcGgXX8zyg7wx
- y89oNBy647Du5XetNR/+W2z++F8oec154aRlqKmSK3qxJG/C6njFTd8mSKz7tkVp07drBjt/fDTc+fO/
- 8ubv/4Fi/xU3ff/Pl7zmEmfkIszUCHIue9BcJbbwhRVcNceX8Sx4cZ5z4++PXJv+/OdZ8PIrd+3xx2zh
- i86zBc3GrhkeaP7zBZh9Zvgy+kzvYfKZfpDJd8YZRp8Zy5h8p+cw+M3BnpkoydEAA0J2Ek+355UAAAAA
- SUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE9jYKA2
- sJrzWsp+3ssch3kvl9nPfXEGhMFsoBhIDmQfUCwGyJ+JYbf17Ce+Tguen0/f8/Fx86WfXyfe+fcfhEFs
- kJjj3Gf7bWc+aQXiMyCMYoDF1Ie+bgufXpp87+//1vO//rec+/W/4/Lv/11X//xvv/T7f9uFX/97r//+
- bznt4ZmZT/+DabgBhpOvS9lMu3t+4u0//2uPfPlfvPf9d/8lT++Y9N86A8Ihq5/e6bry83/VoU9AF/35
- D2KDxOEG6HdcyYnf+Pxxxb53/7M2vfiu33nljEHXlSiYAoPOy1NAYhNu//5ftP3V/7bzX/+D+HADtBrP
- LC/a/+Zr5ton/+0nXL2j1XQOrlmz6WyMVtNZsLObTn0C474bP/+DxOAGqFYdPVN24O3/uKX3/4PYyIGj
- Vn1sJkgMHYPE4erki/edyd758n/worv/QWxcSUOueJ9x8OLbDpm7XtnL5+9XgKuTyNq6PGTFg68eSx7+
- 1208fkcyYyvcCzBFktmbjLTqD1e4LXqQ47f4boh03mZVuAFCyetyjHrOPLZa8eK/28qn30VS1p8RTl4D
- N0QkeY2XSPK6DpfljyZarXiea9h5yk8kda0k3ADhpGVSQslrzlts/vhfa82H/w7rXn7XaDh0hzdm+Rm+
- mOUHNRsO7XJY+3KT1uoPEyy2fMgVTlrtzBC6ig3Fq5yRi3z5ktdcUtz0/b/Eum//lTd//2+48+d/g50/
- Pipt+nYNKLZFcdO3CbwJq+O5ohcjbEc2hS1oti9b+KLz3LXHH/MsePmVa9Of/5wbf3/kWfDiPFfN8WVs
- 4Qsr2IPmKuHPf35zpJh8p+cw+sxYxuQ74wyTz/SDjD7Te5h9Zvgy+M8XoHbmZQAAKzx2EneDTb0AAAAA
- SUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAeJJREFUOE+lk71L
- W1EYxt+z378gJUsgX9MdwhV0STJkCEmXpIvELaNLBhE5oyI6F0RqKbRbW0q/hlIqSAahUISIXAoNDgaV
- DFlcOrSlnr6/k0YuRboYeHjP+3zdcy9EnHNyF0ir1ZJ2u31fETabTalWqxJFkRQKBUmn036yw6Pjw0+O
- B3uy2+1a0Gg0wv8VoM+85HwBv2w2aweDget0OrZSqYS33QAeHR9+cjcFeg5zuZyN49jp1WypVAqTr8AO
- j44P/78F7GE+n7fD4dDV63WrxpBvwGSHR5+FbwqWjZGeYkGBqE+2o9HIlctlm0qlHjDZ4dHx4SfnX+Gr
- Hs4Ul4pX06KwWCza8XjsarXap36/79jh0fHhJ5csCC6MWVQ8VLx8bcz+RiYTTyYTdxgE8Ynu8H/1RS0I
- kgXBqTGbk/n5o18rK1dua+vabW+7k17PHYh85+yhPDo+/FoQ+BscG7N0Pjc3wPQ2k/m2I3L0e33dfdSp
- 2GWyw6Pjw0/OFxwa8yQZ/rG66t6p+b3I0gf9akx2+GSJz1HwRmRfxWvEn2tr7rnOF9OQUMBkh0fHh5+c
- L3gksvclisbc4qmKz6ZmH5wVsMOj48NPzhfsidzT5bHis54xyW0F8Oj48JPzBXf5K5P9A150nLcmaqfe
- AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAiZJREFUOE+llF1I
- U3EYxt9LP1IitohdlHUTa90oY4z1cSGBZCzWh9hFCJGSHxHM6byYzi7KuooG5mIok1IYg1CW4XJnCDLJ
- PFSCFyoryjQvXBE1bfm1p/971s5VkOLFj5dzeJ73f34cziEAtBvoclubSoXbbRXc2AFWpXzB5cpSK54G
- 6W3AOdGrJXGassTqdDL1m+k0Sj1AWacI+DLzopjX+4H6ANAnA6FpgHOcVxZUtLfTpdZWOmu33/y9tYV7
- L3/BN55G4A3wdBIIvgX8r4DHMUD+DMQTAOc4zwtU7/MtLYGhiQnYOppR5/XAF36NXklG/6iM7pHMHJJn
- sZwEVjY2cKah4Ra778i7Z0TC15UUvq+t4XRNjV31fvdMg3+jVe+ztysYRTC+jkQqBXNVlUP1nhoowsyL
- g5gb/kv4EN5Lh/Fh9AjikSLMiWv2djyR0DO1iaXVVZRUVjqJPdjnWukJ3K8z42NUj4UxPb6MH8fPhTKs
- J6/g2+wpLMaOKd7+cBiLySSWhcLR8nIXsQf7nNTpcE6vh/tqCXpvGyH5LfiRaBRv+w4Sn6oxP2ZSvA02
- W2RvcfFdZp/RWE3swT6DD/IUQg/34LmnAMPeQkxHtFia0WFyQINod6Hqvd9spnyDgcQSIvZgn87GHJVH
- jhx4m3Mx2JWPWKgAfR156GrKVb1Fh7QmU2YBe7APe/2PrLfocI8OWCxE7JF12s7kvEacnmVXnzL/Bv4A
- nbSTNl0cgYcAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE+Nkl1I
- FFEYhs+VBXlhUHlRXWW5WyratuoqtpIb5R+4thrrrrna2mRulu6aroIWWlYomj+ZWllmaaWpoRWGBCVo
- 7oQ/QZmEGIlQN0WYiYJv55x0DKzo4pkzvOeb5/tm5hAAhFEVTCRsoXInnU4XTREWiWbZ7zWVakIY/OFF
- QQ0tEBnnfMhQQ3ba1NjYezDYPcuW9ulas0JQoSbiu6okdBwPQF/fCAYHRzE+Pslh9yxje28rTGC1FGJL
- oJelCcqCiPi61IhbCR6oO+iGm/Hb0XTYG3eTd6LR5Inrce64neiF4ZI4sFrzCRPR5eUtC0oCiDhUrEfv
- 6Ug8tgZzrmRqUZqll6jOT8S1swKs+oAP9GGBEilNcNGfiK8uxOJZ7n6J8lwjHRBY+AMsj8rJSZEERUoi
- 9hdq0X0qBHX2GFyyG5BpF/BkYAC6MgcOXXbAVO1AylUHap+OYn5hAeFWa6okKFAQkY3flb4bxZmx/+zc
- 2NOP7/Pz2GuxpEmCfG8isvFbU3yRJ4TxDsNtGzgj7a4Y6aDQleXlD7vxZXYWQWZzuiTI9SDioww16g0y
- ZCVqeIfzR5V40yXDxxdyfJ3QYOqlF8/tTT34NDMDX4PBJgmy5ERsS/XHDaMcNlMI76D3W48zCW7oqPTC
- j+lkjD4P4nltZyc+z83BU6vNlgQZ24j4gAoa6DlIj9/DO9wpXMNpLnJGb6sLWoqdea7SBH5bp1QWuKpU
- SZIgbQsVHPPjh8USp+YdJqenV8DyiMAdk5u8PQiVLB8kYfMvQbPZBycPKGAM/wsRCmhkrhNRW9eSQPeN
- y4IYFyK2W1T8L7TQj3df2CVx74gCDHasGayWQhjSK4SuIjX7nIj4P7DasNWEMH4Cj2pW/p0+C6YAAAAA
- SUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgdJREFUOE+lk71r
- WmEYxV9xEPwAXVxapQRFiqaEKwRvMgiBIPU6+PUPOJVSOgWElrZDoIRCh5bYqUsDafYEp5hEMHIFr6Dx
- Sm2oSa1c0+AuBZen77nEi5JsGQ7vwzm/c1BBRkTsPtLL8XicJRIJlkqlWDqd1t9sNityPbuROJuBRQfd
- uYFkMrnCwef8fYB3MpnQeDymWQ/MnQOSJK3m8/lPo9GIcrncaw69uLoaEoQbHjIwYOc+QSwWY1wv+/0+
- KUqdhkONisXiL03TCMLd6/X0DAxYdIyvIIoii0ajDzOZzLuzsxa1Wk26vLygweCPLtzwkIEBi44xEIlE
- otzYgHZ2vvU6HZX29r53Q6HQFwg3PGRTDh1jQBCEfKOhULl8QrWaTO12mxYXn2yZzWYG4YaHDAxYdIyB
- YDD4qlqtUqlUIryq+oOWloRNk8nEINzwZhl0jAG/37/u8/neQNvbhd/NZocODo6a4fDyWwg3PGRTDh1j
- wOv1Mo/H80gQwh9luUHHx6d0fq7R9fU/XbjhIQMDFh1jwO12M65NWW7R/v4hVSoNKhS+9uv1DkG44SED
- AxYdY8DlcjGup2tr67uK8pMCgcefnU7ne1lWeUEl3PCQgQGLztwAh5jdbo/bbLYth8OxgLfb/ct/0AHN
- emDA3jnAQWa1WnVZLBaJ68ONpKkP5tbAff7O/wFfbRPfU/HxPQAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAZxJREFUOE+llN0r
- Q3EYx58/ggu5EkkkbyX3Lv0DJG9pzfuS1z/ArYUQQs0sr81h2FghWV62NRcrk06Ezd4wbOxuni+zzuTi
- lItP31/PeT6/3/Orcw7FYjH6D1TSZy5l2pDFvbskB6kDoZ0nsCGZapkkHCrq2SljVFNmUeMLRc/kgF44
- cKmw2wRqvaHo6U0gYpYDeuHApYIuI6j3PH8ci76wSQ7ohQOX8ju3QMNt8N1y6XnbluK8exFOrh61+07/
- hOn8YXjT7lEDq/i0AAcu5akMoPHaHzlkwQAc1yH9ntM3vW51DwlnbvU39+q1OJbLoA4OXMrt2ACKK2/4
- wHETEo5cQR2Lo/rT+xEWRqSJNeCeRThwKadNAMoL9+sej6oVrO5xPhGM/cHXM4sruAwHLmW36EGzTXwy
- 8phTfOokZxKo/dSRFldADwcuZSpXKKtptZXvtcG7z0qY4TVALWnNE6zDgUsZiqVyZqB/zj7Pm2zGMfzK
- nzrSgF44cCm9TjuIVxnJ9Mgk4VBq1UxFSuX0GDKtRkNykDr/+pTxG/gEq8OGaNZeGVsAAAAASUVORK5C
- YII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAjVJREFUOE+lkdtL
- FGEYh78L/Q8Kom42ilLKjhAEdRWEIESgFyVSLBSd1NpqzCwiL7rwwCyt5JQH2MlZ29nddltP7aGw2nU3
- S2uxTIlN1h1bXLUTmbfb+xt2bOzgTRcP73zv+3veb5hh2y76GNjO+VV2VAVUdl4K7iLKUbUeqpbTPFX+
- bYGBgkVERSaTGUIljNmeYbkFOTTcd6AudKozNGlpffRBonOl4I+LytyCFz3MkCFy/ngDahSarK855dNC
- gHiSmP0R1IMeZsggu7hg64WHjMgraQxX0k2BifS8n/D9Az8yyMKBywpMvWzL+b7SvlepO/Hped/71Pfe
- 5UAGWThw2eZzPXsIztwzbhtVvnXpiSW+uMLjc1ZfbPqWd+gj7xqcqge18kgLHLhs09nuanxt1Fjiqwe8
- jH92kHTbEVUa5YGkRgM9q+gdll/h3UvU1HlGJRLv97+dEUm8aR9I8vYI8aua6RnwVzpjbXDgsrzyB2zj
- GY/RGZkUHr9JSyQ1Uchy7y+g7x6cEsT+CR4OXLbhtBsUFNYGq0JjMzZHNCnI0WTzEiJ0JpzPFYEy0v7r
- AQ4OXLb+pEujuMz89Gp4bNbWPZwSnVGlJUsrKnqYIUNOseaxdSecGrlrj8sHd3NdlxvcI5Zn79Kiqf2F
- ZDhmv1HTMSyjhxky5ORqnn4BozBbc7Qjf/WRu0biGsHjD6GihxkyuksZfuNiI7uArSqzqqw83F604lBb
- MyrOtEC9ZMkCuoH9Dz8BRapC1u0zrmQAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUpJREFUOE+lk8lO
- AkEURd8/qLG7ykSj4ohzYvwAdnyAmhiISgDbBmfdumHr0o2aGF1onOfxF/in5t6KTbDTIODi9qvqyjv1
- qt4tmdr7nobcnyiIZfVkrqVl9kha547FWjgVnTyXrtSl8D/leZ7I5O5XDoMiI8T5LzGpJmBi53MGykMO
- 1D6+/SGjm28ysvEqw2vPMpR/kgH3wezI3bvTV+WxqQBJviwkJyArDNDn3Elk5dYkE0JYECBMHtt6TwJg
- BSuoF8DyWcEiAHblERoB8Px2dP1lCQDbv4NGAbxAVpACwOYlNgNgB9Rg7jENgGoWwBaq/tX7LACqni6E
- egDJGnIA0H+1sRqAHtC92RsXAB3qA9/CNFYND3TAQPtQoXP5ImaMROtWPiCOCVCJs2o64NvBOqOYkoMA
- zuEDaZs/CVMcj+sQa3ED4Oc/KgFbmIwOgc7x+wAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK8gAA
- CvIBPVL3EQAAAUxJREFUOE+lk0lOw0AUROsOgLCdBYh5HiXEAdjlAICEEgFRCMYJM2yzYUmWbAAJwQLE
- PI9X4E6mqoWjYJmImEX5d7tVr//v/o3R7Y8xyvuOYCyrdeECdZP7qJ86gDVzhET6BM2ZM+i/5Ps+MLL1
- nufgU5HS/IdkqgoY3nwbpwqUSzUObbxiYO0Z/atP6F1+QE/hHl3erdlRu7dkz8tjkwFNgSyaU5QVBehw
- r9G+eGXMgggWBkDmwfWXNAFWOIO/ApS+MpglwK4soRaA6rf7Vh7nCLCDM6gVoANUBhkCbB1iHIBuwOnO
- 32UJcOICdIVO59JNjgCHZYEqVruFyB6gOUG5LGk3FkA7y9yWu/QUIzMIWliNFe4B7SrRXGIDFamdpvnT
- CdNIat3KB6SxAE7q+DeV9Ha4rghTcxigudJumD6MUpKPa49rSQPQ5z/6ApWFkK7wYogxAAAAAElFTkSu
- QmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAdFJREFUOE9jYCAB
- PGdgEMOrPLVpq25KyxZ/bIqeMjDYPGRkXHeekbEdpyEpTVu3pDRtCUNXEBAQoObg4JD/r7T0/yN395dr
- GBhcMAxJadqWltq8dWboqlXMyJIwzX///v2/Zs2aq6sYGI5gdUFK89ZTQNuNkSX3LWWw3zSLccv1Y0H/
- 96wy/sDJydmB0/mpTdseJNfvEIIpgGn++aL6/5UD/q9a8xkO4w/A5m3TgWEwIzMzUxBDcx7b+ezs7OC8
- vDyvtLQ0LnyB2NhY4/9mYb/UW5DNZ/cE/WjIk/wL8d7WVcAw2prSvO05MLxCsBqysJxBbm4VT+27u2n/
- tyw0e9+Sx3Glvr6eBVlxSttWNaBBq9PqN4mgGPKfgYGxP5ux6f+7M/+LwhgXZPgzVOFyKjC8VqQ0bddG
- kW9LYex5dnXZ/5wgxuUZAQye+AIMmOCWJLdu00NX8z/dn3FVii8DqsloqlJbtksCw2QjhheAznoBDKC2
- tJatJrhsB2riAqprBaprwkyJ9dtkgKFbDsTbgU68CAz1BWnN2yqAfk0AsuOAthYB5dYAA3B+Vv0WCZxe
- BIY6U0b9TjGgU72BthUCNbcDNXamNG+vSWnZZkFC5iVOKQCnrtq9RcibTAAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbxJREFUOE+lktkr
- RGEYxt8/ghKJcOlCmTJlq2G4cOXOduyGQogYyxiU3Ll0Rcl+mCTLxDlxM5ZIspQtF0qWaUaWEeNqvM/h
- 1LEkk4tf33ue93mf7zvfOeTz+eg/kM4sA2Nsk5zjD5jBxhTXIoPiW8/rnvPBu/UX4MWMEpDYJoPKm3vv
- prR7bUvvlKwq0IBWgwcaZpQAQ7sEGlyP3p0Uq9Ro7JAIoL6+e9kAX3V4MaMEGK0SpXVIAtPG6PGsnury
- 9nkNYDdoH179h1fQBlA678oNSrbwnTQrFJ7dPK0cXjzaUUNDDx7V+2OArom/yju5jmPXqOPINYJa1X8N
- SOJjagIEx5F7DLAmqDo8n04QXjpB0dXTFG+2k75Z0lLGwyJgvUzbS+V7SjAvKD8gISDCNKmsMXWzzBwl
- ti6BWn4FG0ANDT14okwihRQMfw+ILJ+iqAob6epnww2WxdbVY/fMGoMaGnrwYPi3gEw2VnVN7vfI+05R
- PnCKqKExmd8CwkrGU/n43VhDi0bxKjWnV56N3fP7lfUT9zzgehkaevB8OkFw/lAvX8Y2VqbRH5RLDMwe
- yAjI6u/DGpQ3SP6AgDdx0wjL45XA0gAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAetJREFUOE+lkz1I
- AmEYx19SUBc/bhAJWxMaHBR0j0AaxFoiuMLWwmhpjYYIKmhpaIiKDLIPogxs6esqJCI89SioQBy6IGtw
- KO5wOZ6eR+zAshocfvD6Ps//d89798oAgDVDNbzOGNtAtpBtxlp3GIshCSRdg9YxqlEP9VKGst8F4T2L
- RcgHg/LbwIDyMTKivQ8Pa688r+QCAZlqKAj/Jggf2O1iiefVl2gUZJ6vg/ae+/vVpM0moiBcN0GcRjOb
- hae+PvWxtxfuI5GGPPT0QCESUTdNJoEy+hFW8XxXPp8sdXfDTWfnn+RCITjt6JApowuWGNu8DYUUIRiE
- L458Pkh6PJBwu2HN6YRljqtC65THo1BGFyzi28ana8d+P1QqFSgWi5DNZkGSJCgUClAqlaBcLleJOxyw
- 29amUUYXLOAPsatLO2xvh3w+D5lMpmGYBDso2He5NMrognkc59zrVVI44hY2/EWKBBynUEYXzNLFcTqf
- LvB8Z9jwH3GLRaaMLpjGTzJnMAgXLpd6jVNco+Q3Tmw2dbalRaCMLpjCazmJl2PGaBTTHKdKKJFQ8p1L
- DM8YDCL1UqZOMIEbY1gYR/uK2SynrVblzuHQCFrTHtWoh3obCkaxMISjDeL5kASSrkHrGNWo54egmb/z
- Jx8zDDjpQm/GAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAmNJREFUOE9j+P//
- PwMlGKyZWWczA7PuVgZm/R1AvFOC2WBXChDPAuJtUAxip4DlQGpAaoF6QHrRDfDgtdi72THj5q307rcf
- i6d9+VM09cuftM63H+3TbtwCyQEN8MBlgIeo3YFD6V1vP6e2v/4fUHQDBae2v/qf1Pbqs4jt/kNAAzzQ
- XLBJktd0x5aUtpefI6sf/PfKuQR0HSoo6bv1HyQXVff4M4/J9i3MOpskEV7QWp9qk3jxdljFnf9+Bdf+
- e2Zf/D9x0VUw3nboGdikOWsfgOWCS2/9Nwo/eZsZqAduAJP66rlhlXc/uWee/w/DTimn/ptHHvhf2nHo
- /5kzZ/6Xd+75r+K29r+614b/ZpEHP4H0IAxQXb4zsvruH5e0M/8dkk7+NwzZ+1/de+v/qOK9/8+fv/h/
- 6brj/9U8N/1X89oCxkD5P0xAPQgDlBfvCi2/+dc6/sR/naAD/7UC9v3X8Nv5//bt22Cs6bcLLAbD+qGH
- /jIB9SAMUJg/zyn1wmeDyNP/9SMQWNN/z38QRhYDsbUCjn5mAupBGCA3O0PVfe9di+Sb/00TboCxQeTZ
- /+/evQNjEBsmDqKlbHfcYwLqQRggPV2SQ3HODovEW1+sMp79t0p/+t8k/jrcABAbJAbChtE3vrApzNnB
- BNSDMEBqKgOTxCQvbpW5x82SHn6xz//43w6IDaPOgzGIDcImCQ++cCnPPQ5SywTUg2qA+AQGRv4mbzbR
- zj0KtjsemiU+/uJQ8PUvCIPYIDGQHEgNE1AtdgP4GhgY2EqlGFiLsoF4KRAfhmIQOxskxwhUg2EAJdkZ
- AOypQZHMHzM4AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFrSURBVDhPrZMxa8JAGIYVf4ybSwRBB0E36VIh/0CjaFBQ
- HAKiFJz6RxRsiwaktgGpFrEuTm4OXQpSEFrBWkHw7b0By1UkdTDwEO67556bzuU6x+d2u68EN2q1qp0C
- XZ75vVss7mq1Gvjt/oEOXZ6RA61KpYLtbofNdusIHboi0JIDZrlcxpc4/LleO0KHrgiYcqBjGAY+NhvM
- l0tH6NAVgY4c6JZKJbyL218XC0fo0BWBrhywCoUCxtMp3lYrR+jQFQFLDvRyuRySyeRJ0BWBnhzoZ7NZ
- +P1+KIpyFO7tKRaLDPTlwDCVSiEQCGA0esFg8PwHzrinqiqCwSDy+TwDQzkwTiQSCIVCsKwneL1eG9O8
- t+GMewxEIhHous7AWA5MNE1DOBxGu/1o/0mj0bbZzxiIxWLIZDIMTORndCEWM5/P991sPiAajdrU6x2b
- /YyBeDyOdDoN+ofv8FIM5h6P5/oY3Dvg9hwP2fUD8MfQYXCln30AAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFeSURBVDhPjZC9S0JhFIfP5NzeGA25RFRQQzVGa+o/0FBB
- EC0uLQ4FIVFIH6ANRoYK4v/hcsBoSrtIhJWJYvnJ9et0f4EtR1564YGXcx6ee3mJxpyAz+3yeDybXq93
- B+CO2Tj3b3a1RpHLVWJwPEcPUf/eez5vCcAds9EerophmbvekvTuomQyj5LNPkmhUPwFd8ywgwNXBc5X
- iMU5sdi9BIOnEg7fSDyelFQqLdHbOwmFLiSRSEIRuCpwtkw8dJb94VCeLWss2MGBqwLBJeKeI9j9vhE4
- cFXgZIHYHgyk1e0agQNXBY7midu9nnx3OkbgwFWBwCxxw/l6tdk0AgeuChy6ib9sW0r1uhE4cFXAP0Nc
- dX6/WKsZgQNXBQ6micvttrxUKkbgwFWB/Snij1ZLrHLZCBy4KrA9SfzmPGCuVDICB64K+CaIP50Hem00
- jMCBqwIbLoqsu4j/A9xR4AdKLDJN/KRkLAAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAI3SURBVDhPjZJvSBphHMeP9XJ7Iwh764v14no1fdHCAtsS
- bzlvLLmJjoGDmH+QIYOUuE5OpkMJfOOovXL0IodvwnqxsCQDWW3CXm6DCb1YVMRgbfQHVlbf3e+GcFLK
- nuPDPXCf7/fu4X4Mo1muWIx/KMu+yxBk+YbWvXQvTEz4fzUa2D48xObBAb7v76ssVKugZ05J6u5Y8kAU
- A7+Pj7G5t4dvu7v4srODz9vbyC8ughY958JhQ9sSPhoNHpyc4IfyVm3Jq9lZNOnmOKltgWNsLHSoFPw8
- OrpQQl9CxyGnpUCW5StOp5MXBMHf1dWViUQi6AQ55FKGsozD4dCLoijvKmcOBAJIJBKIxWIXkCQJ8Xhc
- dba2tjA+Pi5TlrHb7Ww2m52p1+twu92IRqPw+Xzwer0YGXFiaMiK/v4B9PbewvCwXXWWllaRTCZnKMtw
- HDc4Nze3WqvVYLValbAfNtswBgYGlaClBav1ruosLJSRyUytUpaxWCzu9fX1jUqlAqPRCJfrsSLxl2Kz
- 3Vcdn3IVCu82KMuYzeZnpVIJ+XweBoMBgvAEPP+oLeTkcjkUi0VQljGZTJFq9T3m50sIhcKYnJxGOj2F
- VGpaw2tl/49g8DnK5U8qlGVYlhVXVtawvLwGj8fzXzQLKMvo9fpRnU73klD+cZpG9t408OYD8PbjV9yO
- j+KmP4U7kQL+nJ6CnKZP2Zahut7X90Ides06Oz8H0Tg7Q0O5k9N2lK/19Dy9yrKpTpCjLfgLj/3c8nL7
- lrMAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAG8SURBVDhPrVM9SEJRFL6GgoGICoqEruqswxsFB8Uh1EUS
- C6HZoaG1uYSGlpawv0EzKWwwiIIukYPE03wkVCAOvSBrcPPhIqdzxB4YZosPPt7hfj/vnPvuZWzWT56x
- hVPG0kXG8ojKCHlaI27q9wqMLZ7Pz3NREOSvRKLH/f4B4RNr0euViSPNxJAcEiWTqdZJJpWPVArkZHIM
- tPa+tKSUDIYaacdCsthaQa/nzXhceY3F4DkSmYiXaBSawaCS0+k4edSQA5zvHluUwmF4CASm4jEUgmuP
- RyaPGrDH2MmT39/jggA/uPZ64cLthrzDAUc2G2QtliGoLrtcPfKoAbu427RZNz4f9Pt9aLfbUK/XQZIk
- aLVa0Ol0oNvtDnFsNsOZ0zkgjxqwMwq4dLmg0WiAKIoTzRRQxICS3T4gjxqwje1wbKuMLRZQMA1l5HMG
- Q488asAWHRyr9e0O57tFwX841Gpl8qgBGfwlGY2GXxmNShW7qGLIXyANackzdhY28HBszs3VSCBhiIQh
- v0EcaUg78TSuIbGO6fvYIsc5udk8GAJrWiOONFPvwyq2tozzreBlwneFMKrTxM368rJvjEdIo/39bLwA
- AAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGbSURBVDhPrZGxSwJhGMbfb/c/uEUEEadzEiQQBBeRBqUl
- bPIPEKdDvuXACJxrMJKgLWqQWiISwkEIQriIW5KWg+KIW1oKCvLrfb40VFQMOnh5732e3/vc93FE//EU
- i8X1QqFgrpIFDvwUWy6XJSqfzy8NgT9mpwKi0ah0HEeVSiWZyWTmhkCHDw787GlNiK7rKj6iTCQSUyGY
- ocMfLc/9iBmLxeRgMFC5XE4yqCF0zNDhs7T0mjrE8zyVTqelYRgb6JhXWdbXWuMvxONx6fu+ymazV91u
- V2GGvvAvvRCFnok2n4TY5TptC9HZDofdIAhULxRy73iGDh8c+N8wl4dHIXaCVKr/Xqm82rY9VI2Guq9W
- 1TXRG95R0OGDA489HeIQbXnJpAPoLBJ52CPqf9Xr6oL7JVETHTN0+ODAY08H9IQ4nFz+sCx1zjCXBtAx
- Q58MwZ4OaBN1bMsawvys1dQx95Nx+uiimKHDBwcee9reJzq4NU0fpzhik+vnaDMPdPjgwGNPI00ig6vF
- wk1rwfI4Cz448Nhb+Fv/YnwDm33pU4rOXh0AAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAH1SURBVDhPrdFPSJNxHMfx56iWRqCXHcq6xKrLRlRUXuwg
- WcKKGB3yECnliGCu7aA4OpR1igbmYiiTUhiDUJbhchuCTDJHJXhQWdIfzYMzoqYt/+3d851tbhC0wB98
- +PI8fPj+ePFTlO08xpaWmot2+7V8I/2c+w1NTddRTzKPSE/6OQvOWa2m9WSSSgdUtcF51+a8oM6rPWDy
- QHcEfBMgPennLDhjNt/4tbHBvZc/cY0k8byBp2PgfQvuV/A4DJHPEI2B9KSvZLtrbDZP/+gohlYrDU4H
- Lv9ruoIReoYidAxuzv7IFAtxWFpb47TJdFP5X3fnYJDFpQTfVlY4VV9vVtLud89K+XvKMv/F3ewN4Y2u
- EkskOFZba1HS7vHeciZf7GF64E/8e3kf3MfM0H6igXKm1W9xW54E6RxfZ355GZ3RaFPEIZ4rlSe533Cc
- DyEts8Navowc5sdsFavxS3ydqmAufDDldvv9zMXjLKiEA9XVzYo4Uh6NhrNaLfbLerpuHyHoPsH3WKP6
- 2neIfazj0/DRlPuQwRDYpdPdlezW6+sUcYin70FRKr6HO3nuKGbAWcJEoIz5SQ1jvaWEOkq23NmPLw7x
- tDUWZPLIUoDTWkhf+w7CvmK6W4tov1W45c5eIA7xiOtfybizF4gjbcpnptzbeX4DJ7oc/jCY5XUAAAAA
- SUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAJrSURBVDhPjZJdSJNRGMfP1W7yQujDiy5T0mGWbanL1MhF
- WQrqprE5c3PpMpfoctkSXaFhgmapZWrZl6WVpgutMCQoQXNv+BGUSYjREOqmCDNR2L89J3xvXosO/HgP
- //Pwew7nfRhbZTnT5DKNRpOq1WotBO0pW61WzBrjWHNDLBOIynA23mbPn5ue/giC9pStnFOtREaHHy5n
- w3V8J4aHJzE2NoWZGQ+H9pTR2fsGI6hWIrgQw4S3dQbcyQpF66FA3MqUo8O8DfdztqPduAVt+s24awrD
- RK0eVCsR1KqYMF6jw9CZJDw9sZtz1Z6CuhKdSJPThOvnLLDpIj9py8stqWVlSaKoOooJb6rT8aJ0v0h9
- qQG0vKtAebLDkScKqpRMGKlMwcDJeLQ60nDJkQG7w4Jno6PQXnTj8BU3jE1u5F1zo+X5FJa9XiTYbPmi
- oELBBLp+f1Esauzp/+zcPjiCn8vL2Gu1FogC51Ym0PW78yJQbjnAO0z0bOBM9gZg0uXD96W8/vEAvi0u
- YpfZXCQKTsuZ8MQWhxsZwSgxqXmH80d34F1/MD6/CsH3WTXmXofx3NExiC8LC4jQ64tFgT2ECT35Ubhp
- CEGxMZ530EWux9msQLgaw/BrPgdTL2N43tLXh69LSwhNTj4lCgqDmPDIJ7jtm4OizD28w73KNZzOKj8M
- dfujq8aP5+Hq6B9rlcqKAJUqWxQUbPIJjkXyYbHq43gHz/y8BMoTo+UeySDlbvwj6DwSjkKNAoaDfyFR
- AXXQulmJIM2fCb1WFf8LXb7He2hRijzIVYCgsSaoViJIkLHmfTIm/A9UuyL4DdOT5vYvoF58AAAAAElF
- TkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAKVSURBVDhPY2CgBrCf93Km/dwXMSCzrOa8lgLycxzmvVxm
- N/fFGRAGsUFiIDms9tnOeHwGjGc+aXWc+3R/+q6Pj5svffo68c6//yAMYoPEnBY8P289+4kvhiGW0x6e
- mfn0/38Q3Xv99/+2C7/+t1/6/b/r6p//HZd//2859+t/6/lf/yff+/vfbeHTSxZTH6IaYtJ380zXlZ9A
- 2/78rzr06T+IHbz66R2QOAj7LH56J3/9+++1R778n3j7z3+baXfOG06+jvCOfueVM23nv/4v2v7q/4Tb
- v/+D+Aadl6bAnGrQdSUKJJa1/sX3in3v/sdvfP5Yv+NKDtwrWk1nz/Td+Pm/6dQnMAZ5BySm2XQWHLAg
- oNV0Lsq27+qdzLVP/hftf/NVq+HMcrgBatXHZqpWHT2DjkHiyAEGko9bev9/2YG3/0FsuJx8/n6FzF2v
- 7IMX33aQK95njCtpyBfvOxO86O7/7J0v/4PYcHXSeZtV/RbfDXFb9CBHq/5whWT2JiN0QyQztkbp1h+/
- 47Hk4f+QpTe+SmRuRXhBJHWtpGHnKT+rFc9zXZY/miiSvK5DJHmNF8wQ4eQ1USIp68+4rXz63WrFi/9G
- PWceCyWvQwQiQ+gqNuGk1c4WWz7kaq3+MMFh7ctNmvWHdvHFLDvIE7P8jEb9wTsO615+11rz4b/F5o//
- hZLWnBdOWoaaKrmiF0vyJqyOV9z0bYLEum9blDZ+vaa78+tHw50//ytv/v4fKPZfcdP3/3zJay5xRi7C
- TI0g57IHzVViC19YwVVzfBkPMNlyrv36kWvTn/88C15+5a46/JgtfNF5tqDZ2DXDA81/vgCzzwxfRp/p
- PUw+0w4y+c44w+g9YxmT7/QcBr852DMTJTkaAA9fdaKg/q9TAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAKUSURBVDhPY2CgNrCa81rKft7LHId5L5fZzX1xBoRBbJAY
- SA5kn/3cFzFA/kwMu61nP/F1WvD8fPquj4+bL336OvHOv/8gDGKDxBznPt1vO/NJq+2Mx2dAGMUAi6kP
- fd0WPr00+d7f/63nf/1vOffrf8fl3/+7rv75337p9/+2C7/+917//d9y2sMzM5/+B9NwAwwnX5eymXbn
- /MTbf/7XHvnyP3/9++8+i5/eMem7eQaEg1c/vdN15ef/qkOfgC768x/EBonDDdDvuJITv/H544p97/5n
- rX/xXb/zyhmDritRMAUGnZemgMQm3P79v2j7q/9t57/+B/HhBmg1nFletP/N18y1T/7b9l29o9V0Dq5Z
- s+lsjFbTWbCzm059AuO+Gz//g8TgBqhWHT1TduDt/7il9/+D2MiBo1Z9bCZIDB2DxOHq5Iv3ncne+fJ/
- 8KK7/0FsXElDrnifcfDi2w6Zu17Zy+fvV4Crk8jcujxk6Y2vHkse/tetP35HMmMr3AswRZLZm4y06g9X
- uC16kOO3+G6IdN5mVbgBQsnrcox6zjy2WvHiv9vKp99FUtafEU5eAzdEJHmNl0jyug6X5Y8mWq14nmvY
- ecpPJHWtJNwA4aRlUkJJa85bbP74X2vNh/8O615+16g/eIcnZvkZvphlBzXrD+1yWPtyk9bqDxMstnzI
- FU5a7cwQuooNxauckYt8+ZLXXFLc9P2/xLpv/5U3f/9vuPPnf92dXz8qbfx6DSi2RXHTtwm8CavjuaIX
- I2xHNoUtaLYvW/ii89xVhx/zLHj5lWvTn/+ca79+5AEmb66a48vYwhdWsAfNVcKf//zmSDH5Ts9h9J6x
- jMl3xhkmn2kHGX2m9zD7zPBl8J8vQO3MywAAM0F1onzOjz8AAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHMSURBVDhPtZO/SwJxGMabFHQQB6cCIzRClFAIvBpEKMEU
- FPEPcIuIpuCgqAYhJAgsJGhoMaI9cMpKMLnAE/xxkkVWJqeJuwQub/dIiqKDBAkP34fn+bzvHXfnxMR/
- /fx+PyNp7VfMWNfxeDyLXq933eVyTeJst9vUarWoPwMzcpnT6VxiWfa42WxSIBDYcbvdG/V6jSB4ZOjA
- gB1a4nA4NiuVCvF8mmo1kWKx2KsoigTBl8vlTgcG7NACm8025fP59vP5HOVyWXp/f6Nq9bMjeGTowIAd
- WGC1Wm0Mw2xB0eh5uVgU6OrqomQ0Gk8heGTouhxmekvMZjObyfCUSNzT4yNHhUKBTCZTqAvAI0MHBixm
- egsMBsN2KpWieDxOOAXhiebnzcEuAI+sn8FMb4FOp1vR6/W7UCQS+chmi3R9fZu1WBb2IHhk6LocZgae
- g1arnZZu64jjMnR390AvLyI1Gt8dwSNDBwbs0FvQaDRBjstJV76hZDJD4fBZJZ0uEgSPDB0YsEML1Gq1
- 025fvuT5Z5qdnTtRqVQHHCdIAwLBI0MHBuzIr1GhUKwqlcqQNDCDs1T6kh5olfozMGP9L2QymUsulx9C
- 8GMN/QX6AQLKSmIufl07AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAI3SURBVDhPY2CgOtDaIsFksCuF2WDnLEb9XdtAGMQGiTEA
- 5fDax6y3w4PbfO9mx4ybt1I63n4srr/ypwiIQWz75Bu3QHIgNVgNYdbb4iFqs+9QfNfbz6ntr/8HFN1A
- wantr/7Ht736LARUA1KLaojGWklukx1b4tvuf46sfvDfK+fSf3RQ0nfrP0guquT+Z26TrVsYgHrghjBp
- rUu1ib9wO6zizn+/gmv/PbMv/p+46CoYbzv0DGzWnLUPwHLBpbf+G4WfvA3SAzeAUXXV3LDKu5/cM8//
- h2GnlFP/zSMP/C/tOPT/zJkz/8s79/xXcVv7X91rw3/DiF2fQHqQDFi6M7L6yh+XtDP/HZJO/jcM2ftf
- 3Xvr/6jivf/Pn7/4f+m64//VPDf9V/PaAsZaWnv/MKou3YkwQHnxLnv7/X+t40/81wk68F8rYN9/Db+d
- /2/fvg3Gmn67wGIwrA9UywjUgzBAYf48p/iTnw0iT//Xj0BgTf89/0EYWQzElvc6+pkRqAcRiLKzMhTd
- 9961SL753zThBhgbRJ79/+7dOzAGsWHiIFrKcus9JqAeRFTKzZDkUJyzwyLx1herjGf/rdKf/jeJvw43
- AMQGiYGwYeCNL6xyc3YwAPWgpAVmiQle3Epzj5sl3flin//xvx0QG0adB2MQG4RNEu584QKqAanFnqR5
- G71ZRdr3yNpue2iWCDQIGFggDGKDxEByDEA1+PMfZ6kUA0tRNhAvZWAtOAzGIDZIDCRHbQAAW754iHPl
- f1UAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAHNJREFUOE9jYMAN
- HIBSMMwGZMMwHi2oUgNjALJTDwAdBMPJQDYM4/XCwBtgB3QfDFcD2TC8GsiGYbxeGHgDDIHug2FxIBuG
- 7wHZMIycPjC8MzAG+AHdAcNxQDYMI6eJyUBxGJ4DZMOwOsgPA28A0dkTm0IAEKI3YFhMEd0AAAAASUVO
- RK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFdSURBVDhPldO9K8VRHMdxSSklJRYGxIDyOCBE8pA85Slk
- 8JAFkyIlg2KiFKFsBovBKGUwGmTHopRSovAfeL91SLqXe0+9+p1fv+/9nPP7nt9NSIg+0nhUFuT+URf1
- UQ5PutGLciTGE5JMcTPWsYsRpMcTkEXxNM5wiWUUxxrgViuxhms84RA9SIklJIOiFmzgCs+4wBzsy7+j
- iIo2LOAAN3jEPuyL/Yk6UnnSgFZ4AvbhFK84D/f2J+rID6u4UkEI2+H6gHtsoQ5JkRJskD+cwAzswzD2
- YDPfw24muWZGCrBBnRhDP2pDyDzXE7zAfqyi5HeAq7u1PoyiPgQY0oWfJ3LE/QDs1/dw9aGg6le6hb7K
- Md7g0S6hEJ+9yINbX4FfXDv8bP2g5NwVPdI73Ia5Oy39CmhiMoVxVEcI8PVmsYltLMJX+wyogAE2zz+N
- xdlwe3Jeg8FQ4ylY24HGDwiaO4lDc1lzAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFdSURBVDhPldO9K8VRHMdxSSklJRYGxIDyOCBE8pA85Slk
- 8JAFkyIlg2KiFKFsBovBKGUwGmTHopRSovAfeL91SLqXe0+9+p1fv+/9nPP7nt9NSIg+0nhUFuT+URf1
- UQ5PutGLciTGE5JMcTPWsYsRpMcTkEXxNM5wiWUUxxrgViuxhms84RA9SIklJIOiFmzgCs+4wBzsy7+j
- iIo2LOAAN3jEPuyL/Yk6UnnSgFZ4AvbhFK84D/f2J+rID6u4UkEI2+H6gHtsoQ5JkRJskD+cwAzswzD2
- YDPfw24muWZGCrBBnRhDP2pDyDzXE7zAfqyi5HeAq7u1PoyiPgQY0oWfJ3LE/QDs1/dw9aGg6le6hb7K
- Md7g0S6hEJ+9yINbX4FfXDv8bP2g5NwVPdI73Ia5Oy39CmhiMoVxVEcI8PVmsYltLMJX+wyogAE2zz+N
- xdlwe3Jeg8FQ4ylY24HGDwiaO4lDc1lzAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
- CvYBwq9wAwAAAPpJREFUOE9jYKAGcEv37EfCx6FsMSxiRkCxMqh4Hdxuz2zfj9lTS78BJe5DJc8B6QAg
- Pp41peQ3EP9HMuwlSBzEp4bjIWYgmR4HMx1JTA9NzAvIb0dxAZADcjIsHOBOBDkfKK4BNQAkDlIDcj6Y
- jdUL//8z/MeFcfoZanI4yGnnrjP8n76S4f+uYwz/8zogbBD+/JUBOSBBLgmAG4jkheMHzzD8Dy2BaIZh
- EB9kICwsoF47TnUvgAMFaEs1UoCCnYrGB4mBvKuJzQugaAQpgIV4P9S54BhCYuOOBbJSF5oTzdH4LDi8
- gUgHWBIScqICsdETGlieLNeiawIAaZgQICy+wd4AAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
- CvYBwq9wAwAAAnZJREFUOE9dlF1PE0EUhpu4sztDqyTG6EVp96vGFgmiwRCVeCHRiEEuUEgRRGxREEwA
- ETQiVEQTAZGoMXpP4l/xt/AvfM7sIuDFm5mer3nPOe82oyvZZhCDC6ATXNHlbCvIcz97yNaGrQhi0GbK
- uaCpfPxEhoDzKjSzKjbbbmw+W4RmwfX1A8557N9VqemnisxrN9B1bC/BCv6HFAoyHq/ifEfQror1Lwp8
- cSPzhuAp7O+PlcxvsMt9jcRF/BtgiwI1CkQwyAWOr4ecUD9Tga7heAxG3aIedH0z7ISm7kRmGt84tiHP
- NyPiVy3ebdifyVClwmtPbPXQvOL1LfDJsgrNCzcwE9hX7asR/kDP81sY1mR2UqCdH88xLhOwCn6Ar/S+
- 4cRNqzCbxrfuRlrsH7h/5Nx2Qz1lC5hytqAKXi/0BlRB91PwKuhwK9l2pzXX6lVyobAE15K2pEVvnBZ6
- KHAyacHXj6A6C5PRiwOd1VuTvTtgDPxJ7zv57mIb/gnbWmQaKjCjFCgkLTBAu5pAP7107/IMSXtpshQQ
- 7HUOdi0QNyOtsbFvDHeOAufSFnSf0FN57wYFS7KeVFw+pwhKzg6Y3peXHdlOi+5BTKcOthDoSWZwl6A6
- Q2rIUKG6xEuLcoIVsA6WrUZavJv7M0i2EJg5kodJnGNlmxRZk16d2K60IclOyezQwiYxDYkVuR9uYQgG
- d2QTOEUsIwrKiKxfFXUf9ypsalZQvh6X2KNCsvI18ykbEQtU+V3UVUmw30eiFZG0tDF2VEgiotC8TQP2
- TxGOKHTJfh+SnChy7V8BJnkatNvPtpztAtfT094RWrcV1//+5C+g+S/3C5lq0y853QAAAABJRU5ErkJg
- gg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
- CvYBwq9wAwAAAONJREFUOE9jYKAGiIyM7EfCx6FsMSxiRkCxMqh4Hdzu2NjYjy0tLd+AEvehkueAdAAQ
- H29ubv4NxP+RDHsJEgfxqeF4iBlIpsfBTEcS00MT8wLy21FcAOSAnAwLB7gTQc4HimtADQCJg9SAnA9m
- U90L4SCnuaV7OgNxPxDHAfFxKBvEF0CLrQC4C5C8ANIQCsQvoZpBfBAG8eHhA/Xacap7ARwoQNdUozsV
- jQ8KSJB3NbF5AeRMkAJYiPdDnQuOISQ2bWIBlg7M0ZzMAuSDkjVyfgGzsXkBxflIXkFPaKgGUBIdALJS
- 5si8Z54VAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAfxJREFUOE9j+P//
- P4Ofnx8GDgwMZAgJCREMDQ11AOIoIE6F0g4gcZA8SB8DHgMU4xKSk6Ys3th99Oqz9fdffTl+8/HbrYvW
- bOsDiQMNUIQb4OPjw4CMfX19BaNi41PWHby68MiN14cevfl29snbb+dAGMTeceLmkujYhBSQOrALPD09
- 0bHzxPlr+3ZfenHg6uOPJ2CaYfS1J59OTF+yYSJQnzPYAGdnZ3ScsO30gzUgA3Dhg5efbALqSwAbYGdn
- h47z9115uQ+mGd0FIP6J22+PAvXlgw2wsLBAx6l7zj/cCDIAm2aQ2Kkbz3cA9aWCDTA0NETHnpPnrpi+
- /+qrw/dffj2NbggwIM/NW7Z2LlCfJ9gABwcHsBdsbW0ZbGxsGMzNzVVc3Nyrj1y8t+/ms88oBjx7//3i
- 5Zv3d1jb2JaoqamJYBhgbW0tDzSkeO3a9f81NLXbJ06fu/Txi3dH3n7+ee3pq/dH5y1YvFJDQ7NWUFBQ
- S05ODpKQYC4AatRyc3Ov2bFjz39RUbFmFhYWLSAOA+JKIG6H0iC+GB8fHwOKAUDnWwQGBrcdOXLmv6Ki
- Ug9QkSoQM+DCKAYA/e+dkJAy4eLFu//19AymATUZ49MMkkMxABhoJbduvfpvb+88j5WV1YWQZgwD9PT0
- tERERFqAmmOI0YxhACggycUArdOzkqbxIJ4AAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAEUSURBVDhPY2CgBnBN9+yHYbc0z+NgdoarGLqYe6q7EVCs
- DCTulu5RB7fbM8X3Y/LU0m/OyZ73wZKpnueABgWADIufEv87a0rJf7hhSZ4vYZZQw/EQM+Cmp3vGwb0A
- 9ZZHpocesphLuocXUH07SA/cBSAnY3MiyPluaW4aIAPcgE4Hew+JjdUL//8z/MeFcfoZanI4yGnnrjP8
- n76S4f+uYwz/8zogbBD+/JUBHpBQ9QEYXgA57+AZhv+hJRDNMAzigwyEhQXEa57HqesFWKgCE0g1WsIK
- QObDvOuS6aWJ6QVgNIIVQEMcxAY5F2YAjA2Tp35CAtuU6mWO7GT7ensWULJG9wbehIScqGB5A10MxQBK
- /AIAoo4O0fuXsPcAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
- pgAADqYBh9ypbwAAAi1JREFUOE+lkV1o0lEYh1+/EEUICb0K68LMSPZvmH1RadtUpmaWSlAXIyxt1aib
- YR+b/TGUDHYTYyUxGF4JdiUjgmRkgu5CtovdTEwcuASXGQRdv51zdINI6GMHHs7V8zu/877g9/uhD8dc
- LtcdnU53Vq/Xg0QiAXpkMhkEn3XgRrwN16YbjH4y+Hy+kNPpBJVK9VSj0QRFIhH3TwFerzdgs9mC4XAY
- O50OEvkWwfS3DTgqt9ttpAGlUgmbzS0UCARxuVx+7k9fYHKr1cJCocACMpkMZrNvcWWljmq1Oj4W+fQt
- EPuS6DcDJjebTaxUKphMJrFcLmMiMYPz829wYSGL1epXHL40lbnysI7+cO2qd7IK4Ha7GVRuNBpMprVT
- qRSS7ZCAOSYvLhZxc/MHWq3We/bxVSRUCAB0TRQ67Xq9zuRcLsdqb79M5Y2N70z2eDxHjf732KO7WwrZ
- NUcGFSoWS7/JtVoHLRbLhMlkOnPKMQ0HhtLY45cAEAqFRkI4nX63U3t9fQu1Wu1djuMGjUYj7Bl8ScG9
- ptc8AQCDSfjonoThfYdpAG1yWiqVRpaWVnFt7TMqFIrHSqXyhMFggIPHx0FyaIbCKwZmYScAb74CDMzB
- B8d9GCFBYrHYTHjew+zYfwSWR24DXuAhPxSF6MkY5M1PAK0Pug22A/D6LODYC8jbJyDKjUJ0wA758yHA
- yzHAi1EWgM4I4OgUoP1RN4DneaTnf2/YjUwf3XWDnxi88DTgdn3hAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
- pgAADqYBh9ypbwAAAZZJREFUOE+lkksoRFEch3//yWYWtpZWHgs7ZEXcokkT7ty88sjGY2iiMNEY06Q8
- I7JClNSQabIwsvJIZEOhyIqiCAvZUuPvHLc7TF2PmlNfZ/V95wmI0VJKMaxOEXaWdRwOxyd3RJKkMzGH
- hWMg/ajcU/MlmgRyb4jWToiGTQNSDngRXfl7QFXVNEVROt7dbr612R7XgEIBJJ9jqEmXzQKGHIlEOBQK
- XQSBg4BwDKKiWWA7QPnrc7RxeajxVjDrxWq1jnjFHSyKgMGPAUN+fejj8z31aagD+ynJCdAslr8DZrK/
- DVByLH8HfpJ9ztjAaUoeuKgXmOvWmXeLc/UiecGT2P981cybS9kPcttyZSkbgdX0AnCxF2zz6IFJl850
- O2jSRQP8fMydlbTYqpKnr5Gi8m6dAi7xg+2+2MCokyARTzl+f7HMLo1WnGVULH9nVy1ht6EQrA2CywbM
- A/6sEuM7sBCDQsyY0FIRLreBq8bAFSO/B7h5Ftw0A3+mHeFqO7hhGlw/Ba6Z+F/g6PqN4wHxyNKNO/AB
- NFrDjHczNdsAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACKSURBVDhPY2AYBeghoM3IyLgGB54OVCxGTJA5AQ1YD8JA
- xTpQDRFQfgQxBugBFW8BYaBiPaiGKCg/ihgD9IGKd2LDQM36xBhgANS8H4SBij2A2ACI46Fiy4FsLkKG
- GAEVHwVhoEIjqGJsYjjN8QNqPgPCQBUmUFXIYir4XGAFlHyIBxcQcv5IlAcAm4MjD8DlZQQAAAAASUVO
- RK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAABgSURBVDhPY2AYBfhCQJuRkXENMgYq1iY1yHSABqwH4h5S
- NcLU6wE1bwFydMk1IA1owAZyNTMANW8Fas4k1wAjoAFHgZoNyTIAqHkJEJ8BajYh1QAroIaHaBgkNgpw
- hAAAm8EOmTkm1pMAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADMSURBVDhPY2AYBfAQsJ/9zMN2zvOZhIIEpAakFkWdxZT7
- HhaT750BYUIGwNSB9IDV6rVd8NBrv3Sm58bf/yCaGGy68ztELVAvg3Ll4TMT7vz/33j2z/+OK3/+N5//
- +b/u1Pf/lUe//C/f//5/8a5X/3O2v/iftO3l/5Btb/+77vj0X3zt1//qu//8B+llkMja4SGWtRXsAhBN
- DAa5AKQOpBfsDb74lR48McvPgDChMICpA+lBUcseONuDLXAOwVgAqQGpJWTRqDwJIQAAilGdHbgOJisA
- AAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAEFSURBVDhPY2CgNqievPN/y9xj/8kyt2Xe8f83btwA44aZ
- B0k3JDa/5z8MxBf2k25A5/xDcBc0TlpDmgHItsNckVA0AcWQpUd//E+vnv3fK7Lgf82U3agWYDMAJAYK
- TJDiqJyO/6GpDf89wnL/57cs/7/k8DfiDABp9o0p+W/jHvXfwjkUzK6atAPTeyXd6//H5HUjArGg+39G
- 9Zz/PlFF/03tA/6b2Pn/t/GIBrsEZxSnVs6AGxCV3f4/rrAPrBGEHXwS/ieXTcUfsMjhAGKDNIKcnVY5
- 839Rx2rCsYJsAEizW3Dm/6z6BYQ1wvyEbIC9d/z/kq51xGsGGQIyABmTlR/orgkAcvMB8BYVXdkAAAAA
- SUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAG2SURBVDhPY2AYWmCNhDzDKtEzDCtFPUh3+Hx+AYZlIhvS
- 3pX/Z1gucoZhGSmGrGJgY1gsPE/nmP3TqEfZ/+Pvx/9mWAQ0hCjwn4GRYb5wq8JWo3sBNxL/e1/1+cWz
- XO4Sw0IRH1T9swU9GGYLngFiVP/NFsgUWKZ8w603/J/9fvu//EsUrzHMFUpG1TwFqGm64BmQAhDNAOKD
- wDQBH465Epfl58v/Vqs3/8e3QP4Ww3SBakyXT+I/4/M095fHhcj/EVcy/zAA+QwT+XKZpgqeFlps8kNx
- k9F/7tnS94FiPQz1DEyYBvTyeTD08pyxvxn/U2mP8X+zEwE/QHypTfKfpXfo/OdbJPeEoYdvHlAzB+5w
- awMa0s5zRuuU8zeJw5r/Nc5Y/hc/pPGff7HcK4ZW3nUM/cBoJAiauTwYmrjPSB9Q+iJ8VuU/+zbx94yN
- PLsZWjilCeqFK4hg92AoYD/DukDgBWMZ2xGGcDZNYjSDAoYfiOWBWJfBiCmNIZ7pDIMWQyiQDzJACYil
- gFgYiHmAmA2IGZENBnFAAQTypzhUsSSULQqkBYGYF4i5oJqZ0Q0gxpVY1QAAJuuF6gTRvEgAAAAASUVO
- RK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIOSURBVDhPrZI9SCNRFIWvY2RUAskQ8qOIFjbisoUSSJk0
- Qpo0CzZiE5JO0cKAjcuyCxoDFmm0ELUyMQq7sqgY0kyhoEiC4h+M7WgRLFIs7DLs4tt7gvMgGqwcOPDm
- 3XO+e+e9IXrvJ0/UvU00uUOUZx0/K4891N7sVyCKfe/o0MuhkFlNJq3fU1MCqiYSVnl42EQNnqaQHBd2
- 3e6KmJ0Vf6anxZrfb6RV9RzC+mRkpPZrYkLsOp0VeBsgazxaob1d/5dKib8zM2K9p8f4QjS3SOSCvhKF
- +X3nx+DgfTUeF7m2Nh0ZCdng7zviER8TiXoYnThQZkVt0wKRB5DDYLBWGhgwkZGAVaItIxy2sm53vTPC
- D+PjryCYJKOqRsnrtZCRgGU+7ZtYTMwryjlGRmdALiORBghq39hz0NcnkJGALL9cRKMCRZhQsCFnQ0MS
- YgOKXV0CGQlY4nH0YNDKtrYaGNMu2JCT/n4bMgdP0eOxkJEAJk8WfD5zX9NqOCgc2EvIaSBQh/xU1dqm
- w2EiIwEZvpJMS4t+1dsrcp2d94BgEvsa7YPNaNpTWdMEvMg0/Auf+edIK0rl1usVh9xlhUdd4DOBsMbe
- NYfhgbfp3/iJCymmb/CIustl3XEAwhp7qMHTLOzgTT/rQ4CvMEKUHiXaGyM6hbDGHmrs+cjiJSEjH4VX
- TpaPhW97S2gELzL0H9Dj5tei7xUOAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUFJREFUOE+lk69L
- Q1Ecxb//wmCra6uDlbXFwcJgYXVMXFkdD9y6BouGWRxM8BeiiGARFINJTFcwCApWMVisYvB4ztU3Bveu
- +MLh8v2ezzn3vQfPAFgWZQrr4lnBsZmdmjUop1Pz4Z9iXvrU8wUKOYxG0Ek15gq89zkYzLyggLD7Hg7x
- 2GziK0mgmVKJ5N57Pe+9djreCwr2Ce7R+Oj3cVOt4q3bhWbpqdXyu/t63e/EBgU0bIfGlMBLu43Lchl3
- tRquKxXsFgo4KRYhT4zYaAEBmxDYJnhRKuEgl/M6yuehnTwx0YJ1GpvUmNAW4XPeesZwKu3kiREbPIGW
- G7+Au2IwJnliFhXIcLcMp9K8YBd+xFXCDwyn0rzG26SYF7zCCsGEoWeW6NTMoEkxLyhgyJYZWmJYp+a0
- IOYFBf/9IzP/jT+zZw/Woa9yPwAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAoklEQVQ4T7XTywqCQBSA4ZlH
- b92qR2id2UXJIiQiIsRN7lz6JtN/oIkpDhKjCh8O6LnCGOecGWJQsBT+JLDWzrBCgjU22GKHDDkOOGLu
- uw4TGD78TUsgVdOeql/JJ+lAZt0HsxacTzijxAVX3HCfpAPZcF/VcXZg3o82gjorXT1QoUZDfIsuage+
- ury1BAu/4Z+qT/5fhsFqgtgLNd5liu3gBRRIn3FPTkzqAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAoklEQVQ4T7WTywqDMBBFk093
- 7da/qGJf+ECklFJK6abddemfxBNwithGSqLCYQKSOXMHoowxKoSgy1b8aaC1jmADKWSQwxZ2cIAjFFBB
- LFOPGyh+/M1cA5e1RtCIZJUJbNb9KGvJWawt5xOc4QLXVSaQBTqtmG/BO1DD9yuC3fBX1sF6pz7gxf03
- dF47ELutcw2SifUpVmrqjOD7oJZ7TL4T9ELIn+co5cQOAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAqklEQVQ4T7WTzQqCQBRG7zy6
- 6x7Ah0gpLfohIiJEoha1a+muTe8wngkcJrUYxhQOjsp857vCiNZahjBosxHbAKVUBFNIIIUZzCGDBSxh
- BRuYNK3dAOGDNz4BbesWwQ72cPAJ+NmmL8DMmjuzrll/WHk+wgmKURq0K79nda2sSzjDdZQG9g9/sV54
- fxeRB1RBDdhoL5+AGKOx3hor9ye8IO8EhB6o/x2m0AY1iSqgdYRW23EAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABDElEQVQ4T2P4//8/AyWYIs0g
- i+EGMDIyMuDC0sq2DCltb5DxfxCfaANABuvaFTJEVj+E4f8gNkkGgAzxyrkIw/9BbJINkNNPZLCKOQDC
- /0E0ugGNQFtWA/FaIF4HxBuAeBMQbwXi7UDcA3KFjt8mEP4Pokl2AZeQDoOK22oQ/g+i0Q1YD7RhIxBv
- htq6A0jvBuJ9sNgRUg5nUHJZC8L/QTQZLtBlUPfcAcL/QTS6ASC/Itt6EMg/AsQngPgMEF/hEzNlMAm7
- wKAfeOI/iCbJBQxAoO2yhMEi6uZ/IH4AotEN6AfaArL1KMxWoJ6rQLwcpBkErGLuMtjGP3RwTH7+H0Sj
- GEBuhqJeZiLXBQDC0LFONyaX7QAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABLUlEQVQ4T2P4//8/AyUYrpmR
- kZEBHzZ2KWdIbX8Lw/9BbJDFRBsAMjym7jEM/wexSTZA0yqHIaDoOgj/B9HoBjQCbVkNxGuBeB0QbwDi
- TUC8FYi3A3GPrF48g03cQQanlBP/QTTJLtBw7GYwDd/1H4gfgGh0A9YDbdkIxJuhtu4A0ruBeB8scNXs
- uxj0A7c6aPls+A+iSXYBAxBoem9mUHVfC6bRDQD5FdnWg0D+ESA+AcRngPgKp5Aug7LrBgcll7X/QTRJ
- LgDZLmPWCbR9638gfgCi0Q3oB9oCsvUozFagnqtAvBykGQTUPLYzaHjtZtD2PfgfRBN0AUwjiOYTM2Uw
- Dj0Pw/9BbJIMsI69y4CE/4PYRBugaFTK4Jj8Ehn/B/FRDCA3R1KUlUGWAgAiG3UaYBp/hAAAAABJRU5E
- rkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABDUlEQVQ4T2P4//8/AyWYIs0g
- i+EGMDIyNgLxaiBeC8TrgHgDEG8C4q1AvB2Ie/QdihniG587pLS9+Q+i0Q1gACrCi51jVjBEVj/8D8QP
- QDS6AeuBBmwE4s1QW3cA6d1AvA9msGPUMoagkpsMXjkX/4Nokl0gIGHIYBVzAIT/g2h0A0B+Rbb1IJB/
- BIhPAPEZIL7CAAQ6fptA+D+IJskFIM2cgtoMKm6rQfg/iEY3oB9oC8jWozBbgXquAvFykGYQkDJuZlBy
- WQvC/0E0QRfANIJoLmF9BnXPHTD8H8QmyQD9wBMMSPg/iE20ATK6uQwWUTeR8X8Qn2gDHJOfM6Dh/yA+
- igHkZijqZSZyXQAA4IG1TpHFZ2gAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
- dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJKSURBVDhPY/j//z+DX8FVDBxZ/ZAhqeWVRkrbm7lA
- fB+If0HpuSBxkDxIHU4DIqruB0bXPrzftODpia0n3+668/zLiaNXPh3oXf7yFEgcJA9SBzbALeMsCvbI
- Oq/hk3fx/rSND3ccufH60MuPP259+vb7+etPP28/evPt7PztT3b5AuVB6sAGWMUcQMdz83svnth96cWB
- q48/ngBpBor9B9FP3n47d+3JpxMlEy6dAqkDG6Djtwkd35+77e72M/feXbj78suDd19+fQCK/QfRID5I
- fOme+3tA6sAGqLitRse/dp5/fgCkGMj+j44/fvv97PC118eA7F9gA5Rc1qLj+wu239sNsgmk+Ofvv5+B
- Yv9BNDgsPv68tWrfw0MgdWAD1D13oOO52W3nz+6/+urw/ZdfT4M0AcXgYQAMyHPF3RcvgdSBDXBwcGCw
- s7NjsLW1ZbCxsWEwd8q0Mgo+/GLe5gdnbz77fBoU+mCbgfSz998vbtj/6pRxyMn7egHHILGAbIC1tbU8
- 0JDijsl7/ltFXnjVOOP5pZNXvpx+/u7H9VNXv5zpmPvymk3crfvmkdcDDYPPQNIBzACgRi03N/eaHTv2
- /BcVFWtWs2qxc0x+PheI7wPxLyg91z7xiYZF1E0GFAOAtlsEBga3HTly5r+iolIPCwuLqpJxCYNTyisM
- DDSAAcUAoO3eCQkpEy5evPtfT89gGlCzMRAzEG2Aubl5ya1br/7b2zvPY2VldQFpJskAPT09LRERkRag
- 5hiYZhAWlrEhzgDy8X8GAJItIDq7n94UAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
- dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIySURBVDhPY/j//z+DtrY2g559IYNfwVU4jqx+yJDU
- 8kojpe3NXCC+D8S/oPRckDhIHqQObACyRhiOqLofGF378H7Tgqcntp58u+vO8y8njl75dKB3+ctTIHGQ
- PEgd2AC3jLMo2CPrvIZP3sX70zY+3HHkxutDj958O/vk7bdzIAxiz9/+ZJcvUB6kDmyAVcwBdDw3v/fi
- id2XXhy4+vjjCZhmGL725NOJkgmXToHUgQ3Q8duEju/P3XZ3+5l77y7cffnlAToGiS/dc38PSB3YABW3
- 1ej4187zzw+AFAPZ/9Hxx2+/nx2+9voYkP0LbICSy1p0fH/B9nu7QTaBFH/69vs5Mn798eetVfseHgKp
- Axug7rkDHc/Nbjt/dv/VV4fvv/x6Gj0MgAF5rrj74iWQOrABDg4ODHZ2dgy2trYMNjY2DOZOmVZGwYdf
- zNv84OzNZ59RDHj2/vvFDftfnTIOOXlfL+AYJBaQDbC2tpYHGlLcMXnPf6vIC68aZzy/dPLKl9PP3/24
- furqlzMdc19es4m7dd888nqgYfAZSDqAGQDUqOXm5l6zY8ee/6KiYs1qVi12jsnP5wLxfSD+BaXn2ic+
- 0bCIusmAYgDQdovAwOC2I0fO/FdUVOphYWFRVTIuYXBKeYWBgQYwoBgAtN07ISFlwsWLd//r6RlMA2o2
- BmIGog0wNzcvuXXr1X97e+d5rKysLiDNJBmgp6enJSIi0gLUHAPTDMLCMjbEGUA+/s8AAJUZIgOF4ptY
- AAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
- dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJISURBVDhPnZLLaxNRFIfvIvkLTF0J0uAjNDKoWaTk
- bS1RUYshLowWqZqFD/BBs/KxUEMoaKEgiJuRbqRQ6UaojTqUYGpJYmpMSFuMxklK2mmmmba2kzSZINd7
- pk1p4qa6+Djn3vs73x24gzDGSKvVIsp6B3XcntzEdS+LLnt5jdtXoAksQdqoNOzDOeRkwdbBGufuso4L
- D7Lso/7Z0HBYeP+DE0OfkiuB3oF8BPbhHHKywH51oo7j12OaUzfj7ADDhTJ8MbNclOZWSlUOgH5wdD50
- mpxDThYYOgON0Ld646F0XsyQHgOFpYpcgZywNuPpS0QgJwsOdLxphKXfpkdAQHq8KErL0EOFNfSvGJaB
- nCzYY3/diPQuxgUgmBfWMHx6Tih9gQrrX6XqXHBqYRxyskDdPtQI2z/y8wMISI8r1d+rMAwV1iAYHM1+
- hJws2H/C3wh9wxebyC4UZ0iPAV4oyxVYKkpc95N4AnKywGazIYvFgsxmMzKZTEjfds1w2BmcH2JmvxdW
- K5svAIjlKj8cLCR1Z8MsdWZ8/RW2CoxG424i6e55xmCD6yv/8AWXCCfFz9xieToyKUZ76PyU6WKK1bum
- HYec0fX/oCYggy12+7H7fj+Dm5p2Pt5n8FqOXOFoAkuQNiptvZTTtJ7/huoE5PZWh8PpGxuL4uZm9VOF
- QrFXrfOgNjf/F0SA6gTk9pNdXe6+eDyNKergczKsI6BtC/R6vSeV4rHVevSlUqlsh+F/ElAU1aJSqbxk
- uLM2DOzYZdqe4P/B6A86Ah9NBTgWLgAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
- dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJXSURBVDhPnZLda1JhHMefC/0Lcl0FMelFZhwqLxy+
- t4YV1UjsImvFKi+qQS9MuujlohIZ1GAQjG7O2k0ERdALpW3SZNpQ0zllall6NKwzj1OWczId8fT8zuaY
- drO6+PBwvs/393kezjkIY4ykUimitNdQ19XoGqabGXTOyknMtjmawBBqqysNOexDjxesH6xz4gZjOHU7
- w9wd+eF96yuMfmPL3o8zJdfA05wfctiHHi/QXwg2cPBSSHLkcpgZepVxeD7nJ+YXaz9LlWU2X6p+/T5X
- CT62Z0ePkn3o8QJFt6sZ+spA2DsWmXVlC5VMrzWESYZBQp6nYtmS1zIY8UOPF+zqet0MQ79L2kEQSBWn
- i+XaPMlwMldOQwY8cTJO6PGCbfrnzdTeh1i+CMDJJFu7AeCO5SehxwvEnS+aYUbsqTEY5n4tJarLvxdI
- hmGF9wCCZx8yE9DjBTsPOZqhe22h4HiUc8+VqtnT1/2YZBhWuAV5kVN998MR6PECnU6HNBoNUqvVSKVS
- IXnHRcVeo3t2+E06mOYW4zBUp7BQTb0c5/yy4z6GOja58hXWC5RK5VYi6et/6MQK0zR35xEb8c2UP7HF
- pbg/Wg7007mY6kyCkZvihj3GwMp/UBeQwTa9/sAth8OJW1o239uhsGr2nWdpAkOora609mxW0n7yC2oQ
- kNPbDQajzeMJ4NZW8QOBQLBdLLOgDjP3F0SAGgTk9MM9PebBcDiJKWr3EBmWEdCGBXK53JJIcFir3T8s
- FAo7YfifBBRFtYlEIisZ7q4PA5u2qDYm+H8w+gNv9h/ta4LougAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHYSURBVDhPY8AH4ltfa6S0vZ6b3Pr6PhD/AtEgPkgcqgQ3
- iKi6Hxhd8/B+0/ynJ7acfLvrzrPPJ45c+Xigd9nLUyBxkDxUKSZwyzmj4Z176f7UjQ92HL7++tCjN9/O
- Pn7z7RwIg9jztz3e5QOUB6mDakEFVjH75xb0Xjyx++KLA1cefToO0wzD1558OlE84eJpkDqoFlSg7bvp
- /pytd3aADMCFl+6+vwekDqoFFSi7rf614/xzuGJ0Fzx+++3soauvjoHUQbWgAiXnNffn77i3G6wZqBib
- ASv3PTgEUgfVggrUPLfPzWo/d3bv5VeH77/4fBrdgEevv54r7rpwCaQOqgUVWDpmWhkGHXoxf/P9szef
- fkIx4Nn7b5fW73t5yjj45H2doKOYsWBpaSlvbW1d3DF5z3/LyAuvGqY/vXTiyqfTz999v37qyucz7fNe
- XrOOvXXfNOIaZjqwsbHRcnV1r9mxY89/UVHRZlXLZjuH5GdzHZOf3XdMevYLRIP49vFPMW0G2moRGBjc
- duTImf8KCko9bGxsqlApwgBos098fPKEixfv/tfT05/KyspqDJUiDpiZmZXcuvXqv52d8zxmZmYXqDDx
- wMDAQEtYWLgFaHMMVIhegIEBADK7VwLsrsplAAAAAElFTkSuQmCC
-
-
-
- ..\icons\notification-counter-01.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-02.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-03.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-04.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-05.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-06.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-07.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-08.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-09.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-19.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-20-plus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\notification-counter-20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\balloon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\icons\resize.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- 551, 17
-
-
- 17, 54
-
-
- 662, 17
-
-
- 452, 17
-
-
- 116, 54
-
-
- 17, 17
-
-
- 782, 17
-
-
- ..\Resources\AutoCrop.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\Resources\CropHorizontal.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\Resources\CropVertical.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFMSURBVDhPY2BAAmFhYb4hISFayGIksQMCAjKKioqqyTYE
+ aEDmfyDIz8+v8fX11SbJdpBiT0/PbJABIJCVlVVLsiFubm65MANAdEZGRr2rq6sO0S5xcnLKRzYAxE5J
+ SWl0dnbWJcoQGxubQnQDQPz4+PhmoJweQUMsLS2LsRkAEouKimoxNzfHb4iJiUkpLgNA4uHh4W0GBgb6
+ OF2ip6dXgWzAp0+fvjo4ONSDxGEYaEAUTgPU1dWrQAY8f/78fWdn50oQe+7cuTtVVVVx24psmoKCQh1I
+ MzDq+oHs+PPnz9/58OHDNyMjo3wVFRV2goEoKSnZaG9vP1FGRkZXTExMHBhwM0CumDJlyl4pKSlDggYI
+ CQkli4qKwp0L5AefOXPmHsgVsrKyhQQNQFfAxcUlAcwfs0GuAHpjMskGgDQICwv7AWNgKgcHhx02AwCj
+ LeXNW0xBiwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGhSURBVDhPY2CgFBiX7TEzLtuVA6KJNQtFj2HJ7tz///+f
+ AdFGpTuiicHIehiMynZZGJTuyp+58+7Cl+++nyIGg9SC9ID0gl1tULIj7sW77yfvv/q6mxgMUgvSA/ey
+ ftH2hKfvvx+/8/zTDmIwSC1ID9wAncKtiY9efzl688mnbcj48uMPG07cfrN4/+WXM3acfzZx85mnfSB8
+ +u675SA9cAO08zYm33/x5dCVR+83g/C5ux/W7b3ycs7G008mrDv5tA+Cn8DxkRtvloL0wA3Qyt+cevvF
+ lwPnH3zYAJLcePrplHUnnkxadwqIkWkQG4gPXX+9AqQHboB6zvr0q08/7tt75dXiDaeeTgPjE0+nYmCo
+ 3JEbr1eB9MANUMtalwn01/b1p57MWnvyycwNaBgkBhMH0Ueuv1oH0gM3QDljdfbRG282Af06D4bXn3w6
+ F4RBfHQ2UO1GkB6wAUppy50VUla0lC88u+Tw9TdbQBgYDpuRaZg4TAykFqQHpJdBOn5RLygpg2ip+MWl
+ xGBkPQwiEXO8RcJnTwXRxGYmcvTgNBsAn7X331hK7TkAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIMSURBVDhPY2DAAYzL9pgZl+3KAdG41GAV1y/frmBUtsvb
+ sGR37v///8+AaMOyXYkgMZAcTsPs6/ezGJbucvZtP5S55PDDSbP33F5iULwzb9rOOwsfv/m2ESQGkgOp
+ AanFMMiwZIdH4fzzpY/fft31+M2XA/dffd2NjEFiIDmQGpBaFAN0inZoBHcfzXv86uuuO88/7QTiHTjw
+ TpAakFqQHrghuoVbo7aeezITpOnW009b8WGQGpBakB6wAVp5m2y087eU9m++sfTqow+bkPH5e+/WHLnx
+ asGOCy+mbjzztG/1ycddINy4/NIskB6QXpABFaDQBtEXHnxYD8Kn7rxbtePC8xkrjz3uWXnkIRivOPKw
+ G4aR9TBo5qy31czZWNW+/uqS07ffrt1/5dXCVcceTVxx9FEfMl5+5FE/CIPEqpadnwPSA9IL9oZ69obE
+ VUcfTN97+eWSFUcfTl5+9OEkXHjN8UfTF+671wfSAw9E9ez1uu6Ne8oOXX25dBVQAdCWadgwSO7QtZdL
+ XBt2loL0oESlSsaa4Jj+gzVHgIYAAwzojYezQHj18cezQTRIDCQHUgNSi5GQjNNmssqnrQiwKNtY2b3u
+ 4qSDV54vLJx7aolC8orWqoVnV4LEQHIgNSC1OJO0ROxCTam4RYlSsQvrJGMX9oFiCESDxEByJGUskYg5
+ 3kA8DUSTpJEUxQBDDL1n/h9HZwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADASURBVDhPYzAu22NmXLYrB0QzkAMMS3bn/v///wyIJkc/
+ g1HZLguD4p15BqU7s3Qq94iTZQhIk2nJFgmDkh1xIJoyQ4q3xWtRYghIs07h1kSNgu2SZLsEpFknf3MS
+ xYZoF2xK0ShYS75L1LM3SGnkbUwD0WR7B6RZPXtdBkWGqKavlFbLXJsFosl2CUizcvqaHIoMUUlZKyOf
+ vLxBIXlFq1ziCheyXCMZu7APlHdANFkGiETM8QbiaSCaLAPQNQEAHzZMfWDTaNwAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADOSURBVDhPYzAu22NmXLYrB0QzkAMMS3bn/v///wyIJkc/
+ g1HZLguD4p15BqU7s3Qq94iTZQhIk2nJFgmDkh1xIJoyQ4q3xWtRYghIs07h1kSNgu2SZLsEpFknf3MS
+ xYZoF2xK0ShYS75L1LM3SGnkbUwD0WR7B6RZPXtdBswQ7fzNDSQbppq+Ulotc22Wdt7mXrIMANkI0qyc
+ viYHRJPsApCtUNwnn7y8QSF5Ratc4goXkg0CaZCMXdgHyjsgmiwDRCLmeAPxNBBNlgHomgDCEFXWJ2yt
+ cwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHZSURBVDhPY2AgATxnYBDDqzy1aatuSssWf2yKnjIw2Dxk
+ ZFx3npGxHachKU1bt6Q0bQlDVxAQEKDm4OCQ/6+09P8jd/eXaxgYXDAMSWnalpbavHVm6KpVzMiSMM1/
+ //79v2bNmqurGBiOYHVBUvOWU0DbjZEl9y1lsN80i3HL9WNB//esMv7AycnZgdP5qfXbHiTX7xCCKYBp
+ /vmi+v+VPX6vWvMZDuMPwOZt01Mat87IzMwUxNCcw3Y+Ozs7OC8vzystLY0LXyA21td4vlnYL/oWZPOJ
+ PUE/Glwk/0K8t3VVavOWrSnN254DwysEqyELyxnk5lbx1L67m/Z/y0Kz9y25HFfq6+tZkBWntG1VAxq0
+ Oq1+kwiKIf8ZGBj7sxmb/r87878ojHFBhj9DFS6npjZtW5HStF0bRb4thbHn2dVl/3OCGJdnBDB44guw
+ 1KYtS5Jbt+mhq/mf7s+4KsWXAdVkNFWpLdslk5u3bsTwAjAaXwADqC2tZasJLtuBmriAzm8FqmvCTIn1
+ 22SAoVue0rhtO9CJF4GhviCteVsF0K8JQHZcSvPWouSmbWuAqXV+Vv0WCZxeBIY6U0b9TjGgU72BthUC
+ NbcDDe5Mad5ek9KyzYKEzEucUgDgY9pgutX3/gAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFZSURBVDhPY2CgBjAu2+NqVLYrihQM0gO326xqd9Lrj98u
+ vvz4/RQxGKQWpAdugG31zuwX776f3Hn++Rq3hl31MAwSA2FkMZAakBhID9wAx9pdJa8/fj/nVL+zDCYI
+ Yj99//04CKOLg9SC9MANcG/YFetav7PGpX6XBUwQZMPT11+OgjCybSA1ILUgPXjD37xqZ8KdF1/2XXv4
+ aRuITXJkmZbujj504+XSQ9deLgGxSTbApHRX7OHrb5aBMIhNsgHmlbtSD117vRKEQWySDbCt2lFw+Mbr
+ NSAMYpNkgHn+egWnmh3Vh6+92XAUiEFskBhRhiilrw1UTl+T07TiYvvuiy9W7r78YiWIDRIDyWEYIpe4
+ wkUheUUriAZJKqQuz7/x9PPxCw8+7Dt2/c0WED5378NekBhIDsMAydiFff///z8DoiVjFpWRgsGGiUTM
+ 8QbiaSCaKD+iKQIAuEYmAAjjsCcAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFZSURBVDhPY2CgBjAu2+NqVLYrihQM0gO326xqd9Lrj98u
+ vvz4/RQxGKQWpAdugG31zuwX776f3Hn++Rq3hl31MAwSA2FkMZAakBhID9wAx9pdJa8/fj/nVL+zDCYI
+ Yj99//04CKOLg9SC9MANcG/YFetav7PGpX6XBUwQZMPT11+OgjCybSA1ILUgPXjD37xqZ8KdF1/2XXv4
+ aRuITXJkmZbujj504+XSQ9deLgGxSTbApHRX7OHrb5aBMIhNsgHmlbtSD117vRKEQWySDbCt2lFw+Mbr
+ NSAMYpNkgHn+egWnmh3Vh6+92XAUiEFskBhRhiilrw1UTl+T07TiYvvuiy9W7r78YiWIDRIDyWEYIpe4
+ wkUheUUriAZJKqQuz7/x9PPxCw8+7Dt2/c0WED5378NekBhIDsMAydiFff///z8DoiVjFpWRgsGGiUTM
+ 8QbiaSCaKD+iKQIAuEYmAAjjsCcAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFRSURBVDhP1ZI/a8JQFMVPMFu3unVMCM3egkuHDkWEFgqF
+ jq4ODoLgB3AsOETc3EQN+AeVuroUUeuQUXAQRVEEUfMVbt99bQqWDHHsg8chL/f8uPe8B/isePw163fu
+ e3Y44ON4BAml/R6024EymRfabkGbDWi9Bq1WoOUStFiAZjPcn4BcF9TpmJTP31G7bUpAOv0sd6NhSkC9
+ bsrvWs2k+Ryn3TGAO2i1rimVepIAVu6AdTQKS/U68AXkchFynEtKJmMSwMoA1uEwLNUDTKfIDga4+h2D
+ M0gkHkSbOrEygJW3betyhGr1+1+lotN4jLdeD063i2LgoL3Cfh8xNvPIkwlc20YiMOSvuVyGUyrhJhDg
+ n5pVVb01DOPdC+ysmUUwRigUKlqWRZqmfZ5rhmdWFKUrYGkBuAiUNheJVybv+cf8GNjoFTabcAoFONFo
+ sDv+AmJ7C7hZF4QaAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIFSURBVDhPxZDdS1NhHID9ByLoJrrpIiGIMIy8MYVqrEhi
+ FpWCSUmmrCFzjPzooo0ZtiAzyD4u1k1hMLEtLTUUtlKwhrD8yGmWpWPamDr6OuLa2Pa0991VtF37wu/m
+ /J7nec85OTmbfspNJs1Zs1mbaWqsYbLthCdf/pTJdJks59y1QLYVwksHmpp0iWSSg7ehuB1Ud0HdAfpu
+ 0Bh8VD8FowNuDoHdCz1TIHjhyUBJQ0NdLJFA15UCndA6CG0uePQODl0cpWMY7o2k5ZF5GF8CwQtPBo7p
+ 9fpIPE7rwFucE6sMfYTBWfjwDfafeUVv6sZ+X1qeWIYvayB44cmASqczKLEYh1uqKW03Yh/zMR0E/3fY
+ fdyJZyHKmP8Pk8sxPq/GCf5KInjhyUBxba3xRzTKjvNF7K3XUGKt486AA/fMLLvUz3g9F8KdmtGvYaaC
+ CoGfUQQvPBkorKq6Eo5E2FZazvbTleRe0HLA0Ize9pjcoy8wPx/mwRsfnV4/vTMruBYUBC88GSioqGgM
+ bWxQoLVRVP8EdXM3J6/3c8MxyZ4TbiwvP3HLtchDT4jO6d/0LEaRfMqTgX1lZVeD6+v/BDSWPlrs46mf
+ 6KWxaw5LX4A29xr3PQq29zEELzwZ2KlSmVdS37SkKP9NYeV8xueCF54MbM3Pr9mSl2fNNEcuhci2E54M
+ bPr5CzGs8HBMuX66AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAF0SURBVDhPY2DAAU5tYghHltq7jHEzLrUY4ruWMOgeXMm4
+ CUQTrQmmcMschtgtsxh3vrub9h9Eg/gwOU9PTzUnJ6cCAwMDLbwGb5nPYLB0AsOh9VMYDNA1f/jw4b+q
+ qmoNTgNOrYf4fVYrQyouzTIyMti9BrQ5dut8xh0gGskGPyD7AcxmmGacgbqomyEZXXNZWdl/oNhzRUVF
+ woEaHh5+IDs7+395efl/EB0UFPTf2tr6v4mJyX8rK6v/bm5u/0NDQ/+npKT8z8/PP4ArLPxMTU1/vH37
+ 9v+3b1//Hz165P/q1av/b9266//Jk1f+5+QUX8MXC2A/+/j4/MdtQMlNnDaDNKenp/9nZGT8GRcX97+k
+ pOQ/yDCgi/57eXn9h8rtxmYA2OakpCRwgAENuIHHgKPoBoA1gzSANANxENCA83gMOI9sAFhzVFQUXDNU
+ 8iYuA4DyKGHwABh16JpBZjzCY8AjZBdYwpyN5q9SIP8lDgySAwMASvXss8cC3BsAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHWSURBVDhPY2CAgv1JLBkHEpm7QTi57c0BmDjR9N5E5t6/
+ N5f9/3Vl4f+4hmf/idYIs3l3ItOZX5cX/L+/se5/aPmd/zDXYKNBeuAWwGy+0uf6/8fFef8/n5j63zv3
+ ItgluDBID9yA3QnM/SCbL3Y7/f9+bvb/u+uq/9snHv3/9dR0sGuQaRAbhEF64AaYhe85YBq++39ZWPzL
+ L0DJdwf7/oP42PD9TfVgF+6KZZ6IEUYbI5lnfTo+5f+tVeX/dfw2YgQiSAzkwo9HJ/3fFsc8BcOAtZHM
+ cz8cnvD/5a72/6ruazAMAImBvAdy4ZZo5ukYBqwKZ17w7kDv/2vLiv8ruazGMAAkBnLhm33d/0GuxTBg
+ WSjjkjd7Ov8/2dzwX9l1HYYBILGbQO+BXAhyLYYBi4IZV7za2fb/ysI8oBe2YsUgFz7f3vI/1jnmHUiN
+ mtsWRIqd78+49gVQ8gHQny+2Nf+/sigfhdb23f//+tIisAv3lRv8f7O74z9ID9wlE70Ydz3f2vT/3ppK
+ rNgw+PR/kAsfbaj9v71Q+z9ILUgP3IA2Z8YpzQ6Mx3Bh88hrYFeBXDjFl+ktSB1ID9F5xjb+4f/XQBc8
+ 29KIajOxJjglvzgAcx2yzQAGOo0BdV/WSAAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGdSURBVDhPY2AYMiCp9fWy6JZXkiQ5OLL64f/g4usOIE0g
+ dmTVw0kEDXDPuKjumXPurFbOxT+uORcfeOVc/A/SBKIDCk69804/L43XEKuoA+vtEo6aghRZxRz475x8
+ HOwCELtl3rULljEH8LvCIGibFzYbdPw2/b/68P0R46Ct7/S9N+N3BcSA/4za+Vs0tfM3g12g4rb6/4sP
+ 365U9Z2+quK6Gr8rNLLXCWvmbvRPn3miUiNnQyrIACWXtf/vvPh84sLd98dUnde8U3XC4gr7+v0sytnr
+ LO2qtmUtP3x/1vWHn46pZa3LBBmg7rnj//kHHw5eAuLS3kuX1Ty3o7pCPn25gmr6qoSKRafaj958s3Hr
+ 2aer9l1+sVU5bVUuyAD9wBP/Vx17vGzCtltT9lx4scUw6MQ7/ZBj0gyioVN4JGMX+jtVbaneevrJ2lO3
+ 3xzac+XVjm3nnm5etP/uCsmYRWUgAyyibv5fsvfp/i3nnm06eP3V7vrpT66YRd2YxCAUPjsIiOvw4CCQ
+ AQ5Jz5Y5Jj//j4xBYgQT1uBXAAB4ctTtvOBX4gAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGcSURBVDhPY2AYdCC65ZVkUuvrZWQ7LLLq4aTI6of/QQYE
+ F193gLGJMtA7/bx0QMGpd145F8EGgGjXnIsPtHIu/vHMOXfWPeOiOl6DLGMOTGqZd+2CVcwBsAHOyccd
+ YGy7hKOmVlEH1uM0QN97s7Rx0NZ3Vx++P6LjtwlsADowCNrmhdMAFdfVk6r6Tl998eHbFRW31WADtPM3
+ O2jnb9FkYPjPiNfpqk6bpVWd17y7cPf9sTsvPp9QclkLNkAjZ0Nq+swTlZq5G/01stcJ4zREzXP7pNLe
+ S5cvPfhw8DwQq3vuABuglrUu8/rDT8eWH74/y65qW5Zy9jpL+/r9LCgG6YcckzYMOvFuz4UXWyZsuzVl
+ 1bHHy/QDT4ANUE5blbvv8outW88+XXX05puNFYtOtaumr0qQT1+uADfELOrGpPrpT64cvP5q95ZzzzYt
+ 2ft0v0XUTbABkjGLyhbtv7ti27mnm/dcebXj1O03h7aefrLWqWpLtWTsQn/R0Ck8DA5Jz5Y5Jj//j4xB
+ YiADhMJnBwFxHR4cRFQCG9yKAPGK1O3Fnfm/AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE9jYKAG
+ sJ/3cqb93BcxILOs5ryWAvJzHOa9XAYUOwPCYDZQDCSH1T7bmU/OQHGr49xn+9P3fHzcfOnn14l3/v0H
+ YRAbJOa04Pl569lPfDEMsZz28MzMp///g+je67//t1349b/90u//XVf//O+4/Pt/y7lf/1vP//o/+d7f
+ /24Ln16ymPoQ1RCT/ltnuq78BNr253/VoU//QeyQ1U/vgMRB2H/J0zvFe99/rz3y5f/E23/+20y7e95w
+ 8nWEd/Q7r5xpO//1f9H2V/8n3P79H8Q36Lw8BeZUg64rUSCxrE0vvlfse/c/fuPzx/odV3LgXtFqOnum
+ 78bP/02nPoExyDsgMc2ms+CABQGtpnNR9hOu3slc++R/0f43X7UazyyHG6BWfWymatXRM+gYJI4cYCD5
+ uKX3/5cdePsfxIbLyefvV8jc9co+ePFtB7nifca4koZ88b4zwYvu/s/e+fI/iA1XJ523WdVv8d0Qt0UP
+ crTqD1dIZm8yQjdEMmNrlG7j8TseSx7+D1nx4KtE1laEF0RS10oadp7ys1rxPNdl+aOJIsnrOkSS13jB
+ DBFOXhMlkrL+jNvKp9+tVrz4b9Rz5rFQ8jpEIDKErmITTlrtbLHlQ67W6g8THNa+3KTZcGgXX8zyg7wx
+ y89oNBy647Du5XetNR/+W2z++F8oec154aRlqKmSK3qxJG/C6njFTd8mSKz7tkVp07drBjt/fDTc+fO/
+ 8ubv/4Fi/xU3ff/Pl7zmEmfkIszUCHIue9BcJbbwhRVcNceX8Sx4cZ5z4++PXJv+/OdZ8PIrd+3xx2zh
+ i86zBc3GrhkeaP7zBZh9Zvgy+kzvYfKZfpDJd8YZRp8Zy5h8p+cw+M3BnpkoydEAA0J2Ek+355UAAAAA
+ SUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE9jYKA2
+ sJrzWsp+3ssch3kvl9nPfXEGhMFsoBhIDmQfUCwGyJ+JYbf17Ce+Tguen0/f8/Fx86WfXyfe+fcfhEFs
+ kJjj3Gf7bWc+aQXiMyCMYoDF1Ie+bgufXpp87+//1vO//rec+/W/4/Lv/11X//xvv/T7f9uFX/97r//+
+ bznt4ZmZT/+DabgBhpOvS9lMu3t+4u0//2uPfPlfvPf9d/8lT++Y9N86A8Ihq5/e6bry83/VoU9AF/35
+ D2KDxOEG6HdcyYnf+Pxxxb53/7M2vfiu33nljEHXlSiYAoPOy1NAYhNu//5ftP3V/7bzX/+D+HADtBrP
+ LC/a/+Zr5ton/+0nXL2j1XQOrlmz6WyMVtNZsLObTn0C474bP/+DxOAGqFYdPVN24O3/uKX3/4PYyIGj
+ Vn1sJkgMHYPE4erki/edyd758n/worv/QWxcSUOueJ9x8OLbDpm7XtnL5+9XgKuTyNq6PGTFg68eSx7+
+ 1208fkcyYyvcCzBFktmbjLTqD1e4LXqQ47f4boh03mZVuAFCyetyjHrOPLZa8eK/28qn30VS1p8RTl4D
+ N0QkeY2XSPK6DpfljyZarXiea9h5yk8kda0k3ADhpGVSQslrzlts/vhfa82H/w7rXn7XaDh0hzdm+Rm+
+ mOUHNRsO7XJY+3KT1uoPEyy2fMgVTlrtzBC6ig3Fq5yRi3z5ktdcUtz0/b/Eum//lTd//2+48+d/g50/
+ Pipt+nYNKLZFcdO3CbwJq+O5ohcjbEc2hS1oti9b+KLz3LXHH/MsePmVa9Of/5wbf3/kWfDiPFfN8WVs
+ 4Qsr2IPmKuHPf35zpJh8p+cw+sxYxuQ74wyTz/SDjD7Te5h9Zvgy+M8XoHbmZQAAKzx2EneDTb0AAAAA
+ SUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAeJJREFUOE+lk71L
+ W1EYxt+z378gJUsgX9MdwhV0STJkCEmXpIvELaNLBhE5oyI6F0RqKbRbW0q/hlIqSAahUISIXAoNDgaV
+ DFlcOrSlnr6/k0YuRboYeHjP+3zdcy9EnHNyF0ir1ZJ2u31fETabTalWqxJFkRQKBUmn036yw6Pjw0+O
+ B3uy2+1a0Gg0wv8VoM+85HwBv2w2aweDget0OrZSqYS33QAeHR9+cjcFeg5zuZyN49jp1WypVAqTr8AO
+ j44P/78F7GE+n7fD4dDV63WrxpBvwGSHR5+FbwqWjZGeYkGBqE+2o9HIlctlm0qlHjDZ4dHx4SfnX+Gr
+ Hs4Ul4pX06KwWCza8XjsarXap36/79jh0fHhJ5csCC6MWVQ8VLx8bcz+RiYTTyYTdxgE8Ynu8H/1RS0I
+ kgXBqTGbk/n5o18rK1dua+vabW+7k17PHYh85+yhPDo+/FoQ+BscG7N0Pjc3wPQ2k/m2I3L0e33dfdSp
+ 2GWyw6Pjw0/OFxwa8yQZ/rG66t6p+b3I0gf9akx2+GSJz1HwRmRfxWvEn2tr7rnOF9OQUMBkh0fHh5+c
+ L3gksvclisbc4qmKz6ZmH5wVsMOj48NPzhfsidzT5bHis54xyW0F8Oj48JPzBXf5K5P9A150nLcmaqfe
+ AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAiZJREFUOE+llF1I
+ U3EYxt9LP1IitohdlHUTa90oY4z1cSGBZCzWh9hFCJGSHxHM6byYzi7KuooG5mIok1IYg1CW4XJnCDLJ
+ PFSCFyoryjQvXBE1bfm1p/971s5VkOLFj5dzeJ73f34cziEAtBvoclubSoXbbRXc2AFWpXzB5cpSK54G
+ 6W3AOdGrJXGassTqdDL1m+k0Sj1AWacI+DLzopjX+4H6ANAnA6FpgHOcVxZUtLfTpdZWOmu33/y9tYV7
+ L3/BN55G4A3wdBIIvgX8r4DHMUD+DMQTAOc4zwtU7/MtLYGhiQnYOppR5/XAF36NXklG/6iM7pHMHJJn
+ sZwEVjY2cKah4Ra778i7Z0TC15UUvq+t4XRNjV31fvdMg3+jVe+ztysYRTC+jkQqBXNVlUP1nhoowsyL
+ g5gb/kv4EN5Lh/Fh9AjikSLMiWv2djyR0DO1iaXVVZRUVjqJPdjnWukJ3K8z42NUj4UxPb6MH8fPhTKs
+ J6/g2+wpLMaOKd7+cBiLySSWhcLR8nIXsQf7nNTpcE6vh/tqCXpvGyH5LfiRaBRv+w4Sn6oxP2ZSvA02
+ W2RvcfFdZp/RWE3swT6DD/IUQg/34LmnAMPeQkxHtFia0WFyQINod6Hqvd9spnyDgcQSIvZgn87GHJVH
+ jhx4m3Mx2JWPWKgAfR156GrKVb1Fh7QmU2YBe7APe/2PrLfocI8OWCxE7JF12s7kvEacnmVXnzL/Bv4A
+ nbSTNl0cgYcAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAApJJREFUOE+Nkl1I
+ FFEYhs+VBXlhUHlRXWW5WyratuoqtpIb5R+4thrrrrna2mRulu6aroIWWlYomj+ZWllmaaWpoRWGBCVo
+ 7oQ/QZmEGIlQN0WYiYJv55x0DKzo4pkzvOeb5/tm5hAAhFEVTCRsoXInnU4XTREWiWbZ7zWVakIY/OFF
+ QQ0tEBnnfMhQQ3ba1NjYezDYPcuW9ulas0JQoSbiu6okdBwPQF/fCAYHRzE+Pslh9yxje28rTGC1FGJL
+ oJelCcqCiPi61IhbCR6oO+iGm/Hb0XTYG3eTd6LR5Inrce64neiF4ZI4sFrzCRPR5eUtC0oCiDhUrEfv
+ 6Ug8tgZzrmRqUZqll6jOT8S1swKs+oAP9GGBEilNcNGfiK8uxOJZ7n6J8lwjHRBY+AMsj8rJSZEERUoi
+ 9hdq0X0qBHX2GFyyG5BpF/BkYAC6MgcOXXbAVO1AylUHap+OYn5hAeFWa6okKFAQkY3flb4bxZmx/+zc
+ 2NOP7/Pz2GuxpEmCfG8isvFbU3yRJ4TxDsNtGzgj7a4Y6aDQleXlD7vxZXYWQWZzuiTI9SDioww16g0y
+ ZCVqeIfzR5V40yXDxxdyfJ3QYOqlF8/tTT34NDMDX4PBJgmy5ERsS/XHDaMcNlMI76D3W48zCW7oqPTC
+ j+lkjD4P4nltZyc+z83BU6vNlgQZ24j4gAoa6DlIj9/DO9wpXMNpLnJGb6sLWoqdea7SBH5bp1QWuKpU
+ SZIgbQsVHPPjh8USp+YdJqenV8DyiMAdk5u8PQiVLB8kYfMvQbPZBycPKGAM/wsRCmhkrhNRW9eSQPeN
+ y4IYFyK2W1T8L7TQj3df2CVx74gCDHasGayWQhjSK4SuIjX7nIj4P7DasNWEMH4Cj2pW/p0+C6YAAAAA
+ SUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgdJREFUOE+lk71r
+ WmEYxV9xEPwAXVxapQRFiqaEKwRvMgiBIPU6+PUPOJVSOgWElrZDoIRCh5bYqUsDafYEp5hEMHIFr6Dx
+ Sm2oSa1c0+AuBZen77nEi5JsGQ7vwzm/c1BBRkTsPtLL8XicJRIJlkqlWDqd1t9sNityPbuROJuBRQfd
+ uYFkMrnCwef8fYB3MpnQeDymWQ/MnQOSJK3m8/lPo9GIcrncaw69uLoaEoQbHjIwYOc+QSwWY1wv+/0+
+ KUqdhkONisXiL03TCMLd6/X0DAxYdIyvIIoii0ajDzOZzLuzsxa1Wk26vLygweCPLtzwkIEBi44xEIlE
+ otzYgHZ2vvU6HZX29r53Q6HQFwg3PGRTDh1jQBCEfKOhULl8QrWaTO12mxYXn2yZzWYG4YaHDAxYdIyB
+ YDD4qlqtUqlUIryq+oOWloRNk8nEINzwZhl0jAG/37/u8/neQNvbhd/NZocODo6a4fDyWwg3PGRTDh1j
+ wOv1Mo/H80gQwh9luUHHx6d0fq7R9fU/XbjhIQMDFh1jwO12M65NWW7R/v4hVSoNKhS+9uv1DkG44SED
+ AxYdY8DlcjGup2tr67uK8pMCgcefnU7ne1lWeUEl3PCQgQGLztwAh5jdbo/bbLYth8OxgLfb/ct/0AHN
+ emDA3jnAQWa1WnVZLBaJ68ONpKkP5tbAff7O/wFfbRPfU/HxPQAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAZxJREFUOE+llN0r
+ Q3EYx58/ggu5EkkkbyX3Lv0DJG9pzfuS1z/ArYUQQs0sr81h2FghWV62NRcrk06Ezd4wbOxuni+zzuTi
+ lItP31/PeT6/3/Orcw7FYjH6D1TSZy5l2pDFvbskB6kDoZ0nsCGZapkkHCrq2SljVFNmUeMLRc/kgF44
+ cKmw2wRqvaHo6U0gYpYDeuHApYIuI6j3PH8ci76wSQ7ohQOX8ju3QMNt8N1y6XnbluK8exFOrh61+07/
+ hOn8YXjT7lEDq/i0AAcu5akMoPHaHzlkwQAc1yH9ntM3vW51DwlnbvU39+q1OJbLoA4OXMrt2ACKK2/4
+ wHETEo5cQR2Lo/rT+xEWRqSJNeCeRThwKadNAMoL9+sej6oVrO5xPhGM/cHXM4sruAwHLmW36EGzTXwy
+ 8phTfOokZxKo/dSRFldADwcuZSpXKKtptZXvtcG7z0qY4TVALWnNE6zDgUsZiqVyZqB/zj7Pm2zGMfzK
+ nzrSgF44cCm9TjuIVxnJ9Mgk4VBq1UxFSuX0GDKtRkNykDr/+pTxG/gEq8OGaNZeGVsAAAAASUVORK5C
+ YII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAjVJREFUOE+lkdtL
+ FGEYh78L/Q8Kom42ilLKjhAEdRWEIESgFyVSLBSd1NpqzCwiL7rwwCyt5JQH2MlZ29nddltP7aGw2nU3
+ S2uxTIlN1h1bXLUTmbfb+xt2bOzgTRcP73zv+3veb5hh2y76GNjO+VV2VAVUdl4K7iLKUbUeqpbTPFX+
+ bYGBgkVERSaTGUIljNmeYbkFOTTcd6AudKozNGlpffRBonOl4I+LytyCFz3MkCFy/ngDahSarK855dNC
+ gHiSmP0R1IMeZsggu7hg64WHjMgraQxX0k2BifS8n/D9Az8yyMKBywpMvWzL+b7SvlepO/Hped/71Pfe
+ 5UAGWThw2eZzPXsIztwzbhtVvnXpiSW+uMLjc1ZfbPqWd+gj7xqcqge18kgLHLhs09nuanxt1Fjiqwe8
+ jH92kHTbEVUa5YGkRgM9q+gdll/h3UvU1HlGJRLv97+dEUm8aR9I8vYI8aua6RnwVzpjbXDgsrzyB2zj
+ GY/RGZkUHr9JSyQ1Uchy7y+g7x6cEsT+CR4OXLbhtBsUFNYGq0JjMzZHNCnI0WTzEiJ0JpzPFYEy0v7r
+ AQ4OXLb+pEujuMz89Gp4bNbWPZwSnVGlJUsrKnqYIUNOseaxdSecGrlrj8sHd3NdlxvcI5Zn79Kiqf2F
+ ZDhmv1HTMSyjhxky5ORqnn4BozBbc7Qjf/WRu0biGsHjD6GihxkyuksZfuNiI7uArSqzqqw83F604lBb
+ MyrOtEC9ZMkCuoH9Dz8BRapC1u0zrmQAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUpJREFUOE+lk8lO
+ AkEURd8/qLG7ykSj4ohzYvwAdnyAmhiISgDbBmfdumHr0o2aGF1onOfxF/in5t6KTbDTIODi9qvqyjv1
+ qt4tmdr7nobcnyiIZfVkrqVl9kha547FWjgVnTyXrtSl8D/leZ7I5O5XDoMiI8T5LzGpJmBi53MGykMO
+ 1D6+/SGjm28ysvEqw2vPMpR/kgH3wezI3bvTV+WxqQBJviwkJyArDNDn3Elk5dYkE0JYECBMHtt6TwJg
+ BSuoF8DyWcEiAHblERoB8Px2dP1lCQDbv4NGAbxAVpACwOYlNgNgB9Rg7jENgGoWwBaq/tX7LACqni6E
+ egDJGnIA0H+1sRqAHtC92RsXAB3qA9/CNFYND3TAQPtQoXP5ImaMROtWPiCOCVCJs2o64NvBOqOYkoMA
+ zuEDaZs/CVMcj+sQa3ED4Oc/KgFbmIwOgc7x+wAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK8gAA
+ CvIBPVL3EQAAAUxJREFUOE+lk0lOw0AUROsOgLCdBYh5HiXEAdjlAICEEgFRCMYJM2yzYUmWbAAJwQLE
+ PI9X4E6mqoWjYJmImEX5d7tVr//v/o3R7Y8xyvuOYCyrdeECdZP7qJ86gDVzhET6BM2ZM+i/5Ps+MLL1
+ nufgU5HS/IdkqgoY3nwbpwqUSzUObbxiYO0Z/atP6F1+QE/hHl3erdlRu7dkz8tjkwFNgSyaU5QVBehw
+ r9G+eGXMgggWBkDmwfWXNAFWOIO/ApS+MpglwK4soRaA6rf7Vh7nCLCDM6gVoANUBhkCbB1iHIBuwOnO
+ 32UJcOICdIVO59JNjgCHZYEqVruFyB6gOUG5LGk3FkA7y9yWu/QUIzMIWliNFe4B7SrRXGIDFamdpvnT
+ CdNIat3KB6SxAE7q+DeV9Ha4rghTcxigudJumD6MUpKPa49rSQPQ5z/6ApWFkK7wYogxAAAAAElFTkSu
+ QmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAdFJREFUOE9jYCAB
+ PGdgEMOrPLVpq25KyxZ/bIqeMjDYPGRkXHeekbEdpyEpTVu3pDRtCUNXEBAQoObg4JD/r7T0/yN395dr
+ GBhcMAxJadqWltq8dWboqlXMyJIwzX///v2/Zs2aq6sYGI5gdUFK89ZTQNuNkSX3LWWw3zSLccv1Y0H/
+ 96wy/sDJydmB0/mpTdseJNfvEIIpgGn++aL6/5UD/q9a8xkO4w/A5m3TgWEwIzMzUxBDcx7b+ezs7OC8
+ vDyvtLQ0LnyB2NhY4/9mYb/UW5DNZ/cE/WjIk/wL8d7WVcAw2prSvO05MLxCsBqysJxBbm4VT+27u2n/
+ tyw0e9+Sx3Glvr6eBVlxSttWNaBBq9PqN4mgGPKfgYGxP5ux6f+7M/+LwhgXZPgzVOFyKjC8VqQ0bddG
+ kW9LYex5dnXZ/5wgxuUZAQye+AIMmOCWJLdu00NX8z/dn3FVii8DqsloqlJbtksCw2QjhheAznoBDKC2
+ tJatJrhsB2riAqprBaprwkyJ9dtkgKFbDsTbgU68CAz1BWnN2yqAfk0AsuOAthYB5dYAA3B+Vv0WCZxe
+ BIY6U0b9TjGgU72BthUCNbcDNXamNG+vSWnZZkFC5iVOKQCnrtq9RcibTAAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbxJREFUOE+lktkr
+ RGEYxt8/ghKJcOlCmTJlq2G4cOXOduyGQogYyxiU3Ll0Rcl+mCTLxDlxM5ZIspQtF0qWaUaWEeNqvM/h
+ 1LEkk4tf33ue93mf7zvfOeTz+eg/kM4sA2Nsk5zjD5jBxhTXIoPiW8/rnvPBu/UX4MWMEpDYJoPKm3vv
+ prR7bUvvlKwq0IBWgwcaZpQAQ7sEGlyP3p0Uq9Ro7JAIoL6+e9kAX3V4MaMEGK0SpXVIAtPG6PGsnury
+ 9nkNYDdoH179h1fQBlA678oNSrbwnTQrFJ7dPK0cXjzaUUNDDx7V+2OArom/yju5jmPXqOPINYJa1X8N
+ SOJjagIEx5F7DLAmqDo8n04QXjpB0dXTFG+2k75Z0lLGwyJgvUzbS+V7SjAvKD8gISDCNKmsMXWzzBwl
+ ti6BWn4FG0ANDT14okwihRQMfw+ILJ+iqAob6epnww2WxdbVY/fMGoMaGnrwYPi3gEw2VnVN7vfI+05R
+ PnCKqKExmd8CwkrGU/n43VhDi0bxKjWnV56N3fP7lfUT9zzgehkaevB8OkFw/lAvX8Y2VqbRH5RLDMwe
+ yAjI6u/DGpQ3SP6AgDdx0wjL45XA0gAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAetJREFUOE+lkz1I
+ AmEYx19SUBc/bhAJWxMaHBR0j0AaxFoiuMLWwmhpjYYIKmhpaIiKDLIPogxs6esqJCI89SioQBy6IGtw
+ KO5wOZ6eR+zAshocfvD6Ps//d89798oAgDVDNbzOGNtAtpBtxlp3GIshCSRdg9YxqlEP9VKGst8F4T2L
+ RcgHg/LbwIDyMTKivQ8Pa688r+QCAZlqKAj/Jggf2O1iiefVl2gUZJ6vg/ae+/vVpM0moiBcN0GcRjOb
+ hae+PvWxtxfuI5GGPPT0QCESUTdNJoEy+hFW8XxXPp8sdXfDTWfnn+RCITjt6JApowuWGNu8DYUUIRiE
+ L458Pkh6PJBwu2HN6YRljqtC65THo1BGFyzi28ana8d+P1QqFSgWi5DNZkGSJCgUClAqlaBcLleJOxyw
+ 29amUUYXLOAPsatLO2xvh3w+D5lMpmGYBDso2He5NMrognkc59zrVVI44hY2/EWKBBynUEYXzNLFcTqf
+ LvB8Z9jwH3GLRaaMLpjGTzJnMAgXLpd6jVNco+Q3Tmw2dbalRaCMLpjCazmJl2PGaBTTHKdKKJFQ8p1L
+ DM8YDCL1UqZOMIEbY1gYR/uK2SynrVblzuHQCFrTHtWoh3obCkaxMISjDeL5kASSrkHrGNWo54egmb/z
+ Jx8zDDjpQm/GAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAmNJREFUOE9j+P//
+ PwMlGKyZWWczA7PuVgZm/R1AvFOC2WBXChDPAuJtUAxip4DlQGpAaoF6QHrRDfDgtdi72THj5q307rcf
+ i6d9+VM09cuftM63H+3TbtwCyQEN8MBlgIeo3YFD6V1vP6e2v/4fUHQDBae2v/qf1Pbqs4jt/kNAAzzQ
+ XLBJktd0x5aUtpefI6sf/PfKuQR0HSoo6bv1HyQXVff4M4/J9i3MOpskEV7QWp9qk3jxdljFnf9+Bdf+
+ e2Zf/D9x0VUw3nboGdikOWsfgOWCS2/9Nwo/eZsZqAduAJP66rlhlXc/uWee/w/DTimn/ptHHvhf2nHo
+ /5kzZ/6Xd+75r+K29r+614b/ZpEHP4H0IAxQXb4zsvruH5e0M/8dkk7+NwzZ+1/de+v/qOK9/8+fv/h/
+ 6brj/9U8N/1X89oCxkD5P0xAPQgDlBfvCi2/+dc6/sR/naAD/7UC9v3X8Nv5//bt22Cs6bcLLAbD+qGH
+ /jIB9SAMUJg/zyn1wmeDyNP/9SMQWNN/z38QRhYDsbUCjn5mAupBGCA3O0PVfe9di+Sb/00TboCxQeTZ
+ /+/evQNjEBsmDqKlbHfcYwLqQRggPV2SQ3HODovEW1+sMp79t0p/+t8k/jrcABAbJAbChtE3vrApzNnB
+ BNSDMEBqKgOTxCQvbpW5x82SHn6xz//43w6IDaPOgzGIDcImCQ++cCnPPQ5SywTUg2qA+AQGRv4mbzbR
+ zj0KtjsemiU+/uJQ8PUvCIPYIDGQHEgNE1AtdgP4GhgY2EqlGFiLsoF4KRAfhmIQOxskxwhUg2EAJdkZ
+ AOypQZHMHzM4AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFrSURBVDhPrZMxa8JAGIYVf4ybSwRBB0E36VIh/0CjaFBQ
+ HAKiFJz6RxRsiwaktgGpFrEuTm4OXQpSEFrBWkHw7b0By1UkdTDwEO67556bzuU6x+d2u68EN2q1qp0C
+ XZ75vVss7mq1Gvjt/oEOXZ6RA61KpYLtbofNdusIHboi0JIDZrlcxpc4/LleO0KHrgiYcqBjGAY+NhvM
+ l0tH6NAVgY4c6JZKJbyL218XC0fo0BWBrhywCoUCxtMp3lYrR+jQFQFLDvRyuRySyeRJ0BWBnhzoZ7NZ
+ +P1+KIpyFO7tKRaLDPTlwDCVSiEQCGA0esFg8PwHzrinqiqCwSDy+TwDQzkwTiQSCIVCsKwneL1eG9O8
+ t+GMewxEIhHous7AWA5MNE1DOBxGu/1o/0mj0bbZzxiIxWLIZDIMTORndCEWM5/P991sPiAajdrU6x2b
+ /YyBeDyOdDoN+ofv8FIM5h6P5/oY3Dvg9hwP2fUD8MfQYXCln30AAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFeSURBVDhPjZC9S0JhFIfP5NzeGA25RFRQQzVGa+o/0FBB
+ EC0uLQ4FIVFIH6ANRoYK4v/hcsBoSrtIhJWJYvnJ9et0f4EtR1564YGXcx6ee3mJxpyAz+3yeDybXq93
+ B+CO2Tj3b3a1RpHLVWJwPEcPUf/eez5vCcAds9EerophmbvekvTuomQyj5LNPkmhUPwFd8ywgwNXBc5X
+ iMU5sdi9BIOnEg7fSDyelFQqLdHbOwmFLiSRSEIRuCpwtkw8dJb94VCeLWss2MGBqwLBJeKeI9j9vhE4
+ cFXgZIHYHgyk1e0agQNXBY7midu9nnx3OkbgwFWBwCxxw/l6tdk0AgeuChy6ib9sW0r1uhE4cFXAP0Nc
+ dX6/WKsZgQNXBQ6micvttrxUKkbgwFWB/Snij1ZLrHLZCBy4KrA9SfzmPGCuVDICB64K+CaIP50Hem00
+ jMCBqwIbLoqsu4j/A9xR4AdKLDJN/KRkLAAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAI3SURBVDhPjZJvSBphHMeP9XJ7Iwh764v14no1fdHCAtsS
+ bzlvLLmJjoGDmH+QIYOUuE5OpkMJfOOovXL0IodvwnqxsCQDWW3CXm6DCb1YVMRgbfQHVlbf3e+GcFLK
+ nuPDPXCf7/fu4X4Mo1muWIx/KMu+yxBk+YbWvXQvTEz4fzUa2D48xObBAb7v76ssVKugZ05J6u5Y8kAU
+ A7+Pj7G5t4dvu7v4srODz9vbyC8ughY958JhQ9sSPhoNHpyc4IfyVm3Jq9lZNOnmOKltgWNsLHSoFPw8
+ OrpQQl9CxyGnpUCW5StOp5MXBMHf1dWViUQi6AQ55FKGsozD4dCLoijvKmcOBAJIJBKIxWIXkCQJ8Xhc
+ dba2tjA+Pi5TlrHb7Ww2m52p1+twu92IRqPw+Xzwer0YGXFiaMiK/v4B9PbewvCwXXWWllaRTCZnKMtw
+ HDc4Nze3WqvVYLValbAfNtswBgYGlaClBav1ruosLJSRyUytUpaxWCzu9fX1jUqlAqPRCJfrsSLxl2Kz
+ 3Vcdn3IVCu82KMuYzeZnpVIJ+XweBoMBgvAEPP+oLeTkcjkUi0VQljGZTJFq9T3m50sIhcKYnJxGOj2F
+ VGpaw2tl/49g8DnK5U8qlGVYlhVXVtawvLwGj8fzXzQLKMvo9fpRnU73klD+cZpG9t408OYD8PbjV9yO
+ j+KmP4U7kQL+nJ6CnKZP2Zahut7X90Ides06Oz8H0Tg7Q0O5k9N2lK/19Dy9yrKpTpCjLfgLj/3c8nL7
+ lrMAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAG8SURBVDhPrVM9SEJRFL6GgoGICoqEruqswxsFB8Uh1EUS
+ C6HZoaG1uYSGlpawv0EzKWwwiIIukYPE03wkVCAOvSBrcPPhIqdzxB4YZosPPt7hfj/vnPvuZWzWT56x
+ hVPG0kXG8ojKCHlaI27q9wqMLZ7Pz3NREOSvRKLH/f4B4RNr0euViSPNxJAcEiWTqdZJJpWPVArkZHIM
+ tPa+tKSUDIYaacdCsthaQa/nzXhceY3F4DkSmYiXaBSawaCS0+k4edSQA5zvHluUwmF4CASm4jEUgmuP
+ RyaPGrDH2MmT39/jggA/uPZ64cLthrzDAUc2G2QtliGoLrtcPfKoAbu427RZNz4f9Pt9aLfbUK/XQZIk
+ aLVa0Ol0oNvtDnFsNsOZ0zkgjxqwMwq4dLmg0WiAKIoTzRRQxICS3T4gjxqwje1wbKuMLRZQMA1l5HMG
+ Q488asAWHRyr9e0O57tFwX841Gpl8qgBGfwlGY2GXxmNShW7qGLIXyANackzdhY28HBszs3VSCBhiIQh
+ v0EcaUg78TSuIbGO6fvYIsc5udk8GAJrWiOONFPvwyq2tozzreBlwneFMKrTxM368rJvjEdIo/39bLwA
+ AAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAGbSURBVDhPrZGxSwJhGMbfb/c/uEUEEadzEiQQBBeRBqUl
+ bPIPEKdDvuXACJxrMJKgLWqQWiISwkEIQriIW5KWg+KIW1oKCvLrfb40VFQMOnh5732e3/vc93FE//EU
+ i8X1QqFgrpIFDvwUWy6XJSqfzy8NgT9mpwKi0ah0HEeVSiWZyWTmhkCHDw787GlNiK7rKj6iTCQSUyGY
+ ocMfLc/9iBmLxeRgMFC5XE4yqCF0zNDhs7T0mjrE8zyVTqelYRgb6JhXWdbXWuMvxONx6fu+ymazV91u
+ V2GGvvAvvRCFnok2n4TY5TptC9HZDofdIAhULxRy73iGDh8c+N8wl4dHIXaCVKr/Xqm82rY9VI2Guq9W
+ 1TXRG95R0OGDA489HeIQbXnJpAPoLBJ52CPqf9Xr6oL7JVETHTN0+ODAY08H9IQ4nFz+sCx1zjCXBtAx
+ Q58MwZ4OaBN1bMsawvys1dQx95Nx+uiimKHDBwcee9reJzq4NU0fpzhik+vnaDMPdPjgwGNPI00ig6vF
+ wk1rwfI4Cz448Nhb+Fv/YnwDm33pU4rOXh0AAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAH1SURBVDhPrdFPSJNxHMfx56iWRqCXHcq6xKrLRlRUXuwg
+ WcKKGB3yECnliGCu7aA4OpR1igbmYiiTUhiDUJbhchuCTDJHJXhQWdIfzYMzoqYt/+3d851tbhC0wB98
+ +PI8fPj+ePFTlO08xpaWmot2+7V8I/2c+w1NTddRTzKPSE/6OQvOWa2m9WSSSgdUtcF51+a8oM6rPWDy
+ QHcEfBMgPennLDhjNt/4tbHBvZc/cY0k8byBp2PgfQvuV/A4DJHPEI2B9KSvZLtrbDZP/+gohlYrDU4H
+ Lv9ruoIReoYidAxuzv7IFAtxWFpb47TJdFP5X3fnYJDFpQTfVlY4VV9vVtLud89K+XvKMv/F3ewN4Y2u
+ EkskOFZba1HS7vHeciZf7GF64E/8e3kf3MfM0H6igXKm1W9xW54E6RxfZ355GZ3RaFPEIZ4rlSe533Cc
+ DyEts8Navowc5sdsFavxS3ydqmAufDDldvv9zMXjLKiEA9XVzYo4Uh6NhrNaLfbLerpuHyHoPsH3WKP6
+ 2neIfazj0/DRlPuQwRDYpdPdlezW6+sUcYin70FRKr6HO3nuKGbAWcJEoIz5SQ1jvaWEOkq23NmPLw7x
+ tDUWZPLIUoDTWkhf+w7CvmK6W4tov1W45c5eIA7xiOtfybizF4gjbcpnptzbeX4DJ7oc/jCY5XUAAAAA
+ SUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAJrSURBVDhPjZJdSJNRGMfP1W7yQujDiy5T0mGWbanL1MhF
+ WQrqprE5c3PpMpfoctkSXaFhgmapZWrZl6WVpgutMCQoQXNv+BGUSYjREOqmCDNR2L89J3xvXosO/HgP
+ //Pwew7nfRhbZTnT5DKNRpOq1WotBO0pW61WzBrjWHNDLBOIynA23mbPn5ue/giC9pStnFOtREaHHy5n
+ w3V8J4aHJzE2NoWZGQ+H9pTR2fsGI6hWIrgQw4S3dQbcyQpF66FA3MqUo8O8DfdztqPduAVt+s24awrD
+ RK0eVCsR1KqYMF6jw9CZJDw9sZtz1Z6CuhKdSJPThOvnLLDpIj9py8stqWVlSaKoOooJb6rT8aJ0v0h9
+ qQG0vKtAebLDkScKqpRMGKlMwcDJeLQ60nDJkQG7w4Jno6PQXnTj8BU3jE1u5F1zo+X5FJa9XiTYbPmi
+ oELBBLp+f1Esauzp/+zcPjiCn8vL2Gu1FogC51Ym0PW78yJQbjnAO0z0bOBM9gZg0uXD96W8/vEAvi0u
+ YpfZXCQKTsuZ8MQWhxsZwSgxqXmH80d34F1/MD6/CsH3WTXmXofx3NExiC8LC4jQ64tFgT2ECT35Ubhp
+ CEGxMZ530EWux9msQLgaw/BrPgdTL2N43tLXh69LSwhNTj4lCgqDmPDIJ7jtm4OizD28w73KNZzOKj8M
+ dfujq8aP5+Hq6B9rlcqKAJUqWxQUbPIJjkXyYbHq43gHz/y8BMoTo+UeySDlbvwj6DwSjkKNAoaDfyFR
+ AXXQulmJIM2fCb1WFf8LXb7He2hRijzIVYCgsSaoViJIkLHmfTIm/A9UuyL4DdOT5vYvoF58AAAAAElF
+ TkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAKVSURBVDhPY2CgBrCf93Km/dwXMSCzrOa8lgLycxzmvVxm
+ N/fFGRAGsUFiIDms9tnOeHwGjGc+aXWc+3R/+q6Pj5svffo68c6//yAMYoPEnBY8P289+4kvhiGW0x6e
+ mfn0/38Q3Xv99/+2C7/+t1/6/b/r6p//HZd//2859+t/6/lf/yff+/vfbeHTSxZTH6IaYtJ380zXlZ9A
+ 2/78rzr06T+IHbz66R2QOAj7LH56J3/9+++1R778n3j7z3+baXfOG06+jvCOfueVM23nv/4v2v7q/4Tb
+ v/+D+Aadl6bAnGrQdSUKJJa1/sX3in3v/sdvfP5Yv+NKDtwrWk1nz/Td+Pm/6dQnMAZ5BySm2XQWHLAg
+ oNV0Lsq27+qdzLVP/hftf/NVq+HMcrgBatXHZqpWHT2DjkHiyAEGko9bev9/2YG3/0FsuJx8/n6FzF2v
+ 7IMX33aQK95njCtpyBfvOxO86O7/7J0v/4PYcHXSeZtV/RbfDXFb9CBHq/5whWT2JiN0QyQztkbp1h+/
+ 47Hk4f+QpTe+SmRuRXhBJHWtpGHnKT+rFc9zXZY/miiSvK5DJHmNF8wQ4eQ1USIp68+4rXz63WrFi/9G
+ PWceCyWvQwQiQ+gqNuGk1c4WWz7kaq3+MMFh7ctNmvWHdvHFLDvIE7P8jEb9wTsO615+11rz4b/F5o//
+ hZLWnBdOWoaaKrmiF0vyJqyOV9z0bYLEum9blDZ+vaa78+tHw50//ytv/v4fKPZfcdP3/3zJay5xRi7C
+ TI0g57IHzVViC19YwVVzfBkPMNlyrv36kWvTn/88C15+5a46/JgtfNF5tqDZ2DXDA81/vgCzzwxfRp/p
+ PUw+0w4y+c44w+g9YxmT7/QcBr852DMTJTkaAA9fdaKg/q9TAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAKUSURBVDhPY2CgNrCa81rKft7LHId5L5fZzX1xBoRBbJAY
+ SA5kn/3cFzFA/kwMu61nP/F1WvD8fPquj4+bL336OvHOv/8gDGKDxBznPt1vO/NJq+2Mx2dAGMUAi6kP
+ fd0WPr00+d7f/63nf/1vOffrf8fl3/+7rv75337p9/+2C7/+917//d9y2sMzM5/+B9NwAwwnX5eymXbn
+ /MTbf/7XHvnyP3/9++8+i5/eMem7eQaEg1c/vdN15ef/qkOfgC768x/EBonDDdDvuJITv/H544p97/5n
+ rX/xXb/zyhmDritRMAUGnZemgMQm3P79v2j7q/9t57/+B/HhBmg1nFletP/N18y1T/7b9l29o9V0Dq5Z
+ s+lsjFbTWbCzm059AuO+Gz//g8TgBqhWHT1TduDt/7il9/+D2MiBo1Z9bCZIDB2DxOHq5Iv3ncne+fJ/
+ 8KK7/0FsXElDrnifcfDi2w6Zu17Zy+fvV4Crk8jcujxk6Y2vHkse/tetP35HMmMr3AswRZLZm4y06g9X
+ uC16kOO3+G6IdN5mVbgBQsnrcox6zjy2WvHiv9vKp99FUtafEU5eAzdEJHmNl0jyug6X5Y8mWq14nmvY
+ ecpPJHWtJNwA4aRlUkJJa85bbP74X2vNh/8O615+16g/eIcnZvkZvphlBzXrD+1yWPtyk9bqDxMstnzI
+ FU5a7cwQuooNxauckYt8+ZLXXFLc9P2/xLpv/5U3f/9vuPPnf92dXz8qbfx6DSi2RXHTtwm8CavjuaIX
+ I2xHNoUtaLYvW/ii89xVhx/zLHj5lWvTn/+ca79+5AEmb66a48vYwhdWsAfNVcKf//zmSDH5Ts9h9J6x
+ jMl3xhkmn2kHGX2m9zD7zPBl8J8vQO3MywAAM0F1onzOjz8AAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAHMSURBVDhPtZO/SwJxGMabFHQQB6cCIzRClFAIvBpEKMEU
+ FPEPcIuIpuCgqAYhJAgsJGhoMaI9cMpKMLnAE/xxkkVWJqeJuwQub/dIiqKDBAkP34fn+bzvHXfnxMR/
+ /fx+PyNp7VfMWNfxeDyLXq933eVyTeJst9vUarWoPwMzcpnT6VxiWfa42WxSIBDYcbvdG/V6jSB4ZOjA
+ gB1a4nA4NiuVCvF8mmo1kWKx2KsoigTBl8vlTgcG7NACm8025fP59vP5HOVyWXp/f6Nq9bMjeGTowIAd
+ WGC1Wm0Mw2xB0eh5uVgU6OrqomQ0Gk8heGTouhxmekvMZjObyfCUSNzT4yNHhUKBTCZTqAvAI0MHBixm
+ egsMBsN2KpWieDxOOAXhiebnzcEuAI+sn8FMb4FOp1vR6/W7UCQS+chmi3R9fZu1WBb2IHhk6LocZgae
+ g1arnZZu64jjMnR390AvLyI1Gt8dwSNDBwbs0FvQaDRBjstJV76hZDJD4fBZJZ0uEgSPDB0YsEML1Gq1
+ 025fvuT5Z5qdnTtRqVQHHCdIAwLBI0MHBuzIr1GhUKwqlcqQNDCDs1T6kh5olfozMGP9L2QymUsulx9C
+ 8GMN/QX6AQLKSmIufl07AAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAI3SURBVDhPY2CgOtDaIsFksCuF2WDnLEb9XdtAGMQGiTEA
+ 5fDax6y3w4PbfO9mx4ybt1I63n4srr/ypwiIQWz75Bu3QHIgNVgNYdbb4iFqs+9QfNfbz6ntr/8HFN1A
+ wantr/7Ht736LARUA1KLaojGWklukx1b4tvuf46sfvDfK+fSf3RQ0nfrP0guquT+Z26TrVsYgHrghjBp
+ rUu1ib9wO6zizn+/gmv/PbMv/p+46CoYbzv0DGzWnLUPwHLBpbf+G4WfvA3SAzeAUXXV3LDKu5/cM8//
+ h2GnlFP/zSMP/C/tOPT/zJkz/8s79/xXcVv7X91rw3/DiF2fQHqQDFi6M7L6yh+XtDP/HZJO/jcM2ftf
+ 3Xvr/6jivf/Pn7/4f+m64//VPDf9V/PaAsZaWnv/MKou3YkwQHnxLnv7/X+t40/81wk68F8rYN9/Db+d
+ /2/fvg3Gmn67wGIwrA9UywjUgzBAYf48p/iTnw0iT//Xj0BgTf89/0EYWQzElvc6+pkRqAcRiLKzMhTd
+ 9961SL753zThBhgbRJ79/+7dOzAGsWHiIFrKcus9JqAeRFTKzZDkUJyzwyLx1herjGf/rdKf/jeJvw43
+ AMQGiYGwYeCNL6xyc3YwAPWgpAVmiQle3Epzj5sl3flin//xvx0QG0adB2MQG4RNEu584QKqAanFnqR5
+ G71ZRdr3yNpue2iWCDQIGFggDGKDxEByDEA1+PMfZ6kUA0tRNhAvZWAtOAzGIDZIDCRHbQAAW754iHPl
+ f1UAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAHNJREFUOE9jYMAN
+ HIBSMMwGZMMwHi2oUgNjALJTDwAdBMPJQDYM4/XCwBtgB3QfDFcD2TC8GsiGYbxeGHgDDIHug2FxIBuG
+ 7wHZMIycPjC8MzAG+AHdAcNxQDYMI6eJyUBxGJ4DZMOwOsgPA28A0dkTm0IAEKI3YFhMEd0AAAAASUVO
+ RK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFdSURBVDhPldO9K8VRHMdxSSklJRYGxIDyOCBE8pA85Slk
+ 8JAFkyIlg2KiFKFsBovBKGUwGmTHopRSovAfeL91SLqXe0+9+p1fv+/9nPP7nt9NSIg+0nhUFuT+URf1
+ UQ5PutGLciTGE5JMcTPWsYsRpMcTkEXxNM5wiWUUxxrgViuxhms84RA9SIklJIOiFmzgCs+4wBzsy7+j
+ iIo2LOAAN3jEPuyL/Yk6UnnSgFZ4AvbhFK84D/f2J+rID6u4UkEI2+H6gHtsoQ5JkRJskD+cwAzswzD2
+ YDPfw24muWZGCrBBnRhDP2pDyDzXE7zAfqyi5HeAq7u1PoyiPgQY0oWfJ3LE/QDs1/dw9aGg6le6hb7K
+ Md7g0S6hEJ+9yINbX4FfXDv8bP2g5NwVPdI73Ia5Oy39CmhiMoVxVEcI8PVmsYltLMJX+wyogAE2zz+N
+ xdlwe3Jeg8FQ4ylY24HGDwiaO4lDc1lzAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFdSURBVDhPldO9K8VRHMdxSSklJRYGxIDyOCBE8pA85Slk
+ 8JAFkyIlg2KiFKFsBovBKGUwGmTHopRSovAfeL91SLqXe0+9+p1fv+/9nPP7nt9NSIg+0nhUFuT+URf1
+ UQ5PutGLciTGE5JMcTPWsYsRpMcTkEXxNM5wiWUUxxrgViuxhms84RA9SIklJIOiFmzgCs+4wBzsy7+j
+ iIo2LOAAN3jEPuyL/Yk6UnnSgFZ4AvbhFK84D/f2J+rID6u4UkEI2+H6gHtsoQ5JkRJskD+cwAzswzD2
+ YDPfw24muWZGCrBBnRhDP2pDyDzXE7zAfqyi5HeAq7u1PoyiPgQY0oWfJ3LE/QDs1/dw9aGg6le6hb7K
+ Md7g0S6hEJ+9yINbX4FfXDv8bP2g5NwVPdI73Ia5Oy39CmhiMoVxVEcI8PVmsYltLMJX+wyogAE2zz+N
+ xdlwe3Jeg8FQ4ylY24HGDwiaO4lDc1lzAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
+ CvYBwq9wAwAAAPpJREFUOE9jYKAGcEv37EfCx6FsMSxiRkCxMqh4Hdxuz2zfj9lTS78BJe5DJc8B6QAg
+ Pp41peQ3EP9HMuwlSBzEp4bjIWYgmR4HMx1JTA9NzAvIb0dxAZADcjIsHOBOBDkfKK4BNQAkDlIDcj6Y
+ jdUL//8z/MeFcfoZanI4yGnnrjP8n76S4f+uYwz/8zogbBD+/JUBOSBBLgmAG4jkheMHzzD8Dy2BaIZh
+ EB9kICwsoF47TnUvgAMFaEs1UoCCnYrGB4mBvKuJzQugaAQpgIV4P9S54BhCYuOOBbJSF5oTzdH4LDi8
+ gUgHWBIScqICsdETGlieLNeiawIAaZgQICy+wd4AAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
+ CvYBwq9wAwAAAnZJREFUOE9dlF1PE0EUhpu4sztDqyTG6EVp96vGFgmiwRCVeCHRiEEuUEgRRGxREEwA
+ ETQiVEQTAZGoMXpP4l/xt/AvfM7sIuDFm5mer3nPOe82oyvZZhCDC6ATXNHlbCvIcz97yNaGrQhi0GbK
+ uaCpfPxEhoDzKjSzKjbbbmw+W4RmwfX1A8557N9VqemnisxrN9B1bC/BCv6HFAoyHq/ifEfQror1Lwp8
+ cSPzhuAp7O+PlcxvsMt9jcRF/BtgiwI1CkQwyAWOr4ecUD9Tga7heAxG3aIedH0z7ISm7kRmGt84tiHP
+ NyPiVy3ebdifyVClwmtPbPXQvOL1LfDJsgrNCzcwE9hX7asR/kDP81sY1mR2UqCdH88xLhOwCn6Ar/S+
+ 4cRNqzCbxrfuRlrsH7h/5Nx2Qz1lC5hytqAKXi/0BlRB91PwKuhwK9l2pzXX6lVyobAE15K2pEVvnBZ6
+ KHAyacHXj6A6C5PRiwOd1VuTvTtgDPxJ7zv57mIb/gnbWmQaKjCjFCgkLTBAu5pAP7107/IMSXtpshQQ
+ 7HUOdi0QNyOtsbFvDHeOAufSFnSf0FN57wYFS7KeVFw+pwhKzg6Y3peXHdlOi+5BTKcOthDoSWZwl6A6
+ Q2rIUKG6xEuLcoIVsA6WrUZavJv7M0i2EJg5kodJnGNlmxRZk16d2K60IclOyezQwiYxDYkVuR9uYQgG
+ d2QTOEUsIwrKiKxfFXUf9ypsalZQvh6X2KNCsvI18ykbEQtU+V3UVUmw30eiFZG0tDF2VEgiotC8TQP2
+ TxGOKHTJfh+SnChy7V8BJnkatNvPtpztAtfT094RWrcV1//+5C+g+S/3C5lq0y853QAAAABJRU5ErkJg
+ gg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK9gAA
+ CvYBwq9wAwAAAONJREFUOE9jYKAGiIyM7EfCx6FsMSxiRkCxMqh4Hdzu2NjYjy0tLd+AEvehkueAdAAQ
+ H29ubv4NxP+RDHsJEgfxqeF4iBlIpsfBTEcS00MT8wLy21FcAOSAnAwLB7gTQc4HimtADQCJg9SAnA9m
+ U90L4SCnuaV7OgNxPxDHAfFxKBvEF0CLrQC4C5C8ANIQCsQvoZpBfBAG8eHhA/Xacap7ARwoQNdUozsV
+ jQ8KSJB3NbF5AeRMkAJYiPdDnQuOISQ2bWIBlg7M0ZzMAuSDkjVyfgGzsXkBxflIXkFPaKgGUBIdALJS
+ 5si8Z54VAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAfxJREFUOE9j+P//
+ P4Ofnx8GDgwMZAgJCREMDQ11AOIoIE6F0g4gcZA8SB8DHgMU4xKSk6Ys3th99Oqz9fdffTl+8/HbrYvW
+ bOsDiQMNUIQb4OPjw4CMfX19BaNi41PWHby68MiN14cevfl29snbb+dAGMTeceLmkujYhBSQOrALPD09
+ 0bHzxPlr+3ZfenHg6uOPJ2CaYfS1J59OTF+yYSJQnzPYAGdnZ3ScsO30gzUgA3Dhg5efbALqSwAbYGdn
+ h47z9115uQ+mGd0FIP6J22+PAvXlgw2wsLBAx6l7zj/cCDIAm2aQ2Kkbz3cA9aWCDTA0NETHnpPnrpi+
+ /+qrw/dffj2NbggwIM/NW7Z2LlCfJ9gABwcHsBdsbW0ZbGxsGMzNzVVc3Nyrj1y8t+/ms88oBjx7//3i
+ 5Zv3d1jb2JaoqamJYBhgbW0tDzSkeO3a9f81NLXbJ06fu/Txi3dH3n7+ee3pq/dH5y1YvFJDQ7NWUFBQ
+ S05ODpKQYC4AatRyc3Ov2bFjz39RUbFmFhYWLSAOA+JKIG6H0iC+GB8fHwOKAUDnWwQGBrcdOXLmv6Ki
+ Ug9QkSoQM+DCKAYA/e+dkJAy4eLFu//19AymATUZ49MMkkMxABhoJbduvfpvb+88j5WV1YWQZgwD9PT0
+ tERERFqAmmOI0YxhACggycUArdOzkqbxIJ4AAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAEUSURBVDhPY2CgBnBN9+yHYbc0z+NgdoarGLqYe6q7EVCs
+ DCTulu5RB7fbM8X3Y/LU0m/OyZ73wZKpnueABgWADIufEv87a0rJf7hhSZ4vYZZQw/EQM+Cmp3vGwb0A
+ 9ZZHpocesphLuocXUH07SA/cBSAnY3MiyPluaW4aIAPcgE4Hew+JjdUL//8z/MeFcfoZanI4yGnnrjP8
+ n76S4f+uYwz/8zogbBD+/JUBHpBQ9QEYXgA57+AZhv+hJRDNMAzigwyEhQXEa57HqesFWKgCE0g1WsIK
+ QObDvOuS6aWJ6QVgNIIVQEMcxAY5F2YAjA2Tp35CAtuU6mWO7GT7ensWULJG9wbehIScqGB5A10MxQBK
+ /AIAoo4O0fuXsPcAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ pgAADqYBh9ypbwAAAi1JREFUOE+lkV1o0lEYh1+/EEUICb0K68LMSPZvmH1RadtUpmaWSlAXIyxt1aib
+ YR+b/TGUDHYTYyUxGF4JdiUjgmRkgu5CtovdTEwcuASXGQRdv51zdINI6GMHHs7V8zu/877g9/uhD8dc
+ LtcdnU53Vq/Xg0QiAXpkMhkEn3XgRrwN16YbjH4y+Hy+kNPpBJVK9VSj0QRFIhH3TwFerzdgs9mC4XAY
+ O50OEvkWwfS3DTgqt9ttpAGlUgmbzS0UCARxuVx+7k9fYHKr1cJCocACMpkMZrNvcWWljmq1Oj4W+fQt
+ EPuS6DcDJjebTaxUKphMJrFcLmMiMYPz829wYSGL1epXHL40lbnysI7+cO2qd7IK4Ha7GVRuNBpMprVT
+ qRSS7ZCAOSYvLhZxc/MHWq3We/bxVSRUCAB0TRQ67Xq9zuRcLsdqb79M5Y2N70z2eDxHjf732KO7WwrZ
+ NUcGFSoWS7/JtVoHLRbLhMlkOnPKMQ0HhtLY45cAEAqFRkI4nX63U3t9fQu1Wu1djuMGjUYj7Bl8ScG9
+ ptc8AQCDSfjonoThfYdpAG1yWiqVRpaWVnFt7TMqFIrHSqXyhMFggIPHx0FyaIbCKwZmYScAb74CDMzB
+ B8d9GCFBYrHYTHjew+zYfwSWR24DXuAhPxSF6MkY5M1PAK0Pug22A/D6LODYC8jbJyDKjUJ0wA758yHA
+ yzHAi1EWgM4I4OgUoP1RN4DneaTnf2/YjUwf3XWDnxi88DTgdn3hAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ pgAADqYBh9ypbwAAAZZJREFUOE+lkksoRFEch3//yWYWtpZWHgs7ZEXcokkT7ty88sjGY2iiMNEY06Q8
+ I7JClNSQabIwsvJIZEOhyIqiCAvZUuPvHLc7TF2PmlNfZ/V95wmI0VJKMaxOEXaWdRwOxyd3RJKkMzGH
+ hWMg/ajcU/MlmgRyb4jWToiGTQNSDngRXfl7QFXVNEVROt7dbr612R7XgEIBJJ9jqEmXzQKGHIlEOBQK
+ XQSBg4BwDKKiWWA7QPnrc7RxeajxVjDrxWq1jnjFHSyKgMGPAUN+fejj8z31aagD+ynJCdAslr8DZrK/
+ DVByLH8HfpJ9ztjAaUoeuKgXmOvWmXeLc/UiecGT2P981cybS9kPcttyZSkbgdX0AnCxF2zz6IFJl850
+ O2jSRQP8fMydlbTYqpKnr5Gi8m6dAi7xg+2+2MCokyARTzl+f7HMLo1WnGVULH9nVy1ht6EQrA2CywbM
+ A/6sEuM7sBCDQsyY0FIRLreBq8bAFSO/B7h5Ftw0A3+mHeFqO7hhGlw/Ba6Z+F/g6PqN4wHxyNKNO/AB
+ NFrDjHczNdsAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACKSURBVDhPY2AYBeghoM3IyLgGB54OVCxGTJA5AQ1YD8JA
+ xTpQDRFQfgQxBugBFW8BYaBiPaiGKCg/ihgD9IGKd2LDQM36xBhgANS8H4SBij2A2ACI46Fiy4FsLkKG
+ GAEVHwVhoEIjqGJsYjjN8QNqPgPCQBUmUFXIYir4XGAFlHyIBxcQcv5IlAcAm4MjD8DlZQQAAAAASUVO
+ RK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAABgSURBVDhPY2AYBfhCQJuRkXENMgYq1iY1yHSABqwH4h5S
+ NcLU6wE1bwFydMk1IA1owAZyNTMANW8Fas4k1wAjoAFHgZoNyTIAqHkJEJ8BajYh1QAroIaHaBgkNgpw
+ hAAAm8EOmTkm1pMAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAADMSURBVDhPY2AYBfAQsJ/9zMN2zvOZhIIEpAakFkWdxZT7
+ HhaT750BYUIGwNSB9IDV6rVd8NBrv3Sm58bf/yCaGGy68ztELVAvg3Ll4TMT7vz/33j2z/+OK3/+N5//
+ +b/u1Pf/lUe//C/f//5/8a5X/3O2v/iftO3l/5Btb/+77vj0X3zt1//qu//8B+llkMja4SGWtRXsAhBN
+ DAa5AKQOpBfsDb74lR48McvPgDChMICpA+lBUcseONuDLXAOwVgAqQGpJWTRqDwJIQAAilGdHbgOJisA
+ AAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAEFSURBVDhPY2CgNqievPN/y9xj/8kyt2Xe8f83btwA44aZ
+ B0k3JDa/5z8MxBf2k25A5/xDcBc0TlpDmgHItsNckVA0AcWQpUd//E+vnv3fK7Lgf82U3agWYDMAJAYK
+ TJDiqJyO/6GpDf89wnL/57cs/7/k8DfiDABp9o0p+W/jHvXfwjkUzK6atAPTeyXd6//H5HUjArGg+39G
+ 9Zz/PlFF/03tA/6b2Pn/t/GIBrsEZxSnVs6AGxCV3f4/rrAPrBGEHXwS/ieXTcUfsMjhAGKDNIKcnVY5
+ 839Rx2rCsYJsAEizW3Dm/6z6BYQ1wvyEbIC9d/z/kq51xGsGGQIyABmTlR/orgkAcvMB8BYVXdkAAAAA
+ SUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAG2SURBVDhPY2AYWmCNhDzDKtEzDCtFPUh3+Hx+AYZlIhvS
+ 3pX/Z1gucoZhGSmGrGJgY1gsPE/nmP3TqEfZ/+Pvx/9mWAQ0hCjwn4GRYb5wq8JWo3sBNxL/e1/1+cWz
+ XO4Sw0IRH1T9swU9GGYLngFiVP/NFsgUWKZ8w603/J/9fvu//EsUrzHMFUpG1TwFqGm64BmQAhDNAOKD
+ wDQBH465Epfl58v/Vqs3/8e3QP4Ww3SBakyXT+I/4/M095fHhcj/EVcy/zAA+QwT+XKZpgqeFlps8kNx
+ k9F/7tnS94FiPQz1DEyYBvTyeTD08pyxvxn/U2mP8X+zEwE/QHypTfKfpXfo/OdbJPeEoYdvHlAzB+5w
+ awMa0s5zRuuU8zeJw5r/Nc5Y/hc/pPGff7HcK4ZW3nUM/cBoJAiauTwYmrjPSB9Q+iJ8VuU/+zbx94yN
+ PLsZWjilCeqFK4hg92AoYD/DukDgBWMZ2xGGcDZNYjSDAoYfiOWBWJfBiCmNIZ7pDIMWQyiQDzJACYil
+ gFgYiHmAmA2IGZENBnFAAQTypzhUsSSULQqkBYGYF4i5oJqZ0Q0gxpVY1QAAJuuF6gTRvEgAAAAASUVO
+ RK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAIOSURBVDhPrZI9SCNRFIWvY2RUAskQ8qOIFjbisoUSSJk0
+ Qpo0CzZiE5JO0cKAjcuyCxoDFmm0ELUyMQq7sqgY0kyhoEiC4h+M7WgRLFIs7DLs4tt7gvMgGqwcOPDm
+ 3XO+e+e9IXrvJ0/UvU00uUOUZx0/K4891N7sVyCKfe/o0MuhkFlNJq3fU1MCqiYSVnl42EQNnqaQHBd2
+ 3e6KmJ0Vf6anxZrfb6RV9RzC+mRkpPZrYkLsOp0VeBsgazxaob1d/5dKib8zM2K9p8f4QjS3SOSCvhKF
+ +X3nx+DgfTUeF7m2Nh0ZCdng7zviER8TiXoYnThQZkVt0wKRB5DDYLBWGhgwkZGAVaItIxy2sm53vTPC
+ D+PjryCYJKOqRsnrtZCRgGU+7ZtYTMwryjlGRmdALiORBghq39hz0NcnkJGALL9cRKMCRZhQsCFnQ0MS
+ YgOKXV0CGQlY4nH0YNDKtrYaGNMu2JCT/n4bMgdP0eOxkJEAJk8WfD5zX9NqOCgc2EvIaSBQh/xU1dqm
+ w2EiIwEZvpJMS4t+1dsrcp2d94BgEvsa7YPNaNpTWdMEvMg0/Auf+edIK0rl1usVh9xlhUdd4DOBsMbe
+ NYfhgbfp3/iJCymmb/CIustl3XEAwhp7qMHTLOzgTT/rQ4CvMEKUHiXaGyM6hbDGHmrs+cjiJSEjH4VX
+ TpaPhW97S2gELzL0H9Dj5tei7xUOAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUFJREFUOE+lk69L
+ Q1Ecxb//wmCra6uDlbXFwcJgYXVMXFkdD9y6BouGWRxM8BeiiGARFINJTFcwCApWMVisYvB4ztU3Bveu
+ +MLh8v2ezzn3vQfPAFgWZQrr4lnBsZmdmjUop1Pz4Z9iXvrU8wUKOYxG0Ek15gq89zkYzLyggLD7Hg7x
+ 2GziK0mgmVKJ5N57Pe+9djreCwr2Ce7R+Oj3cVOt4q3bhWbpqdXyu/t63e/EBgU0bIfGlMBLu43Lchl3
+ tRquKxXsFgo4KRYhT4zYaAEBmxDYJnhRKuEgl/M6yuehnTwx0YJ1GpvUmNAW4XPeesZwKu3kiREbPIGW
+ G7+Au2IwJnliFhXIcLcMp9K8YBd+xFXCDwyn0rzG26SYF7zCCsGEoWeW6NTMoEkxLyhgyJYZWmJYp+a0
+ IOYFBf/9IzP/jT+zZw/Woa9yPwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAoklEQVQ4T7XTywqCQBSA4ZlH
+ b92qR2id2UXJIiQiIsRN7lz6JtN/oIkpDhKjCh8O6LnCGOecGWJQsBT+JLDWzrBCgjU22GKHDDkOOGLu
+ uw4TGD78TUsgVdOeql/JJ+lAZt0HsxacTzijxAVX3HCfpAPZcF/VcXZg3o82gjorXT1QoUZDfIsuage+
+ ury1BAu/4Z+qT/5fhsFqgtgLNd5liu3gBRRIn3FPTkzqAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAoklEQVQ4T7WTywqDMBBFk093
+ 7da/qGJf+ECklFJK6abddemfxBNwithGSqLCYQKSOXMHoowxKoSgy1b8aaC1jmADKWSQwxZ2cIAjFFBB
+ LFOPGyh+/M1cA5e1RtCIZJUJbNb9KGvJWawt5xOc4QLXVSaQBTqtmG/BO1DD9yuC3fBX1sF6pz7gxf03
+ dF47ELutcw2SifUpVmrqjOD7oJZ7TL4T9ELIn+co5cQOAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAqklEQVQ4T7WTzQqCQBRG7zy6
+ 6x7Ah0gpLfohIiJEoha1a+muTe8wngkcJrUYxhQOjsp857vCiNZahjBosxHbAKVUBFNIIIUZzCGDBSxh
+ BRuYNK3dAOGDNz4BbesWwQ72cPAJ+NmmL8DMmjuzrll/WHk+wgmKURq0K79nda2sSzjDdZQG9g9/sV54
+ fxeRB1RBDdhoL5+AGKOx3hor9ye8IO8EhB6o/x2m0AY1iSqgdYRW23EAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABDElEQVQ4T2P4//8/AyWYIs0g
+ i+EGMDIyMuDC0sq2DCltb5DxfxCfaANABuvaFTJEVj+E4f8gNkkGgAzxyrkIw/9BbJINkNNPZLCKOQDC
+ /0E0ugGNQFtWA/FaIF4HxBuAeBMQbwXi7UDcA3KFjt8mEP4Pokl2AZeQDoOK22oQ/g+i0Q1YD7RhIxBv
+ htq6A0jvBuJ9sNgRUg5nUHJZC8L/QTQZLtBlUPfcAcL/QTS6ASC/Itt6EMg/AsQngPgMEF/hEzNlMAm7
+ wKAfeOI/iCbJBQxAoO2yhMEi6uZ/IH4AotEN6AfaArL1KMxWoJ6rQLwcpBkErGLuMtjGP3RwTH7+H0Sj
+ GEBuhqJeZiLXBQDC0LFONyaX7QAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABLUlEQVQ4T2P4//8/AyUYrpmR
+ kZEBHzZ2KWdIbX8Lw/9BbJDFRBsAMjym7jEM/wexSTZA0yqHIaDoOgj/B9HoBjQCbVkNxGuBeB0QbwDi
+ TUC8FYi3A3GPrF48g03cQQanlBP/QTTJLtBw7GYwDd/1H4gfgGh0A9YDbdkIxJuhtu4A0ruBeB8scNXs
+ uxj0A7c6aPls+A+iSXYBAxBoem9mUHVfC6bRDQD5FdnWg0D+ESA+AcRngPgKp5Aug7LrBgcll7X/QTRJ
+ LgDZLmPWCbR9638gfgCi0Q3oB9oCsvUozFagnqtAvBykGQTUPLYzaHjtZtD2PfgfRBN0AUwjiOYTM2Uw
+ Dj0Pw/9BbJIMsI69y4CE/4PYRBugaFTK4Jj8Ehn/B/FRDCA3R1KUlUGWAgAiG3UaYBp/hAAAAABJRU5E
+ rkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABDUlEQVQ4T2P4//8/AyWYIs0g
+ i+EGMDIyNgLxaiBeC8TrgHgDEG8C4q1AvB2Ie/QdihniG587pLS9+Q+i0Q1gACrCi51jVjBEVj/8D8QP
+ QDS6AeuBBmwE4s1QW3cA6d1AvA9msGPUMoagkpsMXjkX/4Nokl0gIGHIYBVzAIT/g2h0A0B+Rbb1IJB/
+ BIhPAPEZIL7CAAQ6fptA+D+IJskFIM2cgtoMKm6rQfg/iEY3oB9oC8jWozBbgXquAvFykGYQkDJuZlBy
+ WQvC/0E0QRfANIJoLmF9BnXPHTD8H8QmyQD9wBMMSPg/iE20ATK6uQwWUTeR8X8Qn2gDHJOfM6Dh/yA+
+ igHkZijqZSZyXQAA4IG1TpHFZ2gAAAAASUVORK5CYII=
+
+
+
+ ..\icons\notification-counter-01.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-02.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-03.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-04.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-05.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-06.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-07.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-08.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-09.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-10.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-11.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-12.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-13.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-14.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-15.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-17.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-18.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-19.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-20-plus.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\notification-counter-20.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\balloon.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\icons\resize.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ 551, 17
+
+
+ 17, 54
+
+
+ 662, 17
+
+
+ 452, 17
+
+
+ 116, 54
+
+
+ 17, 17
+
\ No newline at end of file
diff --git a/src/Greenshot/Forms/LanguageDialog.Designer.cs b/Greenshot/Forms/LanguageDialog.Designer.cs
similarity index 92%
rename from src/Greenshot/Forms/LanguageDialog.Designer.cs
rename to Greenshot/Forms/LanguageDialog.Designer.cs
index 22df57775..20d61cbc3 100644
--- a/src/Greenshot/Forms/LanguageDialog.Designer.cs
+++ b/Greenshot/Forms/LanguageDialog.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
namespace Greenshot.Forms {
partial class LanguageDialog {
diff --git a/Greenshot/Forms/LanguageDialog.cs b/Greenshot/Forms/LanguageDialog.cs
new file mode 100644
index 000000000..c043017da
--- /dev/null
+++ b/Greenshot/Forms/LanguageDialog.cs
@@ -0,0 +1,96 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Threading;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace Greenshot.Forms {
+ ///
+ /// Description of LanguageDialog.
+ ///
+ public partial class LanguageDialog : Form {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(LanguageDialog));
+ private static LanguageDialog uniqueInstance;
+ private bool properOkPressed;
+
+ private LanguageDialog() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ Icon = GreenshotResources.getGreenshotIcon();
+ Load += FormLoad;
+ FormClosing += PreventFormClose;
+ }
+
+ private void PreventFormClose(object sender, FormClosingEventArgs e) {
+ if(!properOkPressed) {
+ e.Cancel = true;
+ }
+ }
+
+ public string SelectedLanguage {
+ get { return comboBoxLanguage.SelectedValue.ToString(); }
+ }
+
+ protected void FormLoad(object sender, EventArgs e) {
+ // Initialize the Language ComboBox
+ comboBoxLanguage.DisplayMember = "Description";
+ comboBoxLanguage.ValueMember = "Ietf";
+
+ // Set datasource last to prevent problems
+ // See: http://www.codeproject.com/KB/database/scomlistcontrolbinding.aspx?fid=111644
+ comboBoxLanguage.DataSource = Language.SupportedLanguages;
+
+ if (Language.CurrentLanguage != null) {
+ LOG.DebugFormat("Selecting {0}", Language.CurrentLanguage);
+ comboBoxLanguage.SelectedValue = Language.CurrentLanguage;
+ } else {
+ comboBoxLanguage.SelectedValue = Thread.CurrentThread.CurrentUICulture.Name;
+ }
+
+ // Close again when there is only one language, this shows the form briefly!
+ // But the use-case is not so interesting, only happens once, to invest a lot of time here.
+ if (Language.SupportedLanguages.Count == 1) {
+ comboBoxLanguage.SelectedValue = Language.SupportedLanguages[0].Ietf;
+ Language.CurrentLanguage = SelectedLanguage;
+ properOkPressed = true;
+ Close();
+ }
+ }
+
+ private void BtnOKClick(object sender, EventArgs e) {
+ properOkPressed = true;
+ // Fix for Bug #3431100
+ Language.CurrentLanguage = SelectedLanguage;
+ Close();
+ }
+
+ public static LanguageDialog GetInstance() {
+ if(uniqueInstance == null) {
+ uniqueInstance = new LanguageDialog();
+ }
+ return uniqueInstance;
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/MainForm.Designer.cs b/Greenshot/Forms/MainForm.Designer.cs
similarity index 72%
rename from src/Greenshot/Forms/MainForm.Designer.cs
rename to Greenshot/Forms/MainForm.Designer.cs
index b558bf4f9..d77a39c10 100644
--- a/src/Greenshot/Forms/MainForm.Designer.cs
+++ b/Greenshot/Forms/MainForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Forms {
+namespace Greenshot {
partial class MainForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -53,30 +50,32 @@ namespace Greenshot.Forms {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.contextmenu_capturearea = new GreenshotToolStripMenuItem();
- this.contextmenu_capturelastregion = new GreenshotToolStripMenuItem();
- this.contextmenu_capturewindow = new GreenshotToolStripMenuItem();
- this.contextmenu_capturefullscreen = new GreenshotToolStripMenuItem();
- this.contextmenu_captureie = new GreenshotToolStripMenuItem();
- this.contextmenu_capturewindowfromlist = new GreenshotToolStripMenuItem();
- this.contextmenu_captureiefromlist = new GreenshotToolStripMenuItem();
- this.contextmenu_captureclipboard = new GreenshotToolStripMenuItem();
- this.contextmenu_openfile = new GreenshotToolStripMenuItem();
- this.contextmenu_openrecentcapture = new GreenshotToolStripMenuItem();
- this.contextmenu_quicksettings = new GreenshotToolStripMenuItem();
- this.contextmenu_settings = new GreenshotToolStripMenuItem();
- this.contextmenu_help = new GreenshotToolStripMenuItem();
- this.contextmenu_donate = new GreenshotToolStripMenuItem();
- this.contextmenu_about = new GreenshotToolStripMenuItem();
- this.contextmenu_exit = new GreenshotToolStripMenuItem();
- this.toolStripListCaptureSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripOtherSourcesSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripOpenFolderSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripPluginSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripMiscSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_capturearea = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_capturelastregion = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_capturewindow = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_capturefullscreen = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_captureie = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripListCaptureSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_capturewindowfromlist = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_captureiefromlist = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripOtherSourcesSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_captureclipboard = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_openfile = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripOpenFolderSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_openrecentcapture = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripPluginSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_quicksettings = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_settings = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.toolStripMiscSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.contextmenu_help = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_donate = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.contextmenu_about = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
this.toolStripCloseSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.contextMenu.SuspendLayout();
- this.SuspendLayout();
+ this.contextmenu_exit = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem();
+ this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
+ this.backgroundWorkerTimer = new System.Windows.Forms.Timer(this.components);
+ this.contextMenu.SuspendLayout();
+ this.SuspendLayout();
//
// contextMenu
//
@@ -106,7 +105,7 @@ namespace Greenshot.Forms {
this.contextMenu.Name = "contextMenu";
this.contextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.ContextMenuClosing);
this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ContextMenuOpening);
- this.contextMenu.Renderer = new Greenshot.Controls.ContextMenuToolStripProfessionalRenderer(this);
+ this.contextMenu.Renderer = new Greenshot.Controls.ContextMenuToolStripProfessionalRenderer();
//
// contextmenu_capturearea
//
@@ -123,7 +122,7 @@ namespace Greenshot.Forms {
this.contextmenu_capturelastregion.Name = "contextmenu_capturelastregion";
this.contextmenu_capturelastregion.ShortcutKeyDisplayString = "Shift + Print";
this.contextmenu_capturelastregion.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_capturelastregion.Click += new System.EventHandler(this.Contextmenu_CaptureLastRegionClick);
+ this.contextmenu_capturelastregion.Click += new System.EventHandler(this.Contextmenu_capturelastregionClick);
//
// contextmenu_capturewindow
//
@@ -131,7 +130,7 @@ namespace Greenshot.Forms {
this.contextmenu_capturewindow.Name = "contextmenu_capturewindow";
this.contextmenu_capturewindow.ShortcutKeyDisplayString = "Alt + Print";
this.contextmenu_capturewindow.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_capturewindow.Click += new System.EventHandler(this.Contextmenu_CaptureWindow_Click);
+ this.contextmenu_capturewindow.Click += new System.EventHandler(this.Contextmenu_capturewindow_Click);
//
// contextmenu_capturefullscreen
//
@@ -145,7 +144,7 @@ namespace Greenshot.Forms {
this.contextmenu_captureie.Name = "contextmenu_captureie";
this.contextmenu_captureie.ShortcutKeyDisplayString = "Ctrl + Shift + Print";
this.contextmenu_captureie.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_captureie.Click += new System.EventHandler(this.Contextmenu_CaptureIe_Click);
+ this.contextmenu_captureie.Click += new System.EventHandler(this.Contextmenu_captureie_Click);
//
// toolStripListCaptureSeparator
//
@@ -211,7 +210,7 @@ namespace Greenshot.Forms {
this.contextmenu_settings.Image = ((System.Drawing.Image)(resources.GetObject("contextmenu_settings.Image")));
this.contextmenu_settings.Name = "contextmenu_settings";
this.contextmenu_settings.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_settings.Click += new System.EventHandler(this.Contextmenu_SettingsClick);
+ this.contextmenu_settings.Click += new System.EventHandler(this.Contextmenu_settingsClick);
//
// toolStripMiscSeparator
//
@@ -223,20 +222,20 @@ namespace Greenshot.Forms {
this.contextmenu_help.Image = ((System.Drawing.Image)(resources.GetObject("contextmenu_help.Image")));
this.contextmenu_help.Name = "contextmenu_help";
this.contextmenu_help.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_help.Click += new System.EventHandler(this.Contextmenu_HelpClick);
+ this.contextmenu_help.Click += new System.EventHandler(this.Contextmenu_helpClick);
//
// contextmenu_donate
//
this.contextmenu_donate.Image = ((System.Drawing.Image)(resources.GetObject("contextmenu_donate.Image")));
this.contextmenu_donate.Name = "contextmenu_donate";
this.contextmenu_donate.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_donate.Click += new System.EventHandler(this.Contextmenu_DonateClick);
+ this.contextmenu_donate.Click += new System.EventHandler(this.Contextmenu_donateClick);
//
// contextmenu_about
//
this.contextmenu_about.Name = "contextmenu_about";
this.contextmenu_about.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_about.Click += new System.EventHandler(this.Contextmenu_AboutClick);
+ this.contextmenu_about.Click += new System.EventHandler(this.Contextmenu_aboutClick);
//
// toolStripCloseSeparator
//
@@ -248,15 +247,20 @@ namespace Greenshot.Forms {
this.contextmenu_exit.Image = ((System.Drawing.Image)(resources.GetObject("contextmenu_exit.Image")));
this.contextmenu_exit.Name = "contextmenu_exit";
this.contextmenu_exit.Size = new System.Drawing.Size(170, 22);
- this.contextmenu_exit.Click += new System.EventHandler(this.Contextmenu_ExitClick);
+ this.contextmenu_exit.Click += new System.EventHandler(this.Contextmenu_exitClick);
//
// notifyIcon
//
- this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.notifyIcon.ContextMenuStrip = this.contextMenu;
this.notifyIcon.Text = "Greenshot";
this.notifyIcon.MouseUp += new System.Windows.Forms.MouseEventHandler(this.NotifyIconClickTest);
- //
+ //
+ // backgroundWorkerTimer
+ //
+ this.backgroundWorkerTimer.Enabled = true;
+ this.backgroundWorkerTimer.Interval = 300000;
+ this.backgroundWorkerTimer.Tick += new System.EventHandler(this.BackgroundWorkerTimerTick);
+ //
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -273,29 +277,30 @@ namespace Greenshot.Forms {
this.contextMenu.ResumeLayout(false);
this.ResumeLayout(false);
}
- private GreenshotToolStripMenuItem contextmenu_captureiefromlist;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureiefromlist;
private System.Windows.Forms.ToolStripSeparator toolStripOtherSourcesSeparator;
- private GreenshotToolStripMenuItem contextmenu_capturewindowfromlist;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturewindowfromlist;
private System.Windows.Forms.ToolStripSeparator toolStripListCaptureSeparator;
- private GreenshotToolStripMenuItem contextmenu_openrecentcapture;
- private GreenshotToolStripMenuItem contextmenu_captureie;
- private GreenshotToolStripMenuItem contextmenu_donate;
- private GreenshotToolStripMenuItem contextmenu_openfile;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_openrecentcapture;
+ private System.Windows.Forms.Timer backgroundWorkerTimer;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureie;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_donate;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_openfile;
private System.Windows.Forms.ToolStripSeparator toolStripPluginSeparator;
- private GreenshotToolStripMenuItem contextmenu_captureclipboard;
- private GreenshotToolStripMenuItem contextmenu_quicksettings;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureclipboard;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_quicksettings;
private System.Windows.Forms.ToolStripSeparator toolStripMiscSeparator;
- private GreenshotToolStripMenuItem contextmenu_help;
- private GreenshotToolStripMenuItem contextmenu_capturewindow;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_help;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturewindow;
private System.Windows.Forms.ToolStripSeparator toolStripOpenFolderSeparator;
- private GreenshotToolStripMenuItem contextmenu_about;
- private GreenshotToolStripMenuItem contextmenu_capturefullscreen;
- private GreenshotToolStripMenuItem contextmenu_capturelastregion;
- private GreenshotToolStripMenuItem contextmenu_capturearea;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_about;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturefullscreen;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturelastregion;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturearea;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ToolStripSeparator toolStripCloseSeparator;
- private GreenshotToolStripMenuItem contextmenu_exit;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_exit;
private System.Windows.Forms.ContextMenuStrip contextMenu;
- private GreenshotToolStripMenuItem contextmenu_settings;
+ private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_settings;
}
}
diff --git a/Greenshot/Forms/MainForm.cs b/Greenshot/Forms/MainForm.cs
new file mode 100644
index 000000000..23bb8960f
--- /dev/null
+++ b/Greenshot/Forms/MainForm.cs
@@ -0,0 +1,1468 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using Greenshot.Experimental;
+using Greenshot.Forms;
+using Greenshot.Help;
+using Greenshot.Helpers;
+using Greenshot.Plugin;
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using Greenshot.Destinations;
+using Greenshot.Drawing;
+using log4net;
+using Timer = System.Timers.Timer;
+
+namespace Greenshot {
+ ///
+ /// Description of MainForm.
+ ///
+ public partial class MainForm : BaseForm {
+ private static ILog LOG;
+ private static ResourceMutex _applicationMutex;
+ private static CoreConfiguration _conf;
+ public static string LogFileLocation;
+
+ public static void Start(string[] arguments) {
+ var filesToOpen = new List();
+
+ // Set the Thread name, is better than "1"
+ Thread.CurrentThread.Name = Application.ProductName;
+
+ // Init Log4NET
+ LogFileLocation = LogHelper.InitializeLog4Net();
+ // Get logger
+ LOG = LogManager.GetLogger(typeof(MainForm));
+
+ Application.ThreadException += Application_ThreadException;
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+
+ // Initialize the IniConfig
+ IniConfig.Init();
+
+ // Log the startup
+ LOG.Info("Starting: " + EnvironmentInfo.EnvironmentToString(false));
+
+ // Read configuration
+ _conf = IniConfig.GetIniSection();
+ try {
+ // Fix for Bug 2495900, Multi-user Environment
+ // check whether there's an local instance running already
+ _applicationMutex = ResourceMutex.Create("F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08", "Greenshot", false);
+
+ var isAlreadyRunning = !_applicationMutex.IsLocked;
+
+ if (arguments.Length > 0 && LOG.IsDebugEnabled) {
+ StringBuilder argumentString = new StringBuilder();
+ foreach (string argument in arguments)
+ {
+ argumentString.Append("[").Append(argument).Append("] ");
+ }
+ LOG.Debug("Greenshot arguments: " + argumentString);
+ }
+
+ for(int argumentNr = 0; argumentNr < arguments.Length; argumentNr++) {
+ string argument = arguments[argumentNr];
+ // Help
+ if (argument.ToLower().Equals("/help") || argument.ToLower().Equals("/h") || argument.ToLower().Equals("/?")) {
+ // Try to attach to the console
+ bool attachedToConsole = Kernel32.AttachConsole(Kernel32.ATTACHCONSOLE_ATTACHPARENTPROCESS);
+ // If attach didn't work, open a console
+ if (!attachedToConsole) {
+ Kernel32.AllocConsole();
+ }
+ var helpOutput = new StringBuilder();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("Greenshot commandline options:");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t/help");
+ helpOutput.AppendLine("\t\tThis help.");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t/exit");
+ helpOutput.AppendLine("\t\tTries to close all running instances.");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t/reload");
+ helpOutput.AppendLine("\t\tReload the configuration of Greenshot.");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t/language [language code]");
+ helpOutput.AppendLine("\t\tSet the language of Greenshot, e.g. greenshot /language en-US.");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t/inidirectory [directory]");
+ helpOutput.AppendLine("\t\tSet the directory where the greenshot.ini should be stored & read.");
+ helpOutput.AppendLine();
+ helpOutput.AppendLine();
+ helpOutput.AppendLine("\t[filename]");
+ helpOutput.AppendLine("\t\tOpen the bitmap files in the running Greenshot instance or start a new instance");
+ Console.WriteLine(helpOutput.ToString());
+
+ // If attach didn't work, wait for key otherwise the console will close to quickly
+ if (!attachedToConsole) {
+ Console.ReadKey();
+ }
+ FreeMutex();
+ return;
+ }
+
+ if (argument.ToLower().Equals("/exit")) {
+ // unregister application on uninstall (allow uninstall)
+ try {
+ LOG.Info("Sending all instances the exit command.");
+ // Pass Exit to running instance, if any
+ SendData(new CopyDataTransport(CommandEnum.Exit));
+ } catch (Exception e) {
+ LOG.Warn("Exception by exit.", e);
+ }
+ FreeMutex();
+ return;
+ }
+
+ // Reload the configuration
+ if (argument.ToLower().Equals("/reload")) {
+ // Modify configuration
+ LOG.Info("Reloading configuration!");
+ // Update running instances
+ SendData(new CopyDataTransport(CommandEnum.ReloadConfig));
+ FreeMutex();
+ return;
+ }
+
+ // Stop running
+ if (argument.ToLower().Equals("/norun")) {
+ // Make an exit possible
+ FreeMutex();
+ return;
+ }
+
+ // Language
+ if (argument.ToLower().Equals("/language")) {
+ _conf.Language = arguments[++argumentNr];
+ IniConfig.Save();
+ continue;
+ }
+
+ // Setting the INI-directory
+ if (argument.ToLower().Equals("/inidirectory")) {
+ IniConfig.IniDirectory = arguments[++argumentNr];
+ continue;
+ }
+
+ // Files to open
+ filesToOpen.Add(argument);
+ }
+
+ // Finished parsing the command line arguments, see if we need to do anything
+ CopyDataTransport transport = new CopyDataTransport();
+ if (filesToOpen.Count > 0) {
+ foreach(string fileToOpen in filesToOpen) {
+ transport.AddCommand(CommandEnum.OpenFile, fileToOpen);
+ }
+ }
+
+ if (isAlreadyRunning) {
+ // We didn't initialize the language yet, do it here just for the message box
+ if (filesToOpen.Count > 0) {
+ SendData(transport);
+ } else {
+ StringBuilder instanceInfo = new StringBuilder();
+ bool matchedThisProcess = false;
+ int index = 1;
+ int currentProcessId;
+ using (Process currentProcess = Process.GetCurrentProcess()) {
+ currentProcessId = currentProcess.Id;
+ }
+ foreach (Process greenshotProcess in Process.GetProcessesByName("greenshot")) {
+ try {
+ instanceInfo.Append(index++ + ": ").AppendLine(Kernel32.GetProcessPath(greenshotProcess.Id));
+ if (currentProcessId == greenshotProcess.Id) {
+ matchedThisProcess = true;
+ }
+ } catch (Exception ex) {
+ LOG.Debug(ex);
+ }
+ greenshotProcess.Dispose();
+ }
+ if (!matchedThisProcess) {
+ using (Process currentProcess = Process.GetCurrentProcess()) {
+ instanceInfo.Append(index + ": ").AppendLine(Kernel32.GetProcessPath(currentProcess.Id));
+ }
+ }
+
+ // A dirty fix to make sure the messagebox is visible as a Greenshot window on the taskbar
+ using (Form dummyForm = new Form()) {
+ dummyForm.Icon = GreenshotResources.getGreenshotIcon();
+ dummyForm.ShowInTaskbar = true;
+ dummyForm.FormBorderStyle = FormBorderStyle.None;
+ dummyForm.Location = new Point(int.MinValue, int.MinValue);
+ dummyForm.Load += delegate { dummyForm.Size = Size.Empty; };
+ dummyForm.Show();
+ MessageBox.Show(dummyForm, Language.GetString(LangKey.error_multipleinstances) + "\r\n" + instanceInfo, Language.GetString(LangKey.error), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ }
+ }
+ FreeMutex();
+ Application.Exit();
+ return;
+ }
+
+ // BUG-1809: Add message filter, to filter out all the InputLangChanged messages which go to a target control with a handle > 32 bit.
+ Application.AddMessageFilter(new WmInputLangChangeRequestFilter());
+
+ // From here on we continue starting Greenshot
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+
+ // if language is not set, show language dialog
+ if(string.IsNullOrEmpty(_conf.Language)) {
+ LanguageDialog languageDialog = LanguageDialog.GetInstance();
+ languageDialog.ShowDialog();
+ _conf.Language = languageDialog.SelectedLanguage;
+ IniConfig.Save();
+ }
+
+ // Check if it's the first time launch?
+ if(_conf.IsFirstLaunch) {
+ _conf.IsFirstLaunch = false;
+ IniConfig.Save();
+ transport.AddCommand(CommandEnum.FirstLaunch);
+ }
+ // Should fix BUG-1633
+ Application.DoEvents();
+ _instance = new MainForm(transport);
+ Application.Run();
+ } catch(Exception ex) {
+ LOG.Error("Exception in startup.", ex);
+ Application_ThreadException(ActiveForm, new ThreadExceptionEventArgs(ex));
+ }
+ }
+
+ ///
+ /// Send DataTransport Object via Window-messages
+ ///
+ /// DataTransport with data for a running instance
+ private static void SendData(CopyDataTransport dataTransport) {
+ string appName = Application.ProductName;
+ CopyData copyData = new CopyData();
+ copyData.Channels.Add(appName);
+ copyData.Channels[appName].Send(dataTransport);
+ }
+
+ private static void FreeMutex() {
+ // Remove the application mutex
+ if (_applicationMutex != null) {
+ try {
+ _applicationMutex.Dispose();
+ _applicationMutex = null;
+ } catch (Exception ex) {
+ LOG.Error("Error releasing Mutex!", ex);
+ }
+ }
+ }
+
+ private static MainForm _instance;
+ public static MainForm Instance => _instance;
+
+ private readonly CopyData _copyData;
+
+ // Thumbnail preview
+ private ThumbnailForm _thumbnailForm;
+ // Make sure we have only one settings form
+ private SettingsForm _settingsForm;
+ // Make sure we have only one about form
+ private AboutForm _aboutForm;
+ // Timer for the double click test
+ private readonly Timer _doubleClickTimer = new Timer();
+
+ public NotifyIcon NotifyIcon => notifyIcon;
+
+ public MainForm(CopyDataTransport dataTransport) {
+ _instance = this;
+
+ // Factory for surface objects
+ ImageHelper.SurfaceFactory = () => new Surface();
+
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ try {
+ InitializeComponent();
+ } catch (ArgumentException ex) {
+ // Added for Bug #1420, this doesn't solve the issue but maybe the user can do something with it.
+ ex.Data.Add("more information here", "http://support.microsoft.com/kb/943140");
+ throw;
+ }
+ notifyIcon.Icon = GreenshotResources.getGreenshotIcon();
+
+ // Disable access to the settings, for feature #3521446
+ contextmenu_settings.Visible = !_conf.DisableSettings;
+
+ // Make sure all hotkeys pass this window!
+ HotkeyControl.RegisterHotkeyHwnd(Handle);
+ RegisterHotkeys();
+
+ new ToolTip();
+
+ UpdateUi();
+
+ // This forces the registration of all destinations inside Greenshot itself.
+ DestinationHelper.GetAllDestinations();
+ // This forces the registration of all processors inside Greenshot itself.
+ ProcessorHelper.GetAllProcessors();
+
+ // Load all the plugins
+ PluginHelper.Instance.LoadPlugins();
+
+ // Check destinations, remove all that don't exist
+ foreach(string destination in _conf.OutputDestinations.ToArray()) {
+ if (DestinationHelper.GetDestination(destination) == null) {
+ _conf.OutputDestinations.Remove(destination);
+ }
+ }
+
+ // we should have at least one!
+ if (_conf.OutputDestinations.Count == 0) {
+ _conf.OutputDestinations.Add(EditorDestination.DESIGNATION);
+ }
+ if (_conf.DisableQuickSettings) {
+ contextmenu_quicksettings.Visible = false;
+ } else {
+ // Do after all plugins & finding the destination, otherwise they are missing!
+ InitializeQuickSettingsMenu();
+ }
+ SoundHelper.Initialize();
+
+ coreConfiguration.PropertyChanged += OnIconSizeChanged;
+ OnIconSizeChanged(this, new PropertyChangedEventArgs("IconSize"));
+
+ // Set the Greenshot icon visibility depending on the configuration. (Added for feature #3521446)
+ // Setting it to true this late prevents Problems with the context menu
+ notifyIcon.Visible = !_conf.HideTrayicon;
+
+ // Make sure we never capture the mainform
+ WindowDetails.RegisterIgnoreHandle(Handle);
+
+ // Create a new instance of the class: copyData = new CopyData();
+ _copyData = new CopyData();
+
+ // Assign the handle:
+ _copyData.AssignHandle(Handle);
+ // Create the channel to send on:
+ _copyData.Channels.Add("Greenshot");
+ // Hook up received event:
+ _copyData.CopyDataReceived += CopyDataDataReceived;
+
+ if (dataTransport != null) {
+ HandleDataTransport(dataTransport);
+ }
+ // Make Greenshot use less memory after startup
+ if (_conf.MinimizeWorkingSetSize) {
+ PsAPI.EmptyWorkingSet();
+ }
+ }
+
+ ///
+ /// DataReceivedEventHandler
+ ///
+ ///
+ ///
+ private void CopyDataDataReceived(object sender, CopyDataReceivedEventArgs copyDataReceivedEventArgs) {
+ // Cast the data to the type of object we sent:
+ var dataTransport = (CopyDataTransport)copyDataReceivedEventArgs.Data;
+ HandleDataTransport(dataTransport);
+ }
+
+ private void BalloonTipClicked(object sender, EventArgs e) {
+ try {
+ ShowSetting();
+ } finally {
+ BalloonTipClosed(sender, e);
+ }
+ }
+
+ private void BalloonTipClosed(object sender, EventArgs e) {
+ notifyIcon.BalloonTipClicked -= BalloonTipClicked;
+ notifyIcon.BalloonTipClosed -= BalloonTipClosed;
+ }
+
+ private void HandleDataTransport(CopyDataTransport dataTransport) {
+ foreach(KeyValuePair command in dataTransport.Commands) {
+ LOG.Debug("Data received, Command = " + command.Key + ", Data: " + command.Value);
+ switch(command.Key) {
+ case CommandEnum.Exit:
+ LOG.Info("Exit requested");
+ Exit();
+ break;
+ case CommandEnum.FirstLaunch:
+ LOG.Info("FirstLaunch: Created new configuration, showing balloon.");
+ try {
+ notifyIcon.BalloonTipClicked += BalloonTipClicked;
+ notifyIcon.BalloonTipClosed += BalloonTipClosed;
+ notifyIcon.ShowBalloonTip(2000, "Greenshot", Language.GetFormattedString(LangKey.tooltip_firststart, HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.RegionHotkey)), ToolTipIcon.Info);
+ } catch (Exception ex) {
+ LOG.Warn("Exception while showing first launch: ", ex);
+ }
+ break;
+ case CommandEnum.ReloadConfig:
+ LOG.Info("Reload requested");
+ try {
+ IniConfig.Reload();
+ Invoke((MethodInvoker) delegate {
+ // Even update language when needed
+ UpdateUi();
+ // Update the hotkey
+ // Make sure the current hotkeys are disabled
+ HotkeyControl.UnregisterHotkeys();
+ RegisterHotkeys();
+ });
+ } catch (Exception ex) {
+ LOG.Warn("Exception while reloading configuration: ", ex);
+ }
+ break;
+ case CommandEnum.OpenFile:
+ string filename = command.Value;
+ LOG.InfoFormat("Open file requested: {0}", filename);
+ if (File.Exists(filename)) {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureFile(filename);
+ });
+ } else {
+ LOG.Warn("No such file: " + filename);
+ }
+ break;
+ default:
+ LOG.Error("Unknown command!");
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Main context menu
+ ///
+ public ContextMenuStrip MainMenu => contextMenu;
+
+ protected override void WndProc(ref Message m) {
+ if (HotkeyControl.HandleMessages(ref m)) {
+ return;
+ }
+ // BUG-1809 prevention, filter the InputLangChange messages
+ if (WmInputLangChangeRequestFilter.PreFilterMessageExternal(ref m))
+ {
+ return;
+ }
+ base.WndProc(ref m);
+ }
+
+ #region hotkeys
+
+ ///
+ /// Helper method to cleanly register a hotkey
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static bool RegisterHotkey(StringBuilder failedKeys, string functionName, string hotkeyString, HotKeyHandler handler) {
+ Keys modifierKeyCode = HotkeyControl.HotkeyModifiersFromString(hotkeyString);
+ Keys virtualKeyCode = HotkeyControl.HotkeyFromString(hotkeyString);
+ if (!Keys.None.Equals(virtualKeyCode)) {
+ if (HotkeyControl.RegisterHotKey(modifierKeyCode, virtualKeyCode, handler) < 0) {
+ LOG.DebugFormat("Failed to register {0} to hotkey: {1}", functionName, hotkeyString);
+ if (failedKeys.Length > 0) {
+ failedKeys.Append(", ");
+ }
+ failedKeys.Append(hotkeyString);
+ return false;
+ }
+ LOG.DebugFormat("Registered {0} to hotkey: {1}", functionName, hotkeyString);
+ } else {
+ LOG.InfoFormat("Skipping hotkey registration for {0}, no hotkey set!", functionName);
+ }
+ return true;
+ }
+
+ private static bool RegisterWrapper(StringBuilder failedKeys, string functionName, string configurationKey, HotKeyHandler handler, bool ignoreFailedRegistration) {
+ IniValue hotkeyValue = _conf.Values[configurationKey];
+ try {
+ bool success = RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
+ if (!success && ignoreFailedRegistration) {
+ LOG.DebugFormat("Ignoring failed hotkey registration for {0}, with value '{1}', resetting to 'None'.", functionName, hotkeyValue);
+ _conf.Values[configurationKey].Value = Keys.None.ToString();
+ _conf.IsDirty = true;
+ }
+ return success;
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ LOG.WarnFormat("Restoring default hotkey for {0}, stored under {1} from '{2}' to '{3}'", functionName, configurationKey, hotkeyValue.Value, hotkeyValue.Attributes.DefaultValue);
+ // when getting an exception the key wasn't found: reset the hotkey value
+ hotkeyValue.UseValueOrDefault(null);
+ hotkeyValue.ContainingIniSection.IsDirty = true;
+ return RegisterHotkey(failedKeys, functionName, hotkeyValue.Value.ToString(), handler);
+ }
+ }
+
+ ///
+ /// Fix icon reference
+ ///
+ ///
+ ///
+ private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) {
+ if (e.PropertyName == "IconSize") {
+ contextMenu.ImageScalingSize = coreConfiguration.IconSize;
+ string ieExePath = PluginUtils.GetExePath("iexplore.exe");
+ if (!string.IsNullOrEmpty(ieExePath)) {
+ contextmenu_captureie.Image = PluginUtils.GetCachedExeIcon(ieExePath, 0);
+ }
+ }
+ }
+
+ ///
+ /// Registers all hotkeys as configured, displaying a dialog in case of hotkey conflicts with other tools.
+ ///
+ /// Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).
+ public static bool RegisterHotkeys() {
+ return RegisterHotkeys(false);
+ }
+
+ ///
+ /// Registers all hotkeys as configured, displaying a dialog in case of hotkey conflicts with other tools.
+ ///
+ /// if true, a failed hotkey registration will not be reported to the user - the hotkey will simply not be registered
+ /// Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).
+ private static bool RegisterHotkeys(bool ignoreFailedRegistration) {
+ if (_instance == null) {
+ return false;
+ }
+ bool success = true;
+ StringBuilder failedKeys = new StringBuilder();
+
+ if (!RegisterWrapper(failedKeys, "CaptureRegion", "RegionHotkey", _instance.CaptureRegion, ignoreFailedRegistration)) {
+ success = false;
+ }
+ if (!RegisterWrapper(failedKeys, "CaptureWindow", "WindowHotkey", _instance.CaptureWindow, ignoreFailedRegistration)) {
+ success = false;
+ }
+ if (!RegisterWrapper(failedKeys, "CaptureFullScreen", "FullscreenHotkey", _instance.CaptureFullScreen, ignoreFailedRegistration)) {
+ success = false;
+ }
+ if (!RegisterWrapper(failedKeys, "CaptureLastRegion", "LastregionHotkey", _instance.CaptureLastRegion, ignoreFailedRegistration)) {
+ success = false;
+ }
+ if (_conf.IECapture) {
+ if (!RegisterWrapper(failedKeys, "CaptureIE", "IEHotkey", _instance.CaptureIE, ignoreFailedRegistration)) {
+ success = false;
+ }
+ }
+
+ if (!success) {
+ if (!ignoreFailedRegistration) {
+ success = HandleFailedHotkeyRegistration(failedKeys.ToString());
+ } else {
+ // if failures have been ignored, the config has probably been updated
+ if (_conf.IsDirty) {
+ IniConfig.Save();
+ }
+ }
+ }
+ return success || ignoreFailedRegistration;
+ }
+
+ ///
+ /// Check if OneDrive is blocking hotkeys
+ ///
+ /// true if onedrive has hotkeys turned on
+ private static bool IsOneDriveBlockingHotkey()
+ {
+ if (!Environment.OSVersion.IsWindows10())
+ {
+ return false;
+ }
+ var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ var oneDriveSettingsPath = Path.Combine(localAppData, @"Microsoft\OneDrive\settings\Personal");
+ if (!Directory.Exists(oneDriveSettingsPath))
+ {
+ return false;
+ }
+ var oneDriveSettingsFile = Directory.GetFiles(oneDriveSettingsPath, "*_screenshot.dat").FirstOrDefault();
+ if (!File.Exists(oneDriveSettingsFile))
+ {
+ return false;
+ }
+ var screenshotSetting = File.ReadAllLines(oneDriveSettingsFile).Skip(1).Take(1).First();
+ return "2".Equals(screenshotSetting);
+ }
+
+ ///
+ /// Displays a dialog for the user to choose how to handle hotkey registration failures:
+ /// retry (allowing to shut down the conflicting application before),
+ /// ignore (not registering the conflicting hotkey and resetting the respective config to "None", i.e. not trying to register it again on next startup)
+ /// abort (do nothing about it)
+ ///
+ /// comma separated list of the hotkeys that could not be registered, for display in dialog text
+ ///
+ private static bool HandleFailedHotkeyRegistration(string failedKeys) {
+ bool success = false;
+ var warningTitle = Language.GetString(LangKey.warning);
+ var message = string.Format(Language.GetString(LangKey.warning_hotkeys), failedKeys, IsOneDriveBlockingHotkey() ? " (OneDrive)": "");
+ DialogResult dr = MessageBox.Show(Instance, message, warningTitle, MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation);
+ if (dr == DialogResult.Retry) {
+ LOG.DebugFormat("Re-trying to register hotkeys");
+ HotkeyControl.UnregisterHotkeys();
+ success = RegisterHotkeys(false);
+ } else if (dr == DialogResult.Ignore) {
+ LOG.DebugFormat("Ignoring failed hotkey registration");
+ HotkeyControl.UnregisterHotkeys();
+ success = RegisterHotkeys(true);
+ }
+ return success;
+ }
+ #endregion
+
+ public void UpdateUi() {
+ // As the form is never loaded, call ApplyLanguage ourselves
+ ApplyLanguage();
+
+ // Show hotkeys in Contextmenu
+ contextmenu_capturearea.ShortcutKeyDisplayString = HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.RegionHotkey);
+ contextmenu_capturelastregion.ShortcutKeyDisplayString = HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.LastregionHotkey);
+ contextmenu_capturewindow.ShortcutKeyDisplayString = HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.WindowHotkey);
+ contextmenu_capturefullscreen.ShortcutKeyDisplayString = HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.FullscreenHotkey);
+ contextmenu_captureie.ShortcutKeyDisplayString = HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.IEHotkey);
+ }
+
+
+ #region mainform events
+
+ private void MainFormFormClosing(object sender, FormClosingEventArgs e) {
+ LOG.DebugFormat("Mainform closing, reason: {0}", e.CloseReason);
+ _instance = null;
+ Exit();
+ }
+
+ private void MainFormActivated(object sender, EventArgs e) {
+ Hide();
+ ShowInTaskbar = false;
+ }
+ #endregion
+
+ #region key handlers
+
+ private void CaptureRegion() {
+ CaptureHelper.CaptureRegion(true);
+ }
+
+ private void CaptureFile() {
+ var openFileDialog = new OpenFileDialog
+ {
+ Filter = "Image files (*.greenshot, *.png, *.jpg, *.gif, *.bmp, *.ico, *.tiff, *.wmf)|*.greenshot; *.png; *.jpg; *.jpeg; *.gif; *.bmp; *.ico; *.tiff; *.tif; *.wmf"
+ };
+ if (openFileDialog.ShowDialog() == DialogResult.OK) {
+ if (File.Exists(openFileDialog.FileName)) {
+ CaptureHelper.CaptureFile(openFileDialog.FileName);
+ }
+ }
+ }
+
+ private void CaptureFullScreen() {
+ CaptureHelper.CaptureFullscreen(true, _conf.ScreenCaptureMode);
+ }
+
+ private void CaptureLastRegion() {
+ CaptureHelper.CaptureLastRegion(true);
+ }
+
+ private void CaptureIE() {
+ if (_conf.IECapture) {
+ CaptureHelper.CaptureIe(true, null);
+ }
+ }
+
+ private void CaptureWindow() {
+ if (_conf.CaptureWindowsInteractive) {
+ CaptureHelper.CaptureWindowInteractive(true);
+ } else {
+ CaptureHelper.CaptureWindow(true);
+ }
+ }
+ #endregion
+
+
+ #region contextmenu
+
+ private void ContextMenuOpening(object sender, CancelEventArgs e) {
+ contextmenu_captureclipboard.Enabled = ClipboardHelper.ContainsImage();
+ contextmenu_capturelastregion.Enabled = coreConfiguration.LastCapturedRegion != Rectangle.Empty;
+
+ // IE context menu code
+ try {
+ if (_conf.IECapture && IeCaptureHelper.IsIeRunning()) {
+ contextmenu_captureie.Enabled = true;
+ contextmenu_captureiefromlist.Enabled = true;
+ } else {
+ contextmenu_captureie.Enabled = false;
+ contextmenu_captureiefromlist.Enabled = false;
+ }
+ } catch (Exception ex) {
+ LOG.WarnFormat("Problem accessing IE information: {0}", ex.Message);
+ }
+
+ // Multi-Screen captures
+ contextmenu_capturefullscreen.Click -= CaptureFullScreenToolStripMenuItemClick;
+ contextmenu_capturefullscreen.DropDownOpening -= MultiScreenDropDownOpening;
+ contextmenu_capturefullscreen.DropDownClosed -= MultiScreenDropDownClosing;
+ if (Screen.AllScreens.Length > 1) {
+ contextmenu_capturefullscreen.DropDownOpening += MultiScreenDropDownOpening;
+ contextmenu_capturefullscreen.DropDownClosed += MultiScreenDropDownClosing;
+ } else {
+ contextmenu_capturefullscreen.Click += CaptureFullScreenToolStripMenuItemClick;
+ }
+
+ var now = DateTime.Now;
+ if ((now.Month == 12 && now.Day > 19 && now.Day < 27) || // christmas
+ (now.Month == 3 && now.Day > 13 && now.Day < 21)) { // birthday
+ var resources = new ComponentResourceManager(typeof(MainForm));
+ contextmenu_donate.Image = (Image)resources.GetObject("contextmenu_present.Image");
+ }
+ }
+
+ private void ContextMenuClosing(object sender, EventArgs e) {
+ contextmenu_captureiefromlist.DropDownItems.Clear();
+ contextmenu_capturewindowfromlist.DropDownItems.Clear();
+ CleanupThumbnail();
+ }
+
+ ///
+ /// Build a selectable list of IE tabs when we enter the menu item
+ ///
+ private void CaptureIeMenuDropDownOpening(object sender, EventArgs e) {
+ if (!_conf.IECapture) {
+ return;
+ }
+ try {
+ List> tabs = IeCaptureHelper.GetBrowserTabs();
+ contextmenu_captureiefromlist.DropDownItems.Clear();
+ if (tabs.Count > 0) {
+ contextmenu_captureie.Enabled = true;
+ contextmenu_captureiefromlist.Enabled = true;
+ Dictionary counter = new Dictionary();
+
+ foreach(KeyValuePair tabData in tabs) {
+ string title = tabData.Value;
+ if (title == null) {
+ continue;
+ }
+ if (title.Length > _conf.MaxMenuItemLength) {
+ title = title.Substring(0, Math.Min(title.Length, _conf.MaxMenuItemLength));
+ }
+ var captureIeTabItem = contextmenu_captureiefromlist.DropDownItems.Add(title);
+ int index = counter.ContainsKey(tabData.Key) ? counter[tabData.Key] : 0;
+ captureIeTabItem.Image = tabData.Key.DisplayIcon;
+ captureIeTabItem.Tag = new KeyValuePair(tabData.Key, index++);
+ captureIeTabItem.Click += Contextmenu_captureiefromlist_Click;
+ contextmenu_captureiefromlist.DropDownItems.Add(captureIeTabItem);
+ if (counter.ContainsKey(tabData.Key)) {
+ counter[tabData.Key] = index;
+ } else {
+ counter.Add(tabData.Key, index);
+ }
+ }
+ } else {
+ contextmenu_captureie.Enabled = false;
+ contextmenu_captureiefromlist.Enabled = false;
+ }
+ } catch (Exception ex) {
+ LOG.WarnFormat("Problem accessing IE information: {0}", ex.Message);
+ }
+ }
+
+ ///
+ /// MultiScreenDropDownOpening is called when mouse hovers over the Capture-Screen context menu
+ ///
+ ///
+ ///
+ private void MultiScreenDropDownOpening(object sender, EventArgs e) {
+ ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender;
+ captureScreenMenuItem.DropDownItems.Clear();
+ if (Screen.AllScreens.Length > 1) {
+ Rectangle allScreensBounds = WindowCapture.GetScreenBounds();
+
+ var captureScreenItem = new ToolStripMenuItem(Language.GetString(LangKey.contextmenu_capturefullscreen_all));
+ captureScreenItem.Click += delegate {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureFullscreen(false, ScreenCaptureMode.FullScreen);
+ });
+ };
+ captureScreenMenuItem.DropDownItems.Add(captureScreenItem);
+ foreach (Screen screen in Screen.AllScreens) {
+ Screen screenToCapture = screen;
+ string deviceAlignment = "";
+ if(screen.Bounds.Top == allScreensBounds.Top && screen.Bounds.Bottom != allScreensBounds.Bottom) {
+ deviceAlignment += " " + Language.GetString(LangKey.contextmenu_capturefullscreen_top);
+ } else if(screen.Bounds.Top != allScreensBounds.Top && screen.Bounds.Bottom == allScreensBounds.Bottom) {
+ deviceAlignment += " " + Language.GetString(LangKey.contextmenu_capturefullscreen_bottom);
+ }
+ if(screen.Bounds.Left == allScreensBounds.Left && screen.Bounds.Right != allScreensBounds.Right) {
+ deviceAlignment += " " + Language.GetString(LangKey.contextmenu_capturefullscreen_left);
+ } else if(screen.Bounds.Left != allScreensBounds.Left && screen.Bounds.Right == allScreensBounds.Right) {
+ deviceAlignment += " " + Language.GetString(LangKey.contextmenu_capturefullscreen_right);
+ }
+ captureScreenItem = new ToolStripMenuItem(deviceAlignment);
+ captureScreenItem.Click += delegate {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureRegion(false, screenToCapture.Bounds);
+ });
+ };
+ captureScreenMenuItem.DropDownItems.Add(captureScreenItem);
+ }
+ }
+ }
+
+ ///
+ /// MultiScreenDropDownOpening is called when mouse leaves the context menu
+ ///
+ ///
+ ///
+ private void MultiScreenDropDownClosing(object sender, EventArgs e) {
+ ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender;
+ captureScreenMenuItem.DropDownItems.Clear();
+ }
+
+ ///
+ /// Build a selectable list of windows when we enter the menu item
+ ///
+ private void CaptureWindowFromListMenuDropDownOpening(object sender, EventArgs e) {
+ // The Capture window context menu item used to go to the following code:
+ // captureForm.MakeCapture(CaptureMode.Window, false);
+ // Now we check which windows are there to capture
+ ToolStripMenuItem captureWindowFromListMenuItem = (ToolStripMenuItem)sender;
+ AddCaptureWindowMenuItems(captureWindowFromListMenuItem, Contextmenu_capturewindowfromlist_Click);
+ }
+
+ private void CaptureWindowFromListMenuDropDownClosed(object sender, EventArgs e) {
+ CleanupThumbnail();
+ }
+
+ private void ShowThumbnailOnEnter(object sender, EventArgs e) {
+ ToolStripMenuItem captureWindowItem = sender as ToolStripMenuItem;
+ if (captureWindowItem != null) {
+ WindowDetails window = captureWindowItem.Tag as WindowDetails;
+ if (_thumbnailForm == null) {
+ _thumbnailForm = new ThumbnailForm();
+ }
+ _thumbnailForm.ShowThumbnail(window, captureWindowItem.GetCurrentParent().TopLevelControl);
+ }
+ }
+
+ private void HideThumbnailOnLeave(object sender, EventArgs e)
+ {
+ _thumbnailForm?.Hide();
+ }
+
+ private void CleanupThumbnail() {
+ if (_thumbnailForm == null)
+ {
+ return;
+ }
+ _thumbnailForm.Close();
+ _thumbnailForm = null;
+ }
+
+ public void AddCaptureWindowMenuItems(ToolStripMenuItem menuItem, EventHandler eventHandler) {
+ menuItem.DropDownItems.Clear();
+ // check if thumbnailPreview is enabled and DWM is enabled
+ bool thumbnailPreview = _conf.ThumnailPreview && DWM.IsDwmEnabled();
+
+ foreach(WindowDetails window in WindowDetails.GetTopLevelWindows()) {
+
+ string title = window.Text;
+ if (title != null) {
+ if (title.Length > _conf.MaxMenuItemLength) {
+ title = title.Substring(0, Math.Min(title.Length, _conf.MaxMenuItemLength));
+ }
+ ToolStripItem captureWindowItem = menuItem.DropDownItems.Add(title);
+ captureWindowItem.Tag = window;
+ captureWindowItem.Image = window.DisplayIcon;
+ captureWindowItem.Click += eventHandler;
+ // Only show preview when enabled
+ if (thumbnailPreview) {
+ captureWindowItem.MouseEnter += ShowThumbnailOnEnter;
+ captureWindowItem.MouseLeave += HideThumbnailOnLeave;
+ }
+ }
+ }
+ }
+
+ private void CaptureAreaToolStripMenuItemClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureRegion(false);
+ });
+ }
+
+ private void CaptureClipboardToolStripMenuItemClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)CaptureHelper.CaptureClipboard);
+ }
+
+ private void OpenFileToolStripMenuItemClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)CaptureFile);
+ }
+
+ private void CaptureFullScreenToolStripMenuItemClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureFullscreen(false, _conf.ScreenCaptureMode);
+ });
+ }
+
+ private void Contextmenu_capturelastregionClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureLastRegion(false);
+ });
+ }
+
+ private void Contextmenu_capturewindow_Click(object sender,EventArgs e) {
+ BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.CaptureWindowInteractive(false);
+ });
+ }
+
+ private void Contextmenu_capturewindowfromlist_Click(object sender,EventArgs e) {
+ ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
+ BeginInvoke((MethodInvoker)delegate {
+ try {
+ WindowDetails windowToCapture = (WindowDetails)clickedItem.Tag;
+ CaptureHelper.CaptureWindow(windowToCapture);
+ } catch (Exception exception) {
+ LOG.Error(exception);
+ }
+ });
+ }
+
+ private void Contextmenu_captureie_Click(object sender, EventArgs e) {
+ CaptureIE();
+ }
+
+ private void Contextmenu_captureiefromlist_Click(object sender, EventArgs e) {
+ if (!_conf.IECapture) {
+ LOG.InfoFormat("IE Capture is disabled.");
+ return;
+ }
+ ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
+ KeyValuePair tabData = (KeyValuePair)clickedItem.Tag;
+ BeginInvoke((MethodInvoker)delegate {
+ WindowDetails ieWindowToCapture = tabData.Key;
+ if (ieWindowToCapture != null && (!ieWindowToCapture.Visible || ieWindowToCapture.Iconic)) {
+ ieWindowToCapture.Restore();
+ }
+ try {
+ IeCaptureHelper.ActivateIeTab(ieWindowToCapture, tabData.Value);
+ } catch (Exception exception) {
+ LOG.Error(exception);
+ }
+ try {
+ CaptureHelper.CaptureIe(false, ieWindowToCapture);
+ } catch (Exception exception) {
+ LOG.Error(exception);
+ }
+ });
+ }
+
+ ///
+ /// Context menu entry "Support Greenshot"
+ ///
+ ///
+ ///
+ private void Contextmenu_donateClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)delegate {
+ Process.Start("http://getgreenshot.org/support/?version=" + Assembly.GetEntryAssembly().GetName().Version);
+ });
+ }
+
+ ///
+ /// Context menu entry "Preferences"
+ ///
+ ///
+ ///
+ private void Contextmenu_settingsClick(object sender, EventArgs e) {
+ BeginInvoke((MethodInvoker)ShowSetting);
+ }
+
+ ///
+ /// This is called indirectly from the context menu "Preferences"
+ ///
+ public void ShowSetting() {
+ if (_settingsForm != null) {
+ WindowDetails.ToForeground(_settingsForm.Handle);
+ } else {
+ try {
+ using (_settingsForm = new SettingsForm()) {
+ if (_settingsForm.ShowDialog() == DialogResult.OK) {
+ InitializeQuickSettingsMenu();
+ }
+ }
+ } finally {
+ _settingsForm = null;
+ }
+ }
+ }
+
+ ///
+ /// The "About Greenshot" entry is clicked
+ ///
+ ///
+ ///
+ private void Contextmenu_aboutClick(object sender, EventArgs e) {
+ ShowAbout();
+ }
+
+ public void ShowAbout() {
+ if (_aboutForm != null) {
+ WindowDetails.ToForeground(_aboutForm.Handle);
+ } else {
+ try {
+ using (_aboutForm = new AboutForm()) {
+ _aboutForm.ShowDialog(this);
+ }
+ } finally {
+ _aboutForm = null;
+ }
+ }
+ }
+
+ ///
+ /// The "Help" entry is clicked
+ ///
+ ///
+ ///
+ private void Contextmenu_helpClick(object sender, EventArgs e) {
+ HelpFileLoader.LoadHelp();
+ }
+
+ ///
+ /// The "Exit" entry is clicked
+ ///
+ ///
+ ///
+ private void Contextmenu_exitClick(object sender, EventArgs e) {
+ Exit();
+ }
+
+ private void CheckStateChangedHandler(object sender, EventArgs e) {
+ ToolStripMenuSelectListItem captureMouseItem = sender as ToolStripMenuSelectListItem;
+ if (captureMouseItem != null) {
+ _conf.CaptureMousepointer = captureMouseItem.Checked;
+ }
+ }
+
+ ///
+ /// This needs to be called to initialize the quick settings menu entries
+ ///
+ private void InitializeQuickSettingsMenu() {
+ contextmenu_quicksettings.DropDownItems.Clear();
+
+ if (_conf.DisableQuickSettings) {
+ return;
+ }
+
+ // Only add if the value is not fixed
+ if (!_conf.Values["CaptureMousepointer"].IsFixed) {
+ // For the capture mousecursor option
+ ToolStripMenuSelectListItem captureMouseItem = new ToolStripMenuSelectListItem
+ {
+ Text = Language.GetString("settings_capture_mousepointer"),
+ Checked = _conf.CaptureMousepointer,
+ CheckOnClick = true
+ };
+ captureMouseItem.CheckStateChanged += CheckStateChangedHandler;
+
+ contextmenu_quicksettings.DropDownItems.Add(captureMouseItem);
+ }
+ ToolStripMenuSelectList selectList;
+ if (!_conf.Values["Destinations"].IsFixed) {
+ // screenshot destination
+ selectList = new ToolStripMenuSelectList("destinations", true)
+ {
+ Text = Language.GetString(LangKey.settings_destination)
+ };
+ // Working with IDestination:
+ foreach (var destination in DestinationHelper.GetAllDestinations()) {
+ selectList.AddItem(destination.Description, destination, _conf.OutputDestinations.Contains(destination.Designation));
+ }
+ selectList.CheckedChanged += QuickSettingDestinationChanged;
+ contextmenu_quicksettings.DropDownItems.Add(selectList);
+ }
+
+ if (!_conf.Values["WindowCaptureMode"].IsFixed) {
+ // Capture Modes
+ selectList = new ToolStripMenuSelectList("capturemodes", false)
+ {
+ Text = Language.GetString(LangKey.settings_window_capture_mode)
+ };
+ string enumTypeName = typeof(WindowCaptureMode).Name;
+ foreach (WindowCaptureMode captureMode in Enum.GetValues(typeof(WindowCaptureMode))) {
+ selectList.AddItem(Language.GetString(enumTypeName + "." + captureMode), captureMode, _conf.WindowCaptureMode == captureMode);
+ }
+ selectList.CheckedChanged += QuickSettingCaptureModeChanged;
+ contextmenu_quicksettings.DropDownItems.Add(selectList);
+ }
+
+ // print options
+ selectList = new ToolStripMenuSelectList("printoptions", true)
+ {
+ Text = Language.GetString(LangKey.settings_printoptions)
+ };
+
+ IniValue iniValue;
+ foreach(string propertyName in _conf.Values.Keys) {
+ if (propertyName.StartsWith("OutputPrint")) {
+ iniValue = _conf.Values[propertyName];
+ if (iniValue.Attributes.LanguageKey != null && !iniValue.IsFixed) {
+ selectList.AddItem(Language.GetString(iniValue.Attributes.LanguageKey), iniValue, (bool)iniValue.Value);
+ }
+ }
+ }
+ if (selectList.DropDownItems.Count > 0) {
+ selectList.CheckedChanged += QuickSettingBoolItemChanged;
+ contextmenu_quicksettings.DropDownItems.Add(selectList);
+ }
+
+ // effects
+ selectList = new ToolStripMenuSelectList("effects", true)
+ {
+ Text = Language.GetString(LangKey.settings_visualization)
+ };
+
+ iniValue = _conf.Values["PlayCameraSound"];
+ if (!iniValue.IsFixed) {
+ selectList.AddItem(Language.GetString(iniValue.Attributes.LanguageKey), iniValue, (bool)iniValue.Value);
+ }
+ iniValue = _conf.Values["ShowTrayNotification"];
+ if (!iniValue.IsFixed) {
+ selectList.AddItem(Language.GetString(iniValue.Attributes.LanguageKey), iniValue, (bool)iniValue.Value);
+ }
+ if (selectList.DropDownItems.Count > 0) {
+ selectList.CheckedChanged += QuickSettingBoolItemChanged;
+ contextmenu_quicksettings.DropDownItems.Add(selectList);
+ }
+ }
+
+ private void QuickSettingCaptureModeChanged(object sender, EventArgs e) {
+ ToolStripMenuSelectListItem item = ((ItemCheckedChangedEventArgs)e).Item;
+ WindowCaptureMode windowsCaptureMode = (WindowCaptureMode)item.Data;
+ if (item.Checked) {
+ _conf.WindowCaptureMode = windowsCaptureMode;
+ }
+ }
+
+ private void QuickSettingBoolItemChanged(object sender, EventArgs e) {
+ ToolStripMenuSelectListItem item = ((ItemCheckedChangedEventArgs)e).Item;
+ IniValue iniValue = item.Data as IniValue;
+ if (iniValue != null) {
+ iniValue.Value = item.Checked;
+ IniConfig.Save();
+ }
+ }
+
+ private void QuickSettingDestinationChanged(object sender, EventArgs e) {
+ ToolStripMenuSelectListItem item = ((ItemCheckedChangedEventArgs)e).Item;
+ IDestination selectedDestination = (IDestination)item.Data;
+ if (item.Checked) {
+ if (selectedDestination.Designation.Equals(PickerDestination.DESIGNATION)) {
+ // If the item is the destination picker, remove all others
+ _conf.OutputDestinations.Clear();
+ } else {
+ // If the item is not the destination picker, remove the picker
+ _conf.OutputDestinations.Remove(PickerDestination.DESIGNATION);
+ }
+ // Checked an item, add if the destination is not yet selected
+ if (!_conf.OutputDestinations.Contains(selectedDestination.Designation)) {
+ _conf.OutputDestinations.Add(selectedDestination.Designation);
+ }
+ } else {
+ // deselected a destination, only remove if it was selected
+ if (_conf.OutputDestinations.Contains(selectedDestination.Designation)) {
+ _conf.OutputDestinations.Remove(selectedDestination.Designation);
+ }
+ }
+ // Check if something was selected, if not make the picker the default
+ if (_conf.OutputDestinations == null || _conf.OutputDestinations.Count == 0) {
+ _conf.OutputDestinations.Add(PickerDestination.DESIGNATION);
+ }
+ IniConfig.Save();
+
+ // Rebuild the quick settings menu with the new settings.
+ InitializeQuickSettingsMenu();
+ }
+ #endregion
+
+ private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
+ Exception exceptionToLog = e.ExceptionObject as Exception;
+ string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
+ LOG.Error("Exception caught in the UnhandledException handler.");
+ LOG.Error(exceptionText);
+ if (exceptionText != null && exceptionText.Contains("InputLanguageChangedEventArgs"))
+ {
+ // Ignore for BUG-1809
+ return;
+ }
+ new BugReportForm(exceptionText).ShowDialog();
+ }
+
+ private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
+ Exception exceptionToLog = e.Exception;
+ string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
+ LOG.Error("Exception caught in the ThreadException handler.");
+ LOG.Error(exceptionText);
+ if (exceptionText != null && exceptionText.Contains("InputLanguageChangedEventArgs"))
+ {
+ // Ignore for BUG-1809
+ return;
+ }
+
+ new BugReportForm(exceptionText).ShowDialog();
+ }
+
+ ///
+ /// Handle the notify icon click
+ ///
+ ///
+ ///
+ private void NotifyIconClickTest(object sender, MouseEventArgs e) {
+ if (e.Button != MouseButtons.Left) {
+ return;
+ }
+ // The right button will automatically be handled with the context menu, here we only check the left.
+ if (_conf.DoubleClickAction == ClickActions.DO_NOTHING) {
+ // As there isn't a double-click we can start the Left click
+ NotifyIconClick(_conf.LeftClickAction);
+ // ready with the test
+ return;
+ }
+ // If the timer is enabled we are waiting for a double click...
+ if (_doubleClickTimer.Enabled) {
+ // User clicked a second time before the timer tick: Double-click!
+ _doubleClickTimer.Elapsed -= NotifyIconSingleClickTest;
+ _doubleClickTimer.Stop();
+ NotifyIconClick(_conf.DoubleClickAction);
+ } else {
+ // User clicked without a timer, set the timer and if it ticks it was a single click
+ // Create timer, if it ticks before the NotifyIconClickTest is called again we have a single click
+ _doubleClickTimer.Elapsed += NotifyIconSingleClickTest;
+ _doubleClickTimer.Interval = SystemInformation.DoubleClickTime;
+ _doubleClickTimer.Start();
+ }
+ }
+
+ ///
+ /// Called by the doubleClickTimer, this means a single click was used on the tray icon
+ ///
+ ///
+ ///
+ private void NotifyIconSingleClickTest(object sender, EventArgs e) {
+ _doubleClickTimer.Elapsed -= NotifyIconSingleClickTest;
+ _doubleClickTimer.Stop();
+ BeginInvoke((MethodInvoker)delegate {
+ NotifyIconClick(_conf.LeftClickAction);
+ });
+ }
+
+ ///
+ /// Handle the notify icon click
+ ///
+ private void NotifyIconClick(ClickActions clickAction) {
+ switch (clickAction) {
+ case ClickActions.OPEN_LAST_IN_EXPLORER:
+ Contextmenu_OpenRecent(this, null);
+ break;
+ case ClickActions.OPEN_LAST_IN_EDITOR:
+ _conf.ValidateAndCorrectOutputFileAsFullpath();
+
+ if (File.Exists(_conf.OutputFileAsFullpath)) {
+ CaptureHelper.CaptureFile(_conf.OutputFileAsFullpath, DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
+ }
+ break;
+ case ClickActions.OPEN_SETTINGS:
+ ShowSetting();
+ break;
+ case ClickActions.SHOW_CONTEXT_MENU:
+ MethodInfo oMethodInfo = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
+ oMethodInfo.Invoke(notifyIcon, null);
+ break;
+ }
+ }
+
+ ///
+ /// The Contextmenu_OpenRecent currently opens the last know save location
+ ///
+ private void Contextmenu_OpenRecent(object sender, EventArgs eventArgs)
+ {
+ _conf.ValidateAndCorrectOutputFilePath();
+ _conf.ValidateAndCorrectOutputFileAsFullpath();
+ string path = _conf.OutputFileAsFullpath;
+ if (!File.Exists(path))
+ {
+ path = FilenameHelper.FillVariables(_conf.OutputFilePath, false);
+ // Fix for #1470, problems with a drive which is no longer available
+ try
+ {
+ string lastFilePath = Path.GetDirectoryName(_conf.OutputFileAsFullpath);
+
+ if (lastFilePath != null && Directory.Exists(lastFilePath))
+ {
+ path = lastFilePath;
+ }
+ else if (!Directory.Exists(path))
+ {
+ // What do I open when nothing can be found? Right, nothing...
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ LOG.Warn("Couldn't open the path to the last exported file, taking default.", ex);
+ }
+ }
+ try
+ {
+ ExplorerHelper.OpenInExplorer(path);
+ }
+ catch (Exception ex)
+ {
+ // Make sure we show what we tried to open in the exception
+ ex.Data.Add("path", path);
+ LOG.Warn("Couldn't open the path to the last exported file", ex);
+ // No reason to create a bug-form, we just display the error.
+ MessageBox.Show(this, ex.Message, "Opening " + path, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Shutdown / cleanup
+ ///
+ public void Exit() {
+ LOG.Info("Exit: " + EnvironmentInfo.EnvironmentToString(false));
+
+ // Close all open forms (except this), use a separate List to make sure we don't get a "InvalidOperationException: Collection was modified"
+ List
\ No newline at end of file
diff --git a/src/Greenshot.Editor/Forms/MovableShowColorForm.Designer.cs b/Greenshot/Forms/MovableShowColorForm.Designer.cs
similarity index 94%
rename from src/Greenshot.Editor/Forms/MovableShowColorForm.Designer.cs
rename to Greenshot/Forms/MovableShowColorForm.Designer.cs
index 856e59abb..811772d0b 100644
--- a/src/Greenshot.Editor/Forms/MovableShowColorForm.Designer.cs
+++ b/Greenshot/Forms/MovableShowColorForm.Designer.cs
@@ -1,183 +1,188 @@
-namespace Greenshot.Editor.Forms
-{
- partial class MovableShowColorForm
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.panel1 = new System.Windows.Forms.Panel();
- this.html = new System.Windows.Forms.Label();
- this.label1 = new System.Windows.Forms.Label();
- this.preview = new System.Windows.Forms.Label();
- this.label2 = new System.Windows.Forms.Label();
- this.red = new System.Windows.Forms.Label();
- this.green = new System.Windows.Forms.Label();
- this.label4 = new System.Windows.Forms.Label();
- this.blue = new System.Windows.Forms.Label();
- this.label6 = new System.Windows.Forms.Label();
- this.alpha = new System.Windows.Forms.Label();
- this.label5 = new System.Windows.Forms.Label();
- this.panel1.SuspendLayout();
- this.SuspendLayout();
- //
- // html
- //
- this.html.Location = new System.Drawing.Point(40, 18);
- this.html.Name = "html";
- this.html.Size = new System.Drawing.Size(59, 19);
- this.html.TabIndex = 2;
- //
- // label1
- //
- this.label1.Location = new System.Drawing.Point(40, 5);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(37, 13);
- this.label1.TabIndex = 1;
- this.label1.Text = "HTML";
- //
- // preview
- //
- this.preview.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.preview.Location = new System.Drawing.Point(5, 5);
- this.preview.Name = "preview";
- this.preview.Size = new System.Drawing.Size(32, 32);
- this.preview.TabIndex = 0;
- //
- // label2
- //
- this.label2.Location = new System.Drawing.Point(2, 37);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(33, 13);
- this.label2.TabIndex = 3;
- this.label2.Text = "Red: ";
- //
- // red
- //
- this.red.Location = new System.Drawing.Point(43, 37);
- this.red.Name = "red";
- this.red.Size = new System.Drawing.Size(55, 13);
- this.red.TabIndex = 4;
- //
- // green
- //
- this.green.Location = new System.Drawing.Point(43, 50);
- this.green.Name = "green";
- this.green.Size = new System.Drawing.Size(55, 13);
- this.green.TabIndex = 6;
- //
- // label4
- //
- this.label4.Location = new System.Drawing.Point(2, 50);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(42, 13);
- this.label4.TabIndex = 5;
- this.label4.Text = "Green: ";
- //
- // blue
- //
- this.blue.Location = new System.Drawing.Point(43, 63);
- this.blue.Name = "blue";
- this.blue.Size = new System.Drawing.Size(55, 13);
- this.blue.TabIndex = 8;
- //
- // label6
- //
- this.label6.Location = new System.Drawing.Point(2, 63);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(34, 13);
- this.label6.TabIndex = 7;
- this.label6.Text = "Blue: ";
- //
- // alpha
- //
- this.alpha.Location = new System.Drawing.Point(43, 76);
- this.alpha.Name = "alpha";
- this.alpha.Size = new System.Drawing.Size(55, 13);
- this.alpha.TabIndex = 10;
- //
- // label5
- //
- this.label5.Location = new System.Drawing.Point(2, 76);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(40, 13);
- this.label5.TabIndex = 9;
- this.label5.Text = "Alpha: ";
- //
- // panel1
- //
- this.panel1.BackColor = System.Drawing.SystemColors.Info;
- this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.panel1.Controls.Add(this.alpha);
- this.panel1.Controls.Add(this.label5);
- this.panel1.Controls.Add(this.blue);
- this.panel1.Controls.Add(this.label6);
- this.panel1.Controls.Add(this.green);
- this.panel1.Controls.Add(this.label4);
- this.panel1.Controls.Add(this.red);
- this.panel1.Controls.Add(this.label2);
- this.panel1.Controls.Add(this.html);
- this.panel1.Controls.Add(this.label1);
- this.panel1.Controls.Add(this.preview);
- this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.panel1.Location = new System.Drawing.Point(0, 0);
- this.panel1.Name = "panel1";
- this.panel1.Size = new System.Drawing.Size(100, 100);
- this.panel1.TabIndex = 0;
- //
- // Zoomer
- //
- this.Visible = false;
- this.Location = new System.Drawing.Point(-10000,-10000);
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(100, 100);
- this.Controls.Add(this.panel1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
- this.Name = "Zoomer";
- this.ShowIcon = false;
- this.ShowInTaskbar = false;
- this.Text = "Zoomer";
- this.TopMost = true;
- this.panel1.ResumeLayout(true);
- this.ResumeLayout(true);
- }
-
- #endregion
-
- private System.Windows.Forms.Panel panel1;
- private System.Windows.Forms.Label html;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.Label preview;
- private System.Windows.Forms.Label alpha;
- private System.Windows.Forms.Label label5;
- private System.Windows.Forms.Label blue;
- private System.Windows.Forms.Label label6;
- private System.Windows.Forms.Label green;
- private System.Windows.Forms.Label label4;
- private System.Windows.Forms.Label red;
- private System.Windows.Forms.Label label2;
- }
-}
+namespace Greenshot.Forms
+{
+ partial class MovableShowColorForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.html = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.preview = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.red = new System.Windows.Forms.Label();
+ this.green = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.blue = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
+ this.alpha = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // html
+ //
+ this.html.Location = new System.Drawing.Point(40, 18);
+ this.html.Name = "html";
+ this.html.Size = new System.Drawing.Size(59, 19);
+ this.html.TabIndex = 2;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(40, 5);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(37, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "HTML";
+ //
+ // preview
+ //
+ this.preview.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.preview.Location = new System.Drawing.Point(5, 5);
+ this.preview.Name = "preview";
+ this.preview.Size = new System.Drawing.Size(32, 32);
+ this.preview.TabIndex = 0;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(2, 37);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(33, 13);
+ this.label2.TabIndex = 3;
+ this.label2.Text = "Red: ";
+ //
+ // red
+ //
+ this.red.Location = new System.Drawing.Point(43, 37);
+ this.red.Name = "red";
+ this.red.Size = new System.Drawing.Size(55, 13);
+ this.red.TabIndex = 4;
+ //
+ // green
+ //
+ this.green.Location = new System.Drawing.Point(43, 50);
+ this.green.Name = "green";
+ this.green.Size = new System.Drawing.Size(55, 13);
+ this.green.TabIndex = 6;
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(2, 50);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(42, 13);
+ this.label4.TabIndex = 5;
+ this.label4.Text = "Green: ";
+ //
+ // blue
+ //
+ this.blue.Location = new System.Drawing.Point(43, 63);
+ this.blue.Name = "blue";
+ this.blue.Size = new System.Drawing.Size(55, 13);
+ this.blue.TabIndex = 8;
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(2, 63);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(34, 13);
+ this.label6.TabIndex = 7;
+ this.label6.Text = "Blue: ";
+ //
+ // alpha
+ //
+ this.alpha.Location = new System.Drawing.Point(43, 76);
+ this.alpha.Name = "alpha";
+ this.alpha.Size = new System.Drawing.Size(55, 13);
+ this.alpha.TabIndex = 10;
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(2, 76);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(40, 13);
+ this.label5.TabIndex = 9;
+ this.label5.Text = "Alpha: ";
+ //
+ // panel1
+ //
+ this.panel1.BackColor = System.Drawing.SystemColors.Info;
+ this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.panel1.Controls.Add(this.alpha);
+ this.panel1.Controls.Add(this.label5);
+ this.panel1.Controls.Add(this.blue);
+ this.panel1.Controls.Add(this.label6);
+ this.panel1.Controls.Add(this.green);
+ this.panel1.Controls.Add(this.label4);
+ this.panel1.Controls.Add(this.red);
+ this.panel1.Controls.Add(this.label2);
+ this.panel1.Controls.Add(this.html);
+ this.panel1.Controls.Add(this.label1);
+ this.panel1.Controls.Add(this.preview);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(100, 100);
+ this.panel1.TabIndex = 0;
+ //
+ // Zoomer
+ //
+ this.Visible = false;
+ this.Location = new System.Drawing.Point(-10000,-10000);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(100, 100);
+ this.Controls.Add(this.panel1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.Name = "Zoomer";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.Text = "Zoomer";
+ this.TopMost = true;
+ this.panel1.ResumeLayout(true);
+ this.ResumeLayout(true);
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.Label html;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label preview;
+ private System.Windows.Forms.Label alpha;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Label blue;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.Label green;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label red;
+ private System.Windows.Forms.Label label2;
+ }
+}
diff --git a/Greenshot/Forms/MovableShowColorForm.cs b/Greenshot/Forms/MovableShowColorForm.cs
new file mode 100644
index 000000000..86f193206
--- /dev/null
+++ b/Greenshot/Forms/MovableShowColorForm.cs
@@ -0,0 +1,100 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using System.Drawing;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace Greenshot.Forms {
+ ///
+ /// This code was supplied by Hi-Coder as a patch for Greenshot
+ /// Needed some modifications to be stable.
+ ///
+ public partial class MovableShowColorForm : Form {
+ public Color color {
+ get {
+ return preview.BackColor;
+ }
+ }
+
+ public MovableShowColorForm() {
+ InitializeComponent();
+ }
+
+ ///
+ /// Move the MovableShowColorForm to the specified location and display the color under the (current mouse) coordinates
+ ///
+ /// Coordinates
+ public void MoveTo(Point screenCoordinates) {
+ Color c = GetPixelColor(screenCoordinates);
+ preview.BackColor = c;
+ html.Text = "#" + c.Name.Substring(2).ToUpper();
+ red.Text = "" + c.R;
+ blue.Text = "" + c.B;
+ green.Text = "" + c.G;
+ alpha.Text = "" + c.A;
+
+ Size cursorSize = Cursor.Current.Size;
+ Point hotspot = Cursor.Current.HotSpot;
+
+ Point zoomerLocation = new Point(screenCoordinates.X, screenCoordinates.Y);
+ zoomerLocation.X += cursorSize.Width + 5 - hotspot.X;
+ zoomerLocation.Y += cursorSize.Height + 5 - hotspot.Y;
+
+ foreach (Screen screen in Screen.AllScreens) {
+ Rectangle screenRectangle = screen.Bounds;
+ if (screen.Bounds.Contains(screenCoordinates)) {
+ if (zoomerLocation.X < screenRectangle.X) {
+ zoomerLocation.X = screenRectangle.X;
+ } else if (zoomerLocation.X + Width > screenRectangle.X + screenRectangle.Width) {
+ zoomerLocation.X = screenCoordinates.X - Width - 5 - hotspot.X;
+ }
+
+ if (zoomerLocation.Y < screenRectangle.Y) {
+ zoomerLocation.Y = screenRectangle.Y;
+ } else if (zoomerLocation.Y + Height > screenRectangle.Y + screenRectangle.Height) {
+ zoomerLocation.Y = screenCoordinates.Y - Height - 5 - hotspot.Y;
+ }
+ break;
+ }
+ }
+ Location = zoomerLocation;
+ Update();
+ }
+
+ ///
+ /// Get the color from the pixel on the screen at "x,y"
+ ///
+ /// Point with the coordinates
+ /// Color at the specified screenCoordinates
+ private static Color GetPixelColor(Point screenCoordinates) {
+ using (SafeWindowDcHandle screenDC = SafeWindowDcHandle.FromDesktop()) {
+ try {
+ uint pixel = GDI32.GetPixel(screenDC, screenCoordinates.X, screenCoordinates.Y);
+ Color color = Color.FromArgb(255, (int)(pixel & 0xFF), (int)(pixel & 0xFF00) >> 8, (int)(pixel & 0xFF0000) >> 16);
+ return color;
+ } catch (Exception) {
+ return Color.Empty;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs b/Greenshot/Forms/PrintOptionsDialog.Designer.cs
similarity index 76%
rename from src/Greenshot/Forms/PrintOptionsDialog.Designer.cs
rename to Greenshot/Forms/PrintOptionsDialog.Designer.cs
index 9f9d0a13a..57071d867 100644
--- a/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs
+++ b/Greenshot/Forms/PrintOptionsDialog.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,11 +16,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
namespace Greenshot.Forms
{
partial class PrintOptionsDialog
@@ -51,26 +48,27 @@ namespace Greenshot.Forms
///
private void InitializeComponent()
{
- this.checkbox_dontaskagain = new GreenshotCheckBox();
- this.checkboxAllowShrink = new GreenshotCheckBox();
- this.checkboxAllowEnlarge = new GreenshotCheckBox();
- this.checkboxAllowCenter = new GreenshotCheckBox();
- this.checkboxAllowRotate = new GreenshotCheckBox();
- this.button_ok = new GreenshotButton();
- this.checkboxDateTime = new GreenshotCheckBox();
- this.button_cancel = new GreenshotButton();
- this.checkboxPrintInverted = new GreenshotCheckBox();
- this.radioBtnGrayScale = new GreenshotRadioButton();
- this.radioBtnMonochrome = new GreenshotRadioButton();
- this.groupBoxPrintLayout = new GreenshotGroupBox();
- this.groupBoxColors = new GreenshotGroupBox();
- this.radioBtnColorPrint = new GreenshotRadioButton();
+ this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowShrink = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowEnlarge = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowCenter = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowRotate = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
+ this.checkboxDateTime = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.button_cancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.checkboxPrintInverted = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.radioBtnGrayScale = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.radioBtnMonochrome = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.groupBoxPrintLayout = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.groupBoxColors = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.radioBtnColorPrint = new GreenshotPlugin.Controls.GreenshotRadioButton();
this.groupBoxPrintLayout.SuspendLayout();
this.groupBoxColors.SuspendLayout();
this.SuspendLayout();
//
// checkbox_dontaskagain
//
+ this.checkbox_dontaskagain.AutoSize = true;
this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.LanguageKey = "printoptions_dontaskagain";
@@ -84,12 +82,13 @@ namespace Greenshot.Forms
//
// checkboxAllowShrink
//
+ this.checkboxAllowShrink.AutoSize = true;
this.checkboxAllowShrink.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowShrink.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
- this.checkboxAllowShrink.PropertyName = nameof(coreConfiguration.OutputPrintAllowShrink);
+ this.checkboxAllowShrink.PropertyName = "OutputPrintAllowShrink";
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
this.checkboxAllowShrink.TabIndex = 2;
this.checkboxAllowShrink.Text = "Shrink printout to fit paper size";
@@ -98,12 +97,13 @@ namespace Greenshot.Forms
//
// checkboxAllowEnlarge
//
+ this.checkboxAllowEnlarge.AutoSize = true;
this.checkboxAllowEnlarge.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowEnlarge.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
- this.checkboxAllowEnlarge.PropertyName = nameof(coreConfiguration.OutputPrintAllowEnlarge);
+ this.checkboxAllowEnlarge.PropertyName = "OutputPrintAllowEnlarge";
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
this.checkboxAllowEnlarge.TabIndex = 3;
this.checkboxAllowEnlarge.Text = "Enlarge printout to fit paper size";
@@ -112,12 +112,13 @@ namespace Greenshot.Forms
//
// checkboxAllowCenter
//
+ this.checkboxAllowCenter.AutoSize = true;
this.checkboxAllowCenter.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowCenter.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
- this.checkboxAllowCenter.PropertyName = nameof(coreConfiguration.OutputPrintCenter);
+ this.checkboxAllowCenter.PropertyName = "OutputPrintCenter";
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
this.checkboxAllowCenter.TabIndex = 5;
this.checkboxAllowCenter.Text = "Center printout on page";
@@ -126,12 +127,13 @@ namespace Greenshot.Forms
//
// checkboxAllowRotate
//
+ this.checkboxAllowRotate.AutoSize = true;
this.checkboxAllowRotate.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowRotate.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
- this.checkboxAllowRotate.PropertyName = nameof(coreConfiguration.OutputPrintAllowRotate);
+ this.checkboxAllowRotate.PropertyName = "OutputPrintAllowRotate";
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
this.checkboxAllowRotate.TabIndex = 4;
this.checkboxAllowRotate.Text = "Rotate printout to page orientation";
@@ -153,12 +155,13 @@ namespace Greenshot.Forms
//
// checkboxDateTime
//
+ this.checkboxDateTime.AutoSize = true;
this.checkboxDateTime.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxDateTime.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
this.checkboxDateTime.Name = "checkboxDateTime";
- this.checkboxDateTime.PropertyName = nameof(coreConfiguration.OutputPrintFooter);
+ this.checkboxDateTime.PropertyName = "OutputPrintFooter";
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
this.checkboxDateTime.TabIndex = 6;
this.checkboxDateTime.Text = "Print date / time at bottom of page";
@@ -179,12 +182,13 @@ namespace Greenshot.Forms
//
// checkboxPrintInverted
//
+ this.checkboxPrintInverted.AutoSize = true;
this.checkboxPrintInverted.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxPrintInverted.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
- this.checkboxPrintInverted.PropertyName = nameof(coreConfiguration.OutputPrintInverted);
+ this.checkboxPrintInverted.PropertyName = "OutputPrintInverted";
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
this.checkboxPrintInverted.TabIndex = 14;
this.checkboxPrintInverted.Text = "Print with inverted colors";
@@ -193,12 +197,13 @@ namespace Greenshot.Forms
//
// radioBtnGrayScale
//
+ this.radioBtnGrayScale.AutoSize = true;
this.radioBtnGrayScale.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnGrayScale.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
- this.radioBtnGrayScale.PropertyName = nameof(coreConfiguration.OutputPrintGrayscale);
+ this.radioBtnGrayScale.PropertyName = "OutputPrintGrayscale";
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
this.radioBtnGrayScale.TabIndex = 12;
this.radioBtnGrayScale.Text = "Force grayscale printing";
@@ -207,12 +212,13 @@ namespace Greenshot.Forms
//
// radioBtnMonochrome
//
+ this.radioBtnMonochrome.AutoSize = true;
this.radioBtnMonochrome.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnMonochrome.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
- this.radioBtnMonochrome.PropertyName = nameof(coreConfiguration.OutputPrintMonochrome);
+ this.radioBtnMonochrome.PropertyName = "OutputPrintMonochrome";
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
this.radioBtnMonochrome.TabIndex = 13;
this.radioBtnMonochrome.Text = "Force black/white printing";
@@ -221,6 +227,7 @@ namespace Greenshot.Forms
//
// groupBoxPrintLayout
//
+ this.groupBoxPrintLayout.AutoSize = true;
this.groupBoxPrintLayout.Controls.Add(this.checkboxDateTime);
this.groupBoxPrintLayout.Controls.Add(this.checkboxAllowShrink);
this.groupBoxPrintLayout.Controls.Add(this.checkboxAllowEnlarge);
@@ -236,6 +243,7 @@ namespace Greenshot.Forms
//
// groupBoxColors
//
+ this.groupBoxColors.AutoSize = true;
this.groupBoxColors.Controls.Add(this.checkboxPrintInverted);
this.groupBoxColors.Controls.Add(this.radioBtnColorPrint);
this.groupBoxColors.Controls.Add(this.radioBtnGrayScale);
@@ -250,11 +258,13 @@ namespace Greenshot.Forms
//
// radioBtnColorPrint
//
+ this.radioBtnColorPrint.AutoSize = true;
this.radioBtnColorPrint.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnColorPrint.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
+ this.radioBtnColorPrint.PropertyName = "OutputPrintColor";
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
this.radioBtnColorPrint.TabIndex = 11;
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -264,6 +274,7 @@ namespace Greenshot.Forms
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(355, 390);
this.Controls.Add(this.groupBoxColors);
this.Controls.Add(this.groupBoxPrintLayout);
@@ -284,19 +295,19 @@ namespace Greenshot.Forms
this.PerformLayout();
}
- private GreenshotRadioButton radioBtnGrayScale;
- private GreenshotCheckBox checkboxPrintInverted;
- private GreenshotButton button_cancel;
- private GreenshotCheckBox checkboxDateTime;
- private GreenshotButton button_ok;
- private GreenshotCheckBox checkboxAllowRotate;
- private GreenshotCheckBox checkboxAllowCenter;
- private GreenshotCheckBox checkboxAllowEnlarge;
- private GreenshotCheckBox checkboxAllowShrink;
- private GreenshotCheckBox checkbox_dontaskagain;
- private GreenshotRadioButton radioBtnMonochrome;
- private GreenshotGroupBox groupBoxPrintLayout;
- private GreenshotGroupBox groupBoxColors;
- private GreenshotRadioButton radioBtnColorPrint;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnGrayScale;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxPrintInverted;
+ private GreenshotPlugin.Controls.GreenshotButton button_cancel;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxDateTime;
+ private GreenshotPlugin.Controls.GreenshotButton button_ok;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowRotate;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowCenter;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowEnlarge;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowShrink;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnMonochrome;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxPrintLayout;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxColors;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnColorPrint;
}
}
diff --git a/Greenshot/Forms/PrintOptionsDialog.cs b/Greenshot/Forms/PrintOptionsDialog.cs
new file mode 100644
index 000000000..34884d402
--- /dev/null
+++ b/Greenshot/Forms/PrintOptionsDialog.cs
@@ -0,0 +1,53 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+
+namespace Greenshot.Forms {
+ ///
+ /// Description of PrintOptionsDialog.
+ ///
+ public partial class PrintOptionsDialog : BaseForm {
+ public PrintOptionsDialog() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ checkbox_dontaskagain.Checked = false;
+ }
+
+
+ private void Button_okClick(object sender, EventArgs e) {
+ // update config
+ coreConfiguration.OutputPrintPromptOptions = !checkbox_dontaskagain.Checked;
+ IniConfig.Save();
+ DialogResult = DialogResult.OK;
+ }
+
+ protected override void OnFieldsFilled() {
+ // the color radio button is not actually bound to a setting, but checked when monochrome/grayscale are not checked
+ if(!radioBtnGrayScale.Checked && !radioBtnMonochrome.Checked) {
+ radioBtnColorPrint.Checked = true;
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/ResizeSettingsForm.Designer.cs b/Greenshot/Forms/ResizeSettingsForm.Designer.cs
similarity index 77%
rename from src/Greenshot.Editor/Forms/ResizeSettingsForm.Designer.cs
rename to Greenshot/Forms/ResizeSettingsForm.Designer.cs
index 958ac5968..6061844ff 100644
--- a/src/Greenshot.Editor/Forms/ResizeSettingsForm.Designer.cs
+++ b/Greenshot/Forms/ResizeSettingsForm.Designer.cs
@@ -1,182 +1,180 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Editor.Forms {
- partial class ResizeSettingsForm {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.checkbox_aspectratio = new GreenshotCheckBox();
- this.label_width = new GreenshotLabel();
- this.label_height = new GreenshotLabel();
- this.textbox_height = new System.Windows.Forms.TextBox();
- this.textbox_width = new System.Windows.Forms.TextBox();
- this.combobox_width = new System.Windows.Forms.ComboBox();
- this.combobox_height = new System.Windows.Forms.ComboBox();
- this.SuspendLayout();
- //
- // buttonOK
- //
- this.buttonOK.LanguageKey = "OK";
- this.buttonOK.Location = new System.Drawing.Point(76, 87);
- this.buttonOK.Name = "buttonOK";
- this.buttonOK.Size = new System.Drawing.Size(75, 23);
- this.buttonOK.TabIndex = 6;
- this.buttonOK.UseVisualStyleBackColor = true;
- this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
- //
- // buttonCancel
- //
- this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.buttonCancel.LanguageKey = "CANCEL";
- this.buttonCancel.Location = new System.Drawing.Point(157, 87);
- this.buttonCancel.Name = "buttonCancel";
- this.buttonCancel.Size = new System.Drawing.Size(75, 23);
- this.buttonCancel.TabIndex = 7;
- this.buttonCancel.UseVisualStyleBackColor = true;
- //
- // checkbox_aspectratio
- //
- this.checkbox_aspectratio.LanguageKey = "editor_resize_aspectratio";
- this.checkbox_aspectratio.Location = new System.Drawing.Point(22, 64);
- this.checkbox_aspectratio.Name = "checkbox_aspectratio";
- this.checkbox_aspectratio.Size = new System.Drawing.Size(124, 17);
- this.checkbox_aspectratio.TabIndex = 5;
- this.checkbox_aspectratio.UseVisualStyleBackColor = true;
- //
- // label_width
- //
- this.label_width.LanguageKey = "editor_resize_width";
- this.label_width.Location = new System.Drawing.Point(19, 15);
- this.label_width.Name = "label_width";
- this.label_width.Size = new System.Drawing.Size(35, 13);
- this.label_width.TabIndex = 14;
- //
- // label_height
- //
- this.label_height.LanguageKey = "editor_resize_height";
- this.label_height.Location = new System.Drawing.Point(19, 38);
- this.label_height.Name = "label_height";
- this.label_height.Size = new System.Drawing.Size(38, 13);
- this.label_height.TabIndex = 15;
- //
- // textbox_height
- //
- this.textbox_height.Location = new System.Drawing.Point(90, 38);
- this.textbox_height.Name = "textbox_height";
- this.textbox_height.Size = new System.Drawing.Size(69, 20);
- this.textbox_height.TabIndex = 3;
- this.textbox_height.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Textbox_KeyUp);
- this.textbox_height.Validating += new System.ComponentModel.CancelEventHandler(this.Textbox_Validating);
- //
- // textbox_width
- //
- this.textbox_width.Location = new System.Drawing.Point(90, 12);
- this.textbox_width.Name = "textbox_width";
- this.textbox_width.Size = new System.Drawing.Size(69, 20);
- this.textbox_width.TabIndex = 1;
- this.textbox_width.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Textbox_KeyUp);
- this.textbox_width.Validating += new System.ComponentModel.CancelEventHandler(this.Textbox_Validating);
- //
- // combobox_width
- //
- this.combobox_width.FormattingEnabled = true;
- this.combobox_width.Location = new System.Drawing.Point(165, 11);
- this.combobox_width.Name = "combobox_width";
- this.combobox_width.Size = new System.Drawing.Size(65, 21);
- this.combobox_width.TabIndex = 2;
- this.combobox_width.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- //
- // combobox_height
- //
- this.combobox_height.FormattingEnabled = true;
- this.combobox_height.ItemHeight = 13;
- this.combobox_height.Location = new System.Drawing.Point(165, 38);
- this.combobox_height.Name = "combobox_height";
- this.combobox_height.Size = new System.Drawing.Size(65, 21);
- this.combobox_height.TabIndex = 4;
- this.combobox_height.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- //
- // ResizeSettingsForm
- //
- this.AcceptButton = this.buttonOK;
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.CancelButton = this.buttonCancel;
- this.ClientSize = new System.Drawing.Size(244, 122);
- this.ControlBox = false;
- this.Controls.Add(this.combobox_height);
- this.Controls.Add(this.combobox_width);
- this.Controls.Add(this.textbox_width);
- this.Controls.Add(this.textbox_height);
- this.Controls.Add(this.label_height);
- this.Controls.Add(this.label_width);
- this.Controls.Add(this.checkbox_aspectratio);
- this.Controls.Add(this.buttonCancel);
- this.Controls.Add(this.buttonOK);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
- this.LanguageKey = "editor_resize_settings";
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "ResizeSettingsForm";
- this.ShowIcon = false;
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private GreenshotButton buttonOK;
- private GreenshotButton buttonCancel;
- private GreenshotCheckBox checkbox_aspectratio;
- private GreenshotLabel label_width;
- private GreenshotLabel label_height;
- private System.Windows.Forms.TextBox textbox_height;
- private System.Windows.Forms.TextBox textbox_width;
- private System.Windows.Forms.ComboBox combobox_width;
- private System.Windows.Forms.ComboBox combobox_height;
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace Greenshot.Forms {
+ partial class ResizeSettingsForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.checkbox_aspectratio = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_width = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_height = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textbox_height = new System.Windows.Forms.TextBox();
+ this.textbox_width = new System.Windows.Forms.TextBox();
+ this.combobox_width = new System.Windows.Forms.ComboBox();
+ this.combobox_height = new System.Windows.Forms.ComboBox();
+ this.SuspendLayout();
+ //
+ // buttonOK
+ //
+ this.buttonOK.LanguageKey = "OK";
+ this.buttonOK.Location = new System.Drawing.Point(76, 87);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 23);
+ this.buttonOK.TabIndex = 6;
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.LanguageKey = "CANCEL";
+ this.buttonCancel.Location = new System.Drawing.Point(157, 87);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 7;
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // checkbox_aspectratio
+ //
+ this.checkbox_aspectratio.AutoSize = true;
+ this.checkbox_aspectratio.LanguageKey = "editor_resize_aspectratio";
+ this.checkbox_aspectratio.Location = new System.Drawing.Point(22, 64);
+ this.checkbox_aspectratio.Name = "checkbox_aspectratio";
+ this.checkbox_aspectratio.Size = new System.Drawing.Size(124, 17);
+ this.checkbox_aspectratio.TabIndex = 5;
+ this.checkbox_aspectratio.UseVisualStyleBackColor = true;
+ //
+ // label_width
+ //
+ this.label_width.AutoSize = true;
+ this.label_width.LanguageKey = "editor_resize_width";
+ this.label_width.Location = new System.Drawing.Point(19, 15);
+ this.label_width.Name = "label_width";
+ this.label_width.Size = new System.Drawing.Size(35, 13);
+ this.label_width.TabIndex = 14;
+ //
+ // label_height
+ //
+ this.label_height.AutoSize = true;
+ this.label_height.LanguageKey = "editor_resize_height";
+ this.label_height.Location = new System.Drawing.Point(19, 38);
+ this.label_height.Name = "label_height";
+ this.label_height.Size = new System.Drawing.Size(38, 13);
+ this.label_height.TabIndex = 15;
+ //
+ // textbox_height
+ //
+ this.textbox_height.Location = new System.Drawing.Point(90, 38);
+ this.textbox_height.Name = "textbox_height";
+ this.textbox_height.Size = new System.Drawing.Size(69, 20);
+ this.textbox_height.TabIndex = 3;
+ this.textbox_height.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textbox_KeyUp);
+ this.textbox_height.Validating += new System.ComponentModel.CancelEventHandler(this.textbox_Validating);
+ //
+ // textbox_width
+ //
+ this.textbox_width.Location = new System.Drawing.Point(90, 12);
+ this.textbox_width.Name = "textbox_width";
+ this.textbox_width.Size = new System.Drawing.Size(69, 20);
+ this.textbox_width.TabIndex = 1;
+ this.textbox_width.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textbox_KeyUp);
+ this.textbox_width.Validating += new System.ComponentModel.CancelEventHandler(this.textbox_Validating);
+ //
+ // combobox_width
+ //
+ this.combobox_width.FormattingEnabled = true;
+ this.combobox_width.Location = new System.Drawing.Point(165, 11);
+ this.combobox_width.Name = "combobox_width";
+ this.combobox_width.Size = new System.Drawing.Size(65, 21);
+ this.combobox_width.TabIndex = 2;
+ //
+ // combobox_height
+ //
+ this.combobox_height.FormattingEnabled = true;
+ this.combobox_height.ItemHeight = 13;
+ this.combobox_height.Location = new System.Drawing.Point(165, 38);
+ this.combobox_height.Name = "combobox_height";
+ this.combobox_height.Size = new System.Drawing.Size(65, 21);
+ this.combobox_height.TabIndex = 4;
+ //
+ // ResizeSettingsForm
+ //
+ this.AcceptButton = this.buttonOK;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.buttonCancel;
+ this.ClientSize = new System.Drawing.Size(244, 122);
+ this.ControlBox = false;
+ this.Controls.Add(this.combobox_height);
+ this.Controls.Add(this.combobox_width);
+ this.Controls.Add(this.textbox_width);
+ this.Controls.Add(this.textbox_height);
+ this.Controls.Add(this.label_height);
+ this.Controls.Add(this.label_width);
+ this.Controls.Add(this.checkbox_aspectratio);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.LanguageKey = "editor_resize_settings";
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "ResizeSettingsForm";
+ this.ShowIcon = false;
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_aspectratio;
+ private GreenshotPlugin.Controls.GreenshotLabel label_width;
+ private GreenshotPlugin.Controls.GreenshotLabel label_height;
+ private System.Windows.Forms.TextBox textbox_height;
+ private System.Windows.Forms.TextBox textbox_width;
+ private System.Windows.Forms.ComboBox combobox_width;
+ private System.Windows.Forms.ComboBox combobox_height;
+ }
}
\ No newline at end of file
diff --git a/Greenshot/Forms/ResizeSettingsForm.cs b/Greenshot/Forms/ResizeSettingsForm.cs
new file mode 100644
index 000000000..4471ed443
--- /dev/null
+++ b/Greenshot/Forms/ResizeSettingsForm.cs
@@ -0,0 +1,164 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Effects;
+
+namespace Greenshot.Forms {
+ ///
+ /// A form to set the resize settings
+ ///
+ public partial class ResizeSettingsForm : BaseForm {
+ private readonly ResizeEffect _effect;
+ private readonly string _valuePercent;
+ private double _newWidth, _newHeight;
+
+ public ResizeSettingsForm(ResizeEffect effect) {
+ _effect = effect;
+ InitializeComponent();
+ var valuePixel = Language.GetString("editor_resize_pixel");
+ _valuePercent = Language.GetString("editor_resize_percent");
+ combobox_width.Items.Add(valuePixel);
+ combobox_width.Items.Add(_valuePercent);
+ combobox_width.SelectedItem = valuePixel;
+ combobox_height.Items.Add(valuePixel);
+ combobox_height.Items.Add(_valuePercent);
+ combobox_height.SelectedItem = valuePixel;
+
+ textbox_width.Text = effect.Width.ToString();
+ textbox_height.Text = effect.Height.ToString();
+ _newWidth = effect.Width;
+ _newHeight = effect.Height;
+ combobox_width.SelectedIndexChanged += combobox_SelectedIndexChanged;
+ combobox_height.SelectedIndexChanged += combobox_SelectedIndexChanged;
+
+ checkbox_aspectratio.Checked = effect.MaintainAspectRatio;
+ }
+
+ private void buttonOK_Click(object sender, EventArgs e) {
+ if (_newWidth != _effect.Width || _newHeight != _effect.Height) {
+ _effect.Width = (int)_newWidth;
+ _effect.Height = (int)_newHeight;
+ _effect.MaintainAspectRatio = checkbox_aspectratio.Checked;
+ DialogResult = DialogResult.OK;
+ }
+ }
+
+ private static bool Validate(object sender) {
+ TextBox textbox = sender as TextBox;
+ if (textbox != null) {
+ double numberEntered;
+ if (!double.TryParse(textbox.Text, out numberEntered)) {
+ textbox.BackColor = Color.Red;
+ return false;
+ }
+ textbox.BackColor = Color.White;
+ }
+ return true;
+ }
+
+ private void DisplayWidth() {
+ double displayValue;
+ if (_valuePercent.Equals(combobox_width.SelectedItem)) {
+ displayValue = _newWidth / _effect.Width * 100d;
+ } else {
+ displayValue = _newWidth;
+ }
+ textbox_width.Text = ((int)displayValue).ToString();
+ }
+
+ private void DisplayHeight() {
+ double displayValue;
+ if (_valuePercent.Equals(combobox_height.SelectedItem)) {
+ displayValue = _newHeight / _effect.Height * 100d;
+ } else {
+ displayValue = _newHeight;
+ }
+ textbox_height.Text = ((int)displayValue).ToString();
+ }
+
+ private void textbox_KeyUp(object sender, KeyEventArgs e) {
+ if (!Validate(sender)) {
+ return;
+ }
+ TextBox textbox = sender as TextBox;
+ if (string.IsNullOrEmpty(textbox?.Text)) {
+ return;
+ }
+ bool isWidth = textbox == textbox_width;
+ if (!checkbox_aspectratio.Checked) {
+ if (isWidth) {
+ _newWidth = double.Parse(textbox_width.Text);
+ } else {
+ _newHeight = double.Parse(textbox_height.Text);
+ }
+ return;
+ }
+ var isPercent = _valuePercent.Equals(isWidth ? combobox_width.SelectedItem : combobox_height.SelectedItem);
+ double percent;
+ if (isWidth) {
+ if (isPercent) {
+ percent = double.Parse(textbox_width.Text);
+ _newWidth = _effect.Width / 100d * percent;
+ } else {
+ _newWidth = double.Parse(textbox_width.Text);
+ percent = double.Parse(textbox_width.Text) / _effect.Width * 100d;
+ }
+ if (checkbox_aspectratio.Checked) {
+ _newHeight = _effect.Height / 100d * percent;
+ DisplayHeight();
+ }
+ } else {
+ if (isPercent) {
+ percent = double.Parse(textbox_height.Text);
+ _newHeight = _effect.Height / 100d * percent;
+ } else {
+ _newHeight = double.Parse(textbox_height.Text);
+ percent = double.Parse(textbox_height.Text) / _effect.Height * 100d;
+ }
+ if (checkbox_aspectratio.Checked) {
+ _newWidth = _effect.Width / 100d * percent;
+ DisplayWidth();
+ }
+ }
+ }
+
+ private void textbox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+ Validate(sender);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void combobox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (Validate(textbox_width)) {
+ DisplayWidth();
+ }
+ if (Validate(textbox_height)) {
+ DisplayHeight();
+ }
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/SettingsForm.Designer.cs b/Greenshot/Forms/SettingsForm.Designer.cs
similarity index 76%
rename from src/Greenshot/Forms/SettingsForm.Designer.cs
rename to Greenshot/Forms/SettingsForm.Designer.cs
index 6bea356df..c07019503 100644
--- a/src/Greenshot/Forms/SettingsForm.Designer.cs
+++ b/Greenshot/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,15 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-using Greenshot.Base.Core;
-using Greenshot.Editor.Configuration;
-using Greenshot.Editor.Controls;
-
-namespace Greenshot.Forms {
+namespace Greenshot {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -53,103 +47,103 @@ namespace Greenshot.Forms {
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm));
- this.textbox_storagelocation = new GreenshotTextBox();
- this.label_storagelocation = new GreenshotLabel();
- this.settings_cancel = new GreenshotButton();
- this.settings_confirm = new GreenshotButton();
+ this.textbox_storagelocation = new GreenshotPlugin.Controls.GreenshotTextBox();
+ this.label_storagelocation = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.settings_cancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.settings_confirm = new GreenshotPlugin.Controls.GreenshotButton();
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
this.browse = new System.Windows.Forms.Button();
- this.label_screenshotname = new GreenshotLabel();
- this.textbox_screenshotname = new GreenshotTextBox();
- this.label_language = new GreenshotLabel();
+ this.label_screenshotname = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textbox_screenshotname = new GreenshotPlugin.Controls.GreenshotTextBox();
+ this.label_language = new GreenshotPlugin.Controls.GreenshotLabel();
this.combobox_language = new System.Windows.Forms.ComboBox();
- this.combobox_primaryimageformat = new GreenshotComboBox();
- this.label_primaryimageformat = new GreenshotLabel();
- this.groupbox_preferredfilesettings = new GreenshotGroupBox();
+ this.combobox_primaryimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_primaryimageformat = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.groupbox_preferredfilesettings = new GreenshotPlugin.Controls.GreenshotGroupBox();
this.btnPatternHelp = new System.Windows.Forms.Button();
- this.checkbox_copypathtoclipboard = new GreenshotCheckBox();
- this.checkbox_zoomer = new GreenshotCheckBox();
- this.groupbox_applicationsettings = new GreenshotGroupBox();
- this.checkbox_autostartshortcut = new GreenshotCheckBox();
- this.groupbox_qualitysettings = new GreenshotGroupBox();
- this.checkbox_reducecolors = new GreenshotCheckBox();
- this.checkbox_alwaysshowqualitydialog = new GreenshotCheckBox();
- this.label_jpegquality = new GreenshotLabel();
+ this.checkbox_copypathtoclipboard = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_zoomer = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.groupbox_applicationsettings = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_autostartshortcut = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.groupbox_qualitysettings = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_reducecolors = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_alwaysshowqualitydialog = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_jpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
- this.groupbox_destination = new GreenshotGroupBox();
- this.checkbox_picker = new GreenshotCheckBox();
+ this.groupbox_destination = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_picker = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.listview_destinations = new System.Windows.Forms.ListView();
this.destination = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.tabcontrol = new System.Windows.Forms.TabControl();
- this.tab_general = new GreenshotTabPage();
- this.groupbox_network = new GreenshotGroupBox();
+ this.tab_general = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.groupbox_network = new GreenshotPlugin.Controls.GreenshotGroupBox();
this.numericUpDown_daysbetweencheck = new System.Windows.Forms.NumericUpDown();
- this.label_checkperiod = new GreenshotLabel();
- this.checkbox_usedefaultproxy = new GreenshotCheckBox();
- this.groupbox_hotkeys = new GreenshotGroupBox();
- this.label_lastregion_hotkey = new GreenshotLabel();
- this.lastregion_hotkeyControl = new HotkeyControl();
- this.label_ie_hotkey = new GreenshotLabel();
- this.ie_hotkeyControl = new HotkeyControl();
- this.label_region_hotkey = new GreenshotLabel();
- this.label_window_hotkey = new GreenshotLabel();
- this.label_fullscreen_hotkey = new GreenshotLabel();
- this.region_hotkeyControl = new HotkeyControl();
- this.window_hotkeyControl = new HotkeyControl();
- this.fullscreen_hotkeyControl = new HotkeyControl();
- this.tab_capture = new GreenshotTabPage();
- this.groupbox_editor = new GreenshotGroupBox();
+ this.label_checkperiod = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkbox_usedefaultproxy = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.groupbox_hotkeys = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.label_lastregion_hotkey = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.lastregion_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl();
+ this.label_ie_hotkey = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.ie_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl();
+ this.label_region_hotkey = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_window_hotkey = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_fullscreen_hotkey = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.region_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl();
+ this.window_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl();
+ this.fullscreen_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl();
+ this.tab_capture = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.groupbox_editor = new GreenshotPlugin.Controls.GreenshotGroupBox();
this.numericUpdownIconSize = new System.Windows.Forms.NumericUpDown();
- this.label_icon_size = new GreenshotLabel();
- this.checkbox_editor_match_capture_size = new GreenshotCheckBox();
- this.groupbox_iecapture = new GreenshotGroupBox();
- this.checkbox_ie_capture = new GreenshotCheckBox();
- this.groupbox_windowscapture = new GreenshotGroupBox();
- this.colorButton_window_background = new ColorButton();
- this.radiobuttonWindowCapture = new GreenshotRadioButton();
- this.radiobuttonInteractiveCapture = new GreenshotRadioButton();
+ this.label_icon_size = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkbox_editor_match_capture_size = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.groupbox_iecapture = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_ie_capture = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.groupbox_windowscapture = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.colorButton_window_background = new Greenshot.Controls.ColorButton();
+ this.radiobuttonWindowCapture = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.radiobuttonInteractiveCapture = new GreenshotPlugin.Controls.GreenshotRadioButton();
this.combobox_window_capture_mode = new System.Windows.Forms.ComboBox();
- this.groupbox_capture = new GreenshotGroupBox();
- this.checkbox_notifications = new GreenshotCheckBox();
- this.checkbox_playsound = new GreenshotCheckBox();
- this.checkbox_capture_mousepointer = new GreenshotCheckBox();
+ this.groupbox_capture = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_notifications = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_playsound = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_capture_mousepointer = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.numericUpDownWaitTime = new System.Windows.Forms.NumericUpDown();
- this.label_waittime = new GreenshotLabel();
- this.tab_output = new GreenshotTabPage();
- this.tab_destinations = new GreenshotTabPage();
- this.tab_printer = new GreenshotTabPage();
- this.groupBoxColors = new GreenshotGroupBox();
- this.checkboxPrintInverted = new GreenshotCheckBox();
- this.radioBtnColorPrint = new GreenshotRadioButton();
- this.radioBtnGrayScale = new GreenshotRadioButton();
- this.radioBtnMonochrome = new GreenshotRadioButton();
- this.groupBoxPrintLayout = new GreenshotGroupBox();
- this.checkboxDateTime = new GreenshotCheckBox();
- this.checkboxAllowShrink = new GreenshotCheckBox();
- this.checkboxAllowEnlarge = new GreenshotCheckBox();
- this.checkboxAllowRotate = new GreenshotCheckBox();
- this.checkboxAllowCenter = new GreenshotCheckBox();
- this.checkbox_alwaysshowprintoptionsdialog = new GreenshotCheckBox();
- this.tab_plugins = new GreenshotTabPage();
- this.groupbox_plugins = new GreenshotGroupBox();
+ this.label_waittime = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.tab_output = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.tab_destinations = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.tab_printer = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.groupBoxColors = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkboxPrintInverted = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.radioBtnColorPrint = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.radioBtnGrayScale = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.radioBtnMonochrome = new GreenshotPlugin.Controls.GreenshotRadioButton();
+ this.groupBoxPrintLayout = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkboxDateTime = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowShrink = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowEnlarge = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowRotate = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkboxAllowCenter = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_alwaysshowprintoptionsdialog = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.tab_plugins = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.groupbox_plugins = new GreenshotPlugin.Controls.GreenshotGroupBox();
this.listview_plugins = new System.Windows.Forms.ListView();
- this.button_pluginconfigure = new GreenshotButton();
- this.tab_expert = new GreenshotTabPage();
- this.groupbox_expert = new GreenshotGroupBox();
- this.checkbox_reuseeditor = new GreenshotCheckBox();
- this.checkbox_minimizememoryfootprint = new GreenshotCheckBox();
- this.checkbox_checkunstableupdates = new GreenshotCheckBox();
- this.checkbox_suppresssavedialogatclose = new GreenshotCheckBox();
- this.label_counter = new GreenshotLabel();
- this.textbox_counter = new GreenshotTextBox();
- this.label_footerpattern = new GreenshotLabel();
- this.textbox_footerpattern = new GreenshotTextBox();
- this.checkbox_thumbnailpreview = new GreenshotCheckBox();
- this.checkbox_optimizeforrdp = new GreenshotCheckBox();
- this.checkbox_autoreducecolors = new GreenshotCheckBox();
- this.label_clipboardformats = new GreenshotLabel();
- this.checkbox_enableexpert = new GreenshotCheckBox();
+ this.button_pluginconfigure = new GreenshotPlugin.Controls.GreenshotButton();
+ this.tab_expert = new GreenshotPlugin.Controls.GreenshotTabPage();
+ this.groupbox_expert = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.checkbox_reuseeditor = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_minimizememoryfootprint = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_checkunstableupdates = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_suppresssavedialogatclose = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_counter = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textbox_counter = new GreenshotPlugin.Controls.GreenshotTextBox();
+ this.label_footerpattern = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textbox_footerpattern = new GreenshotPlugin.Controls.GreenshotTextBox();
+ this.checkbox_thumbnailpreview = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_optimizeforrdp = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_autoreducecolors = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_clipboardformats = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkbox_enableexpert = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.listview_clipboardformats = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupbox_preferredfilesettings.SuspendLayout();
@@ -237,7 +231,7 @@ namespace Greenshot.Forms {
//
this.textbox_screenshotname.Location = new System.Drawing.Point(138, 41);
this.textbox_screenshotname.Name = "textbox_screenshotname";
- this.textbox_screenshotname.PropertyName = nameof(CoreConfiguration.OutputFileFilenamePattern);
+ this.textbox_screenshotname.PropertyName = "OutputFileFilenamePattern";
this.textbox_screenshotname.Size = new System.Drawing.Size(233, 20);
this.textbox_screenshotname.TabIndex = 3;
this.textbox_screenshotname.TextChanged += new System.EventHandler(this.FilenamePatternChanged);
@@ -266,7 +260,7 @@ namespace Greenshot.Forms {
this.combobox_primaryimageformat.FormattingEnabled = true;
this.combobox_primaryimageformat.Location = new System.Drawing.Point(138, 64);
this.combobox_primaryimageformat.Name = "combobox_primaryimageformat";
- this.combobox_primaryimageformat.PropertyName = nameof(CoreConfiguration.OutputFileFormat);
+ this.combobox_primaryimageformat.PropertyName = "OutputFileFormat";
this.combobox_primaryimageformat.Size = new System.Drawing.Size(268, 21);
this.combobox_primaryimageformat.TabIndex = 5;
//
@@ -311,7 +305,7 @@ namespace Greenshot.Forms {
this.checkbox_copypathtoclipboard.LanguageKey = "settings_copypathtoclipboard";
this.checkbox_copypathtoclipboard.Location = new System.Drawing.Point(12, 89);
this.checkbox_copypathtoclipboard.Name = "checkbox_copypathtoclipboard";
- this.checkbox_copypathtoclipboard.PropertyName = nameof(CoreConfiguration.OutputFileCopyPathToClipboard);
+ this.checkbox_copypathtoclipboard.PropertyName = "OutputFileCopyPathToClipboard";
this.checkbox_copypathtoclipboard.Size = new System.Drawing.Size(394, 24);
this.checkbox_copypathtoclipboard.TabIndex = 6;
this.checkbox_copypathtoclipboard.UseVisualStyleBackColor = true;
@@ -376,7 +370,7 @@ namespace Greenshot.Forms {
this.checkbox_reducecolors.LanguageKey = "settings_reducecolors";
this.checkbox_reducecolors.Location = new System.Drawing.Point(12, 72);
this.checkbox_reducecolors.Name = "checkbox_reducecolors";
- this.checkbox_reducecolors.PropertyName = nameof(CoreConfiguration.OutputFileReduceColors);
+ this.checkbox_reducecolors.PropertyName = "OutputFileReduceColors";
this.checkbox_reducecolors.Size = new System.Drawing.Size(394, 25);
this.checkbox_reducecolors.TabIndex = 10;
this.checkbox_reducecolors.UseVisualStyleBackColor = true;
@@ -386,7 +380,7 @@ namespace Greenshot.Forms {
this.checkbox_alwaysshowqualitydialog.LanguageKey = "settings_alwaysshowqualitydialog";
this.checkbox_alwaysshowqualitydialog.Location = new System.Drawing.Point(12, 50);
this.checkbox_alwaysshowqualitydialog.Name = "checkbox_alwaysshowqualitydialog";
- this.checkbox_alwaysshowqualitydialog.PropertyName = nameof(CoreConfiguration.OutputFilePromptQuality);
+ this.checkbox_alwaysshowqualitydialog.PropertyName = "OutputFilePromptQuality";
this.checkbox_alwaysshowqualitydialog.Size = new System.Drawing.Size(394, 25);
this.checkbox_alwaysshowqualitydialog.TabIndex = 9;
this.checkbox_alwaysshowqualitydialog.UseVisualStyleBackColor = true;
@@ -528,7 +522,7 @@ namespace Greenshot.Forms {
this.checkbox_usedefaultproxy.LanguageKey = "settings_usedefaultproxy";
this.checkbox_usedefaultproxy.Location = new System.Drawing.Point(7, 11);
this.checkbox_usedefaultproxy.Name = "checkbox_usedefaultproxy";
- this.checkbox_usedefaultproxy.PropertyName = nameof(CoreConfiguration.UseProxy);
+ this.checkbox_usedefaultproxy.PropertyName = "UseProxy";
this.checkbox_usedefaultproxy.Size = new System.Drawing.Size(397, 25);
this.checkbox_usedefaultproxy.TabIndex = 7;
this.checkbox_usedefaultproxy.UseVisualStyleBackColor = true;
@@ -566,7 +560,7 @@ namespace Greenshot.Forms {
this.lastregion_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
this.lastregion_hotkeyControl.Location = new System.Drawing.Point(224, 94);
this.lastregion_hotkeyControl.Name = "lastregion_hotkeyControl";
- this.lastregion_hotkeyControl.PropertyName = nameof(CoreConfiguration.LastregionHotkey);
+ this.lastregion_hotkeyControl.PropertyName = "LastregionHotkey";
this.lastregion_hotkeyControl.Size = new System.Drawing.Size(179, 20);
this.lastregion_hotkeyControl.TabIndex = 5;
//
@@ -584,7 +578,7 @@ namespace Greenshot.Forms {
this.ie_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
this.ie_hotkeyControl.Location = new System.Drawing.Point(224, 120);
this.ie_hotkeyControl.Name = "ie_hotkeyControl";
- this.ie_hotkeyControl.PropertyName = nameof(CoreConfiguration.IEHotkey);
+ this.ie_hotkeyControl.PropertyName = "IEHotkey";
this.ie_hotkeyControl.Size = new System.Drawing.Size(179, 20);
this.ie_hotkeyControl.TabIndex = 6;
//
@@ -618,7 +612,7 @@ namespace Greenshot.Forms {
this.region_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
this.region_hotkeyControl.Location = new System.Drawing.Point(224, 68);
this.region_hotkeyControl.Name = "region_hotkeyControl";
- this.region_hotkeyControl.PropertyName = nameof(CoreConfiguration.RegionHotkey);
+ this.region_hotkeyControl.PropertyName = "RegionHotkey";
this.region_hotkeyControl.Size = new System.Drawing.Size(179, 20);
this.region_hotkeyControl.TabIndex = 4;
//
@@ -628,7 +622,7 @@ namespace Greenshot.Forms {
this.window_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
this.window_hotkeyControl.Location = new System.Drawing.Point(224, 42);
this.window_hotkeyControl.Name = "window_hotkeyControl";
- this.window_hotkeyControl.PropertyName = nameof(CoreConfiguration.WindowHotkey);
+ this.window_hotkeyControl.PropertyName = "WindowHotkey";
this.window_hotkeyControl.Size = new System.Drawing.Size(179, 20);
this.window_hotkeyControl.TabIndex = 3;
//
@@ -638,7 +632,7 @@ namespace Greenshot.Forms {
this.fullscreen_hotkeyControl.HotkeyModifiers = System.Windows.Forms.Keys.None;
this.fullscreen_hotkeyControl.Location = new System.Drawing.Point(224, 16);
this.fullscreen_hotkeyControl.Name = "fullscreen_hotkeyControl";
- this.fullscreen_hotkeyControl.PropertyName = nameof(CoreConfiguration.FullscreenHotkey);
+ this.fullscreen_hotkeyControl.PropertyName = "FullscreenHotkey";
this.fullscreen_hotkeyControl.Size = new System.Drawing.Size(179, 20);
this.fullscreen_hotkeyControl.TabIndex = 2;
//
@@ -670,7 +664,7 @@ namespace Greenshot.Forms {
this.checkbox_editor_match_capture_size.LanguageKey = "editor_match_capture_size";
this.checkbox_editor_match_capture_size.Location = new System.Drawing.Point(6, 19);
this.checkbox_editor_match_capture_size.Name = "checkbox_editor_match_capture_size";
- this.checkbox_editor_match_capture_size.PropertyName = nameof(EditorConfiguration.MatchSizeToCapture);
+ this.checkbox_editor_match_capture_size.PropertyName = "MatchSizeToCapture";
this.checkbox_editor_match_capture_size.SectionName = "Editor";
this.checkbox_editor_match_capture_size.Size = new System.Drawing.Size(397, 24);
this.checkbox_editor_match_capture_size.TabIndex = 11;
@@ -691,7 +685,7 @@ namespace Greenshot.Forms {
this.checkbox_ie_capture.LanguageKey = "settings_iecapture";
this.checkbox_ie_capture.Location = new System.Drawing.Point(6, 19);
this.checkbox_ie_capture.Name = "checkbox_ie_capture";
- this.checkbox_ie_capture.PropertyName = nameof(CoreConfiguration.IECapture);
+ this.checkbox_ie_capture.PropertyName = "IECapture";
this.checkbox_ie_capture.Size = new System.Drawing.Size(404, 24);
this.checkbox_ie_capture.TabIndex = 10;
this.checkbox_ie_capture.UseVisualStyleBackColor = true;
@@ -711,6 +705,7 @@ namespace Greenshot.Forms {
//
// colorButton_window_background
//
+ this.colorButton_window_background.AutoSize = true;
this.colorButton_window_background.Image = ((System.Drawing.Image)(resources.GetObject("colorButton_window_background.Image")));
this.colorButton_window_background.Location = new System.Drawing.Point(374, 37);
this.colorButton_window_background.Name = "colorButton_window_background";
@@ -721,6 +716,7 @@ namespace Greenshot.Forms {
//
// radiobuttonWindowCapture
//
+ this.radiobuttonWindowCapture.AutoSize = true;
this.radiobuttonWindowCapture.LanguageKey = "settings_window_capture_mode";
this.radiobuttonWindowCapture.Location = new System.Drawing.Point(11, 44);
this.radiobuttonWindowCapture.Name = "radiobuttonWindowCapture";
@@ -731,15 +727,16 @@ namespace Greenshot.Forms {
//
// radiobuttonInteractiveCapture
//
+ this.radiobuttonInteractiveCapture.AutoSize = true;
this.radiobuttonInteractiveCapture.LanguageKey = "settings_capture_windows_interactive";
this.radiobuttonInteractiveCapture.Location = new System.Drawing.Point(11, 20);
this.radiobuttonInteractiveCapture.Name = "radiobuttonInteractiveCapture";
- this.radiobuttonInteractiveCapture.PropertyName = nameof(CoreConfiguration.CaptureWindowsInteractive);
+ this.radiobuttonInteractiveCapture.PropertyName = "CaptureWindowsInteractive";
this.radiobuttonInteractiveCapture.Size = new System.Drawing.Size(203, 17);
this.radiobuttonInteractiveCapture.TabIndex = 6;
this.radiobuttonInteractiveCapture.TabStop = true;
this.radiobuttonInteractiveCapture.UseVisualStyleBackColor = true;
- this.radiobuttonInteractiveCapture.CheckedChanged += new System.EventHandler(this.Radiobutton_CheckedChanged);
+ this.radiobuttonInteractiveCapture.CheckedChanged += new System.EventHandler(this.radiobutton_CheckedChanged);
//
// combobox_window_capture_mode
//
@@ -772,7 +769,7 @@ namespace Greenshot.Forms {
this.checkbox_zoomer.LanguageKey = "settings_zoom";
this.checkbox_zoomer.Location = new System.Drawing.Point(11, 79);
this.checkbox_zoomer.Name = "checkbox_zoomer";
- this.checkbox_zoomer.PropertyName = nameof(CoreConfiguration.ZoomerEnabled);
+ this.checkbox_zoomer.PropertyName = "ZoomerEnabled";
this.checkbox_zoomer.Size = new System.Drawing.Size(399, 24);
this.checkbox_zoomer.TabIndex = 4;
this.checkbox_zoomer.UseVisualStyleBackColor = true;
@@ -782,7 +779,7 @@ namespace Greenshot.Forms {
this.checkbox_notifications.LanguageKey = "settings_shownotify";
this.checkbox_notifications.Location = new System.Drawing.Point(11, 59);
this.checkbox_notifications.Name = "checkbox_notifications";
- this.checkbox_notifications.PropertyName = nameof(CoreConfiguration.ShowTrayNotification);
+ this.checkbox_notifications.PropertyName = "ShowTrayNotification";
this.checkbox_notifications.Size = new System.Drawing.Size(399, 24);
this.checkbox_notifications.TabIndex = 3;
this.checkbox_notifications.UseVisualStyleBackColor = true;
@@ -792,7 +789,7 @@ namespace Greenshot.Forms {
this.checkbox_playsound.LanguageKey = "settings_playsound";
this.checkbox_playsound.Location = new System.Drawing.Point(11, 39);
this.checkbox_playsound.Name = "checkbox_playsound";
- this.checkbox_playsound.PropertyName = nameof(CoreConfiguration.PlayCameraSound);
+ this.checkbox_playsound.PropertyName = "PlayCameraSound";
this.checkbox_playsound.Size = new System.Drawing.Size(399, 24);
this.checkbox_playsound.TabIndex = 2;
this.checkbox_playsound.UseVisualStyleBackColor = true;
@@ -802,7 +799,7 @@ namespace Greenshot.Forms {
this.checkbox_capture_mousepointer.LanguageKey = "settings_capture_mousepointer";
this.checkbox_capture_mousepointer.Location = new System.Drawing.Point(11, 19);
this.checkbox_capture_mousepointer.Name = "checkbox_capture_mousepointer";
- this.checkbox_capture_mousepointer.PropertyName = nameof(CoreConfiguration.CaptureMousepointer);
+ this.checkbox_capture_mousepointer.PropertyName = "CaptureMousepointer";
this.checkbox_capture_mousepointer.Size = new System.Drawing.Size(394, 24);
this.checkbox_capture_mousepointer.TabIndex = 1;
this.checkbox_capture_mousepointer.UseVisualStyleBackColor = true;
@@ -871,6 +868,7 @@ namespace Greenshot.Forms {
//
// groupBoxColors
//
+ this.groupBoxColors.AutoSize = true;
this.groupBoxColors.Controls.Add(this.checkboxPrintInverted);
this.groupBoxColors.Controls.Add(this.radioBtnColorPrint);
this.groupBoxColors.Controls.Add(this.radioBtnGrayScale);
@@ -884,12 +882,13 @@ namespace Greenshot.Forms {
//
// checkboxPrintInverted
//
+ this.checkboxPrintInverted.AutoSize = true;
this.checkboxPrintInverted.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxPrintInverted.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxPrintInverted.LanguageKey = "printoptions_inverted";
this.checkboxPrintInverted.Location = new System.Drawing.Point(13, 88);
this.checkboxPrintInverted.Name = "checkboxPrintInverted";
- this.checkboxPrintInverted.PropertyName = nameof(CoreConfiguration.OutputPrintInverted);
+ this.checkboxPrintInverted.PropertyName = "OutputPrintInverted";
this.checkboxPrintInverted.Size = new System.Drawing.Size(141, 17);
this.checkboxPrintInverted.TabIndex = 14;
this.checkboxPrintInverted.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -897,11 +896,13 @@ namespace Greenshot.Forms {
//
// radioBtnColorPrint
//
+ this.radioBtnColorPrint.AutoSize = true;
this.radioBtnColorPrint.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnColorPrint.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnColorPrint.LanguageKey = "printoptions_printcolor";
this.radioBtnColorPrint.Location = new System.Drawing.Point(13, 19);
this.radioBtnColorPrint.Name = "radioBtnColorPrint";
+ this.radioBtnColorPrint.PropertyName = "OutputPrintColor";
this.radioBtnColorPrint.Size = new System.Drawing.Size(90, 17);
this.radioBtnColorPrint.TabIndex = 11;
this.radioBtnColorPrint.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -909,12 +910,13 @@ namespace Greenshot.Forms {
//
// radioBtnGrayScale
//
+ this.radioBtnGrayScale.AutoSize = true;
this.radioBtnGrayScale.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnGrayScale.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnGrayScale.LanguageKey = "printoptions_printgrayscale";
this.radioBtnGrayScale.Location = new System.Drawing.Point(13, 42);
this.radioBtnGrayScale.Name = "radioBtnGrayScale";
- this.radioBtnGrayScale.PropertyName = nameof(coreConfiguration.OutputPrintGrayscale);
+ this.radioBtnGrayScale.PropertyName = "OutputPrintGrayscale";
this.radioBtnGrayScale.Size = new System.Drawing.Size(137, 17);
this.radioBtnGrayScale.TabIndex = 12;
this.radioBtnGrayScale.Text = "Force grayscale printing";
@@ -923,12 +925,13 @@ namespace Greenshot.Forms {
//
// radioBtnMonochrome
//
+ this.radioBtnMonochrome.AutoSize = true;
this.radioBtnMonochrome.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnMonochrome.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.radioBtnMonochrome.LanguageKey = "printoptions_printmonochrome";
this.radioBtnMonochrome.Location = new System.Drawing.Point(13, 65);
this.radioBtnMonochrome.Name = "radioBtnMonochrome";
- this.radioBtnMonochrome.PropertyName = nameof(coreConfiguration.OutputPrintMonochrome);
+ this.radioBtnMonochrome.PropertyName = "OutputPrintMonochrome";
this.radioBtnMonochrome.Size = new System.Drawing.Size(148, 17);
this.radioBtnMonochrome.TabIndex = 13;
this.radioBtnMonochrome.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -936,6 +939,7 @@ namespace Greenshot.Forms {
//
// groupBoxPrintLayout
//
+ this.groupBoxPrintLayout.AutoSize = true;
this.groupBoxPrintLayout.Controls.Add(this.checkboxDateTime);
this.groupBoxPrintLayout.Controls.Add(this.checkboxAllowShrink);
this.groupBoxPrintLayout.Controls.Add(this.checkboxAllowEnlarge);
@@ -950,12 +954,13 @@ namespace Greenshot.Forms {
//
// checkboxDateTime
//
+ this.checkboxDateTime.AutoSize = true;
this.checkboxDateTime.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxDateTime.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxDateTime.LanguageKey = "printoptions_timestamp";
this.checkboxDateTime.Location = new System.Drawing.Point(13, 115);
this.checkboxDateTime.Name = "checkboxDateTime";
- this.checkboxDateTime.PropertyName = nameof(coreConfiguration.OutputPrintFooter);
+ this.checkboxDateTime.PropertyName = "OutputPrintFooter";
this.checkboxDateTime.Size = new System.Drawing.Size(187, 17);
this.checkboxDateTime.TabIndex = 6;
this.checkboxDateTime.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -963,12 +968,13 @@ namespace Greenshot.Forms {
//
// checkboxAllowShrink
//
+ this.checkboxAllowShrink.AutoSize = true;
this.checkboxAllowShrink.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowShrink.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowShrink.LanguageKey = "printoptions_allowshrink";
this.checkboxAllowShrink.Location = new System.Drawing.Point(13, 23);
this.checkboxAllowShrink.Name = "checkboxAllowShrink";
- this.checkboxAllowShrink.PropertyName = nameof(coreConfiguration.OutputPrintAllowShrink);
+ this.checkboxAllowShrink.PropertyName = "OutputPrintAllowShrink";
this.checkboxAllowShrink.Size = new System.Drawing.Size(168, 17);
this.checkboxAllowShrink.TabIndex = 2;
this.checkboxAllowShrink.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -976,12 +982,13 @@ namespace Greenshot.Forms {
//
// checkboxAllowEnlarge
//
+ this.checkboxAllowEnlarge.AutoSize = true;
this.checkboxAllowEnlarge.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowEnlarge.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowEnlarge.LanguageKey = "printoptions_allowenlarge";
this.checkboxAllowEnlarge.Location = new System.Drawing.Point(13, 46);
this.checkboxAllowEnlarge.Name = "checkboxAllowEnlarge";
- this.checkboxAllowEnlarge.PropertyName = nameof(coreConfiguration.OutputPrintAllowEnlarge);
+ this.checkboxAllowEnlarge.PropertyName = "OutputPrintAllowEnlarge";
this.checkboxAllowEnlarge.Size = new System.Drawing.Size(174, 17);
this.checkboxAllowEnlarge.TabIndex = 3;
this.checkboxAllowEnlarge.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -989,12 +996,13 @@ namespace Greenshot.Forms {
//
// checkboxAllowRotate
//
+ this.checkboxAllowRotate.AutoSize = true;
this.checkboxAllowRotate.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowRotate.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowRotate.LanguageKey = "printoptions_allowrotate";
this.checkboxAllowRotate.Location = new System.Drawing.Point(13, 69);
this.checkboxAllowRotate.Name = "checkboxAllowRotate";
- this.checkboxAllowRotate.PropertyName = nameof(coreConfiguration.OutputPrintAllowRotate);
+ this.checkboxAllowRotate.PropertyName = "OutputPrintAllowRotate";
this.checkboxAllowRotate.Size = new System.Drawing.Size(187, 17);
this.checkboxAllowRotate.TabIndex = 4;
this.checkboxAllowRotate.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -1002,12 +1010,13 @@ namespace Greenshot.Forms {
//
// checkboxAllowCenter
//
+ this.checkboxAllowCenter.AutoSize = true;
this.checkboxAllowCenter.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowCenter.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkboxAllowCenter.LanguageKey = "printoptions_allowcenter";
this.checkboxAllowCenter.Location = new System.Drawing.Point(13, 92);
this.checkboxAllowCenter.Name = "checkboxAllowCenter";
- this.checkboxAllowCenter.PropertyName = nameof(coreConfiguration.OutputPrintCenter);
+ this.checkboxAllowCenter.PropertyName = "OutputPrintCenter";
this.checkboxAllowCenter.Size = new System.Drawing.Size(137, 17);
this.checkboxAllowCenter.TabIndex = 5;
this.checkboxAllowCenter.TextAlign = System.Drawing.ContentAlignment.TopLeft;
@@ -1018,7 +1027,7 @@ namespace Greenshot.Forms {
this.checkbox_alwaysshowprintoptionsdialog.LanguageKey = "settings_alwaysshowprintoptionsdialog";
this.checkbox_alwaysshowprintoptionsdialog.Location = new System.Drawing.Point(19, 293);
this.checkbox_alwaysshowprintoptionsdialog.Name = "checkbox_alwaysshowprintoptionsdialog";
- this.checkbox_alwaysshowprintoptionsdialog.PropertyName = nameof(coreConfiguration.OutputPrintPromptOptions);
+ this.checkbox_alwaysshowprintoptionsdialog.PropertyName = "OutputPrintPromptOptions";
this.checkbox_alwaysshowprintoptionsdialog.Size = new System.Drawing.Size(394, 20);
this.checkbox_alwaysshowprintoptionsdialog.TabIndex = 15;
this.checkbox_alwaysshowprintoptionsdialog.Text = "Show print options dialog every time an image is printed";
@@ -1066,6 +1075,7 @@ namespace Greenshot.Forms {
// button_pluginconfigure
//
this.button_pluginconfigure.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.button_pluginconfigure.AutoSize = true;
this.button_pluginconfigure.Enabled = false;
this.button_pluginconfigure.LanguageKey = "settings_configureplugin";
this.button_pluginconfigure.Location = new System.Drawing.Point(6, 285);
@@ -1115,7 +1125,7 @@ namespace Greenshot.Forms {
this.checkbox_reuseeditor.LanguageKey = "expertsettings_reuseeditorifpossible";
this.checkbox_reuseeditor.Location = new System.Drawing.Point(10, 225);
this.checkbox_reuseeditor.Name = "checkbox_reuseeditor";
- this.checkbox_reuseeditor.PropertyName = nameof(EditorConfiguration.ReuseEditor);
+ this.checkbox_reuseeditor.PropertyName = "ReuseEditor";
this.checkbox_reuseeditor.SectionName = "Editor";
this.checkbox_reuseeditor.Size = new System.Drawing.Size(394, 24);
this.checkbox_reuseeditor.TabIndex = 9;
@@ -1126,7 +1136,7 @@ namespace Greenshot.Forms {
this.checkbox_minimizememoryfootprint.LanguageKey = "expertsettings_minimizememoryfootprint";
this.checkbox_minimizememoryfootprint.Location = new System.Drawing.Point(10, 206);
this.checkbox_minimizememoryfootprint.Name = "checkbox_minimizememoryfootprint";
- this.checkbox_minimizememoryfootprint.PropertyName = nameof(coreConfiguration.MinimizeWorkingSetSize);
+ this.checkbox_minimizememoryfootprint.PropertyName = "MinimizeWorkingSetSize";
this.checkbox_minimizememoryfootprint.Size = new System.Drawing.Size(394, 24);
this.checkbox_minimizememoryfootprint.TabIndex = 8;
this.checkbox_minimizememoryfootprint.UseVisualStyleBackColor = true;
@@ -1136,7 +1146,7 @@ namespace Greenshot.Forms {
this.checkbox_checkunstableupdates.LanguageKey = "expertsettings_checkunstableupdates";
this.checkbox_checkunstableupdates.Location = new System.Drawing.Point(10, 187);
this.checkbox_checkunstableupdates.Name = "checkbox_checkunstableupdates";
- this.checkbox_checkunstableupdates.PropertyName = nameof(coreConfiguration.CheckForUnstable);
+ this.checkbox_checkunstableupdates.PropertyName = "CheckForUnstable";
this.checkbox_checkunstableupdates.Size = new System.Drawing.Size(394, 24);
this.checkbox_checkunstableupdates.TabIndex = 7;
this.checkbox_checkunstableupdates.UseVisualStyleBackColor = true;
@@ -1146,7 +1156,7 @@ namespace Greenshot.Forms {
this.checkbox_suppresssavedialogatclose.LanguageKey = "expertsettings_suppresssavedialogatclose";
this.checkbox_suppresssavedialogatclose.Location = new System.Drawing.Point(10, 168);
this.checkbox_suppresssavedialogatclose.Name = "checkbox_suppresssavedialogatclose";
- this.checkbox_suppresssavedialogatclose.PropertyName = nameof(EditorConfiguration.SuppressSaveDialogAtClose);
+ this.checkbox_suppresssavedialogatclose.PropertyName = "SuppressSaveDialogAtClose";
this.checkbox_suppresssavedialogatclose.SectionName = "Editor";
this.checkbox_suppresssavedialogatclose.Size = new System.Drawing.Size(394, 24);
this.checkbox_suppresssavedialogatclose.TabIndex = 6;
@@ -1154,6 +1164,7 @@ namespace Greenshot.Forms {
//
// label_counter
//
+ this.label_counter.AutoSize = true;
this.label_counter.LanguageKey = "expertsettings_counter";
this.label_counter.Location = new System.Drawing.Point(7, 285);
this.label_counter.Name = "label_counter";
@@ -1164,12 +1175,13 @@ namespace Greenshot.Forms {
//
this.textbox_counter.Location = new System.Drawing.Point(259, 282);
this.textbox_counter.Name = "textbox_counter";
- this.textbox_counter.PropertyName = nameof(coreConfiguration.OutputFileIncrementingNumber);
+ this.textbox_counter.PropertyName = "OutputFileIncrementingNumber";
this.textbox_counter.Size = new System.Drawing.Size(141, 20);
this.textbox_counter.TabIndex = 11;
//
// label_footerpattern
//
+ this.label_footerpattern.AutoSize = true;
this.label_footerpattern.LanguageKey = "expertsettings_footerpattern";
this.label_footerpattern.Location = new System.Drawing.Point(7, 259);
this.label_footerpattern.Name = "label_footerpattern";
@@ -1181,7 +1193,7 @@ namespace Greenshot.Forms {
//
this.textbox_footerpattern.Location = new System.Drawing.Point(138, 256);
this.textbox_footerpattern.Name = "textbox_footerpattern";
- this.textbox_footerpattern.PropertyName = nameof(coreConfiguration.OutputPrintFooterPattern);
+ this.textbox_footerpattern.PropertyName = "OutputPrintFooterPattern";
this.textbox_footerpattern.Size = new System.Drawing.Size(262, 20);
this.textbox_footerpattern.TabIndex = 10;
//
@@ -1190,7 +1202,7 @@ namespace Greenshot.Forms {
this.checkbox_thumbnailpreview.LanguageKey = "expertsettings_thumbnailpreview";
this.checkbox_thumbnailpreview.Location = new System.Drawing.Point(10, 149);
this.checkbox_thumbnailpreview.Name = "checkbox_thumbnailpreview";
- this.checkbox_thumbnailpreview.PropertyName = nameof(coreConfiguration.ThumnailPreview);
+ this.checkbox_thumbnailpreview.PropertyName = "ThumnailPreview";
this.checkbox_thumbnailpreview.Size = new System.Drawing.Size(394, 24);
this.checkbox_thumbnailpreview.TabIndex = 5;
this.checkbox_thumbnailpreview.UseVisualStyleBackColor = true;
@@ -1200,7 +1212,7 @@ namespace Greenshot.Forms {
this.checkbox_optimizeforrdp.LanguageKey = "expertsettings_optimizeforrdp";
this.checkbox_optimizeforrdp.Location = new System.Drawing.Point(10, 130);
this.checkbox_optimizeforrdp.Name = "checkbox_optimizeforrdp";
- this.checkbox_optimizeforrdp.PropertyName = nameof(coreConfiguration.OptimizeForRDP);
+ this.checkbox_optimizeforrdp.PropertyName = "OptimizeForRDP";
this.checkbox_optimizeforrdp.Size = new System.Drawing.Size(394, 24);
this.checkbox_optimizeforrdp.TabIndex = 4;
this.checkbox_optimizeforrdp.UseVisualStyleBackColor = true;
@@ -1210,13 +1222,14 @@ namespace Greenshot.Forms {
this.checkbox_autoreducecolors.LanguageKey = "expertsettings_autoreducecolors";
this.checkbox_autoreducecolors.Location = new System.Drawing.Point(10, 111);
this.checkbox_autoreducecolors.Name = "checkbox_autoreducecolors";
- this.checkbox_autoreducecolors.PropertyName = nameof(coreConfiguration.OutputFileAutoReduceColors);
+ this.checkbox_autoreducecolors.PropertyName = "OutputFileAutoReduceColors";
this.checkbox_autoreducecolors.Size = new System.Drawing.Size(408, 24);
this.checkbox_autoreducecolors.TabIndex = 3;
this.checkbox_autoreducecolors.UseVisualStyleBackColor = true;
//
// label_clipboardformats
//
+ this.label_clipboardformats.AutoSize = true;
this.label_clipboardformats.LanguageKey = "expertsettings_clipboardformats";
this.label_clipboardformats.Location = new System.Drawing.Point(7, 39);
this.label_clipboardformats.Name = "label_clipboardformats";
@@ -1231,7 +1244,7 @@ namespace Greenshot.Forms {
this.checkbox_enableexpert.Size = new System.Drawing.Size(394, 24);
this.checkbox_enableexpert.TabIndex = 1;
this.checkbox_enableexpert.UseVisualStyleBackColor = true;
- this.checkbox_enableexpert.CheckedChanged += new System.EventHandler(this.Checkbox_enableexpert_CheckedChanged);
+ this.checkbox_enableexpert.CheckedChanged += new System.EventHandler(this.checkbox_enableexpert_CheckedChanged);
//
// listview_clipboardformats
//
@@ -1258,8 +1271,9 @@ namespace Greenshot.Forms {
//
// SettingsForm
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(451, 431);
this.Controls.Add(this.tabcontrol);
this.Controls.Add(this.settings_confirm);
@@ -1307,104 +1321,104 @@ namespace Greenshot.Forms {
this.ResumeLayout(false);
}
- private GreenshotCheckBox checkbox_notifications;
- private GreenshotCheckBox checkbox_minimizememoryfootprint;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_notifications;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_minimizememoryfootprint;
private System.Windows.Forms.ColumnHeader destination;
- private GreenshotCheckBox checkbox_picker;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_picker;
private System.Windows.Forms.ListView listview_destinations;
- private GreenshotGroupBox groupbox_editor;
- private GreenshotCheckBox checkbox_editor_match_capture_size;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_editor;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_editor_match_capture_size;
private System.Windows.Forms.NumericUpDown numericUpDown_daysbetweencheck;
- private GreenshotGroupBox groupbox_network;
- private GreenshotCheckBox checkbox_usedefaultproxy;
- private GreenshotLabel label_checkperiod;
- private HotkeyControl fullscreen_hotkeyControl;
- private HotkeyControl window_hotkeyControl;
- private HotkeyControl region_hotkeyControl;
- private GreenshotLabel label_fullscreen_hotkey;
- private GreenshotLabel label_window_hotkey;
- private GreenshotLabel label_region_hotkey;
- private HotkeyControl ie_hotkeyControl;
- private GreenshotLabel label_ie_hotkey;
- private HotkeyControl lastregion_hotkeyControl;
- private GreenshotLabel label_lastregion_hotkey;
- private GreenshotGroupBox groupbox_hotkeys;
- private ColorButton colorButton_window_background;
- private GreenshotRadioButton radiobuttonWindowCapture;
- private GreenshotCheckBox checkbox_ie_capture;
- private GreenshotGroupBox groupbox_capture;
- private GreenshotGroupBox groupbox_windowscapture;
- private GreenshotGroupBox groupbox_iecapture;
- private GreenshotTabPage tab_capture;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_network;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usedefaultproxy;
+ private GreenshotPlugin.Controls.GreenshotLabel label_checkperiod;
+ private GreenshotPlugin.Controls.HotkeyControl fullscreen_hotkeyControl;
+ private GreenshotPlugin.Controls.HotkeyControl window_hotkeyControl;
+ private GreenshotPlugin.Controls.HotkeyControl region_hotkeyControl;
+ private GreenshotPlugin.Controls.GreenshotLabel label_fullscreen_hotkey;
+ private GreenshotPlugin.Controls.GreenshotLabel label_window_hotkey;
+ private GreenshotPlugin.Controls.GreenshotLabel label_region_hotkey;
+ private GreenshotPlugin.Controls.HotkeyControl ie_hotkeyControl;
+ private GreenshotPlugin.Controls.GreenshotLabel label_ie_hotkey;
+ private GreenshotPlugin.Controls.HotkeyControl lastregion_hotkeyControl;
+ private GreenshotPlugin.Controls.GreenshotLabel label_lastregion_hotkey;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_hotkeys;
+ private Greenshot.Controls.ColorButton colorButton_window_background;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radiobuttonWindowCapture;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_ie_capture;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_capture;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_windowscapture;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_iecapture;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_capture;
private System.Windows.Forms.ComboBox combobox_window_capture_mode;
private System.Windows.Forms.NumericUpDown numericUpDownWaitTime;
- private GreenshotLabel label_waittime;
- private GreenshotRadioButton radiobuttonInteractiveCapture;
- private GreenshotCheckBox checkbox_capture_mousepointer;
- private GreenshotTabPage tab_printer;
+ private GreenshotPlugin.Controls.GreenshotLabel label_waittime;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radiobuttonInteractiveCapture;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_capture_mousepointer;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_printer;
private System.Windows.Forms.ListView listview_plugins;
- private GreenshotButton button_pluginconfigure;
- private GreenshotGroupBox groupbox_plugins;
- private GreenshotTabPage tab_plugins;
+ private GreenshotPlugin.Controls.GreenshotButton button_pluginconfigure;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_plugins;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_plugins;
private System.Windows.Forms.Button btnPatternHelp;
- private GreenshotCheckBox checkbox_copypathtoclipboard;
- private GreenshotTabPage tab_output;
- private GreenshotTabPage tab_general;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_copypathtoclipboard;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_output;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_general;
private System.Windows.Forms.TabControl tabcontrol;
- private GreenshotCheckBox checkbox_autostartshortcut;
- private GreenshotGroupBox groupbox_destination;
- private GreenshotCheckBox checkbox_alwaysshowqualitydialog;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_autostartshortcut;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_destination;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_alwaysshowqualitydialog;
private System.Windows.Forms.TextBox textBoxJpegQuality;
- private GreenshotLabel label_jpegquality;
+ private GreenshotPlugin.Controls.GreenshotLabel label_jpegquality;
private System.Windows.Forms.TrackBar trackBarJpegQuality;
- private GreenshotGroupBox groupbox_qualitysettings;
- private GreenshotGroupBox groupbox_applicationsettings;
- private GreenshotGroupBox groupbox_preferredfilesettings;
- private GreenshotCheckBox checkbox_playsound;
- private GreenshotLabel label_primaryimageformat;
- private GreenshotComboBox combobox_primaryimageformat;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_qualitysettings;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_applicationsettings;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_preferredfilesettings;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_playsound;
+ private GreenshotPlugin.Controls.GreenshotLabel label_primaryimageformat;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_primaryimageformat;
private System.Windows.Forms.ComboBox combobox_language;
- private GreenshotLabel label_language;
- private GreenshotTextBox textbox_screenshotname;
- private GreenshotLabel label_screenshotname;
+ private GreenshotPlugin.Controls.GreenshotLabel label_language;
+ private GreenshotPlugin.Controls.GreenshotTextBox textbox_screenshotname;
+ private GreenshotPlugin.Controls.GreenshotLabel label_screenshotname;
private System.Windows.Forms.Button browse;
private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
- private GreenshotButton settings_cancel;
- private GreenshotButton settings_confirm;
- private GreenshotTextBox textbox_storagelocation;
- private GreenshotLabel label_storagelocation;
- private GreenshotTabPage tab_destinations;
- private GreenshotTabPage tab_expert;
- private GreenshotGroupBox groupbox_expert;
- private GreenshotLabel label_clipboardformats;
- private GreenshotCheckBox checkbox_enableexpert;
+ private GreenshotPlugin.Controls.GreenshotButton settings_cancel;
+ private GreenshotPlugin.Controls.GreenshotButton settings_confirm;
+ private GreenshotPlugin.Controls.GreenshotTextBox textbox_storagelocation;
+ private GreenshotPlugin.Controls.GreenshotLabel label_storagelocation;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_destinations;
+ private GreenshotPlugin.Controls.GreenshotTabPage tab_expert;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_expert;
+ private GreenshotPlugin.Controls.GreenshotLabel label_clipboardformats;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_enableexpert;
private System.Windows.Forms.ListView listview_clipboardformats;
private System.Windows.Forms.ColumnHeader columnHeader1;
- private GreenshotCheckBox checkbox_autoreducecolors;
- private GreenshotCheckBox checkbox_optimizeforrdp;
- private GreenshotCheckBox checkbox_thumbnailpreview;
- private GreenshotLabel label_footerpattern;
- private GreenshotTextBox textbox_footerpattern;
- private GreenshotLabel label_counter;
- private GreenshotTextBox textbox_counter;
- private GreenshotCheckBox checkbox_reducecolors;
- private GreenshotCheckBox checkbox_suppresssavedialogatclose;
- private GreenshotCheckBox checkbox_checkunstableupdates;
- private GreenshotCheckBox checkbox_reuseeditor;
- private GreenshotCheckBox checkbox_alwaysshowprintoptionsdialog;
- private GreenshotGroupBox groupBoxColors;
- private GreenshotCheckBox checkboxPrintInverted;
- private GreenshotRadioButton radioBtnColorPrint;
- private GreenshotRadioButton radioBtnGrayScale;
- private GreenshotRadioButton radioBtnMonochrome;
- private GreenshotGroupBox groupBoxPrintLayout;
- private GreenshotCheckBox checkboxDateTime;
- private GreenshotCheckBox checkboxAllowShrink;
- private GreenshotCheckBox checkboxAllowEnlarge;
- private GreenshotCheckBox checkboxAllowRotate;
- private GreenshotCheckBox checkboxAllowCenter;
- private GreenshotCheckBox checkbox_zoomer;
- private GreenshotLabel label_icon_size;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_autoreducecolors;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_optimizeforrdp;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_thumbnailpreview;
+ private GreenshotPlugin.Controls.GreenshotLabel label_footerpattern;
+ private GreenshotPlugin.Controls.GreenshotTextBox textbox_footerpattern;
+ private GreenshotPlugin.Controls.GreenshotLabel label_counter;
+ private GreenshotPlugin.Controls.GreenshotTextBox textbox_counter;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_reducecolors;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_suppresssavedialogatclose;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_checkunstableupdates;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_reuseeditor;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_alwaysshowprintoptionsdialog;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxColors;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxPrintInverted;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnColorPrint;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnGrayScale;
+ private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnMonochrome;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxPrintLayout;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxDateTime;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowShrink;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowEnlarge;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowRotate;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowCenter;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_zoomer;
+ private GreenshotPlugin.Controls.GreenshotLabel label_icon_size;
private System.Windows.Forms.NumericUpDown numericUpdownIconSize;
}
}
diff --git a/Greenshot/Forms/SettingsForm.cs b/Greenshot/Forms/SettingsForm.cs
new file mode 100644
index 000000000..6f5b65eca
--- /dev/null
+++ b/Greenshot/Forms/SettingsForm.cs
@@ -0,0 +1,686 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using Greenshot.Destinations;
+using Greenshot.Helpers;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+using Greenshot.Plugin;
+using Greenshot.IniFile;
+using System.Text.RegularExpressions;
+using log4net;
+
+namespace Greenshot {
+ ///
+ /// Description of SettingsForm.
+ ///
+ public partial class SettingsForm : BaseForm {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(SettingsForm));
+ private readonly ToolTip _toolTip = new ToolTip();
+ private bool _inHotkey;
+ private int _daysbetweencheckPreviousValue;
+
+ public SettingsForm() {
+ InitializeComponent();
+
+ // Make sure the store isn't called to early, that's why we do it manually
+ ManualStoreFields = true;
+ }
+
+ protected override void OnLoad(EventArgs e) {
+ base.OnLoad(e);
+
+ // Fix for Vista/XP differences
+ trackBarJpegQuality.BackColor = Environment.OSVersion.Version.Major >= 6 ? SystemColors.Window : SystemColors.Control;
+
+ // This makes it possible to still capture the settings screen
+ fullscreen_hotkeyControl.Enter += EnterHotkeyControl;
+ fullscreen_hotkeyControl.Leave += LeaveHotkeyControl;
+ window_hotkeyControl.Enter += EnterHotkeyControl;
+ window_hotkeyControl.Leave += LeaveHotkeyControl;
+ region_hotkeyControl.Enter += EnterHotkeyControl;
+ region_hotkeyControl.Leave += LeaveHotkeyControl;
+ ie_hotkeyControl.Enter += EnterHotkeyControl;
+ ie_hotkeyControl.Leave += LeaveHotkeyControl;
+ lastregion_hotkeyControl.Enter += EnterHotkeyControl;
+ lastregion_hotkeyControl.Leave += LeaveHotkeyControl;
+ // Changes for BUG-2077
+ numericUpDown_daysbetweencheck.ValueChanged += NumericUpDownDaysbetweencheckOnValueChanged;
+
+ _daysbetweencheckPreviousValue = (int) numericUpDown_daysbetweencheck.Value;
+ DisplayPluginTab();
+ UpdateUi();
+ ExpertSettingsEnableState(false);
+ DisplaySettings();
+ CheckSettings();
+ }
+
+ ///
+ /// This makes sure the check cannot be set to 1-6
+ ///
+ /// object
+ /// EventArgs
+ private void NumericUpDownDaysbetweencheckOnValueChanged(object sender, EventArgs eventArgs)
+ {
+ int currentValue = (int)numericUpDown_daysbetweencheck.Value;
+
+ // Check if we can into the forbidden range
+ if (currentValue > 0 && currentValue < 7)
+ {
+ if (_daysbetweencheckPreviousValue <= currentValue)
+ {
+ numericUpDown_daysbetweencheck.Value = 7;
+ }
+ else
+ {
+ numericUpDown_daysbetweencheck.Value = 0;
+ }
+ }
+ if ((int)numericUpDown_daysbetweencheck.Value < 0)
+ {
+ numericUpDown_daysbetweencheck.Value = 0;
+ }
+ if ((int)numericUpDown_daysbetweencheck.Value > 365)
+ {
+ numericUpDown_daysbetweencheck.Value = 365;
+ }
+ _daysbetweencheckPreviousValue = (int)numericUpDown_daysbetweencheck.Value;
+ }
+
+ private void EnterHotkeyControl(object sender, EventArgs e) {
+ HotkeyControl.UnregisterHotkeys();
+ _inHotkey = true;
+ }
+
+ private void LeaveHotkeyControl(object sender, EventArgs e) {
+ MainForm.RegisterHotkeys();
+ _inHotkey = false;
+ }
+
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
+ switch (keyData) {
+ case Keys.Escape:
+ if (!_inHotkey) {
+ DialogResult = DialogResult.Cancel;
+ } else {
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+ break;
+ default:
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+ return true;
+ }
+
+ ///
+ /// This is a method to populate the ComboBox
+ /// with the items from the enumeration
+ ///
+ /// ComboBox to populate
+ ///
+ ///
+ private void PopulateComboBox(ComboBox comboBox, TEnum[] availableValues, TEnum selectedValue) where TEnum : struct {
+ comboBox.Items.Clear();
+ foreach(TEnum enumValue in availableValues) {
+ comboBox.Items.Add(Language.Translate(enumValue));
+ }
+ comboBox.SelectedItem = Language.Translate(selectedValue);
+ }
+
+
+ ///
+ /// Get the selected enum value from the combobox, uses generics
+ ///
+ /// Combobox to get the value from
+ /// The generics value of the combobox
+ private TEnum GetSelected(ComboBox comboBox) {
+ string enumTypeName = typeof(TEnum).Name;
+ string selectedValue = comboBox.SelectedItem as string;
+ TEnum[] availableValues = (TEnum[])Enum.GetValues(typeof(TEnum));
+ TEnum returnValue = availableValues[0];
+ foreach(TEnum enumValue in availableValues) {
+ string translation = Language.GetString(enumTypeName + "." + enumValue);
+ if (translation.Equals(selectedValue)) {
+ returnValue = enumValue;
+ break;
+ }
+ }
+ return returnValue;
+ }
+
+ private void SetWindowCaptureMode(WindowCaptureMode selectedWindowCaptureMode) {
+ WindowCaptureMode[] availableModes;
+ if (!DWM.IsDwmEnabled()) {
+ // Remove DWM from configuration, as DWM is disabled!
+ if (coreConfiguration.WindowCaptureMode == WindowCaptureMode.Aero || coreConfiguration.WindowCaptureMode == WindowCaptureMode.AeroTransparent) {
+ coreConfiguration.WindowCaptureMode = WindowCaptureMode.GDI;
+ }
+ availableModes = new[]{WindowCaptureMode.Auto, WindowCaptureMode.Screen, WindowCaptureMode.GDI};
+ } else {
+ availableModes = new[]{WindowCaptureMode.Auto, WindowCaptureMode.Screen, WindowCaptureMode.GDI, WindowCaptureMode.Aero, WindowCaptureMode.AeroTransparent};
+ }
+ PopulateComboBox(combobox_window_capture_mode, availableModes, selectedWindowCaptureMode);
+ }
+
+ private void DisplayPluginTab() {
+ if (!PluginHelper.Instance.HasPlugins()) {
+ tabcontrol.TabPages.Remove(tab_plugins);
+ } else {
+ // Draw the Plugin listview
+ listview_plugins.BeginUpdate();
+ listview_plugins.Items.Clear();
+ listview_plugins.Columns.Clear();
+ string[] columns = {
+ Language.GetString("settings_plugins_name"),
+ Language.GetString("settings_plugins_version"),
+ Language.GetString("settings_plugins_createdby"),
+ Language.GetString("settings_plugins_dllpath")};
+ foreach (string column in columns) {
+ listview_plugins.Columns.Add(column);
+ }
+ PluginHelper.Instance.FillListview(listview_plugins);
+ // Maximize Column size!
+ for (int i = 0; i < listview_plugins.Columns.Count; i++) {
+ listview_plugins.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
+ int width = listview_plugins.Columns[i].Width;
+ listview_plugins.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.HeaderSize);
+ if (width > listview_plugins.Columns[i].Width) {
+ listview_plugins.Columns[i].Width = width;
+ }
+ }
+ listview_plugins.EndUpdate();
+ listview_plugins.Refresh();
+
+ // Disable the configure button, it will be enabled when a plugin is selected AND isConfigurable
+ button_pluginconfigure.Enabled = false;
+ }
+ }
+
+ ///
+ /// Update the UI to reflect the language and other text settings
+ ///
+ private void UpdateUi() {
+ if (coreConfiguration.HideExpertSettings) {
+ tabcontrol.Controls.Remove(tab_expert);
+ }
+ _toolTip.SetToolTip(label_language, Language.GetString(LangKey.settings_tooltip_language));
+ _toolTip.SetToolTip(label_storagelocation, Language.GetString(LangKey.settings_tooltip_storagelocation));
+ _toolTip.SetToolTip(label_screenshotname, Language.GetString(LangKey.settings_tooltip_filenamepattern));
+ _toolTip.SetToolTip(label_primaryimageformat, Language.GetString(LangKey.settings_tooltip_primaryimageformat));
+
+ // Removing, otherwise we keep getting the event multiple times!
+ combobox_language.SelectedIndexChanged -= Combobox_languageSelectedIndexChanged;
+
+ // Initialize the Language ComboBox
+ combobox_language.DisplayMember = "Description";
+ combobox_language.ValueMember = "Ietf";
+ // Set datasource last to prevent problems
+ // See: http://www.codeproject.com/KB/database/scomlistcontrolbinding.aspx?fid=111644
+ combobox_language.DataSource = Language.SupportedLanguages;
+ if (Language.CurrentLanguage != null) {
+ combobox_language.SelectedValue = Language.CurrentLanguage;
+ }
+
+ // Delaying the SelectedIndexChanged events untill all is initiated
+ combobox_language.SelectedIndexChanged += Combobox_languageSelectedIndexChanged;
+ UpdateDestinationDescriptions();
+ UpdateClipboardFormatDescriptions();
+ }
+
+ // Check the settings and somehow visibly mark when something is incorrect
+ private bool CheckSettings() {
+ return CheckFilenamePattern() && CheckStorageLocationPath();
+ }
+
+ private bool CheckFilenamePattern() {
+ string filename = FilenameHelper.GetFilenameFromPattern(textbox_screenshotname.Text, coreConfiguration.OutputFileFormat, null);
+ // we allow dynamically created subfolders, need to check for them, too
+ string[] pathParts = filename.Split(Path.DirectorySeparatorChar);
+
+ string filenamePart = pathParts[pathParts.Length-1];
+ var settingsOk = FilenameHelper.IsFilenameValid(filenamePart);
+
+ for (int i = 0; settingsOk && i= 6 ? SystemColors.Window : SystemColors.Control;
+ } else {
+ textbox.BackColor = Color.Red;
+ }
+ }
+
+ private void FilenamePatternChanged(object sender, EventArgs e) {
+ CheckFilenamePattern();
+ }
+
+ private void StorageLocationChanged(object sender, EventArgs e) {
+ CheckStorageLocationPath();
+ }
+
+ ///
+ /// Show all destination descriptions in the current language
+ ///
+ private void UpdateDestinationDescriptions() {
+ foreach (ListViewItem item in listview_destinations.Items) {
+ IDestination destinationFromTag = item.Tag as IDestination;
+ if (destinationFromTag != null) {
+ item.Text = destinationFromTag.Description;
+ }
+ }
+ }
+
+ ///
+ /// Show all clipboard format descriptions in the current language
+ ///
+ private void UpdateClipboardFormatDescriptions() {
+ foreach(ListViewItem item in listview_clipboardformats.Items) {
+ ClipboardFormat cf = (ClipboardFormat) item.Tag;
+ item.Text = Language.Translate(cf);
+ }
+ }
+
+ ///
+ /// Build the view with all the destinations
+ ///
+ private void DisplayDestinations() {
+ bool destinationsEnabled = true;
+ if (coreConfiguration.Values.ContainsKey("Destinations")) {
+ destinationsEnabled = !coreConfiguration.Values["Destinations"].IsFixed;
+ }
+ checkbox_picker.Checked = false;
+
+ listview_destinations.Items.Clear();
+ listview_destinations.ListViewItemSorter = new ListviewWithDestinationComparer();
+ ImageList imageList = new ImageList();
+ listview_destinations.SmallImageList = imageList;
+ int imageNr = -1;
+ foreach (IDestination currentDestination in DestinationHelper.GetAllDestinations()) {
+ Image destinationImage = currentDestination.DisplayIcon;
+ if (destinationImage != null) {
+ imageList.Images.Add(currentDestination.DisplayIcon);
+ imageNr++;
+ }
+ if (PickerDestination.DESIGNATION.Equals(currentDestination.Designation)) {
+ checkbox_picker.Checked = coreConfiguration.OutputDestinations.Contains(currentDestination.Designation);
+ checkbox_picker.Text = currentDestination.Description;
+ } else {
+ ListViewItem item;
+ if (destinationImage != null) {
+ item = listview_destinations.Items.Add(currentDestination.Description, imageNr);
+ } else {
+ item = listview_destinations.Items.Add(currentDestination.Description);
+ }
+ item.Tag = currentDestination;
+ item.Checked = coreConfiguration.OutputDestinations.Contains(currentDestination.Designation);
+ }
+ }
+ if (checkbox_picker.Checked) {
+ listview_destinations.Enabled = false;
+ foreach (int index in listview_destinations.CheckedIndices) {
+ ListViewItem item = listview_destinations.Items[index];
+ item.Checked = false;
+ }
+ }
+ checkbox_picker.Enabled = destinationsEnabled;
+ listview_destinations.Enabled = destinationsEnabled;
+ }
+
+ private void DisplaySettings() {
+ colorButton_window_background.SelectedColor = coreConfiguration.DWMBackgroundColor;
+
+ // Expert mode, the clipboard formats
+ foreach (ClipboardFormat clipboardFormat in Enum.GetValues(typeof(ClipboardFormat))) {
+ ListViewItem item = listview_clipboardformats.Items.Add(Language.Translate(clipboardFormat));
+ item.Tag = clipboardFormat;
+ item.Checked = coreConfiguration.ClipboardFormats.Contains(clipboardFormat);
+ }
+
+ if (Language.CurrentLanguage != null) {
+ combobox_language.SelectedValue = Language.CurrentLanguage;
+ }
+ // Disable editing when the value is fixed
+ combobox_language.Enabled = !coreConfiguration.Values["Language"].IsFixed;
+
+ textbox_storagelocation.Text = FilenameHelper.FillVariables(coreConfiguration.OutputFilePath, false);
+ // Disable editing when the value is fixed
+ textbox_storagelocation.Enabled = !coreConfiguration.Values["OutputFilePath"].IsFixed;
+
+ SetWindowCaptureMode(coreConfiguration.WindowCaptureMode);
+ // Disable editing when the value is fixed
+ combobox_window_capture_mode.Enabled = !coreConfiguration.CaptureWindowsInteractive && !coreConfiguration.Values["WindowCaptureMode"].IsFixed;
+ radiobuttonWindowCapture.Checked = !coreConfiguration.CaptureWindowsInteractive;
+
+ trackBarJpegQuality.Value = coreConfiguration.OutputFileJpegQuality;
+ trackBarJpegQuality.Enabled = !coreConfiguration.Values["OutputFileJpegQuality"].IsFixed;
+ textBoxJpegQuality.Text = coreConfiguration.OutputFileJpegQuality+"%";
+
+ DisplayDestinations();
+
+ numericUpDownWaitTime.Value = coreConfiguration.CaptureDelay >=0?coreConfiguration.CaptureDelay:0;
+ numericUpDownWaitTime.Enabled = !coreConfiguration.Values["CaptureDelay"].IsFixed;
+ if (IniConfig.IsPortable) {
+ checkbox_autostartshortcut.Visible = false;
+ checkbox_autostartshortcut.Checked = false;
+ } else {
+ // Autostart checkbox logic.
+ if (StartupHelper.HasRunAll()) {
+ // Remove runUser if we already have a run under all
+ StartupHelper.DeleteRunUser();
+ checkbox_autostartshortcut.Enabled = StartupHelper.CanWriteRunAll();
+ checkbox_autostartshortcut.Checked = true; // We already checked this
+ } else if (StartupHelper.IsInStartupFolder()) {
+ checkbox_autostartshortcut.Enabled = false;
+ checkbox_autostartshortcut.Checked = true; // We already checked this
+ } else {
+ // No run for all, enable the checkbox and set it to true if the current user has a key
+ checkbox_autostartshortcut.Enabled = StartupHelper.CanWriteRunUser();
+ checkbox_autostartshortcut.Checked = StartupHelper.HasRunUser();
+ }
+ }
+
+ numericUpDown_daysbetweencheck.Value = coreConfiguration.UpdateCheckInterval;
+ numericUpDown_daysbetweencheck.Enabled = !coreConfiguration.Values["UpdateCheckInterval"].IsFixed;
+ numericUpdownIconSize.Value = coreConfiguration.IconSize.Width /16 * 16;
+ CheckDestinationSettings();
+ }
+
+ private void SaveSettings() {
+ if (combobox_language.SelectedItem != null) {
+ string newLang = combobox_language.SelectedValue.ToString();
+ if (!string.IsNullOrEmpty(newLang)) {
+ coreConfiguration.Language = combobox_language.SelectedValue.ToString();
+ }
+ }
+
+ // retrieve the set clipboard formats
+ List clipboardFormats = new List();
+ foreach (int index in listview_clipboardformats.CheckedIndices) {
+ ListViewItem item = listview_clipboardformats.Items[index];
+ if (item.Checked) {
+ clipboardFormats.Add((ClipboardFormat)item.Tag);
+ }
+ }
+ coreConfiguration.ClipboardFormats = clipboardFormats;
+
+ coreConfiguration.WindowCaptureMode = GetSelected(combobox_window_capture_mode);
+ if (!FilenameHelper.FillVariables(coreConfiguration.OutputFilePath, false).Equals(textbox_storagelocation.Text)) {
+ coreConfiguration.OutputFilePath = textbox_storagelocation.Text;
+ }
+ coreConfiguration.OutputFileJpegQuality = trackBarJpegQuality.Value;
+
+ List destinations = new List();
+ if (checkbox_picker.Checked) {
+ destinations.Add(PickerDestination.DESIGNATION);
+ }
+ foreach(int index in listview_destinations.CheckedIndices) {
+ ListViewItem item = listview_destinations.Items[index];
+
+ IDestination destinationFromTag = item.Tag as IDestination;
+ if (item.Checked && destinationFromTag != null) {
+ destinations.Add(destinationFromTag.Designation);
+ }
+ }
+ coreConfiguration.OutputDestinations = destinations;
+ coreConfiguration.CaptureDelay = (int)numericUpDownWaitTime.Value;
+ coreConfiguration.DWMBackgroundColor = colorButton_window_background.SelectedColor;
+ coreConfiguration.UpdateCheckInterval = (int)numericUpDown_daysbetweencheck.Value;
+
+ coreConfiguration.IconSize = new Size((int)numericUpdownIconSize.Value, (int)numericUpdownIconSize.Value);
+
+ try {
+ if (checkbox_autostartshortcut.Checked) {
+ // It's checked, so we set the RunUser if the RunAll isn't set.
+ // Do this every time, so the executable is correct.
+ if (!StartupHelper.HasRunAll()) {
+ StartupHelper.SetRunUser();
+ }
+ } else {
+ // Delete both settings if it's unchecked
+ if (StartupHelper.HasRunAll()) {
+ StartupHelper.DeleteRunAll();
+ }
+ if (StartupHelper.HasRunUser()) {
+ StartupHelper.DeleteRunUser();
+ }
+ }
+ } catch (Exception e) {
+ Log.Warn("Problem checking registry, ignoring for now: ", e);
+ }
+ }
+
+ private void Settings_cancelClick(object sender, EventArgs e) {
+ DialogResult = DialogResult.Cancel;
+ }
+
+ private void Settings_okayClick(object sender, EventArgs e) {
+ if (CheckSettings()) {
+ HotkeyControl.UnregisterHotkeys();
+ SaveSettings();
+ StoreFields();
+ MainForm.RegisterHotkeys();
+
+ // Make sure the current language & settings are reflected in the Main-context menu
+ MainForm.Instance.UpdateUi();
+ DialogResult = DialogResult.OK;
+ } else {
+ tabcontrol.SelectTab(tab_output);
+ }
+ }
+
+ private void BrowseClick(object sender, EventArgs e) {
+ // Get the storage location and replace the environment variables
+ folderBrowserDialog1.SelectedPath = FilenameHelper.FillVariables(textbox_storagelocation.Text, false);
+ if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) {
+ // Only change if there is a change, otherwise we might overwrite the environment variables
+ if (folderBrowserDialog1.SelectedPath != null && !folderBrowserDialog1.SelectedPath.Equals(FilenameHelper.FillVariables(textbox_storagelocation.Text, false))) {
+ textbox_storagelocation.Text = folderBrowserDialog1.SelectedPath;
+ }
+ }
+ }
+
+ private void TrackBarJpegQualityScroll(object sender, EventArgs e) {
+ textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+
+ private void BtnPatternHelpClick(object sender, EventArgs e) {
+ string filenamepatternText = Language.GetString(LangKey.settings_message_filenamepattern);
+ // Convert %NUM% to ${NUM} for old language files!
+ filenamepatternText = Regex.Replace(filenamepatternText, "%([a-zA-Z_0-9]+)%", @"${$1}");
+ MessageBox.Show(filenamepatternText, Language.GetString(LangKey.settings_filenamepattern));
+ }
+
+ private void Listview_pluginsSelectedIndexChanged(object sender, EventArgs e) {
+ button_pluginconfigure.Enabled = PluginHelper.Instance.IsSelectedItemConfigurable(listview_plugins);
+ }
+
+ private void Button_pluginconfigureClick(object sender, EventArgs e) {
+ PluginHelper.Instance.ConfigureSelectedItem(listview_plugins);
+ }
+
+ private void Combobox_languageSelectedIndexChanged(object sender, EventArgs e) {
+ // Get the combobox values BEFORE changing the language
+ //EmailFormat selectedEmailFormat = GetSelected(combobox_emailformat);
+ WindowCaptureMode selectedWindowCaptureMode = GetSelected(combobox_window_capture_mode);
+ if (combobox_language.SelectedItem != null) {
+ Log.Debug("Setting language to: " + (string)combobox_language.SelectedValue);
+ Language.CurrentLanguage = (string)combobox_language.SelectedValue;
+ }
+ // Reflect language changes to the settings form
+ UpdateUi();
+
+ // Reflect Language changes form
+ ApplyLanguage();
+
+ // Update the email & windows capture mode
+ //SetEmailFormat(selectedEmailFormat);
+ SetWindowCaptureMode(selectedWindowCaptureMode);
+ }
+
+ private void Combobox_window_capture_modeSelectedIndexChanged(object sender, EventArgs e) {
+ int windowsVersion = Environment.OSVersion.Version.Major;
+ WindowCaptureMode mode = GetSelected(combobox_window_capture_mode);
+ if (windowsVersion >= 6) {
+ switch (mode) {
+ case WindowCaptureMode.Aero:
+ colorButton_window_background.Visible = true;
+ return;
+ }
+ }
+ colorButton_window_background.Visible = false;
+ }
+
+ ///
+ /// Check the destination settings
+ ///
+ private void CheckDestinationSettings() {
+ bool clipboardDestinationChecked = false;
+ bool pickerSelected = checkbox_picker.Checked;
+ bool destinationsEnabled = true;
+ if (coreConfiguration.Values.ContainsKey("Destinations")) {
+ destinationsEnabled = !coreConfiguration.Values["Destinations"].IsFixed;
+ }
+ listview_destinations.Enabled = destinationsEnabled;
+
+ foreach(int index in listview_destinations.CheckedIndices) {
+ ListViewItem item = listview_destinations.Items[index];
+ IDestination destinationFromTag = item.Tag as IDestination;
+ if (destinationFromTag != null && destinationFromTag.Designation.Equals(ClipboardDestination.DESIGNATION)) {
+ clipboardDestinationChecked = true;
+ break;
+ }
+ }
+
+ if (pickerSelected) {
+ listview_destinations.Enabled = false;
+ foreach(int index in listview_destinations.CheckedIndices) {
+ ListViewItem item = listview_destinations.Items[index];
+ item.Checked = false;
+ }
+ } else {
+ // Prevent multiple clipboard settings at once, see bug #3435056
+ if (clipboardDestinationChecked) {
+ checkbox_copypathtoclipboard.Checked = false;
+ checkbox_copypathtoclipboard.Enabled = false;
+ } else {
+ checkbox_copypathtoclipboard.Enabled = true;
+ }
+ }
+ }
+
+ private void DestinationsCheckStateChanged(object sender, EventArgs e) {
+ CheckDestinationSettings();
+ }
+
+ protected override void OnFieldsFilled() {
+ // the color radio button is not actually bound to a setting, but checked when monochrome/grayscale are not checked
+ if(!radioBtnGrayScale.Checked && !radioBtnMonochrome.Checked) {
+ radioBtnColorPrint.Checked = true;
+ }
+ }
+
+ ///
+ /// Set the enable state of the expert settings
+ ///
+ ///
+ private void ExpertSettingsEnableState(bool state) {
+ listview_clipboardformats.Enabled = state;
+ checkbox_autoreducecolors.Enabled = state;
+ checkbox_optimizeforrdp.Enabled = state;
+ checkbox_thumbnailpreview.Enabled = state;
+ textbox_footerpattern.Enabled = state;
+ textbox_counter.Enabled = state;
+ checkbox_suppresssavedialogatclose.Enabled = state;
+ checkbox_checkunstableupdates.Enabled = state;
+ checkbox_minimizememoryfootprint.Enabled = state;
+ checkbox_reuseeditor.Enabled = state;
+ }
+
+ ///
+ /// Called if the "I know what I am doing" on the settings form is changed
+ ///
+ ///
+ ///
+ private void checkbox_enableexpert_CheckedChanged(object sender, EventArgs e) {
+ CheckBox checkBox = sender as CheckBox;
+ if (checkBox != null) {
+ ExpertSettingsEnableState(checkBox.Checked);
+ }
+ }
+
+ private void radiobutton_CheckedChanged(object sender, EventArgs e) {
+ combobox_window_capture_mode.Enabled = radiobuttonWindowCapture.Checked;
+ }
+ }
+
+ public class ListviewWithDestinationComparer : IComparer {
+ public int Compare(object x, object y) {
+ if (!(x is ListViewItem)) {
+ return 0;
+ }
+ if (!(y is ListViewItem)) {
+ return 0;
+ }
+
+ ListViewItem l1 = (ListViewItem)x;
+ ListViewItem l2 = (ListViewItem)y;
+
+ IDestination firstDestination = l1.Tag as IDestination;
+ IDestination secondDestination = l2.Tag as IDestination;
+
+ if (secondDestination == null) {
+ return 1;
+ }
+ if (firstDestination != null && firstDestination.Priority == secondDestination.Priority) {
+ return string.Compare(firstDestination.Description, secondDestination.Description, StringComparison.Ordinal);
+ }
+ if (firstDestination != null) {
+ return firstDestination.Priority - secondDestination.Priority;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/src/Greenshot/Forms/SettingsForm.resx b/Greenshot/Forms/SettingsForm.resx
similarity index 94%
rename from src/Greenshot/Forms/SettingsForm.resx
rename to Greenshot/Forms/SettingsForm.resx
index c1d301171..d6671649c 100644
--- a/src/Greenshot/Forms/SettingsForm.resx
+++ b/Greenshot/Forms/SettingsForm.resx
@@ -112,15 +112,15 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
116, 17
-
+
iVBORw0KGgoAAAANSUhEUgAAABcAAAAYCAYAAAARfGZ1AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6
diff --git a/Greenshot/Forms/ToolStripMenuSelectList.cs b/Greenshot/Forms/ToolStripMenuSelectList.cs
new file mode 100644
index 000000000..e6a77f53b
--- /dev/null
+++ b/Greenshot/Forms/ToolStripMenuSelectList.cs
@@ -0,0 +1,271 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Greenshot.Forms {
+ ///
+ /// the ToolStripMenuSelectList makes it possible to have a single or multi-check menu
+ ///
+ public sealed class ToolStripMenuSelectList : ToolStripMenuItem {
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private readonly bool _multiCheckAllowed;
+ private bool _updateInProgress;
+ private static Image _defaultImage;
+
+ ///
+ /// Occurs when one of the list's child element's Checked state changes.
+ ///
+ public new event EventHandler CheckedChanged;
+ public object Identifier {
+ get;
+ private set;
+ }
+
+ public ToolStripMenuSelectList(object identifier, bool allowMultiCheck) {
+ Identifier = identifier;
+ CheckOnClick = false;
+ _multiCheckAllowed = allowMultiCheck;
+ if (_defaultImage == null || _defaultImage.Size != CoreConfig.IconSize) {
+ _defaultImage?.Dispose();
+ _defaultImage = ImageHelper.CreateEmpty(CoreConfig.IconSize.Width, CoreConfig.IconSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb, Color.Transparent, 96f, 96f);
+ }
+ Image = _defaultImage;
+ }
+ public ToolStripMenuSelectList() : this(null,false) {}
+ public ToolStripMenuSelectList(object identifier) : this(identifier,false) {}
+
+ ///
+ /// gets or sets the currently checked item
+ ///
+ public ToolStripMenuSelectListItem CheckedItem {
+
+ get {
+ IEnumerator items = DropDownItems.GetEnumerator();
+ while (items.MoveNext()) {
+ ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current;
+ if (tsmi != null && tsmi.Checked) {
+ return tsmi;
+ }
+ }
+ return null;
+ }
+ set {
+ IEnumerator items = DropDownItems.GetEnumerator();
+ while (items.MoveNext()) {
+ ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current;
+ if (tsmi != null && !_multiCheckAllowed && !tsmi.Equals(value)) {
+ tsmi.Checked = false;
+ } else if (tsmi != null && tsmi.Equals(value)) {
+ tsmi.Checked = true;
+ }
+ }
+ }
+ }
+
+ ///
+ /// gets or sets the currently checked items
+ ///
+ public ToolStripMenuSelectListItem[] CheckedItems {
+ get {
+ List sel = new List();
+ IEnumerator items = DropDownItems.GetEnumerator();
+ while(items.MoveNext()) {
+ ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current;
+ if (tsmi != null && tsmi.Checked) {
+ sel.Add(tsmi);
+ }
+ }
+ return sel.ToArray();
+ }
+ set {
+ if (!_multiCheckAllowed) {
+ throw new ArgumentException("Writing to checkedItems is only allowed in multi-check mode. Either set allowMultiCheck to true or use set SelectedItem instead of SelectedItems.");
+ }
+ IEnumerator items = DropDownItems.GetEnumerator();
+ IEnumerator sel = value.GetEnumerator();
+ while (items.MoveNext()) {
+ var toolStripMenuSelectListItem = (ToolStripMenuSelectListItem)items.Current;
+ if (toolStripMenuSelectListItem == null)
+ {
+ continue;
+ }
+ while (sel.MoveNext())
+ {
+ toolStripMenuSelectListItem.Checked = toolStripMenuSelectListItem.Equals(sel.Current);
+ if (!_multiCheckAllowed && !toolStripMenuSelectListItem.Equals(sel.Current)) {
+ toolStripMenuSelectListItem.Checked = false;
+ } else if (toolStripMenuSelectListItem.Equals(value)) {
+ toolStripMenuSelectListItem.Checked = true;
+ }
+ }
+ }
+ }
+ }
+
+ private void ItemCheckStateChanged(object sender, EventArgs e) {
+ if (_updateInProgress) {
+ return;
+ }
+ var toolStripMenuSelectListItem = (ToolStripMenuSelectListItem)sender;
+ _updateInProgress = true;
+ if (toolStripMenuSelectListItem.Checked && !_multiCheckAllowed) {
+ UncheckAll();
+ toolStripMenuSelectListItem.Checked = true;
+ }
+ _updateInProgress = false;
+ CheckedChanged?.Invoke(this, new ItemCheckedChangedEventArgs(toolStripMenuSelectListItem));
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// the icon to be displayed
+ /// the data to be returned when an item is queried
+ /// whether the item is initially checked
+ public void AddItem(string label, Image image, object data, bool isChecked) {
+ var toolStripMenuSelectListItem = new ToolStripMenuSelectListItem
+ {
+ Text = label
+ };
+ if (image == null) {
+ image = _defaultImage;
+ }
+ toolStripMenuSelectListItem.DisplayStyle = ToolStripItemDisplayStyle.Text;
+ toolStripMenuSelectListItem.Image = image;
+ toolStripMenuSelectListItem.CheckOnClick = true;
+ toolStripMenuSelectListItem.CheckStateChanged += ItemCheckStateChanged;
+ toolStripMenuSelectListItem.Data = data;
+ if (isChecked) {
+ if (!_multiCheckAllowed) {
+ _updateInProgress = true;
+ UncheckAll();
+ _updateInProgress = false;
+ }
+ toolStripMenuSelectListItem.Checked = true;
+ }
+ DropDownItems.Add(toolStripMenuSelectListItem);
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// the icon to be displayed
+ public void AddItem(string label, Image image) {
+ AddItem(label, image, null, false);
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// the data to be returned when an item is queried
+ public void AddItem(string label, object data) {
+ AddItem(label, null, data, false);
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ public void AddItem(string label) {
+ AddItem(label, null, null, false);
+ }
+
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// the icon to be displayed
+ /// whether the item is initially checked
+ public void AddItem(string label, Image image, bool isChecked) {
+ AddItem(label, image, null, isChecked);
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// the data to be returned when an item is queried
+ /// whether the item is initially checked
+ public void AddItem(string label, object data, bool isChecked) {
+ AddItem(label, null, data, isChecked);
+ }
+
+ ///
+ /// adds an item to the select list
+ ///
+ /// the label to be displayed
+ /// whether the item is initially checked
+ public void AddItem(string label, bool isChecked) {
+ AddItem(label, null, null, isChecked);
+ }
+
+ ///
+ /// unchecks all items of the list
+ ///
+ public void UncheckAll() {
+ IEnumerator items = DropDownItems.GetEnumerator();
+ while (items.MoveNext())
+ {
+ var toolStripMenuSelectListItem = (ToolStripMenuSelectListItem)items.Current;
+ if (toolStripMenuSelectListItem != null)
+ {
+ toolStripMenuSelectListItem.Checked = false;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Event class for the CheckedChanged event in the ToolStripMenuSelectList
+ ///
+ public class ItemCheckedChangedEventArgs : EventArgs {
+ public ToolStripMenuSelectListItem Item {
+ get;
+ set;
+ }
+ public ItemCheckedChangedEventArgs(ToolStripMenuSelectListItem item) {
+ Item = item;
+ }
+ }
+
+ ///
+ /// Wrapper around the ToolStripMenuItem, which can contain an object
+ /// Also the Checked property hides the normal checked property so we can render our own check
+ ///
+ public class ToolStripMenuSelectListItem : ToolStripMenuItem {
+ public object Data {
+ get;
+ set;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Editor/Forms/TornEdgeSettingsForm.Designer.cs b/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs
similarity index 82%
rename from src/Greenshot.Editor/Forms/TornEdgeSettingsForm.Designer.cs
rename to Greenshot/Forms/TornEdgeSettingsForm.Designer.cs
index bafdb0777..fc966f257 100644
--- a/src/Greenshot.Editor/Forms/TornEdgeSettingsForm.Designer.cs
+++ b/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs
@@ -1,439 +1,448 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Editor.Forms {
- partial class TornEdgeSettingsForm {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.thickness = new System.Windows.Forms.NumericUpDown();
- this.offsetX = new System.Windows.Forms.NumericUpDown();
- this.label3 = new System.Windows.Forms.Label();
- this.offsetY = new System.Windows.Forms.NumericUpDown();
- this.shadowDarkness = new System.Windows.Forms.TrackBar();
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.labelDarkness = new GreenshotLabel();
- this.labelOffset = new GreenshotLabel();
- this.labelThickness = new GreenshotLabel();
- this.toothsize = new System.Windows.Forms.NumericUpDown();
- this.label_toothsize = new GreenshotLabel();
- this.label_horizontaltoothrange = new GreenshotLabel();
- this.horizontaltoothrange = new System.Windows.Forms.NumericUpDown();
- this.labelVerticaltoothrange = new GreenshotLabel();
- this.verticaltoothrange = new System.Windows.Forms.NumericUpDown();
- this.top = new GreenshotCheckBox();
- this.right = new GreenshotCheckBox();
- this.bottom = new GreenshotCheckBox();
- this.left = new GreenshotCheckBox();
- this.shadowCheckbox = new GreenshotCheckBox();
- this.all = new GreenshotCheckBox();
- ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.shadowDarkness)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.toothsize)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.horizontaltoothrange)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.verticaltoothrange)).BeginInit();
- this.SuspendLayout();
- //
- // thickness
- //
- this.thickness.Location = new System.Drawing.Point(173, 35);
- this.thickness.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.thickness.Minimum = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.thickness.Name = "thickness";
- this.thickness.Size = new System.Drawing.Size(45, 20);
- this.thickness.TabIndex = 2;
- this.thickness.Value = new decimal(new int[] {
- 9,
- 0,
- 0,
- 0});
- //
- // offsetX
- //
- this.offsetX.Location = new System.Drawing.Point(102, 61);
- this.offsetX.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.offsetX.Minimum = new decimal(new int[] {
- 20,
- 0,
- 0,
- -2147483648});
- this.offsetX.Name = "offsetX";
- this.offsetX.Size = new System.Drawing.Size(45, 20);
- this.offsetX.TabIndex = 3;
- this.offsetX.Value = new decimal(new int[] {
- 1,
- 0,
- 0,
- -2147483648});
- //
- // label3
- //
- this.label3.Location = new System.Drawing.Point(153, 63);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(12, 13);
- this.label3.TabIndex = 5;
- this.label3.Text = "x";
- //
- // offsetY
- //
- this.offsetY.Location = new System.Drawing.Point(173, 61);
- this.offsetY.Maximum = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- this.offsetY.Minimum = new decimal(new int[] {
- 20,
- 0,
- 0,
- -2147483648});
- this.offsetY.Name = "offsetY";
- this.offsetY.Size = new System.Drawing.Size(45, 20);
- this.offsetY.TabIndex = 4;
- this.offsetY.Value = new decimal(new int[] {
- 1,
- 0,
- 0,
- -2147483648});
- //
- // shadowDarkness
- //
- this.shadowDarkness.Location = new System.Drawing.Point(102, 87);
- this.shadowDarkness.Maximum = 40;
- this.shadowDarkness.Minimum = 1;
- this.shadowDarkness.Name = "shadowDarkness";
- this.shadowDarkness.Size = new System.Drawing.Size(116, 45);
- this.shadowDarkness.TabIndex = 5;
- this.shadowDarkness.Value = 40;
- //
- // buttonOK
- //
- this.buttonOK.LanguageKey = "OK";
- this.buttonOK.Location = new System.Drawing.Point(334, 192);
- this.buttonOK.Name = "buttonOK";
- this.buttonOK.Size = new System.Drawing.Size(75, 23);
- this.buttonOK.TabIndex = 20;
- this.buttonOK.UseVisualStyleBackColor = true;
- this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
- //
- // buttonCancel
- //
- this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.buttonCancel.LanguageKey = "CANCEL";
- this.buttonCancel.Location = new System.Drawing.Point(415, 192);
- this.buttonCancel.Name = "buttonCancel";
- this.buttonCancel.Size = new System.Drawing.Size(75, 23);
- this.buttonCancel.TabIndex = 21;
- this.buttonCancel.UseVisualStyleBackColor = true;
- //
- // labelDarkness
- //
- this.labelDarkness.LanguageKey = "editor_dropshadow_darkness";
- this.labelDarkness.Location = new System.Drawing.Point(12, 97);
- this.labelDarkness.Name = "labelDarkness";
- this.labelDarkness.Size = new System.Drawing.Size(92, 13);
- this.labelDarkness.TabIndex = 13;
- this.labelDarkness.Text = "Shadow darkness";
- //
- // labelOffset
- //
- this.labelOffset.LanguageKey = "editor_dropshadow_offset";
- this.labelOffset.Location = new System.Drawing.Point(12, 63);
- this.labelOffset.Name = "labelOffset";
- this.labelOffset.Size = new System.Drawing.Size(75, 13);
- this.labelOffset.TabIndex = 14;
- //
- // labelThickness
- //
- this.labelThickness.LanguageKey = "editor_dropshadow_thickness";
- this.labelThickness.Location = new System.Drawing.Point(12, 37);
- this.labelThickness.Name = "labelThickness";
- this.labelThickness.Size = new System.Drawing.Size(94, 13);
- this.labelThickness.TabIndex = 15;
- //
- // toothsize
- //
- this.toothsize.Location = new System.Drawing.Point(173, 138);
- this.toothsize.Maximum = new decimal(new int[] {
- 40,
- 0,
- 0,
- 0});
- this.toothsize.Minimum = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.toothsize.Name = "toothsize";
- this.toothsize.Size = new System.Drawing.Size(45, 20);
- this.toothsize.TabIndex = 6;
- this.toothsize.Value = new decimal(new int[] {
- 12,
- 0,
- 0,
- 0});
- //
- // label_toothsize
- //
- this.label_toothsize.LanguageKey = "editor_tornedge_toothsize";
- this.label_toothsize.Location = new System.Drawing.Point(12, 140);
- this.label_toothsize.Name = "label_toothsize";
- this.label_toothsize.Size = new System.Drawing.Size(56, 13);
- this.label_toothsize.TabIndex = 17;
- //
- // label_horizontaltoothrange
- //
- this.label_horizontaltoothrange.LanguageKey = "editor_tornedge_horizontaltoothrange";
- this.label_horizontaltoothrange.Location = new System.Drawing.Point(12, 166);
- this.label_horizontaltoothrange.Name = "label_horizontaltoothrange";
- this.label_horizontaltoothrange.Size = new System.Drawing.Size(111, 13);
- this.label_horizontaltoothrange.TabIndex = 19; //
- // horizontaltoothrange
- //
- this.horizontaltoothrange.Location = new System.Drawing.Point(173, 164);
- this.horizontaltoothrange.Maximum = new decimal(new int[] {
- 40,
- 0,
- 0,
- 0});
- this.horizontaltoothrange.Minimum = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.horizontaltoothrange.Name = "horizontaltoothrange";
- this.horizontaltoothrange.Size = new System.Drawing.Size(45, 20);
- this.horizontaltoothrange.TabIndex = 7;
- this.horizontaltoothrange.Value = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- //
- // labelVerticaltoothrange
- //
- this.labelVerticaltoothrange.LanguageKey = "editor_tornedge_verticaltoothrange";
- this.labelVerticaltoothrange.Location = new System.Drawing.Point(12, 192);
- this.labelVerticaltoothrange.Name = "labelVerticaltoothrange";
- this.labelVerticaltoothrange.Size = new System.Drawing.Size(99, 13);
- this.labelVerticaltoothrange.TabIndex = 21;
- //
- // verticaltoothrange
- //
- this.verticaltoothrange.Location = new System.Drawing.Point(173, 190);
- this.verticaltoothrange.Maximum = new decimal(new int[] {
- 40,
- 0,
- 0,
- 0});
- this.verticaltoothrange.Minimum = new decimal(new int[] {
- 2,
- 0,
- 0,
- 0});
- this.verticaltoothrange.Name = "verticaltoothrange";
- this.verticaltoothrange.Size = new System.Drawing.Size(45, 20);
- this.verticaltoothrange.TabIndex = 8;
- this.verticaltoothrange.Value = new decimal(new int[] {
- 20,
- 0,
- 0,
- 0});
- //
- // top
- //
- this.top.CheckAlign = System.Drawing.ContentAlignment.BottomCenter;
- this.top.LanguageKey = "editor_tornedge_top";
- this.top.Location = new System.Drawing.Point(263, 35);
- this.top.Name = "top";
- this.top.Size = new System.Drawing.Size(228, 33);
- this.top.TabIndex = 10;
- this.top.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
- this.top.UseVisualStyleBackColor = true;
- this.top.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
- //
- // right
- //
- this.right.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.right.LanguageKey = "editor_tornedge_right";
- this.right.Location = new System.Drawing.Point(393, 60);
- this.right.Name = "right";
- this.right.Size = new System.Drawing.Size(98, 49);
- this.right.TabIndex = 11;
- this.right.UseVisualStyleBackColor = true;
- this.right.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
- //
- // bottom
- //
- this.bottom.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
- this.bottom.LanguageKey = "editor_tornedge_bottom";
- this.bottom.Location = new System.Drawing.Point(263, 98);
- this.bottom.Name = "bottom";
- this.bottom.Size = new System.Drawing.Size(228, 31);
- this.bottom.TabIndex = 12;
- this.bottom.TextAlign = System.Drawing.ContentAlignment.TopCenter;
- this.bottom.UseVisualStyleBackColor = true;
- this.bottom.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
- //
- // left
- //
- this.left.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.left.LanguageKey = "editor_tornedge_left";
- this.left.Location = new System.Drawing.Point(243, 60);
- this.left.Name = "left";
- this.left.Size = new System.Drawing.Size(118, 49);
- this.left.TabIndex = 13;
- this.left.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.left.UseVisualStyleBackColor = true;
- this.left.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
- //
- // shadowCheckbox
- //
- this.shadowCheckbox.LanguageKey = "editor_tornedge_shadow";
- this.shadowCheckbox.Location = new System.Drawing.Point(12, 12);
- this.shadowCheckbox.Name = "shadowCheckbox";
- this.shadowCheckbox.Size = new System.Drawing.Size(110, 17);
- this.shadowCheckbox.TabIndex = 1;
- this.shadowCheckbox.UseVisualStyleBackColor = true;
- this.shadowCheckbox.CheckedChanged += new System.EventHandler(this.ShadowCheckbox_CheckedChanged);
- //
- // all
- //
- this.all.LanguageKey = "editor_tornedge_all";
- this.all.Location = new System.Drawing.Point(251, 12);
- this.all.Name = "all";
- this.all.Size = new System.Drawing.Size(88, 17);
- this.all.TabIndex = 9;
- this.all.UseVisualStyleBackColor = true;
- this.all.CheckedChanged += new System.EventHandler(this.all_CheckedChanged);
- //
- // TornEdgeSettingsForm
- //
- this.AcceptButton = this.buttonOK;
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.CancelButton = this.buttonCancel;
- this.ClientSize = new System.Drawing.Size(502, 223);
- this.ControlBox = false;
- this.Controls.Add(this.all);
- this.Controls.Add(this.shadowCheckbox);
- this.Controls.Add(this.left);
- this.Controls.Add(this.bottom);
- this.Controls.Add(this.right);
- this.Controls.Add(this.top);
- this.Controls.Add(this.labelVerticaltoothrange);
- this.Controls.Add(this.verticaltoothrange);
- this.Controls.Add(this.label_horizontaltoothrange);
- this.Controls.Add(this.horizontaltoothrange);
- this.Controls.Add(this.label_toothsize);
- this.Controls.Add(this.toothsize);
- this.Controls.Add(this.labelThickness);
- this.Controls.Add(this.labelOffset);
- this.Controls.Add(this.labelDarkness);
- this.Controls.Add(this.buttonCancel);
- this.Controls.Add(this.buttonOK);
- this.Controls.Add(this.shadowDarkness);
- this.Controls.Add(this.offsetY);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.offsetX);
- this.Controls.Add(this.thickness);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
- this.LanguageKey = "editor_tornedge_settings";
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "TornEdgeSettingsForm";
- this.ShowIcon = false;
- this.Load += new System.EventHandler(this.TornEdgeSettingsForm_Load);
- ((System.ComponentModel.ISupportInitialize)(this.thickness)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetX)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.offsetY)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.shadowDarkness)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.toothsize)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.horizontaltoothrange)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.verticaltoothrange)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.NumericUpDown thickness;
- private System.Windows.Forms.NumericUpDown offsetX;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.NumericUpDown offsetY;
- private System.Windows.Forms.TrackBar shadowDarkness;
- private GreenshotButton buttonOK;
- private GreenshotButton buttonCancel;
- private GreenshotLabel labelDarkness;
- private GreenshotLabel labelOffset;
- private GreenshotLabel labelThickness;
- private System.Windows.Forms.NumericUpDown toothsize;
- private GreenshotLabel label_toothsize;
- private GreenshotLabel label_horizontaltoothrange;
- private System.Windows.Forms.NumericUpDown horizontaltoothrange;
- private GreenshotLabel labelVerticaltoothrange;
- private System.Windows.Forms.NumericUpDown verticaltoothrange;
- private GreenshotCheckBox top;
- private GreenshotCheckBox right;
- private GreenshotCheckBox bottom;
- private GreenshotCheckBox left;
- private GreenshotCheckBox shadowCheckbox;
- private GreenshotCheckBox all;
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+
+namespace Greenshot.Forms {
+ partial class TornEdgeSettingsForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.thickness = new System.Windows.Forms.NumericUpDown();
+ this.offsetX = new System.Windows.Forms.NumericUpDown();
+ this.label3 = new System.Windows.Forms.Label();
+ this.offsetY = new System.Windows.Forms.NumericUpDown();
+ this.shadowDarkness = new System.Windows.Forms.TrackBar();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.labelDarkness = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelOffset = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.labelThickness = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.toothsize = new System.Windows.Forms.NumericUpDown();
+ this.label_toothsize = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_horizontaltoothrange = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.horizontaltoothrange = new System.Windows.Forms.NumericUpDown();
+ this.labelVerticaltoothrange = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.verticaltoothrange = new System.Windows.Forms.NumericUpDown();
+ this.top = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.right = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.bottom = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.left = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.shadowCheckbox = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.all = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.shadowDarkness)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.toothsize)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.horizontaltoothrange)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.verticaltoothrange)).BeginInit();
+ this.SuspendLayout();
+ //
+ // thickness
+ //
+ this.thickness.Location = new System.Drawing.Point(173, 35);
+ this.thickness.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.thickness.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.thickness.Name = "thickness";
+ this.thickness.Size = new System.Drawing.Size(45, 20);
+ this.thickness.TabIndex = 2;
+ this.thickness.Value = new decimal(new int[] {
+ 9,
+ 0,
+ 0,
+ 0});
+ //
+ // offsetX
+ //
+ this.offsetX.Location = new System.Drawing.Point(102, 61);
+ this.offsetX.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.offsetX.Minimum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ -2147483648});
+ this.offsetX.Name = "offsetX";
+ this.offsetX.Size = new System.Drawing.Size(45, 20);
+ this.offsetX.TabIndex = 3;
+ this.offsetX.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(153, 63);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(12, 13);
+ this.label3.TabIndex = 5;
+ this.label3.Text = "x";
+ //
+ // offsetY
+ //
+ this.offsetY.Location = new System.Drawing.Point(173, 61);
+ this.offsetY.Maximum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ this.offsetY.Minimum = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ -2147483648});
+ this.offsetY.Name = "offsetY";
+ this.offsetY.Size = new System.Drawing.Size(45, 20);
+ this.offsetY.TabIndex = 4;
+ this.offsetY.Value = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ -2147483648});
+ //
+ // shadowDarkness
+ //
+ this.shadowDarkness.Location = new System.Drawing.Point(102, 87);
+ this.shadowDarkness.Maximum = 40;
+ this.shadowDarkness.Minimum = 1;
+ this.shadowDarkness.Name = "shadowDarkness";
+ this.shadowDarkness.Size = new System.Drawing.Size(116, 45);
+ this.shadowDarkness.TabIndex = 5;
+ this.shadowDarkness.Value = 40;
+ //
+ // buttonOK
+ //
+ this.buttonOK.LanguageKey = "OK";
+ this.buttonOK.Location = new System.Drawing.Point(334, 192);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 23);
+ this.buttonOK.TabIndex = 20;
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.LanguageKey = "CANCEL";
+ this.buttonCancel.Location = new System.Drawing.Point(415, 192);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 21;
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // labelDarkness
+ //
+ this.labelDarkness.AutoSize = true;
+ this.labelDarkness.LanguageKey = "editor_dropshadow_darkness";
+ this.labelDarkness.Location = new System.Drawing.Point(12, 97);
+ this.labelDarkness.Name = "labelDarkness";
+ this.labelDarkness.Size = new System.Drawing.Size(92, 13);
+ this.labelDarkness.TabIndex = 13;
+ this.labelDarkness.Text = "Shadow darkness";
+ //
+ // labelOffset
+ //
+ this.labelOffset.AutoSize = true;
+ this.labelOffset.LanguageKey = "editor_dropshadow_offset";
+ this.labelOffset.Location = new System.Drawing.Point(12, 63);
+ this.labelOffset.Name = "labelOffset";
+ this.labelOffset.Size = new System.Drawing.Size(75, 13);
+ this.labelOffset.TabIndex = 14;
+ //
+ // labelThickness
+ //
+ this.labelThickness.AutoSize = true;
+ this.labelThickness.LanguageKey = "editor_dropshadow_thickness";
+ this.labelThickness.Location = new System.Drawing.Point(12, 37);
+ this.labelThickness.Name = "labelThickness";
+ this.labelThickness.Size = new System.Drawing.Size(94, 13);
+ this.labelThickness.TabIndex = 15;
+ //
+ // toothsize
+ //
+ this.toothsize.Location = new System.Drawing.Point(173, 138);
+ this.toothsize.Maximum = new decimal(new int[] {
+ 40,
+ 0,
+ 0,
+ 0});
+ this.toothsize.Minimum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.toothsize.Name = "toothsize";
+ this.toothsize.Size = new System.Drawing.Size(45, 20);
+ this.toothsize.TabIndex = 6;
+ this.toothsize.Value = new decimal(new int[] {
+ 12,
+ 0,
+ 0,
+ 0});
+ //
+ // label_toothsize
+ //
+ this.label_toothsize.AutoSize = true;
+ this.label_toothsize.LanguageKey = "editor_tornedge_toothsize";
+ this.label_toothsize.Location = new System.Drawing.Point(12, 140);
+ this.label_toothsize.Name = "label_toothsize";
+ this.label_toothsize.Size = new System.Drawing.Size(56, 13);
+ this.label_toothsize.TabIndex = 17;
+ //
+ // label_horizontaltoothrange
+ //
+ this.label_horizontaltoothrange.AutoSize = true;
+ this.label_horizontaltoothrange.LanguageKey = "editor_tornedge_horizontaltoothrange";
+ this.label_horizontaltoothrange.Location = new System.Drawing.Point(12, 166);
+ this.label_horizontaltoothrange.Name = "label_horizontaltoothrange";
+ this.label_horizontaltoothrange.Size = new System.Drawing.Size(111, 13);
+ this.label_horizontaltoothrange.TabIndex = 19; //
+ // horizontaltoothrange
+ //
+ this.horizontaltoothrange.Location = new System.Drawing.Point(173, 164);
+ this.horizontaltoothrange.Maximum = new decimal(new int[] {
+ 40,
+ 0,
+ 0,
+ 0});
+ this.horizontaltoothrange.Minimum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.horizontaltoothrange.Name = "horizontaltoothrange";
+ this.horizontaltoothrange.Size = new System.Drawing.Size(45, 20);
+ this.horizontaltoothrange.TabIndex = 7;
+ this.horizontaltoothrange.Value = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ //
+ // labelVerticaltoothrange
+ //
+ this.labelVerticaltoothrange.AutoSize = true;
+ this.labelVerticaltoothrange.LanguageKey = "editor_tornedge_verticaltoothrange";
+ this.labelVerticaltoothrange.Location = new System.Drawing.Point(12, 192);
+ this.labelVerticaltoothrange.Name = "labelVerticaltoothrange";
+ this.labelVerticaltoothrange.Size = new System.Drawing.Size(99, 13);
+ this.labelVerticaltoothrange.TabIndex = 21;
+ //
+ // verticaltoothrange
+ //
+ this.verticaltoothrange.Location = new System.Drawing.Point(173, 190);
+ this.verticaltoothrange.Maximum = new decimal(new int[] {
+ 40,
+ 0,
+ 0,
+ 0});
+ this.verticaltoothrange.Minimum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.verticaltoothrange.Name = "verticaltoothrange";
+ this.verticaltoothrange.Size = new System.Drawing.Size(45, 20);
+ this.verticaltoothrange.TabIndex = 8;
+ this.verticaltoothrange.Value = new decimal(new int[] {
+ 20,
+ 0,
+ 0,
+ 0});
+ //
+ // top
+ //
+ this.top.CheckAlign = System.Drawing.ContentAlignment.BottomCenter;
+ this.top.LanguageKey = "editor_tornedge_top";
+ this.top.Location = new System.Drawing.Point(263, 35);
+ this.top.Name = "top";
+ this.top.Size = new System.Drawing.Size(228, 33);
+ this.top.TabIndex = 10;
+ this.top.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
+ this.top.UseVisualStyleBackColor = true;
+ this.top.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
+ //
+ // right
+ //
+ this.right.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.right.LanguageKey = "editor_tornedge_right";
+ this.right.Location = new System.Drawing.Point(393, 60);
+ this.right.Name = "right";
+ this.right.Size = new System.Drawing.Size(98, 49);
+ this.right.TabIndex = 11;
+ this.right.UseVisualStyleBackColor = true;
+ this.right.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
+ //
+ // bottom
+ //
+ this.bottom.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.bottom.LanguageKey = "editor_tornedge_bottom";
+ this.bottom.Location = new System.Drawing.Point(263, 98);
+ this.bottom.Name = "bottom";
+ this.bottom.Size = new System.Drawing.Size(228, 31);
+ this.bottom.TabIndex = 12;
+ this.bottom.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.bottom.UseVisualStyleBackColor = true;
+ this.bottom.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
+ //
+ // left
+ //
+ this.left.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.left.LanguageKey = "editor_tornedge_left";
+ this.left.Location = new System.Drawing.Point(243, 60);
+ this.left.Name = "left";
+ this.left.Size = new System.Drawing.Size(118, 49);
+ this.left.TabIndex = 13;
+ this.left.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.left.UseVisualStyleBackColor = true;
+ this.left.CheckedChanged += new System.EventHandler(this.AnySideCheckedChanged);
+ //
+ // shadowCheckbox
+ //
+ this.shadowCheckbox.AutoSize = true;
+ this.shadowCheckbox.LanguageKey = "editor_tornedge_shadow";
+ this.shadowCheckbox.Location = new System.Drawing.Point(12, 12);
+ this.shadowCheckbox.Name = "shadowCheckbox";
+ this.shadowCheckbox.Size = new System.Drawing.Size(110, 17);
+ this.shadowCheckbox.TabIndex = 1;
+ this.shadowCheckbox.UseVisualStyleBackColor = true;
+ this.shadowCheckbox.CheckedChanged += new System.EventHandler(this.ShadowCheckbox_CheckedChanged);
+ //
+ // all
+ //
+ this.all.AutoSize = true;
+ this.all.LanguageKey = "editor_tornedge_all";
+ this.all.Location = new System.Drawing.Point(251, 12);
+ this.all.Name = "all";
+ this.all.Size = new System.Drawing.Size(88, 17);
+ this.all.TabIndex = 9;
+ this.all.UseVisualStyleBackColor = true;
+ this.all.CheckedChanged += new System.EventHandler(this.all_CheckedChanged);
+ //
+ // TornEdgeSettingsForm
+ //
+ this.AcceptButton = this.buttonOK;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.buttonCancel;
+ this.ClientSize = new System.Drawing.Size(502, 223);
+ this.ControlBox = false;
+ this.Controls.Add(this.all);
+ this.Controls.Add(this.shadowCheckbox);
+ this.Controls.Add(this.left);
+ this.Controls.Add(this.bottom);
+ this.Controls.Add(this.right);
+ this.Controls.Add(this.top);
+ this.Controls.Add(this.labelVerticaltoothrange);
+ this.Controls.Add(this.verticaltoothrange);
+ this.Controls.Add(this.label_horizontaltoothrange);
+ this.Controls.Add(this.horizontaltoothrange);
+ this.Controls.Add(this.label_toothsize);
+ this.Controls.Add(this.toothsize);
+ this.Controls.Add(this.labelThickness);
+ this.Controls.Add(this.labelOffset);
+ this.Controls.Add(this.labelDarkness);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.Controls.Add(this.shadowDarkness);
+ this.Controls.Add(this.offsetY);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.offsetX);
+ this.Controls.Add(this.thickness);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.LanguageKey = "editor_tornedge_settings";
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "TornEdgeSettingsForm";
+ this.ShowIcon = false;
+ this.Load += new System.EventHandler(this.TornEdgeSettingsForm_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.thickness)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetX)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.offsetY)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.shadowDarkness)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.toothsize)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.horizontaltoothrange)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.verticaltoothrange)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.NumericUpDown thickness;
+ private System.Windows.Forms.NumericUpDown offsetX;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.NumericUpDown offsetY;
+ private System.Windows.Forms.TrackBar shadowDarkness;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotLabel labelDarkness;
+ private GreenshotPlugin.Controls.GreenshotLabel labelOffset;
+ private GreenshotPlugin.Controls.GreenshotLabel labelThickness;
+ private System.Windows.Forms.NumericUpDown toothsize;
+ private GreenshotPlugin.Controls.GreenshotLabel label_toothsize;
+ private GreenshotPlugin.Controls.GreenshotLabel label_horizontaltoothrange;
+ private System.Windows.Forms.NumericUpDown horizontaltoothrange;
+ private GreenshotPlugin.Controls.GreenshotLabel labelVerticaltoothrange;
+ private System.Windows.Forms.NumericUpDown verticaltoothrange;
+ private GreenshotPlugin.Controls.GreenshotCheckBox top;
+ private GreenshotPlugin.Controls.GreenshotCheckBox right;
+ private GreenshotPlugin.Controls.GreenshotCheckBox bottom;
+ private GreenshotPlugin.Controls.GreenshotCheckBox left;
+ private GreenshotPlugin.Controls.GreenshotCheckBox shadowCheckbox;
+ private GreenshotPlugin.Controls.GreenshotCheckBox all;
+ }
}
\ No newline at end of file
diff --git a/Greenshot/Forms/TornEdgeSettingsForm.cs b/Greenshot/Forms/TornEdgeSettingsForm.cs
new file mode 100644
index 000000000..1eb9b7e53
--- /dev/null
+++ b/Greenshot/Forms/TornEdgeSettingsForm.cs
@@ -0,0 +1,102 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using GreenshotPlugin.Effects;
+
+namespace Greenshot.Forms {
+ public partial class TornEdgeSettingsForm : BaseForm {
+ private readonly TornEdgeEffect _effect;
+ public TornEdgeSettingsForm(TornEdgeEffect effect) {
+ _effect = effect;
+ InitializeComponent();
+ ShowSettings();
+ }
+
+ private void ShowSettings() {
+ shadowCheckbox.Checked = _effect.GenerateShadow;
+ // Fix to prevent BUG-1753
+ shadowDarkness.Value = Math.Max(shadowDarkness.Minimum, Math.Min(shadowDarkness.Maximum, (int)(_effect.Darkness * shadowDarkness.Maximum)));
+ offsetX.Value = _effect.ShadowOffset.X;
+ offsetY.Value = _effect.ShadowOffset.Y;
+ toothsize.Value = _effect.ToothHeight;
+ verticaltoothrange.Value = _effect.VerticalToothRange;
+ horizontaltoothrange.Value = _effect.HorizontalToothRange;
+ top.Checked = _effect.Edges[0];
+ right.Checked = _effect.Edges[1];
+ bottom.Checked = _effect.Edges[2];
+ left.Checked = _effect.Edges[3];
+ }
+
+ private void ButtonOK_Click(object sender, EventArgs e) {
+ _effect.Darkness = shadowDarkness.Value / (float)40;
+ _effect.ShadowOffset = new Point((int)offsetX.Value, (int)offsetY.Value);
+ _effect.ShadowSize = (int)thickness.Value;
+ _effect.ToothHeight = (int)toothsize.Value;
+ _effect.VerticalToothRange = (int)verticaltoothrange.Value;
+ _effect.HorizontalToothRange = (int)horizontaltoothrange.Value;
+ _effect.Edges = new[] { top.Checked, right.Checked, bottom.Checked, left.Checked };
+ _effect.GenerateShadow = shadowCheckbox.Checked;
+ DialogResult = DialogResult.OK;
+ }
+
+ private void ShadowCheckbox_CheckedChanged(object sender, EventArgs e) {
+ thickness.Enabled = shadowCheckbox.Checked;
+ offsetX.Enabled = shadowCheckbox.Checked;
+ offsetY.Enabled = shadowCheckbox.Checked;
+ shadowDarkness.Enabled = shadowCheckbox.Checked;
+ }
+
+
+
+ private void all_CheckedChanged(object sender, EventArgs e) {
+ AnySideChangeChecked(top, all.Checked);
+ AnySideChangeChecked(right, all.Checked);
+ AnySideChangeChecked(bottom, all.Checked);
+ AnySideChangeChecked(left, all.Checked);
+ }
+
+ private void AnySideCheckedChanged(object sender, EventArgs e) {
+ all.CheckedChanged -= all_CheckedChanged;
+ all.Checked = top.Checked && right.Checked && bottom.Checked && left.Checked;
+ all.CheckedChanged += all_CheckedChanged;
+ }
+
+ ///
+ /// changes the Checked property of top/right/bottom/left checkboxes without triggering AnySideCheckedChange
+ ///
+ /// Checkbox to change Checked
+ /// true to check
+ private void AnySideChangeChecked(CheckBox cb, bool status) {
+ if (status != cb.Checked) {
+ cb.CheckedChanged -= AnySideCheckedChanged;
+ cb.Checked = status;
+ cb.CheckedChanged += AnySideCheckedChanged;
+ }
+ }
+
+ private void TornEdgeSettingsForm_Load(object sender, EventArgs e)
+ {
+
+ }
+ }
+}
diff --git a/Greenshot/GlobalSuppressions.cs b/Greenshot/GlobalSuppressions.cs
new file mode 100644
index 000000000..c3a0d1715
Binary files /dev/null and b/Greenshot/GlobalSuppressions.cs differ
diff --git a/Greenshot/Greenshot.csproj b/Greenshot/Greenshot.csproj
new file mode 100644
index 000000000..ef68e31b5
--- /dev/null
+++ b/Greenshot/Greenshot.csproj
@@ -0,0 +1,450 @@
+
+
+
+
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}
+ WinExe
+ Greenshot
+ Greenshot
+ OnBuildSuccess
+ icons\applicationIcon\icon.ico
+ True
+ False
+ 4
+ false
+ v2.0
+ greenshot.manifest
+
+
+
+ 3.5
+
+
+
+
+
+ ..\packages\LinqBridge.1.3.0\lib\net20\LinqBridge.dll
+ True
+
+
+ Lib\log4net.dll
+
+
+
+
+
+
+
+
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+ Component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Component
+
+
+
+ Form
+
+
+ AboutForm.cs
+
+
+ Form
+
+
+ Form
+
+
+ CaptureForm.cs
+
+
+ Form
+
+
+ DropShadowSettingsForm.cs
+
+
+ Form
+
+
+ ImageEditorForm.cs
+
+
+ Form
+
+
+ Form
+
+
+ ResizeSettingsForm.cs
+
+
+ Form
+
+
+ TornEdgeSettingsForm.cs
+
+
+ Form
+
+
+ LanguageDialog.cs
+
+
+ Form
+
+
+ MainForm.cs
+
+
+ Form
+
+
+ PrintOptionsDialog.cs
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+ Component
+
+
+ Form
+
+
+ BugReportForm.cs
+
+
+ Form
+
+
+ MovableShowColorForm.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ColorDialog.cs
+
+
+ ImageEditorForm.cs
+
+
+ MainForm.cs
+
+
+ SettingsForm.cs
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
+ PreserveNewest
+
+
+ Never
+
+
+ ColorDialog.cs
+
+
+ Form
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+ Always
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
+
+copy "$(ProjectDir)log4net-debug.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\log4net.xml"
+
+
\ No newline at end of file
diff --git a/Greenshot/GreenshotMain.cs b/Greenshot/GreenshotMain.cs
new file mode 100644
index 000000000..150e2aecb
--- /dev/null
+++ b/Greenshot/GreenshotMain.cs
@@ -0,0 +1,53 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Reflection;
+
+// Remove AppendPrivatePath warning:
+#pragma warning disable 0618
+namespace Greenshot {
+ ///
+ /// Description of Main.
+ ///
+ public class GreenshotMain {
+ static GreenshotMain() {
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ }
+
+ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
+ Assembly ayResult = null;
+ string sShortAssemblyName = args.Name.Split(',')[0];
+ Assembly[] ayAssemblies = AppDomain.CurrentDomain.GetAssemblies();
+ foreach (Assembly ayAssembly in ayAssemblies) {
+ if (sShortAssemblyName == ayAssembly.FullName.Split(',')[0]) {
+ ayResult = ayAssembly;
+ break;
+ }
+ }
+ return ayResult;
+ }
+
+ [STAThread]
+ public static void Main(string[] args) {
+ MainForm.Start(args);
+ }
+ }
+}
diff --git a/Greenshot/Help/HelpFileLoader.cs b/Greenshot/Help/HelpFileLoader.cs
new file mode 100644
index 000000000..d51fffcc4
--- /dev/null
+++ b/Greenshot/Help/HelpFileLoader.cs
@@ -0,0 +1,88 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Core;
+using System.Diagnostics;
+using System.Net;
+using log4net;
+
+namespace Greenshot.Help
+{
+ ///
+ /// Description of HelpFileLoader.
+ ///
+ public static class HelpFileLoader
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(HelpFileLoader));
+
+ private const string ExtHelpUrl = @"http://getgreenshot.org/help/";
+
+ public static void LoadHelp() {
+ string uri = FindOnlineHelpUrl(Language.CurrentLanguage) ?? Language.HelpFilePath;
+ Process.Start(uri);
+ }
+
+ /// URL of help file in selected ietf, or (if not present) default ietf, or null (if not present, too. probably indicating that there is no internet connection)
+ private static string FindOnlineHelpUrl(string currentIETF) {
+ string ret = null;
+
+ string extHelpUrlForCurrrentIETF = ExtHelpUrl;
+
+ if(!currentIETF.Equals("en-US")) {
+ extHelpUrlForCurrrentIETF += currentIETF.ToLower() + "/";
+ }
+
+ HttpStatusCode? httpStatusCode = GetHttpStatus(extHelpUrlForCurrrentIETF);
+ if(httpStatusCode == HttpStatusCode.OK) {
+ ret = extHelpUrlForCurrrentIETF;
+ } else if(httpStatusCode != null && !extHelpUrlForCurrrentIETF.Equals(ExtHelpUrl)) {
+ Log.DebugFormat("Localized online help not found at {0}, will try {1} as fallback", extHelpUrlForCurrrentIETF, ExtHelpUrl);
+ httpStatusCode = GetHttpStatus(ExtHelpUrl);
+ if(httpStatusCode == HttpStatusCode.OK) {
+ ret = ExtHelpUrl;
+ } else {
+ Log.WarnFormat("{0} returned status {1}", ExtHelpUrl, httpStatusCode);
+ }
+ } else if(httpStatusCode == null){
+ Log.Info("Internet connection does not seem to be available, will load help from file system.");
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Retrieves HTTP status for a given url.
+ ///
+ /// URL for which the HTTP status is to be checked
+ /// An HTTP status code, or null if there is none (probably indicating that there is no internet connection available
+ private static HttpStatusCode? GetHttpStatus(string url) {
+ try {
+ HttpWebRequest req = NetworkHelper.CreateWebRequest(url);
+ using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
+ {
+ return res.StatusCode;
+ }
+ } catch (WebException e) {
+ return ((HttpWebResponse) e.Response)?.StatusCode;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs
new file mode 100644
index 000000000..adffadb58
--- /dev/null
+++ b/Greenshot/Helpers/CaptureHelper.cs
@@ -0,0 +1,962 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Configuration;
+using Greenshot.Destinations;
+using Greenshot.Drawing;
+using Greenshot.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Greenshot.Helpers {
+ ///
+ /// CaptureHelper contains all the capture logic
+ ///
+ public class CaptureHelper : IDisposable {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(CaptureHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ // TODO: when we get the screen capture code working correctly, this needs to be enabled
+ //private static ScreenCaptureHelper screenCapture = null;
+ private List _windows = new List();
+ private WindowDetails _selectedCaptureWindow;
+ private Rectangle _captureRect = Rectangle.Empty;
+ private readonly bool _captureMouseCursor;
+ private ICapture _capture;
+ private CaptureMode _captureMode;
+ private ScreenCaptureMode _screenCaptureMode = ScreenCaptureMode.Auto;
+
+ ///
+ /// The public accessible Dispose
+ /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
+ ///
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ // The bulk of the clean-up code is implemented in Dispose(bool)
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ /// When disposing==true all non-managed resources should be freed too!
+ ///
+ ///
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ // Cleanup
+ }
+ // Unfortunately we can't dispose the capture, this might still be used somewhere else.
+ _windows = null;
+ _selectedCaptureWindow = null;
+ _capture = null;
+ // Empty working set after capturing
+ if (CoreConfig.MinimizeWorkingSetSize) {
+ PsAPI.EmptyWorkingSet();
+ }
+ }
+ public static void CaptureClipboard() {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Clipboard)) {
+ captureHelper.MakeCapture();
+ }
+ }
+ public static void CaptureRegion(bool captureMouse) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Region, captureMouse)) {
+ captureHelper.MakeCapture();
+ }
+ }
+ public static void CaptureRegion(bool captureMouse, IDestination destination) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Region, captureMouse, destination)) {
+ captureHelper.MakeCapture();
+ }
+ }
+ public static void CaptureRegion(bool captureMouse, Rectangle region) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Region, captureMouse)) {
+ captureHelper.MakeCapture(region);
+ }
+ }
+ public static void CaptureFullscreen(bool captureMouse, ScreenCaptureMode screenCaptureMode) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.FullScreen, captureMouse)) {
+ captureHelper._screenCaptureMode = screenCaptureMode;
+ captureHelper.MakeCapture();
+ }
+ }
+ public static void CaptureLastRegion(bool captureMouse) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.LastRegion, captureMouse)) {
+ captureHelper.MakeCapture();
+ }
+ }
+
+ public static void CaptureIe(bool captureMouse, WindowDetails windowToCapture) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.IE, captureMouse)) {
+ captureHelper.SelectedCaptureWindow = windowToCapture;
+ captureHelper.MakeCapture();
+ }
+ }
+
+ public static void CaptureWindow(bool captureMouse) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.ActiveWindow, captureMouse)) {
+ captureHelper.MakeCapture();
+ }
+ }
+
+ public static void CaptureWindow(WindowDetails windowToCapture) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.ActiveWindow)) {
+ captureHelper.SelectedCaptureWindow = windowToCapture;
+ captureHelper.MakeCapture();
+ }
+ }
+
+ public static void CaptureWindowInteractive(bool captureMouse) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Window)) {
+ captureHelper.MakeCapture();
+ }
+ }
+
+ public static void CaptureFile(string filename) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.File)) {
+ captureHelper.MakeCapture(filename);
+ }
+ }
+
+ public static void CaptureFile(string filename, IDestination destination) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.File)) {
+ captureHelper.AddDestination(destination).MakeCapture(filename);
+ }
+ }
+
+ public static void ImportCapture(ICapture captureToImport) {
+ using (CaptureHelper captureHelper = new CaptureHelper(CaptureMode.File)) {
+ captureHelper._capture = captureToImport;
+ captureHelper.HandleCapture();
+ }
+ }
+
+ public CaptureHelper AddDestination(IDestination destination) {
+ _capture.CaptureDetails.AddDestination(destination);
+ return this;
+ }
+
+ public CaptureHelper(CaptureMode captureMode) {
+ _captureMode = captureMode;
+ _capture = new Capture();
+ }
+
+ public CaptureHelper(CaptureMode captureMode, bool captureMouseCursor) : this(captureMode) {
+ _captureMouseCursor = captureMouseCursor;
+ }
+
+ public CaptureHelper(CaptureMode captureMode, bool captureMouseCursor, ScreenCaptureMode screenCaptureMode) : this(captureMode) {
+ _captureMouseCursor = captureMouseCursor;
+ _screenCaptureMode = screenCaptureMode;
+ }
+
+ public CaptureHelper(CaptureMode captureMode, bool captureMouseCursor, IDestination destination) : this(captureMode, captureMouseCursor) {
+ _capture.CaptureDetails.AddDestination(destination);
+ }
+
+ public WindowDetails SelectedCaptureWindow {
+ get {
+ return _selectedCaptureWindow;
+ }
+ set {
+ _selectedCaptureWindow = value;
+ }
+ }
+
+ private void DoCaptureFeedback() {
+ if(CoreConfig.PlayCameraSound) {
+ SoundHelper.Play();
+ }
+ }
+
+ ///
+ /// Make Capture with file name
+ ///
+ /// filename
+ private void MakeCapture(string filename) {
+ _capture.CaptureDetails.Filename = filename;
+ MakeCapture();
+ }
+
+ ///
+ /// Make Capture for region
+ ///
+ /// Rectangle
+ private void MakeCapture(Rectangle region) {
+ _captureRect = region;
+ MakeCapture();
+ }
+
+
+ ///
+ /// Make Capture with specified destinations
+ ///
+ private void MakeCapture() {
+ Thread retrieveWindowDetailsThread = null;
+
+ // This fixes a problem when a balloon is still visible and a capture needs to be taken
+ // forcefully removes the balloon!
+ if (!CoreConfig.HideTrayicon) {
+ MainForm.Instance.NotifyIcon.Visible = false;
+ MainForm.Instance.NotifyIcon.Visible = true;
+ }
+ Log.Debug($"Capturing with mode {_captureMode} and using Cursor {_captureMouseCursor}");
+ _capture.CaptureDetails.CaptureMode = _captureMode;
+
+ // Get the windows details in a seperate thread, only for those captures that have a Feedback
+ // As currently the "elements" aren't used, we don't need them yet
+ switch (_captureMode) {
+ case CaptureMode.Region:
+ // Check if a region is pre-supplied!
+ if (Rectangle.Empty.Equals(_captureRect)) {
+ retrieveWindowDetailsThread = PrepareForCaptureWithFeedback();
+ }
+ break;
+ case CaptureMode.Window:
+ retrieveWindowDetailsThread = PrepareForCaptureWithFeedback();
+ break;
+ }
+
+ // Add destinations if no-one passed a handler
+ if (_capture.CaptureDetails.CaptureDestinations == null || _capture.CaptureDetails.CaptureDestinations.Count == 0) {
+ AddConfiguredDestination();
+ }
+
+ // Delay for the Context menu
+ if (CoreConfig.CaptureDelay > 0) {
+ Thread.Sleep(CoreConfig.CaptureDelay);
+ } else {
+ CoreConfig.CaptureDelay = 0;
+ }
+
+ // Capture Mousecursor if we are not loading from file or clipboard, only show when needed
+ if (_captureMode != CaptureMode.File && _captureMode != CaptureMode.Clipboard)
+ {
+ _capture = WindowCapture.CaptureCursor(_capture);
+ _capture.CursorVisible = _captureMouseCursor && CoreConfig.CaptureMousepointer;
+ }
+
+ switch(_captureMode) {
+ case CaptureMode.Window:
+ _capture = WindowCapture.CaptureScreen(_capture);
+ _capture.CaptureDetails.AddMetaData("source", "Screen");
+ SetDpi();
+ CaptureWithFeedback();
+ break;
+ case CaptureMode.ActiveWindow:
+ if (CaptureActiveWindow()) {
+ // Capture worked, offset mouse according to screen bounds and capture location
+ _capture.MoveMouseLocation(_capture.ScreenBounds.Location.X-_capture.Location.X, _capture.ScreenBounds.Location.Y-_capture.Location.Y);
+ _capture.CaptureDetails.AddMetaData("source", "Window");
+ } else {
+ _captureMode = CaptureMode.FullScreen;
+ _capture = WindowCapture.CaptureScreen(_capture);
+ _capture.CaptureDetails.AddMetaData("source", "Screen");
+ _capture.CaptureDetails.Title = "Screen";
+ }
+ SetDpi();
+ HandleCapture();
+ break;
+ case CaptureMode.IE:
+ if (IeCaptureHelper.CaptureIe(_capture, SelectedCaptureWindow) != null) {
+ _capture.CaptureDetails.AddMetaData("source", "Internet Explorer");
+ SetDpi();
+ HandleCapture();
+ }
+ break;
+ case CaptureMode.FullScreen:
+ // Check how we need to capture the screen
+ bool captureTaken = false;
+ switch (_screenCaptureMode) {
+ case ScreenCaptureMode.Auto:
+ Point mouseLocation = User32.GetCursorLocation();
+ foreach (Screen screen in Screen.AllScreens) {
+ if (screen.Bounds.Contains(mouseLocation)) {
+ _capture = WindowCapture.CaptureRectangle(_capture, screen.Bounds);
+ captureTaken = true;
+ break;
+ }
+ }
+ break;
+ case ScreenCaptureMode.Fixed:
+ if (CoreConfig.ScreenToCapture > 0 && CoreConfig.ScreenToCapture <= Screen.AllScreens.Length) {
+ _capture = WindowCapture.CaptureRectangle(_capture, Screen.AllScreens[CoreConfig.ScreenToCapture].Bounds);
+ captureTaken = true;
+ }
+ break;
+ case ScreenCaptureMode.FullScreen:
+ // Do nothing, we take the fullscreen capture automatically
+ break;
+ }
+ if (!captureTaken) {
+ _capture = WindowCapture.CaptureScreen(_capture);
+ }
+ SetDpi();
+ HandleCapture();
+ break;
+ case CaptureMode.Clipboard:
+ Image clipboardImage = ClipboardHelper.GetImage();
+ if (clipboardImage != null) {
+ if (_capture != null) {
+ _capture.Image = clipboardImage;
+ } else {
+ _capture = new Capture(clipboardImage);
+ }
+ _capture.CaptureDetails.Title = "Clipboard";
+ _capture.CaptureDetails.AddMetaData("source", "Clipboard");
+ // Force Editor, keep picker
+ if (_capture.CaptureDetails.HasDestination(PickerDestination.DESIGNATION)) {
+ _capture.CaptureDetails.ClearDestinations();
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(PickerDestination.DESIGNATION));
+ } else {
+ _capture.CaptureDetails.ClearDestinations();
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
+ }
+ HandleCapture();
+ } else {
+ MessageBox.Show(Language.GetString("clipboard_noimage"));
+ }
+ break;
+ case CaptureMode.File:
+ Image fileImage = null;
+ string filename = _capture.CaptureDetails.Filename;
+
+ if (!string.IsNullOrEmpty(filename)) {
+ try {
+ if (filename.ToLower().EndsWith("." + OutputFormat.greenshot)) {
+ ISurface surface = new Surface();
+ surface = ImageOutput.LoadGreenshotSurface(filename, surface);
+ surface.CaptureDetails = _capture.CaptureDetails;
+ DestinationHelper.GetDestination(EditorDestination.DESIGNATION).ExportCapture(true, surface, _capture.CaptureDetails);
+ break;
+ }
+ } catch (Exception e) {
+ Log.Error(e.Message, e);
+ MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename));
+ }
+ try {
+ fileImage = ImageHelper.LoadImage(filename);
+ } catch (Exception e) {
+ Log.Error(e.Message, e);
+ MessageBox.Show(Language.GetFormattedString(LangKey.error_openfile, filename));
+ }
+ }
+ if (fileImage != null) {
+ _capture.CaptureDetails.Title = Path.GetFileNameWithoutExtension(filename);
+ _capture.CaptureDetails.AddMetaData("file", filename);
+ _capture.CaptureDetails.AddMetaData("source", "file");
+ if (_capture != null) {
+ _capture.Image = fileImage;
+ } else {
+ _capture = new Capture(fileImage);
+ }
+ // Force Editor, keep picker, this is currently the only usefull destination
+ if (_capture.CaptureDetails.HasDestination(PickerDestination.DESIGNATION)) {
+ _capture.CaptureDetails.ClearDestinations();
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(PickerDestination.DESIGNATION));
+ } else {
+ _capture.CaptureDetails.ClearDestinations();
+ _capture.CaptureDetails.AddDestination(DestinationHelper.GetDestination(EditorDestination.DESIGNATION));
+ }
+ HandleCapture();
+ }
+ break;
+ case CaptureMode.LastRegion:
+ if (!CoreConfig.LastCapturedRegion.IsEmpty) {
+ _capture = WindowCapture.CaptureRectangle(_capture, CoreConfig.LastCapturedRegion);
+ // TODO: Reactive / check if the elements code is activated
+ //if (windowDetailsThread != null) {
+ // windowDetailsThread.Join();
+ //}
+
+ // Set capture title, fixing bug #3569703
+ foreach (WindowDetails window in WindowDetails.GetVisibleWindows()) {
+ Point estimatedLocation = new Point(CoreConfig.LastCapturedRegion.X + CoreConfig.LastCapturedRegion.Width / 2, CoreConfig.LastCapturedRegion.Y + CoreConfig.LastCapturedRegion.Height / 2);
+ if (window.Contains(estimatedLocation)) {
+ _selectedCaptureWindow = window;
+ _capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
+ break;
+ }
+ }
+ // Move cursor, fixing bug #3569703
+ _capture.MoveMouseLocation(_capture.ScreenBounds.Location.X - _capture.Location.X, _capture.ScreenBounds.Location.Y - _capture.Location.Y);
+ //capture.MoveElements(capture.ScreenBounds.Location.X - capture.Location.X, capture.ScreenBounds.Location.Y - capture.Location.Y);
+
+ _capture.CaptureDetails.AddMetaData("source", "screen");
+ SetDpi();
+ HandleCapture();
+ }
+ break;
+ case CaptureMode.Region:
+ // Check if a region is pre-supplied!
+ if (Rectangle.Empty.Equals(_captureRect)) {
+ _capture = WindowCapture.CaptureScreen(_capture);
+ _capture.CaptureDetails.AddMetaData("source", "screen");
+ SetDpi();
+ CaptureWithFeedback();
+ } else {
+ _capture = WindowCapture.CaptureRectangle(_capture, _captureRect);
+ _capture.CaptureDetails.AddMetaData("source", "screen");
+ SetDpi();
+ HandleCapture();
+ }
+ break;
+ default:
+ Log.Warn("Unknown capture mode: " + _captureMode);
+ break;
+ }
+ // Wait for thread, otherwise we can't dipose the CaptureHelper
+ retrieveWindowDetailsThread?.Join();
+ if (_capture != null) {
+ Log.Debug("Disposing capture");
+ _capture.Dispose();
+ }
+ }
+
+ ///
+ /// Pre-Initialization for CaptureWithFeedback, this will get all the windows before we change anything
+ ///
+ private Thread PrepareForCaptureWithFeedback() {
+ _windows = new List();
+
+ // If the App Launcher is visisble, no other windows are active
+ WindowDetails appLauncherWindow = WindowDetails.GetAppLauncher();
+ if (appLauncherWindow != null && appLauncherWindow.Visible) {
+ _windows.Add(appLauncherWindow);
+ return null;
+ }
+
+ Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails)
+ {
+ Name = "Retrieve window details",
+ IsBackground = true
+ };
+ getWindowDetailsThread.Start();
+ return getWindowDetailsThread;
+ }
+
+ private void RetrieveWindowDetails() {
+ Log.Debug("start RetrieveWindowDetails");
+ // Start Enumeration of "active" windows
+ foreach (var window in WindowDetails.GetVisibleWindows()) {
+ // Make sure the details are retrieved once
+ window.FreezeDetails();
+
+ // Force children retrieval, sometimes windows close on losing focus and this is solved by caching
+ int goLevelDeep = 3;
+ if (CoreConfig.WindowCaptureAllChildLocations) {
+ goLevelDeep = 20;
+ }
+ window.GetChildren(goLevelDeep);
+ lock (_windows) {
+ _windows.Add(window);
+ }
+ }
+ Log.Debug("end RetrieveWindowDetails");
+ }
+
+ private void AddConfiguredDestination() {
+ foreach(string destinationDesignation in CoreConfig.OutputDestinations) {
+ IDestination destination = DestinationHelper.GetDestination(destinationDesignation);
+ if (destination != null) {
+ _capture.CaptureDetails.AddDestination(destination);
+ }
+ }
+ }
+
+ ///
+ /// If a balloon tip is show for a taken capture, this handles the click on it
+ ///
+ ///
+ ///
+ private void OpenCaptureOnClick(object sender, EventArgs e) {
+ SurfaceMessageEventArgs eventArgs = MainForm.Instance.NotifyIcon.Tag as SurfaceMessageEventArgs;
+ if (eventArgs == null) {
+ Log.Warn("OpenCaptureOnClick called without SurfaceMessageEventArgs");
+ RemoveEventHandler(sender, e);
+ return;
+ }
+ ISurface surface = eventArgs.Surface;
+ if (surface != null)
+ {
+ switch (eventArgs.MessageType)
+ {
+ case SurfaceMessageTyp.FileSaved:
+ ExplorerHelper.OpenInExplorer(surface.LastSaveFullPath);
+ break;
+ case SurfaceMessageTyp.UploadedUri:
+ Process.Start(surface.UploadUrl);
+ break;
+ }
+ }
+ Log.DebugFormat("Deregistering the BalloonTipClicked");
+ RemoveEventHandler(sender, e);
+ }
+
+ private void RemoveEventHandler(object sender, EventArgs e) {
+ MainForm.Instance.NotifyIcon.BalloonTipClicked -= OpenCaptureOnClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed -= RemoveEventHandler;
+ MainForm.Instance.NotifyIcon.Tag = null;
+ }
+
+ ///
+ /// This is the SufraceMessageEvent receiver
+ ///
+ ///
+ ///
+ private void SurfaceMessageReceived(object sender, SurfaceMessageEventArgs eventArgs) {
+ if (string.IsNullOrEmpty(eventArgs?.Message)) {
+ return;
+ }
+ if (MainForm.Instance == null)
+ {
+ return;
+ }
+ switch (eventArgs.MessageType) {
+ case SurfaceMessageTyp.Error:
+ MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", eventArgs.Message, ToolTipIcon.Error);
+ break;
+ case SurfaceMessageTyp.Info:
+ MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", eventArgs.Message, ToolTipIcon.Info);
+ break;
+ case SurfaceMessageTyp.FileSaved:
+ case SurfaceMessageTyp.UploadedUri:
+ // Show a balloon and register an event handler to open the "capture" for if someone clicks the balloon.
+ MainForm.Instance.NotifyIcon.BalloonTipClicked += OpenCaptureOnClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed += RemoveEventHandler;
+ // Store for later usage
+ MainForm.Instance.NotifyIcon.Tag = eventArgs;
+ MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", eventArgs.Message, ToolTipIcon.Info);
+ break;
+ }
+ }
+
+
+ private void HandleCapture() {
+ // Flag to see if the image was "exported" so the FileEditor doesn't
+ // ask to save the file as long as nothing is done.
+ bool outputMade = false;
+
+ // Make sure the user sees that the capture is made
+ if (_capture.CaptureDetails.CaptureMode == CaptureMode.File || _capture.CaptureDetails.CaptureMode == CaptureMode.Clipboard) {
+ // Maybe not "made" but the original is still there... somehow
+ outputMade = true;
+ } else {
+ // Make sure the resolution is set correctly!
+ if (_capture.CaptureDetails != null) {
+ ((Bitmap) _capture.Image)?.SetResolution(_capture.CaptureDetails.DpiX, _capture.CaptureDetails.DpiY);
+ }
+ DoCaptureFeedback();
+ }
+
+ Log.Debug("A capture of: " + _capture.CaptureDetails.Title);
+
+ // check if someone has passed a destination
+ if (_capture.CaptureDetails.CaptureDestinations == null || _capture.CaptureDetails.CaptureDestinations.Count == 0) {
+ AddConfiguredDestination();
+ }
+
+ // Create Surface with capture, this way elements can be added automatically (like the mouse cursor)
+ Surface surface = new Surface(_capture)
+ {
+ Modified = !outputMade
+ };
+
+ // Register notify events if this is wanted
+ if (CoreConfig.ShowTrayNotification && !CoreConfig.HideTrayicon) {
+ surface.SurfaceMessage += SurfaceMessageReceived;
+
+ }
+ // Let the processors do their job
+ foreach(IProcessor processor in ProcessorHelper.GetAllProcessors()) {
+ if (processor.isActive) {
+ Log.InfoFormat("Calling processor {0}", processor.Description);
+ processor.ProcessCapture(surface, _capture.CaptureDetails);
+ }
+ }
+
+ // As the surfaces copies the reference to the image, make sure the image is not being disposed (a trick to save memory)
+ _capture.Image = null;
+
+ // Get CaptureDetails as we need it even after the capture is disposed
+ ICaptureDetails captureDetails = _capture.CaptureDetails;
+ bool canDisposeSurface = true;
+
+ if (captureDetails.HasDestination(PickerDestination.DESIGNATION)) {
+ DestinationHelper.ExportCapture(false, PickerDestination.DESIGNATION, surface, captureDetails);
+ captureDetails.CaptureDestinations.Clear();
+ canDisposeSurface = false;
+ }
+
+ // Disable capturing
+ _captureMode = CaptureMode.None;
+ // Dispose the capture, we don't need it anymore (the surface copied all information and we got the title (if any)).
+ _capture.Dispose();
+ _capture = null;
+
+ int destinationCount = captureDetails.CaptureDestinations.Count;
+ if (destinationCount > 0) {
+ // Flag to detect if we need to create a temp file for the email
+ // or use the file that was written
+ foreach(IDestination destination in captureDetails.CaptureDestinations) {
+ if (PickerDestination.DESIGNATION.Equals(destination.Designation)) {
+ continue;
+ }
+ Log.InfoFormat("Calling destination {0}", destination.Description);
+
+ ExportInformation exportInformation = destination.ExportCapture(false, surface, captureDetails);
+ if (EditorDestination.DESIGNATION.Equals(destination.Designation) && exportInformation.ExportMade) {
+ canDisposeSurface = false;
+ }
+ }
+ }
+ if (canDisposeSurface) {
+ surface.Dispose();
+ }
+ }
+
+ private bool CaptureActiveWindow() {
+ bool presupplied = false;
+ Log.Debug("CaptureActiveWindow");
+ if (_selectedCaptureWindow != null) {
+ Log.Debug("Using supplied window");
+ presupplied = true;
+ } else {
+ _selectedCaptureWindow = WindowDetails.GetActiveWindow();
+ if (_selectedCaptureWindow != null) {
+ if (Log.IsDebugEnabled)
+ {
+ Log.DebugFormat("Capturing window: {0} with {1}", _selectedCaptureWindow.Text, _selectedCaptureWindow.WindowRectangle);
+ }
+ }
+ }
+ if (_selectedCaptureWindow == null || (!presupplied && _selectedCaptureWindow.Iconic)) {
+ Log.Warn("No window to capture!");
+ // Nothing to capture, code up in the stack will capture the full screen
+ return false;
+ }
+ if (!presupplied && _selectedCaptureWindow != null && _selectedCaptureWindow.Iconic) {
+ // Restore the window making sure it's visible!
+ // This is done mainly for a screen capture, but some applications like Excel and TOAD have weird behaviour!
+ _selectedCaptureWindow.Restore();
+ }
+ _selectedCaptureWindow = SelectCaptureWindow(_selectedCaptureWindow);
+ if (_selectedCaptureWindow == null) {
+ Log.Warn("No window to capture, after SelectCaptureWindow!");
+ // Nothing to capture, code up in the stack will capture the full screen
+ return false;
+ }
+ // Fix for Bug #3430560
+ CoreConfig.LastCapturedRegion = _selectedCaptureWindow.WindowRectangle;
+ bool returnValue = CaptureWindow(_selectedCaptureWindow, _capture, CoreConfig.WindowCaptureMode) != null;
+ return returnValue;
+ }
+
+ ///
+ /// Select the window to capture, this has logic which takes care of certain special applications
+ /// like TOAD or Excel
+ ///
+ /// WindowDetails with the target Window
+ /// WindowDetails with the target Window OR a replacement
+ public static WindowDetails SelectCaptureWindow(WindowDetails windowToCapture) {
+ Rectangle windowRectangle = windowToCapture.WindowRectangle;
+ if (windowRectangle.Width == 0 || windowRectangle.Height == 0) {
+ Log.WarnFormat("Window {0} has nothing to capture, using workaround to find other window of same process.", windowToCapture.Text);
+ // Trying workaround, the size 0 arrises with e.g. Toad.exe, has a different Window when minimized
+ WindowDetails linkedWindow = WindowDetails.GetLinkedWindow(windowToCapture);
+ if (linkedWindow != null) {
+ windowToCapture = linkedWindow;
+ } else {
+ return null;
+ }
+ }
+ return windowToCapture;
+ }
+
+ ///
+ /// Check if Process uses PresentationFramework.dll -> meaning it uses WPF
+ ///
+ /// Proces to check for the presentation framework
+ /// true if the process uses WPF
+ private static bool IsWpf(Process process) {
+ if (process != null) {
+ try {
+ foreach (ProcessModule module in process.Modules) {
+ if (module.ModuleName.StartsWith("PresentationFramework")) {
+ Log.InfoFormat("Found that Process {0} uses {1}, assuming it's using WPF", process.ProcessName, module.FileName);
+ return true;
+ }
+ }
+ } catch (Exception) {
+ // Access denied on the modules
+ Log.WarnFormat("No access on the modules from process {0}, assuming WPF is used.", process.ProcessName);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Capture the supplied Window
+ ///
+ /// Window to capture
+ /// The capture to store the details
+ /// What WindowCaptureMode to use
+ ///
+ public static ICapture CaptureWindow(WindowDetails windowToCapture, ICapture captureForWindow, WindowCaptureMode windowCaptureMode) {
+ if (captureForWindow == null) {
+ captureForWindow = new Capture();
+ }
+ Rectangle windowRectangle = windowToCapture.WindowRectangle;
+
+ // When Vista & DWM (Aero) enabled
+ bool dwmEnabled = DWM.IsDwmEnabled();
+ // get process name to be able to exclude certain processes from certain capture modes
+ using (Process process = windowToCapture.Process) {
+ bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto;
+ // For WindowCaptureMode.Auto we check:
+ // 1) Is window IE, use IE Capture
+ // 2) Is Windows >= Vista & DWM enabled: use DWM
+ // 3) Otherwise use GDI (Screen might be also okay but might lose content)
+ if (isAutoMode) {
+ if (CoreConfig.IECapture && IeCaptureHelper.IsIeWindow(windowToCapture)) {
+ try {
+ ICapture ieCapture = IeCaptureHelper.CaptureIe(captureForWindow, windowToCapture);
+ if (ieCapture != null) {
+ return ieCapture;
+ }
+ } catch (Exception ex) {
+ Log.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message);
+ }
+ }
+
+ // Take default screen
+ windowCaptureMode = WindowCaptureMode.Screen;
+
+ // Change to GDI, if allowed
+ if (!windowToCapture.IsMetroApp && WindowCapture.IsGdiAllowed(process)) {
+ if (!dwmEnabled && IsWpf(process)) {
+ // do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF
+ Log.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName);
+ } else {
+ windowCaptureMode = WindowCaptureMode.GDI;
+ }
+ }
+
+ // Change to DWM, if enabled and allowed
+ if (dwmEnabled) {
+ if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) {
+ windowCaptureMode = WindowCaptureMode.Aero;
+ }
+ }
+ } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) {
+ if (!dwmEnabled || (!windowToCapture.IsMetroApp && !WindowCapture.IsDwmAllowed(process))) {
+ // Take default screen
+ windowCaptureMode = WindowCaptureMode.Screen;
+ // Change to GDI, if allowed
+ if (WindowCapture.IsGdiAllowed(process)) {
+ windowCaptureMode = WindowCaptureMode.GDI;
+ }
+ }
+ } else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.IsGdiAllowed(process)) {
+ // GDI not allowed, take screen
+ windowCaptureMode = WindowCaptureMode.Screen;
+ }
+
+ Log.InfoFormat("Capturing window with mode {0}", windowCaptureMode);
+ bool captureTaken = false;
+ windowRectangle.Intersect(captureForWindow.ScreenBounds);
+ // Try to capture
+ while (!captureTaken) {
+ ICapture tmpCapture = null;
+ switch (windowCaptureMode) {
+ case WindowCaptureMode.GDI:
+ if (WindowCapture.IsGdiAllowed(process)) {
+ if (windowToCapture.Iconic) {
+ // Restore the window making sure it's visible!
+ windowToCapture.Restore();
+ } else {
+ windowToCapture.ToForeground(false);
+ }
+ tmpCapture = windowToCapture.CaptureGdiWindow(captureForWindow);
+ if (tmpCapture != null) {
+ // check if GDI capture any good, by comparing it with the screen content
+ int blackCountGdi = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false);
+ int gdiPixels = tmpCapture.Image.Width * tmpCapture.Image.Height;
+ int blackPercentageGdi = blackCountGdi * 100 / gdiPixels;
+ if (blackPercentageGdi >= 1) {
+ int screenPixels = windowRectangle.Width * windowRectangle.Height;
+ using (ICapture screenCapture = new Capture()) {
+ screenCapture.CaptureDetails = captureForWindow.CaptureDetails;
+ if (WindowCapture.CaptureRectangleFromDesktopScreen(screenCapture, windowRectangle) != null) {
+ int blackCountScreen = ImageHelper.CountColor(screenCapture.Image, Color.Black, false);
+ int blackPercentageScreen = blackCountScreen * 100 / screenPixels;
+ if (screenPixels == gdiPixels) {
+ // "easy compare", both have the same size
+ // If GDI has more black, use the screen capture.
+ if (blackPercentageGdi > blackPercentageScreen) {
+ Log.Debug("Using screen capture, as GDI had additional black.");
+ // changeing the image will automatically dispose the previous
+ tmpCapture.Image = screenCapture.Image;
+ // Make sure it's not disposed, else the picture is gone!
+ screenCapture.NullImage();
+ }
+ } else if (screenPixels < gdiPixels) {
+ // Screen capture is cropped, window is outside of screen
+ if (blackPercentageGdi > 50 && blackPercentageGdi > blackPercentageScreen) {
+ Log.Debug("Using screen capture, as GDI had additional black.");
+ // changeing the image will automatically dispose the previous
+ tmpCapture.Image = screenCapture.Image;
+ // Make sure it's not disposed, else the picture is gone!
+ screenCapture.NullImage();
+ }
+ } else {
+ // Use the GDI capture by doing nothing
+ Log.Debug("This should not happen, how can there be more screen as GDI pixels?");
+ }
+ }
+ }
+ }
+ }
+ }
+ if (tmpCapture != null) {
+ captureForWindow = tmpCapture;
+ captureTaken = true;
+ } else {
+ // A problem, try Screen
+ windowCaptureMode = WindowCaptureMode.Screen;
+ }
+ break;
+ case WindowCaptureMode.Aero:
+ case WindowCaptureMode.AeroTransparent:
+ if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) {
+ tmpCapture = windowToCapture.CaptureDwmWindow(captureForWindow, windowCaptureMode, isAutoMode);
+ }
+ if (tmpCapture != null) {
+ captureForWindow = tmpCapture;
+ captureTaken = true;
+ } else {
+ // A problem, try GDI
+ windowCaptureMode = WindowCaptureMode.GDI;
+ }
+ break;
+ default:
+ // Screen capture
+ if (windowToCapture.Iconic) {
+ // Restore the window making sure it's visible!
+ windowToCapture.Restore();
+ } else {
+ windowToCapture.ToForeground();
+ }
+
+ try {
+ captureForWindow = WindowCapture.CaptureRectangleFromDesktopScreen(captureForWindow, windowRectangle);
+ captureTaken = true;
+ } catch (Exception e) {
+ Log.Error("Problem capturing", e);
+ return null;
+ }
+ break;
+ }
+ }
+ }
+
+ if (captureForWindow != null)
+ {
+ captureForWindow.CaptureDetails.Title = windowToCapture.Text;
+ }
+
+ return captureForWindow;
+ }
+
+ private void SetDpi() {
+ // Workaround for proble with DPI retrieval, the FromHwnd activates the window...
+ WindowDetails previouslyActiveWindow = WindowDetails.GetActiveWindow();
+ // Workaround for changed DPI settings in Windows 7
+ using (Graphics graphics = Graphics.FromHwnd(MainForm.Instance.Handle)) {
+ _capture.CaptureDetails.DpiX = graphics.DpiX;
+ _capture.CaptureDetails.DpiY = graphics.DpiY;
+ }
+ // Set previouslyActiveWindow as foreground window
+ previouslyActiveWindow?.ToForeground(false);
+ if (_capture.CaptureDetails != null) {
+ ((Bitmap) _capture.Image)?.SetResolution(_capture.CaptureDetails.DpiX, _capture.CaptureDetails.DpiY);
+ }
+
+ }
+
+ #region capture with feedback
+ private void CaptureWithFeedback() {
+ // The following, to be precise the HideApp, causes the app to close as described in BUG-1620
+ // Added check for metro (Modern UI) apps, which might be maximized and cover the screen.
+
+ //foreach(WindowDetails app in WindowDetails.GetMetroApps()) {
+ // if (app.Maximised) {
+ // app.HideApp();
+ // }
+ //}
+
+ using (CaptureForm captureForm = new CaptureForm(_capture, _windows)) {
+ // Make sure the form is hidden after showing, even if an exception occurs, so all errors will be shown
+ DialogResult result;
+ try {
+ result = captureForm.ShowDialog(MainForm.Instance);
+ } finally {
+ captureForm.Hide();
+ }
+ if (result == DialogResult.OK) {
+ _selectedCaptureWindow = captureForm.SelectedCaptureWindow;
+ _captureRect = captureForm.CaptureRectangle;
+ // Get title
+ if (_selectedCaptureWindow != null) {
+ _capture.CaptureDetails.Title = _selectedCaptureWindow.Text;
+ }
+
+ if (_captureRect.Height > 0 && _captureRect.Width > 0) {
+ // Take the captureRect, this already is specified as bitmap coordinates
+ _capture.Crop(_captureRect);
+
+ // save for re-capturing later and show recapture context menu option
+ // Important here is that the location needs to be offsetted back to screen coordinates!
+ Rectangle tmpRectangle = _captureRect;
+ tmpRectangle.Offset(_capture.ScreenBounds.Location.X, _capture.ScreenBounds.Location.Y);
+ CoreConfig.LastCapturedRegion = tmpRectangle;
+ HandleCapture();
+ }
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Greenshot/Helpers/Colors.cs b/Greenshot/Helpers/Colors.cs
new file mode 100644
index 000000000..31ade9946
--- /dev/null
+++ b/Greenshot/Helpers/Colors.cs
@@ -0,0 +1,52 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Greenshot.Helpers {
+ public static class Colors {
+ public static bool IsVisible(Color c) {
+ return c != null && !c.Equals(Color.Empty) && !c.Equals(Color.Transparent) && c.A > 0;
+ }
+
+ public static Color Mix(List colors) {
+ int a = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ int count = 0;
+ foreach (Color color in colors) {
+ if (!color.Equals(Color.Empty)) {
+ a += color.A;
+ r += color.R;
+ g += color.G;
+ b += color.B;
+ count++;
+ }
+ }
+ if (count==0) {
+ return Color.Empty;
+ }
+ return Color.FromArgb(a/count, r/count, g/count, b/count);
+ }
+ }
+}
diff --git a/Greenshot/Helpers/CopyData.cs b/Greenshot/Helpers/CopyData.cs
new file mode 100644
index 000000000..131684e9d
--- /dev/null
+++ b/Greenshot/Helpers/CopyData.cs
@@ -0,0 +1,532 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Windows.Forms;
+
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Helpers {
+ public enum CommandEnum { OpenFile, Exit, FirstLaunch, ReloadConfig };
+
+ ///
+ /// Code from vbAccelerator, location:
+ /// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows_Messages/Simple_Interprocess_Communication/WM_COPYDATA_Demo_zip_SimpleInterprocessCommunicationsCS_CopyData_cs.asp
+ ///
+ [Serializable()]
+ public class CopyDataTransport {
+ private readonly List> _commands;
+ public List> Commands => _commands;
+
+ public CopyDataTransport() {
+ _commands = new List>();
+ }
+
+ public CopyDataTransport(CommandEnum command) : this() {
+ AddCommand(command, null);
+ }
+
+ public CopyDataTransport(CommandEnum command, string commandData) : this() {
+ AddCommand(command, commandData);
+ }
+ public void AddCommand(CommandEnum command) {
+ _commands.Add(new KeyValuePair(command, null));
+ }
+ public void AddCommand(CommandEnum command, string commandData) {
+ _commands.Add(new KeyValuePair(command, commandData));
+ }
+
+ }
+
+ public delegate void CopyDataReceivedEventHandler(object sender, CopyDataReceivedEventArgs e);
+
+ ///
+ /// A class which wraps using Windows native WM_COPYDATA
+ /// message to send interprocess data between applications.
+ /// This is a simple technique for interprocess data sends
+ /// using Windows. The alternative to this is to use
+ /// Remoting, which requires a network card and a way
+ /// to register the Remoting name of an object so it
+ /// can be read by other applications.
+ ///
+ public class CopyData : NativeWindow, IDisposable {
+ ///
+ /// Event raised when data is received on any of the channels
+ /// this class is subscribed to.
+ ///
+ public event CopyDataReceivedEventHandler CopyDataReceived;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct COPYDATASTRUCT {
+ public readonly IntPtr dwData;
+ public readonly int cbData;
+ public readonly IntPtr lpData;
+ }
+
+ private const int WM_COPYDATA = 0x4A;
+ private const int WM_DESTROY = 0x2;
+
+ #region Member Variables
+ private CopyDataChannels _channels;
+ #endregion
+
+ ///
+ /// Override for a form's Window Procedure to handle WM_COPYDATA
+ /// messages sent by other instances of this class.
+ ///
+ /// The Windows Message information.
+ protected override void WndProc (ref Message m ) {
+ if (m.Msg == WM_COPYDATA)
+ {
+ var cds = (COPYDATASTRUCT) Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
+ if (cds.cbData > 0) {
+ byte[] data = new byte[cds.cbData];
+ Marshal.Copy(cds.lpData, data, 0, cds.cbData);
+ MemoryStream stream = new MemoryStream(data);
+ BinaryFormatter b = new BinaryFormatter();
+ CopyDataObjectData cdo = (CopyDataObjectData) b.Deserialize(stream);
+
+ if (_channels != null && _channels.Contains(cdo.Channel)) {
+ CopyDataReceivedEventArgs d = new CopyDataReceivedEventArgs(cdo.Channel, cdo.Data, cdo.Sent);
+ OnCopyDataReceived(d);
+ m.Result = (IntPtr) 1;
+ }
+ }
+ } else if (m.Msg == WM_DESTROY) {
+ // WM_DESTROY fires before OnHandleChanged and is
+ // a better place to ensure that we've cleared
+ // everything up.
+ _channels?.OnHandleChange();
+ base.OnHandleChange();
+ }
+ base.WndProc(ref m);
+ }
+
+ ///
+ /// Raises the DataReceived event from this class.
+ ///
+ /// The data which has been received.
+ protected void OnCopyDataReceived(CopyDataReceivedEventArgs e)
+ {
+ CopyDataReceived?.Invoke(this, e);
+ }
+
+ ///
+ /// If the form's handle changes, the properties associated
+ /// with the window need to be cleared up. This override ensures
+ /// that it is done. Note that the CopyData class will then
+ /// stop responding to events and it should be recreated once
+ /// the new handle has been assigned.
+ ///
+ protected override void OnHandleChange () {
+ // need to clear up everything we had set.
+ _channels?.OnHandleChange();
+ base.OnHandleChange();
+ }
+
+ ///
+ /// Gets the collection of channels.
+ ///
+ public CopyDataChannels Channels => _channels;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Clears up any resources associated with this object.
+ ///
+ protected virtual void Dispose(bool disposing) {
+ if (disposing && _channels != null) {
+ _channels.Clear();
+ _channels = null;
+ }
+ }
+
+ ///
+ /// Constructs a new instance of the CopyData class
+ ///
+ public CopyData() {
+ _channels = new CopyDataChannels(this);
+ }
+
+ ///
+ /// Finalises a CopyData class which has not been disposed.
+ /// There may be a minor resource leak if this class is finalised
+ /// after the form it is associated with.
+ ///
+ ~CopyData() {
+ Dispose(false);
+ }
+ }
+
+ ///
+ /// Contains data and other information associated with data
+ /// which has been sent from another application.
+ ///
+ public class CopyDataReceivedEventArgs : EventArgs {
+ ///
+ /// Gets the channel name that this data was sent on.
+ ///
+ public string ChannelName { get; }
+
+ ///
+ /// Gets the data object which was sent.
+ ///
+ public object Data { get; }
+
+ ///
+ /// Gets the date and time which at the data was sent
+ /// by the sending application.
+ ///
+ public DateTime Sent { get; }
+
+ ///
+ /// Gets the date and time which this data item as
+ /// received.
+ ///
+ public DateTime Received { get; }
+
+ ///
+ /// Constructs an instance of this class.
+ ///
+ /// The channel that the data was received from
+ /// The data which was sent
+ /// The date and time the data was sent
+ internal CopyDataReceivedEventArgs(string channelName, object data, DateTime sent) {
+ ChannelName = channelName;
+ Data = data;
+ Sent = sent;
+ Received = DateTime.Now;
+ }
+ }
+
+ ///
+ /// A strongly-typed collection of channels associated with the CopyData
+ /// class.
+ ///
+ public class CopyDataChannels : DictionaryBase {
+ private readonly NativeWindow _owner;
+
+ ///
+ /// Returns an enumerator for each of the CopyDataChannel objects
+ /// within this collection.
+ ///
+ /// An enumerator for each of the CopyDataChannel objects
+ /// within this collection.
+ public new IEnumerator GetEnumerator ( ) {
+ return Dictionary.Values.GetEnumerator();
+ }
+
+ ///
+ /// Returns the CopyDataChannel at the specified 0-based index.
+ ///
+ public CopyDataChannel this[int index] {
+ get {
+ CopyDataChannel ret = null;
+ int i = 0;
+ foreach (CopyDataChannel cdc in Dictionary.Values) {
+ i++;
+ if (i == index) {
+ ret = cdc;
+ break;
+ }
+ }
+ return ret;
+ }
+ }
+ ///
+ /// Returns the CopyDataChannel for the specified channelName
+ ///
+ public CopyDataChannel this[string channelName] => (CopyDataChannel) Dictionary[channelName];
+
+ ///
+ /// Adds a new channel on which this application can send and
+ /// receive messages.
+ ///
+ public void Add(string channelName) {
+ CopyDataChannel cdc = new CopyDataChannel(_owner, channelName);
+ Dictionary.Add(channelName , cdc);
+ }
+ ///
+ /// Removes an existing channel.
+ ///
+ /// The channel to remove
+ public void Remove(string channelName) {
+ Dictionary.Remove(channelName);
+ }
+ ///
+ /// Gets/sets whether this channel contains a CopyDataChannel
+ /// for the specified channelName.
+ ///
+ public bool Contains(string channelName) {
+ return Dictionary.Contains(channelName);
+ }
+
+ ///
+ /// Ensures the resources associated with a CopyDataChannel
+ /// object collected by this class are cleared up.
+ ///
+ protected override void OnClear() {
+ foreach (CopyDataChannel cdc in Dictionary.Values) {
+ cdc.Dispose();
+ }
+ base.OnClear();
+ }
+
+ ///
+ /// Ensures any resoures associated with the CopyDataChannel object
+ /// which has been removed are cleared up.
+ ///
+ /// The channelName
+ /// The CopyDataChannel object which has
+ /// just been removed
+ protected override void OnRemoveComplete ( object key , object data ) {
+ ( (CopyDataChannel) data).Dispose();
+ OnRemove(key, data);
+ }
+
+ ///
+ /// If the form's handle changes, the properties associated
+ /// with the window need to be cleared up. This override ensures
+ /// that it is done. Note that the CopyData class will then
+ /// stop responding to events and it should be recreated once
+ /// the new handle has been assigned.
+ ///
+ public void OnHandleChange() {
+ foreach (CopyDataChannel cdc in Dictionary.Values) {
+ cdc.OnHandleChange();
+ }
+ }
+
+ ///
+ /// Constructs a new instance of the CopyDataChannels collection.
+ /// Automatically managed by the CopyData class.
+ ///
+ /// The NativeWindow this collection
+ /// will be associated with
+ internal CopyDataChannels(NativeWindow owner) {
+ _owner = owner;
+ }
+ }
+
+ ///
+ /// A channel on which messages can be sent.
+ ///
+ public class CopyDataChannel : IDisposable {
+ #region Unmanaged Code
+ [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern IntPtr GetProp(IntPtr hwnd, string lpString);
+ [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern bool SetProp(IntPtr hwnd, string lpString, IntPtr hData);
+ [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern IntPtr RemoveProp(IntPtr hwnd, string lpString);
+
+ [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, ref COPYDATASTRUCT lParam);
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct COPYDATASTRUCT {
+ public IntPtr dwData;
+ public int cbData;
+ public IntPtr lpData;
+ }
+
+ private const int WM_COPYDATA = 0x4A;
+ #endregion
+
+ #region Member Variables
+
+ private readonly NativeWindow _owner;
+ private bool _recreateChannel;
+ #endregion
+
+ ///
+ /// Gets the name associated with this channel.
+ ///
+ public string ChannelName { get; private set; }
+
+ ///
+ /// Sends the specified object on this channel to any other
+ /// applications which are listening. The object must have the
+ /// SerializableAttribute set, or must implement ISerializable.
+ ///
+ /// The object to send
+ /// The number of recipients
+ public int Send(object obj) {
+ int recipients = 0;
+
+ if (_recreateChannel) {
+ // handle has changed
+ AddChannel();
+ }
+
+ CopyDataObjectData cdo = new CopyDataObjectData(obj, ChannelName);
+
+
+ // Try to do a binary serialization on obj.
+ // This will throw and exception if the object to
+ // be passed isn't serializable.
+ BinaryFormatter b = new BinaryFormatter();
+ MemoryStream stream = new MemoryStream();
+ b.Serialize(stream, cdo);
+ stream.Flush();
+
+ // Now move the data into a pointer so we can send
+ // it using WM_COPYDATA:
+ // Get the length of the data:
+ int dataSize = (int)stream.Length;
+ if (dataSize > 0) {
+ // This isn't very efficient if your data is very large.
+ // First we copy to a byte array, then copy to a CoTask
+ // Mem object... And when we use WM_COPYDATA windows will
+ // make yet another copy! But if you're talking about 4K
+ // or less of data then it doesn't really matter.
+ byte[] data = new byte[dataSize];
+ stream.Seek(0, SeekOrigin.Begin);
+ stream.Read(data, 0, dataSize);
+ IntPtr ptrData = Marshal.AllocCoTaskMem(dataSize);
+ Marshal.Copy(data, 0, ptrData, dataSize);
+
+ // Send the data to each window identified on
+ // the channel:
+ foreach(WindowDetails window in WindowDetails.GetAllWindows()) {
+ if (!window.Handle.Equals(_owner.Handle)) {
+ if (GetProp(window.Handle, ChannelName) != IntPtr.Zero) {
+ COPYDATASTRUCT cds = new COPYDATASTRUCT
+ {
+ cbData = dataSize,
+ dwData = IntPtr.Zero,
+ lpData = ptrData
+ };
+ SendMessage(window.Handle, WM_COPYDATA, _owner.Handle, ref cds);
+ recipients += Marshal.GetLastWin32Error() == 0 ? 1 : 0;
+ }
+ }
+ }
+
+ // Clear up the data:
+ Marshal.FreeCoTaskMem(ptrData);
+ }
+ stream.Close();
+
+ return recipients;
+ }
+
+ private void AddChannel() {
+ // Tag this window with property "channelName"
+ SetProp(_owner.Handle, ChannelName, _owner.Handle);
+ }
+
+ private void RemoveChannel() {
+ // Remove the "channelName" property from this window
+ RemoveProp(_owner.Handle, ChannelName);
+ }
+
+ ///
+ /// If the form's handle changes, the properties associated
+ /// with the window need to be cleared up. This method ensures
+ /// that it is done. Note that the CopyData class will then
+ /// stop responding to events and it should be recreated once
+ /// the new handle has been assigned.
+ ///
+ public void OnHandleChange() {
+ RemoveChannel();
+ _recreateChannel = true;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Clears up any resources associated with this channel.
+ ///
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (ChannelName.Length > 0) {
+ RemoveChannel();
+ }
+ ChannelName = "";
+ }
+ }
+
+ ///
+ /// Constructs a new instance of a CopyData channel. Called
+ /// automatically by the CopyDataChannels collection.
+ ///
+ /// The owning native window
+ /// The name of the channel to
+ /// send messages on
+ internal CopyDataChannel(NativeWindow owner, string channelName) {
+ _owner = owner;
+ ChannelName = channelName;
+ AddChannel();
+ }
+
+ ~CopyDataChannel() {
+ Dispose(false);
+ }
+ }
+
+ ///
+ /// A class which wraps the data being copied, used
+ /// internally within the CopyData class objects.
+ ///
+ [Serializable()]
+ internal class CopyDataObjectData {
+ ///
+ /// The Object to copy. Must be Serializable.
+ ///
+ public object Data;
+ ///
+ /// The date and time this object was sent.
+ ///
+ public DateTime Sent;
+ ///
+ /// The name of the channel this object is being sent on
+ ///
+ public string Channel;
+
+ ///
+ /// Constructs a new instance of this object
+ ///
+ /// The data to copy
+ /// The channel name to send on
+ /// If data is not serializable.
+ public CopyDataObjectData(object data, string channel) {
+ Data = data;
+ if (!data.GetType().IsSerializable) {
+ throw new ArgumentException("Data object must be serializable.",
+ nameof(data));
+ }
+ Channel = channel;
+ Sent = DateTime.Now;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/DestinationHelper.cs b/Greenshot/Helpers/DestinationHelper.cs
new file mode 100644
index 000000000..6ce287460
--- /dev/null
+++ b/Greenshot/Helpers/DestinationHelper.cs
@@ -0,0 +1,145 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Description of DestinationHelper.
+ ///
+ public static class DestinationHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(DestinationHelper));
+ private static readonly Dictionary RegisteredDestinations = new Dictionary();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ /// Initialize the destinations
+ static DestinationHelper() {
+ foreach(Type destinationType in InterfaceUtils.GetSubclassesOf(typeof(IDestination),true)) {
+ // Only take our own
+ if (!"Greenshot.Destinations".Equals(destinationType.Namespace)) {
+ continue;
+ }
+ if (!destinationType.IsAbstract) {
+ IDestination destination;
+ try {
+ destination = (IDestination)Activator.CreateInstance(destinationType);
+ } catch (Exception e) {
+ Log.ErrorFormat("Can't create instance of {0}", destinationType);
+ Log.Error(e);
+ continue;
+ }
+ if (destination.IsActive) {
+ Log.DebugFormat("Found destination {0} with designation {1}", destinationType.Name, destination.Designation);
+ RegisterDestination(destination);
+ } else {
+ Log.DebugFormat("Ignoring destination {0} with designation {1}", destinationType.Name, destination.Designation);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Register your destination here, if it doesn't come from a plugin and needs to be available
+ ///
+ ///
+ public static void RegisterDestination(IDestination destination) {
+ if (CoreConfig.ExcludeDestinations == null || !CoreConfig.ExcludeDestinations.Contains(destination.Designation)) {
+ // don't test the key, an exception should happen wenn it's not unique
+ RegisteredDestinations.Add(destination.Designation, destination);
+ }
+ }
+
+ ///
+ /// Method to get all the destinations from the plugins
+ ///
+ /// List of IDestination
+ private static List GetPluginDestinations() {
+ List destinations = new List();
+ foreach (PluginAttribute pluginAttribute in PluginHelper.Instance.Plugins.Keys) {
+ IGreenshotPlugin plugin = PluginHelper.Instance.Plugins[pluginAttribute];
+ try {
+ foreach (IDestination destination in plugin.Destinations()) {
+ if (CoreConfig.ExcludeDestinations == null || !CoreConfig.ExcludeDestinations.Contains(destination.Designation)) {
+ destinations.Add(destination);
+ }
+ }
+ } catch (Exception ex) {
+ Log.ErrorFormat("Couldn't get destinations from the plugin {0}", pluginAttribute.Name);
+ Log.Error(ex);
+ }
+ }
+ destinations.Sort();
+ return destinations;
+ }
+
+ ///
+ /// Get a list of all destinations, registered or supplied by a plugin
+ ///
+ ///
+ public static List GetAllDestinations() {
+ List destinations = new List();
+ destinations.AddRange(RegisteredDestinations.Values);
+ destinations.AddRange(GetPluginDestinations());
+ destinations.Sort();
+ return destinations;
+ }
+
+ ///
+ /// Get a destination by a designation
+ ///
+ /// Designation of the destination
+ /// IDestination or null
+ public static IDestination GetDestination(string designation) {
+ if (designation == null) {
+ return null;
+ }
+ if (RegisteredDestinations.ContainsKey(designation)) {
+ return RegisteredDestinations[designation];
+ }
+ foreach (IDestination destination in GetPluginDestinations()) {
+ if (designation.Equals(destination.Designation)) {
+ return destination;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// A simple helper method which will call ExportCapture for the destination with the specified designation
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static ExportInformation ExportCapture(bool manuallyInitiated, string designation, ISurface surface, ICaptureDetails captureDetails) {
+ IDestination destination = GetDestination(designation);
+ if (destination != null && destination.IsActive) {
+ return destination.ExportCapture(manuallyInitiated, surface, captureDetails);
+ }
+ return null;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/EnvironmentInfo.cs b/Greenshot/Helpers/EnvironmentInfo.cs
new file mode 100644
index 000000000..70ce20a8c
--- /dev/null
+++ b/Greenshot/Helpers/EnvironmentInfo.cs
@@ -0,0 +1,817 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace Greenshot.Helpers
+{
+ ///
+ /// Description of EnvironmentInfo.
+ ///
+ public static class EnvironmentInfo
+ {
+ private static bool? _isWindows;
+
+ public static bool IsWindows
+ {
+ get
+ {
+ if (_isWindows.HasValue)
+ {
+ return _isWindows.Value;
+ }
+ _isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win");
+ return _isWindows.Value;
+ }
+ }
+
+ public static bool IsNet45OrNewer()
+ {
+ // Class "ReflectionContext" exists from .NET 4.5 onwards.
+ return Type.GetType("System.Reflection.ReflectionContext", false) != null;
+ }
+
+ public static string EnvironmentToString(bool newline)
+ {
+ StringBuilder environment = new StringBuilder();
+ environment.Append("Software version: " + Application.ProductVersion);
+ if (IniConfig.IsPortable) {
+ environment.Append(" Portable");
+ }
+ environment.Append(" (" + OsInfo.Bits + " bit)");
+
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.Append(".NET runtime version: " + Environment.Version);
+ if (IsNet45OrNewer())
+ {
+ environment.Append("+");
+
+ }
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
+
+ if (IsWindows)
+ {
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.Append(string.Format("OS: {0} {1} {2} (x{3}) {4}", OsInfo.Name, OsInfo.Edition, OsInfo.ServicePack, OsInfo.Bits, OsInfo.VersionString));
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ // Get some important information for fixing GDI related Problems
+ environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount());
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount());
+ }
+ else
+ {
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform);
+ }
+ if (newline)
+ {
+ environment.AppendLine();
+ }
+ else
+ {
+ environment.Append(", ");
+ }
+ // TODO: Is this needed?
+ // environment.AppendFormat("Surface count: {0}", Surface.Count);
+
+ return environment.ToString();
+ }
+
+ public static string ExceptionToString(Exception ex)
+ {
+ if (ex == null)
+ return "null\r\n";
+
+ StringBuilder report = new StringBuilder();
+
+ report.AppendLine("Exception: " + ex.GetType());
+ report.AppendLine("Message: " + ex.Message);
+ if (ex.Data.Count > 0)
+ {
+ report.AppendLine();
+ report.AppendLine("Additional Information:");
+ foreach (object key in ex.Data.Keys)
+ {
+ object data = ex.Data[key];
+ if (data != null)
+ {
+ report.AppendLine(key + " : " + data);
+ }
+ }
+ }
+ if (ex is ExternalException)
+ {
+ // e.g. COMException
+ report.AppendLine().AppendLine("ErrorCode: 0x" + (ex as ExternalException).ErrorCode.ToString("X"));
+ }
+
+ report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace);
+
+ if (ex is ReflectionTypeLoadException)
+ {
+ report.AppendLine().AppendLine("LoaderExceptions: ");
+ foreach (Exception cbE in (ex as ReflectionTypeLoadException).LoaderExceptions)
+ {
+ report.AppendLine(cbE.Message);
+ }
+ }
+
+ if (ex.InnerException != null)
+ {
+ report.AppendLine("--- InnerException: ---");
+ report.AppendLine(ExceptionToString(ex.InnerException));
+ }
+ return report.ToString();
+ }
+
+ public static string BuildReport(Exception exception)
+ {
+ StringBuilder exceptionText = new StringBuilder();
+ exceptionText.AppendLine(EnvironmentToString(true));
+ exceptionText.AppendLine(ExceptionToString(exception));
+ exceptionText.AppendLine("Configuration dump:");
+
+ return exceptionText.ToString();
+ }
+ }
+
+ ///
+ /// Provides detailed information about the host operating system.
+ /// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
+ ///
+ public static class OsInfo
+ {
+ #region BITS
+ ///
+ /// Determines if the current application is 32 or 64-bit.
+ ///
+ public static int Bits
+ {
+ get
+ {
+ return IntPtr.Size * 8;
+ }
+ }
+ #endregion BITS
+
+ #region EDITION
+ private static string _sEdition;
+ ///
+ /// Gets the edition of the operating system running on this computer.
+ ///
+ public static string Edition
+ {
+ get
+ {
+ if (_sEdition != null)
+ {
+ return _sEdition; //***** RETURN *****//
+ }
+
+ string edition = string.Empty;
+
+ OperatingSystem osVersion = Environment.OSVersion;
+ OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX
+ {
+ dwOSVersionInfoSize = Marshal.SizeOf(typeof (OSVERSIONINFOEX))
+ };
+
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ int majorVersion = osVersion.Version.Major;
+ int minorVersion = osVersion.Version.Minor;
+ byte productType = osVersionInfo.wProductType;
+ short suiteMask = osVersionInfo.wSuiteMask;
+
+ #region VERSION 4
+ if (majorVersion == 4)
+ {
+ if (productType == VER_NT_WORKSTATION)
+ {
+ // Windows NT 4.0 Workstation
+ edition = "Workstation";
+ }
+ else if (productType == VER_NT_SERVER)
+ {
+ edition = (suiteMask & VER_SUITE_ENTERPRISE) != 0 ? "Enterprise Server" : "Standard Server";
+ }
+ }
+ #endregion VERSION 4
+
+ #region VERSION 5
+ else if (majorVersion == 5)
+ {
+ if (productType == VER_NT_WORKSTATION)
+ {
+ if ((suiteMask & VER_SUITE_PERSONAL) != 0)
+ {
+ // Windows XP Home Edition
+ edition = "Home";
+ }
+ else
+ {
+ // Windows XP / Windows 2000 Professional
+ edition = "Professional";
+ }
+ }
+ else if (productType == VER_NT_SERVER)
+ {
+ if (minorVersion == 0)
+ {
+ if ((suiteMask & VER_SUITE_DATACENTER) != 0)
+ {
+ // Windows 2000 Datacenter Server
+ edition = "Datacenter Server";
+ }
+ else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
+ {
+ // Windows 2000 Advanced Server
+ edition = "Advanced Server";
+ }
+ else
+ {
+ // Windows 2000 Server
+ edition = "Server";
+ }
+ }
+ else
+ {
+ if ((suiteMask & VER_SUITE_DATACENTER) != 0)
+ {
+ // Windows Server 2003 Datacenter Edition
+ edition = "Datacenter";
+ }
+ else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0)
+ {
+ // Windows Server 2003 Enterprise Edition
+ edition = "Enterprise";
+ }
+ else if ((suiteMask & VER_SUITE_BLADE) != 0)
+ {
+ // Windows Server 2003 Web Edition
+ edition = "Web Edition";
+ }
+ else
+ {
+ // Windows Server 2003 Standard Edition
+ edition = "Standard";
+ }
+ }
+ }
+ }
+ #endregion VERSION 5
+
+ #region VERSION 6
+ else if (majorVersion == 6)
+ {
+ int ed;
+ if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.wServicePackMajor, osVersionInfo.wServicePackMinor, out ed))
+ {
+ switch (ed)
+ {
+ case PRODUCT_BUSINESS:
+ edition = "Business";
+ break;
+ case PRODUCT_BUSINESS_N:
+ edition = "Business N";
+ break;
+ case PRODUCT_CLUSTER_SERVER:
+ edition = "HPC Edition";
+ break;
+ case PRODUCT_DATACENTER_SERVER:
+ edition = "Datacenter Server";
+ break;
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ edition = "Datacenter Server (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE:
+ edition = "Enterprise";
+ break;
+ case PRODUCT_ENTERPRISE_N:
+ edition = "Enterprise N";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER:
+ edition = "Enterprise Server";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ edition = "Enterprise Server (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE_V:
+ edition = "Enterprise Server without Hyper-V (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ edition = "Enterprise Server for Itanium-based Systems";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_V:
+ edition = "Enterprise Server without Hyper-V";
+ break;
+ case PRODUCT_HOME_BASIC:
+ edition = "Home Basic";
+ break;
+ case PRODUCT_HOME_BASIC_N:
+ edition = "Home Basic N";
+ break;
+ case PRODUCT_HOME_PREMIUM:
+ edition = "Home Premium";
+ break;
+ case PRODUCT_HOME_PREMIUM_N:
+ edition = "Home Premium N";
+ break;
+ case PRODUCT_HYPERV:
+ edition = "Microsoft Hyper-V Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
+ edition = "Windows Essential Business Management Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
+ edition = "Windows Essential Business Messaging Server";
+ break;
+ case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
+ edition = "Windows Essential Business Security Server";
+ break;
+ case PRODUCT_SERVER_FOR_SMALLBUSINESS:
+ edition = "Windows Essential Server Solutions";
+ break;
+ case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
+ edition = "Windows Essential Server Solutions without Hyper-V";
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ edition = "Windows Small Business Server";
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ edition = "Standard Server";
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE:
+ edition = "Standard Server (core installation)";
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE_V:
+ edition = "Standard Server without Hyper-V (core installation)";
+ break;
+ case PRODUCT_STANDARD_SERVER_V:
+ edition = "Standard Server without Hyper-V";
+ break;
+ case PRODUCT_STARTER:
+ edition = "Starter";
+ break;
+ case PRODUCT_STORAGE_ENTERPRISE_SERVER:
+ edition = "Enterprise Storage Server";
+ break;
+ case PRODUCT_STORAGE_EXPRESS_SERVER:
+ edition = "Express Storage Server";
+ break;
+ case PRODUCT_STORAGE_STANDARD_SERVER:
+ edition = "Standard Storage Server";
+ break;
+ case PRODUCT_STORAGE_WORKGROUP_SERVER:
+ edition = "Workgroup Storage Server";
+ break;
+ case PRODUCT_UNDEFINED:
+ edition = "Unknown product";
+ break;
+ case PRODUCT_ULTIMATE:
+ edition = "Ultimate";
+ break;
+ case PRODUCT_ULTIMATE_N:
+ edition = "Ultimate N";
+ break;
+ case PRODUCT_WEB_SERVER:
+ edition = "Web Server";
+ break;
+ case PRODUCT_WEB_SERVER_CORE:
+ edition = "Web Server (core installation)";
+ break;
+ }
+ }
+ }
+ #endregion VERSION 6
+ }
+
+ _sEdition = edition;
+ return edition;
+ }
+ }
+ #endregion EDITION
+
+ #region NAME
+ private static string _name;
+ ///
+ /// Gets the name of the operating system running on this computer.
+ ///
+ public static string Name
+ {
+ get
+ {
+ if (_name != null)
+ {
+ return _name; //***** RETURN *****//
+ }
+
+ string name = "unknown";
+
+ OperatingSystem osVersion = Environment.OSVersion;
+ OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX
+ {
+ dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
+ };
+
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ int majorVersion = osVersion.Version.Major;
+ int minorVersion = osVersion.Version.Minor;
+ byte productType = osVersionInfo.wProductType;
+ short suiteMask = osVersionInfo.wSuiteMask;
+ switch (osVersion.Platform)
+ {
+ case PlatformID.Win32Windows:
+ if (majorVersion == 4)
+ {
+ string csdVersion = osVersionInfo.szCSDVersion;
+ switch (minorVersion)
+ {
+ case 0:
+ if (csdVersion == "B" || csdVersion == "C")
+ {
+ name = "Windows 95 OSR2";
+ }
+ else
+ {
+ name = "Windows 95";
+ }
+ break;
+ case 10:
+ name = csdVersion == "A" ? "Windows 98 Second Edition" : "Windows 98";
+ break;
+ case 90:
+ name = "Windows Me";
+ break;
+ }
+ }
+ break;
+ case PlatformID.Win32NT:
+ switch (majorVersion)
+ {
+ case 3:
+ name = "Windows NT 3.51";
+ break;
+ case 4:
+ switch (productType)
+ {
+ case 1:
+ name = "Windows NT 4.0";
+ break;
+ case 3:
+ name = "Windows NT 4.0 Server";
+ break;
+ }
+ break;
+ case 5:
+ switch (minorVersion)
+ {
+ case 0:
+ name = "Windows 2000";
+ break;
+ case 1:
+ switch (suiteMask)
+ {
+ case 0x0200:
+ name = "Windows XP Professional";
+ break;
+ default:
+ name = "Windows XP";
+ break;
+ }
+ break;
+ case 2:
+ switch (suiteMask)
+ {
+ case 0x0200:
+ name = "Windows XP Professional x64";
+ break;
+ case 0x0002:
+ name = "Windows Server 2003 Enterprise";
+ break;
+ case 0x0080:
+ name = "Windows Server 2003 Data Center";
+ break;
+ case 0x0400:
+ name = "Windows Server 2003 Web Edition";
+ break;
+ case unchecked((short)0x8000):
+ name = "Windows Home Server";
+ break;
+ default:
+ name = "Windows Server 2003";
+ break;
+ }
+ break;
+ }
+ break;
+ case 6:
+ switch (minorVersion)
+ {
+ case 0:
+ switch (productType)
+ {
+ case 3:
+ name = "Windows Server 2008";
+ break;
+ default:
+ name = "Windows Vista";
+ break;
+ }
+ break;
+ case 1:
+ switch (productType)
+ {
+ case 3:
+ name = "Windows Server 2008 R2";
+ break;
+ default:
+ name = "Windows 7";
+ break;
+ }
+ break;
+ case 2:
+ name = "Windows 8";
+ break;
+ case 3:
+ name = "Windows 8.1";
+ break;
+ }
+ break;
+ case 10:
+ name = "Windows 10";
+ break;
+ }
+ break;
+ }
+ }
+
+ _name = name;
+ return name;
+ }
+ }
+ #endregion NAME
+
+ #region PINVOKE
+ #region GET
+ #region PRODUCT INFO
+ [DllImport("Kernel32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetProductInfo(
+ int osMajorVersion,
+ int osMinorVersion,
+ int spMajorVersion,
+ int spMinorVersion,
+ out int edition);
+ #endregion PRODUCT INFO
+
+ #region VERSION
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);
+ #endregion VERSION
+ #endregion GET
+
+ #region OSVERSIONINFOEX
+ [StructLayout(LayoutKind.Sequential)]
+ private struct OSVERSIONINFOEX
+ {
+ public int dwOSVersionInfoSize;
+ public readonly int dwMajorVersion;
+ public readonly int dwMinorVersion;
+ public readonly int dwBuildNumber;
+ public readonly int dwPlatformId;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public readonly string szCSDVersion;
+ public readonly short wServicePackMajor;
+ public readonly short wServicePackMinor;
+ public readonly short wSuiteMask;
+ public readonly byte wProductType;
+ public readonly byte wReserved;
+ }
+ #endregion OSVERSIONINFOEX
+
+ #region PRODUCT
+ private const int PRODUCT_UNDEFINED = 0x00000000;
+ private const int PRODUCT_ULTIMATE = 0x00000001;
+ private const int PRODUCT_HOME_BASIC = 0x00000002;
+ private const int PRODUCT_HOME_PREMIUM = 0x00000003;
+ private const int PRODUCT_ENTERPRISE = 0x00000004;
+ private const int PRODUCT_HOME_BASIC_N = 0x00000005;
+ private const int PRODUCT_BUSINESS = 0x00000006;
+ private const int PRODUCT_STANDARD_SERVER = 0x00000007;
+ private const int PRODUCT_DATACENTER_SERVER = 0x00000008;
+ private const int PRODUCT_SMALLBUSINESS_SERVER = 0x00000009;
+ private const int PRODUCT_ENTERPRISE_SERVER = 0x0000000A;
+ private const int PRODUCT_STARTER = 0x0000000B;
+ private const int PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C;
+ private const int PRODUCT_STANDARD_SERVER_CORE = 0x0000000D;
+ private const int PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E;
+ private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F;
+ private const int PRODUCT_BUSINESS_N = 0x00000010;
+ private const int PRODUCT_WEB_SERVER = 0x00000011;
+ private const int PRODUCT_CLUSTER_SERVER = 0x00000012;
+ private const int PRODUCT_HOME_SERVER = 0x00000013;
+ private const int PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014;
+ private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015;
+ private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016;
+ private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017;
+ private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018;
+ private const int PRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019;
+ private const int PRODUCT_HOME_PREMIUM_N = 0x0000001A;
+ private const int PRODUCT_ENTERPRISE_N = 0x0000001B;
+ private const int PRODUCT_ULTIMATE_N = 0x0000001C;
+ private const int PRODUCT_WEB_SERVER_CORE = 0x0000001D;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F;
+ private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020;
+ private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023;
+ private const int PRODUCT_STANDARD_SERVER_V = 0x00000024;
+ private const int PRODUCT_ENTERPRISE_SERVER_V = 0x00000026;
+ private const int PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028;
+ private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029;
+ private const int PRODUCT_HYPERV = 0x0000002A;
+ #endregion PRODUCT
+
+ #region VERSIONS
+ private const int VER_NT_WORKSTATION = 1;
+ private const int VER_NT_SERVER = 3;
+ private const int VER_SUITE_ENTERPRISE = 2;
+ private const int VER_SUITE_DATACENTER = 128;
+ private const int VER_SUITE_PERSONAL = 512;
+ private const int VER_SUITE_BLADE = 1024;
+ #endregion VERSIONS
+ #endregion PINVOKE
+
+ #region SERVICE PACK
+ ///
+ /// Gets the service pack information of the operating system running on this computer.
+ ///
+ public static string ServicePack
+ {
+ get
+ {
+ string servicePack = string.Empty;
+ OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX
+ {
+ dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX))
+ };
+
+
+ if (GetVersionEx(ref osVersionInfo))
+ {
+ servicePack = osVersionInfo.szCSDVersion;
+ }
+
+ return servicePack;
+ }
+ }
+ #endregion SERVICE PACK
+
+ #region VERSION
+ #region BUILD
+ ///
+ /// Gets the build version number of the operating system running on this computer.
+ ///
+ public static int BuildVersion => Environment.OSVersion.Version.Build;
+
+ #endregion BUILD
+
+ #region FULL
+ #region STRING
+ ///
+ /// Gets the full version string of the operating system running on this computer.
+ ///
+ public static string VersionString
+ {
+ get
+ {
+ return string.Format("{0}.{1} build {3} revision {2:X}", Environment.OSVersion.Version.Major, Environment.OSVersion.Version.Minor, Environment.OSVersion.Version.Revision, Environment.OSVersion.Version.Build);
+ }
+ }
+ #endregion STRING
+
+ #region VERSION
+ ///
+ /// Gets the full version of the operating system running on this computer.
+ ///
+ public static Version Version
+ {
+ get
+ {
+ return Environment.OSVersion.Version;
+ }
+ }
+ #endregion VERSION
+ #endregion FULL
+
+ #region MAJOR
+ ///
+ /// Gets the major version number of the operating system running on this computer.
+ ///
+ public static int MajorVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Major;
+ }
+ }
+ #endregion MAJOR
+
+ #region MINOR
+ ///
+ /// Gets the minor version number of the operating system running on this computer.
+ ///
+ public static int MinorVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Minor;
+ }
+ }
+ #endregion MINOR
+
+ #region REVISION
+ ///
+ /// Gets the revision version number of the operating system running on this computer.
+ ///
+ public static int RevisionVersion
+ {
+ get
+ {
+ return Environment.OSVersion.Version.Revision;
+ }
+ }
+ #endregion REVISION
+ #endregion VERSION
+ }
+}
\ No newline at end of file
diff --git a/Greenshot/Helpers/GeometryHelper.cs b/Greenshot/Helpers/GeometryHelper.cs
new file mode 100644
index 000000000..56b6a5381
--- /dev/null
+++ b/Greenshot/Helpers/GeometryHelper.cs
@@ -0,0 +1,59 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Description of GeometryHelper.
+ ///
+ public static class GeometryHelper {
+ ///
+ /// Finds the distance between two points on a 2D surface.
+ ///
+ /// The point on the x-axis of the first point
+ /// The point on the x-axis of the second point
+ /// The point on the y-axis of the first point
+ /// The point on the y-axis of the second point
+ ///
+ public static int Distance2D(int x1, int y1, int x2, int y2) {
+ //Take x2-x1, then square it
+ double part1 = Math.Pow(x2 - x1, 2);
+ //Take y2-y1, then square it
+ double part2 = Math.Pow(y2 - y1, 2);
+ //Add both of the parts together
+ double underRadical = part1 + part2;
+ //Get the square root of the parts
+ return (int)Math.Sqrt(underRadical);
+ }
+
+ ///
+ /// Calculates the angle of a line defined by two points on a 2D surface.
+ ///
+ /// The point on the x-axis of the first point
+ /// The point on the x-axis of the second point
+ /// The point on the y-axis of the first point
+ /// The point on the y-axis of the second point
+ ///
+ public static double Angle2D(int x1, int y1, int x2, int y2) {
+ return Math.Atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/GuiRectangle.cs b/Greenshot/Helpers/GuiRectangle.cs
new file mode 100644
index 000000000..b7af60ec0
--- /dev/null
+++ b/Greenshot/Helpers/GuiRectangle.cs
@@ -0,0 +1,64 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Helper class for creating rectangles with positive dimensions, regardless of input coordinates
+ ///
+ public static class GuiRectangle {
+
+ public static Rectangle GetGuiRectangle(int x, int y, int w, int h) {
+ Rectangle rect = new Rectangle(x, y, w, h);
+ MakeGuiRectangle(ref rect);
+ return rect;
+ }
+
+ public static void MakeGuiRectangle(ref Rectangle rect) {
+ if (rect.Width < 0) {
+ rect.X += rect.Width;
+ rect.Width = -rect.Width;
+ }
+ if (rect.Height < 0) {
+ rect.Y += rect.Height;
+ rect.Height = -rect.Height;
+ }
+ }
+
+ public static RectangleF GetGuiRectangleF(float x, float y, float w, float h) {
+ RectangleF rect = new RectangleF(x, y, w, h);
+ MakeGuiRectangleF(ref rect);
+ return rect;
+ }
+
+ public static void MakeGuiRectangleF(ref RectangleF rect) {
+ if (rect.Width < 0) {
+ rect.X += rect.Width;
+ rect.Width = -rect.Width;
+ }
+ if (rect.Height < 0) {
+ rect.Y += rect.Height;
+ rect.Height = -rect.Height;
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/IECaptureHelper.cs b/Greenshot/Helpers/IECaptureHelper.cs
new file mode 100644
index 000000000..b7440825b
--- /dev/null
+++ b/Greenshot/Helpers/IECaptureHelper.cs
@@ -0,0 +1,671 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Greenshot.Configuration;
+using Greenshot.Helpers.IEInterop;
+using Greenshot.Interop;
+using Greenshot.Interop.IE;
+using Greenshot.Plugin;
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// The code for this helper comes from: http://www.codeproject.com/KB/graphics/IECapture.aspx
+ /// The code is modified with some of the suggestions in different comments and there still were leaks which I fixed.
+ /// On top I modified it to use the already available code in Greenshot.
+ /// Many thanks to all the people who contributed here!
+ ///
+ public static class IeCaptureHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(IeCaptureHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ // Helper method to activate a certain IE Tab
+ public static void ActivateIeTab(WindowDetails ieWindowDetails, int tabIndex) {
+ WindowDetails directUiWindowDetails = IEHelper.GetDirectUI(ieWindowDetails);
+ if(directUiWindowDetails != null) {
+ // Bring window to the front
+ ieWindowDetails.Restore();
+ // Get accessible
+ Accessible ieAccessible = new Accessible(directUiWindowDetails.Handle);
+ // Activate Tab
+ ieAccessible.ActivateIETab(tabIndex);
+ }
+ }
+
+ ///
+ /// Return true if the supplied window has a sub-window which covers more than the supplied percentage
+ ///
+ /// WindowDetails to check
+ /// min percentage
+ ///
+ public static bool IsMostlyIeWindow(WindowDetails someWindow, int minimumPercentage) {
+ WindowDetails ieWindow = someWindow.GetChild("Internet Explorer_Server");
+ if (ieWindow != null) {
+ Rectangle wholeClient = someWindow.ClientRectangle;
+ Rectangle partClient = ieWindow.ClientRectangle;
+ int percentage = (int)(100*(float)(partClient.Width * partClient.Height) / (wholeClient.Width * wholeClient.Height));
+ Log.InfoFormat("Window {0}, ie part {1}, percentage {2}", wholeClient, partClient, percentage);
+ if (percentage > minimumPercentage) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Does the supplied window have a IE part?
+ ///
+ ///
+ ///
+ public static bool IsIeWindow(WindowDetails someWindow) {
+ if ("IEFrame".Equals(someWindow.ClassName)) {
+ return true;
+ }
+ if (CoreConfig.WindowClassesToCheckForIE != null && CoreConfig.WindowClassesToCheckForIE.Contains(someWindow.ClassName)) {
+ return someWindow.GetChild("Internet Explorer_Server") != null;
+ }
+ return false;
+ }
+
+ ///
+ /// Get Windows displaying an IE
+ ///
+ /// IEnumerable WindowDetails
+ public static IEnumerable GetIeWindows() {
+ foreach (var possibleIeWindow in WindowDetails.GetAllWindows()) {
+ if (possibleIeWindow.Text.Length == 0) {
+ continue;
+ }
+ if (possibleIeWindow.ClientRectangle.IsEmpty) {
+ continue;
+ }
+ if (IsIeWindow(possibleIeWindow)) {
+ yield return possibleIeWindow;
+ }
+ }
+ }
+
+ ///
+ /// Simple check if IE is running
+ ///
+ /// bool
+ public static bool IsIeRunning()
+ {
+ return GetIeWindows().Any();
+ }
+
+ ///
+ /// Gets a list of all IE Windows & tabs with the captions of the instances
+ ///
+ /// List with KeyValuePair of WindowDetails and string
+ public static List> GetBrowserTabs() {
+ var ieHandleList = new List();
+ var browserWindows = new Dictionary>();
+
+ // Find the IE windows
+ foreach (var ieWindow in GetIeWindows()) {
+ try {
+ if (ieHandleList.Contains(ieWindow.Handle))
+ {
+ continue;
+ }
+ if ("IEFrame".Equals(ieWindow.ClassName)) {
+ var directUiwd = IEHelper.GetDirectUI(ieWindow);
+ if (directUiwd != null) {
+ var accessible = new Accessible(directUiwd.Handle);
+ browserWindows.Add(ieWindow, accessible.IETabCaptions);
+ }
+ } else if (CoreConfig.WindowClassesToCheckForIE != null && CoreConfig.WindowClassesToCheckForIE.Contains(ieWindow.ClassName)) {
+ var singleWindowText = new List();
+ try {
+ var document2 = GetHtmlDocument(ieWindow);
+ string title = document2.title;
+ Marshal.ReleaseComObject(document2);
+ if (string.IsNullOrEmpty(title)) {
+ singleWindowText.Add(ieWindow.Text);
+ } else {
+ singleWindowText.Add(ieWindow.Text + " - " + title);
+ }
+ } catch {
+ singleWindowText.Add(ieWindow.Text);
+ }
+ browserWindows.Add(ieWindow, singleWindowText);
+ }
+ ieHandleList.Add(ieWindow.Handle);
+ } catch (Exception) {
+ Log.Warn("Can't get Info from " + ieWindow.ClassName);
+ }
+ }
+
+ var returnList = new List>();
+ foreach(var windowDetails in browserWindows.Keys) {
+ foreach(string tab in browserWindows[windowDetails]) {
+ returnList.Add(new KeyValuePair(windowDetails, tab));
+ }
+ }
+ return returnList;
+ }
+
+ ///
+ /// Helper Method to get the IHTMLDocument2
+ ///
+ ///
+ ///
+ private static IHTMLDocument2 GetHtmlDocument(WindowDetails mainWindow) {
+ var ieServer = "Internet Explorer_Server".Equals(mainWindow.ClassName) ? mainWindow : mainWindow.GetChild("Internet Explorer_Server");
+ if (ieServer == null) {
+ Log.WarnFormat("No Internet Explorer_Server for {0}", mainWindow.Text);
+ return null;
+ }
+
+ uint windowMessage = User32.RegisterWindowMessage("WM_HTML_GETOBJECT");
+ if (windowMessage == 0) {
+ Log.WarnFormat("Couldn't register WM_HTML_GETOBJECT");
+ return null;
+ }
+
+ Log.DebugFormat("Trying WM_HTML_GETOBJECT on {0}", ieServer.ClassName);
+ UIntPtr response;
+ User32.SendMessageTimeout(ieServer.Handle, windowMessage, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_NORMAL, 5000, out response);
+ IHTMLDocument2 document2;
+ if (response != UIntPtr.Zero) {
+ document2 = (IHTMLDocument2)Accessible.ObjectFromLresult(response, typeof(IHTMLDocument).GUID, IntPtr.Zero);
+ if (document2 == null) {
+ Log.Error("No IHTMLDocument2 found");
+ return null;
+ }
+ } else {
+ Log.Error("No answer on WM_HTML_GETOBJECT.");
+ return null;
+ }
+ return document2;
+ }
+
+ ///
+ /// Helper method which will retrieve the IHTMLDocument2 for the supplied window,
+ /// or return the first if none is supplied.
+ ///
+ /// The WindowDetails to get the IHTMLDocument2 for
+ /// The WindowDetails to which the IHTMLDocument2 belongs
+ private static DocumentContainer CreateDocumentContainer(WindowDetails browserWindow) {
+ DocumentContainer returnDocumentContainer = null;
+ WindowDetails returnWindow = null;
+ IHTMLDocument2 returnDocument2 = null;
+ // alternative if no match
+ WindowDetails alternativeReturnWindow = null;
+ IHTMLDocument2 alternativeReturnDocument2 = null;
+
+ // Find the IE windows
+ foreach (WindowDetails ieWindow in GetIeWindows()) {
+ Log.DebugFormat("Processing {0} - {1}", ieWindow.ClassName, ieWindow.Text);
+
+ Accessible ieAccessible = null;
+ WindowDetails directUiwd = IEHelper.GetDirectUI(ieWindow);
+ if (directUiwd != null) {
+ ieAccessible = new Accessible(directUiwd.Handle);
+ }
+ if (ieAccessible == null) {
+ if (browserWindow != null) {
+ Log.InfoFormat("Active Window is {0}", browserWindow.Text);
+ }
+ if (!ieWindow.Equals(browserWindow)) {
+ Log.WarnFormat("No ieAccessible for {0}", ieWindow.Text);
+ continue;
+ }
+ Log.DebugFormat("No ieAccessible, but the active window is an IE window: {0}, ", ieWindow.Text);
+ }
+
+ try {
+ // Get the Document
+ IHTMLDocument2 document2 = GetHtmlDocument(ieWindow);
+ if (document2 == null) {
+ continue;
+ }
+
+ // Get the content window handle for the shellWindow.Document
+ IOleWindow oleWindow = (IOleWindow)document2;
+ IntPtr contentWindowHandle = IntPtr.Zero;
+ oleWindow?.GetWindow(out contentWindowHandle);
+
+ if (contentWindowHandle != IntPtr.Zero) {
+ // Get the HTMLDocument to check the hasFocus
+ // See: http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/60c6c95d-377c-4bf4-860d-390840fce31c/
+ IHTMLDocument4 document4 = (IHTMLDocument4)document2;
+
+ if (document4.hasFocus()) {
+ Log.DebugFormat("Matched focused document: {0}", document2.title);
+ // Look no further, we got what we wanted!
+ returnDocument2 = document2;
+ returnWindow = new WindowDetails(contentWindowHandle);
+ break;
+ }
+ try {
+ if (ieWindow.Equals(browserWindow)) {
+ returnDocument2 = document2;
+ returnWindow = new WindowDetails(contentWindowHandle);
+ break;
+ }
+ if (ieAccessible != null && returnWindow == null && document2.title.Equals(ieAccessible.IEActiveTabCaption) ) {
+ Log.DebugFormat("Title: {0}", document2.title);
+ returnDocument2 = document2;
+ returnWindow = new WindowDetails(contentWindowHandle);
+ } else {
+ alternativeReturnDocument2 = document2;
+ alternativeReturnWindow = new WindowDetails(contentWindowHandle);
+ }
+ } catch (Exception) {
+ alternativeReturnDocument2 = document2;
+ alternativeReturnWindow = new WindowDetails(contentWindowHandle);
+ }
+ }
+ } catch (Exception e) {
+ Log.ErrorFormat("Major problem: Problem retrieving Document from {0}", ieWindow.Text);
+ Log.Error(e);
+ }
+ }
+
+ // check if we have something to return
+ if (returnWindow != null) {
+ // As it doesn't have focus, make sure it's active
+ returnWindow.Restore();
+ returnWindow.GetParent();
+
+ // Create the container
+ try {
+ returnDocumentContainer = new DocumentContainer(returnDocument2, returnWindow);
+ } catch (Exception e) {
+ Log.Error("Major problem: Problem retrieving Document.");
+ Log.Error(e);
+ }
+ }
+
+ if (returnDocumentContainer == null && alternativeReturnDocument2 != null) {
+ // As it doesn't have focus, make sure it's active
+ alternativeReturnWindow.Restore();
+ alternativeReturnWindow.GetParent();
+ // Create the container
+ try {
+ returnDocumentContainer = new DocumentContainer(alternativeReturnDocument2, alternativeReturnWindow);
+ } catch (Exception e) {
+ Log.Error("Major problem: Problem retrieving Document.");
+ Log.Error(e);
+ }
+ }
+ return returnDocumentContainer;
+ }
+
+ ///
+ /// Here the logic for capturing the IE Content is located
+ ///
+ /// ICapture where the capture needs to be stored
+ /// ICapture with the content (if any)
+ public static ICapture CaptureIe(ICapture capture) {
+ return CaptureIe(capture, WindowDetails.GetActiveWindow());
+ }
+ ///
+ /// Here the logic for capturing the IE Content is located
+ ///
+ /// ICapture where the capture needs to be stored
+ /// window to use
+ /// ICapture with the content (if any)
+ public static ICapture CaptureIe(ICapture capture, WindowDetails windowToCapture) {
+ if (windowToCapture == null) {
+ windowToCapture = WindowDetails.GetActiveWindow();
+ }
+ // Show backgroundform after retrieving the active window..
+ BackgroundForm backgroundForm = new BackgroundForm(Language.GetString(LangKey.contextmenu_captureie), Language.GetString(LangKey.wait_ie_capture));
+ backgroundForm.Show();
+ //BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture));
+ try {
+ //Get IHTMLDocument2 for the current active window
+ DocumentContainer documentContainer = CreateDocumentContainer(windowToCapture);
+
+ // Nothing found
+ if (documentContainer == null) {
+ Log.Debug("Nothing to capture found");
+ return null;
+ }
+
+ try {
+ Log.DebugFormat("Window class {0}", documentContainer.ContentWindow.ClassName);
+ Log.DebugFormat("Window location {0}", documentContainer.ContentWindow.Location);
+ } catch (Exception ex) {
+ Log.Warn("Error while logging information.", ex);
+ }
+
+ // bitmap to return
+ Bitmap returnBitmap = null;
+ try {
+ Size pageSize = PrepareCapture(documentContainer, capture);
+ returnBitmap = CapturePage(documentContainer, pageSize);
+ } catch (Exception captureException) {
+ Log.Error("Exception found, ignoring and returning nothing! Error was: ", captureException);
+ }
+ // TODO: Enable when the elements are usable again.
+ // Capture the element on the page
+ //try {
+ // if (CoreConfig.IEFieldCapture && capture.CaptureDetails.HasDestination("Editor")) {
+ // // clear the current elements, as they are for the window itself
+ // capture.Elements.Clear();
+ // CaptureElement documentCaptureElement = documentContainer.CreateCaptureElements(pageSize);
+ // foreach(DocumentContainer frameDocument in documentContainer.Frames) {
+ // try {
+ // CaptureElement frameCaptureElement = frameDocument.CreateCaptureElements(Size.Empty);
+ // if (frameCaptureElement != null) {
+ // documentCaptureElement.Children.Add(frameCaptureElement);
+ // }
+ // } catch (Exception ex) {
+ // LOG.Warn("An error occurred while creating the capture elements: ", ex);
+ // }
+ // }
+ // capture.AddElement(documentCaptureElement);
+ // // Offset the elements, as they are "back offseted" later...
+ // Point windowLocation = documentContainer.ContentWindow.WindowRectangle.Location;
+ // capture.MoveElements(-(capture.ScreenBounds.Location.X-windowLocation.X), -(capture.ScreenBounds.Location.Y-windowLocation.Y));
+ // }
+ //} catch (Exception elementsException) {
+ // LOG.Warn("An error occurred while creating the capture elements: ", elementsException);
+ //}
+
+
+ if (returnBitmap == null) {
+ return null;
+ }
+
+ // Store the bitmap for further processing
+ capture.Image = returnBitmap;
+ try {
+ // Store the location of the window
+ capture.Location = documentContainer.ContentWindow.Location;
+
+ // The URL is available unter "document2.url" and can be used to enhance the meta-data etc.
+ capture.CaptureDetails.AddMetaData("url", documentContainer.Url);
+ // Store the title of the page
+ capture.CaptureDetails.Title = documentContainer.Name ?? windowToCapture.Text;
+ } catch (Exception ex) {
+ Log.Warn("Problems getting some attributes...", ex);
+ }
+
+ // Store the URL of the page
+ if (documentContainer.Url != null) {
+ try {
+ Uri uri = new Uri(documentContainer.Url);
+ capture.CaptureDetails.AddMetaData("URL", uri.OriginalString);
+ // As the URL can hardly be used in a filename, the following can be used
+ if (!string.IsNullOrEmpty(uri.Scheme)) {
+ capture.CaptureDetails.AddMetaData("URL_SCHEME", uri.Scheme);
+ }
+ if (!string.IsNullOrEmpty(uri.DnsSafeHost)) {
+ capture.CaptureDetails.AddMetaData("URL_HOSTNAME", uri.DnsSafeHost);
+ }
+ if (!string.IsNullOrEmpty(uri.AbsolutePath)) {
+ capture.CaptureDetails.AddMetaData("URL_PATH", uri.AbsolutePath);
+ }
+ if (!string.IsNullOrEmpty(uri.Query)) {
+ capture.CaptureDetails.AddMetaData("URL_QUERY", uri.Query);
+ }
+ if (!string.IsNullOrEmpty(uri.UserInfo)) {
+ capture.CaptureDetails.AddMetaData("URL_USER", uri.UserInfo);
+ }
+ capture.CaptureDetails.AddMetaData("URL_PORT", uri.Port.ToString());
+ } catch(Exception e) {
+ Log.Warn("Exception when trying to use url in metadata "+documentContainer.Url,e);
+ }
+ }
+ try {
+ // Only move the mouse to correct for the capture offset
+ capture.MoveMouseLocation(-documentContainer.ViewportRectangle.X, -documentContainer.ViewportRectangle.Y);
+ // Used to be: capture.MoveMouseLocation(-(capture.Location.X + documentContainer.CaptureOffset.X), -(capture.Location.Y + documentContainer.CaptureOffset.Y));
+ } catch (Exception ex) {
+ Log.Warn("Error while correcting the mouse offset.", ex);
+ }
+ } finally {
+ // Always close the background form
+ backgroundForm.CloseDialog();
+ }
+ return capture;
+ }
+
+ ///
+ /// Prepare the calculates for all the frames, move and fit...
+ ///
+ ///
+ ///
+ /// Size of the complete page
+ private static Size PrepareCapture(DocumentContainer documentContainer, ICapture capture) {
+ // Calculate the page size
+ int pageWidth = documentContainer.ScrollWidth;
+ int pageHeight = documentContainer.ScrollHeight;
+
+ // Here we loop over all the frames and try to make sure they don't overlap
+ bool movedFrame;
+ do {
+ movedFrame = false;
+ foreach(DocumentContainer currentFrame in documentContainer.Frames) {
+ foreach(DocumentContainer otherFrame in documentContainer.Frames) {
+ if (otherFrame.Id == currentFrame.Id) {
+ continue;
+ }
+ // check if we need to move
+ if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) {
+ bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
+ bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
+ bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft;
+ bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop;
+ bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft;
+ bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop;
+
+ if ((horizalResize || horizalMove) && leftOf) {
+ // Current frame resized horizontally, so move other horizontally
+ Log.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name);
+ otherFrame.DestinationLeft = currentFrame.DestinationRight;
+ movedFrame = true;
+ } else if ((verticalResize || verticalMove) && belowOf){
+ // Current frame resized vertically, so move other vertically
+ Log.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name);
+ otherFrame.DestinationTop = currentFrame.DestinationBottom;
+ movedFrame = true;
+ } else {
+ Log.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name);
+ }
+ }
+ }
+ }
+ } while(movedFrame);
+
+ bool movedMouse = false;
+ // Correct cursor location to be inside the window
+ capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y);
+ // See if the page has the correct size, as we capture the full frame content AND might have moved them
+ // the normal pagesize will no longer be enough
+ foreach(DocumentContainer frameData in documentContainer.Frames) {
+ if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) {
+ // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was)
+ capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop);
+ movedMouse = true;
+ // Apply any other offset changes
+ int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X;
+ int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y;
+ capture.MoveMouseLocation(offsetX, offsetY);
+ }
+
+ //Get Frame Width & Height
+ pageWidth = Math.Max(pageWidth, frameData.DestinationRight);
+ pageHeight = Math.Max(pageHeight, frameData.DestinationBottom);
+ }
+
+ // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document
+ if (!movedMouse) {
+ // Correct mouse cursor location
+ capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop);
+ }
+
+ // Limit the size as the editor currently can't work with sizes > short.MaxValue
+ if (pageWidth > short.MaxValue) {
+ Log.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue);
+ pageWidth = Math.Min(pageWidth, short.MaxValue);
+ }
+ if (pageHeight > short.MaxValue) {
+ Log.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue);
+ pageHeight = Math.Min(pageHeight, short.MaxValue);
+ }
+ return new Size(pageWidth, pageHeight);
+ }
+
+ ///
+ /// Capture the actual page (document)
+ ///
+ /// The document wrapped in a container
+ ///
+ /// Bitmap with the page content as an image
+ private static Bitmap CapturePage(DocumentContainer documentContainer, Size pageSize) {
+ WindowDetails contentWindowDetails = documentContainer.ContentWindow;
+
+ //Create a target bitmap to draw into with the calculated page size
+ Bitmap returnBitmap = new Bitmap(pageSize.Width, pageSize.Height, PixelFormat.Format24bppRgb);
+ using (Graphics graphicsTarget = Graphics.FromImage(returnBitmap)) {
+ // Clear the target with the backgroundcolor
+ Color clearColor = documentContainer.BackgroundColor;
+ Log.DebugFormat("Clear color: {0}", clearColor);
+ graphicsTarget.Clear(clearColor);
+
+ // Get the base document & draw it
+ DrawDocument(documentContainer, contentWindowDetails, graphicsTarget);
+
+ // Loop over the frames and clear their source area so we don't see any artefacts
+ foreach(DocumentContainer frameDocument in documentContainer.Frames) {
+ using(Brush brush = new SolidBrush(clearColor)) {
+ graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle);
+ }
+ }
+ // Loop over the frames and capture their content
+ foreach(DocumentContainer frameDocument in documentContainer.Frames) {
+ DrawDocument(frameDocument, contentWindowDetails, graphicsTarget);
+ }
+ }
+ return returnBitmap;
+ }
+
+ ///
+ /// This method takes the actual capture of the document (frame)
+ ///
+ /// DocumentContainer
+ /// Needed for referencing the location of the frame
+ /// Graphics
+ /// Bitmap with the capture
+ private static void DrawDocument(DocumentContainer documentContainer, WindowDetails contentWindowDetails, Graphics graphicsTarget) {
+ documentContainer.SetAttribute("scroll", 1);
+
+ //Get Browser Window Width & Height
+ int pageWidth = documentContainer.ScrollWidth;
+ int pageHeight = documentContainer.ScrollHeight;
+ if (pageWidth * pageHeight == 0) {
+ Log.WarnFormat("Empty page for DocumentContainer {0}: {1}", documentContainer.Name, documentContainer.Url);
+ return;
+ }
+
+ //Get Screen Width & Height (this is better as the WindowDetails.ClientRectangle as the real visible parts are there!
+ int viewportWidth = documentContainer.ClientWidth;
+ int viewportHeight = documentContainer.ClientHeight;
+ if (viewportWidth * viewportHeight == 0) {
+ Log.WarnFormat("Empty viewport for DocumentContainer {0}: {1}", documentContainer.Name, documentContainer.Url);
+ return;
+ }
+
+ // Store the current location so we can set the browser back and use it for the mouse cursor
+ int startLeft = documentContainer.ScrollLeft;
+ int startTop = documentContainer.ScrollTop;
+
+ Log.DebugFormat("Capturing {4} with total size {0},{1} displayed with size {2},{3}", pageWidth, pageHeight, viewportWidth, viewportHeight, documentContainer.Name);
+
+ // Variable used for looping horizontally
+ int horizontalPage = 0;
+
+ // The location of the browser, used as the destination into the bitmap target
+ Point targetOffset = new Point();
+
+ // Loop of the pages and make a copy of the visible viewport
+ while (horizontalPage * viewportWidth < pageWidth) {
+ // Scroll to location
+ documentContainer.ScrollLeft = viewportWidth * horizontalPage;
+ targetOffset.X = documentContainer.ScrollLeft;
+
+ // Variable used for looping vertically
+ int verticalPage = 0;
+ while (verticalPage * viewportHeight < pageHeight) {
+ // Scroll to location
+ documentContainer.ScrollTop = viewportHeight * verticalPage;
+ //Shoot visible window
+ targetOffset.Y = documentContainer.ScrollTop;
+
+ // Draw the captured fragment to the target, but "crop" the scrollbars etc while capturing
+ Size viewPortSize = new Size(viewportWidth, viewportHeight);
+ Rectangle clientRectangle = new Rectangle(documentContainer.SourceLocation, viewPortSize);
+ Image fragment = contentWindowDetails.PrintWindow();
+ if (fragment != null) {
+ Log.DebugFormat("Captured fragment size: {0}x{1}", fragment.Width, fragment.Height);
+ try {
+ // cut all junk, due to IE "border" we need to remove some parts
+ Rectangle viewportRect = documentContainer.ViewportRectangle;
+ if (!viewportRect.IsEmpty) {
+ Log.DebugFormat("Cropping to viewport: {0}", viewportRect);
+ ImageHelper.Crop(ref fragment, ref viewportRect);
+ }
+ Log.DebugFormat("Cropping to clientRectangle: {0}", clientRectangle);
+ // Crop to clientRectangle
+ if (ImageHelper.Crop(ref fragment, ref clientRectangle)) {
+ Point targetLocation = new Point(documentContainer.DestinationLocation.X, documentContainer.DestinationLocation.Y);
+ Log.DebugFormat("Fragment targetLocation is {0}", targetLocation);
+ targetLocation.Offset(targetOffset);
+ Log.DebugFormat("After offsetting the fragment targetLocation is {0}", targetLocation);
+ Log.DebugFormat("Drawing fragment of size {0} to {1}", fragment.Size, targetLocation);
+ graphicsTarget.DrawImage(fragment, targetLocation);
+ graphicsTarget.Flush();
+ } else {
+ // somehow we are capturing nothing!?
+ Log.WarnFormat("Crop of {0} failed?", documentContainer.Name);
+ break;
+ }
+ } finally {
+ fragment.Dispose();
+ }
+ } else {
+ Log.WarnFormat("Capture of {0} failed!", documentContainer.Name);
+ }
+ verticalPage++;
+ }
+ horizontalPage++;
+ }
+ // Return to where we were
+ documentContainer.ScrollLeft = startLeft;
+ documentContainer.ScrollTop = startTop;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/IEInterop/IEContainer.cs b/Greenshot/Helpers/IEInterop/IEContainer.cs
new file mode 100644
index 000000000..f0c3de49f
--- /dev/null
+++ b/Greenshot/Helpers/IEInterop/IEContainer.cs
@@ -0,0 +1,503 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+using GreenshotPlugin.Core;
+using Greenshot.Interop.IE;
+using log4net;
+using IServiceProvider = Greenshot.Interop.IServiceProvider;
+
+namespace Greenshot.Helpers.IEInterop {
+ public class DocumentContainer {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(DocumentContainer));
+ private const int E_ACCESSDENIED = unchecked((int)0x80070005L);
+ private static readonly Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
+ private static readonly Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");
+ private static int _counter;
+ private IHTMLDocument2 _document2;
+ private IHTMLDocument3 _document3;
+ private Point _sourceLocation;
+ private Point _destinationLocation;
+ private Point _startLocation = Point.Empty;
+ private Rectangle _viewportRectangle = Rectangle.Empty;
+ private bool _isDtd;
+ private DocumentContainer _parent;
+ private WindowDetails _contentWindow;
+ private double _zoomLevelX = 1;
+ private double _zoomLevelY = 1;
+ private readonly IList _frames = new List();
+
+ private DocumentContainer(IHTMLWindow2 frameWindow, WindowDetails contentWindow, DocumentContainer parent) {
+ //IWebBrowser2 webBrowser2 = frame as IWebBrowser2;
+ //IHTMLDocument2 document2 = webBrowser2.Document as IHTMLDocument2;
+ IHTMLDocument2 document2 = GetDocumentFromWindow(frameWindow);
+ try {
+ LOG.DebugFormat("frameWindow.name {0}", frameWindow.name);
+ Name = frameWindow.name;
+ } catch {
+ // Ignore
+ }
+ try {
+ LOG.DebugFormat("document2.url {0}",document2.url);
+ } catch {
+ // Ignore
+ }
+ try {
+ LOG.DebugFormat("document2.title {0}", document2.title);
+ } catch {
+ // Ignore
+ }
+
+ _parent = parent;
+ // Calculate startLocation for the frames
+ IHTMLWindow2 window2 = document2.parentWindow;
+ IHTMLWindow3 window3 = (IHTMLWindow3)window2;
+ Point contentWindowLocation = contentWindow.WindowRectangle.Location;
+ int x = window3.screenLeft - contentWindowLocation.X;
+ int y = window3.screenTop - contentWindowLocation.Y;
+
+ // Release IHTMLWindow 2+3 com objects
+ releaseCom(window2);
+ releaseCom(window3);
+
+ _startLocation = new Point(x, y);
+ Init(document2, contentWindow);
+ }
+
+ public DocumentContainer(IHTMLDocument2 document2, WindowDetails contentWindow) {
+ Init(document2, contentWindow);
+ LOG.DebugFormat("Creating DocumentContainer for Document {0} found in window with rectangle {1}", Name, SourceRectangle);
+ }
+
+ ///
+ /// Helper method to release com objects
+ ///
+ ///
+ private void releaseCom(object comObject) {
+ if (comObject != null) {
+ Marshal.ReleaseComObject(comObject);
+ }
+ }
+
+ ///
+ /// Private helper method for the constructors
+ ///
+ /// IHTMLDocument2
+ /// WindowDetails
+ private void Init(IHTMLDocument2 document2, WindowDetails contentWindow) {
+ _document2 = document2;
+ _contentWindow = contentWindow;
+ _document3 = document2 as IHTMLDocument3;
+ // Check what access method is needed for the document
+ IHTMLDocument5 document5 = (IHTMLDocument5)document2;
+
+ //compatibility mode affects how height is computed
+ _isDtd = false;
+ try {
+ if (_document3?.documentElement != null && !document5.compatMode.Equals("BackCompat")) {
+ _isDtd = true;
+ }
+ } catch (Exception ex) {
+ LOG.Error("Error checking the compatibility mode:");
+ LOG.Error(ex);
+ }
+ // Do not release IHTMLDocument5 com object, as this also gives problems with the document2!
+ //Marshal.ReleaseComObject(document5);
+
+ Rectangle clientRectangle = contentWindow.WindowRectangle;
+ try {
+ IHTMLWindow2 window2 = document2.parentWindow;
+ //IHTMLWindow3 window3 = (IHTMLWindow3)document2.parentWindow;
+ IHTMLScreen screen = window2.screen;
+ IHTMLScreen2 screen2 = (IHTMLScreen2)screen;
+ if (_parent != null) {
+ // Copy parent values
+ _zoomLevelX = _parent._zoomLevelX;
+ _zoomLevelY = _parent._zoomLevelY;
+ _viewportRectangle = _parent._viewportRectangle;
+ } else {
+ //DisableScrollbars(document2);
+
+ // Calculate zoom level
+ _zoomLevelX = screen2.deviceXDPI/(double)screen2.logicalXDPI;
+ _zoomLevelY = screen2.deviceYDPI/(double)screen2.logicalYDPI;
+
+
+ // Calculate the viewport rectangle, needed if there is a frame around the html window
+ LOG.DebugFormat("Screen {0}x{1}", ScaleX(screen.width), ScaleY(screen.height));
+ //LOG.DebugFormat("Screen location {0},{1}", window3.screenLeft, window3.screenTop);
+ LOG.DebugFormat("Window rectangle {0}", clientRectangle);
+ LOG.DebugFormat("Client size {0}x{1}", ClientWidth, ClientHeight);
+ int diffX = clientRectangle.Width - ClientWidth;
+ int diffY = clientRectangle.Height - ClientHeight;
+ // If there is a border around the inner window, the diff == 4
+ // If there is a border AND a scrollbar the diff == 20
+ if ((diffX == 4 || diffX >= 20) && (diffY == 4 || diffY >= 20)) {
+ Point viewportOffset = new Point(2, 2);
+ Size viewportSize = new Size(ClientWidth, ClientHeight);
+ _viewportRectangle = new Rectangle(viewportOffset, viewportSize);
+ LOG.DebugFormat("viewportRect {0}", _viewportRectangle);
+ }
+ }
+ LOG.DebugFormat("Zoomlevel {0}, {1}", _zoomLevelX, _zoomLevelY);
+ // Release com objects
+ releaseCom(window2);
+ releaseCom(screen);
+ releaseCom(screen2);
+ } catch (Exception e) {
+ LOG.Warn("Can't get certain properties for documents, using default. Due to: ", e);
+ }
+
+
+ try {
+ LOG.DebugFormat("Calculated location {0} for {1}", _startLocation, document2.title);
+ if (Name == null) {
+ Name = document2.title;
+ }
+ } catch (Exception e) {
+ LOG.Warn("Problem while trying to get document title!", e);
+ }
+
+ try {
+ Url = document2.url;
+ } catch (Exception e) {
+ LOG.Warn("Problem while trying to get document url!", e);
+ }
+ _sourceLocation = new Point(ScaleX(_startLocation.X), ScaleY(_startLocation.Y));
+ _destinationLocation = new Point(ScaleX(_startLocation.X), ScaleY(_startLocation.Y));
+
+ if (_parent != null) {
+ return;
+ }
+ try {
+ IHTMLFramesCollection2 frameCollection = (IHTMLFramesCollection2)document2.frames;
+ for (int frame = 0; frame < frameCollection.length; frame++) {
+ try {
+ IHTMLWindow2 frameWindow = frameCollection.item(frame);
+ DocumentContainer frameData = new DocumentContainer(frameWindow, contentWindow, this);
+ // check if frame is hidden
+ if (!frameData.IsHidden) {
+ LOG.DebugFormat("Creating DocumentContainer for Frame {0} found in window with rectangle {1}", frameData.Name, frameData.SourceRectangle);
+ _frames.Add(frameData);
+ } else {
+ LOG.DebugFormat("Skipping frame {0}", frameData.Name);
+ }
+ // Clean up frameWindow
+ releaseCom(frameWindow);
+ } catch (Exception e) {
+ LOG.Warn("Problem while trying to get information from a frame, skipping the frame!", e);
+ }
+ }
+ // Clean up collection
+ releaseCom(frameCollection);
+ } catch (Exception ex) {
+ LOG.Warn("Problem while trying to get the frames, skipping!", ex);
+ }
+
+ try {
+ // Correct iframe locations
+ foreach (IHTMLElement frameElement in _document3.getElementsByTagName("IFRAME")) {
+ try {
+ CorrectFrameLocations(frameElement);
+ // Clean up frameElement
+ releaseCom(frameElement);
+ } catch (Exception e) {
+ LOG.Warn("Problem while trying to get information from an iframe, skipping the frame!", e);
+ }
+ }
+ } catch (Exception ex) {
+ LOG.Warn("Problem while trying to get the iframes, skipping!", ex);
+ }
+ }
+
+ ///
+ /// Corrent the frame locations with the information
+ ///
+ ///
+ private void CorrectFrameLocations(IHTMLElement frameElement) {
+ long x = 0;
+ long y = 0;
+ IHTMLElement element = frameElement;
+ IHTMLElement oldElement = null;
+ do {
+ x += element.offsetLeft;
+ y += element.offsetTop;
+ element = element.offsetParent;
+ // Release element, but prevent the frameElement to be released
+ if (oldElement != null) {
+ releaseCom(oldElement);
+ }
+ oldElement = element;
+ } while (element != null);
+
+ Point elementLocation = new Point((int)x, (int)y);
+ IHTMLElement2 element2 = (IHTMLElement2)frameElement;
+ IHTMLRect rec = element2.getBoundingClientRect();
+ Point elementBoundingLocation = new Point(rec.left, rec.top);
+ // Release IHTMLRect
+ releaseCom(rec);
+ LOG.DebugFormat("Looking for iframe to correct at {0}", elementBoundingLocation);
+ foreach(DocumentContainer foundFrame in _frames) {
+ Point frameLocation = foundFrame.SourceLocation;
+ if (frameLocation.Equals(elementBoundingLocation)) {
+ // Match found, correcting location
+ LOG.DebugFormat("Correcting frame from {0} to {1}", frameLocation, elementLocation);
+ foundFrame.SourceLocation = elementLocation;
+ foundFrame.DestinationLocation = elementLocation;
+ } else {
+ LOG.DebugFormat("{0} != {1}", frameLocation, elementBoundingLocation);
+ }
+ }
+ }
+
+ ///
+ /// A "workaround" for Access Denied when dealing with Frames from different domains
+ ///
+ /// The IHTMLWindow2 to get the document from
+ /// IHTMLDocument2 or null
+ private static IHTMLDocument2 GetDocumentFromWindow(IHTMLWindow2 htmlWindow) {
+ if (htmlWindow == null) {
+ LOG.Warn("htmlWindow == null");
+ return null;
+ }
+
+ // First try the usual way to get the document.
+ try {
+ IHTMLDocument2 doc = htmlWindow.document;
+ return doc;
+ } catch (COMException comEx) {
+ // I think COMException won't be ever fired but just to be sure ...
+ if (comEx.ErrorCode != E_ACCESSDENIED) {
+ LOG.Warn("comEx.ErrorCode != E_ACCESSDENIED but", comEx);
+ return null;
+ }
+ } catch (UnauthorizedAccessException) {
+ // This error is okay, ignoring it
+ } catch (Exception ex1) {
+ LOG.Warn("Some error: ", ex1);
+ // Any other error.
+ return null;
+ }
+
+ // At this point the error was E_ACCESSDENIED because the frame contains a document from another domain.
+ // IE tries to prevent a cross frame scripting security issue.
+ try {
+ // Convert IHTMLWindow2 to IWebBrowser2 using IServiceProvider.
+ IServiceProvider sp = (IServiceProvider)htmlWindow;
+
+ // Use IServiceProvider.QueryService to get IWebBrowser2 object.
+ object brws;
+ Guid webBrowserApp = IID_IWebBrowserApp;
+ Guid webBrowser2 = IID_IWebBrowser2;
+ sp.QueryService(ref webBrowserApp, ref webBrowser2, out brws);
+
+ // Get the document from IWebBrowser2.
+ IWebBrowser2 browser = (IWebBrowser2)brws;
+
+ return (IHTMLDocument2)browser.Document;
+ } catch (Exception ex2) {
+ LOG.Warn("another error: ", ex2);
+ }
+ return null;
+ }
+
+ public Color BackgroundColor {
+ get {
+ try {
+ string bgColor = (string)_document2.bgColor;
+ if (bgColor != null) {
+ int rgbInt = int.Parse(bgColor.Substring(1), NumberStyles.HexNumber);
+ return Color.FromArgb(rgbInt >> 16, (rgbInt >> 8) & 255, rgbInt & 255);
+ }
+ } catch (Exception ex) {
+ LOG.Error("Problem retrieving the background color: ", ex);
+ }
+ return Color.White;
+ }
+ }
+
+ public Rectangle ViewportRectangle => _viewportRectangle;
+
+ public WindowDetails ContentWindow => _contentWindow;
+
+ public DocumentContainer Parent {
+ get {
+ return _parent;
+ }
+ set {
+ _parent = value;
+ }
+ }
+
+ private int ScaleX(int physicalValue) {
+ return (int)Math.Round(physicalValue * _zoomLevelX, MidpointRounding.AwayFromZero);
+ }
+
+ private int ScaleY(int physicalValue) {
+ return (int)Math.Round(physicalValue * _zoomLevelY, MidpointRounding.AwayFromZero);
+ }
+
+ private int UnscaleX(int physicalValue) {
+ return (int)Math.Round(physicalValue / _zoomLevelX, MidpointRounding.AwayFromZero);
+ }
+
+ private int UnscaleY(int physicalValue) {
+ return (int)Math.Round(physicalValue / _zoomLevelY, MidpointRounding.AwayFromZero);
+ }
+
+ ///
+ /// Set/change an int attribute on a document
+ ///
+ public void SetAttribute(string attribute, int value) {
+ SetAttribute(attribute, value.ToString());
+ }
+
+ ///
+ /// Set/change an attribute on a document
+ ///
+ /// Attribute to set
+ /// Value to set
+ public void SetAttribute(string attribute, string value) {
+ var element = !_isDtd ? _document2.body : _document3.documentElement;
+ element.setAttribute(attribute, value, 1);
+ // Release IHTMLElement com object
+ releaseCom(element);
+ }
+
+ ///
+ /// Get the attribute from a document
+ ///
+ /// Attribute to get
+ /// object with the attribute value
+ public object GetAttribute(string attribute) {
+ var element = !_isDtd ? _document2.body : _document3.documentElement;
+ var retVal = element.getAttribute(attribute, 1);
+ // Release IHTMLElement com object
+ releaseCom(element);
+ return retVal;
+ }
+
+ ///
+ /// Get the attribute as int from a document
+ ///
+ public int GetAttributeAsInt(string attribute) {
+ int retVal = (int)GetAttribute(attribute);
+ return retVal;
+ }
+
+ public int Id { get; } = _counter++;
+
+ public string Name { get; private set; }
+
+ public string Url { get; private set; }
+
+ public bool IsHidden => ClientWidth == 0 || ClientHeight == 0;
+
+ public int ClientWidth => ScaleX(GetAttributeAsInt("clientWidth"));
+
+ public int ClientHeight => ScaleY(GetAttributeAsInt("clientHeight"));
+
+ public int ScrollWidth => ScaleX(GetAttributeAsInt("scrollWidth"));
+
+ public int ScrollHeight => ScaleY(GetAttributeAsInt("scrollHeight"));
+
+ public Point SourceLocation {
+ get {
+ return _sourceLocation;
+ }
+ set {
+ _sourceLocation = value;
+ }
+ }
+
+ public Size SourceSize => new Size(ClientWidth, ClientHeight);
+
+ public Rectangle SourceRectangle => new Rectangle(SourceLocation, SourceSize);
+
+ public int SourceLeft => _sourceLocation.X;
+
+ public int SourceTop => _sourceLocation.Y;
+
+ public int SourceRight => _sourceLocation.X + ClientWidth;
+
+ public int SourceBottom => _sourceLocation.Y + ClientHeight;
+
+ public Point DestinationLocation {
+ get {
+ return _destinationLocation;
+ }
+ set {
+ _destinationLocation = value;
+ }
+
+ }
+
+ public Size DestinationSize => new Size(ScrollWidth, ScrollHeight);
+
+ public Rectangle DestinationRectangle => new Rectangle(DestinationLocation, DestinationSize);
+
+ public int DestinationLeft {
+ get {
+ return _destinationLocation.X;
+ }
+ set {
+ _destinationLocation.X = value;
+ }
+ }
+
+ public int DestinationTop {
+ get {
+ return _destinationLocation.Y;
+ }
+ set {
+ _destinationLocation.Y = value;
+ }
+ }
+
+ public int DestinationRight => _destinationLocation.X + ScrollWidth;
+
+ public int DestinationBottom => _destinationLocation.Y + ScrollHeight;
+
+ public int ScrollLeft {
+ get{
+ return ScaleX(GetAttributeAsInt("scrollLeft"));
+ }
+ set {
+ SetAttribute("scrollLeft", UnscaleX(value));
+ }
+ }
+
+ public int ScrollTop {
+ get{
+ return ScaleY(GetAttributeAsInt("scrollTop"));
+ }
+ set {
+ SetAttribute("scrollTop", UnscaleY(value));
+ }
+ }
+
+ public IList Frames => _frames;
+ }
+}
diff --git a/Greenshot/Helpers/MailHelper.cs b/Greenshot/Helpers/MailHelper.cs
new file mode 100644
index 000000000..f2dfbbfd9
--- /dev/null
+++ b/Greenshot/Helpers/MailHelper.cs
@@ -0,0 +1,728 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using log4net;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Author: Andrew Baker
+ /// Datum: 10.03.2006
+ /// Available from here
+ ///
+ #region Public MapiMailMessage Class
+
+ ///
+ /// Represents an email message to be sent through MAPI.
+ ///
+ public class MapiMailMessage : IDisposable {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(MapiMailMessage));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ ///
+ /// Helper Method for creating an Email with Attachment
+ ///
+ /// Path to file
+ ///
+ public static void SendImage(string fullPath, string title) {
+ using (MapiMailMessage message = new MapiMailMessage(title, null)) {
+ message.Files.Add(fullPath);
+ if (!string.IsNullOrEmpty(CoreConfig.MailApiTo)) {
+ message.Recipients.Add(new Recipient(CoreConfig.MailApiTo, RecipientType.To));
+ }
+ if (!string.IsNullOrEmpty(CoreConfig.MailApiCC)) {
+ message.Recipients.Add(new Recipient(CoreConfig.MailApiCC, RecipientType.CC));
+ }
+ if (!string.IsNullOrEmpty(CoreConfig.MailApiBCC)) {
+ message.Recipients.Add(new Recipient(CoreConfig.MailApiBCC, RecipientType.BCC));
+ }
+ message.ShowDialog();
+ }
+ }
+
+
+ ///
+ /// Helper Method for creating an Email with Image Attachment
+ ///
+ /// The image to send
+ /// ICaptureDetails
+ public static void SendImage(ISurface surface, ICaptureDetails captureDetails) {
+ string tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings());
+
+ if (tmpFile != null) {
+ // Store the list of currently active windows, so we can make sure we show the email window later!
+ var windowsBefore = WindowDetails.GetVisibleWindows();
+ //bool isEmailSend = false;
+ //if (EmailConfigHelper.HasOutlook() && (CoreConfig.OutputEMailFormat == EmailFormat.OUTLOOK_HTML || CoreConfig.OutputEMailFormat == EmailFormat.OUTLOOK_TXT)) {
+ // isEmailSend = OutlookExporter.ExportToOutlook(tmpFile, captureDetails);
+ //}
+ if (/*!isEmailSend &&*/ EmailConfigHelper.HasMapi()) {
+ // Fallback to MAPI
+ // Send the email
+ SendImage(tmpFile, captureDetails.Title);
+ }
+ WindowDetails.ActiveNewerWindows(windowsBefore);
+ }
+ }
+ #region Private MapiFileDescriptor Class
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ private class MapiFileDescriptor {
+ public int reserved = 0;
+ public int flags = 0;
+ public int position;
+ public string path;
+ public string name;
+ public IntPtr type = IntPtr.Zero;
+ }
+
+ #endregion Private MapiFileDescriptor Class
+
+ #region Enums
+
+ ///
+ /// Specifies the valid RecipientTypes for a Recipient.
+ ///
+ public enum RecipientType
+ {
+ ///
+ /// Recipient will be in the TO list.
+ ///
+ To = 1,
+
+ ///
+ /// Recipient will be in the CC list.
+ ///
+ CC = 2,
+
+ ///
+ /// Recipient will be in the BCC list.
+ ///
+ BCC = 3
+ };
+
+ #endregion Enums
+
+ #region Member Variables
+
+ private readonly ManualResetEvent _manualResetEvent;
+
+ #endregion Member Variables
+
+ #region Constructors
+
+ ///
+ /// Creates a blank mail message.
+ ///
+ public MapiMailMessage() {
+ Files = new List();
+ Recipients = new RecipientCollection();
+ _manualResetEvent = new ManualResetEvent(false);
+ }
+
+ ///
+ /// Creates a new mail message with the specified subject.
+ ///
+ public MapiMailMessage(string subject) : this() {
+ Subject = subject;
+ }
+
+ ///
+ /// Creates a new mail message with the specified subject and body.
+ ///
+ public MapiMailMessage(string subject, string body) : this() {
+ Subject = subject;
+ Body = body;
+ }
+
+ #endregion Constructors
+
+ #region Public Properties
+
+ ///
+ /// Gets or sets the subject of this mail message.
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// Gets or sets the body of this mail message.
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// Gets the recipient list for this mail message.
+ ///
+ public RecipientCollection Recipients { get; private set; }
+
+ ///
+ /// Gets the file list for this mail message.
+ ///
+ public List Files { get; }
+
+ #endregion Public Properties
+
+ #region Public Methods
+
+ ///
+ /// Displays the mail message dialog asynchronously.
+ ///
+ public void ShowDialog() {
+ // Create the mail message in an STA thread
+ var thread = new Thread(_ShowMail)
+ {
+ IsBackground = true,
+ Name = "Create MAPI mail"
+ };
+ thread.SetApartmentState(ApartmentState.STA);
+ thread.Start();
+
+ // only return when the new thread has built it's interop representation
+ _manualResetEvent.WaitOne();
+ _manualResetEvent.Reset();
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion Public Methods
+
+ #region Private Methods
+
+ protected virtual void Dispose(bool disposing) {
+ if (!disposing) {
+ return;
+ }
+ _manualResetEvent?.Close();
+ }
+
+ ///
+ /// Sends the mail message.
+ ///
+ private void _ShowMail() {
+ var message = new MapiHelperInterop.MapiMessage();
+
+ using (var interopRecipients = Recipients.GetInteropRepresentation()) {
+ message.Subject = Subject;
+ message.NoteText = Body;
+
+ message.Recipients = interopRecipients.Handle;
+ message.RecipientCount = Recipients.Count;
+
+ // Check if we need to add attachments
+ if (Files.Count > 0) {
+ // Add attachments
+ message.Files = _AllocAttachments(out message.FileCount);
+ }
+
+ // Signal the creating thread (make the remaining code async)
+ _manualResetEvent.Set();
+
+ const int MAPI_DIALOG = 0x8;
+ //const int MAPI_LOGON_UI = 0x1;
+ int error = MapiHelperInterop.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_DIALOG, 0);
+
+ if (Files.Count > 0) {
+ // Deallocate the files
+ _DeallocFiles(message);
+ }
+ MAPI_CODES errorCode = (MAPI_CODES)Enum.ToObject(typeof(MAPI_CODES), error);
+
+ // Check for error
+ if (errorCode == MAPI_CODES.SUCCESS || errorCode == MAPI_CODES.USER_ABORT)
+ {
+ return;
+ }
+ string errorText = GetMapiError(errorCode);
+ Log.Error("Error sending MAPI Email. Error: " + errorText + " (code = " + errorCode + ").");
+ MessageBox.Show(errorText, "Mail (MAPI) destination", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ // Recover from bad settings, show again
+ if (errorCode != MAPI_CODES.INVALID_RECIPS)
+ {
+ return;
+ }
+ Recipients = new RecipientCollection();
+ _ShowMail();
+ }
+ }
+
+ ///
+ /// Deallocates the files in a message.
+ ///
+ /// The message to deallocate the files from.
+ private void _DeallocFiles(MapiHelperInterop.MapiMessage message) {
+ if (message.Files != IntPtr.Zero) {
+ Type fileDescType = typeof(MapiFileDescriptor);
+ int fsize = Marshal.SizeOf(fileDescType);
+
+ // Get the ptr to the files
+ IntPtr runptr = message.Files;
+ // Release each file
+ for (int i = 0; i < message.FileCount; i++) {
+ Marshal.DestroyStructure(runptr, fileDescType);
+ runptr = new IntPtr(runptr.ToInt64() + fsize);
+ }
+ // Release the file
+ Marshal.FreeHGlobal(message.Files);
+ }
+ }
+
+ ///
+ /// Allocates the file attachments
+ ///
+ ///
+ ///
+ private IntPtr _AllocAttachments(out int fileCount) {
+ fileCount = 0;
+ if (Files == null) {
+ return IntPtr.Zero;
+ }
+ if ((Files.Count <= 0) || (Files.Count > 100)) {
+ return IntPtr.Zero;
+ }
+
+ Type atype = typeof(MapiFileDescriptor);
+ int asize = Marshal.SizeOf(atype);
+ IntPtr ptra = Marshal.AllocHGlobal(Files.Count * asize);
+
+ MapiFileDescriptor mfd = new MapiFileDescriptor
+ {
+ position = -1
+ };
+ IntPtr runptr = ptra;
+ foreach (string path in Files)
+ {
+ mfd.name = Path.GetFileName(path);
+ mfd.path = path;
+ Marshal.StructureToPtr(mfd, runptr, false);
+ runptr = new IntPtr(runptr.ToInt64() + asize);
+ }
+
+ fileCount = Files.Count;
+ return ptra;
+ }
+
+ private enum MAPI_CODES {
+ SUCCESS = 0,
+ USER_ABORT = 1,
+ FAILURE = 2,
+ LOGIN_FAILURE = 3,
+ DISK_FULL = 4,
+ INSUFFICIENT_MEMORY = 5,
+ BLK_TOO_SMALL = 6,
+ TOO_MANY_SESSIONS = 8,
+ TOO_MANY_FILES = 9,
+ TOO_MANY_RECIPIENTS = 10,
+ ATTACHMENT_NOT_FOUND = 11,
+ ATTACHMENT_OPEN_FAILURE = 12,
+ ATTACHMENT_WRITE_FAILURE = 13,
+ UNKNOWN_RECIPIENT = 14,
+ BAD_RECIPTYPE = 15,
+ NO_MESSAGES = 16,
+ INVALID_MESSAGE = 17,
+ TEXT_TOO_LARGE = 18,
+ INVALID_SESSION = 19,
+ TYPE_NOT_SUPPORTED = 20,
+ AMBIGUOUS_RECIPIENT = 21,
+ MESSAGE_IN_USE = 22,
+ NETWORK_FAILURE = 23,
+ INVALID_EDITFIELDS = 24,
+ INVALID_RECIPS = 25,
+ NOT_SUPPORTED = 26,
+ NO_LIBRARY = 999,
+ INVALID_PARAMETER = 998
+ }
+ ///
+ /// Logs any Mapi errors.
+ ///
+ private string GetMapiError(MAPI_CODES errorCode) {
+
+ string error = string.Empty;
+
+ switch (errorCode) {
+ case MAPI_CODES.USER_ABORT:
+ error = "User Aborted.";
+ break;
+ case MAPI_CODES.FAILURE:
+ error = "MAPI Failure.";
+ break;
+ case MAPI_CODES.LOGIN_FAILURE:
+ error = "Login Failure.";
+ break;
+ case MAPI_CODES.DISK_FULL:
+ error = "MAPI Disk full.";
+ break;
+ case MAPI_CODES.INSUFFICIENT_MEMORY:
+ error = "MAPI Insufficient memory.";
+ break;
+ case MAPI_CODES.BLK_TOO_SMALL:
+ error = "MAPI Block too small.";
+ break;
+ case MAPI_CODES.TOO_MANY_SESSIONS:
+ error = "MAPI Too many sessions.";
+ break;
+ case MAPI_CODES.TOO_MANY_FILES:
+ error = "MAPI too many files.";
+ break;
+ case MAPI_CODES.TOO_MANY_RECIPIENTS:
+ error = "MAPI too many recipients.";
+ break;
+ case MAPI_CODES.ATTACHMENT_NOT_FOUND:
+ error = "MAPI Attachment not found.";
+ break;
+ case MAPI_CODES.ATTACHMENT_OPEN_FAILURE:
+ error = "MAPI Attachment open failure.";
+ break;
+ case MAPI_CODES.ATTACHMENT_WRITE_FAILURE:
+ error = "MAPI Attachment Write Failure.";
+ break;
+ case MAPI_CODES.UNKNOWN_RECIPIENT:
+ error = "MAPI Unknown recipient.";
+ break;
+ case MAPI_CODES.BAD_RECIPTYPE:
+ error = "MAPI Bad recipient type.";
+ break;
+ case MAPI_CODES.NO_MESSAGES:
+ error = "MAPI No messages.";
+ break;
+ case MAPI_CODES.INVALID_MESSAGE:
+ error = "MAPI Invalid message.";
+ break;
+ case MAPI_CODES.TEXT_TOO_LARGE:
+ error = "MAPI Text too large.";
+ break;
+ case MAPI_CODES.INVALID_SESSION:
+ error = "MAPI Invalid session.";
+ break;
+ case MAPI_CODES.TYPE_NOT_SUPPORTED:
+ error = "MAPI Type not supported.";
+ break;
+ case MAPI_CODES.AMBIGUOUS_RECIPIENT:
+ error = "MAPI Ambiguous recipient.";
+ break;
+ case MAPI_CODES.MESSAGE_IN_USE:
+ error = "MAPI Message in use.";
+ break;
+ case MAPI_CODES.NETWORK_FAILURE:
+ error = "MAPI Network failure.";
+ break;
+ case MAPI_CODES.INVALID_EDITFIELDS:
+ error = "MAPI Invalid edit fields.";
+ break;
+ case MAPI_CODES.INVALID_RECIPS:
+ error = "MAPI Invalid Recipients.";
+ break;
+ case MAPI_CODES.NOT_SUPPORTED:
+ error = "MAPI Not supported.";
+ break;
+ case MAPI_CODES.NO_LIBRARY:
+ error = "MAPI No Library.";
+ break;
+ case MAPI_CODES.INVALID_PARAMETER:
+ error = "MAPI Invalid parameter.";
+ break;
+ }
+ return error;
+ }
+ #endregion Private Methods
+
+ #region Private MAPIHelperInterop Class
+
+ ///
+ /// Internal class for calling MAPI APIs
+ ///
+ internal class MapiHelperInterop {
+ #region Constructors
+
+ ///
+ /// Private constructor.
+ ///
+ private MapiHelperInterop() {
+ // Intenationally blank
+ }
+
+ #endregion Constructors
+
+
+ #region Structs
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public class MapiMessage {
+ public int Reserved = 0;
+ public string Subject;
+ public string NoteText;
+ public string MessageType = null;
+ public string DateReceived = null;
+ public string ConversationID = null;
+ public int Flags = 0;
+ public IntPtr Originator = IntPtr.Zero;
+ public int RecipientCount;
+ public IntPtr Recipients = IntPtr.Zero;
+ public int FileCount;
+ public IntPtr Files = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public class MapiRecipDesc {
+ public int Reserved = 0;
+ public int RecipientClass;
+ public string Name;
+ public string Address;
+ public int eIDSize = 0;
+ public IntPtr EntryID = IntPtr.Zero;
+ }
+
+ [DllImport("MAPI32.DLL", SetLastError = true, CharSet=CharSet.Ansi)]
+ public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv);
+
+ #endregion Structs
+ }
+
+ #endregion Private MAPIHelperInterop Class
+ }
+
+ #endregion Public MapiMailMessage Class
+
+ #region Public Recipient Class
+
+ ///
+ /// Represents a Recipient for a MapiMailMessage.
+ ///
+ public class Recipient {
+ #region Public Properties
+
+ ///
+ /// The email address of this recipient.
+ ///
+ public string Address;
+
+ ///
+ /// The display name of this recipient.
+ ///
+ public string DisplayName;
+
+ ///
+ /// How the recipient will receive this message (To, CC, BCC).
+ ///
+ public MapiMailMessage.RecipientType RecipientType = MapiMailMessage.RecipientType.To;
+
+ #endregion Public Properties
+
+ #region Constructors
+
+ ///
+ /// Creates a new recipient with the specified address.
+ ///
+ public Recipient(string address) {
+ Address = address;
+ }
+
+ ///
+ /// Creates a new recipient with the specified address and display name.
+ ///
+ public Recipient(string address, string displayName) {
+ Address = address;
+ DisplayName = displayName;
+ }
+
+ ///
+ /// Creates a new recipient with the specified address and recipient type.
+ ///
+ public Recipient(string address, MapiMailMessage.RecipientType recipientType) {
+ Address = address;
+ RecipientType = recipientType;
+ }
+
+ ///
+ /// Creates a new recipient with the specified address, display name and recipient type.
+ ///
+ public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType) {
+ Address = address;
+ DisplayName = displayName;
+ RecipientType = recipientType;
+ }
+
+ #endregion Constructors
+
+ #region Internal Methods
+
+ ///
+ /// Returns an interop representation of a recepient.
+ ///
+ ///
+ internal MapiMailMessage.MapiHelperInterop.MapiRecipDesc GetInteropRepresentation() {
+ MapiMailMessage.MapiHelperInterop.MapiRecipDesc interop = new MapiMailMessage.MapiHelperInterop.MapiRecipDesc();
+
+ if (DisplayName == null) {
+ interop.Name = Address;
+ } else {
+ interop.Name = DisplayName;
+ interop.Address = Address;
+ }
+
+ interop.RecipientClass = (int)RecipientType;
+
+ return interop;
+ }
+
+ #endregion Internal Methods
+ }
+
+ #endregion Public Recipient Class
+
+ #region Public RecipientCollection Class
+
+ ///
+ /// Represents a colleciton of recipients for a mail message.
+ ///
+ public class RecipientCollection : CollectionBase {
+ ///
+ /// Adds the specified recipient to this collection.
+ ///
+ public void Add(Recipient value) {
+ List.Add(value);
+ }
+
+ ///
+ /// Adds a new recipient with the specified address to this collection.
+ ///
+ public void Add(string address) {
+ Add(new Recipient(address));
+ }
+
+ ///
+ /// Adds a new recipient with the specified address and display name to this collection.
+ ///
+ public void Add(string address, string displayName) {
+ Add(new Recipient(address, displayName));
+ }
+
+ ///
+ /// Adds a new recipient with the specified address and recipient type to this collection.
+ ///
+ public void Add(string address, MapiMailMessage.RecipientType recipientType) {
+ Add(new Recipient(address, recipientType));
+ }
+
+ ///
+ /// Adds a new recipient with the specified address, display name and recipient type to this collection.
+ ///
+ public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType) {
+ Add(new Recipient(address, displayName, recipientType));
+ }
+
+ ///
+ /// Returns the recipient stored in this collection at the specified index.
+ ///
+ public Recipient this[int index] => (Recipient)List[index];
+
+ internal InteropRecipientCollection GetInteropRepresentation() {
+ return new InteropRecipientCollection(this);
+ }
+
+ ///
+ /// Struct which contains an interop representation of a colleciton of recipients.
+ ///
+ internal struct InteropRecipientCollection : IDisposable {
+ #region Member Variables
+
+ private int _count;
+
+ #endregion Member Variables
+
+ #region Constructors
+
+ ///
+ /// Default constructor for creating InteropRecipientCollection.
+ ///
+ ///
+ public InteropRecipientCollection(RecipientCollection outer) {
+ _count = outer.Count;
+
+ if (_count == 0) {
+ Handle = IntPtr.Zero;
+ return;
+ }
+
+ // allocate enough memory to hold all recipients
+ int size = Marshal.SizeOf(typeof(MapiMailMessage.MapiHelperInterop.MapiRecipDesc));
+ Handle = Marshal.AllocHGlobal(_count * size);
+
+ // place all interop recipients into the memory just allocated
+ IntPtr ptr = Handle;
+ foreach (Recipient native in outer) {
+ MapiMailMessage.MapiHelperInterop.MapiRecipDesc interop = native.GetInteropRepresentation();
+
+ // stick it in the memory block
+ Marshal.StructureToPtr(interop, ptr, false);
+ ptr = new IntPtr(ptr.ToInt64() + size);
+ }
+ }
+
+ #endregion Costructors
+
+ #region Public Properties
+
+ public IntPtr Handle { get; private set; }
+
+ #endregion Public Properties
+
+ #region Public Methods
+
+ ///
+ /// Disposes of resources.
+ ///
+ public void Dispose() {
+ if (Handle != IntPtr.Zero) {
+ Type type = typeof(MapiMailMessage.MapiHelperInterop.MapiRecipDesc);
+ int size = Marshal.SizeOf(type);
+
+ // destroy all the structures in the memory area
+ IntPtr ptr = Handle;
+ for (int i = 0; i < _count; i++) {
+ Marshal.DestroyStructure(ptr, type);
+ ptr = new IntPtr(ptr.ToInt64() + size);
+ }
+
+ // free the memory
+ Marshal.FreeHGlobal(Handle);
+
+ Handle = IntPtr.Zero;
+ _count = 0;
+ }
+ }
+
+ #endregion Public Methods
+ }
+ }
+
+ #endregion Public RecipientCollection Class
+}
\ No newline at end of file
diff --git a/Greenshot/Helpers/PluginHelper.cs b/Greenshot/Helpers/PluginHelper.cs
new file mode 100644
index 000000000..ed4adc649
--- /dev/null
+++ b/Greenshot/Helpers/PluginHelper.cs
@@ -0,0 +1,335 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Reflection;
+using System.Windows.Forms;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// The PluginHelper takes care of all plugin related functionality
+ ///
+ [Serializable]
+ public class PluginHelper : IGreenshotHost {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PluginHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ private static readonly string PluginPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),Application.ProductName);
+ private static readonly string ApplicationPath = Path.GetDirectoryName(Application.ExecutablePath);
+ private static readonly string PafPath = Path.Combine(Application.StartupPath, @"App\Greenshot");
+ private static readonly IDictionary plugins = new SortedDictionary();
+ private static readonly PluginHelper instance = new PluginHelper();
+
+ public static PluginHelper Instance => instance;
+
+ private PluginHelper() {
+ PluginUtils.Host = this;
+ }
+
+ public Form GreenshotForm => MainForm.Instance;
+
+ public NotifyIcon NotifyIcon => MainForm.Instance.NotifyIcon;
+
+ public bool HasPlugins() {
+ return plugins != null && plugins.Count > 0;
+ }
+
+ public void Shutdown() {
+ foreach(var plugin in plugins.Values) {
+ plugin.Shutdown();
+ plugin.Dispose();
+ }
+ plugins.Clear();
+ }
+
+ // Add plugins to the Listview
+ public void FillListview(ListView listview) {
+ foreach(var pluginAttribute in plugins.Keys) {
+ var item = new ListViewItem(pluginAttribute.Name)
+ {
+ Tag = pluginAttribute
+ };
+ item.SubItems.Add(pluginAttribute.Version);
+ item.SubItems.Add(pluginAttribute.CreatedBy);
+ item.SubItems.Add(pluginAttribute.DllFile);
+ listview.Items.Add(item);
+ }
+ }
+
+ public bool IsSelectedItemConfigurable(ListView listview) {
+ if (listview.SelectedItems.Count <= 0)
+ {
+ return false;
+ }
+ var pluginAttribute = (PluginAttribute)listview.SelectedItems[0].Tag;
+ return pluginAttribute != null && pluginAttribute.Configurable;
+ }
+
+ public void ConfigureSelectedItem(ListView listview) {
+ if (listview.SelectedItems.Count <= 0)
+ {
+ return;
+ }
+ var pluginAttribute = (PluginAttribute)listview.SelectedItems[0].Tag;
+ if (pluginAttribute == null)
+ {
+ return;
+ }
+ var plugin = plugins[pluginAttribute];
+ plugin.Configure();
+ }
+
+ #region Implementation of IGreenshotPluginHost
+
+ ///
+ /// Create a Thumbnail
+ ///
+ /// Image of which we need a Thumbnail
+ /// Thumbnail width
+ /// Thumbnail height
+ /// Image with Thumbnail
+ public Image GetThumbnail(Image image, int width, int height) {
+ return image.GetThumbnailImage(width, height, ThumbnailCallback, IntPtr.Zero);
+ }
+
+ ///
+ /// Required for GetThumbnail, but not used
+ ///
+ /// true
+ private bool ThumbnailCallback() {
+ return true;
+ }
+
+ public ContextMenuStrip MainMenu => MainForm.Instance.MainMenu;
+
+ public IDictionary Plugins => plugins;
+
+ public IDestination GetDestination(string designation) {
+ return DestinationHelper.GetDestination(designation);
+ }
+ public List GetAllDestinations() {
+ return DestinationHelper.GetAllDestinations();
+ }
+
+ public ExportInformation ExportCapture(bool manuallyInitiated, string designation, ISurface surface, ICaptureDetails captureDetails) {
+ return DestinationHelper.ExportCapture(manuallyInitiated, designation, surface, captureDetails);
+ }
+
+ ///
+ /// Make Capture with specified Handler
+ ///
+ /// bool false if the mouse should not be captured, true if the configuration should be checked
+ /// IDestination
+ public void CaptureRegion(bool captureMouseCursor, IDestination destination) {
+ CaptureHelper.CaptureRegion(captureMouseCursor, destination);
+ }
+
+ ///
+ /// Use the supplied image, and handle it as if it's captured.
+ ///
+ /// Image to handle
+ public void ImportCapture(ICapture captureToImport) {
+ MainForm.Instance.BeginInvoke((MethodInvoker)delegate {
+ CaptureHelper.ImportCapture(captureToImport);
+ });
+ }
+
+ ///
+ /// Get an ICapture object, so the plugin can modify this
+ ///
+ ///
+ public ICapture GetCapture(Image imageToCapture) {
+ var capture = new Capture(imageToCapture)
+ {
+ CaptureDetails = new CaptureDetails
+ {
+ CaptureMode = CaptureMode.Import,
+ Title = "Imported"
+ }
+ };
+ return capture;
+ }
+ #endregion
+
+ #region Plugin loading
+ public PluginAttribute FindPlugin(string name) {
+ foreach(PluginAttribute pluginAttribute in plugins.Keys) {
+ if (name.Equals(pluginAttribute.Name)) {
+ return pluginAttribute;
+ }
+ }
+ return null;
+ }
+
+ private bool isNewer(string version1, string version2) {
+ string [] version1Parts = version1.Split('.');
+ string [] version2Parts = version2.Split('.');
+ int parts = Math.Min(version1Parts.Length, version2Parts.Length);
+ for(int i=0; i < parts; i++) {
+ int v1 = Convert.ToInt32(version1Parts[i]);
+ int v2 = Convert.ToInt32(version2Parts[i]);
+ if (v1 > v2) {
+ return true;
+ }
+ if (v1 < v2) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Private helper to find the plugins in the path
+ ///
+ ///
+ ///
+ private void findPluginsOnPath(List pluginFiles, string path) {
+ if (Directory.Exists(path)) {
+ try {
+ foreach (string pluginFile in Directory.GetFiles(path, "*.gsp", SearchOption.AllDirectories)) {
+ pluginFiles.Add(pluginFile);
+ }
+ } catch (UnauthorizedAccessException) {
+ } catch (Exception ex) {
+ Log.Error("Error loading plugin: ", ex);
+ }
+ }
+ }
+
+ ///
+ /// Load the plugins
+ ///
+ public void LoadPlugins() {
+ List pluginFiles = new List();
+
+ if (IniConfig.IsPortable) {
+ findPluginsOnPath(pluginFiles, PafPath);
+ } else {
+ findPluginsOnPath(pluginFiles, PluginPath);
+ findPluginsOnPath(pluginFiles, ApplicationPath);
+ }
+
+ Dictionary tmpAttributes = new Dictionary();
+ Dictionary tmpAssemblies = new Dictionary();
+ // Loop over the list of available files and get the Plugin Attributes
+ foreach (string pluginFile in pluginFiles) {
+ //LOG.DebugFormat("Checking the following file for plugins: {0}", pluginFile);
+ try {
+ Assembly assembly = Assembly.LoadFrom(pluginFile);
+ PluginAttribute[] pluginAttributes = assembly.GetCustomAttributes(typeof(PluginAttribute), false) as PluginAttribute[];
+ if (pluginAttributes.Length > 0) {
+ PluginAttribute pluginAttribute = pluginAttributes[0];
+
+ if (string.IsNullOrEmpty(pluginAttribute.Name)) {
+ AssemblyProductAttribute[] assemblyProductAttributes = assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false) as AssemblyProductAttribute[];
+ if (assemblyProductAttributes.Length > 0) {
+ pluginAttribute.Name = assemblyProductAttributes[0].Product;
+ } else {
+ continue;
+ }
+ }
+ if (string.IsNullOrEmpty(pluginAttribute.CreatedBy)) {
+ AssemblyCompanyAttribute[] assemblyCompanyAttributes = assembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false) as AssemblyCompanyAttribute[];
+ if (assemblyCompanyAttributes.Length > 0) {
+ pluginAttribute.CreatedBy = assemblyCompanyAttributes[0].Company;
+ } else {
+ continue;
+ }
+ }
+ pluginAttribute.Version = assembly.GetName().Version.ToString();
+ pluginAttribute.DllFile = pluginFile;
+
+ // check if this plugin is already available
+ PluginAttribute checkPluginAttribute = null;
+ if (tmpAttributes.ContainsKey(pluginAttribute.Name)) {
+ checkPluginAttribute = tmpAttributes[pluginAttribute.Name];
+ }
+
+ if (checkPluginAttribute != null) {
+ Log.WarnFormat("Duplicate plugin {0} found", pluginAttribute.Name);
+ if (isNewer(pluginAttribute.Version, checkPluginAttribute.Version)) {
+ // Found is newer
+ tmpAttributes[pluginAttribute.Name] = pluginAttribute;
+ tmpAssemblies[pluginAttribute.Name] = assembly;
+ Log.InfoFormat("Loading the newer plugin {0} with version {1} from {2}", pluginAttribute.Name, pluginAttribute.Version, pluginAttribute.DllFile);
+ } else {
+ Log.InfoFormat("Skipping (as the duplicate is newer or same version) the plugin {0} with version {1} from {2}", pluginAttribute.Name, pluginAttribute.Version, pluginAttribute.DllFile);
+ }
+ continue;
+ }
+ if (CoreConfig.ExcludePlugins != null && CoreConfig.ExcludePlugins.Contains(pluginAttribute.Name)) {
+ Log.WarnFormat("Exclude list: {0}", CoreConfig.ExcludePlugins.ToArray());
+ Log.WarnFormat("Skipping the excluded plugin {0} with version {1} from {2}", pluginAttribute.Name, pluginAttribute.Version, pluginAttribute.DllFile);
+ continue;
+ }
+ if (CoreConfig.IncludePlugins != null && CoreConfig.IncludePlugins.Count > 0 && !CoreConfig.IncludePlugins.Contains(pluginAttribute.Name)) {
+ // Whitelist is set
+ Log.WarnFormat("Include list: {0}", CoreConfig.IncludePlugins.ToArray());
+ Log.WarnFormat("Skipping the not included plugin {0} with version {1} from {2}", pluginAttribute.Name, pluginAttribute.Version, pluginAttribute.DllFile);
+ continue;
+ }
+ Log.InfoFormat("Loading the plugin {0} with version {1} from {2}", pluginAttribute.Name, pluginAttribute.Version, pluginAttribute.DllFile);
+ tmpAttributes[pluginAttribute.Name] = pluginAttribute;
+ tmpAssemblies[pluginAttribute.Name] = assembly;
+ } else {
+ Log.ErrorFormat("Can't find the needed Plugin Attribute ({0}) in the assembly of the file \"{1}\", skipping this file.", typeof(PluginAttribute), pluginFile);
+ }
+ } catch (Exception e) {
+ Log.Warn("Can't load file: " + pluginFile, e);
+ }
+ }
+ foreach(string pluginName in tmpAttributes.Keys) {
+ try {
+ PluginAttribute pluginAttribute = tmpAttributes[pluginName];
+ Assembly assembly = tmpAssemblies[pluginName];
+ Type entryType = assembly.GetType(pluginAttribute.EntryType);
+ if (entryType == null) {
+ Log.ErrorFormat("Can't find the in the PluginAttribute referenced type {0} in \"{1}\"", pluginAttribute.EntryType, pluginAttribute.DllFile);
+ continue;
+ }
+ try {
+ IGreenshotPlugin plugin = (IGreenshotPlugin)Activator.CreateInstance(entryType);
+ if (plugin != null) {
+ if (plugin.Initialize(this, pluginAttribute)) {
+ plugins.Add(pluginAttribute, plugin);
+ } else {
+ Log.InfoFormat("Plugin {0} not initialized!", pluginAttribute.Name);
+ }
+ } else {
+ Log.ErrorFormat("Can't create an instance of the in the PluginAttribute referenced type {0} from \"{1}\"", pluginAttribute.EntryType, pluginAttribute.DllFile);
+ }
+ } catch(Exception e) {
+ Log.Error("Can't load Plugin: " + pluginAttribute.Name, e);
+ }
+ } catch(Exception e) {
+ Log.Error("Can't load Plugin: " + pluginName, e);
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Greenshot/Helpers/PrintHelper.cs b/Greenshot/Helpers/PrintHelper.cs
new file mode 100644
index 000000000..ad10d48d1
--- /dev/null
+++ b/Greenshot/Helpers/PrintHelper.cs
@@ -0,0 +1,244 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Drawing.Printing;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using Greenshot.Forms;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using GreenshotPlugin.Effects;
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Description of PrintHelper.
+ ///
+ public class PrintHelper : IDisposable {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PrintHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ private ISurface _surface;
+ private readonly ICaptureDetails _captureDetails;
+ private PrintDocument _printDocument = new PrintDocument();
+ private PrintDialog _printDialog = new PrintDialog();
+
+ public PrintHelper(ISurface surface, ICaptureDetails captureDetails) {
+ _surface = surface;
+ _captureDetails = captureDetails;
+ _printDialog.UseEXDialog = true;
+ _printDocument.DocumentName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails);
+ _printDocument.PrintPage += DrawImageForPrint;
+ _printDialog.Document = _printDocument;
+ }
+
+ /**
+ * Destructor
+ */
+ ~PrintHelper() {
+ Dispose(false);
+ }
+
+ /**
+ * The public accessible Dispose
+ * Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
+ */
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /**
+ * This Dispose is called from the Dispose and the Destructor.
+ * When disposing==true all non-managed resources should be freed too!
+ */
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ _printDocument?.Dispose();
+ _printDialog?.Dispose();
+ }
+ _surface = null;
+ _printDocument = null;
+ _printDialog = null;
+ }
+
+ ///
+ /// displays options dialog (if not disabled via settings) and windows
+ /// print dialog.
+ ///
+ /// printer settings if actually printed, or null if print was cancelled or has failed
+ public PrinterSettings PrintTo(string printerName) {
+ PrinterSettings returnPrinterSettings = null;
+ DialogResult? printOptionsResult = ShowPrintOptionsDialog();
+ try {
+ if (printOptionsResult == null || printOptionsResult == DialogResult.OK) {
+ _printDocument.PrinterSettings.PrinterName = printerName;
+ if (!IsColorPrint()) {
+ _printDocument.DefaultPageSettings.Color = false;
+ }
+ _printDocument.Print();
+ returnPrinterSettings = _printDocument.PrinterSettings;
+ }
+ } catch (Exception e) {
+ Log.Error("An error ocurred while trying to print", e);
+ MessageBox.Show(Language.GetString(LangKey.print_error), Language.GetString(LangKey.error));
+ }
+ return returnPrinterSettings;
+ }
+
+ ///
+ /// displays options dialog (if not disabled via settings) and windows
+ /// print dialog.
+ ///
+ /// printer settings if actually printed, or null if print was cancelled or has failed
+ public PrinterSettings PrintWithDialog() {
+ PrinterSettings returnPrinterSettings = null;
+ if (_printDialog.ShowDialog() == DialogResult.OK) {
+ DialogResult? printOptionsResult = ShowPrintOptionsDialog();
+ try {
+ if (printOptionsResult == null || printOptionsResult == DialogResult.OK) {
+ if (!IsColorPrint()) {
+ _printDocument.DefaultPageSettings.Color = false;
+ }
+ _printDocument.Print();
+ returnPrinterSettings = _printDialog.PrinterSettings;
+ }
+ } catch (Exception e) {
+ Log.Error("An error ocurred while trying to print", e);
+ MessageBox.Show(Language.GetString(LangKey.print_error), Language.GetString(LangKey.error));
+ }
+
+ }
+ return returnPrinterSettings;
+ }
+
+ private bool IsColorPrint() {
+ return !CoreConfig.OutputPrintGrayscale && !CoreConfig.OutputPrintMonochrome;
+ }
+
+ ///
+ /// display print options dialog (if the user has not configured Greenshot not to)
+ ///
+ /// result of the print dialog, or null if the dialog has not been displayed by config
+ private DialogResult? ShowPrintOptionsDialog() {
+ DialogResult? ret = null;
+ if (CoreConfig.OutputPrintPromptOptions) {
+ using (PrintOptionsDialog printOptionsDialog = new PrintOptionsDialog()) {
+ ret = printOptionsDialog.ShowDialog();
+ }
+ }
+ return ret;
+ }
+
+ private void DrawImageForPrint(object sender, PrintPageEventArgs e) {
+
+
+ // Create the output settins
+ SurfaceOutputSettings printOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
+
+ ApplyEffects(printOutputSettings);
+
+ Image image;
+ bool disposeImage = ImageOutput.CreateImageFromSurface(_surface, printOutputSettings, out image);
+ try {
+ ContentAlignment alignment = CoreConfig.OutputPrintCenter ? ContentAlignment.MiddleCenter : ContentAlignment.TopLeft;
+
+ // prepare timestamp
+ float footerStringWidth = 0;
+ float footerStringHeight = 0;
+ string footerString = null; //DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
+ if (CoreConfig.OutputPrintFooter) {
+ footerString = FilenameHelper.FillPattern(CoreConfig.OutputPrintFooterPattern, _captureDetails, false);
+ using (Font f = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular)) {
+ footerStringWidth = e.Graphics.MeasureString(footerString, f).Width;
+ footerStringHeight = e.Graphics.MeasureString(footerString, f).Height;
+ }
+ }
+
+ // Get a rectangle representing the printable Area
+ RectangleF pageRect = e.PageSettings.PrintableArea;
+ if(e.PageSettings.Landscape) {
+ float origWidth = pageRect.Width;
+ pageRect.Width = pageRect.Height;
+ pageRect.Height = origWidth;
+ }
+
+ // Subtract the dateString height from the available area, this way the area stays free
+ pageRect.Height -= footerStringHeight;
+
+ GraphicsUnit gu = GraphicsUnit.Pixel;
+ RectangleF imageRect = image.GetBounds(ref gu);
+ // rotate the image if it fits the page better
+ if (CoreConfig.OutputPrintAllowRotate) {
+ if ((pageRect.Width > pageRect.Height && imageRect.Width < imageRect.Height) || (pageRect.Width < pageRect.Height && imageRect.Width > imageRect.Height)) {
+ image.RotateFlip(RotateFlipType.Rotate270FlipNone);
+ imageRect = image.GetBounds(ref gu);
+ if (alignment.Equals(ContentAlignment.TopLeft)) {
+ alignment = ContentAlignment.TopRight;
+ }
+ }
+ }
+
+ RectangleF printRect = new RectangleF(0, 0, imageRect.Width, imageRect.Height);
+ // scale the image to fit the page better
+ if (CoreConfig.OutputPrintAllowEnlarge || CoreConfig.OutputPrintAllowShrink) {
+ SizeF resizedRect = ScaleHelper.GetScaledSize(imageRect.Size, pageRect.Size, false);
+ if ((CoreConfig.OutputPrintAllowShrink && resizedRect.Width < printRect.Width) || CoreConfig.OutputPrintAllowEnlarge && resizedRect.Width > printRect.Width) {
+ printRect.Size = resizedRect;
+ }
+ }
+
+ // align the image
+ printRect = ScaleHelper.GetAlignedRectangle(printRect, new RectangleF(0, 0, pageRect.Width, pageRect.Height), alignment);
+ if (CoreConfig.OutputPrintFooter) {
+ //printRect = new RectangleF(0, 0, printRect.Width, printRect.Height - (dateStringHeight * 2));
+ using (Font f = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular)) {
+ e.Graphics.DrawString(footerString, f, Brushes.Black, pageRect.Width / 2 - footerStringWidth / 2, pageRect.Height);
+ }
+ }
+ e.Graphics.DrawImage(image, printRect, imageRect, GraphicsUnit.Pixel);
+
+ } finally {
+ if (disposeImage) {
+ image?.Dispose();
+ }
+ }
+ }
+
+ private void ApplyEffects(SurfaceOutputSettings printOutputSettings) {
+ // TODO:
+ // add effects here
+ if (CoreConfig.OutputPrintMonochrome) {
+ byte threshold = CoreConfig.OutputPrintMonochromeThreshold;
+ printOutputSettings.Effects.Add(new MonochromeEffect(threshold));
+ printOutputSettings.ReduceColors = true;
+ }
+
+ // the invert effect should probably be the last
+ if (CoreConfig.OutputPrintInverted) {
+ printOutputSettings.Effects.Add(new InvertEffect());
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/ProcessorHelper.cs b/Greenshot/Helpers/ProcessorHelper.cs
new file mode 100644
index 000000000..dcd1a74e9
--- /dev/null
+++ b/Greenshot/Helpers/ProcessorHelper.cs
@@ -0,0 +1,140 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Description of ProcessorHelper.
+ ///
+ public static class ProcessorHelper {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(ProcessorHelper));
+ private static readonly Dictionary RegisteredProcessors = new Dictionary();
+
+ /// Initialize the Processors
+ static ProcessorHelper() {
+ foreach(Type ProcessorType in InterfaceUtils.GetSubclassesOf(typeof(IProcessor),true)) {
+ // Only take our own
+ if (!"Greenshot.Processors".Equals(ProcessorType.Namespace)) {
+ continue;
+ }
+ try {
+ if (!ProcessorType.IsAbstract) {
+ IProcessor Processor;
+ try {
+ Processor = (IProcessor)Activator.CreateInstance(ProcessorType);
+ } catch (Exception e) {
+ LOG.ErrorFormat("Can't create instance of {0}", ProcessorType);
+ LOG.Error(e);
+ continue;
+ }
+ if (Processor.isActive) {
+ LOG.DebugFormat("Found Processor {0} with designation {1}", ProcessorType.Name, Processor.Designation);
+ RegisterProcessor(Processor);
+ } else {
+ LOG.DebugFormat("Ignoring Processor {0} with designation {1}", ProcessorType.Name, Processor.Designation);
+ }
+ }
+ } catch (Exception ex) {
+ LOG.ErrorFormat("Error loading processor {0}, message: ", ProcessorType.FullName, ex.Message);
+ }
+ }
+ }
+
+ ///
+ /// Register your Processor here, if it doesn't come from a plugin and needs to be available
+ ///
+ ///
+ public static void RegisterProcessor(IProcessor Processor) {
+ // don't test the key, an exception should happen wenn it's not unique
+ RegisteredProcessors.Add(Processor.Designation, Processor);
+ }
+
+ private static List GetPluginsProcessors() {
+ List processors = new List();
+ foreach (PluginAttribute pluginAttribute in PluginHelper.Instance.Plugins.Keys) {
+ IGreenshotPlugin plugin = PluginHelper.Instance.Plugins[pluginAttribute];
+ try {
+ var procs = plugin.Processors();
+ if (procs != null) {
+ processors.AddRange(procs);
+ }
+ } catch (Exception ex) {
+ LOG.ErrorFormat("Couldn't get processors from the plugin {0}", pluginAttribute.Name);
+ LOG.Error(ex);
+ }
+ }
+ processors.Sort();
+ return processors;
+ }
+
+ ///
+ /// Get a list of all Processors, registered or supplied by a plugin
+ ///
+ ///
+ public static List GetAllProcessors() {
+ List processors = new List();
+ processors.AddRange(RegisteredProcessors.Values);
+ processors.AddRange(GetPluginsProcessors());
+ processors.Sort();
+ return processors;
+ }
+
+ ///
+ /// Get a Processor by a designation
+ ///
+ /// Designation of the Processor
+ /// IProcessor or null
+ public static IProcessor GetProcessor(string designation) {
+ if (designation == null) {
+ return null;
+ }
+ if (RegisteredProcessors.ContainsKey(designation)) {
+ return RegisteredProcessors[designation];
+ }
+ foreach (IProcessor processor in GetPluginsProcessors()) {
+ if (designation.Equals(processor.Designation)) {
+ return processor;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// A simple helper method which will call ProcessCapture for the Processor with the specified designation
+ ///
+ ///
+ ///
+ ///
+ public static void ProcessCapture(string designation, ISurface surface, ICaptureDetails captureDetails) {
+ if (RegisteredProcessors.ContainsKey(designation)) {
+ IProcessor Processor = RegisteredProcessors[designation];
+ if (Processor.isActive) {
+ Processor.ProcessCapture(surface, captureDetails);
+ }
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/ResourceMutex.cs b/Greenshot/Helpers/ResourceMutex.cs
new file mode 100644
index 000000000..ae5e12bc6
--- /dev/null
+++ b/Greenshot/Helpers/ResourceMutex.cs
@@ -0,0 +1,185 @@
+// Dapplo - building blocks for desktop applications
+// Copyright (C) 2015-2016 Dapplo
+//
+// For more information see: http://dapplo.net/
+// Dapplo repositories are hosted on GitHub: https://github.com/dapplo
+//
+// This file is part of Dapplo.Addons
+//
+// Dapplo.Addons is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Dapplo.Addons is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have Config a copy of the GNU Lesser General Public License
+// along with Dapplo.Addons. If not, see .
+
+#region using
+
+using log4net;
+using System;
+using System.Security.AccessControl;
+using System.Security.Principal;
+using System.Threading;
+
+#endregion
+
+namespace Greenshot.Helpers
+{
+ ///
+ /// This protects your resources or application from running more than once
+ /// Simplifies the usage of the Mutex class, as described here:
+ /// https://msdn.microsoft.com/en-us/library/System.Threading.Mutex.aspx
+ ///
+ public class ResourceMutex : IDisposable
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(DestinationHelper));
+ private readonly string _mutexId;
+ private readonly string _resourceName;
+ private Mutex _applicationMutex;
+
+ ///
+ /// Private constructor
+ ///
+ ///
+ ///
+ private ResourceMutex(string mutexId, string resourceName = null)
+ {
+ _mutexId = mutexId;
+ _resourceName = resourceName ?? "some resource";
+ }
+
+ ///
+ /// Test if the Mutex was created and locked.
+ ///
+ public bool IsLocked { get; set; }
+
+ ///
+ /// Create a ResourceMutex for the specified mutex id and resource-name
+ ///
+ /// ID of the mutex, preferably a Guid as string
+ /// Name of the resource to lock, e.g your application name, usefull for logs
+ /// true to have a global mutex see: https://msdn.microsoft.com/en-us/library/bwe34f1k.aspx
+ public static ResourceMutex Create(string mutexId, string resourceName = null, bool global = false)
+ {
+ var applicationMutex = new ResourceMutex((global ? @"Global\" : @"Local\") + mutexId, resourceName);
+ applicationMutex.Lock();
+ return applicationMutex;
+ }
+
+ ///
+ /// This tries to get the Mutex, which takes care of having multiple instances running
+ ///
+ /// true if it worked, false if another instance is already running or something went wrong
+ public bool Lock()
+ {
+ Log.DebugFormat("{0} is trying to get Mutex {1}", _resourceName, _mutexId);
+
+ IsLocked = true;
+ // check whether there's an local instance running already, but use local so this works in a multi-user environment
+ try
+ {
+ // Added Mutex Security, hopefully this prevents the UnauthorizedAccessException more gracefully
+ var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
+ var mutexsecurity = new MutexSecurity();
+ mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow));
+ mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.ChangePermissions, AccessControlType.Deny));
+ mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.Delete, AccessControlType.Deny));
+
+ bool createdNew;
+ // 1) Create Mutex
+ _applicationMutex = new Mutex(true, _mutexId, out createdNew, mutexsecurity);
+ // 2) if the mutex wasn't created new get the right to it, this returns false if it's already locked
+ if (!createdNew && !_applicationMutex.WaitOne(100, false))
+ {
+ Log.InfoFormat("{0} is already in use, mutex {1} is NOT locked for the caller", _resourceName, _mutexId);
+ IsLocked = false;
+ // Clean up
+ _applicationMutex.Close();
+ _applicationMutex = null;
+ }
+ else
+ {
+ Log.InfoFormat(createdNew ? "{0} has created & claimed the mutex {1}" : "{0} has claimed the mutex {1}", _resourceName, _mutexId);
+ }
+ }
+ catch (AbandonedMutexException e)
+ {
+ // Another instance didn't cleanup correctly!
+ // we can ignore the exception, it happend on the "waitone" but still the mutex belongs to us
+ Log.WarnFormat("{0} didn't cleanup correctly, but we got the mutex {1}.", _resourceName, _mutexId);
+ Log.Warn(e);
+ }
+ catch (UnauthorizedAccessException e)
+ {
+ Log.ErrorFormat("{0} is most likely already running for a different user in the same session, can't create/get mutex {1} due to error.", _resourceName, _mutexId);
+ Log.Error(e);
+ IsLocked = false;
+ }
+ catch (Exception ex)
+ {
+ Log.ErrorFormat("Problem obtaining the Mutex {1} for {0}, assuming it was already taken!", _resourceName, _mutexId);
+ Log.Error(ex);
+ IsLocked = false;
+ }
+ return IsLocked;
+ }
+
+ #region IDisposable Support
+
+ // To detect redundant Dispose calls
+ private bool _disposedValue;
+
+ ///
+ /// The real disposing code
+ ///
+ /// true if dispose is called, false when the finalizer is called
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (_applicationMutex != null)
+ {
+ try
+ {
+ _applicationMutex.ReleaseMutex();
+ _applicationMutex = null;
+ Log.InfoFormat("Released Mutex {0} for {1}", _mutexId, _resourceName);
+ }
+ catch (Exception ex)
+ {
+ Log.ErrorFormat("Error releasing Mutex {0} for {1}", _mutexId, _resourceName);
+ Log.Error(ex);
+ }
+ }
+ _disposedValue = true;
+ }
+ }
+
+ ///
+ /// Make sure the ApplicationMutex is disposed when the finalizer is called
+ ///
+ ~ResourceMutex()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(false);
+ }
+
+ ///
+ /// The dispose interface, which calls Dispose(true) to signal that dispose is called.
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Greenshot/Helpers/ScaleHelper.cs b/Greenshot/Helpers/ScaleHelper.cs
new file mode 100644
index 000000000..a946c012c
--- /dev/null
+++ b/Greenshot/Helpers/ScaleHelper.cs
@@ -0,0 +1,374 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using Greenshot.Drawing;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Offers a few helper functions for scaling/aligning an element with another element
+ ///
+ public static class ScaleHelper {
+
+ [Flags]
+ public enum ScaleOptions {
+ ///
+ /// Default scale behavior.
+ ///
+ Default = 0x00,
+ ///
+ /// Scale a rectangle in two our four directions, mirrored at it's center coordinates
+ ///
+ Centered = 0x01,
+ ///
+ /// Scale a rectangle maintaining it's aspect ratio
+ ///
+ Rational = 0x02
+ }
+
+ ///
+ /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio
+ ///
+ /// the size of the element to be resized
+ /// the target size of the element
+ /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true)
+ /// a new SizeF object indicating the width and height the element should be scaled to
+ public static SizeF GetScaledSize(SizeF currentSize, SizeF targetSize, bool crop) {
+ float wFactor = targetSize.Width/currentSize.Width;
+ float hFactor = targetSize.Height/currentSize.Height;
+
+ float factor = crop ? Math.Max(wFactor, hFactor) : Math.Min(wFactor, hFactor);
+ return new SizeF(currentSize.Width * factor, currentSize.Height * factor);
+ }
+
+ ///
+ /// calculates the position of an element depending on the desired alignment within a RectangleF
+ ///
+ /// the bounds of the element to be aligned
+ /// the rectangle reference for aligment of the element
+ /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize
+ /// a new RectangleF object with Location aligned aligned to targetRect
+ public static RectangleF GetAlignedRectangle(RectangleF currentRect, RectangleF targetRect, ContentAlignment alignment) {
+ RectangleF newRect = new RectangleF(targetRect.Location, currentRect.Size);
+ switch(alignment) {
+ case ContentAlignment.TopCenter:
+ newRect.X = (targetRect.Width - currentRect.Width) / 2;
+ break;
+ case ContentAlignment.TopRight:
+ newRect.X = targetRect.Width - currentRect.Width;
+ break;
+ case ContentAlignment.MiddleLeft:
+ newRect.Y = (targetRect.Height - currentRect.Height) / 2;
+ break;
+ case ContentAlignment.MiddleCenter:
+ newRect.Y = (targetRect.Height - currentRect.Height) / 2;
+ newRect.X = (targetRect.Width - currentRect.Width) / 2;
+ break;
+ case ContentAlignment.MiddleRight:
+ newRect.Y = (targetRect.Height - currentRect.Height) / 2;
+ newRect.X = targetRect.Width - currentRect.Width;
+ break;
+ case ContentAlignment.BottomLeft:
+ newRect.Y = targetRect.Height - currentRect.Height;
+ break;
+ case ContentAlignment.BottomCenter:
+ newRect.Y = targetRect.Height - currentRect.Height;
+ newRect.X = (targetRect.Width - currentRect.Width) / 2;
+ break;
+ case ContentAlignment.BottomRight:
+ newRect.Y = targetRect.Height - currentRect.Height;
+ newRect.X = targetRect.Width - currentRect.Width;
+ break;
+ }
+ return newRect;
+ }
+
+ ///
+ /// calculates the Rectangle an element must be resized an positioned to, in ordder to fit another element, keeping aspect ratio
+ ///
+ /// the rectangle of the element to be resized/repositioned
+ /// the target size/position of the element
+ /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true)
+ /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize
+ /// a new RectangleF object indicating the width and height the element should be scaled to and the position that should be applied to it for proper alignment
+ public static RectangleF GetScaledRectangle(RectangleF currentRect, RectangleF targetRect, bool crop, ContentAlignment alignment) {
+ SizeF newSize = GetScaledSize(currentRect.Size, targetRect.Size, crop);
+ RectangleF newRect = new RectangleF(new Point(0,0), newSize);
+ return GetAlignedRectangle(newRect, targetRect, alignment);
+ }
+
+ public static void RationalScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
+ Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Rational);
+ }
+
+ public static void CenteredScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
+ Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Centered);
+ }
+
+ public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
+ Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, null);
+ }
+
+ ///
+ /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
+ ///
+ /// bounds of the current rectangle, scaled values will be written to this reference
+ /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
+ /// coordinates of the used handle/gripper
+ /// ScaleOptions to use when scaling
+ public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions? options) {
+ if(options == null) {
+ options = GetScaleOptions();
+ }
+
+ if((options & ScaleOptions.Rational) == ScaleOptions.Rational) {
+ adjustCoordsForRationalScale(originalRectangle, resizeHandlePosition, ref resizeHandleCoords);
+ }
+
+ if((options & ScaleOptions.Centered) == ScaleOptions.Centered) {
+ // store center coordinates of rectangle
+ float rectCenterX = originalRectangle.Left + originalRectangle.Width / 2;
+ float rectCenterY = originalRectangle.Top + originalRectangle.Height / 2;
+ // scale rectangle using handle coordinates
+ scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
+ // mirror handle coordinates via rectangle center coordinates
+ resizeHandleCoords.X -= 2 * (resizeHandleCoords.X - rectCenterX);
+ resizeHandleCoords.Y -= 2 * (resizeHandleCoords.Y - rectCenterY);
+ // scale again with opposing handle and mirrored coordinates
+ resizeHandlePosition = (Positions)((((int)resizeHandlePosition) + 4) % 8);
+ scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
+ } else {
+ scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
+ }
+
+ }
+
+ ///
+ /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
+ ///
+ /// bounds of the current rectangle, scaled values will be written to this reference
+ /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
+ /// coordinates of the used handle/gripper
+ private static void scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
+ switch(resizeHandlePosition) {
+
+ case Positions.TopLeft:
+ originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
+ originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
+ originalRectangle.X = resizeHandleCoords.X;
+ originalRectangle.Y = resizeHandleCoords.Y;
+ break;
+
+ case Positions.TopCenter:
+ originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
+ originalRectangle.Y = resizeHandleCoords.Y;
+ break;
+
+ case Positions.TopRight:
+ originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
+ originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
+ originalRectangle.Y = resizeHandleCoords.Y;
+ break;
+
+ case Positions.MiddleLeft:
+ originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
+ originalRectangle.X = resizeHandleCoords.X;
+ break;
+
+ case Positions.MiddleRight:
+ originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
+ break;
+
+ case Positions.BottomLeft:
+ originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
+ originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
+ originalRectangle.X = resizeHandleCoords.X;
+ break;
+
+ case Positions.BottomCenter:
+ originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
+ break;
+
+ case Positions.BottomRight:
+ originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
+ originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
+ break;
+
+ default:
+ throw new ArgumentException("Position cannot be handled: "+resizeHandlePosition);
+
+ }
+ }
+
+ ///
+ /// Adjusts resizeHandleCoords so that aspect ratio is kept after resizing a given rectangle with provided arguments
+ ///
+ /// bounds of the current rectangle
+ /// position of the handle/gripper being used for resized, see Position
+ /// coordinates of the used handle/gripper, adjusted coordinates will be written to this reference
+ private static void adjustCoordsForRationalScale(RectangleF originalRectangle, Positions resizeHandlePosition, ref PointF resizeHandleCoords) {
+ float originalRatio = originalRectangle.Width / originalRectangle.Height;
+ float newWidth, newHeight, newRatio;
+ switch(resizeHandlePosition) {
+
+ case Positions.TopLeft:
+ newWidth = originalRectangle.Right - resizeHandleCoords.X;
+ newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
+ newRatio = newWidth / newHeight;
+ if(newRatio > originalRatio) { // FIXME
+ resizeHandleCoords.X = originalRectangle.Right - newHeight * originalRatio;
+ } else if(newRatio < originalRatio) {
+ resizeHandleCoords.Y = originalRectangle.Bottom - newWidth / originalRatio;
+ }
+ break;
+
+ case Positions.TopRight:
+ newWidth = resizeHandleCoords.X - originalRectangle.Left;
+ newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
+ newRatio = newWidth / newHeight;
+ if(newRatio > originalRatio) { // FIXME
+ resizeHandleCoords.X = newHeight * originalRatio + originalRectangle.Left;
+ } else if(newRatio < originalRatio) {
+ resizeHandleCoords.Y = originalRectangle.Bottom - newWidth / originalRatio;
+ }
+ break;
+
+ case Positions.BottomLeft:
+ newWidth = originalRectangle.Right - resizeHandleCoords.X;
+ newHeight = resizeHandleCoords.Y - originalRectangle.Top;
+ newRatio = newWidth / newHeight;
+ if(newRatio > originalRatio) {
+ resizeHandleCoords.X = originalRectangle.Right - newHeight * originalRatio;
+ } else if(newRatio < originalRatio) {
+ resizeHandleCoords.Y = newWidth / originalRatio + originalRectangle.Top;
+ }
+ break;
+
+ case Positions.BottomRight:
+ newWidth = resizeHandleCoords.X - originalRectangle.Left;
+ newHeight = resizeHandleCoords.Y - originalRectangle.Top;
+ newRatio = newWidth / newHeight;
+ if(newRatio > originalRatio) {
+ resizeHandleCoords.X = newHeight * originalRatio + originalRectangle.Left;
+ } else if(newRatio < originalRatio) {
+ resizeHandleCoords.Y = newWidth / originalRatio + originalRectangle.Top;
+ }
+ break;
+ }
+ }
+
+ public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize) {
+ Scale(boundsBeforeResize, cursorX, cursorY, ref boundsAfterResize, null);
+ }
+
+ public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
+
+ Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior);
+ }
+
+ public static void Scale(Rectangle boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
+
+ ScaleOptions opts = GetScaleOptions();
+
+ bool rationalScale = (opts & ScaleOptions.Rational) == ScaleOptions.Rational;
+ bool centeredScale = (opts & ScaleOptions.Centered) == ScaleOptions.Centered;
+
+ if(rationalScale) {
+ double angle = GeometryHelper.Angle2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY);
+
+ if(angleRoundBehavior != null) {
+ angle = angleRoundBehavior.Process(angle);
+ }
+
+ int dist = GeometryHelper.Distance2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY);
+
+ boundsAfterResize.Width = (int)Math.Round(dist * Math.Cos(angle / 180 * Math.PI));
+ boundsAfterResize.Height = (int)Math.Round(dist * Math.Sin(angle / 180 * Math.PI));
+ }
+
+ if(centeredScale) {
+ float wdiff = boundsAfterResize.Width - boundsBeforeResize.Width;
+ float hdiff = boundsAfterResize.Height - boundsBeforeResize.Height;
+ boundsAfterResize.Width += wdiff;
+ boundsAfterResize.Height += hdiff;
+ boundsAfterResize.X -= wdiff;
+ boundsAfterResize.Y -= hdiff;
+ }
+
+
+ }
+
+ /// the current ScaleOptions depending on modifier keys held down
+ public static ScaleOptions GetScaleOptions() {
+ bool anchorAtCenter = (Control.ModifierKeys & Keys.Control) != 0;
+ bool maintainAspectRatio = (Control.ModifierKeys & Keys.Shift) != 0;
+ ScaleOptions opts = ScaleOptions.Default;
+ if(anchorAtCenter) opts |= ScaleOptions.Centered;
+ if(maintainAspectRatio) opts |= ScaleOptions.Rational;
+ return opts;
+ }
+
+ public interface IDoubleProcessor {
+ double Process(double d);
+ }
+
+ public class ShapeAngleRoundBehavior : IDoubleProcessor {
+ public static ShapeAngleRoundBehavior Instance = new ShapeAngleRoundBehavior();
+ private ShapeAngleRoundBehavior() {}
+ public double Process(double angle) {
+ return Math.Round((angle+45)/90)*90 - 45;
+ }
+ }
+ public class LineAngleRoundBehavior : IDoubleProcessor {
+ public static LineAngleRoundBehavior Instance = new LineAngleRoundBehavior();
+ private LineAngleRoundBehavior() {}
+ public double Process(double angle) {
+ return Math.Round(angle/15)*15;
+ }
+ }
+ public class FixedAngleRoundBehavior : IDoubleProcessor {
+ private readonly double fixedAngle;
+ public FixedAngleRoundBehavior(double fixedAngle) {
+ this.fixedAngle = fixedAngle;
+ }
+ public double Process(double angle) {
+ return fixedAngle;
+ }
+ }
+
+
+
+
+
+ /*public static int FindGripperPostition(float anchorX, float anchorY, float gripperX, float gripperY) {
+ if(gripperY > anchorY) {
+ if(gripperX > anchorY) return Gripper.POSITION_BOTTOM_RIGHT;
+ else return Gripper.POSITION_BOTTOM_LEFT;
+ } else {
+ if(gripperX > anchorY) return Gripper.POSITION_TOP_RIGHT;
+ else return Gripper.POSITION_TOP_LEFT;
+ }
+ }*/
+
+ }
+}
+
\ No newline at end of file
diff --git a/Greenshot/Helpers/SoundHelper.cs b/Greenshot/Helpers/SoundHelper.cs
new file mode 100644
index 000000000..581a18051
--- /dev/null
+++ b/Greenshot/Helpers/SoundHelper.cs
@@ -0,0 +1,95 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using System.IO;
+
+using log4net;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Create to fix the sometimes wrongly played sample, especially after first start from IDE
+ /// See: http://www.codeproject.com/KB/audio-video/soundplayerbug.aspx?msg=2487569
+ ///
+ public static class SoundHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(SoundHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static GCHandle? _gcHandle;
+ private static byte[] _soundBuffer;
+
+ public static void Initialize() {
+ if (_gcHandle == null) {
+ try {
+ ResourceManager resources = new ResourceManager("Greenshot.Sounds", Assembly.GetExecutingAssembly());
+ _soundBuffer = (byte[])resources.GetObject("camera");
+
+ if (CoreConfig.NotificationSound != null && CoreConfig.NotificationSound.EndsWith(".wav")) {
+ try {
+ if (File.Exists(CoreConfig.NotificationSound)) {
+ _soundBuffer = File.ReadAllBytes(CoreConfig.NotificationSound);
+ }
+ } catch (Exception ex) {
+ Log.WarnFormat("couldn't load {0}: {1}", CoreConfig.NotificationSound, ex.Message);
+ }
+ }
+ // Pin sound so it can't be moved by the Garbage Collector, this was the cause for the bad sound
+ _gcHandle = GCHandle.Alloc(_soundBuffer, GCHandleType.Pinned);
+ } catch (Exception e) {
+ Log.Error("Error initializing.", e);
+ }
+ }
+ }
+
+ public static void Play() {
+ if (_soundBuffer != null) {
+ //Thread playSoundThread = new Thread(delegate() {
+ SoundFlags flags = SoundFlags.SND_ASYNC | SoundFlags.SND_MEMORY | SoundFlags.SND_NOWAIT | SoundFlags.SND_NOSTOP;
+ try {
+ if (_gcHandle != null) WinMM.PlaySound(_gcHandle.Value.AddrOfPinnedObject(), (UIntPtr)0, (uint)flags);
+ } catch (Exception e) {
+ Log.Error("Error in play.", e);
+ }
+ //});
+ //playSoundThread.Name = "Play camera sound";
+ //playSoundThread.IsBackground = true;
+ //playSoundThread.Start();
+ }
+ }
+
+ public static void Deinitialize() {
+ try {
+ if (_gcHandle != null) {
+ WinMM.PlaySound(null, (UIntPtr)0, 0);
+ _gcHandle.Value.Free();
+ _gcHandle = null;
+ }
+ } catch (Exception e) {
+ Log.Error("Error in deinitialize.", e);
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/StartupHelper.cs b/Greenshot/Helpers/StartupHelper.cs
new file mode 100644
index 000000000..4944d4dee
--- /dev/null
+++ b/Greenshot/Helpers/StartupHelper.cs
@@ -0,0 +1,258 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using log4net;
+using Microsoft.Win32;
+using System.IO;
+
+namespace Greenshot.Helpers {
+ ///
+ /// A helper class for the startup registry
+ ///
+ public static class StartupHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(StartupHelper));
+
+ private const string RunKey6432 = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run";
+ private const string RunKey = @"Software\Microsoft\Windows\CurrentVersion\Run";
+
+ private const string ApplicationName = "Greenshot";
+
+ private static string GetExecutablePath() {
+ return "\"" + Application.ExecutablePath + "\"";
+ }
+
+ ///
+ /// Return true if the current user can write the RUN key of the local machine.
+ ///
+ /// true if Greenshot can write key
+ public static bool CanWriteRunAll() {
+ try {
+ using (Registry.LocalMachine.OpenSubKey(RunKey, true))
+ {
+ }
+ } catch {
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Return true if the current user can write the RUN key of the current user.
+ ///
+ /// true if Greenshot can write key
+ public static bool CanWriteRunUser() {
+ try {
+ using (Registry.CurrentUser.OpenSubKey(RunKey, true))
+ {
+ }
+ } catch {
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Return the RUN key value of the local machine
+ ///
+ /// the RUN key value of the local machine
+ public static object GetRunAllValue()
+ {
+ using (var key = Registry.LocalMachine.OpenSubKey(RunKey, false))
+ {
+ object runValue = key?.GetValue(ApplicationName);
+ if (runValue != null)
+ {
+ return runValue;
+ }
+ }
+ // for 64-bit systems we need to check the 32-bit keys too
+ if (IntPtr.Size != 8)
+ {
+ return null;
+ }
+ using (var key = Registry.LocalMachine.OpenSubKey(RunKey6432, false))
+ {
+ object runValue = key?.GetValue(ApplicationName);
+ if (runValue != null)
+ {
+ return runValue;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Return the RUN key value of the current user
+ ///
+ /// the RUN key value of the current user
+ public static object GetRunUserValue() {
+ using (var key = Registry.CurrentUser.OpenSubKey(RunKey, false)) {
+ object runValue = key?.GetValue(ApplicationName);
+ if (runValue != null) {
+ return runValue;
+ }
+ }
+ // for 64-bit systems we need to check the 32-bit keys too
+ if (IntPtr.Size != 8)
+ {
+ return null;
+ }
+ using (var key = Registry.CurrentUser.OpenSubKey(RunKey6432, false)) {
+ object runValue = key?.GetValue(ApplicationName);
+ if (runValue != null) {
+ return runValue;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Return true if the local machine has a RUN entry for Greenshot
+ ///
+ /// true if there is a run key
+ public static bool HasRunAll() {
+ try {
+ return GetRunAllValue() != null;
+ } catch (Exception e) {
+ Log.Error("Error retrieving RunAllValue", e);
+ }
+ return false;
+ }
+
+ ///
+ /// Return true if the current user has a RUN entry for Greenshot
+ ///
+ /// true if there is a run key
+ public static bool HasRunUser() {
+ object runValue = null;
+ try {
+ runValue = GetRunUserValue();
+ } catch (Exception e) {
+ Log.Error("Error retrieving RunUserValue", e);
+ }
+ return runValue != null;
+ }
+
+ ///
+ /// Delete the RUN key for the localmachine ("ALL")
+ ///
+ public static void DeleteRunAll() {
+ if (!HasRunAll())
+ {
+ return;
+ }
+ try {
+ using (var key = Registry.LocalMachine.OpenSubKey(RunKey, true)) {
+ key?.DeleteValue(ApplicationName);
+ }
+ } catch (Exception e) {
+ Log.Error("Error in deleteRunAll.", e);
+ }
+ try
+ {
+ // for 64-bit systems we need to delete the 32-bit keys too
+ if (IntPtr.Size != 8)
+ {
+ return;
+ }
+ using (var key = Registry.LocalMachine.OpenSubKey(RunKey6432, false)) {
+ key?.DeleteValue(ApplicationName);
+ }
+ } catch (Exception e) {
+ Log.Error("Error in deleteRunAll.", e);
+ }
+ }
+
+ ///
+ /// Delete the RUN key for the current user
+ ///
+ public static void DeleteRunUser() {
+ if (!HasRunUser())
+ {
+ return;
+ }
+ try {
+ using (var key = Registry.CurrentUser.OpenSubKey(RunKey, true)) {
+ key?.DeleteValue(ApplicationName);
+ }
+ } catch (Exception e) {
+ Log.Error("Error in deleteRunUser.", e);
+ }
+ try
+ {
+ // for 64-bit systems we need to delete the 32-bit keys too
+ if (IntPtr.Size != 8)
+ {
+ return;
+ }
+ using (var key = Registry.CurrentUser.OpenSubKey(RunKey6432, false)) {
+ key?.DeleteValue(ApplicationName);
+ }
+ } catch (Exception e) {
+ Log.Error("Error in deleteRunUser.", e);
+ }
+ }
+
+ ///
+ /// Set the RUN key for the current user
+ ///
+ public static void SetRunUser() {
+ try {
+ using (var key = Registry.CurrentUser.OpenSubKey(RunKey, true))
+ {
+ key?.SetValue(ApplicationName, GetExecutablePath());
+ }
+ } catch (Exception e) {
+ Log.Error("Error in setRunUser.", e);
+ }
+ }
+
+ ///
+ /// Test if there is a link in the Statup folder
+ ///
+ ///
+ public static bool IsInStartupFolder() {
+ try {
+ string lnkName = Path.GetFileNameWithoutExtension(Application.ExecutablePath) + ".lnk";
+ string startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
+ if (Directory.Exists(startupPath)) {
+ Log.DebugFormat("Startup path: {0}", startupPath);
+ if (File.Exists(Path.Combine(startupPath, lnkName))) {
+ return true;
+ }
+ }
+ string startupAll = Environment.GetEnvironmentVariable("ALLUSERSPROFILE") + @"\Microsoft\Windows\Start Menu\Programs\Startup";
+ if (Directory.Exists(startupAll)) {
+ Log.DebugFormat("Startup all path: {0}", startupAll);
+ if (File.Exists(Path.Combine(startupAll, lnkName))) {
+ return true;
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ return false;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/ToolStripItemEndisabler.cs b/Greenshot/Helpers/ToolStripItemEndisabler.cs
new file mode 100644
index 000000000..dc62f4cc7
--- /dev/null
+++ b/Greenshot/Helpers/ToolStripItemEndisabler.cs
@@ -0,0 +1,96 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+
+namespace Greenshot.Helpers {
+ ///
+ /// Enables or disables toolstrip items, taking care of the hierarchy.
+ /// (parent) OwnerItems are ENabled with ToolStripItems,
+ /// (child) DropDownItems are ENabled and DISabled with ToolStripItems.
+ ///
+ public static class ToolStripItemEndisabler {
+ [Flags]
+ private enum PropagationMode {NONE=0, CHILDREN=1, ANCESTORS=2};
+
+ ///
+ /// Enables all of a ToolStrip's children (recursively),
+ /// but not the ToolStrip itself
+ ///
+ public static void Enable(ToolStrip ts) {
+ Endisable(ts, true, PropagationMode.CHILDREN);
+ }
+
+ ///
+ /// Disables all of a ToolStrip's children (recursively),
+ /// but not the ToolStrip itself
+ ///
+ public static void Disable(ToolStrip ts) {
+ Endisable(ts, false, PropagationMode.CHILDREN);
+ }
+
+ ///
+ /// Enables the ToolStripItem, including children (ToolStripDropDownItem)
+ /// and ancestor (OwnerItem)
+ ///
+ public static void Enable(ToolStripItem tsi) {
+ Endisable(tsi, true, PropagationMode.CHILDREN | PropagationMode.ANCESTORS);
+ }
+
+ ///
+ /// Disables the ToolStripItem, including children (ToolStripDropDownItem),
+ /// but NOT the ancestor (OwnerItem)
+ ///
+ public static void Disable(ToolStripItem tsi) {
+ Endisable(tsi, false, PropagationMode.CHILDREN);
+ }
+
+ private static void Endisable(ToolStrip ts, bool enable, PropagationMode mode){
+ if((mode & PropagationMode.CHILDREN) == PropagationMode.CHILDREN) {
+ foreach(ToolStripItem tsi in ts.Items) {
+ Endisable(tsi, enable, PropagationMode.CHILDREN);
+ }
+ }
+ }
+
+ private static void Endisable(ToolStripItem tsi, bool enable, PropagationMode mode){
+ if(tsi is ToolStripDropDownItem) {
+ Endisable(tsi as ToolStripDropDownItem, enable, mode);
+ } else {
+ tsi.Enabled = enable;
+ }
+ if((mode & PropagationMode.ANCESTORS) == PropagationMode.ANCESTORS) {
+ if(tsi.OwnerItem != null) Endisable(tsi.OwnerItem, enable, PropagationMode.ANCESTORS);
+ }
+
+ }
+
+ private static void Endisable(ToolStripDropDownItem tsddi, bool enable, PropagationMode mode) {
+
+ if((mode & PropagationMode.CHILDREN) == PropagationMode.CHILDREN) {
+ foreach(ToolStripItem tsi in tsddi.DropDownItems) {
+ Endisable(tsi, enable, PropagationMode.CHILDREN);
+ }
+ }
+ tsddi.Enabled = enable;
+ }
+ }
+}
diff --git a/Greenshot/Helpers/UpdateHelper.cs b/Greenshot/Helpers/UpdateHelper.cs
new file mode 100644
index 000000000..28c522c18
--- /dev/null
+++ b/Greenshot/Helpers/UpdateHelper.cs
@@ -0,0 +1,177 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Windows.Forms;
+
+using Greenshot.Configuration;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Experimental {
+ ///
+ /// Description of RssFeedHelper.
+ ///
+ public static class UpdateHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(UpdateHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private const string StableDownloadLink = "https://getgreenshot.org/downloads/";
+ private const string VersionHistoryLink = "https://getgreenshot.org/version-history/";
+ private static readonly object LockObject = new object();
+ private static RssFile _latestGreenshot;
+ private static string _downloadLink = StableDownloadLink;
+
+ ///
+ /// Is an update check needed?
+ ///
+ /// bool true if yes
+ public static bool IsUpdateCheckNeeded() {
+ lock (LockObject)
+ {
+ if (CoreConfig.UpdateCheckInterval == 0)
+ {
+ return false;
+ }
+ DateTime checkTime = CoreConfig.LastUpdateCheck;
+ checkTime = checkTime.AddDays(CoreConfig.UpdateCheckInterval);
+ if (DateTime.Now.CompareTo(checkTime) < 0)
+ {
+ Log.DebugFormat("No need to check RSS feed for updates, feed check will be after {0}", checkTime);
+ return false;
+ }
+ Log.DebugFormat("Update check is due, last check was {0} check needs to be made after {1} (which is one {2} later)", CoreConfig.LastUpdateCheck, checkTime, CoreConfig.UpdateCheckInterval);
+ if (!RssHelper.IsRssModifiedAfter(CoreConfig.LastUpdateCheck))
+ {
+ Log.DebugFormat("RSS feed has not been updated since after {0}", CoreConfig.LastUpdateCheck);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Read the RSS feed to see if there is a Greenshot update
+ ///
+ public static void CheckAndAskForUpdate() {
+ lock (LockObject) {
+ Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
+ // Test like this:
+ // currentVersion = new Version("0.8.1.1198");
+
+ try {
+ _latestGreenshot = null;
+ ProcessRssInfo(currentVersion);
+ if (_latestGreenshot != null) {
+ MainForm.Instance.NotifyIcon.BalloonTipClicked += HandleBalloonTipClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed += CleanupBalloonTipClick;
+ MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", Language.GetFormattedString(LangKey.update_found, "'" + _latestGreenshot.File + "'"), ToolTipIcon.Info);
+ }
+ CoreConfig.LastUpdateCheck = DateTime.Now;
+ } catch (Exception e) {
+ Log.Error("An error occured while checking for updates, the error will be ignored: ", e);
+ }
+ }
+ }
+
+ private static void CleanupBalloonTipClick(object sender, EventArgs e) {
+ MainForm.Instance.NotifyIcon.BalloonTipClicked -= HandleBalloonTipClick;
+ MainForm.Instance.NotifyIcon.BalloonTipClosed -= CleanupBalloonTipClick;
+ }
+
+ private static void HandleBalloonTipClick(object sender, EventArgs e) {
+ try {
+ if (_latestGreenshot != null) {
+ // "Direct" download link
+ // Process.Start(latestGreenshot.Link);
+ // Go to getgreenshot.org
+ Process.Start(_downloadLink);
+ }
+ } catch (Exception) {
+ MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, _downloadLink), Language.GetString(LangKey.error));
+ } finally {
+ CleanupBalloonTipClick(sender, e);
+ }
+ }
+
+ private static void ProcessRssInfo(Version currentVersion) {
+ // Reset latest Greenshot
+ IList rssFiles = RssHelper.ReadRss();
+
+ if (rssFiles == null) {
+ return;
+ }
+
+ // Retrieve the current and latest greenshot
+ foreach(RssFile rssFile in rssFiles) {
+ if (rssFile.File.StartsWith("Greenshot")) {
+ // check for exe
+ if (!rssFile.IsExe) {
+ continue;
+ }
+
+ // do we have a version?
+ if (rssFile.Version == null) {
+ Log.DebugFormat("Skipping unversioned exe {0} which is published at {1} : {2}", rssFile.File, rssFile.Pubdate.ToLocalTime(), rssFile.Link);
+ continue;
+ }
+
+ // if the file is unstable, we will skip it when:
+ // the current version is a release or release candidate AND check unstable is turned off.
+ if (rssFile.IsUnstable) {
+ // Skip if we shouldn't check unstables
+ if ((CoreConfig.BuildState == BuildStates.RELEASE) && !CoreConfig.CheckForUnstable) {
+ continue;
+ }
+ }
+
+ // if the file is a release candidate, we will skip it when:
+ // the current version is a release AND check unstable is turned off.
+ if (rssFile.IsReleaseCandidate) {
+ if (CoreConfig.BuildState == BuildStates.RELEASE && !CoreConfig.CheckForUnstable) {
+ continue;
+ }
+ }
+
+ // Compare versions
+ int versionCompare = rssFile.Version.CompareTo(currentVersion);
+ if (versionCompare > 0) {
+ Log.DebugFormat("Found newer Greenshot '{0}' with version {1} published at {2} : {3}", rssFile.File, rssFile.Version, rssFile.Pubdate.ToLocalTime(), rssFile.Link);
+ if (_latestGreenshot == null || rssFile.Version.CompareTo(_latestGreenshot.Version) > 0) {
+ _latestGreenshot = rssFile;
+ if (rssFile.IsReleaseCandidate || rssFile.IsUnstable) {
+ _downloadLink = VersionHistoryLink;
+ } else {
+ _downloadLink = StableDownloadLink;
+ }
+ }
+ } else if (versionCompare < 0) {
+ Log.DebugFormat("Skipping older greenshot with version {0}", rssFile.Version);
+ } else if (versionCompare == 0) {
+ Log.DebugFormat("Found current version as exe {0} with version {1} published at {2} : {3}", rssFile.File, rssFile.Version, rssFile.Pubdate.ToLocalTime(), rssFile.Link);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Greenshot/Helpers/WindowWrapper.cs b/Greenshot/Helpers/WindowWrapper.cs
new file mode 100644
index 000000000..63cb51e81
--- /dev/null
+++ b/Greenshot/Helpers/WindowWrapper.cs
@@ -0,0 +1,32 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+
+namespace Greenshot.Helpers {
+ public class WindowWrapper : IWin32Window {
+ public WindowWrapper(IntPtr handle) {
+ Handle = handle;
+ }
+
+ public IntPtr Handle { get; }
+ }
+}
diff --git a/src/Greenshot/Languages/help-de-DE.html b/Greenshot/Languages/help-de-DE.html
similarity index 94%
rename from src/Greenshot/Languages/help-de-DE.html
rename to Greenshot/Languages/help-de-DE.html
index 2f3754957..f2228ee42 100644
--- a/src/Greenshot/Languages/help-de-DE.html
+++ b/Greenshot/Languages/help-de-DE.html
@@ -76,7 +76,7 @@
Im Bereichsmodus können Sie einen Bildschirmbereich auswählen, der abfotografiert
werden soll.
Nach dem Starten des Bereichsmodus sehen Sie ein Fadenkreuz, das die Position
- des Mauszeigers auf dem Bildschirm anzeigt. Klicken und halten Sie die linke
+ des Mousezeigers auf dem Bildschirm anzeigt. Klicken und halten Sie die linke
Maustaste an der Stelle, an der eine der Ecken Ihres Screenshots liegen soll.
Halten Sie die Maustaste gedrückt, während Sie die Maus bewegen, um das Rechteck
zu markieren, von dem ein Screenshot erstellt werden soll. Wenn das grüne Rechteck
@@ -136,7 +136,7 @@
Verwendung des Bildeditors
- Greenshot bietet Ihnen ein einfaches Bildbearbeitungswerkzeug mit praktischen
+ Greenshot bietet Ihnen einen einfaches Bildbearbeitungswerkzeug mit praktischen
Möglichkeiten; ein Screenshot kann beispielsweise mit Anmerkungen und Formen
ergänzt werden. Es ist auch möglich, Teile des Screenshots hervorzuheben oder
unkenntlich zu machen.
@@ -149,8 +149,8 @@
Zwischenablage öffnen.
- Standardmäßig wird der Bildeditor immer geöffnet, wenn ein Screenshot
- gemacht wird. Wenn Sie den Bildeditor nicht verwenden wollen, können
+ Standardmäßig wird der Bildbearbeiter immer geöffnet, wenn ein Screenshot
+ gemacht wird. Wenn Sie den Bildbearbeiter nicht verwenden wollen, können
Sie dies in den Einstellungen deaktivieren.
@@ -302,7 +302,7 @@
Allgemeine Einstellungen
Sprache : Die Sprache, in der Sie Greenshot verwenden möchten.
- Hier können Sie weitere Sprachen für Greenshot herunterladen.
+ Hier können Sie weitere Sprachen für Greenshot herunterladen.
Greenshot mit Windows starten : Das Programm wird automatisch gestartet wenn das System hochfährt.
Tastenkombinationen : Konfigurieren Sie die Tastenkombinationen für das Erstellen von Screenshots
Standard-Proxyserver des Betriebssystems verwenden : Wenn ausgewählt, wird der im Betriebssystem eingetragene Standard-Proxyserver verwendet, um nach Updates zu suchen.
@@ -377,7 +377,7 @@
Spenden
- Wir stecken sehr viel Arbeit in Greenshot und verbringen einige Zeit damit, ein
+ Wir stecken sehr viel Arbeit in Greenshot oder verbringen einige Zeit damit, ein
gutes Programm kostenlos und quelloffen zur Verfügung zu stellen. Wenn Sie
merken, dass Greenshot Ihnen hilft, produktiver zu sein, wenn es Ihnen (oder
Ihrer Firma) viel Zeit und Geld spart, oder wenn Sie einfach Greenshot und die
@@ -385,7 +385,7 @@
Anerkennung durch eine Spende zukommen zu lassen.
Bitte werfen Sie einen Blick auf unsere Webseite, um zu sehen, wie Sie das
Greenshot Entwicker-Team unterstützen können:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -405,7 +405,7 @@
Wenn Sie registrierter Nutzer bei sourceforge.net sind, können Sie Übersetzungen
hier hochladen.
Bitte stellen Sie vorher sicher, dass keine Übersetzung für Ihre Sprache auf unserer
- Download-Seite existiert. Prüfen Sie auch hier , ob
+ Download-Seite existiert. Prüfen Sie auch hier , ob
evtl. eine Übersetzung in Arbeit oder in Vorbereitung ist.
Bitte bedenken Sie, dass wir eine Übersetzung nur auf unserer Download-Seite zur
Verfügung stellen werden, wenn Sie über ein Sourceforge.net-Benutzerkonto bereit gestellt
diff --git a/src/Greenshot/Languages/help-en-US.html b/Greenshot/Languages/help-en-US.html
similarity index 96%
rename from src/Greenshot/Languages/help-en-US.html
rename to Greenshot/Languages/help-en-US.html
index 9284bbeab..2d49ad719 100644
--- a/src/Greenshot/Languages/help-en-US.html
+++ b/Greenshot/Languages/help-en-US.html
@@ -332,7 +332,7 @@
General settings
Language : The language you prefer to be used.
- You can download additional language files for Greenshot here .
+ You can download additional language files for Greenshot here .
Launch Greenshot on startup : Start the program when the system has been booted.
Hotkeys : Customize the hotkeys to be used to create screenshots.
Use default system proxy : If checked, Greenshot uses the default system proxy to check for updates.
@@ -428,7 +428,7 @@
a lot of time and money, or if you simply like Greenshot and
the idea of open source software: please consider honoring our effort by donating.
Please have a look at our home page to see how you can support the Greenshot development team:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -447,7 +447,7 @@
If you are a registered user at sourceforge.net, you can submit translations to our
translations tracker .
Please make sure there is no existing translation for your language on our
- downloads page . Also check our translations tracker ,
+ downloads page . Also check our translations tracker ,
there might be a translation in progress, or at least in discussion.
Please note that we will only provide a translation on our downloads page if it has
been submitted through your sourceforge.net user account. Since we most probably are
diff --git a/src/Greenshot/Languages/help-es-ES.html b/Greenshot/Languages/help-es-ES.html
similarity index 97%
rename from src/Greenshot/Languages/help-es-ES.html
rename to Greenshot/Languages/help-es-ES.html
index fed8c6c94..e248bd90a 100644
--- a/src/Greenshot/Languages/help-es-ES.html
+++ b/Greenshot/Languages/help-es-ES.html
@@ -370,7 +370,7 @@
con una donación.
Por favor visite nuestra página web para ver como usted puede apoyar al
equipo de desarrollo de Greenshot:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
diff --git a/src/Greenshot/Languages/help-fr-FR.html b/Greenshot/Languages/help-fr-FR.html
similarity index 97%
rename from src/Greenshot/Languages/help-fr-FR.html
rename to Greenshot/Languages/help-fr-FR.html
index 751bb91ea..dc6fe3640 100644
--- a/src/Greenshot/Languages/help-fr-FR.html
+++ b/Greenshot/Languages/help-fr-FR.html
@@ -342,7 +342,7 @@
Langue : La langue que vous prfrez utiliser.
Vous pouvez tlcharger des fichiers de langues supplmentaires ici .
+ href="http://getgreenshot.org/downloads/">ici.
Lancer Greenshot au dmarrage de Windows : dmarrez le
programme lorsque le systme a t dmarr.
Raccourcis clavier : Personnaliser les raccourcis clavier
@@ -478,8 +478,8 @@
efforts en faisant un don.
Jetez un œil notre page d'accueil pour voir comment vous pouvez soutenir
l’quipe de dveloppement Greenshot :
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
Diffuser l’information
Si vous aimez Greenshot, faites le savoir autour de vous, vos amis et
@@ -494,7 +494,7 @@
soumettre votre traduction notre tracker
de traduction .
Assurez-vous qu’aucune traduction n’existe dans votre langue sur notre page de
+ target="_blank" href="http://getgreenshot.org/downloads/">page de
tlchargement . Vrifiez galement notre tracker
de traduction , pour vrifier qu’il n’y a aucune traduction en cours
ou en discussion.
diff --git a/src/Greenshot/Languages/help-hu-HU.html b/Greenshot/Languages/help-hu-HU.html
similarity index 96%
rename from src/Greenshot/Languages/help-hu-HU.html
rename to Greenshot/Languages/help-hu-HU.html
index 10792d048..5a9438813 100644
--- a/src/Greenshot/Languages/help-hu-HU.html
+++ b/Greenshot/Languages/help-hu-HU.html
@@ -235,7 +235,7 @@
ltalnos belltsok
Nyelv : A hasznlni kvnt nyelv kivlasztsa.
- Letlthet tovbbi nyelvi fjlokat a Greenshot oldalrl itt .
+ Letlthet tovbbi nyelvi fjlokat a Greenshot oldalrl itt .
Gyorsbillentyk hasznlata : Ha be van jellve, indthatod a Greenshot programot a Print + Scrn billentyvel.
Program indtsa a Windows indulsakor : a Greenshot program elindul Windows indulsakor.
Fnykpez vaku : Vizulis visszajelzs kpernykp ksztsekor.
@@ -279,7 +279,7 @@
vagy ha csak gy, szereted a Greenshot programot s ha van egy j tleted a programhoz,
krlek tartsd tiszteletben az erfesztsnket s fontold meg az adomnyozst.
Krjk tekintse meg honlapunkat, hogy hogyan tudn segteni a Greenshot fejleszti csapatot.:
- https://getgreenshot.org/?locale=default&page=support
+ http://getgreenshot.org/?locale=default&page=support
@@ -295,7 +295,7 @@
Greenshot nem rhet el a kvnt nyelvet? Ha gy rzi, fordtsa le a szoftvert s kldje el neknk, szvesen fogadjuk.
Ha n regisztrl a sourceforge.net -en fel tudja tlteni a fordtst a keresnkre .
- Krjk, gyzdjn meg rla, hogy nincs e ltez fordtsa az n nyelvt a letltsi oldalunkon .
+ Krjk, gyzdjn meg rla, hogy nincs e ltez fordtsa az n nyelvt a letltsi oldalunkon .
Nzze meg a keresnkben , hogy fordts nincs e folyamatban vagy elbrls alatt.
Felhvjuk figyelmt, hogy csak akkor tudjuk a fordtst elfogadni, ha a sourceforge.net -en sajt felhasznli fikjn keresztl tlti fel.
Nagy valsznsggel nem rtjk meg az n fordtst, j esetben a tbbi soundforge felhasznl elri az n fejlesztst
diff --git a/Greenshot/Languages/help-it-IT.html b/Greenshot/Languages/help-it-IT.html
new file mode 100644
index 000000000..1d5744287
--- /dev/null
+++ b/Greenshot/Languages/help-it-IT.html
@@ -0,0 +1,395 @@
+
+
+
+
+ Guida in linea di Greenshot
+
+
+
+
+ Guida in linea di Greenshot
+
+ Versione 0.8
+
+ Contenuti
+
+ Creazione immagine dello schermo
+
+ Cattura regione
+ Cattura ultima regione
+ Cattura finestra
+ Cattura schermo intero
+ Cattura Internet Explorer
+
+
+ Uso della Gestione Immagini
+
+ Disegnare forme
+ Aggiungere testo
+ Evidenziare qualcosa
+ Offuscare qualcosa
+ Ritagliare l'immagine
+ Aggiungere elementi grafici all'immagine
+ Riutilizzare gli elementi disegnati
+ Esportare l'immagine
+
+ La pagina delle Impostazioni
+
+ Impostazioni Generali
+ Impostazioni di Cattura
+ Impostazioni di Emissione
+ Impostazioni Stampante
+
+ Vuoi aiutarci?
+
+ Considera una donazione
+ Spargi la parola
+ Invia una traduzione
+
+
+
+
+ Creazione immagine dello schermo
+
+ L'immagine può essere creata utilizzando il tasto Stamp della tastiera,
+ oppure cliccando il tasto destro del mouse sull'icona di Greenshot nella barra.
+ Ci sono varie opzioni per creare un'immagine:
+
+
+
+ Cattura regione Stamp
+
+ Il metodo cattura regione consente di selezionare una parte dello schermo da "fotografare".
+ Dopo aver avviato il metodo regione, apparirà un mirino sulla posizione del mouse sullo
+ schermo. Cliccare e tenere premuto dove si vuole impostare un angolo della regione da
+ fotografare. Tenendo premuto il pulsante del mouse, muovere il mouse fino a definire il
+ rettangolo da fotografare. Rilasciare quindi il pulsante quando il rettangolo verde avrà
+ coperto l'area da catturare nell'immagine.
+
+
+ Si può usare il tasto Spazio per cambiare da metodo regione a metodo
+ finestra .
+
+
+ Se si vuol catturare precisamente un'area, potrebbe risultare più facile selezionare
+ un'area più grande e quindi ritagliare l'immagine in
+ seguito, utilizzando la Gestione Immagini di Greenshot.
+
+
+
+ Cattura ultima regione Maiusc + Stamp
+
+ Usando questa opzione, se avete già eseguito un cattura regione o finestra ,
+ si può ricatturare automaticamente la stessa regione.
+
+
+
+ Cattura finestra Alt + Stamp
+
+ Crea un'immagine della finestra che è attiva in quel momento.
+
+
+ La pagina delle impostazioni offre una possibilità per non catturare
+ direttamente la finestra attiva, consentendo quindi di sceglierne una interattivamente.
+ Se si seleziona questa opzione, la finestra può essere scelta cliccandovi (come nel metodo
+ regione , Greenshot evidenzierà l'area che verrà catturata).
+ Se si vuol catturare una finestra figlia (es: una browser
+ viewport (senza barra strumenti, ecc...) o un singolo frame di una pagina web che usa i framesets)
+ si può puntare il cursore del mouse sulla finestra e premere il tasto PgDown . Dopo di questo, sarà
+ possibile selezionare elementi da catturare nella finestra figlia.
+
+
+
+ Cattura schermo intero Ctrl + Stamp
+
+ Crea un'immagine dell'intero schermo.
+
+
Cattura Internet Explorer Ctrl + Maiusc + Stamp
+
+ Crea facilmente un'immagine della pagina web attiva in quel momento su Internet Explorer.
+ Si può usare il menu sensibile al contesto di Greenshot per selezionare la tab di Internet Explorer da catturare, oppure premere
+ Crtl + Maiusc + Stamp per catturare la tab attiva.
+
+
+
+ Uso della Gestione Immagini
+
+ Greenshot fornisce anche una pratica gestione delle immagini, che include degli utili strumenti
+ per aggiungere note e forme alle immagini. Essa permette inoltre di evidenziare o
+ offuscare parti dell'immagine.
+
+
+ La Gestioni Immagini di Greenshot non è solo per le immagini catturate. Si può usare
+ anche per aprire e modificare immagini da file o da Appunti. E' sufficiente premere il tasto destro
+ sull'icona di Greenshot nella barra, e selezionare rispettivamente Apri immagine da file
+ o Apri immagine da Appunti .
+
+
+ Come default, la gestione immagini verrà aperta ogniqualvolta un'immagine viene catturata.
+ Se non si vuole passare per la gestione immagini, si può disabilitare questo funzionamento
+ nella pagina delle impostazioni .
+
+
+
+
+ Disegnare forme
+
+ Selezionare uno degli strumenti di disegno dalla barra degli strumenti sul lato sinistro
+ della gestione immagini o dal menù Oggetti . Per facilitarne la selezione, ciascun
+ strumento è assegnato ad un tasto.
+ Le forme disponibili sono: rettangolo R , ellisse E , linea L
+ e freccia A .
+ Cliccare, tenendo premuto il pulsante del mouse e trascinare per definire la posizione e la dimensione della forma.
+ Completata la definizione, rilasciare il pulsante del mouse.
+
+
+ Le forme possono essere mosse e ridimensionate facilmente, previa selezione mediante lo strumento
+ ESC disponibile nella barra a sinistra. Per ciascun tipo di elemento c'è un gruppo di
+ opzioni specifiche per cambiarne l'aspetto (es: spessore linea,
+ colore linea, colore di riempimento). Si possono modificare le opzioni di un elemento esistente, previa selezione,
+ e anche quelle di nuovi elementi da disegnare, previa selezione dello strumento di disegno.
+
+
+ Si possono inoltre selezionare più elementi per una modifica simultanea. Per selezionare più elementi,
+ tenere premuto il tasto Maiusc mentre si clicca sugli elementi.
+
+
+
+ Aggiungere testo
+
+ L'uso dello strumento di testo T è simile all'uso degli strumenti di disegno
+ forme . E' sufficiente disegnare l'elemento di testo delle dimensioni desiderate,
+ e quindi digitare il testo.
+ Per modificare il testo di un elemento esistente, premere il doppio click sull'elemento.
+
+
+
+ Evidenziare qualcosa
+
+ Dopo aver selezionato lo strumento di evidenziazione H , definire l'area da evidenziare esattamente
+ come si volesse disegnare una forma .
+ Ci sono varie opzioni per evidenziare, esse possono essere selezionate cliccando il pulsante
+ più in alto a sinistra nella barra degli strumenti:
+
+
+ Evidenzia il testo : evidenzia un'area applicando un colore brillante ad essa, come un
+ pennarello evidenziatore
+ Evidenzia l'area : sfuoca* e scurisce tutto all'esterno dell'area selezionata
+ Scala di grigi : tutto ciò che è al di fuori dell'area selezionata viene trasformato in scala di grigi
+ Ingrandisci : l'area selezionata verrà visualizzata come ingrandita da una lente
+
+
+
+ Offuscare qualcosa
+
+ Offuscare parti di un'immagine può essere una buona idea se essa contiene dati privati che non devono essere
+ visti da altre persone, per esempio dati conto bancario, nomi, parole d'ordine o volti di persone.
+ Usare lo strumento di offuscamento O esattamente come lo strumento di evidenziazione .
+ Le opzioni disponibili per l'offuscamento, sono:
+
+
+ Offusca/pixelize : aumenta le dimensioni dei pixel nell'area selezionata
+ Sfuma * : sfuma e sfuoca l'area selezionata
+
+
+
+ * A seconda delle prestazioni del proprio PC, applicare un effetto di sfumatura potrebbe rallentare la Gestione
+ Immagini di Greenshot. Se si vede che la Gestione Immagini risponde lentamente subito dopo aver eseguito una sfumatura,
+ è utile provare a ridurre il valore di Qualità anteprima nella barra strumenti di offuscamento,
+ o a diminuire il valore di Raggio sfumatura .
+ Se le prestazioni della sfumatura sono ancora deludenti per poterci lavorare, si consiglia si usare invece
+ l'effetto Offusca/pixelize.
+
+
+
+ Ritagliare l'immagine
+
+ Per ricavare solo una parte dell'immagine catturata, si può usare lo strumento di ritaglio C
+ per ritagliare l'area desiderata.
+ Dopo aver selezionato lo strumento di ritaglio, disegnare un rettangolo per l'area che si vuole mantenere.
+ Come per gli atri elementi, si possono facilmente modificare le dimensioni dell'area selezionata.
+ Dopo aver impostato correttamente la selezione dell'area, premere il pulsante di conferma della barra strumenti
+ oppure premere il tasto Invio . Si può annullare l'azione di ritaglio, cliccando il pulsante di cancellazione o premendo
+ ESC .
+
+
+ Ritaglia Automaticamente : Se si ha la necessità di ritagliare un pezzo dell'immagine lungo i bordi di uno sfondo con colore compatto,
+ è sufficiente scegliere Ritaglia Automaticamente dal menù Modifica e Greenshot automaticamente
+ selezionerà l'area di ritaglio.
+
+
+
+ Aggiunta elementi grafici all'immagine
+
+ Si possono facilmente aggiungere degli elementi grafici o delle altre immagini alla immagine in lavorazione, è sufficiente trascinare un file di immagine
+ all'interno della finestra di gestione immagini. Inoltre, selezionando Inserisci finestra dal menù Modifica , si possono inserire
+ immagini prese da altre finestre. In questo caso, appare una lista con tutte le finestre aperte, consentendo quindi di scegliere quella che si
+ vuole inserire.
+
+
+
+
+ Ri-utilizzare elementi disegnati
+
+ Se ci si ritrova a utilizzare lo stesso o simile elemento nella maggior parte delle immagini,
+ (es: campo di testo contenente tipo browser e versione, oppure offuscamento dello stesso elemento
+ su più immagini), è possibile riutilizzare gli elementi in modo semplice.
+ Selezionare Salva oggetti su file dal menù Oggetti per salvare di elementi correnti
+ per poterli riutilizzare poi. Carica oggetti da file viene invece usato per applicare su un'altra immagine
+ gli elementi salvati in precedenza.
+
+
+
+ Esportare l'immagine
+
+ Dopo aver modificato l'immagine, si può esportare il risultato per vari scopi, a seconda delle necessità.
+ Si può accedere a tutte le opzioni di esportazione mediante il menù File ,
+ sulla barra principale, o per mezzo delle seguenti scorciatoie:
+
+
+ Salva Ctrl + S : salva l'immagine su un file (se l'immagine è già stata salvata, altrimenti emette la finestra di Salva come... )
+ Salva come... Ctrl + Maiusc + S : permette di scegliere la destinazione, il nome file e il formato immagine per il file da salvare
+ Copia immagine sugli appunti Ctrl + Maiusc + C : mette una copia dell'immagine sugli appunti, consentendo poi di incollarla dentro altri programmi
+ Stampa... Ctrl + P : invia l'immagine a una stampante
+ E-Mail Ctrl + E : apre un nuovo messaggio sul programma di e-mail di default, aggiungendo l'immagine come allegato
+
+
+ Dopo aver salvato un'immagine dalla gestione, cliccando con il tasto destro del mouse sulla barra di stato in basso sulla finestra
+ della gestione immagini, è possibile copiare il percorso sugli appunti, oppure aprire la cartella di destinazione con la gestione risorse.
+
+
+
+
+ Le Preferenze
+
+
+ Impostazioni Generali
+
+ Lingua : La lingua che si preferisce usare.
+ Si possono scaricare i file per le lingue aggiuntive di Greenshot qui .
+ Lancia Greenshot all'avvio : Avvia il programma in automatico all'accensione del sistema.
+ Scorciatoie di tastiera : Personalizza le scorciatoie (hotkeys) da usare per catturare le immagini.
+ Usa il proxy di default del sistema : Se selezionato, Greenshot usa il proxy di default del sistema per controllare se ci sono aggiornamenti.
+ Intervallo di controllo aggiornamento, in giorni : Greenshot può controllare automaticamente se ci sono aggiornamenti. Questo parametro può essere
+ utilizzato per specificare l'intervallo (in giorni); per disabilitare il controllo aggiornamento si può usare il valore 0.
+
+
+
+ Impostazioni di Cattura
+
+ Cattura puntatore mouse : Se selezionato, il puntatore del mouse verrà catturato. Il puntatore viene gestito come un elemento separato, in modo che possa essere spostato o rimosso in seguito.
+ Emetti suono fotocamera : Attiva il riscontro udibile dell'azione di cattura (suono dello scatto fotografico).
+ Millisecondi di attesa prima di catturare : Utile per aggiungere un tempo di ritardo prima dell'effettiva cattura dello schermo.
+ Usa la modalità di cattura via finestra interattiva : Invece di catturare direttamente la finestra attiva, la modalità interattiva
+ consente di selezionare la finestra da catturare. E' inoltre possibile catturare le finestre figlie, vedi Cattura finestra .
+
+ Cattura in stile Aero (so Windows Vista / 7) : Se si sta usando Greenshot su Windows Vista or Windows 7 con lo stile di visualizzazione Aero abilitato, è possibile
+ scegliere come devono essere gestiti i bordi della finestra trasparente quando vengono create le immagini in modalità finestra. Questa impostazione è da usare per evitare
+ la cattura di elementi dello sfondo che appaiono attraverso i bordi trasparenti.
+
+ Automaticamente : Greenshot deciderà come gestire la trasparenza.
+ Come visualizzata : I bordi trasparenti verranno catturati come visualizzati sullo schermo.
+ Usa i colori di default : Al posto della trasparenza verrà applicato un colore compatto di default.
+ Usa colori personalizzati : Si può scegliere il colore che sarà applicato al posto della trasparenza.
+ Conserva la trasparenza : I bordi verranno catturati conservando la trasparenza, senza però catturare gli elementi che potrebbero essere sullo sfondo. (Nota: le aree
+ trasparenti verrano visualizzate usando un modello selezionato nella gestione immagini. Il modello non verrà esportato se si salverà l'immagine su file. Ricordarsi di salvare
+ il file come PNG se si vuole conservance il pieno supporto della trasparenza.)
+
+
+ Cattura Internet Explorer : Abilita la comoda cattura delle pagine web utilizzando Internet Explorer.
+ Adatta finestra Gestione a dimensioni di cattura : Se selezionata, la finestra della Gestione immagini verrà automaticamente ridimensionata in base alla dimensione dell'immagine catturata.
+
+
+
+ Impostazioni di Emissione
+
+ Destinazione dell'immagine : Consente di scegliere la destinazione/i automatiche delle immagini subito dopo l'azione di cattura.
+ Impostazioni Preferite per l'Emissione File : Cartella e nome file da usare quando si salva automaticamente, o da suggerire quando si salva (usando la finestra "Salva come"). Cliccare il pulsante ? per sapere di più sulle variabili che possono essere usate nel modello del nome file.
+ Impostazioni JPEG : Qualità da usare quando si salvano file JPEG.
+
+
+
+ Impostazioni Stampante
+
+ Riduci alle dimensioni pagina : Se l'immagine eccede le dimensioni della pagina, essa verrà ridotta e adattata alle dimensioni della pagina.
+ Ingrandisci fino alle dimensioni pagina : Se l'immagine è più piccola delle dimensioni della pagina, essa verrà ingrandita per stamparla più grande possibile senza superare le dimensioni della pagina.
+ Ruota a seconda dell'orientamento pagina : Ruoterà l'immagine in formato orizzontale di 90° per la stampa.
+ Centra nella pagina : L'immagine verrà stampata al centro della pagina.
+ Stampa data / ora sul piede della pagina : La data e l'ora di stampa verranno stampati sul piede della pagina.
+ Stampa con colori inverititi (negativo) : Trasformerà l'immagine in negativo prima di stamparla, utile per esempio quando si stampa un'immagine con testo bianco su sfondo nero (per risparmiare toner o inchiostro).
+ Visualizza scelta opzioni di stampa ogni volta che si stampa un'immagine : Permette di scegliere se visualizzare o meno la finestra di scelta opzioni per le stampe successive alla prima.
+
+
+
+ Impostazioni Componenti Aggiuntivi
+
+ Visualizza la lista dei componenti aggiuntivi di Greenshot che sono attualmente installati. La configurazione del singolo componente aggiuntivo è disponibile selezionando
+ il componente dalla lista e quindi cliccando su Configura .
+
+
+
+
+ Desideri aiutarci?
+
+
+ Attualmente non abbiamo bisogno di aiuto per lo sviluppo. Tuttavia, ci sono molte cose che puoi fare per
+ supportare Greenshot e il team di sviluppo.
+ Grazie anticipatamente :)
+
+
+
+ Considera una donazione
+
+ Stiamo lavorando molto su Greenshot e stiamo spendendo molto tempo per fornire
+ un buon prodotto software gratuito e open source. Se ti sei reso conto che Greenshot
+ ti ha reso più produttivo, e se fa risparmiare a te (o alla tua società)
+ molto tempo e denaro, o se semplicemente ti piace Greenshot e l'idea
+ di software open source: per cortesia, considera di onorare i nostri sforzi con una donazione.
+ Per cortesia dai un'occhiata alla nostra home page per vedere come puoi aiutare il team di sviluppo di Greenshot:
+ http://getgreenshot.org/support/
+
+
+
+ Spargi la parola
+
+ Se ti piace Greenshot, fallo sapere anche agli altri: racconta ai tuoi amici di Greenshot.
+ Anche loro, a loro volta :)
+ Commenta positivamente Greenshot sui portali di software, oppure metti un link sulla tua home page, blog o sito web.
+
+
+
+ Invia una traduzione
+
+ Greenshot non è disponibile nella tua lingua preferita? Se ti senti in grado di tradurre un pezzo di software,
+ sei più che benvenuto.
+ Se sei un utente registrato su sourceforge.net, puoi inviare le traduzioni al nostro
+ translations tracker .
+ Prima di farlo, assicurati che non esista già la traduzione sulla nostra
+ pagina di download . Controlla anche il nostro translations tracker ,
+ ci potrebbe essere una traduzione in lavorazione, o almeno in discussione.
+ Ti preghiamo di notare che forniremo una traduzione della nostra pagina di download solo se è stata inviata mediante
+ il tuo conto utente su sourceforge.net. Visto che molto probabilmente non siamo in grado di capire la traduzione, è opportuno
+ che gli altri utenti di sourceforge possano essere in grado di contattarti per revisioni o miglioramenti
+ in caso di nuove versioni di Greenshot.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/help-ko-KR.html b/Greenshot/Languages/help-ko-KR.html
similarity index 96%
rename from src/Greenshot/Languages/help-ko-KR.html
rename to Greenshot/Languages/help-ko-KR.html
index 4b5951125..907b75a6e 100644
--- a/src/Greenshot/Languages/help-ko-KR.html
+++ b/Greenshot/Languages/help-ko-KR.html
@@ -263,7 +263,7 @@
일반 설정
사용 언어 : 사용자가 사용할 언어.
- 사용할 각국 GreenShot 언어를 다운 받는 곳은 이 곳을 누르세요 .
+ 사용할 각국 GreenShot 언어를 다운 받는 곳은 이 곳을 누르세요 .
윈도우 구동시 Greenshot 실행 : 윈도우를 처음 구동시 GreenShot 프로그램이 자동을 실행됩니다.
단축키 : 이미지를 생성하기 위하여 사용되는 단축키를 지정합니다.
기본 시스템 프록시 사용 : 체크되었을 경우 업데이트를 위한 체크시 기본 시스템 프록시를 사용합니다.
@@ -346,7 +346,7 @@
우리는 GreenShot에 많은 수고를 하고 있으며 무료이며 오픈 소스인 좋은 프로그램 제작에 많은 시간을 할애하고 있습니다.
여러분이 더 생산적으로 만들고자 한다면 또는 여러분이나 여러분 회사가 많은 시간과 돈을 절약하고자 한다면, 그리고 GreenShot과 오픈소스 소프트웨어를 좋아하신다면 기부로서 우리의 노력에 대한 도움을 부탁드립니다.
GreenShot 개발팀 지원을 하기 위한 방법은 아래 언급된 GreenShot 홈페이지를 방문해주시기 바랍니다:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -359,10 +359,10 @@
언어 번역 소개
- Greenshot에 사용할 언어가 없습니까? 사용할 언어를 넣고 싶다면 반가운 일입니다. https://sourceforge.net에 사용자등록이 되어 있다면 GreenShot 번역 상황 에서 번역을 할 수 있습니다.
- GreenShot 다운로드 페이지 에서 사용할 언어 번역이 없는지 먼저 확인하세요. 다음으로 GreenShot 번역 상황 을 체크해보세요,
+ Greenshot에 사용할 언어가 없습니까? 사용할 언어를 넣고 싶다면 반가운 일입니다. http://sourceforge.net에 사용자등록이 되어 있다면 GreenShot 번역 상황 에서 번역을 할 수 있습니다.
+ GreenShot 다운로드 페이지 에서 사용할 언어 번역이 없는지 먼저 확인하세요. 다음으로 GreenShot 번역 상황 을 체크해보세요,
진행 중인 번역이 있거나 또는 최소 논의 중인 것이 있을 수 있습니다.
- https://sourceforge.net 사용자 계정을 통해 등록된 언어파일만 다운로드 페이지를 통한 번역만을 제공함을 유의하시기 바랍니다.
+ http://sourceforge.net 사용자 계정을 통해 등록된 언어파일만 다운로드 페이지를 통한 번역만을 제공함을 유의하시기 바랍니다.
당신의 언어 번역본을 이해할 수 없을 때 새 Greenshot 버전일 경우에 개선하기 위하여 다른 사용자가 여러분과 연락할 수 있습니다.
diff --git a/src/Greenshot/Languages/help-nl-NL.html b/Greenshot/Languages/help-nl-NL.html
similarity index 92%
rename from src/Greenshot/Languages/help-nl-NL.html
rename to Greenshot/Languages/help-nl-NL.html
index 999bca3cc..236d2f304 100644
--- a/src/Greenshot/Languages/help-nl-NL.html
+++ b/Greenshot/Languages/help-nl-NL.html
@@ -69,14 +69,14 @@
Een schermopname maken
U kunt een schermopname maken door op uw toetsenbord de Print -toets te drukken of
- door middel van een rechtermuisklik op het Greenshot-icoon in het systeemvak.
+ door middel van een rechtermuisklik op het Greenshot-icoon in het systeemvak.
Er zijn meerdere mogelijkheden om een schermopname te maken:
Interactief kader Print
- Deze "regio"-opnamemodus maakt het mogelijk om een gebied van het beeldscherm te selecteren voor een schermopname.
+ Deze "regio"-opnamemodus maakt het mogelijk om een gebied van het beeldscherm te selecteren voor een schermopname.
Bij het vastleggen van het opnamegebied verandert de mouse-cursor in een haarkruis.
Positioneer de muis naar een hoek van het gebied waarvan u een schermopname wilt maken en
druk op de linkermuisknop en houd deze ingedrukt. Beweeg nu de muis naar de diagonale hoek
@@ -115,7 +115,7 @@
het actieve venster te fotograferen, maar een venster interactief te selecteren.
Als deze optie geactiveerd is, kunt u een venster selecteren door het te klikken. Net als bij
Interactief kader , zal Greenshot het te fotograferen
- gebied markeren. Wilt u een deelvenster fotograferen, zoals bijv. een browservenster
+ gebied markeren. Wilt u een deelvenster fotograferen, zoals bijv. een browservenster
zonder menu of gereedschapsbalk of een enkel onderdeel in een webpagina,
positioneer dan de muis over het deelvenster en druk de Page Down -toets. Hierna
kunt u de specifieke vensterelementen selecteren voor de schermopname.
@@ -168,15 +168,15 @@
Kies een van de vormen in de gereedschapsbalk aan de linkerzijde van de beeldbewerker
of van het menu Object . Aan elke toets is tevens een sneltoets gekoppeld
- voor snelle toegang via het toetsenbord.
+ voor snelle toegang via het toetsenbord.
Beschikbare vormen zijn: rechthoek R , ellips E , lijn L
- pijl A en vrije vorm F .
+ pijl A en vrije vorm F .
Klik en sleep de muis om de positie en de grootte van de vorm te bepalen.
Laat de muisknop los als de vorm van de juiste afmetingen is.
Getekende vormen kunnen worden verplaatst en vergroot met behulp van de knop Selectie
- ESC op de gereedschapsbalk. Voor elk vormtype zijn specifieke
+ ESC op de gereedschapsbalk.Voor elk vormtype zijn specifieke
opties beschikbaar om de karakteristieken aan te passen (bijv. lijndikte,
lijnkleur, vulkleur). U kunt het uiterlijk veranderen voor een bestaand geselecteerd object,
maar u kunt ook de eigenschappen instellen voor de volgende te tekenen vorm.
@@ -188,7 +188,7 @@
Wilt u een symmetrische vorm tekenen (bijv. een vierkant of een cirkel)? Houd dan tijdens het tekenen
de Shift -toets ingedrukt. Bij het tekenen van pijlen, beperkt de Shift -toets
- de mogelijke hoeken tot veelvouden van 15°.
+ de mogelijke hoeken tot veelvouden van 15°.
Bij het vergroten van een bestaand object zorgt de Shift -toets ervoor dat de verhoudingen behouden blijven.
@@ -202,8 +202,8 @@
Het gebruik van de Tekst-functie T is vergelijkbaar met dat van
Vormen toevoegen. Plaats een tekstkader van de gewenste grootte
- en typ de tekst.
- Dubbelklik een bestaande tekst om deze te bewerken.
+ en typ de tekst.
+ Dubbelklik een bestaande tekst om deze te bewerken.
Gebruik Return of Enter als u klaar bent met bewerken.
@@ -215,7 +215,7 @@
Markeren
Met de Markeer-functie H , kunt u een gebied markeren op precies dezelfde wijze
- als waarmee u een vorm shape tekent.
+ als waarmee u een vorm shape tekent.
De volgende opties bij het markeren zijn beschilbaar via de meest linkse knop
in de gereedschapsbalk:
@@ -231,8 +231,8 @@
Maskeren
Delen van een schermopname maskeren is een goed gebruik wanneer persoonlijke gegevens in beeld zijn
- die beter privé kunnen blijven, zoals bijv. bankgegevens, namen, wachtwoorden of herkenbare personen.
- De functie Maskeren O gebruikt u net als het Markeren .
+ die beter privé kunnen blijven, zoals bijv. bankgegevens, namen, wachtwoorden of herkenbare personen.
+ De functie Maskeren O gebruikt u net als het Markeren .
Beschikbare opties voor Maskeren zijn:
@@ -245,7 +245,7 @@
* Afhankelijk van uw computer kan het vervagingseffect de werking van Greenshot's beeldbewerker
trager maken. Merkt u dat de beeldbewerker bij de toepassing van Vervagen traag en sloom wordt,
probeer dan de kwaliteit van de voorvertoning in de gereedschapsbalk te verminderen of
- verlaag de waarde voor de Vervagings-radius .
+ verlaag de waarde voor de Vervagings-radius .
Blijft de functie Vervagen traag reageren, probeer dan de functie Pixeleren te gebuiken.
@@ -262,9 +262,9 @@
Schermopname bijsnijden
Als u maar een deel van de schermopname nodig hebt, gebruik dan de functie bijsnijden C
- om overtollige delen weg te snijden.
+ om overtollige delen weg te snijden.
Teken hiertoe een rechthoek om het gebied van de schermopname dat behouden moet worden.
- U kunt de afmetingen van het geselecteerde gebied naar wens aanpassen.
+ U kunt de afmetingen van het geselecteerde gebied naar wens aanpassen.
Bent u tevreden over het geselecteerde gebied, bevestig het bijsnijden dan in de gereedschapsbalk of toets Enter .
U kunt het bijsnijden afbreken met de toets ESC .
@@ -294,7 +294,7 @@
Als u regelmatig dezelfde elementen toepast in de bewerking van uw schermopnamen
(bijv. een tekstkader met browsertype en versienummer, of het maskeren van hetzelfde
- element in verschillende schermopnamen) dan kunt u deze elementen hergebruiken.
+ element in verschillende schermopnamen) dan kunt u deze elementen hergebruiken.
Kies in het menu Objecten , Objecten opslaan om de huidige elementen op te slaan
voor later gebruik. Objecten laden past deze eerder opgeslagen elementen toe
op een andere schermopname.
@@ -331,8 +331,8 @@
Algemene instellingen
- Taal : De taal waarin Greenshot wordt weergegeven.
- Aanvullende taalbestanden zijn te downloaden van de Greenshot website .
+ Taal : De taal waarin Greenshot wordt weergegeven.
+ Aanvullende taalbestanden zijn te downloaden van de Greenshot website .
Greenshot met Windows opstarten : Start het programma als de PC wordt opgestart.
Sneltoetsen : Hier kunt u de sneltoetsen voor het maken van schermopnames aanpassen.
Standaard systeem-proxy gebruiken : Greenshot gebruikt de systeem-proxy instelllingen bij het zoeken naar updates.
@@ -414,7 +414,7 @@
Op dit moment zoeken we geen hulp bij de ontwikkeling.
- Maar dit betekent niet dat u niets kunt doen om het Greenshot ontwikkelteam te ondersteunen.
+ Maar dit betekent niet dat u niets kunt doen om het Greenshot ontwikkelteam te ondersteunen.
Bij voorbaat dank :)
@@ -425,16 +425,16 @@
goede software gratis en vrij toegankelijk te houden. Als Greenshot
u helpt in uw werkzaamheden, als het u (of uw bedrijf)
tijd en geld bespaart, of u vindt het gewoon een fijn programma en
- u staat positief tegenover het concept van open source software: Ondersteun ons werk dan met een donatie.
- Bezoek onze website en lees daar hoe u het Greenshot-team kunt ondersteunen:
- https://getgreenshot.org/support/
+ u staat positief tegenover het concept van open source software: Ondersteun ons werk dan met een donatie.
+ Bezoek onze website en lees daar hoe u het Greenshot-team kunt ondersteunen:
+ http://getgreenshot.org/support/
Vertel het door
Bevalt Greenshot u? Vertel het dan door: vertel uw vrienden en collega's over Greenshot.
- En ook uw aanhang en achterban ! :)
+ En ook uw aanhang en achterban ! :)
Bespreek Greenshot met goede kritieken op software portals of plaats een verwijzing naar Greenshot in uw blog of op uw website.
@@ -443,10 +443,10 @@
Is Greenshot niet beschikbaar in uw favoriete taal en u denkt dat u software kunt vertalen dan bent u van harte welkom!
Als geregisteerde gebruiker bij sourceforge.net kunt u uw vertaling in onze
- vertalings tracker aanmelden.
+ vertalings tracker aanmelden.
Voordat u begint is het verstandig om te kijken of Greenshot niet al in de taal vertaald is, zie de
downloads pagina . Ook kunt u op onze vertalings tracker kijken.
- Het zou namelijk kunnen zijn dat iemand al aan de vertaling werkt of misschien hierover heeft gecommuniceerd.
+ Het zou namelijk kunnen zijn dat iemand al aan de vertaling werkt of misschien hierover heeft gecommuniceerd.
Merk op dat vertalingen alleen kunnen worden geaccepteerd als ze afkomstig zijn van een geregistreerde
sourceforge.net-gebruiker. Wij kunnen niet elke vertaling doorgronden en daarom is het belangrijk dat we
diff --git a/src/Greenshot/Languages/help-nn-NO.html b/Greenshot/Languages/help-nn-NO.html
similarity index 96%
rename from src/Greenshot/Languages/help-nn-NO.html
rename to Greenshot/Languages/help-nn-NO.html
index 2e29a9064..f4ff1d77a 100644
--- a/src/Greenshot/Languages/help-nn-NO.html
+++ b/Greenshot/Languages/help-nn-NO.html
@@ -301,7 +301,7 @@
Generelle innstillingar
Sprk : Sprket du nskjer bruke i Greenshot.
- Du kan laste ned tilleggssprk her .
+ Du kan laste ned tilleggssprk her .
Start Greenshot med systemet : Aktiverar Greenshot nr Windows startar
Snggtastar : Redigerar snggtastane knytt til skjermknipsing
Bruk systemets standardproxy : Om dette er huka av, vil Greenshot bruke systemet sin proxyserver for sj etter oppdateringar.
@@ -412,7 +412,7 @@
du rett og slett likar ideen om open kjeldekode er du velkomen til re innsatsen
vr med ein donasjon.
P heimesida vr finn du informasjon om korleis du kan sttte utviklarane:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -421,7 +421,7 @@
Om du likar Greenshot, syt for at andre fr greie p det! Fortel vener, kollegaer og
fygljarar p sosiale media om Greenshot!
Gje tilbakemelding p Greenshot p relevante programvaresider eller legg ei
- lenkje til nettsida vr (https://getgreenshot.org) p bloggen eller heimesida di.
+ lenkje til nettsida vr (http://getgreenshot.org) p bloggen eller heimesida di.
@@ -432,7 +432,7 @@
Om du er registrert p sourceforge.net kan du sende inn omsetjingar til vr
omsetjings-tracker .
Kontroller fyrst om det alt finst ei omsetjing p
- nedlastingssida .
+ nedlastingssida .
Sjekk g omsetjings-trackeren ,
d den kan innehalde ein omsetjing under arbeid eller diskusjon.
Ver merksam p at me bare tilbyr omsetjingar p nedlastingssida vr om den har
diff --git a/src/Greenshot/Languages/help-pl-PL.html b/Greenshot/Languages/help-pl-PL.html
similarity index 97%
rename from src/Greenshot/Languages/help-pl-PL.html
rename to Greenshot/Languages/help-pl-PL.html
index 555d2038e..7e2ad2396 100644
--- a/src/Greenshot/Languages/help-pl-PL.html
+++ b/Greenshot/Languages/help-pl-PL.html
@@ -303,7 +303,7 @@
dużo czasu i pieniędzy, czy po prostu podobnie jak Greenshot, popierasz ideę
oprogramowania open source:. rozważ uhonorowanie naszych wysiłków, przekazując darowiznę
Proszę spojrzeć na naszą stronę domową, aby zobaczyć, jak można wspierać zespół rozwoju Greenshot
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
diff --git a/src/Greenshot/Languages/help-pt-PT.html b/Greenshot/Languages/help-pt-PT.html
similarity index 98%
rename from src/Greenshot/Languages/help-pt-PT.html
rename to Greenshot/Languages/help-pt-PT.html
index 9709eb0b0..40467a293 100644
--- a/src/Greenshot/Languages/help-pt-PT.html
+++ b/Greenshot/Languages/help-pt-PT.html
@@ -333,7 +333,7 @@
Definies Gerais
Idioma : O idioma preferido a utilizar.
- Pode transferir ficheiros de idiomas adicionais para o Greenshot aqui .
+ Pode transferir ficheiros de idiomas adicionais para o Greenshot aqui .
Iniciar o Greenshot no arranque : Inicia o programa no arranque do sistema.
Teclas de Atalho : Personaliza as teclas de atalho a serem usadas para criar capturas.
Usar proxy padro do sistema : Se seleccionado, o Greenshot usa proxy padro do sistema para procurar actualizaes.
@@ -429,7 +429,7 @@
muito tempo e dinheiro, ou se simplesmente gosta do Greenshot e
da ideia de sotware de cdigo aberto: por favor considere compensar o nosso esforo, doando.
Por favor visite a nossa pgina web para ver como pode apoiar a equipa de desenvolvimento do Greenshot:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -448,7 +448,7 @@
Se um utilizador registado no sourceforge.net, pode enviar tradues para o nosso
monitor de tradues .
Por favor certifique-se de que no existe traduo para o seu idioma na nossa
- pgina de transferncias . Veja tambm no nosso monitor de tradues ,
+ pgina de transferncias . Veja tambm no nosso monitor de tradues ,
se existe alguma traduo a decorrer, ou pelo menos em discusso.
Tenha em ateno que s disponibilizaremos uma traduo na nossa pgina de transferncias se ela
tiver sido enviada atravs da sua conta no sourceforge.net. Uma vez que o mais provvel ns
diff --git a/src/Greenshot/Languages/help-ru-RU.html b/Greenshot/Languages/help-ru-RU.html
similarity index 97%
rename from src/Greenshot/Languages/help-ru-RU.html
rename to Greenshot/Languages/help-ru-RU.html
index a9b022dca..33eb7d114 100644
--- a/src/Greenshot/Languages/help-ru-RU.html
+++ b/Greenshot/Languages/help-ru-RU.html
@@ -283,7 +283,7 @@
Общие
Язык (Language) : Язык интерфейса.
- Вы можете скачать дополнительные языковые файлы здесь .
+ Вы можете скачать дополнительные языковые файлы здесь .
Автозагрузка : Запуск программы при загрузке системы.
Горячие клавиши : Настройка горячих клавиш, которые будут использоваться для создания скриншотов.
Использовать прокси-сервер системы по умолчанию : Если флажок установлен, Greenshot использует прокси-сервер по умолчанию системы для проверки обновлений.
@@ -359,7 +359,7 @@
сберегает вам или вашей компании время и деньги, или если Greenshot вам просто нравится, вы можете пожертвовать
некоторую сумму денег, чтобы поддержать дальнейшую разработку,
перейдите на нашу домашнюю страницу, чтобы узнать, как вы можете поддержать команду разработчиков Greenshot:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -380,7 +380,7 @@
If you are a registered user at sourceforge.net, you can submit translations to our
translations tracker .
Please make sure there is no existing translation for your language on our
- downloads page . Also check our translations tracker ,
+ downloads page . Also check our translations tracker ,
there might be a translation in progress, or at least in discussion.
Please note that we will only provide a translation on our downloads page if it has
been submitted through your sourceforge.net user account. Since we most probably are
diff --git a/src/Greenshot/Languages/help-sv-SE.html b/Greenshot/Languages/help-sv-SE.html
similarity index 96%
rename from src/Greenshot/Languages/help-sv-SE.html
rename to Greenshot/Languages/help-sv-SE.html
index 8ca8737e4..cdff974f1 100644
--- a/src/Greenshot/Languages/help-sv-SE.html
+++ b/Greenshot/Languages/help-sv-SE.html
@@ -263,7 +263,7 @@
Sprk : Det sprk du fredrar.
- Du kan ladda ner ytterligare sprkfiler fr Greenshot hr .
+ Du kan ladda ner ytterligare sprkfiler fr Greenshot hr .
Starta Greenshot nr datorn startas : Starta programmet nr systemet startat upp.
@@ -358,7 +358,7 @@
Vi lgger ner mycket arbete p Greenshot och spenderar en hel del tid till att tillhandahlla ett bra program helt gratis och med ppen kllkod. Om du tycker att programmet gr dig mer produktiv, om det sparar dig (eller ditt fretag) en massa tid och pengar, eller om du helt enkelt bara tycker om Greenshot och tanken p mjukvara med ppen kllkod: vervg att belna vrt arbete genom att donera.
Ta en titt p vr hemsida fr f reda p hur du kan stdja Greenshots utvecklingsteam:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -374,7 +374,7 @@
r inte Greenshot tillgngligt p ditt sprk? Om du knner dig trygg med att verstta mjukvara r du mer n vlkommen att gra s.
Om du r en registrerad anvndare p sourceforge.net kan du skicka in versttningar till vr versttnings-tracker .
Se till s att det inte finns ngon existerande versttning till ditt sprk p vr
- nerladdningssida . Kolla ocks vr versttnings-tracker ,
+ nerladdningssida . Kolla ocks vr versttnings-tracker ,
det kan finnas pgende versttningar, eller i alla fall i planeringsstadiet.
Observera att vi enbart tillhandahller en versttning p vr nerladdningssida om den blivit inskickad via ditt konto p sourceforge.net. Eftersom vi sannolikt inte har mjlighet att frst din versttning r det bra om andra anvndare p sourceforge kan kontakta dig angende frbttringar eller ndringar om en ny version av Greenshot slpps.
diff --git a/src/Greenshot/Languages/help-tr-TR.html b/Greenshot/Languages/help-tr-TR.html
similarity index 95%
rename from src/Greenshot/Languages/help-tr-TR.html
rename to Greenshot/Languages/help-tr-TR.html
index 11161cf9f..81705a566 100644
--- a/src/Greenshot/Languages/help-tr-TR.html
+++ b/Greenshot/Languages/help-tr-TR.html
@@ -260,7 +260,7 @@
Genel ayarlar
Dil : Programı kullanmayı tercih ettiğiniz dil.
- Greenshot için kullanılabilecek diğer dilleri buradan indirebilirsiniz .
+ Greenshot için kullanılabilecek diğer dilleri buradan indirebilirsiniz .
Kısayol tuşlarını devral : İşaretlediğinizde, Greenshot Print tuşu ile kullanılabilir.
Windows başlangıcında çalıştır : Bilgisayar başlatıldığında programı çalıştır.
Flaş etkisi : Ekran yakalarken görsel flaş çakması etkisi oluşturur
@@ -303,7 +303,7 @@
veya kurumunuza para ve zaman kazandırıyorsa ya da Greenshot ve açık kaynak felsefesinden
hoşlanıyorsanız lütfen bağış yaparak emeklerimize saygı gösterin.
Greenshot geliştirici takımını nasıl destekleyeceğinizi görmek için web sitemize bakın:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -321,7 +321,7 @@
Eğer kayıtlı bir sourceforge.net üyesi iseniz, çevirilerinizi
çeviri izleyicimize gönderbilirsiniz.
Öncesinde
- indirme sayfasından dilinizde bir çeviri olmadığından emin olun. Ayrıca çeviri izleyicimizden de durumu denetleyin.
+ indirme sayfasından dilinizde bir çeviri olmadığından emin olun. Ayrıca çeviri izleyicimizden de durumu denetleyin.
Dilinizde bir çeviri çalışması planlanıyor veya yapılıyor olabilir.
Çevirileri indirme sayfalarımızda ancak sourceforge.net kullanıcı hesabınızla gönderdiyseniz
yayınlayacağız. Böylece bizler çevirinizi büyük olasılıkla anlayamayacağımız için diğer sourceforge.
diff --git a/src/Greenshot/Languages/help-zh-CN.html b/Greenshot/Languages/help-zh-CN.html
similarity index 95%
rename from src/Greenshot/Languages/help-zh-CN.html
rename to Greenshot/Languages/help-zh-CN.html
index 74c9b1387..c3e2e8402 100644
--- a/src/Greenshot/Languages/help-zh-CN.html
+++ b/Greenshot/Languages/help-zh-CN.html
@@ -272,7 +272,7 @@
常规设置
语言 :你希望使用的语言。
- 你可以在这里 下载Greenshot额外的语言文件。
+ 你可以在这里 下载Greenshot额外的语言文件。
注册快捷键 :如果选中,则Greenshot将可以使用Print 按键来抓图。
开机时自动启动Greenshot :当系统启动的时启动Greenshot程序。
抓屏时闪光 :抓图时发出闪光(闪光灯提示)。
@@ -362,7 +362,7 @@
我们把大部分工作都放在了Greenshot中并花费时间来提供这样一个不错的免费开源的软件。如果你感觉它帮助你提高了效率,或者节省了你(或者你的公司)的时间和金钱,或者你仅仅是喜欢Greenshot和开源软件精神:请考虑一下用捐助的方式来赞助我们。
请查看我们的主页了解如何赞助Greenshot开发小组:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -378,7 +378,7 @@
Greenshot还没有支持你所使用的语言?如果你觉得自己适合来为此软件制作一个翻译,不用客气来做吧。
如果你已经在开源社区sourceforge.net注册,你可以在我们的translations tracker 提交你的翻译。
- 但是请先确认在我们的下载页面 里还没有你使用的语言的翻译存在,同样请查看一下我们的translations tracker ,是否已经有了正在进行中的翻译或者至少已经开始讨论。
+ 但是请先确认在我们的下载页面 里还没有你使用的语言的翻译存在,同样请查看一下我们的translations tracker ,是否已经有了正在进行中的翻译或者至少已经开始讨论。
请注意我们只会在我们的下载页提供一个通过sourceforge.net提交的翻译,因为我们没有能力去阅读所有的语言,所以这样可以让其他用户能够联系到你,并帮助你在下一个新版本的Greenshot的翻译中提出改进意见。
diff --git a/src/Greenshot/Languages/language-ar-SY.xml b/Greenshot/Languages/language-ar-SY.xml
similarity index 97%
rename from src/Greenshot/Languages/language-ar-SY.xml
rename to Greenshot/Languages/language-ar-SY.xml
index a7363a326..e9d31d52c 100644
--- a/src/Greenshot/Languages/language-ar-SY.xml
+++ b/Greenshot/Languages/language-ar-SY.xml
@@ -5,7 +5,7 @@
اذا اعجبك البرنامج انت مدعو لدعمنا:
جرين شوت استضيف بواسطة GitHub في
الايقونات بواسطة مجموعة ايقونات يوسوكي كامياماني (تحت رخصة المشاع الإبداعي الاصدار 3.0)
- حقوق النشر © 2007 -2021 توماس براون, جينس كلنجين, روبين كروم
+ حقوق النشر © 2007 - 2012 توماس براون, جينس كلنجين, روبين كروم
جرين شوت لا يأتي مع أية ضمان. هذا برنامج حر, مرحبا بك لتعيد توزيعه تحت شروط معينة.
تفاصيل حول رخصة جنو العمومية:
حول جرين شوت
@@ -62,7 +62,6 @@
انسخ المسار الي الذاكرة
نسخ
قص (C)
- قص
اداة التحديد (ESC)
قص
احذف
diff --git a/src/Greenshot/Languages/language-ca-CA.xml b/Greenshot/Languages/language-ca-CA.xml
similarity index 97%
rename from src/Greenshot/Languages/language-ca-CA.xml
rename to Greenshot/Languages/language-ca-CA.xml
index 323f7849f..df48b4bc3 100644
--- a/src/Greenshot/Languages/language-ca-CA.xml
+++ b/Greenshot/Languages/language-ca-CA.xml
@@ -5,7 +5,7 @@
Si Greenshot us agrada , us agrairem que ens ajudeu:
Greenshot s'allotja a sourceforge.net
Icones del conjunt d'icones Fugue de Yusuke Kamiyamane(Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot s'ofereix SENSE CAP GARANTIA. Aquest és un programari gratuït, i podeu redistribuir-lo amb algunes condicions.
Detalls sobre la Llicència General Publica GNU:
Quant a Greenshot
@@ -92,8 +92,6 @@ Abans de crear un nou informe d'error, us agrairem que comproveu que l'error no
Copia el camí al porta-retalls
Copia
Retalla(C)
- Retalla
- Autorretalla
Eina de selecció (ESC)
Retalla
Esborra
@@ -305,7 +303,7 @@ Malgrat això, encara es poden utilitzar totes les característiques de Greensho
Afegeix un comptador (I)
Afegeix una bafarada (S)
- Canvia la mida (Z)
+ Canvia la mida
Configuració del canvi de mida
Manté la relació d'aspecte
Amplada
diff --git a/src/Greenshot/Languages/language-cs-CZ.xml b/Greenshot/Languages/language-cs-CZ.xml
similarity index 85%
rename from src/Greenshot/Languages/language-cs-CZ.xml
rename to Greenshot/Languages/language-cs-CZ.xml
index cc409c66f..666896aaf 100644
--- a/src/Greenshot/Languages/language-cs-CZ.xml
+++ b/Greenshot/Languages/language-cs-CZ.xml
@@ -1,34 +1,33 @@
-
+
Chyby prosím hlaste na adrese
Pokud se vám Greenshot líbí, uvítáme Vaší podporu
- Greenshot je hostován na github.com
+ Greenshot je hostován na sourceforge.net
Ikony pochází ze sady Yusuke Kamiyamane's Fugue (licence Creative Commons Attribution 3.0)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
Greenshot je ABSOLUTNĚ BEZ ZÁRUKY. Toto je svobodný software, můžete jej dále šířit za určitých podmínek.
Podrobnosti o GNU General Public License:
O programu Greenshot
- Překlad: Zdeněk Chalupský <chalzd@gmail.com>. Korektura: Petr Toman a Svatopluk Vít
+ Překlad: Zdeněk Chalupský <chalzd@gmail.com>. Korektura: Petr Toman
Greenshot - revoluční utilita pro snímání obrazovky
Zavřít
Omlouváme se, ale došlo k neočekávané chybě.
-
Dobrá zpráva: můžete nám pomoci odstranit chybu, když o ní podáte hlášení.
Navštivte prosím níže uvedenou adresu, vytvořte nové hlášení o chybě a vložte popis chyby.
Zadejte prosím smysluplné shrnutí a připojte informace, které považujete za užitečné pro popis hlášeného problému.
Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není evidována. (Můžete použít rychlé vyhledávání.) Děkujeme :-)
Chyba
- Zrušit
+ Zrušit
Neočekávaná chyba při zápisu do schránky.
Greenshot nemohl zapsat data do schránky, je {0} blokován přístup.
Obrázek ve schránce nebyl nalezen.
Windows Bitmap
- Device Independent Bitmap (DIB)
+ Zařízení Independent Bitmap (DIB)
HTML
HTML s vloženými obrázky
- PNG
+ PNG
Alfa
Použít
Modrá
@@ -45,17 +44,17 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Označit oblast snímání
Otevřít obrázek ze schránky
Zachytit celou obrazovku
- Vše
- Spodní
- Vlevo
- Vpravo
- Nahoře
- Zachytávat aplikaci Internet Explorer
+ vše
+ spodní
+ vlevo
+ vpravo
+ horní
+ Zachytávat aplikaci Internet Explorer
Zachytit Internet Explorer ze seznamu
- Zachycení posledně snímané oblasti
- Vybrat snímané okno
- Snímat okno ze seznamu
- Podpora Greenshotu
+ Zachycení poslední oblasti
+ Vybrat okno pro zachycení
+ Zachytit okno ze seznamu
+ Podpora pro Greenshot
Konec
Nápověda
Otevřít obrázek ze souboru
@@ -71,30 +70,28 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Vpravo
Nahoře
Vertikální zarovnání
- Uspořádat
+ Uspořádat
Tvar šipky
Oba
Koncový bod
Žádný
Počáteční bod
- Automatické oříznutí
+ Automatické oříznutí
Barva výplně
Poloměr rozostření
Tučné
- Okraj
+ Hranice
Jas
Zrušit
Chyba při přístupu do schránky. Zkuste to prosím znovu.
Zavřít
- Chcete uložit snímek?
+ Přejete si uložit snímek?
Uložit snímek?
Potvrdit
Kopírovat obrázek do schránky
Kopírovat cestu do schránky
Kopírovat
Oříznout (C)
- Oříznout
- Automatické oříznutí
Výběr objektů (ESC)
Vystřihnout
Odstranit
@@ -102,15 +99,15 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Úplně dolů
Nakreslit šipku (A)
Nakreslit elipsu (E)
- Kreslení od ruky (F)
+ Kreslení od ruky (F)
Zvýraznit (H)
Nakreslit linku (L)
Nakreslit obdélník (R)
- Přidat textový rámec (T)
+ Přidat textbox (T)
Duplikovat vybraný prvek
Úpravy
Efekty
- E-mail
+ E-Mail
Soubor
Velikost
Barva čáry
@@ -123,20 +120,20 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Vržený stín
Obrázek uložen do {0}.
Vložit okno
- Invertovat
- Skloněné
+ Invertovat
+ Italika
Načíst objekty ze souboru
Faktor zvětšení
- Přizpůsobit velikosti snímku
+ Přizpůsobit velikosti snímku
Zamlžit (O)
Rozmazat
Ztížení rozeznání obsahu
Pixelizace
Objekt
- Otevřít složku v průzkumníkovi Windows
+ Otevřít složku v prohlížeči Windows
Vložit
Velikost pixelu
- Kvalita náhledu
+ Náhled kvality
Tisk
Znovu {0}
Obnovit velikost
@@ -154,7 +151,7 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Tloušťka linky
Greenshot editor obrázků
Potrhané okraje
- Zpět {0}
+ Zpět {0}
Nahoru o jednu úroveň
Posunout úplně nahoru
MAPI klient
@@ -162,7 +159,7 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Aplikace Outlook s prostým textem
Chyba
Program Greenshot je již spuštěn
- Nelze uložit soubor do {0}.
+ Nelze uložit soubor do {0}.
Zkontrolujte prosím dostupnost vybraného cíle.
Soubor "{0}" nelze otevřít.
Nelze otevřít odkaz.
@@ -170,7 +167,7 @@ Zkontrolujte prosím dostupnost vybraného cíle.
Vygenerovaný název souboru nebo složky není platný. Opravte prosím vzor názvu a zkuste to znovu.
Expert
Vytvořit 8bitový obrázek, pokud má méně než 256 barev
- Kontrolovat aktualizace nestabilních verzí
+ Kontrolovat nestabilní aktualizace
Formáty schránky
Číslo pro ${NUM} ve vzoru pro název souboru
Vím, co dělám!
@@ -180,12 +177,12 @@ Zkontrolujte prosím dostupnost vybraného cíle.
Znovu použít editor, je-li to možné
Potlačit dialog Uložit při zavírání editoru
Zobrazovat miniatury oken v kontextové nabídce (pro Vista a Windows 7)
- Exportovat do: {0}
+ Exportovat do: {0}
Došlo k chybě při exportu do{0}:
Nápověda Greenshot
- Klávesové zkratky
- Nastavte kvalitu obrázku v JPEG formátu
- Ok
+ Klávesové zkratky
+ Vyberte nastavení kvality obrázku v JPEG formátu
+ Ok
Nastala chyba při pokusu o tisk.
Centrovat obrázek na stránce
Zvětšit oblast tisku, aby odpovídala velikosti papíru
@@ -216,15 +213,15 @@ Zkontrolujte prosím dostupnost vybraného cíle.
Cíl snímku
Kopírovat do schránky
Otevřít v editoru obrázků
- E-mail
+ E-Mail
Uložit přímo (pomocí nastavení níže)
Uložit jako (zobrazit dialog)
Vybrat cíl dynamicky
Odeslat na tiskárnu
- Editor
+ Editor
Vzor pro název souboru
Obecné
- Snímek aplikace Internet Explorer
+ Snímek aplikace Internet Explorer
Kvalita JPEG
Jazyk
Následující symboly budou automaticky nahrazeny:
@@ -235,20 +232,17 @@ ${hh} hodina, 2 číslice
${mm} minuta, 2 číslice
${ss} sekunda, 2 číslice
${NUM} počítadlo, 6 číslic
-${RRR...} náhodný alfanumerický znak, délka dle počtu použitých znaků R
${title} titulek okna
${user} uživatel Windows
-${domain} doména Windows
+${domain} doména Windows
${hostname} název počítače
Složky také můžete vytvářet dynamicky pomocí zpětného lomítka (symbol \).
-Například: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
-vytvoří ve výchozím úložišti složku pro dnešní den, např. 2008-06-29, a název souboru snímku bude odvozen od aktuálního času,
-např. 11_58_32 (plus rozšíření uvedené v nastavení).
- Síť a aktualizace
+Například: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss} vytvoří ve výchozím úložišti složku pro dnešní den, např. 2008-06-29, a název souboru snímku bude odvozen od aktuálního času, např. 11_58_32 (plus rozšíření uvedené v nastavení).
+ Síť a aktualizace
Výstup
- Přehrát zvuk závěrky fotoaparátu
- Zásuvné moduly
+ Přehrát zvuk uzávěrky fotoaparátu
+ Pluginy
Autor
Cesta k DLL
Název
@@ -258,10 +252,10 @@ např. 11_58_32 (plus rozšíření uvedené v nastavení).
Tisk
Možnosti tisku
Nastavení kvality
- Snížit počet barev na maximálně 256
+ Snížit počet barev na maximálně 256
Registrovat klávesové zkratky
Použít blesk
- Zobrazovat upozornění
+ Zobrazovat upozornění
Zobrazit lupu
Cíl
Nastavení
@@ -270,14 +264,14 @@ např. 11_58_32 (plus rozšíření uvedené v nastavení).
Výchozí formát obrázku
Definuje klávesové zkratky Prnt, Ctrl + Print, Alt + Prnt, které jsou vyhrazeny pro globální použití od startu do ukončení Greenshotu.
Výchozí místo pro uložení snímků (ponechte prázdné pro uložení do počítače)
- Použít výchozí systémovou proxy
+ Použít výchozí systémovou proxy
Efekty
Před zachycením počkat daný počet milisekund
Režim zachycování okna
- Snímek okna
+ Snímek okna
Klikněte pravým tlačítkem myši nebo stiskněte klávesu PrtSc.
- K dispozici je novější verze aplikace Greenshot! Přejete si stáhnout Greenshot {0}?
- Počkejte prosím než bude zachycena stránka v aplikaci Internet Explorer...
+ K dispozici je novější verze Greenshot! Přejete si stáhnout Greenshot {0}?
+ Počkejte prosím než bude zachycena stránka v aplikaci Internet Explorer...
Upozornění
Klávesovou(é) zkratku(y) "{0}" nelze použít. Tento problém je pravděpodobně způsoben jiným programem používajícím tytéž klávesové zkratky! Můžete změnit nastavení klávesových zkratek, deaktivovat je nebo změnit nastavení softwaru využívajícího shodné klávesové zkratky.
@@ -287,7 +281,7 @@ Všechny funkce Greenshotu jsou stále dostupné přímo z místní nabídky bez
Automaticky
Použít výchozí barvu
Jak je zobrazeno
-
+
Intenzita stínu
Vyrovnání stínu
@@ -304,11 +298,11 @@ Všechny funkce Greenshotu jsou stále dostupné přímo z místní nabídky bez
Horní strana
Dolní strana
Vytvořit stín
-
+
Přidat počítadlo (I)
Přidat textovou bublinu (S)
- Změnit velikost (Z)
+ Změnit velikost
Nastavení změny velikosti
Zachovat poměr stran
Šířka
diff --git a/src/Greenshot/Languages/language-da-DK.xml b/Greenshot/Languages/language-da-DK.xml
similarity index 95%
rename from src/Greenshot/Languages/language-da-DK.xml
rename to Greenshot/Languages/language-da-DK.xml
index b032e8aff..7e8b6c01a 100644
--- a/src/Greenshot/Languages/language-da-DK.xml
+++ b/Greenshot/Languages/language-da-DK.xml
@@ -4,7 +4,6 @@
Dansk oversættelse af Jens Jacob Thomsen
@@ -469,9 +468,6 @@ tidspunktet, fx 11_58_32 (plus filendelsen angivet i indstillingerne).
Beskær (C)
-
- Beskær
-
Åbn billede fra udklipsholder
diff --git a/src/Greenshot/Languages/language-de-DE.xml b/Greenshot/Languages/language-de-DE.xml
similarity index 82%
rename from src/Greenshot/Languages/language-de-DE.xml
rename to Greenshot/Languages/language-de-DE.xml
index b636da112..cab377ef9 100644
--- a/src/Greenshot/Languages/language-de-DE.xml
+++ b/Greenshot/Languages/language-de-DE.xml
@@ -5,7 +5,7 @@
Wenn Sie Greenshot mögen, können Sie uns gerne unterstützen:
Greenshot wird von GitHub gehostet unter
Icons aus Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Für Greenshot besteht KEINERLEI GARANTIE. Greenshot ist freie Software, die Sie unter bestimmten Bedingungen weitergeben dürfen.
Detaillierte Informationen zur GNU General Public License:
Über Greenshot
@@ -14,7 +14,7 @@ Detaillierte Informationen zur GNU General Public License:
Tut uns leid, ein unerwarteter Fehler ist aufgetreten.
Die gute Nachricht ist: Sie können uns helfen, ihn zu beseitigen, indem Sie uns einen Fehlerbericht zukommen lassen.
Besuchen Sie die unten stehende URL und erstellen Sie einen neuen Fehlerbericht.
-Bitte geben Sie eine aussagekräftige Zusammenfassung an, fügen Sie den Inhalt des Textfelds in die Beschreibung ein, und ergänzen Sie diese mit zusätzlichen
+Bitte geben Sie eine aussgekräftige Zusammenfassung an, fügen Sie den Inhalt des Textfelds in die Beschreibung ein, und ergänzen Sie diese mit zusätzlichen
Informationen, die für das Nachvollziehen des Fehlers hilfreich sein könnten.
Wir wären sehr dankbar, wenn Sie vorher prüfen würden, ob dieser Fehler schon gemeldet wurde - nutzen Sie einfach die Suche, um bestehende Fehlerberichte
schnell zu finden. Vielen Dank :)
@@ -57,8 +57,8 @@ schnell zu finden. Vielen Dank :)
Greenshot unterstützen
Schließen
Hilfe
- Datei öffnen...
- Letzten Speicherort im Explorer öffnen
+ Datei öffnen
+ Letzten Screenshot im Explorer anzeigen
Schnelleinstellungen
Einstellungen...
Fehler beim Exportieren nach '{0}'. Bitte wiederholen Sie den Vorgang.
@@ -77,8 +77,7 @@ schnell zu finden. Vielen Dank :)
Keine
Anfangspunkt
Automatisch zuschneiden
- Automatisches Zuschneiden nicht möglich
- Hintergrundfarbe (0-9)
+ Hintergrundfarbe
Weichzeichner-Radius
Fett
Rand
@@ -93,19 +92,14 @@ schnell zu finden. Vielen Dank :)
Pfad in Zwischenablage kopieren
Kopieren
Zuschneiden (C)
- Zuschneiden - Modus
- Zuschneiden
- Vertikal ausschneiden
- Horizontal ausschneiden
- Automatisch zuschneiden
- Auswahlwerkzeug (Esc)
+ Auswahlwerkzeug (ESC)
Ausschneiden
Gewähltes Element löschen
Eine Ebene nach hinten
In den Hintergrund
Pfeil zeichnen (A)
Ellipse zeichnen (E)
- Frei Hand zeichnen (F)
+ Freihand zeichnen (F)
Hervorheben (H)
Linie zeichnen (L)
Rechteck zeichnen (R)
@@ -116,7 +110,7 @@ schnell zu finden. Vielen Dank :)
E-Mail
Datei
Größe
- Rahmenfarbe (Num+0-9, Umschalt+0-9)
+ Rahmenfarbe
Graustufe
Bereich hervorheben
Graustufen
@@ -136,7 +130,7 @@ schnell zu finden. Vielen Dank :)
Unkenntlich machen - Modus
Verpixeln
Objekt
- Verzeichnis im Windows Explorer öffnen
+ Verzeichnis in Windows Explorer öffnen
Einfügen
Pixelgröße
Vorschauqualität
@@ -152,10 +146,10 @@ schnell zu finden. Vielen Dank :)
Speichern unter...
Alle Objekte auswählen
Druckauftrag wurde an '{0}' gesendet.
- Schatten an/aus (/)
+ Schatten An/Aus
Bild wurde in Zwischenablage kopiert.
Linienstärke
- Greenshot - Editor
+ Greenshot Editor
Gerissene Kanten
Rückgängig {0}
Eine Ebene nach vorne
@@ -167,15 +161,15 @@ schnell zu finden. Vielen Dank :)
Greenshot läuft bereits.
Konnte Datei nicht nach {0} speichern.
Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicherort.
- Die Datei '{0}' konnte nicht geöffnet werden.
+ Die Datei "{0}" konnte nicht geöffnet werden.
Konnte Link '{0}' nicht öffnen.
Screenshot konnte nicht gespeichert werden, bitte wählen Sie einen anderen Speicherort.
- Der generierte Datei- oder Verzeichnisname ist nicht gültig. Bitte korrigieren Sie das Dateinamensmuster und versuchen Sie es erneut.
+ Der generierte Datei- oder Verzeichnisname ist nicht gültig. Bitte korrigieren Sie das Dateiname-Muster und versuchen Sie es erneut.
Experten
- 8-Bit-Bilder bei weniger als 256 Farben erstellen
+ 8-Bit-Bilder erstellen bei weniger als 256 Farben
Auch instabile Updates anbieten
Zwischenablage-Formate
- Wert für ${NUM} im Dateinamensmuster
+ Wert für ${NUM} im Dateiname-Muster
Ich weiß, was ich tue!
Fußzeile für Druck
Speicherverbrauch reduzieren (auf Kosten der Performance - nicht empfohlen)
@@ -184,24 +178,24 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
Speichern-Dialog beim Schließen des Editors unterdrücken
Fenster-Vorschau im Kontextmenü anzeigen (für Vista und Windows 7)
Exportiert nach: {0}
- Beim Export nach {0} ist ein Fehler aufgetreten:
+ Beim Export zu {0} ist ein Fehler aufgetreten:
Greenshot - Hilfe
Tastenkombinationen
Bitte wählen Sie die Qualität Ihres JPEG-Bildes.
OK
Beim Versuch zu drucken ist ein Fehler aufgetreten.
- Auf der Seite zentrieren
- Auf Seitengröße vergrößern
- In die Seitenausrichtung drehen
- Auf Seitengröße verkleinern
+ Ausdruck auf der Seite zentrieren
+ Ausdruck auf Seitengröße vergrößern
+ Drehung des Ausdrucks an das Seitenformat anpassen
+ Ausdruck auf Seitengröße verkleinern
Farb-Einstellungen
Als Standard speichern und nicht wieder fragen
Farben umkehren
Layout-Einstellungen
Farbdruck
Nur in Graustufen ausdrucken
- Schwarz-Weiß-Druck erzwingen
- Datum/Uhrzeit am Seitenende
+ Schwarzweiß-Druck erzwingen
+ Datum und Uhrzeit am Ende der Seite einfügen
Greenshot - Druckeinstellungen
Als Standardqualität speichern und nicht wieder fragen
Greenshot - Qualität
@@ -212,42 +206,42 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
Greenshot mit Windows starten
Abfotografieren
Mauszeiger mitfotografieren
- Fensterteile einzeln abfotografieren
- Prüfen auf Updates alle x Tage (0 = keine Prüfung)
- Konfigurieren...
+ Fenster-Teile einzeln abfotografieren
+ Prüfen auf Updates alle X Tage (0=keine Prüfung)
+ Konfigurieren
Dateipfad in die Zwischenablage kopieren, wenn ein Bild gespeichert wird
Ziele
In Zwischenablage kopieren
Im Greenshot-Editor öffnen
E-Mail
Sofort speichern
- Speichern unter... (mit Dialog)
+ Speichern unter (mit Dialog)
Ziel dynamisch auswählen
An Drucker senden
Editor
- Dateinamensmuster
+ Dateiname-Muster
Allgemein
Internet Explorer abfotografieren
JPEG-Qualität
Sprache
Die folgenden Platzhalter werden im festgelegten Muster automatisch ersetzt:
-${YYYY} Jahr, 4-stellig
-${MM} Monat, 2-stellig
-${DD} Tag, 2-stellig
-${hh} Stunde, 2-stellig
-${mm} Minute, 2-stellig
-${ss} Sekunde, 2-stellig
-${NUM} inkrementierende Zahl, 6-stellig
-${title} Fenstertitel
-${user} Windows-Benutzername
-${domain} Windows-Domäne
-${hostname} Computername
+${YYYY} Jahr, 4-stellig
+${MM} Monat, 2-stellig
+${DD} Tag, 2-stellig
+${hh} Stunde, 2-stellig
+${mm} Minute, 2-stellig
+${ss} Sekunde, 2-stellig
+${NUM} inkrementierende Zahl, 6-stellig
+${title} Fenstertitel
+${user} Windows-Benutzername
+${domain} Windows-Domäne
+${hostname} Computername
-Greenshot kann auch Verzeichnisse dynamisch erstellen.
-Verwenden Sie den Backslash \, um Verzeichnisse vom Dateinamen zu trennen.
-Beispiel: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
-Dieses Muster legt ein Verzeichnis für den aktuellen Tag im Standard-Speicherort an und speichert die Bilddateien im Uhrzeit-Format mit der vorgegebenen Dateiendung ab.
-Beispiel: C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
+Greenshot kann auch Verzeichnisse dynamisch erstellen.
+Verwenden Sie das Backslash-Symbol \ um Verzeichnisse vom Dateinamen zu trennen.
+Zum Beispiel: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+Dieses Muster legt ein Verzeichnis für den aktuellen Tag im Standard-Speicherort an und speichert die Bilddateien im Uhrzeit-Format, mit der vorgegebenen Dateiendung ab.
+z.B. C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
Netzwerk und Aktualisierungen
Ausgabe
Kameraton abspielen
@@ -260,7 +254,7 @@ Beispiel: C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
Bildformat
Drucker
Druckeinstellungen
- JPEG-Qualitätseinstellungen
+ Qualitätseinstellungen
Maximal 256 Farben verwenden
Globale Tastenkombinationen aktivieren
Blitzlicht anzeigen
@@ -270,21 +264,22 @@ Beispiel: C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
Muster, das beim Speichern von Screenshots zum Generieren von Dateinamen verwendet wird
Sprache der Benutzeroberfläche
Standard-Bildformat
- Legt fest, ob beim Programmstart die Tastenkombinationen Druck, Strg+Druck, Alt+Druck beim Betriebssystem zur globalen Verwendung durch Greenshot reserviert werden, bis das Programm geschlossen wird.
+ Legt fest, ob beim Programmstart die Tastenkombinationen Drucken, Strg + Drucken, Alt + Drucken beim Betriebssystem zur globalen
+Verwendung durch Greenshot reserviert werden, bis das Programm geschlossen wird.
Standardpfad für Bildschirmausdrucke. Leer lassen für Desktop.
Standard-Proxyserver des Betriebssystems verwenden
Effekte
- Millisekunden vor dem Abfotografieren warten
- Aufnahmemodus
+ Millisekunden warten vor abfotografieren
+ Fenster abfotografier Modus
Fenster abfotografieren
Lupe anzeigen
- Klicken Sie hier mit der rechten Maustaste oder drücken Sie die Taste {0}.
- Eine neuere Greenshot-Version steht zur Verfügung. Wollen Sie Greenshot {0} herunterladen?
+ Klicken Sie hier mit der rechten Maustaste oder drücken Sie die {0} Taste.
+ Eine neuere Greenshot Version steht zur Verfügung. Wollen Sie Greenshot {0} herunterladen?
Bitte warten Sie, während die Seite im Internet Explorer abfotografiert wird...
Hinweis
- Die globale Tastenkombination {0} konnte nicht aktiviert werden.
-Vermutlich wurde dieselbe Tastenkombination bereits von einem anderen Programm {1} reserviert.
-Sie können die Tastenkombination für Greenshot ändern oder das Programm, das die Tastenkombination verwendet, deaktivieren.
+ Die globale Tastenkombination "{0}" konnte nicht aktiviert werden.
+Vermutlich wurde dieselbe Tastenkombination bereits von einem anderen Programm{1} reserviert.
+Sie können die Tastenkombinationen für Greenshot ändern, oder das Programm, das die Tastenkombination verwendet, deaktivieren.
Sie können aber auch alle Greenshot-Funktionen über das Kontextmenü des Greenshot-Icons im Infobereich verwenden.
Benutzerdefinierte Farbe verwenden
@@ -312,11 +307,11 @@ Sie können aber auch alle Greenshot-Funktionen über das Kontextmenü des Green
Zähler hinzufügen (I)
Sprechblase hinzufügen (S)
- Skalieren (Z)
+ Skalieren
Einstellungen für Skalierung
Seitenverhältnis beibehalten
Breite
Höhe
Symbolgröße
-
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/language-de-x-franconia.xml b/Greenshot/Languages/language-de-x-franconia.xml
similarity index 96%
rename from src/Greenshot/Languages/language-de-x-franconia.xml
rename to Greenshot/Languages/language-de-x-franconia.xml
index 34da6f0b7..f2b69af5c 100644
--- a/src/Greenshot/Languages/language-de-x-franconia.xml
+++ b/Greenshot/Languages/language-de-x-franconia.xml
@@ -5,7 +5,7 @@
Wenn der Greenshot gfälld, kannsd uns gern a weng helfn:
Greenshot is a bei GitHub, und zwa dordn:
Dei Fuztl-Bildla sin vom Yusuke Kamiyamane's Fugue icon set (Griäidif Gommens Äddribuschn 3.0 Laisns)
- Kobbireid (C) 2007-2021 Domas Braun, Jens Glingen, Robin Grohm
+ Kobbireid (C) 2007-2012 Domas Braun, Jens Glingen, Robin Grohm
A Garandie gibds für Greenshot ned, des kannst vergessn. Greenshot is umsonsd und wennsd mogst, kannsd es a rumreichn.
Mehr Infos zur GNU Dschännerel Bablig Laisns:
Was issn Greenshot???
@@ -88,8 +88,6 @@ Dangschee, wassd scho :)
Bfad in däi Zwischnblach nei
Kobiern
Zamschneidn (C)
- Zamschneidn
- Audomadisch zamschneidn
Angriffln (ESC)
Ausschneidn
Wech mid dem Ding!
@@ -228,9 +226,9 @@ ${user} Windous-Benudzername
${domain} Windous-Domäne
${hostname} Kombjudername
-Greenshot kann a Ordner selber ohleeng.
-Wennsd Ordner vom Dadeinamen drennen willsd, nimssd an Beggsläsch \
-So hald: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+Greenshot kann a Ordner selber ohleeng.
+Wennsd Ordner vom Dadeinamen drennen willsd, nimssd an Beggsläsch \
+So hald: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
Da gibds dann an Ordner fürn agduelln Dooch im Schdandard-Schbeicherord und däi Foddos landn dann da drin und heißn wäi die Uhrzeid.
z.B. C:\Users\MaxMusdermann\Desgdob\2012-08-13\12-58-32.png
Nedswerch und Abdäids
@@ -266,8 +264,8 @@ z.B. C:\Users\MaxMusdermann\Desgdob\2012-08-13\12-58-32.png
Was hasdn du für an aldn Scheiß?! Magsd des neue Greenshot {0} ham?
Etz watzd an Momend! Des dauerd a weng...
Hinweis
- Die globale Dasdnkombi "{0}" konnd ned agdivierd wern.
-Warscheinli hoggd irgend so a andrer Debb draff.
+ Die globale Dasdnkombi "{0}" konnd ned agdivierd wern.
+Warscheinli hoggd irgend so a andrer Debb draff.
Endweder ändersd die Dasdnkombi für Greenshot, oder du bisd a Mann und findsd die Sau!
Wennsd mogsd, kannsd nadürlich a einfach es Gondexdmenü nehmen (des grüne G rechds undn).
diff --git a/src/Greenshot/Languages/language-el-GR.xml b/Greenshot/Languages/language-el-GR.xml
similarity index 98%
rename from src/Greenshot/Languages/language-el-GR.xml
rename to Greenshot/Languages/language-el-GR.xml
index 1feb74b51..e248a55f3 100644
--- a/src/Greenshot/Languages/language-el-GR.xml
+++ b/Greenshot/Languages/language-el-GR.xml
@@ -5,7 +5,7 @@
Αν σας αρέσει το Greenshot, είστε ευπρόσδεκτοι να μας υποστηρίξετε:
Το Greenshot φιλοξενείται από τη GitHub:
Εικονίδια από Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Δεν παρέχεται ΚΑΜΙΑ ΕΓΓΥΗΣΗ για το Greenshot. Είναι ελεύθερο λογισμικό. Είστε ελεύθεροι να το αναδιανείμετε κάτω από ορισμένες συνθήκες.
Λεπτομέρειες σχετικά με την GNU General Public License:
Πληροφορίες για το Greenshot
@@ -93,8 +93,6 @@
Αντιγραφή της θέσης του αρχείου στο πρόχειρο
Αντιγραφή
Περικοπή (C)
- Περικοπή
- Αυτόματη Περικοπή
Εργαλείο Επιλογής (ESC)
Αποκοπή
Διαγραφή
diff --git a/src/Greenshot/Languages/language-en-US.xml b/Greenshot/Languages/language-en-US.xml
similarity index 93%
rename from src/Greenshot/Languages/language-en-US.xml
rename to Greenshot/Languages/language-en-US.xml
index 1403d3e9c..3100b76f0 100644
--- a/src/Greenshot/Languages/language-en-US.xml
+++ b/Greenshot/Languages/language-en-US.xml
@@ -5,14 +5,13 @@
If you like Greenshot, you are welcome to support us:
Greenshot is hosted by GitHub at
Icons from Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
Details about the GNU General Public License:
About Greenshot
-
Greenshot - the revolutionary screenshot utility
Close
- Sorry, an unexpected error occurred.
+ Sorry, an unexpected error occured.
The good news is: you can help us getting rid of it by filing a bug report.
Please visit the URL below, create a new bug report and paste the contents from the text area into the description.
@@ -21,11 +20,11 @@ Please add a meaningful summary and enclose any information you consider to be h
Also, we would highly appreciate if you checked whether a tracker item already exists for this bug. (You can use the search to find those quickly.) Thank you :)
Error
Cancel
- An unexpected error occurred while writing to the clipboard.
+ An unexpected error occured while writing to the clipboard.
Greenshot wasn't able to write to the clipboard as the process {0} blocked the access.
Couldn't find a clipboard image.
Windows Bitmap
- Device Independent Bitmap (DIB)
+ Device Independend Bitmap (DIB)
HTML
HTML with inline images
PNG
@@ -78,8 +77,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
None
Start point
Auto crop
- Auto crop not possible
- Fill color (0-9)
+ Fill color
Blur radius
Bold
Border
@@ -94,11 +92,6 @@ Also, we would highly appreciate if you checked whether a tracker item already e
Copy path to clipboard
Copy
Crop (C)
- Crop mode
- Crop
- Crop out vertically
- Crop out horizontally
- Auto crop
Selection Tool (ESC)
Cut
Delete
@@ -117,7 +110,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
E-Mail
File
Size
- Line color (NumPad0-9, Shift+0-9)
+ Line color
Grayscale
Highlight area
Grayscale
@@ -153,7 +146,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
Save as...
Select all
Print job was sent to '{0}'.
- Drop shadow (/)
+ Drop shadow
Image stored to clipboard.
Line thickness
Greenshot image editor
@@ -185,7 +178,7 @@ Please check write accessibility of the selected storage location.
Suppress the save dialog when closing the editor
Show window thumbnails in context menu (for Vista and windows 7)
Exported to: {0}
- An error occurred while exporting to {0}:
+ An error occured while exporting to {0}:
Greenshot Help
Hotkeys
Please choose the JPEG quality for your image.
@@ -239,7 +232,6 @@ ${hh} hour, 2 digits
${mm} minute, 2 digits
${ss} second, 2 digits
${NUM} incrementing number, 6 digits
-${RRR...} random alphanumerics, same length as 'R's
${title} Window title
${user} Windows user
${domain} Windows domain
@@ -312,7 +304,7 @@ All Greenshot features still work directly from the tray icon context menu witho
Add counter (I)
Add speechbubble (S)
- Resize (Z)
+ Resize
Resize settings
Maintain aspect ratio
Width
@@ -320,4 +312,4 @@ All Greenshot features still work directly from the tray icon context menu witho
Icon size
-
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/language-es-ES.xml b/Greenshot/Languages/language-es-ES.xml
similarity index 97%
rename from src/Greenshot/Languages/language-es-ES.xml
rename to Greenshot/Languages/language-es-ES.xml
index 0badf64a4..190e1f832 100644
--- a/src/Greenshot/Languages/language-es-ES.xml
+++ b/Greenshot/Languages/language-es-ES.xml
@@ -5,7 +5,7 @@
Si te gusta Greenshot, te agradeceremos que nos ayudes:
Greenshot está alojado en GitHub en
Iconos del conjunto de iconos Fugue de Yusuke Kamiyamane(Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot viene ABSOLUTAMENTE SIN GARANTIA. Este es software gratuito, y eres bienvenido a redistribuirlo bajo ciertas condiciones.
Detalles acerca de la Licencia General Publica GNU:
Acerca de Greenshot
@@ -80,8 +80,6 @@ Antes de crear un nuevo informe de error, te agradeceríamos que comprobaras que
Copiar ruta al portapapeles
Copiar
Recortar(C)
- Recortar
- Autorrecortar
Herramienta de selección (ESC)
Cortar
Borrar
diff --git a/src/Greenshot/Languages/language-et-EE.xml b/Greenshot/Languages/language-et-EE.xml
similarity index 97%
rename from src/Greenshot/Languages/language-et-EE.xml
rename to Greenshot/Languages/language-et-EE.xml
index 7a4b0dcc3..fbe51c0d4 100644
--- a/src/Greenshot/Languages/language-et-EE.xml
+++ b/Greenshot/Languages/language-et-EE.xml
@@ -5,7 +5,7 @@
Greenshoti kasutamismugavust ja arendust saate toetada siin:
Greenshot asub portaalis GitHub
Yusuke Kamiyamane on ikoonide tegija Fugue ikooni paketist (Creative Commons Attribution 3.0 litsents)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
Greenshot ei paku GARANTIID. See on vabaravaline programm ja Te võite seda levitava vabalt teatud tingimuste alusel.
Lisainfo GNU Põhilise Avaliku Litsentsi kohta:
Info Greenshoti kohta
@@ -14,7 +14,7 @@ Lisainfo GNU Põhilise Avaliku Litsentsi kohta:
Vabandust aga ilmnes tundmatu viga.
Hea uudis on: saate meil aidata seda eemaldada saates meile veateate.
-Uue veateate teavitamiseks, palun külastage kõrvalolevat URLi ja tekstialalt asetage sisu kirjeldusse.
+Uue veateate teavitamiseks, palun külastage kõrvalolevat URLi ja tekstialalt asetage sisu kirjeldusse.
Vea paremaks parandamiseks lisage palun arusaadav kokkuvõte veast ja lisage ka pisidetailid.
Me oleksime väga tänulik, kui te enne kontrolliksite, ega sellest veast pole juba teavitatud. (Postituse kiiresti leidmiseks kasutage otsingut.) Aitäh :)
@@ -92,8 +92,6 @@ Me oleksime väga tänulik, kui te enne kontrolliksite, ega sellest veast pole j
Kopeerige asukoht lõikelauale
Kopeeri
Lõika (C)
- Lõika
- Automaatne lõikus
Valiku tööriist (ESC)
Lõika
Kustuta
diff --git a/src/Greenshot/Languages/language-fa-IR.xml b/Greenshot/Languages/language-fa-IR.xml
similarity index 98%
rename from src/Greenshot/Languages/language-fa-IR.xml
rename to Greenshot/Languages/language-fa-IR.xml
index 2ab2c8242..20e1da09f 100644
--- a/src/Greenshot/Languages/language-fa-IR.xml
+++ b/Greenshot/Languages/language-fa-IR.xml
@@ -67,7 +67,6 @@ Could not save Greenshot's configuration file. Please check access permissions f
رونویس
چیدن
(C دکمه)
- چیدن
انتخابگر
(ESC دکمه)
برش
diff --git a/src/Greenshot/Languages/language-fi-FI.xml b/Greenshot/Languages/language-fi-FI.xml
similarity index 97%
rename from src/Greenshot/Languages/language-fi-FI.xml
rename to Greenshot/Languages/language-fi-FI.xml
index a2f211b03..88384f60e 100644
--- a/src/Greenshot/Languages/language-fi-FI.xml
+++ b/Greenshot/Languages/language-fi-FI.xml
@@ -5,7 +5,7 @@
Jos pidät Greenshotista niin toivottavasti tuet meitä:
Greenshot is hosted by GitHub at
Ikonit ovat Yusuke Kamiyamane:n Fugue ikonisarjasta (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
Details about the GNU General Public License:
Tietoja Greenshotista
@@ -62,7 +62,6 @@ Olisi myös hyvä jos voisit tarkistaa onko virhe jo raportoitu aikaisemmin (voi
Kopioi tiedostopolku leikepöydälle
Kopioi
Rajaa (C)
- Rajaa
Valintatyökalu (ESC)
Leikkaa
Poista
diff --git a/src/Greenshot/Languages/language-fr-FR.xml b/Greenshot/Languages/language-fr-FR.xml
similarity index 97%
rename from src/Greenshot/Languages/language-fr-FR.xml
rename to Greenshot/Languages/language-fr-FR.xml
index 4ef502438..0a6ff34a5 100644
--- a/src/Greenshot/Languages/language-fr-FR.xml
+++ b/Greenshot/Languages/language-fr-FR.xml
@@ -5,7 +5,7 @@
Si vous aimez Greenshot, vous pouvez nous soutenir :
Greenshot est hébergé par GitHub à
Icônes provenant du lot d'icônes Fugue de Kamiyamane Yuusuke (Creative Commons Attribution 3.0 license)
- Copyright © 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright © 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot vous est fourni SANS AUCUNE GARANTIE. C'est un logiciel gratuit que vous êtes libres de redistribuer sous certaines conditions.
Détails de la GNU General Public License :
À propos de Greenshot
@@ -93,8 +93,6 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
Copier
Ajouter un compteur
Recadrer (C)
- Recadrer
- Cadrage automatique
Outil de sélection (ESC)
Couper
Supprimer
@@ -144,7 +142,7 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
Imprimer
Rétablir {0}
Réinitialiser la taille
- Redimensionner (Z)
+ Redimensionner
Maintenir le rapport L / H
Hauteur
Pourcentage
diff --git a/src/Greenshot/Languages/language-fr-QC.xml b/Greenshot/Languages/language-fr-QC.xml
similarity index 97%
rename from src/Greenshot/Languages/language-fr-QC.xml
rename to Greenshot/Languages/language-fr-QC.xml
index cf822fa16..4e1884644 100644
--- a/src/Greenshot/Languages/language-fr-QC.xml
+++ b/Greenshot/Languages/language-fr-QC.xml
@@ -5,7 +5,7 @@
Si vous aimez Greenshot, vous pouvez nous soutenir :
Greenshot est hébergé par GitHub à
Icônes provenant du lot d'icônes Fugue de Kamiyamane Yuusuke (Creative Commons Attribution 3.0 license)
- Copyright © 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright © 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
Greenshot vous est fourni SANS AUCUNE GARANTIE. C'est un logiciel gratuit que vous êtes libres de redistribuer sous certaines conditions.
Détails de la GNU General Public License :
A propos de Greenshot
@@ -78,8 +78,6 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
Copier le chemin vers le presse-papier
Copier
Rogner (C)
- Rogner
- Rognage automatique
Outil de sélection (ESC)
Couper
Supprimer
diff --git a/src/Greenshot/Languages/language-he-IL.xml b/Greenshot/Languages/language-he-IL.xml
similarity index 97%
rename from src/Greenshot/Languages/language-he-IL.xml
rename to Greenshot/Languages/language-he-IL.xml
index 537f77067..b8e219bf0 100644
--- a/src/Greenshot/Languages/language-he-IL.xml
+++ b/Greenshot/Languages/language-he-IL.xml
@@ -5,7 +5,7 @@
:אם את\ה נהנה\ית משימוש בתוכנה, את\ה מוזמן לתרום לנו
Greenshot is hosted by GitHub at
Icons from Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
Details about the GNU General Public License:
Greenshot אודות התוכנה
@@ -63,7 +63,6 @@ Details about the GNU General Public License:
העתק נתיב אל הלוח
העתקה
חתוך (C)
- חתוך
כלי בחירה (ESC)
חיתוך
מחיקה
diff --git a/src/Greenshot/Languages/language-hu-HU.xml b/Greenshot/Languages/language-hu-HU.xml
similarity index 97%
rename from src/Greenshot/Languages/language-hu-HU.xml
rename to Greenshot/Languages/language-hu-HU.xml
index 20035f3c5..cd5382890 100644
--- a/src/Greenshot/Languages/language-hu-HU.xml
+++ b/Greenshot/Languages/language-hu-HU.xml
@@ -5,7 +5,7 @@
Ha szereted Greenshot -ot, akkor támogass minket:
Greenshot kiszolgálója a GitHub
Az ikonokat Yusuke Kamiyamane's Fugue készítette (Creative Commons Attribution 3.0 license)
- Szerzői jog (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Szerzői jog (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
SEMMIFÉLE GARANCIA sincs a Greenshot -hoz. Ez egy ingyenes program, és hálásak vagyunk, hogy terjeszted bizonyos feltételekkel.
Részletek a GNU Fő Nyílvános Engedélyről:
Greenshot névjegye
@@ -63,7 +63,6 @@ Kérjük adjon összefoglaló leírást és csatoljon minden olyan információt
Másolja a vágólapra
Másolás
Vágás eszköz (C)
- Vágás eszköz
Kiválasztó eszköz (ESC)
Kivágás
Törlés
diff --git a/src/Greenshot/Languages/language-id-ID.xml b/Greenshot/Languages/language-id-ID.xml
similarity index 97%
rename from src/Greenshot/Languages/language-id-ID.xml
rename to Greenshot/Languages/language-id-ID.xml
index fcb887082..315dcba9f 100644
--- a/src/Greenshot/Languages/language-id-ID.xml
+++ b/Greenshot/Languages/language-id-ID.xml
@@ -5,18 +5,18 @@
Jika anda menyukai Greenshot, anda dipersilahkan untuk mendukung kami:
Greenshot dikelola oleh GitHub di
Ikon dari Yusuke Kamiyamane Fugue ikon set (lisensi Creative Commons Attribution 3.0)
- Hak Cipta milik Thomas Braun, Jens Klingen, Robin Krom 2007-2021
-Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
+ Hak Cipta milik Thomas Braun, Jens Klingen, Robin Krom 2007-2015
+Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
Details about the GNU General Public License:
Tentang Greenshot
Greenshot - utilitas penangkap layar yang revolusioner
Tutup
- Maaf, kesalahan yang tak terduga terjadi.
-
-Kabar baiknya: anda dapat membantu kami memperbaikinya dengan mengisi laporan kesalahan.
-Harap kunjungi laman berikut, buat laporan kesalahan baru dan letakkan konten dari area teks ke wadah deskripsi.
-
-Harap tambah penjelasan yang berarti dan sertakan informasi lain yang penting untuk kami tiru kesalahannya.
+ Maaf, kesalahan yang tak terduga terjadi.
+
+Kabar baiknya: anda dapat membantu kami memperbaikinya dengan mengisi laporan kesalahan.
+Harap kunjungi laman berikut, buat laporan kesalahan baru dan letakkan konten dari area teks ke wadah deskripsi.
+
+Harap tambah penjelasan yang berarti dan sertakan informasi lain yang penting untuk kami tiru kesalahannya.
Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan kepunyaan anda. (Anda dapat menggunakan pencarian untuk mencari dengan cepat.) Terima kasih :)
Kesalahan
Batal
@@ -93,8 +93,6 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
Kopi
Buat penomor
Potong (C)
- Potong
- Auto potong
Alat seleksi (ESC)
Gunting
Hapus
@@ -144,7 +142,7 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
Cetak
Ulang {0}
Reset ukuran
- Ubah ukuran (Z)
+ Ubah ukuran
Pertahankan aspek rasio
Tinggi
Persen
@@ -182,7 +180,7 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
Outlook dengan teks
Kesalahan
Sesuatu dari Greenshot telah dijalankan.
- Tidak dapat berkas {0}.
+ Tidak dapat berkas {0}.
Harap cek aksesibilitas menuis pada lokasi penyimpanan yang dipilih.
Berkas "{0}" tidak dapat dibuka.
Tidak dapat membuka link '{0}'.
@@ -247,22 +245,22 @@ Harap cek aksesibilitas menuis pada lokasi penyimpanan yang dipilih.
Tangkap Internet Explorer
Kualitas JPEG
Bahasa
- Pedoman berikut akan ditimpa otomatis dalam pola yang ditetapkan:
-${YYYY} tahun, 4 digit
-${MM} bulan, 2 digit
-${DD} hari, 2 digit
-${hh} jam, 2 digit
-${mm} menit, 2 digit
-${ss} detik, 2 digit
-${NUM} angka tambahan, 6 digit
-${title} judul jendela
-${user} pengguna Windows
-${domain} domain Windows
-${hostname} nama PC
-
-Anda juga dapat membuat direktori Greenshot secara dinamis, cukup gunakan simbol garis miring {\} untuk memisahkan folder dan nama berkas
-Contoh: pola ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
-akan menbuat folder untuk hari terbaru di lokasi penyimpan default, cont. 2008-06-29, nama berkas didasarkan pada waktu terbaru
+ Pedoman berikut akan ditimpa otomatis dalam pola yang ditetapkan:
+${YYYY} tahun, 4 digit
+${MM} bulan, 2 digit
+${DD} hari, 2 digit
+${hh} jam, 2 digit
+${mm} menit, 2 digit
+${ss} detik, 2 digit
+${NUM} angka tambahan, 6 digit
+${title} judul jendela
+${user} pengguna Windows
+${domain} domain Windows
+${hostname} nama PC
+
+Anda juga dapat membuat direktori Greenshot secara dinamis, cukup gunakan simbol garis miring {\} untuk memisahkan folder dan nama berkas
+Contoh: pola ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+akan menbuat folder untuk hari terbaru di lokasi penyimpan default, cont. 2008-06-29, nama berkas didasarkan pada waktu terbaru
cont, 11_58_32 (ditambah ekstensi yang ditetapkan pada pengaturan)
Jaringan dan pembaruan
Output
@@ -298,8 +296,8 @@ cont, 11_58_32 (ditambah ekstensi yang ditetapkan pada pengaturan)
Versi baru Greenshot telah tersedia! Apakah anda ingin mengunduh Greenshot {0}?
Harap tunggu ketika halaman Internet Explorer sedang ditangkap
Peringatan
- hotkey {0} tak dapat terdaftar, kemungkinan akibat alat lain telah mengklaim penggunaan hotkey, anda dapat mengganti hotkey yang lain atau menonaktifkannya.
-
+ hotkey {0} tak dapat terdaftar, kemungkinan akibat alat lain telah mengklaim penggunaan hotkey, anda dapat mengganti hotkey yang lain atau menonaktifkannya.
+
Semua fitur Greenshot masih bekerja dengan baik dari ikon tray menu konteks tanpa hotkey.
Gunakan warna kesukaan
Pertahankan kebeningan
diff --git a/src/Greenshot/Languages/installer/language-installer-de-DE.xml b/Greenshot/Languages/language-installer-de-DE.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-de-DE.xml
rename to Greenshot/Languages/language-installer-de-DE.xml
index de1fa31e3..ffbbafc05 100644
--- a/src/Greenshot/Languages/installer/language-installer-de-DE.xml
+++ b/Greenshot/Languages/language-installer-de-DE.xml
@@ -1,14 +1,14 @@
-
-
-
- {#ExeName} starten wenn Windows hochfährt
- {#ExeName} starten
- Jira Plug-in
- Confluence Plug-in
- Öffne mit ein externem Kommando Plug-in
- OCR Plug-in (benötigt Microsoft Office Document Imaging (MODI))
- Imgur Plug-in (Siehe: https://imgur.com)
- Zusätzliche Sprachen
- Optimierung der Leistung, kann etwas dauern.
-
+
+
+
+ {#ExeName} starten wenn Windows hochfährt
+ {#ExeName} starten
+ Jira Plug-in
+ Confluence Plug-in
+ Öffne mit ein externem Kommando Plug-in
+ OCR Plug-in (benötigt Microsoft Office Document Imaging (MODI))
+ Imgur Plug-in (Siehe: http://imgur.com)
+ Zusätzliche Sprachen
+ Optimierung der Leistung, kann etwas dauern.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-en-US.xml b/Greenshot/Languages/language-installer-en-US.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-en-US.xml
rename to Greenshot/Languages/language-installer-en-US.xml
index 10d3edd56..058b19a91 100644
--- a/src/Greenshot/Languages/installer/language-installer-en-US.xml
+++ b/Greenshot/Languages/language-installer-en-US.xml
@@ -1,14 +1,14 @@
-
-
-
- Start {#ExeName} with Windows start
- Start {#ExeName}
- Jira plug-in
- Confluence plug-in
- Open with external command plug-in
- OCR plug-in (needs Microsoft Office Document Imaging (MODI))
- Imgur plug-in (See: https://imgur.com)
- Additional languages
- Optimizing performance, this may take a while.
-
+
+
+
+ Start {#ExeName} with Windows start
+ Start {#ExeName}
+ Jira plug-in
+ Confluence plug-in
+ Open with external command plug-in
+ OCR plug-in (needs Microsoft Office Document Imaging (MODI))
+ Imgur plug-in (See: http://imgur.com)
+ Additional languages
+ Optimizing performance, this may take a while.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-es-ES.xml b/Greenshot/Languages/language-installer-es-ES.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-es-ES.xml
rename to Greenshot/Languages/language-installer-es-ES.xml
index 55bf0e7fc..78a27e00d 100644
--- a/src/Greenshot/Languages/installer/language-installer-es-ES.xml
+++ b/Greenshot/Languages/language-installer-es-ES.xml
@@ -1,14 +1,14 @@
-
-
-
- Extensión para Confluence
- Extensión para abrir con programas externos
- Extensión para Imgur (Ver https://imgur.com)
- Extensión para Jira
- Idiomas adicionales
- Extensión para OCR (necesita Microsoft Office Document Imaging (MODI))
- Optimizando rendimiento; por favor, espera.
- Lanzar {#ExeName}
- Lanzar {#ExeName} al iniciarse Windows
-
+
+
+
+ Extensión para Confluence
+ Extensión para abrir con programas externos
+ Extensión para Imgur (Ver http://imgur.com)
+ Extensión para Jira
+ Idiomas adicionales
+ Extensión para OCR (necesita Microsoft Office Document Imaging (MODI))
+ Optimizando rendimiento; por favor, espera.
+ Lanzar {#ExeName}
+ Lanzar {#ExeName} al iniciarse Windows
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-fi-FI.xml b/Greenshot/Languages/language-installer-fi-FI.xml
similarity index 88%
rename from src/Greenshot/Languages/installer/language-installer-fi-FI.xml
rename to Greenshot/Languages/language-installer-fi-FI.xml
index ba2133261..90d9376c9 100644
--- a/src/Greenshot/Languages/installer/language-installer-fi-FI.xml
+++ b/Greenshot/Languages/language-installer-fi-FI.xml
@@ -1,14 +1,14 @@
-
-
-
- Käynnistä {#ExeName} Windowsin käynnistyessä
- Käynnistä {#ExeName}
- Jira-liitännäinen
- Confluence-liitännäinen
- Avaa Ulkoinen komento-liitännäisellä
- OCR-liitännäinen (Tarvitaan: Microsoft Office Document Imaging (MODI))
- Imgur-liitännäinen (Katso: https://imgur.com)
- Lisäkielet
- Optimoidaan suorituskykyä, tämä voi kestää hetken.
-
+
+
+
+ Käynnistä {#ExeName} Windowsin käynnistyessä
+ Käynnistä {#ExeName}
+ Jira-liitännäinen
+ Confluence-liitännäinen
+ Avaa Ulkoinen komento-liitännäisellä
+ OCR-liitännäinen (Tarvitaan: Microsoft Office Document Imaging (MODI))
+ Imgur-liitännäinen (Katso: http://imgur.com)
+ Lisäkielet
+ Optimoidaan suorituskykyä, tämä voi kestää hetken.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-fr-FR.xml b/Greenshot/Languages/language-installer-fr-FR.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-fr-FR.xml
rename to Greenshot/Languages/language-installer-fr-FR.xml
index 3448e83d1..608e2fe3f 100644
--- a/src/Greenshot/Languages/installer/language-installer-fr-FR.xml
+++ b/Greenshot/Languages/language-installer-fr-FR.xml
@@ -1,14 +1,14 @@
-
-
-
- Greffon Confluence
- Ouvrir avec le greffon de commande externe
- Greffon Imgur (Voir: https://imgur.com)
- Greffon Jira
- Langues additionnelles
- Greffon OCR (nécessite Document Imaging de Microsoft Office [MODI])
- Optimisation des performances, Ceci peut prendre un certain temps.
- Démarrer {#ExeName}
- Lancer {#ExeName} au démarrage de Windows
-
+
+
+
+ Greffon Confluence
+ Ouvrir avec le greffon de commande externe
+ Greffon Imgur (Voir: http://imgur.com)
+ Greffon Jira
+ Langues additionnelles
+ Greffon OCR (nécessite Document Imaging de Microsoft Office [MODI])
+ Optimisation des performances, Ceci peut prendre un certain temps.
+ Démarrer {#ExeName}
+ Lancer {#ExeName} au démarrage de Windows
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-lv-LV.xml b/Greenshot/Languages/language-installer-lv-LV.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-lv-LV.xml
rename to Greenshot/Languages/language-installer-lv-LV.xml
index 7755045f4..ef7a30d6d 100644
--- a/src/Greenshot/Languages/installer/language-installer-lv-LV.xml
+++ b/Greenshot/Languages/language-installer-lv-LV.xml
@@ -8,7 +8,7 @@
Confluence spraudnis
Pielāgotu darbību spraudnis
OCR spraudnis (nepieciešams Microsoft Office Document Imaging (MODI))
- Imgur spraudnis (Vairāk šeit: https://imgur.com)
+ Imgur spraudnis (Vairāk šeit: http://imgur.com)
Papildus valodas
Uzlaboju veikstpēju, tas prasīs kādu laiciņu.
diff --git a/src/Greenshot/Languages/installer/language-installer-nl-NL.xml b/Greenshot/Languages/language-installer-nl-NL.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-nl-NL.xml
rename to Greenshot/Languages/language-installer-nl-NL.xml
index 83764d32d..612f3943c 100644
--- a/src/Greenshot/Languages/installer/language-installer-nl-NL.xml
+++ b/Greenshot/Languages/language-installer-nl-NL.xml
@@ -1,14 +1,14 @@
-
-
-
- Prestaties verbeteren, kan even duren.
- Extra talen
- Imgur plug-in (Zie: https://imgur.com)
- OCR plug-in (heeft Microsoft Office Document Imaging (MODI) nodig)
- Open met externes commando plug-in
- Confluence plug-in
- Jira plug-in
- Start {#ExeName}
- Start {#ExeName} wanneer Windows opstart
-
+
+
+
+ Prestaties verbeteren, kan even duren.
+ Extra talen
+ Imgur plug-in (Zie: http://imgur.com)
+ OCR plug-in (heeft Microsoft Office Document Imaging (MODI) nodig)
+ Open met externes commando plug-in
+ Confluence plug-in
+ Jira plug-in
+ Start {#ExeName}
+ Start {#ExeName} wanneer Windows opstart
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-nn-NO.xml b/Greenshot/Languages/language-installer-nn-NO.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-nn-NO.xml
rename to Greenshot/Languages/language-installer-nn-NO.xml
index 2b31da768..cfa04e16e 100644
--- a/src/Greenshot/Languages/installer/language-installer-nn-NO.xml
+++ b/Greenshot/Languages/language-installer-nn-NO.xml
@@ -1,14 +1,14 @@
-
-
-
- Confluence-tillegg
- Tillegg for å opne med ekstern kommando
- Imgur-tillegg (sjå https://imgur.com)
- Jira-tillegg
- Andre språk
- OCR-tillegg (krev Microsoft Office Document Imaging (MODI))
- Optimaliserar ytelse, dette kan ta litt tid...
- Start {#ExeName}
- Start {#ExeName} når Windows startar
-
+
+
+
+ Confluence-tillegg
+ Tillegg for å opne med ekstern kommando
+ Imgur-tillegg (sjå http://imgur.com)
+ Jira-tillegg
+ Andre språk
+ OCR-tillegg (krev Microsoft Office Document Imaging (MODI))
+ Optimaliserar ytelse, dette kan ta litt tid...
+ Start {#ExeName}
+ Start {#ExeName} når Windows startar
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-sr-RS.xml b/Greenshot/Languages/language-installer-sr-RS.xml
similarity index 95%
rename from src/Greenshot/Languages/installer/language-installer-sr-RS.xml
rename to Greenshot/Languages/language-installer-sr-RS.xml
index 858e2a492..b55e6d893 100644
--- a/src/Greenshot/Languages/installer/language-installer-sr-RS.xml
+++ b/Greenshot/Languages/language-installer-sr-RS.xml
@@ -1,14 +1,14 @@
-
-
-
- Прикључак за Конфлуенс
- Отвори са прикључком за спољне наредбе
- Прикључак за Имиџер (https://imgur.com)
- Прикључак за Џиру
- Додатни језици
- OCR прикључак (захтева Microsoft Office Document Imaging (MODI))
- Оптимизујем перформансе…
- Покрени Гриншот
- Покрени програм са системом
-
+
+
+
+ Прикључак за Конфлуенс
+ Отвори са прикључком за спољне наредбе
+ Прикључак за Имиџер (http://imgur.com)
+ Прикључак за Џиру
+ Додатни језици
+ OCR прикључак (захтева Microsoft Office Document Imaging (MODI))
+ Оптимизујем перформансе…
+ Покрени Гриншот
+ Покрени програм са системом
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/installer/language-installer-sv-SE.xml b/Greenshot/Languages/language-installer-sv-SE.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-sv-SE.xml
rename to Greenshot/Languages/language-installer-sv-SE.xml
index 6c1004ebf..92b7f27ef 100644
--- a/src/Greenshot/Languages/installer/language-installer-sv-SE.xml
+++ b/Greenshot/Languages/language-installer-sv-SE.xml
@@ -7,7 +7,7 @@
Confluence-insticksprogram
Öppna med externt kommando-insticksprogram
OCR-insticksprogram (kräver Microsoft Office Document Imaging (MODI))
- Imgur-insticksprogram (Se: https://imgur.com)
+ Imgur-insticksprogram (Se: http://imgur.com)
Ytterligare språk
Optimerar prestanda, detta kan ta en stund.
diff --git a/src/Greenshot/Languages/installer/language-installer-uk-UA.xml b/Greenshot/Languages/language-installer-uk-UA.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-uk-UA.xml
rename to Greenshot/Languages/language-installer-uk-UA.xml
index 8de33e3ba..d10360622 100644
--- a/src/Greenshot/Languages/installer/language-installer-uk-UA.xml
+++ b/Greenshot/Languages/language-installer-uk-UA.xml
@@ -1,14 +1,14 @@
-
-
-
- Запускати {#ExeName} під час запуску Windows
- Запустити {#ExeName}
- Плагін Jira
- Плагін Confluence
- Плагін запуску зовнішньої команди
- Плагін OCR (потребує Microsoft Office Document Imaging (MODI))
- Плагін Imgur (див.: https://imgur.com)
- Додаткові мови
- Оптимізація продуктивності, це може зайняти певний час.
-
-
+
+
+
+ Запускати {#ExeName} під час запуску Windows
+ Запустити {#ExeName}
+ Плагін Jira
+ Плагін Confluence
+ Плагін запуску зовнішньої команди
+ Плагін OCR (потребує Microsoft Office Document Imaging (MODI))
+ Плагін Imgur (див.: http://imgur.com)
+ Додаткові мови
+ Оптимізація продуктивності, це може зайняти певний час.
+
+
diff --git a/src/Greenshot/Languages/installer/language-installer-zh-CN.xml b/Greenshot/Languages/language-installer-zh-CN.xml
similarity index 79%
rename from src/Greenshot/Languages/installer/language-installer-zh-CN.xml
rename to Greenshot/Languages/language-installer-zh-CN.xml
index 3abce374d..c73a564b4 100644
--- a/src/Greenshot/Languages/installer/language-installer-zh-CN.xml
+++ b/Greenshot/Languages/language-installer-zh-CN.xml
@@ -1,14 +1,14 @@
-
-
-
- Confluence插件
- 使用外部命令打开插件
- Imgur插件( (请访问: https://imgur.com))
- Jira插件
- 其它语言
- OCR插件(需要Microsoft Office Document Imaging (MODI)的支持)
- 正在优化性能,这可能需要一点时间。
- 启动{#ExeName}
- 让{#ExeName}随Windows一起启动
-
+
+
+
+ Confluence插件
+ 使用外部命令打开插件
+ Imgur插件( (请访问: http://imgur.com))
+ Jira插件
+ 其它语言
+ OCR插件(需要Microsoft Office Document Imaging (MODI)的支持)
+ 正在优化性能,这可能需要一点时间。
+ 启动{#ExeName}
+ 让{#ExeName}随Windows一起启动
+
\ No newline at end of file
diff --git a/Greenshot/Languages/language-it-IT.xml b/Greenshot/Languages/language-it-IT.xml
new file mode 100644
index 000000000..5e7243f54
--- /dev/null
+++ b/Greenshot/Languages/language-it-IT.xml
@@ -0,0 +1,313 @@
+
+
+
+ Per favore, riporta le anomalie a
+ Se gradisci Greenshot, puoi darci il tuo aiuto su:
+ Greenshot è disponibile su GitHub a
+ Icone prese da Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+Greenshot viene fornito SENZA ALCUNA GARANZIA. Questo è "free software", e potete ri-distribuirlo secondo certe condizioni.
+Dettagli sulla General Public License GNU:
+ Notizie su Greenshot
+ Traduzione in Italiano curata da tonytogna
+ Greenshot - Uno straordinario strumento per copiare immagini dallo schermo
+ Chiudi
+ Opss, si è verificato un errore inaspettato.
+
+La buona notizia è: puoi aiutarci ad eliminarlo riempiendo la segnalazione errori.
+Visita la pagina internet qui sotto, crea una nuova segnalazione errore e copia nella descrizione il contenuto preso dall'area di testo.
+
+Aggiungi un riepilogo significativo e includi qualsiasi informazione tu consideri possa esserci d'aiuto per risolvere il problema.
+Inoltre, apprezzeremo molto se prima di inserire, tu controllassi se esiste già una segnalazione per questo tipo di errore (puoi usare la ricerca) Grazie :)
+ Errore
+ Annulla
+ Si è verificato un errore inaspettato durante la scrittura sugli appunti.
+ Nessuna immagine sugli Appunti.
+ Greenshot non è riuscito a scrivere sugli appunti poichè il processo {0} teneva l'accesso bloccato.
+ Windows Bitmap
+ Device Independend Bitmap (DIB)
+ HTML
+ HTML con immagini in linea
+ PNG
+ Alfa
+ Applica
+ Blu
+ Verde
+ Colore HTML
+ Colori usati di recente
+ Rosso
+ Scelta colore
+ Trasparente
+ La destinazione {0} ha rifiutato l'accesso a Greenshot, probabilmente c'è una finestra aperta. Chiudi la finestra e riprova nuovamente.
+ Accesso rifiutato a Greenshot
+ Il file di configurazione di Greenshot non può essere salvato. Controllare i permessi di accesso per '{0}'.
+ Notizie su Greenshot
+ Cattura regione
+ Apri immagine dagli appunti
+ Cattura schermo intero
+ Tutto
+ Basso
+ Sinistra
+ Destra
+ Alto
+ Cattura Internet Explorer
+ Cattura Internet Explorer da lista
+ Cattura ultima regione
+ Cattura finestra
+ Cattura finestra da lista
+ Supporta Greenshot
+ Esci
+ Aiuto
+ Apri immagine da file
+ Apri ultima ubicazione di cattura
+ Preferenze veloci
+ Preferenze...
+ Errori durente l'esportazione verso {0}. Pregasi riprovare nuovamente.
+ In basso
+ Centro
+ Allineamento orizzontale
+ Sinistra
+ In mezzo
+ Destra
+ Alto
+ Allineamento verticale
+ Disponi
+ Tipi di punta di freccia
+ Entrambe
+ Punto finale
+ Nessuna
+ Punto iniziale
+ Ritaglia Automaticamente
+ Colore di riempimento
+ Raggio sfumatura
+ Grassetto
+ Bordi
+ Luminosità
+ Cancella
+ Errore durante l'accesso agli appunti. Ritenta nuovamente.
+ Chiudi
+ Desideri salvare l'immagine?
+ Salva l'immagine?
+ Conferma
+ Copia immagine sugli appunti
+ Copia percorso sugli appunti
+ Copia
+ Ritaglia (C)
+ Strumento di selezione (ESC)
+ Taglia
+ Elimina
+ Giù di un livello
+ Giù fino in fondo
+ Disegna freccia (A)
+ Disegna ellisse (E)
+ Disegna mano libera (F)
+ Evidenzia (H)
+ Disegna linea (L)
+ Disegna rettangolo (R)
+ Aggiungi casella di testo (T)
+ Duplica elementi selezionati
+ Modifica
+ Effetti
+ E-Mail
+ File
+ Dimensioni
+ Colore linea
+ Scala di grigi
+ Evidenzia l'area
+ Scala di grigi
+ Ingrandisci
+ Modalità evidenziazione
+ Evidenzia il testo
+ Aggiungi ombra
+ Immagine salvata su {0}.
+ Inserisci finestra
+ Negativo
+ Corsivo
+ Carica oggetti da file
+ Fattore di ingrandimento
+ Adatta a dimensioni di cattura
+ Offusca (O)
+ Sfuma
+ Modalità di offuscamento
+ Offusca/ pixelize
+ Oggetti
+ Apri cartella su Windows Explorer
+ Incolla
+ Dimensioni pixel
+ Qualità anteprima
+ Stampa
+ Ripeti azione {0}
+ Azzera Dimensione
+ Percentuale
+ Pixels
+ Ruota senso antiorario
+ Ruota senso orario
+ Salva
+ Salva oggetti su file
+ Salva come...
+ Seleziona tutto
+ Stampa inviata a '{0}'.
+ Ombra
+ Ombra
+ Immagine posta negli appunti (clipboard).
+ Spessore linea
+ Gestione Immagini di Greenshot
+ Bordi strappati
+ Annulla azione {0}
+ Su di un livello
+ Su fino in cima
+ Client MAPI
+ Outlook con HTML
+ Outlook con testo
+ Errore
+ Un istanza di Greenshot è già attiva.
+ Non è possibile salvare il file su {0}.
+Verifica l'accesso in scrittura sulla destinazione di salvataggio.
+ Il file "{0}" non può essere aperto.
+ Impossibile aprire il link '{0}'.
+ Impossibile salvare l'immagine, è necessario trovare una destinazione valida.
+ Utente esperto
+ Crea una immagine 8-bit se i colori sono meno di 256 e l'immagine ha > 8 bits
+ Controlla anche per Aggiornamenti instabili
+ Formati degli appunti
+ Numero per var. ${NUM} nel modello del nome file
+ Sono consapevole di ciò che sto facendo!
+ Modello piede di stampa
+ Riduci uso della memoria, perdendo però in prestazioni (sconsigliato).
+ Esegui ottimizzazioni per uso con desktop remoto
+ Riutilizza la Gestione Immagini, se possibile
+ Evita avviso di salvataggio in chiusura della gestione immagini
+ Mostra anteprima finestra nel menù di contesto (Vista e Windows 7)
+ Esportato su: {0}
+ Si è verificato un errore durante l'esportazione verso {0}:
+ Guida di Greenshot
+ Scorciatoie di tastiera
+ Scegliere la qualità per l'immagine JPEG.
+ Salva come qualità JPEG di default, e non chiedere nuovamente
+ Qualità JPEG di Greenshot
+ Ok
+ Si è verificato un errore durante la stampa.
+ Centra nella pagina
+ Ingrandisci fino alle dimensioni pagina
+ Ruota a seconda dell'orientamento pagina
+ Riduci alle dimensioni pagina
+ Salva le opzioni come default, e non chiedere più
+ Stampa con colori invertiti (negativo)
+ Impostazione Colori
+ Forza stampa in scala di grigi
+ Forza stampa in bianco e nero
+ Stampa data / ora sul piede della pagina
+ Opzioni di stampa di Greenshot
+ Impostazioni Layout di pagina
+ Forza stampa a colori
+ Save come qualità di default, e non chiedere più
+ Qualità di Greenshot
+ Salva direttamente (usando le impostazioni di emissione preferite)
+ Visualizza scelta opzioni di stampa ogni volta che si stampa un'immagine
+ Visualizza scelta qualità ogni volta che si salva una immagine
+ Impostazioni dell'applicazione
+ Lancia Greenshot all'avvio
+ Cattura
+ Cattura puntatore mouse
+ Usa la modalità di cattura via finestra interattiva
+ Intervallo di controllo aggiornamento, in giorni (0=nessun controllo)
+ Configura
+ Copia percorso file sugli appunti, ogni volta che una immagine viene salvata
+ Destinazione dell'immagine
+ Copia sugli appunti
+ Apri in Gest. Immagini
+ E-Mail
+ Salva direttamente (usando le impostazioni qui sotto esposte)
+ Salva come (visualizzando le scelte)
+ Scegli la destinazione dinamicamente
+ Invia alla stampante
+ Gestione Immagini
+ Modello del Nome File
+ Generali
+ Cattura Internet Explorer
+ Qualità JPEG
+ Impostazioni JPEG
+ Lingua
+ I parametri racchiusi tra % verranno sostituiti automaticamente:
+${YYYY} anno, 4 digits
+${MM} mese, 2 digits
+${DD} giorno, 2 digits
+${hh} ora, 2 digits
+${mm} minuti, 2 digits
+${ss} secondi, 2 digits
+${NUM} numero progressivo, 6 digits
+${title} Titolo finestra
+${user} Utente Windows
+${domain} Dominio Windows
+${hostname} Nome PC
+
+Puoi anche chiedere a Greenshot di creare le cartelle dinamicamente, basta usare la barra rovescia (\) per separare cartelle e nome file.
+Esempio: il modello ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+genererà una cartella per il giorno corrente sulla destinazione di memorizzazione di default, es: 2008-06-29, il nome del file di immagine sarà basato sull'orario
+corrente, es: 11_58_32 (più l'estensione definita nelle impostazioni)
+ Rete e aggiornamenti
+ Emissione
+ Emetti suono fotocamera
+ Componenti Aggiuntivi
+ Creato da
+ Percorso DLL
+ Nome
+ Versione
+ Impostazioni Preferite per l'Emissione File
+ Formato immagine
+ Stampante
+ Opzioni di stampa
+ Impostazioni Qualità
+ Riduci i colori a un massimo di 256
+ Registra scorciatoie di tastiera
+ Mostra torcia elettrica
+ Mostra le notifiche
+ Mostra lente ingrandimento
+ Destinaz. salvataggio
+ Impostazioni
+ Modello usato per generare il nome file in fase di salvataggio delle immagini
+ Lingua dell'interfaccia utente di Greenshot (richiede il riavvio)
+ Formato immagine di default
+ Definisce se le scorciatoie Stamp, Ctrl + Stamp, Alt + Stamp sono riservate per uso globale di Greenshot dall'avvio del programma fino a quando viene chiuso.
+ Destinazione dove le immagini dello schermo vengono salvate per default (lasciare vuoto per salvare sul desktop)
+ Usa il proxy di default del sistema
+ Effetti
+ Millisecondi di attesa prima di catturare
+ Modalità cattura finestra
+ Cattura finestra
+ Clicca tasto destro qui, o premi il tasto Stamp.
+ Una nuova versione di Greenshot è ora disponibile! Vuoi scaricare Greenshot {0}?
+ Attendere prego, finchè la pagina di Internet Explorer viene catturata...
+ Attenzione
+ La registrazione della/e scorciatoie di tastiera "{0}" non è andata a buon fine. Questo problema è causato probabilmente da un altro software{1} che richiede l'uso delle stesse scorciatoie di tastiera. E' possibile però variare le impostazioni delle scorciatoie, oppure disattivare il software.
+
+In alternativa alle scorciatoie di tastiera, tutte le funzioni di Greenshot sono comunque disponibili dal menù visualizzabile con tasto destro del mouse sull'icona G nella barra.
+ Usa colori personalizzati
+ Conserva la trasparenza
+ Automaticamente
+ Usa i colori di default
+ Come visualizzata
+
+ Aggiungi conteggio
+ Aggiungi nuvoletta
+ Ridimensiona
+ Impostazioni ridimensionamento
+ Mantieni il rapporto dimensioni
+ Larghezza
+ Altezza
+ Intensità ombra
+ Offset ombra
+ Impostazioni Ombreggiatura
+ Spessore ombra
+
+ Intervallo orizzontale dentellatura
+ Impostazioni Bordi Strappati
+ Dimensione dentellatura
+ Intervallo verticale dentellatura
+ Strappo lato sinistro
+ Strappo lato destro
+ Strappo lato in alto
+ Strappo lato in basso
+ Genera ombra
+
+
diff --git a/src/Greenshot/Languages/language-ja-JP.xml b/Greenshot/Languages/language-ja-JP.xml
similarity index 92%
rename from src/Greenshot/Languages/language-ja-JP.xml
rename to Greenshot/Languages/language-ja-JP.xml
index 36f5231f2..bacd10fda 100644
--- a/src/Greenshot/Languages/language-ja-JP.xml
+++ b/Greenshot/Languages/language-ja-JP.xml
@@ -1,11 +1,11 @@
-
+
バグ等の報告先 :
Greenshot がお気に召したなら、是非支援をお願いします :
Greenshot は GitHub によって運営されています :
上山根 祐輔氏の Fugue Icons を使用しています (Creative Commons Attribution 3.0 license) :
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot には一切の保障がありません。GNU General Public License に定められた条件下で再配布をおこなうことができます。:
Greenshot について
Greenshot - the revolutionary screenshot utility
@@ -16,7 +16,7 @@ Greenshot には一切の保障がありません。GNU General Public License
次の URL にアクセスし、そこでバグ レポートを作成して、テキスト エリアの内容を説明として貼り付けてください。
どのような状況で発生したのか、またバグを修正するのに役立つと思われる情報を、できる限りつけ加えてください。
-すでに同じようなバグが報告されているかどうか、確認した上で報告してくださると、我々はさらに助かります(検索機能を使用すれば簡単におこなえます)。 ありがとうございました :)
+すでに同じようなバグが報告されているかどうか、確認した上で報告してくださると、我々はさらに助かります(検索機能を使用すれば簡単におこなえます)。 ありがとうございました :)
エラー
キャンセル
クリップボードへの書き込み中に予期しないエラーが発生しました。
@@ -90,10 +90,8 @@ Greenshot には一切の保障がありません。GNU General Public License
画像をクリップボードにコピー
パスをクリップボードにコピー
コピー
- カウンターを挿入する (I)
+ カウンターを挿入する
切り抜き (C)
- 切り抜き
- 自動切り抜き
選択ツール (ESC)
切り取り
削除
@@ -143,7 +141,7 @@ Greenshot には一切の保障がありません。GNU General Public License
印刷
やり直し{0}
サイズをリセット
- リサイズ (Z)
+ リサイズ
縦横比を維持する
高さ
パーセント
@@ -158,20 +156,19 @@ Greenshot には一切の保障がありません。GNU General Public License
すべて選択
'{0}' に印刷ジョブを送りました。
シャドウ
- 吹き出しを挿入する (S)
+ 吹き出しを挿入する
画像をクリップボードに送りました。
線の太さ
Greenshot イメージ エディター
破れたエッジ
- すべて破る
- 下端を破る
+ 下側のエッジを破る
水平方向のギザギザの範囲
- 左端を破る
- 右端を破る
+ 左側のエッジを破る
+ 右側のエッジを破る
破れたようなエッジの設定
影をつける
ギザギザの大きさ
- 上端を破る
+ 上側のエッジを破る
垂直方向のギザギザの範囲
元に戻す{0}
一階層手前へ
@@ -186,7 +183,6 @@ Greenshot には一切の保障がありません。GNU General Public License
ファイル "{0}" が開けません。
リンク '{0}' が開けません。
スクリーンショットを保存できません。適切な場所を指定し直してください。
- 生成されたファイル名またはディレクトリ名が無効です。ファイル名のパターンを修正してから、もう一度やり直してください。
高度な設定
256色以下の画像の場合は8ビットの画像を生成する
安定版以外のアップデートを確認する
@@ -198,12 +194,14 @@ Greenshot には一切の保障がありません。GNU General Public License
リモートデスクトップの使用に最適化
可能であればエディターを再び使用する
エディターを閉じる際に保存ダイアログを表示しない
- コンテキストメニューにウィンドウのサムネイルを表示する (Vista, 7, 8 ,10対象)
+ コンテキストメニューにウィンドウのサムネイルを表示する (Vista, 7, 8 対象)
出力先: {0}
{0}への出力中にエラーが発生しました:
Greenshot - ヘルプ
ホットキー
JPEG 画像の品質を指定してください。
+ デフォルトの JPEG 品質設定として保存して、以降は確認しない
+ Greenshot - JPEG 品質の設定
OK
印刷の実行中にエラーが発生しました。
ページの中央に配置
@@ -221,7 +219,8 @@ Greenshot には一切の保障がありません。GNU General Public License
Greenshot - 印刷オプション
デフォルトの品質で保存し、以降は確認しない
Greenshot - 保存する画像の品質
- ディレクトリに保存 (デフォルトの保存先を使用)
+ ディレクトリに保存 (デフォルトの保存先を使用)
+ JPEG 画像の保存時は、つねに JPEG 品質の設定ダイアログを表示する
画像を印刷する際に毎回「印刷オプション」ダイアログを表示する
画像を保存する際に毎回「保存する画像の品質」ダイアログを表示する
アプリケーションの設定
@@ -236,19 +235,19 @@ Greenshot には一切の保障がありません。GNU General Public License
クリップボードにコピー
イメージ エディターで開く
Eメール
- 保存 (下欄の設定を使用)
- 名前を付けて保存 (ダイアログを表示)
+ 保存 (下欄の設定を使用)
+ 名前を付けて保存 (ダイアログを表示)
撮影後の操作を毎回選択する
プリンターに送る
エディター
ファイル名パターン
一般
- アイコンサイズ
Internet Explorerのキャプチャー
JPEG の品質
+ JPEG の設定
表示言語
ファイルの名称に次のパターンを用いると、自動的に置き換えられます。
-
+
${YYYY} 年, 4 桁表示
${MM} 月, 2 桁表示
${DD} 日, 2 桁表示
@@ -288,13 +287,13 @@ ${hostname} PC の名称
保存場所
設定
スクリーンショット保存時に使用するファイル名のパターン
- Greenshot のユーザー インターフェースに使用する言語 (変更後は Greenshot の再起動が必要です)
+ Greenshot のユーザー インターフェースに使用する言語 (変更後は Greenshot の再起動が必要です)
デフォルトで使用する画像フォーマット
Greenshot の起動時から終了までは、Prnt, Ctrl + Print, Alt + Prnt の各キーはグローバルなショートカットとして確保、使用されます。
- スクリーンショットのデフォルト保存先 (空欄はユーザーのデスクトップ フォルダ)
+ スクリーンショットのデフォルト保存先 (空欄はユーザーのデスクトップ フォルダ)
デフォルトのシステムプロクシーを利用する
エフェクト
- ミリ秒 (キャプチャー時の遅延時間)
+ ミリ秒 (キャプチャー時の遅延時間)
ウィンドウキャプチャーモード
ウィンドウキャプチャー
拡大鏡を表示する
diff --git a/src/Greenshot/Languages/language-kab-DZ.xml b/Greenshot/Languages/language-kab-DZ.xml
similarity index 98%
rename from src/Greenshot/Languages/language-kab-DZ.xml
rename to Greenshot/Languages/language-kab-DZ.xml
index 8a690952c..b57a01695 100644
--- a/src/Greenshot/Languages/language-kab-DZ.xml
+++ b/Greenshot/Languages/language-kab-DZ.xml
@@ -5,7 +5,7 @@
Ma tḥemled Greenshot, Mudd-aɣ-d afus :
Greenshot yezdeɣ di sourceforge.net di
Tignitin i d-yekkan seg uqettun n tignitin Fugue n Kamiyamane Yuusuke (Creative Commons Attribution 3.0 license)
- Copyright © 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright © 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
Greenshot yettunefk-d S WAR ṬMANA. d aseɣẓan ilelli i tzemreḍ ad tezuzreḍ s kra n tewtilin.
Talqayt ɣef GNU General Public License :
Ɣef Greenshot
@@ -93,8 +93,6 @@ Rnu ɣur-s, nḥemmel aṭas ma yella tesneqdeḍ aneqqis igebren ugur-agi. (Tze
Nɣel
Rnu Amesmiḍan
Seggem (C)
- Seggem
- Aseggem awurman
Afecku n ufran (ESC)
Gzem
Kkes
@@ -144,7 +142,7 @@ Rnu ɣur-s, nḥemmel aṭas ma yella tesneqdeḍ aneqqis igebren ugur-agi. (Tze
Siggez
Err-d {0}
Wennez teɣzi
- Snifel tahri/teɣzi (Z)
+ Snifel tahri/teɣzi
Eǧǧ afmiḍi Teɣ / Teh
Awrir
Afmiḍi
diff --git a/src/Greenshot/Languages/language-ko-KR.xml b/Greenshot/Languages/language-ko-KR.xml
similarity index 97%
rename from src/Greenshot/Languages/language-ko-KR.xml
rename to Greenshot/Languages/language-ko-KR.xml
index 144188ad8..50930abb9 100644
--- a/src/Greenshot/Languages/language-ko-KR.xml
+++ b/Greenshot/Languages/language-ko-KR.xml
@@ -5,7 +5,7 @@
Greenshot이 좋다면 아래 URL로 방문하셔서 지원할 수 있습니다.
Greenshot은 GitHub 관리하에 아래 링크에서 호스팅되고 있습니다
아이콘은 Yusuke Kamiyamane's Fugue icon set으로부터 제공받은 것입니다. (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom
Greenshot comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
Details about the GNU General Public License:
Greenshot 프로그램 소개...
@@ -92,8 +92,6 @@ Also, we would highly appreciate if you checked whether a tracker item already e
경로를 클립보드로 복사
복사
잘라내기 (C)
- 잘라내기
- 자동 잘라내기
선택도구 (ESC)
잘라내기
삭제
@@ -289,7 +287,7 @@ ${hostname} PC명
음영 오프셋
음영 설정
음영 두께
-
+
수평 범위
경계 자르기 설정
자르기 크기
@@ -300,16 +298,16 @@ ${hostname} PC명
상단
하단
음영 넣기
-
+
카운터 더하기 (I)
설명선 더하기(S)
-
- 크기조정 (Z)
+
+ 크기조정
크기조정 설정
종횡비 유지
너비
높이
아이콘 크기
-
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/language-lt-LT.xml b/Greenshot/Languages/language-lt-LT.xml
similarity index 97%
rename from src/Greenshot/Languages/language-lt-LT.xml
rename to Greenshot/Languages/language-lt-LT.xml
index 9b1089811..6cbe0628d 100644
--- a/src/Greenshot/Languages/language-lt-LT.xml
+++ b/Greenshot/Languages/language-lt-LT.xml
@@ -5,7 +5,7 @@
Jei jums patiko Greenshot, galite mus paremti:
Greenshot talpinamas GitHub
IIkonų rinkinys Fugue, аutorius Yusuke Kamiyamane, licencija Creative Commons Attribution 3.0
- Visos teisės saugomos (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Visos teisės saugomos (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
Greenshot pateikiama BE JOKIŲ GARANTIJŲ. Greenshot — laisvai platinama PĮ su GPL licencija ir jūs galite laisvai ją platinti, laikydamasi licencinės sutarties:
Apie Greenshot
Greenshot — revoliucinis įrankis ekrano nuotraukoms daryti
@@ -61,7 +61,6 @@ Dėkojame už pagalbą :)
Kopijuoti pilną failo vardą
Коpijuoti
Iškirpti (C)
- Iškirpti
Objektų pasirinkimas (ESC)
Apkirpti
Naikinti
diff --git a/src/Greenshot/Languages/language-lv-LV.xml b/Greenshot/Languages/language-lv-LV.xml
similarity index 98%
rename from src/Greenshot/Languages/language-lv-LV.xml
rename to Greenshot/Languages/language-lv-LV.xml
index dea057944..bcf3eb9e0 100644
--- a/src/Greenshot/Languages/language-lv-LV.xml
+++ b/Greenshot/Languages/language-lv-LV.xml
@@ -6,7 +6,7 @@
Ja Tev patīk „Greenshot”, Tu vari mūs atbalstīt:
„Greenshot” atrodams GitHub adresē
Ikonas veidojis Yusuke Kamiyamane's Fugue (Radošās kopienas Atsaucoties 3.0 licence)
- Autortiesības (C): 2007-20120 Thomas Braun, Jens Klingen, Robin Krom
+ Autortiesības (C): 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
Ņemot vērā, ka „Greenshot” tiek licencēta bez maksas, šai programmai NAV NEKĀDU GARANTIJU. Tu vari to izplatīt un lietot ievērojot GNU Vispārīgo Publisko licenci:
Par „Greenshot”
„Greenshot” - mūsdienīga ekrānattēla ieguves programmatūra
@@ -92,8 +92,6 @@ Mēs būtu Tev pateicīgi, ja Tu vispirms pārbaudītu, vai kāds cits jau nav z
Ievietot ceļu starpliktuvē
Kopēt
Apcirst (C)
- Apcirst
- Automātiski apcirst
Atlases rīks (ESC)
Izgriezt
Izdzēst
@@ -302,16 +300,16 @@ Arī bez karstiem taustiņiem visas darbības iespējams veikt izmantojot „Gre
Augšpuse
Apakšpuse
Veidot ēnu
-
+
Pievienot skaitli (I)
Pievienot teksta norādi (S)
- Mainīt izmēru (Z)
+ Mainīt izmēru
Izmēra maiņas iestatījumi
Saglabāt izmēru attiecības
Platums
Augstums
Ikonas izmērs
-
+
diff --git a/src/Greenshot/Languages/language-nl-NL.xml b/Greenshot/Languages/language-nl-NL.xml
similarity index 96%
rename from src/Greenshot/Languages/language-nl-NL.xml
rename to Greenshot/Languages/language-nl-NL.xml
index d640b0a42..77b7e9aab 100644
--- a/src/Greenshot/Languages/language-nl-NL.xml
+++ b/Greenshot/Languages/language-nl-NL.xml
@@ -5,7 +5,7 @@
Als Greenshot u bevalt, wilt u ons wellicht ondersteunen:
Greenshot wordt uitgegeven door sourceforge.net op
Iconen afkomstig van Yusuke Kamiyamane's Fugue (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2017 Thomas Braun, Jens Klingen, Robin Krom
Greenshot komt zonder enige garantie! Dit is gratis software en het staat u vrij het onder bepaalde voorwaarden te verspreiden.
Details over de GNU General Public License:
Over Greenshot
@@ -78,7 +78,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
Geen
Startpunt
Automatisch bijsnijden
- Vulkleur (0-9)
+ Vulkleur
Vervagingsradius
Vet
Rand
@@ -93,8 +93,6 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
Locatie naar klembord kopiëren
Kopiëren
Bijsnijden (C)
- Bijsnijden
- Automatisch bijsnijden
Selectiegereedschap (ESC)
Knippen
Verwijderen
@@ -113,7 +111,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
E-mail
Bestand
Grootte
- Lijnkleur (NumPad0-9, Shift+0-9)
+ Lijnkleur
Grijstinten
Gebied markeren
Grijstinten
@@ -149,7 +147,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
Opslaan als…
Alles selecteren
Afdruktaak verzonden naar '{0}'.
- Schaduw (/)
+ Schaduw
Afbeelding opgeslagen op het klembord.
Lijndikte
Greenshot beeldbewerker
@@ -303,16 +301,16 @@ Alle Greenshot functies werken ook zonder sneltoetsen via het context menu.Bovenkant
Onderkant
Schaduw
-
+
Teller toevoegen (I)
Tekstballon toevoegen (S)
- Grootte (Z)
+ Grootte
Vergrotingsinstellingen
Verhouding behouden
Breedte
Hoogte
Pictogramgrootte
-
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/language-nn-NO.xml b/Greenshot/Languages/language-nn-NO.xml
similarity index 97%
rename from src/Greenshot/Languages/language-nn-NO.xml
rename to Greenshot/Languages/language-nn-NO.xml
index edd8f31e7..b107307b3 100644
--- a/src/Greenshot/Languages/language-nn-NO.xml
+++ b/Greenshot/Languages/language-nn-NO.xml
@@ -5,7 +5,7 @@
Om du likar Greenshot er du velkomen til å støtte oss:
Greenshot held virtuelt hus hjå GitHub:
Ikon frå Yusuke Kamiyamane sit "Fugue" ikonsett (Creative Commons Attribution 3.0-lisens)
- Med kopirett (C) 2007-2021 Thomas Braun, Jens Klingen og Robin Krom. Norsk omsetjing av Ivar Barstad.
+ Med kopirett (C) 2007-2012 Thomas Braun, Jens Klingen og Robin Krom. Norsk omsetjing av Ivar Barstad.
Greenshot har ABSOLUTT INGEN GARANTI. Dette er gratis programvare, og du står fritt til å distribuere det under visse vilkår.
Detaljar om GNU General Public-lisens:
Om Greenshot
@@ -80,8 +80,6 @@ Me sett òg pris på om du ved hjelp av søkefunksjonen på sida kan sjekke om d
Kopier filstigen til utklyppstavla
Kopier
Skjer bildet [C]
- Skjer bildet
- Auto-skjer
Peikarverktøy [Esc]
Klypp ut
Slett
diff --git a/src/Greenshot/Languages/language-pl-PL.xml b/Greenshot/Languages/language-pl-PL.xml
similarity index 97%
rename from src/Greenshot/Languages/language-pl-PL.xml
rename to Greenshot/Languages/language-pl-PL.xml
index 7f908dba8..6b394c750 100644
--- a/src/Greenshot/Languages/language-pl-PL.xml
+++ b/Greenshot/Languages/language-pl-PL.xml
@@ -5,7 +5,7 @@
Jeśli podoba Ci się Greenshot, chętnie przyjmiemy Twoje wsparcie:
Greenshot jest utrzymywany przez GitHub pod adresem:
Ikony z zestawu Fugue od Yusuke Kamiyamane (licencja Creative Commons Attribution 3.0):
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot nie jest objęty JAKĄKOLWIEK GWARANCJĄ. Jako wolne oprogramowanie może być rozpowszechniany na określonych warunkach.
Szczegóły na temat Powszechnej Licencji Publicznej GNU:
O Greenshot
@@ -93,8 +93,6 @@ Będziemy wdzięczni, jeśli najpierw sprawdzisz, czy takie zdarzenie nie zosta
Kopiuj ścieżkę do schowka
Kopiuj
Przytnij (C)
- Przytnij (C)
- Przytnij automatycznie
Narzędzie wyboru (ESC)
Wytnij
Usuń
diff --git a/src/Greenshot/Languages/language-pt-BR.xml b/Greenshot/Languages/language-pt-BR.xml
similarity index 55%
rename from src/Greenshot/Languages/language-pt-BR.xml
rename to Greenshot/Languages/language-pt-BR.xml
index e53603ccc..dea43a9b8 100644
--- a/src/Greenshot/Languages/language-pt-BR.xml
+++ b/Greenshot/Languages/language-pt-BR.xml
@@ -5,33 +5,22 @@
Se você gostou do Greenshot, por favor contribua:
O Greenshot está armazenado no GitHub em
Ícones de Yusuke Kamiyamane (Biblioteca Fugue, licença "Creative Commons Attribution 3.0")
-
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- O Greenshot não tem NENHUMA GARANTIA. Este software gratuito pode ser redistribuído sob algumas condições.
- Detalhes sobre a licença GNU:
-
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+O Greenshot não tem NENHUMA GARANTIA. Este software gratuito pode ser redistribuido sob algumas condições.
+Detalhes sobre a licença GNU:
Sobre o Greenshot
Greenshot - O revolucionário Utilitário de Captura de Tela
Fechar
-
- Desculpe, ocorreu um erro inesperado.
+ Desculpe, ocorreu um erro inesperado.
- A boa notícia é: você pode nos ajudar a corrigir o problema nos enviando uma descrição do erro.
- Por favor visite a URL abaixo, crie um novo reporte de erro e cole o conteúdo da área de texto na descrição do erro.
+A boa notícia é: você pode nos ajudar a corrigir o problema nos enviando uma descrição do erro.
+Por favor visite a URL abaixo, crie um novo reporte de erro e cole o conteúdo da área de texto na descrição do erro.
- Por favor adicione um resumo significativo do erro, além de qualquer informação que considere útil para a reprodução o problema.
- Também apreciaremos muito se você puder verificar se já não existe um reporte de erro para este problema. (Você pode usar a opção de busca para encontrar rapidamente.) Obrigado :)
-
+Por favor adicione um resumo significativo do erro, além de qualquer informação que considere útil para a reprodução o problema.
+Também apreciaremos muito se você puder verificar se já não existe um reporte de erro para este problema. (Você pode usar a opção de busca para encontrar rapidamente.) Obrigado :)
Erro
- Cancelar
Um erro inesperado ocorreu ao tentar escrever na área de transferência.
O Greenshot não conseguiu escrever na área de transferência porque o processo {0} bloqueou o acesso.
- Não foi possível encontrar uma imagem na área de transferência.
- Windows Bitmap
- Device independent Bitmap (DIB)
- HTML
- HTML com imagens inline
- PNG
Alfa
Aplicar
Azul
@@ -41,34 +30,19 @@
Vermelho
Seletor de Cores
Transparência
- O destino {0} rejeitou acesso do Greenshot, provavelmente um diálogo está aberta. Feche o diálogo e tente novamente.
- Acesso ao Greenshot rejeitado
- Não foi possível salvar o arquivo de configuração do Greenshot. Por favor verifique as permissões de acesso a '{0}'.
+ Não foi possível salvar o arquivo de configuração do Greenshot. Por favor verifique as permissões de acceso a '{0}'.
Sobre o Greenshot
Capturar região
- Abrir imagem da área de transferência
+ Abrir imagen da área de transferência
Capturar a tela inteira
- todos
- inferior
- esquerda
- direita
- superior
- Capturar Internet Explorer
- Capturar Internet Explorer da lista
Capturar a última região
Capturar tela
- Capturar janela da lista
Suporte do Greenshot
Sair
Ajuda
Abrir imagem do arquivo
- Abrir último local capturado
Preferências rápidas
Preferências...
- Erro ao exportar para {0}. Por favor, tente novamente.
- Outlook com HTML
- Outlook com texto
- Abrir imagem no editor
Organizar
Ponta das setas
Em ambos
@@ -89,7 +63,6 @@
Copiar o caminho da pasta atual do arquivo para a Área de transferência
Copiar
Cortar (C)
- Cortar
Ferramenta de Seleção (ESC)
Cortar
Apagar
@@ -140,137 +113,82 @@
Trazer para frente
Erro
Uma instância do Greenshot já está sendo executada.
-
- Não foi possível salvar o arquivo em {0}.
- Por favor verifique o caminho selecionado para o armazenamento.
-
- O arquivo "{0}" não pode ser aberto.
+ Não foi possível salvar o arquivo em {0}.
+Por favor verifique o caminho selecionado para o armazenamento.
+ O arquivo "{0}" não põde ser aberto.
O link '{0}' não pode ser aberto.
A tela capturada não pôde ser salva, por favor encontre um local adequado.
- O nome do arquivo ou nome do diretório gerado não é válido. Corrija o padrão de nome de arquivo e tente novamente.
- Especialista
- Criar uma imagem de 8 bits se as cores são menos de 256, tendo um > imagem de 8 bits
- Verificar atualizações instáveis
- Formatos da área de transferência
- O número para ${NUM} no padrão de nome de arquivo
- Eu sei o que estou fazendo!
- Rodapé padrão de impressão
- Minimizar footprint de memória, mas com uma penalidade de desempenho (não recomendado).
- Faça algumas otimizações para usar com computador remoto
- Reutilizar editor se possível
- Suprimir o diálogo salvar ao fechar o editor
- Mostrar miniaturas de janelas no menu de contexto (para Vista e windows 7)
- Exportado to: {0}
- Ocorreu um erro ao exportar para {0}:
Ajuda do Greenshot
- Teclas de atalho
Por favor selecione a qualidade desejada para a imagem JPEG.
Salvar esta qualidade JPEG como padrão e não perguntar novamente
Qualidade Greenshot para JPEG
- Ok
Ocorreu um erro ao se tentar imprimir.
Centralizar a impressão na página
Aumentar o tamanho da impressão para ocupar toda a página
Rotacionar a impressão de acordo com a orientação da página
Diminuir o tamanho da impressão para caber na página
- configurações de cor
Salvar as opções como padrão e não perguntar de novo
- Imprimir com cores invertidas
- Configurações de layout da página
- Impressão colorida
- Forçar impressão em tons de cinza
- Forçar impressão preto / branco
Imprimir data / hora na parte inferior da página
- Opções de impressão do Greenshot
- Salvar com qualidade padrão e não perguntar novamente
- Qualidade do Greenshot
- Salvar diretamente (Usando configuração padrão para arquivos capturados)
+ Opçoes de impressão do Greenshot
+ Salvar diretamente (Usando a configuração padrão para arquivos de captura)
+ Perguntar a qualidade do JPEG toda vez que uma imagem for salva
Mostrar as opções de impressão toda vez que uma imagem for impressa
- Perguntar a qualidade do JPEG toda vez que uma imagem for salva
Configurações da Aplicação
Executar o Greenshot ao iniciar o Windows
Captura
Capturar também o cursor do mouse
Usar modo interativo
- intervalo de verificação de atualização em dias (0=sem verificar)
- Configurar
Copiar o caminho completo do arquivo para a Área de transferência
Destino da tela capturada
Área de transferência
+ Abrir imagem no editor
Enviar por e-mail
Salvar em um arquivo
Salvar como... (mostrar caixa de diálogo)
- Selecione o destino dinamicamente
Enviar para impressora
- Editor
Formato do nome
Geral
- Qualidade JPEG
- Configurações JPEG
+ Qualidade do JPEG
+ Configurações para JPEG
Idioma
-
- Os seguientes marcadores de posição serão substituídos automaticamente pelo formato definido:
- ${YYYY} ano, 4 dígitos
- ${MM} mês, 2 dígitos
- ${DD} dia, 2 dígitos
- ${hh} hora, 2 dígitos
- ${mm} minuto, 2 dígitos
- ${ss} segundo, 2 dígitos
- ${NUM} número incremental, 6 dígitos
- ${title} Título da janela
- ${user} Usuário do Windows
- ${domain} Domínio do Windows
- ${hostname} Nome do Computador
+ Os seguientes marcadores de posição serão substituídos automaticamente pelo formato definido:
+${YYYY} ano, 4 dígitos
+${MM} mês, 2 dígitos
+${DD} dia, 2 dígitos
+${hh} hora, 2 dígitos
+${mm} minuto, 2 dígitos
+${ss} segundo, 2 dígitos
+${NUM} número incremental, 6 dígitos
+${title} Título da janela
+${user} Usuário do Windows
+${domain} Domínio de Windows
+${hostname} Nome do Computador
- Você também pode fazer o Greenshot criar diretórios dinamicamente, simplesmente usando o símbolo de barra invertida (\) para separar diretórios e nome de arquivo.
- Exemplo: o formato ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
- irá gerar um diretório para o dia atual dentro do caminho de armazenamento padrão, exemplo: 2008-06-29, os nomes das telas capturadas serão baseados na
- hora atual, ejemplo: 11_58_32 (mais a extensão definida nas configurações de preferência)
-
- Rede e atualizações
+Você também pode fazer o Greenshot criar diretórios dinamicamente, simplesmente usando o símbolo de barra invertida (\) para separar diretórios e nome de arquivo.
+Exemplo: o formato ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+irá gerar um diretório para o dia atual dentro do caminho de armazenamento padrão, exemplo: 2008-06-29, os nomes das telas capturadas serão baseados na
+hora atual, ejemplo: 11_58_32 (mais a extensão definida nas configurações de preferência)
Captura
Reproduzir o som de uma câmera
- Plugins
- Criado por
- Caminho da DLL
- Nome
- Versões
- Configurações Padrão para os Arquivos Capturados
+ Configurações Padrão para os Arquivos de Captura
Formato da imagem
Impressora
Opções de Impressão
- Configurações de qualidade
- Reduzir a quantidade de cores para um máximo de 256
Configurar teclas de atalho
Simular o flash de uma câmera
- Mostrar notificações
- Mostrar lupa
Caminho
Preferências
Formato usado para gerar o nome dos arquivos quando se salvam as telas capturadas
Idioma da interface de usuário do Greenshot (necessita reiniciar)
- Formato da imagem usado por padrão
+ Formato da imagen usado por padrão
Configurar os atalhos Print, Ctrl + Print, Alt + Print para uso pelo Greenshot quando este iniciar, e até que ele seja finalizado.
- Local onde as telas capturadas serão salvas por padrão (deixar em branco para salvar na Área de Trabalho)
- Usar proxy padrão do sistema
+ Lugar onde as telas capturadas serão salvas por padrão (deixar em branco para salvar na Área de Trabalho)
Efeitos
Milisegundos à esperar antes de iniciar a captura
- Modo de captura de janela
- Captura de janela
Botão direito aqui ou pressionar a tecla Print.
- A versão mais recente do Greenshot está disponível! Você quer baixar o Greenshot {0}?
- Por favor aguarde enquanto a página no Internet Explorer é capturado ...
Atenção
-
- Uma ou mais teclas de atalho não puderam ser configuradas. Por isso pode não ser possível usar as teclas de atalho do Greenshot.
- Este problema é geralmente causado por outro aplicativo solicitando acesso a estas teclas de atalho.
- Por favor desative o outro programa que está usando a tecla Print ou use as funções do Greenshot via menu de contexto no ícone da bandeja do sistema.
-
- Usar cor personalizada
- Preservar a transparência
- Automaticamente
- Usar cores padrão
- Como exibido
- Tamanho do ícone
+ Uma ou mais teclas de atalho não puderam ser configuradas. Por isso pode não ser possível utilizar as teclas de atalho do Greenshot.
+Este problema é geralmente causado por outro aplicativo solicitando acesso a estas teclas de atalho.
+Por favor desative o outro programa que está utilizando a tecla Print ou utilize as funções do Greenshot via o menu de contexto do ícone no System Tray.
-
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/language-pt-PT.xml b/Greenshot/Languages/language-pt-PT.xml
similarity index 97%
rename from src/Greenshot/Languages/language-pt-PT.xml
rename to Greenshot/Languages/language-pt-PT.xml
index 4da21743d..8792f399f 100644
--- a/src/Greenshot/Languages/language-pt-PT.xml
+++ b/Greenshot/Languages/language-pt-PT.xml
@@ -5,7 +5,7 @@
Se gostou do Greenshot, por favor contribua:
O Greenshot está armazenado no GitHub em
Ícones da colecção Fugue de Yusuke Kamiyamane (Licença "Creative Commons Attribution 3.0")
- Direitos de Autor (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Direitos de Autor (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
O Greenshot não tem NENHUMA GARANTIA. Este software gratuito pode ser redistribuído sob algumas condições.
Detalhes sobre a licença GNU:
Acerca do Greenshot
@@ -92,8 +92,6 @@ Também apreciaremos muito se puder verificar se não existe já um relatório d
Copiar atalho para a Área de transferência
Copiar
Recortar (C)
- Recortar
- Recortar auto
Ferramenta de Selecção (ESC)
Cortar
Eliminar
@@ -305,7 +303,7 @@ Todas as funcionalidades do Greenshot funcionam directamente através do menu de
Adicionar contador (I)
Adicionar balão de texto (S)
- Redimensionar (Z)
+ Redimensionar
Definições de Redimensionamento
Manter proporções
Largura
diff --git a/src/Greenshot/Languages/language-ro-RO.xml b/Greenshot/Languages/language-ro-RO.xml
similarity index 95%
rename from src/Greenshot/Languages/language-ro-RO.xml
rename to Greenshot/Languages/language-ro-RO.xml
index 02fe86c3f..11f17a736 100644
--- a/src/Greenshot/Languages/language-ro-RO.xml
+++ b/Greenshot/Languages/language-ro-RO.xml
@@ -4,7 +4,6 @@
Traducere în limba română - Radu Mogoș
@@ -471,9 +470,6 @@ timpul curent, ex. 11_58_32 (plus extensia fișierului definită în setări)
Taie (C)
-
- Taie
-
Deschide imaginea din clipboard
diff --git a/src/Greenshot/Languages/language-ru-RU.xml b/Greenshot/Languages/language-ru-RU.xml
similarity index 96%
rename from src/Greenshot/Languages/language-ru-RU.xml
rename to Greenshot/Languages/language-ru-RU.xml
index f9973f349..b7df2b940 100644
--- a/src/Greenshot/Languages/language-ru-RU.xml
+++ b/Greenshot/Languages/language-ru-RU.xml
@@ -5,7 +5,7 @@
Если вам нравится Greenshot, вы можете поддержать нас:
Greenshot размещается на GitHub
Набор иконок Yusuke Kamiyamane's Fugue (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.Это бесплатная программа и вы можете распространять её на определённых условиях.
Подробно о GNU General Public License:
О программе Greenshot
@@ -25,7 +25,7 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Greenshot не смог записать в буфер обмена, доступ заблокирован процессом {0}.
Изображение в буфере обмена не найдено.
Windows Bitmap
- Устройство independent Bitmap (DIB)
+ Устройство Independend Bitmap (DIB)
HTML
HTML со встроенными изображениями
PNG
@@ -38,7 +38,7 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Красный
Палитра цветов
Прозрачный
- Назначение {0} отклонил доступ к Greenshot, вероятно, открыто окно. Закройте диалоговое окно и попробуйте ещё раз.
+ Назначение {0} отклонил доступ к Greenshot, вероятно, отрыто окно. Закройте диалоговое окно и попробуйте ещё раз.
Доступ к Greenshot отклонён
Не удалось сохранить файл конфигурации Greenshot's. Пожалуйста, проверьте права доступа для '{0}'.
О программе Greenshot
@@ -61,7 +61,7 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Открыть изображение из файла
Открыть последнее место захвата
Быстрые настройки
- Настройки...
+ Предпочтения...
Ошибка при экспорте {0}. Пожалуйста, попробуйте ещё раз.
Внизу
По центру
@@ -93,8 +93,6 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Копировать путь в буфер обмена
Копировать
Обрезка (C)
- Обрезка
- Автообрезка
Инструмент «Выделение» (ESC)
Вырезать
Удалить
@@ -231,7 +229,6 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Редактор
Шаблон имени файла
Общие
- Размер иконки
Захват Internet Explorer
Качество JPEG
Язык
@@ -249,7 +246,7 @@ ${domain} Домен Windows
${hostname} Имя ПК
Вы также можете создавать динамичные каталоги Greenshot, используя символ обратную косую черту (\) для отдельных папок и названий файлов.
-Пример шаблона: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
+Пример шаблона: ${YYYY}-${MM}-${DD}\${hh}-${mm}-${ss}
Будет создана папка на текущий день, в вашем хранилище по умолчанию, например 2008-06-29.Содержащее имя файла скриншота будет основываться на текущем
времени, например 11_58_32 (плюс расширения, определённые в настройках)
Сеть и обновления
diff --git a/src/Greenshot/Languages/language-sk-SK.xml b/Greenshot/Languages/language-sk-SK.xml
similarity index 97%
rename from src/Greenshot/Languages/language-sk-SK.xml
rename to Greenshot/Languages/language-sk-SK.xml
index 01c68e9ed..53e0e8a9f 100644
--- a/src/Greenshot/Languages/language-sk-SK.xml
+++ b/Greenshot/Languages/language-sk-SK.xml
@@ -5,7 +5,7 @@
Ak se vám Greenshot páči, uvítame vašu podporu:
Greenshot je na GitHub
Ikony z Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot je ÚPLNE BEZ ZÁRUKY. Toto je FREE software, a môžete ho distribuovať za určitých podmienok.
Podrobnosti o GNU General Public License:
O Greenshote
@@ -80,8 +80,6 @@ Tiež by sme velmi ocenili, keby ste najskôr skontrolovali, či už neexistuje
Kopírovať cestu do schránky
Kopírovať
Orezať (C)
- Orezať
- Automatické orezanie
Nástroj pre výber (ESC)
Vystrihnúť
Zmazať
diff --git a/src/Greenshot/Languages/language-sl-SI.xml b/Greenshot/Languages/language-sl-SI.xml
similarity index 97%
rename from src/Greenshot/Languages/language-sl-SI.xml
rename to Greenshot/Languages/language-sl-SI.xml
index ac102397a..3ea4f2025 100644
--- a/src/Greenshot/Languages/language-sl-SI.xml
+++ b/Greenshot/Languages/language-sl-SI.xml
@@ -5,18 +5,18 @@
Če vam je Greenshot všeč nas prosim podprite:
Greenshot gostuje pri GitHub
Ikone: Yusuke Kamiyamane's Fugue icon set (Creative Commons Attribution 3.0 license)
- Avtorske pravice (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
-Greenshot absolutno ne ponuja NOBENE GARANCIJE. Program je brezplačen in ga lahko distribuirate pod določenimi pogoji.
+ Avtorske pravice (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
+Greenshot absolutno ne ponuja NOBENE GARANCIJE. Program je brezplačen in ga lahko distribuirate pod določenimi pogoji.
Licenčne podrobnosti GNU General Public License:
O Greenshot-u
Greenshot - revolucija zajema zaslonskih slik
Zapri
- Oprostite, program je izvedel nepričakovano napako.
-
-Dobra novica je, da nam lahko pomagate pri odpravi te napake.
-Prosimo obiščite spodnji URL, prijavite napako (create bug) in prilepite vsebino opisa napake.
-
-Prosimo dopišite še razumljiv opis kako ste prišli do težave, da jo bomo lahko ponovili.
+ Oprostite, program je izvedel nepričakovano napako.
+
+Dobra novica je, da nam lahko pomagate pri odpravi te napake.
+Prosimo obiščite spodnji URL, prijavite napako (create bug) in prilepite vsebino opisa napake.
+
+Prosimo dopišite še razumljiv opis kako ste prišli do težave, da jo bomo lahko ponovili.
Pred objavo preverite tudi ali je napaka že prijavlja s strani kakšnega drugega uporabnika. Hvala :)
Napaka
Prekliči
@@ -78,8 +78,6 @@ Pred objavo preverite tudi ali je napaka že prijavlja s strani kakšnega drugeg
Kopiraj pot na odložišče
Kopiraj
Obreži (C)
- Obreži
- Samodejno obreži
Orodje za izbor (ESC)
Kopiraj
Briši
@@ -145,7 +143,7 @@ Pred objavo preverite tudi ali je napaka že prijavlja s strani kakšnega drugeg
Outlook kot text
Napaka
Greenshot že teče!
- Ne morem shraniti v {0}.
+ Ne morem shraniti v {0}.
Prosim preverite pravice pisanja v ta direktorij.
Datoteka "{0}" ne more biti odprta.
Ne morem odpreti povezave '{0}'.
@@ -237,8 +235,8 @@ Prosim preverite pravice pisanja v ta direktorij.
Na voljo je nova verzija Greenshot-a! Ali želite prenesti Greenshot {0}?
Prosimo počakajte - zajema se Internet Explorer...
Opozorilo
- Bližnjica "{0}" ne more biti registrirana. Težava je verjetno v tem, da nek drug program uporablja isto bližnjico ! Nastavite si drugo bližnjično tipko ali deaktivirajte bližnjice za ta program.
-
+ Bližnjica "{0}" ne more biti registrirana. Težava je verjetno v tem, da nek drug program uporablja isto bližnjico ! Nastavite si drugo bližnjično tipko ali deaktivirajte bližnjice za ta program.
+
Vse funkcije Greenshota še vedno delujejo preko ikone za hitri zagon.
Uporabi lastne barve
Ohrani prosojnost
diff --git a/src/Greenshot/Languages/language-sr-RS.xml b/Greenshot/Languages/language-sr-RS.xml
similarity index 97%
rename from src/Greenshot/Languages/language-sr-RS.xml
rename to Greenshot/Languages/language-sr-RS.xml
index 9c669dba8..24e1af87e 100644
--- a/src/Greenshot/Languages/language-sr-RS.xml
+++ b/Greenshot/Languages/language-sr-RS.xml
@@ -5,7 +5,7 @@
Ако вам се свиђа Гриншот, помозите нам:
Гриншот покреће Сорсфорџ (GitHub):
Иконе су преузете из пакета „Fugue“ Јусуке Камијамане (лиценца Кријејтив комонс Ауторство 3.0)
- Ауторска права © 2007–2021 Томас Браун, Џенс Клинџен, Робин Кром
+ Ауторска права © 2007–2012 Томас Браун, Џенс Клинџен, Робин Кром
Гриншот се издаје БЕЗ ИКАКВЕ ГАРАНЦИЈЕ. Он је бесплатан програм, који можете да делите под одређеним условима.
Више информација о ГНУ-овој општој јавној лиценци:
О програму
@@ -78,8 +78,6 @@
Умножи путању
Умножи
Опсеци (C)
- Опсеци
- Аутоматско опсецање
Алатка за одабир (ESC)
Исеци
Обриши
@@ -218,9 +216,9 @@ ${user} Виндоусов корисник
${domain} Виндоусов домен
${hostname} назив рачунара
-Гриншот може и да аутоматски прави фасцикле.
+Гриншот може и да аутоматски прави фасцикле.
Користите обрнуту косу црту (\) да раздвојите фасцикле и називе датотека.
-Примерице, образац ${DD}. ${MM}. ${YYYY}\${hh}.${mm}.${ss}
+Примерице, образац ${DD}. ${MM}. ${YYYY}\${hh}.${mm}.${ss}
створиће фасциклу за текући дан у подразумеваном складишту, нпр. 29. 6. 2008., а садржани назив слике биће 11_58_32 (уз екстензију коју сте наместили у подешавањима).
Мрежа и доградње
Излаз
diff --git a/src/Greenshot/Languages/language-sv-SE.xml b/Greenshot/Languages/language-sv-SE.xml
similarity index 97%
rename from src/Greenshot/Languages/language-sv-SE.xml
rename to Greenshot/Languages/language-sv-SE.xml
index c5b1517e2..f0ae0679c 100644
--- a/src/Greenshot/Languages/language-sv-SE.xml
+++ b/Greenshot/Languages/language-sv-SE.xml
@@ -5,7 +5,7 @@
Om du gillar Greenshot, så är du välkommen att stödja oss:
Greenshots hemsida tillhandahålls av GitHub på
Ikoner från "Yusuke Kamiyamane's Fugue icon set" (Creative Commons Attribution 3.0 license)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot lämnar ABSOLUT INGA GARANTIER. Detta är ett gratisprogram, och du får vidaredistribuera programmet under vissa villkor.
Detaljer om "GNU General Public License":
Om Greenshot
@@ -93,8 +93,6 @@ Innan du skickar uppskattar vi verkligen om du kontrollerar om felet redan blivi
Kopiera sökväg till urklipp
Kopiera
Beskär (C)
- Beskär
- Autobeskärning
Markeringsverktyg (ESC)
Klipp ut
Radera
@@ -305,7 +303,7 @@ Alla Greenshots funktioner fungerar fortfarande från snabbmenyn i aktivitetsfä
Lägg till räknare
Lägg till pratbubbla
- Anpassa storlek (Z)
+ Anpassa storlek
Storleksinställningar
Behåll bildförhållande
Bredd
diff --git a/src/Greenshot/Languages/language-tr-TR.xml b/Greenshot/Languages/language-tr-TR.xml
similarity index 97%
rename from src/Greenshot/Languages/language-tr-TR.xml
rename to Greenshot/Languages/language-tr-TR.xml
index 56011063c..6cbee3f0c 100644
--- a/src/Greenshot/Languages/language-tr-TR.xml
+++ b/Greenshot/Languages/language-tr-TR.xml
@@ -5,7 +5,7 @@
Greenshot'ı sevdiyseniz, bizi destekleyin:
Greenshot GitHub üzerinde şu adreste barındırılmaktadır:
Simgeler Yusuke Kamiyamane'nin Fugue simge setidir (Creative Commons Attribution 3.0 lisansı)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot HİÇ BİR GARANTİ vermez. Serbest bir yazılımdır ve belirli koşullar altında dağıtmakta serbestsiniz. GNU
Genel Kamu Lisanslı hakkında daha fazla bilgi için:
Greenshot Hakkında
@@ -78,8 +78,6 @@ Ayrıca bu hata için bir izleyici kaydının açılmış olup olmadığını da
Yolu panoya kopyala
Kopyala
Kırp (C)
- Kırp
- Otomatik kırpma
Seçim Aracı (ESC)
Kes
Sil
diff --git a/src/Greenshot/Languages/language-uk-UA.xml b/Greenshot/Languages/language-uk-UA.xml
similarity index 97%
rename from src/Greenshot/Languages/language-uk-UA.xml
rename to Greenshot/Languages/language-uk-UA.xml
index 057927676..f05ffd078 100644
--- a/src/Greenshot/Languages/language-uk-UA.xml
+++ b/Greenshot/Languages/language-uk-UA.xml
@@ -5,7 +5,7 @@
Якщо Вам подобається Greenshot, можете підтримати нас:
Greenshot розташовується на GitHub
Набір піктограм Fugue від Yusuke Kamiyamane (ліцензія Creative Commons Attribution 3.0)
- Авторство © 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Авторство © 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
Greenshot постачається АБСОЛЮТНО БЕЗ ГАРАНТІЇ. Це вільне програмне забезпечення, Ви можете розповсюджувати його за певних умов.
Подробиці Загальної Публічної Ліцензії GNU:
Про Greenshot
@@ -92,8 +92,6 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ГАРАНТІЇ.
Копіювати шлях у буфер обміну
Копіювати
Обрізати (С)
- Обрізати
- Автоматичне обрізання
Інструмент вибору (Esc)
Вирізати
Видалити
@@ -306,7 +304,7 @@ ${hostname} назва комп’ютера
Додати лічильник (Ш)
Додати словесну бульбашку (І)
- Змінити розмір (Z)
+ Змінити розмір
Параметри зміни розміру
Зберігати пропорції
Ширина
diff --git a/src/Greenshot/Languages/language-vi-VN.xml b/Greenshot/Languages/language-vi-VN.xml
similarity index 97%
rename from src/Greenshot/Languages/language-vi-VN.xml
rename to Greenshot/Languages/language-vi-VN.xml
index 6ddfc7f9d..f31104799 100644
--- a/src/Greenshot/Languages/language-vi-VN.xml
+++ b/Greenshot/Languages/language-vi-VN.xml
@@ -5,7 +5,7 @@
Hãy ủng hộ nếu bạn thấy Greenshot hữu dụng:
Greenshot được tài trợ bởi GitHub
Dùng biểu tượng Fugue (Giấy phép Commons Attribution 3.0 license) :
- Bản quyền (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ Bản quyền (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
Greenshot không đi kèm theo đảm bảo nào và được phân phối dưới giấy phép GNU General Public License.
Giới thiệu Greenshot
Greenshot - Công cụ chụp màn hình
@@ -58,7 +58,6 @@
Chép đuờng dẫn tới clipboard.
Chép
Cắt (C)
- Cắt
Công cụ chọn (ESC)
Cắt
Xóa
@@ -148,7 +147,7 @@
Thiết lập JPEG
Ngôn ngữ hiển thị
Định dạng tên tệp như sau名称のパターンには以下のプレースホルダーが使用できます。
-
+
%YYYY% năm, hai chữ số
%MM% tháng, hai chữ số
%DD% ngày, hai chữ số
@@ -157,14 +156,14 @@
%ss% giây, hai chữ số
%NUM% đánh số, 6 chữ số
%title% Tên cửa sổ
- %user% Tên người dùng
+ %user% Tên người dùng
%domain% Tên miền Windows
%hostname% Tên PC
Có thể chỉ định tên thư mục trong mẫu tên tệp.
Hãy dùng ký tự (\) để ngăn cách.
- Ví dụ: %YYYY%-%MM%-%DD%\%hh%-%mm%-%ss%
+ Ví dụ: %YYYY%-%MM%-%DD%\%hh%-%mm%-%ss%
Sẽ tạo thư mục 2011-06-14 và lưu ảnh với tên là thời gian dạng 23-59-59,
tiếp đó là đuôi tệp.
Xuất
diff --git a/src/Greenshot/Languages/website/language-website-de-DE.xml b/Greenshot/Languages/language-website-de-DE.xml
similarity index 99%
rename from src/Greenshot/Languages/website/language-website-de-DE.xml
rename to Greenshot/Languages/language-website-de-DE.xml
index 07a7406cc..301f1f5c5 100644
--- a/src/Greenshot/Languages/website/language-website-de-DE.xml
+++ b/Greenshot/Languages/language-website-de-DE.xml
@@ -1,20 +1,20 @@
-
-
-
- Downloads
- Greenshot - ein kostenloses Screenshot-Programm für maximale Produktivität
- Greenshot ist kostenlos und open-source
- Falls Sie merken, dass Greenshot Ihnen viel Zeit und/oder Geld spart, würde sich das Entwickler-Team über Ihre <a href="/support/">Unterstützung für die Weiterentwicklung</a> dieser Screenshot-Software freuen.
- Greenshot wurde unter der <a href="http://de.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a> veröffentlicht und kann kostenlos heruntergeladen und verwendet werden, auch zur kommerziellen Nutzung.
- Und weiter?
- Natürlich kann Greenshot noch einiges mehr. Werfen Sie einen Blick auf einige <a title="Screenshots von Greenshot in Aktion" href="/screenshots/">Screenshots</a> von Greenshot in Aktion oder probieren Sie die <a title="Download der aktuellen Version von Greenshot" href="/downloads/">aktuelle Version</a> einfach aus.
- Was ist Greenshot?
- Schnelle Erstellung von kompletten oder teilweisen Screenshots.
- Einfaches Hinzufügen von Kommentaren, Hervorhebungen oder Unkenntlichmachungen.
- Greenshot ist ein kompaktes Screenshot-Programm für Windows mit den folgenden Hauptfunktionen:
- ... und viele weitere Möglichkeiten, die die Erstellung von und die Arbeit mit Screenshots vereinfachen - Tag für Tag.
+
+
+
+ Downloads
+ Greenshot - ein kostenloses Screenshot-Programm für maximale Produktivität
+ Greenshot ist kostenlos und open-source
+ Falls Sie merken, dass Greenshot Ihnen viel Zeit und/oder Geld spart, würde sich das Entwickler-Team über Ihre <a href="/support/">Unterstützung für die Weiterentwicklung</a> dieser Screenshot-Software freuen.
+ Greenshot wurde unter der <a href="http://de.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a> veröffentlicht und kann kostenlos heruntergeladen und verwendet werden, auch zur kommerziellen Nutzung.
+ Und weiter?
+ Natürlich kann Greenshot noch einiges mehr. Werfen Sie einen Blick auf einige <a title="Screenshots von Greenshot in Aktion" href="/screenshots/">Screenshots</a> von Greenshot in Aktion oder probieren Sie die <a title="Download der aktuellen Version von Greenshot" href="/downloads/">aktuelle Version</a> einfach aus.
+ Was ist Greenshot?
+ Schnelle Erstellung von kompletten oder teilweisen Screenshots.
+ Einfaches Hinzufügen von Kommentaren, Hervorhebungen oder Unkenntlichmachungen.
+ Greenshot ist ein kompaktes Screenshot-Programm für Windows mit den folgenden Hauptfunktionen:
+ ... und viele weitere Möglichkeiten, die die Erstellung von und die Arbeit mit Screenshots vereinfachen - Tag für Tag.
Direkter Export des Screenshots in eine Datei, die Zwischenablage,
-an einen Drucker, ein MS Office-Dokument oder als E-Mail-Anhang; Sie können es auch zu verschiedene Bild-Hosting-Services hochladen.
- Da Greenshot leicht verständlich und konfigurierbar ist, ist es ein effizientes Programm für Projektmanager, Software-Entwickler, technische Redakteure, Dokumentations-Entwickler, Tester und andere Personen, die oft mit Screenshots arbeiten.
-
+an einen Drucker, ein MS Office-Dokument oder als E-Mail-Anhang; Sie können es auch zu verschiedene Bild-Hosting-Services hochladen.
+ Da Greenshot leicht verständlich und konfigurierbar ist, ist es ein effizientes Programm für Projektmanager, Software-Entwickler, technische Redakteure, Dokumentations-Entwickler, Tester und andere Personen, die oft mit Screenshots arbeiten.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/website/language-website-en-US.xml b/Greenshot/Languages/language-website-en-US.xml
similarity index 87%
rename from src/Greenshot/Languages/website/language-website-en-US.xml
rename to Greenshot/Languages/language-website-en-US.xml
index 3920492ef..1eb773f8b 100644
--- a/src/Greenshot/Languages/website/language-website-en-US.xml
+++ b/Greenshot/Languages/language-website-en-US.xml
@@ -1,19 +1,19 @@
-
-
-
- Downloads
- Greenshot - a free screenshot tool optimized for productivity
- Greenshot is free and open source
- If you find that Greenshot saves you a lot of time and/or money, you are very welcome to <a href="/support/">support the development</a> of this screenshot software.
- Greenshot was published under <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, i.e. this software can be downloaded and used free of charge, even in a commercial environment.
- Want to see more?
- Of course there is more that Greenshot can do for you. Have a look at some <a title="Screenshots of Greenshot in action" href="/screenshots/">screenshots</a> of Greenshot in action or try the <a title="Download the latest stable version of Greenshot" href="/downloads/">latest release</a>.
- What is Greenshot????
- Quickly create screenshots of a selected region, window or fullscreen; you can even capture complete (scrolling) web pages from Internet Explorer.
- Easily annotate, highlight or obfuscate parts of the screenshot.
- Greenshot is a light-weight screenshot software tool for Windows with the following key features:
- ...and a lot more options simplifying creation of and work with screenshots every day.
- Export the screenshot in various ways: save to file, send to printer, copy to clipboard, attach to e-mail, send Office programs or upload to photo sites like Flickr or Picasa, and others.
- Being easy to understand and configurable, Greenshot is an efficient tool for project managers, software developers, technical writers, testers and anyone else creating screenshots.
-
-
+
+
+
+ Downloads
+ Greenshot - a free screenshot tool optimized for productivity
+ Greenshot is free and open source
+ If you find that Greenshot saves you a lot of time and/or money, you are very welcome to <a href="/support/">support the development</a> of this screenshot software.
+ Greenshot was published under <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, i.e. this software can be downloaded and used free of charge, even in a commercial environment.
+ Want to see more?
+ Of course there is more that Greenshot can do for you. Have a look at some <a title="Screenshots of Greenshot in action" href="/screenshots/">screenshots</a> of Greenshot in action or try the <a title="Download the latest stable version of Greenshot" href="/downloads/">latest release</a>.
+ What is Greenshot????
+ Quickly create screenshots of a selected region, window or fullscreen; you can even capture complete (scrolling) web pages from Internet Explorer.
+ Easily annotate, highlight or obfuscate parts of the screenshot.
+ Greenshot is a light-weight screenshot software tool for Windows with the following key features:
+ ...and a lot more options simplyfying creation of and work with screenshots every day.
+ Export the screenshot in various ways: save to file, send to printer, copy to clipboard, attach to e-mail, send Office programs or upload to photo sites like Flickr or Picasa, and others.
+ Being easy to understand and configurable, Greenshot is an efficient tool for project managers, software developers, technical writers, testers and anyone else creating screenshots.
+
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/website/language-website-es-ES.xml b/Greenshot/Languages/language-website-es-ES.xml
similarity index 88%
rename from src/Greenshot/Languages/website/language-website-es-ES.xml
rename to Greenshot/Languages/language-website-es-ES.xml
index c4f87efb9..f50a92a1f 100644
--- a/src/Greenshot/Languages/website/language-website-es-ES.xml
+++ b/Greenshot/Languages/language-website-es-ES.xml
@@ -1,19 +1,19 @@
-
-
-
- Descargas
- Greenshot - herramienta libre de captura de pantalla, optimizada para una mayor productividad
- Greenshot es código libre y abierto
- Si Greenshot te ahorra tiempo y/o dinero, puedes <a href="/support/">apoyar el desarrollo</a> de esta aplicación de captura de pantallas.
- Greenshot se publica bajo licencia <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>. Esta aplicación se puede descargar y utilizar de forma gratuita, incluso en un entorno comercial.
- ¿Quieres ver más?
- Por supuesto hay mucho más que Greenshot puede hacer. Echa un vistazo a algunas <a href="/screenshots/">capturas de pantalla</a> de Greenshot en acción o prueba la <a href="/downloads/">última versión</a>.
- ¿Qué es Greenshot?
- Creación rápida de capturas de una región seleccionado, una ventana o toda la pantalla; se puede incluso capturar (desplazando) páginas completas de Internet Explorer.
- Anotación, resalte y ocultación de partes de la captura de pantalla fácilmente.
- Greenshot es una herramienta ligera de captura de pantalla para Windows con las características esenciales:
- ... y muchas más opciones para simplificar el día a día en la creación y el trabajo con capturas de pantalla.
- Exportar la captura de pantalla de diversas maneras: guardar en archivo, imprimir, copiar al portapapeles, adjuntar a un correo electrónico, enviar a programa de Office o subir a sitios de fotos como Flickr o Picasa, entre otros.
- Al ser fácil de entender y configurar, Greenshot es una herramienta eficaz para gestores de proyecto, desarrolladores de software, escritores técnicos, evaluadores y cualquier persona que necesite capturas de pantalla.
-
+
+
+
+ Descargas
+ Greenshot - herramienta libre de captura de pantalla, optimizada para una mayor productividad
+ Greenshot es código libre y abierto
+ Si Greenshot te ahorra tiempo y/o dinero, puedes <a href="/support/">apoyar el desarrollo</a> de esta aplicación de captura de pantallas.
+ Greenshot se publica bajo licencia <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>. Esta aplicación se puede descargar y utilizar de forma gratuita, incluso en un entorno comercial.
+ ¿Quieres ver más?
+ Por supuesto hay mucho más que Greenshot puede hacer. Echa un vistazo a algunas <a href="/screenshots/">capturas de pantalla</a> de Greenshot en acción o prueba la <a href="/downloads/">última versión</a>.
+ ¿Qué es Greenshot?
+ Creación rápida de capturas de una región seleccionado, una ventana o toda la pantalla; se puede incluso capturar (desplazando) páginas completas de Internet Explorer.
+ Anotación, resalte y ocultación de partes de la captura de pantalla fácilmente.
+ Greenshot es una herramienta ligera de captura de pantalla para Windows con las características esenciales:
+ ... y muchas más opciones para simplificar el día a día en la creación y el trabajo con capturas de pantalla.
+ Exportar la captura de pantalla de diversas maneras: guardar en archivo, imprimir, copiar al portapapeles, adjuntar a un correo electrónico, enviar a programa de Office o subir a sitios de fotos como Flickr o Picasa, entre otros.
+ Al ser fácil de entender y configurar, Greenshot es una herramienta eficaz para gestores de proyecto, desarrolladores de software, escritores técnicos, evaluadores y cualquier persona que necesite capturas de pantalla.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/website/language-website-fr-FR.xml b/Greenshot/Languages/language-website-fr-FR.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-fr-FR.xml
rename to Greenshot/Languages/language-website-fr-FR.xml
index c8121ddd2..2da7d16f5 100644
--- a/src/Greenshot/Languages/website/language-website-fr-FR.xml
+++ b/Greenshot/Languages/language-website-fr-FR.xml
@@ -1,19 +1,19 @@
-
-
-
- Téléchargement
- Greenshot - Un outil de capture d’écran gratuit pour une productivité optimale
- Greenshot est gratuit et «Open Source».
- Si vous trouvez que Greenshot vous permet de faire des économies de temps et d’argent, vous êtes les bienvenus si vous nous apportez <a href="/support/">votre support dans le développement</a> de ce logiciel de capture d’écran.
- Greenshot a été publié sous <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, à savoir que ce logiciel peut être utilisé gratuitement, même dans un environnement commercial.
- Voulez-vous en savoir plus?
- Bien entendu Greenshot peut en faire beaucoup plus pour vous. Prenez la peine de regarder quelques <a href="/screenshots/">captures d’écran</a> de Greenshot en action ou essayer <a title="Download the latest stable version of Greenshot" href="/downloads/">la dernière mise à niveau</a>.
- Qu’est ce que Greenshot?
- Créer rapidement des captures d'une zone, d'une fenêtre ou d’un écran complet ; Il est même possible de capturer des pages web complètes (défilement) dans Internet Explorer.
- Annoter, surligner, assombrir ou brouiller facilement des parties de la capture.
- Greenshot est un logiciel de capture d’écran léger pour Windows avec les fonctionnalités majeures suivantes:
- ...et bien d'autres options qui permettent de simplifier le travail de création ou de gestion journaliers des captures d’écran.
- Exporter la capture de multiples façons: sauvegarde vers un fichier, impression, copie dans le presse-papier, joindre à un courriel, envoi vers des programmes Office ou envoi vers des sites de photos comme Flickr ou Picasa, et d’autres encore.
- Simple et facile à configurer, Greenshot est un outil efficace pour des responsables de projet, développeurs de logiciel, Concepteurs de manuels techniques, testeurs ou autres personnes créant des captures d’écran.
-
+
+
+
+ Téléchargement
+ Greenshot - Un outil de capture d’écran gratuit pour une productivité optimale
+ Greenshot est gratuit et «Open Source».
+ Si vous trouvez que Greenshot vous permet de faire des économies de temps et d’argent, vous êtes les bienvenus si vous nous apportez <a href="/support/">votre support dans le développement</a> de ce logiciel de capture d’écran.
+ Greenshot a été publié sous <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, à savoir que ce logiciel peut être utilisé gratuitement, même dans un environnement commercial.
+ Voulez-vous en savoir plus?
+ Bien entendu Greenshot peut en faire beaucoup plus pour vous. Prenez la peine de regarder quelques <a href="/screenshots/">captures d’écran</a> de Greenshot en action ou essayer <a title="Download the latest stable version of Greenshot" href="/downloads/">la dernière mise à niveau</a>.
+ Qu’est ce que Greenshot?
+ Créer rapidement des captures d'une zone, d'une fenêtre ou d’un écran complet ; Il est même possible de capturer des pages web complètes (défilement) dans Internet Explorer.
+ Annoter, surligner, assombrir ou brouiller facilement des parties de la capture.
+ Greenshot est un logiciel de capture d’écran léger pour Windows avec les fonctionnalités majeures suivantes:
+ ...et bien d'autres options qui permettent de simplifier le travail de création ou de gestion journaliers des captures d’écran.
+ Exporter la capture de multiples façons: sauvegarde vers un fichier, impression, copie dans le presse-papier, joindre à un courriel, envoi vers des programmes Office ou envoi vers des sites de photos comme Flickr ou Picasa, et d’autres encore.
+ Simple et facile à configurer, Greenshot est un outil efficace pour des responsables de projet, développeurs de logiciel, Concepteurs de manuels techniques, testeurs ou autres personnes créant des captures d’écran.
+
\ No newline at end of file
diff --git a/Greenshot/Languages/language-website-it-IT.xml b/Greenshot/Languages/language-website-it-IT.xml
new file mode 100644
index 000000000..4db0441b5
--- /dev/null
+++ b/Greenshot/Languages/language-website-it-IT.xml
@@ -0,0 +1,19 @@
+
+
+
+ Download
+ Greenshot - strumento di cattura gratis ottimizzato per la produttività
+ Greenshot è gratuito e open source
+ Se si scopre che Greenshot risparmiare un sacco di tempo e / o denaro, è possibile <a href="/support/">sostenere lo sviluppo</a> di questa strumento di cattura.
+ Greenshot è pubblicato sotto licenza <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>. Questo software può essere scaricato e utilizzato gratuitamente, anche in un ambiente commerciale.
+ Vuoi saperne di più?
+ Naturalmente c'è molto di più che si può fare per Greenshot. Check out alcuni <a href="/screenshots/">screenshot</a> di Greenshot in azione o provare la versione <a href="/downloads/">più recente</a>.
+ Greenshot - Che cosa è questo?
+ Rapidamente rendere le immagini di uno schermo selezionata regione, finestra o completo schermo. È possibile anche catturare le pagine web da Internet Explorer completi (scorrimento).
+ Annotare, evidenziare o nascondere parti di screenshot è facilmente.
+ Greenshot è uno strumento di cattura schermo per Windows con leggeri caratteristiche essenziali:
+ ... e molte altre opzioni per creare e lavorare con le immagini ogni giorno.
+ Esportazione screenshot in vari modi: salvare in un file, stampa, copia negli appunti, attaccare a un messaggio, inviare ai programmi di Office o caricare su siti di foto come Flickr e Picasa, tra gli altri.
+ Essere facile da capire e configurare, Greenshot è uno strumento efficace per i project manager, sviluppatori di software, redattori tecnici, collaudatori e chiunque altro la creazione di screenshot.
+
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/website/language-website-lv-LV.xml b/Greenshot/Languages/language-website-lv-LV.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-lv-LV.xml
rename to Greenshot/Languages/language-website-lv-LV.xml
index e8e854415..c9b5739a1 100644
--- a/src/Greenshot/Languages/website/language-website-lv-LV.xml
+++ b/Greenshot/Languages/language-website-lv-LV.xml
@@ -6,7 +6,7 @@
„Greenshot” - mūsdienīga un ērta ekrānattēla ieguves programmatūra
„Greenshot” ir brīvi lietojama atvērtā koda programmatūra
Ja „Greenshot” Tev ļoti palīdz darbā un ļauj ietaupīt laiku un naudu, novērtē to <a href="/support/">atbalstot tās izstrādi</a>..
- „Greenshot” programmatūra ir pieejama ar <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a> licenci. Tas nozīmē, ka to var brīvi lietot jebkurš gan personīgām, gan darba vajadzībām..
+ „Greenshot” programmatūra ir pieejama ar <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a> licenci. Tas nozīmē, ka to var brīvi lietot jebkurš gan personīgām, gan darba vajadzībām..
Vēlies uzzināt ko vairāk?
Ar „Greenshot” iespējams paveikt daudz ko. Iepazīsties ar <a title="„Greenshot” izmantošanas piemēru ekrānattēli" href="/screenshots/"> „Greenshot” izmantošanas piemēriem</a> vai lejupielādē <a title="Lejupielādē jaunāko pārbaudīto „Greenshot” versiju" href="/downloads/">jaunāko pārbaudīto „Greenshot” versiju</a>.
Kas tad ir „Greenshot”?
diff --git a/src/Greenshot/Languages/website/language-website-nn-NO.xml b/Greenshot/Languages/language-website-nn-NO.xml
similarity index 99%
rename from src/Greenshot/Languages/website/language-website-nn-NO.xml
rename to Greenshot/Languages/language-website-nn-NO.xml
index c388583da..1807d9b1e 100644
--- a/src/Greenshot/Languages/website/language-website-nn-NO.xml
+++ b/Greenshot/Languages/language-website-nn-NO.xml
@@ -1,19 +1,19 @@
-
-
-
- Nedlastingar
- Greenshot - ein gratis skjermknipsar som effektiviserer kvardagen
- Greenshot er gratis og har open kjeldekode
- Om du finn ut at Greenshot sparar deg for mykje tid og/eller pengar, er du velkomen til å <a href="/support/">støtte utviklinga</a> av programmet!
- Greenshot blir utgjeven under _GPL_, så programmet kan lastast ned og brukast utan kostnad, også i verksemder.
- Sjå meir?
- Sjølvsagt kan Greenshot by på meir! Ta ein gløtt på _skjermbilde_ av programmet i bruk, eller prøv den _nyaste utgåva_.
- Kva er Greenshot?
- Tar med eit tastetrykk bilde av eit vindauge, område eller heile skjermen - du kan til og med knipse heile nettsider (med rulling) frå Internet Explorer.
- Enkel notering, markering og sensurering i knipsfiksaren.
- Greenshot er eit lite og nett Windows-verktøy med dei fylgjande eigenskapane:
- ...og endå meir som forenklar arbeidet med skjermbilde - kvar dag!
- Eksporter skjermbildet til fil, skrivar, utklyppstavle, e-post, Office-program eller skytenester som til dømes Flickr og Picasa.
- Med det enkle, konfigurerbare grensesnittet er Greenshot eit effektivt verktøy for prosjektleiarar, programvareutviklararar, tekniske skribentar, testarar og alle andre som har nytte av å ta skjermbilde.
-
+
+
+
+ Nedlastingar
+ Greenshot - ein gratis skjermknipsar som effektiviserer kvardagen
+ Greenshot er gratis og har open kjeldekode
+ Om du finn ut at Greenshot sparar deg for mykje tid og/eller pengar, er du velkomen til å <a href="/support/">støtte utviklinga</a> av programmet!
+ Greenshot blir utgjeven under _GPL_, så programmet kan lastast ned og brukast utan kostnad, også i verksemder.
+ Sjå meir?
+ Sjølvsagt kan Greenshot by på meir! Ta ein gløtt på _skjermbilde_ av programmet i bruk, eller prøv den _nyaste utgåva_.
+ Kva er Greenshot?
+ Tar med eit tastetrykk bilde av eit vindauge, område eller heile skjermen - du kan til og med knipse heile nettsider (med rulling) frå Internet Explorer.
+ Enkel notering, markering og sensurering i knipsfiksaren.
+ Greenshot er eit lite og nett Windows-verktøy med dei fylgjande eigenskapane:
+ ...og endå meir som forenklar arbeidet med skjermbilde - kvar dag!
+ Eksporter skjermbildet til fil, skrivar, utklyppstavle, e-post, Office-program eller skytenester som til dømes Flickr og Picasa.
+ Med det enkle, konfigurerbare grensesnittet er Greenshot eit effektivt verktøy for prosjektleiarar, programvareutviklararar, tekniske skribentar, testarar og alle andre som har nytte av å ta skjermbilde.
+
\ No newline at end of file
diff --git a/src/Greenshot/Languages/website/language-website-sv-SE.xml b/Greenshot/Languages/language-website-sv-SE.xml
similarity index 100%
rename from src/Greenshot/Languages/website/language-website-sv-SE.xml
rename to Greenshot/Languages/language-website-sv-SE.xml
diff --git a/src/Greenshot/Languages/website/language-website-uk-UA.xml b/Greenshot/Languages/language-website-uk-UA.xml
similarity index 99%
rename from src/Greenshot/Languages/website/language-website-uk-UA.xml
rename to Greenshot/Languages/language-website-uk-UA.xml
index db80898d3..ef3dfe65c 100644
--- a/src/Greenshot/Languages/website/language-website-uk-UA.xml
+++ b/Greenshot/Languages/language-website-uk-UA.xml
@@ -1,19 +1,19 @@
-
-
-
- Завантаження
- Greenshot — безкоштовний інструмент для створення знімків екрану, оптимізований для покращення продуктивності
- Greenshot безкоштовний і з відкритим кодом
- Якщо Вам здається, що Greenshot зберігає чимало Вашого часу та/або грошей, Ви можете <a href="/support/">підтримати розробку</a> цього програмного забезпечення для створення знімків екрану.
- Greenshot розповсюджується відповідно до <a href="http://uk.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, тобто це програмне забезпечення можна вільно завантажувати та використовувати навіть з комерційною метою.
- Хочете побачити більше?
- Звісно, Greenshot може зробити для Вас набагато більше. Подивіться кілька <a title="Знімки Greenshot у дії" href="/screenshots/">знімків</a> Greenshot у дії та спробуйте <a title="Завантажити найновішу стабільну версію Greenshot" href="/downloads/">останній реліз</a>.
- Що таке Greenshot???
- Швидке створення знімків вибраної області, вікна або всього екрану; Ви навіть можете захоплювати всю (з прокручуванням) Інтернет-сторінку в Internet Explorer.
- Легке коментування, підсвічування або виділення частин знімку.
- Greenshot — це невеличка програма для створення знімків екрану для Windows з такими основними можливостями:
- ...та чимало інших можливостей, що спрощують створення та обробку знімків.
- Кілька варіантів експорту знімків: збереження в файл, друк, копіювання в буфер обміну, долучення до електронного листа, надсилання до офісних програм або вивантаження на фото-хостинги на зразок Flickr, Picasa та інші.
- Завдяки простоті налаштування та інтуїтивності, Greenshot є ефективним інструментом для керівників проектів, розробників програмного забезпечення, технічних авторів, тестерів та будь-кого іншого, кому потрібно створювати знімки.
-
-
+
+
+
+ Завантаження
+ Greenshot — безкоштовний інструмент для створення знімків екрану, оптимізований для покращення продуктивності
+ Greenshot безкоштовний і з відкритим кодом
+ Якщо Вам здається, що Greenshot зберігає чимало Вашого часу та/або грошей, Ви можете <a href="/support/">підтримати розробку</a> цього програмного забезпечення для створення знімків екрану.
+ Greenshot розповсюджується відповідно до <a href="http://uk.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, тобто це програмне забезпечення можна вільно завантажувати та використовувати навіть з комерційною метою.
+ Хочете побачити більше?
+ Звісно, Greenshot може зробити для Вас набагато більше. Подивіться кілька <a title="Знімки Greenshot у дії" href="/screenshots/">знімків</a> Greenshot у дії та спробуйте <a title="Завантажити найновішу стабільну версію Greenshot" href="/downloads/">останній реліз</a>.
+ Що таке Greenshot???
+ Швидке створення знімків вибраної області, вікна або всього екрану; Ви навіть можете захоплювати всю (з прокручуванням) Інтернет-сторінку в Internet Explorer.
+ Легке коментування, підсвічування або виділення частин знімку.
+ Greenshot — це невеличка програма для створення знімків екрану для Windows з такими основними можливостями:
+ ...та чимало інших можливостей, що спрощують створення та обробку знімків.
+ Кілька варіантів експорту знімків: збереження в файл, друк, копіювання в буфер обміну, долучення до електронного листа, надсилання до офісних програм або вивантаження на фото-хостинги на зразок Flickr, Picasa та інші.
+ Завдяки простоті налаштування та інтуїтивності, Greenshot є ефективним інструментом для керівників проектів, розробників програмного забезпечення, технічних авторів, тестерів та будь-кого іншого, кому потрібно створювати знімки.
+
+
diff --git a/src/Greenshot/Languages/language-zh-CN.xml b/Greenshot/Languages/language-zh-CN.xml
similarity index 97%
rename from src/Greenshot/Languages/language-zh-CN.xml
rename to Greenshot/Languages/language-zh-CN.xml
index e69489c8c..9b6bd73f6 100644
--- a/src/Greenshot/Languages/language-zh-CN.xml
+++ b/Greenshot/Languages/language-zh-CN.xml
@@ -5,7 +5,7 @@
如果您喜欢这个软件,希望您可以捐助我们:
Greenshot 托管在 GitHub
图标来源:Yusuke Kamiyamane的Fugue图标基于(Creative Commons Attribution 3.0 协议)
- 版权所有 (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ 版权所有 (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
作者不会对程序进行任何担保。
此程序为自由软件,您可以在遵守 GNU 通用公共许可协议下任意传播本软件。
关于 GNU 通用公共许可协议:
@@ -15,7 +15,7 @@
很抱歉,坏消息是程序出现了错误。
好消息是:您可以填写错误报告来帮助我们纠正错误。
请点击下面的链接,新建一个错误报告将文字区域的内容粘贴到描述栏中。
-
+
并请填写一些你认为可能帮助描述错误产生时的情况的信息。
此外,我们强烈建议您在我们的网站检查一下是否已经有人报告过相同的错误(您可以搜索一下)。非常感谢 :)
错误
@@ -84,8 +84,6 @@
复制路径到剪贴板
复制
裁剪 (C)
- 裁剪
- 自动裁剪
选择工具 (ESC)
剪切
刪除物件
diff --git a/src/Greenshot/Languages/language-zh-TW.xml b/Greenshot/Languages/language-zh-TW.xml
similarity index 88%
rename from src/Greenshot/Languages/language-zh-TW.xml
rename to Greenshot/Languages/language-zh-TW.xml
index 63f8fce2f..26b25065b 100644
--- a/src/Greenshot/Languages/language-zh-TW.xml
+++ b/Greenshot/Languages/language-zh-TW.xml
@@ -1,15 +1,14 @@
-
+
請回報錯誤到以下網址
如果您喜歡 Greenshot,歡迎您支持我們:
Greenshot 的主機在 GitHub 網址是
圖片來源: Yusuke Kamiyamane's Fugue 圖示集 (Creative Commons Attribution 3.0 授權)
- Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
-Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您可以在 GNU General Public License 下任意散佈本軟體。
-關於 GNU General Public License 詳細資料:
+ Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+Greenshot 不對這個程式做任何擔保。 這個程式是自由軟體,您可以在 GNU General Public License 下任意散佈本軟體。
+關於GNU General Public License 詳細資料:
關於 Greenshot
-
Greenshot - 革命性的螢幕截圖工具
關閉
很抱歉,發生未預期錯誤。
@@ -25,7 +24,7 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
Greenshot 無法將資料寫入剪貼簿,因為 {0} 已將剪貼簿鎖定。
找不到剪貼簿圖片。
Windows 點陣圖
- Device Independent Bitmap (DIB)
+ Device Independend Bitmap (DIB)
HTML
HTML 含內嵌圖像
PNG
@@ -93,8 +92,6 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
複製路徑到剪貼簿
複製
裁剪 (C)
- 裁剪
- 自動裁剪
選取工具 (ESC)
剪下
刪除
@@ -107,6 +104,10 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
繪製直線 (L)
繪製矩形 (R)
加入文字方塊 (T)
+ 陰影黑暗
+ 陰影偏移
+ 陰影設定
+ 陰影厚度
複製選取的元素
編輯
效果
@@ -154,8 +155,12 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
直線粗細
Greenshot 圖片編輯器
撕裂邊緣
- 復原 {0}
- 上移一層
+ 水平鋸齒範圍
+ 撕裂邊緣設定
+ 鋸齒大小
+ 垂直鋸齒範圍
+ 復原 {0}
+ 上移一層
移到最上層
MAPI 用戶端
Outlook 使用 HTML
@@ -167,13 +172,12 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
無法開啟檔案「{0}」。
無法開啟連結「{0}」。
無法儲存螢幕擷圖,請尋找適合的位置。
- 產生的檔名或是路徑名稱無效。請修正檔名樣式並重試。
專家
在 > 8 位元圖像時,如果色彩小於 256 則建立 8 位元圖像
檢查 Beta 版更新
剪貼簿格式
檔案名稱樣式中 ${NUM} 的數字
- 我知道我在做什麼!
+ 我明白我所做的動作!
印表機頁尾樣式
最小化記憶體佔用空間,但降低效能 (不建議)。
進行使用遠端桌面的一些最佳化
@@ -184,7 +188,7 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
匯出到 {0} 時發生錯誤:
Greenshot 說明
熱鍵
- 請選擇圖片的 JPEG 品質。
+ 請選擇圖片的 JPEG品質。
確定
嘗試列印時發生錯誤。
列印在紙張的正中央
@@ -227,7 +231,7 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
Internet Explorer 擷取
JPEG 品質
語言
- 在樣式定義中以下預留位置將自動取代:
+ 在樣式定義中以下預留位置將自動取代:
${YYYY} 年,4 位數字
${MM} 月,2 位數字
${DD} 日,2 位數字
@@ -235,7 +239,6 @@ ${hh} 時,2 位數字
${mm} 分,2 位數字
${ss} 秒,2 位數字
${NUM} 自動編號,6 位數字
-${RRR...} 隨機編號, 與 R 的長度相同
${title} 視窗標題
${user} Windows 使用者名稱
${domain} Windows 網域名稱
@@ -275,7 +278,7 @@ ${hostname} 電腦名稱
視窗擷取
顯示放大鏡
右鍵按一下這裡或是按下 {0} 鍵。
- Greenshot 的新版本可以使用! 您要下載 Greenshot {0} 嗎?
+ Greenshot 的新版本可以使用! 您要下載 Greenshot {0} 嗎?
擷取 Internet Explorer 中頁面時請稍候...
警告
無法註冊熱鍵「{0}」。 這個問題可能是另一個工具要求使用相同的熱鍵。 您可以變更熱鍵設定或停用/變更軟體使用熱鍵。
@@ -286,33 +289,5 @@ Greenshot 所有功能仍然可以直接從通知區圖示的內容功能表動
自動
使用預設色彩
如顯示
-
-
- 陰影黑暗
- 陰影偏移
- 陰影設定
- 陰影厚度
-
- 水平鋸齒範圍
- 撕裂邊緣設定
- 鋸齒大小
- 垂直鋸齒範圍
- 撕裂所有邊緣
- 左側
- 右側
- 上方
- 下方
- 產生陰影
-
- 加入計數器 (I)
- 加入對話框 (S)
-
- 縮放 (Z)
- 縮放設定
- 維持長寬比
- 長度
- 寬度
- 圖示大小
-
-
+
\ No newline at end of file
diff --git a/Greenshot/Lib/log4net.dll b/Greenshot/Lib/log4net.dll
new file mode 100644
index 000000000..53d65f10b
Binary files /dev/null and b/Greenshot/Lib/log4net.dll differ
diff --git a/Greenshot/Memento/AddElementMemento.cs b/Greenshot/Memento/AddElementMemento.cs
new file mode 100644
index 000000000..ff7aac4d1
--- /dev/null
+++ b/Greenshot/Memento/AddElementMemento.cs
@@ -0,0 +1,67 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using Greenshot.Drawing;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Memento {
+ ///
+ /// The AddElementMemento makes it possible to undo adding an element
+ ///
+ public class AddElementMemento : IMemento {
+ private IDrawableContainer _drawableContainer;
+ private Surface _surface;
+
+ public AddElementMemento(Surface surface, IDrawableContainer drawableContainer) {
+ _surface = surface;
+ _drawableContainer = drawableContainer;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ //if (disposing) { }
+ _drawableContainer = null;
+ _surface = null;
+ }
+
+ public bool Merge(IMemento otherMemento) {
+ return false;
+ }
+
+ public IMemento Restore() {
+ // Before
+ _drawableContainer.Invalidate();
+ // Store the selected state, as it's overwritten by the RemoveElement
+
+ DeleteElementMemento oldState = new DeleteElementMemento(_surface, _drawableContainer);
+ _surface.RemoveElement(_drawableContainer, false);
+ _drawableContainer.Selected = true;
+
+ // After
+ _drawableContainer.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/AddElementsMemento.cs b/Greenshot/Memento/AddElementsMemento.cs
new file mode 100644
index 000000000..b28543512
--- /dev/null
+++ b/Greenshot/Memento/AddElementsMemento.cs
@@ -0,0 +1,71 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using Greenshot.Drawing;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Memento
+{
+ ///
+ /// The AddElementMemento makes it possible to undo adding an element
+ ///
+ public class AddElementsMemento : IMemento
+ {
+ private IDrawableContainerList _containerList;
+ private Surface _surface;
+
+ public AddElementsMemento(Surface surface, IDrawableContainerList containerList)
+ {
+ _surface = surface;
+ _containerList = containerList;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _containerList?.Dispose();
+ }
+ _containerList = null;
+ _surface = null;
+ }
+
+ public bool Merge(IMemento otherMemento)
+ {
+ return false;
+ }
+
+ public IMemento Restore()
+ {
+ var oldState = new DeleteElementsMemento(_surface, _containerList);
+
+ _surface.RemoveElements(_containerList, false);
+
+ // After, so everything is gone
+ _surface.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/ChangeFieldHolderMemento.cs b/Greenshot/Memento/ChangeFieldHolderMemento.cs
new file mode 100644
index 000000000..0e5c371f3
--- /dev/null
+++ b/Greenshot/Memento/ChangeFieldHolderMemento.cs
@@ -0,0 +1,85 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Interfaces.Drawing;
+
+namespace Greenshot.Memento
+{
+ ///
+ /// The ChangeFieldHolderMemento makes it possible to undo-redo an IDrawableContainer move
+ ///
+ public class ChangeFieldHolderMemento : IMemento
+ {
+ private IDrawableContainer _drawableContainer;
+ private readonly IField _fieldToBeChanged;
+ private readonly object _oldValue;
+
+ public ChangeFieldHolderMemento(IDrawableContainer drawableContainer, IField fieldToBeChanged)
+ {
+ _drawableContainer = drawableContainer;
+ _fieldToBeChanged = fieldToBeChanged;
+ _oldValue = fieldToBeChanged.Value;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _drawableContainer?.Dispose();
+ }
+ _drawableContainer = null;
+ }
+
+ public bool Merge(IMemento otherMemento)
+ {
+ ChangeFieldHolderMemento other = otherMemento as ChangeFieldHolderMemento;
+ if (other != null)
+ {
+ if (other._drawableContainer.Equals(_drawableContainer))
+ {
+ if (other._fieldToBeChanged.Equals(_fieldToBeChanged))
+ {
+ // Match, do not store anything as the initial state is what we want.
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public IMemento Restore()
+ {
+ // Before
+ _drawableContainer.Invalidate();
+ ChangeFieldHolderMemento oldState = new ChangeFieldHolderMemento(_drawableContainer, _fieldToBeChanged);
+ _fieldToBeChanged.Value = _oldValue;
+ // After
+ _drawableContainer.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/DeleteElementMemento.cs b/Greenshot/Memento/DeleteElementMemento.cs
new file mode 100644
index 000000000..818d28264
--- /dev/null
+++ b/Greenshot/Memento/DeleteElementMemento.cs
@@ -0,0 +1,72 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using Greenshot.Drawing;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Memento {
+ ///
+ /// The DeleteElementMemento makes it possible to undo deleting an element
+ ///
+ public class DeleteElementMemento : IMemento {
+ private IDrawableContainer drawableContainer;
+ private readonly Surface surface;
+
+ public DeleteElementMemento(Surface surface, IDrawableContainer drawableContainer) {
+ this.surface = surface;
+ this.drawableContainer = drawableContainer;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (drawableContainer != null) {
+ drawableContainer.Dispose();
+ drawableContainer = null;
+ }
+ }
+ }
+
+ public bool Merge(IMemento otherMemento) {
+ return false;
+ }
+
+ public IMemento Restore() {
+ // Before
+ drawableContainer.Invalidate();
+
+ AddElementMemento oldState = new AddElementMemento(surface, drawableContainer);
+ surface.AddElement(drawableContainer, false);
+ // The container has a selected flag which represents the state at the moment it was deleted.
+ if (drawableContainer.Selected) {
+ surface.SelectElement(drawableContainer);
+ }
+
+ // After
+ drawableContainer.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/DeleteElementsMemento.cs b/Greenshot/Memento/DeleteElementsMemento.cs
new file mode 100644
index 000000000..e0178a36e
--- /dev/null
+++ b/Greenshot/Memento/DeleteElementsMemento.cs
@@ -0,0 +1,69 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using Greenshot.Drawing;
+using Greenshot.Plugin.Drawing;
+
+namespace Greenshot.Memento
+{
+ ///
+ /// The DeleteElementMemento makes it possible to undo deleting an element
+ ///
+ public class DeleteElementsMemento : IMemento
+ {
+ private IDrawableContainerList _containerList;
+ private Surface _surface;
+
+ public DeleteElementsMemento(Surface surface, IDrawableContainerList containerList)
+ {
+ _surface = surface;
+ _containerList = containerList;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _containerList?.Dispose();
+ }
+ _containerList = null;
+ _surface = null;
+ }
+
+ public bool Merge(IMemento otherMemento)
+ {
+ return false;
+ }
+
+ public IMemento Restore()
+ {
+ AddElementsMemento oldState = new AddElementsMemento(_surface, _containerList);
+ _surface.AddElements(_containerList, false);
+ // After
+ _surface.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs b/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs
new file mode 100644
index 000000000..08b4db616
--- /dev/null
+++ b/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs
@@ -0,0 +1,110 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using Greenshot.Drawing;
+using Greenshot.Plugin.Drawing;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Greenshot.Memento
+{
+ ///
+ /// The DrawableContainerBoundsChangeMemento makes it possible to undo-redo an IDrawableContainer resize & move
+ ///
+ public class DrawableContainerBoundsChangeMemento : IMemento
+ {
+ private readonly List _points = new List();
+ private readonly List _sizes = new List();
+ private IDrawableContainerList _listOfdrawableContainer;
+
+ private void StoreBounds()
+ {
+ foreach (IDrawableContainer drawableContainer in _listOfdrawableContainer)
+ {
+ _points.Add(drawableContainer.Location);
+ _sizes.Add(drawableContainer.Size);
+ }
+ }
+
+ public DrawableContainerBoundsChangeMemento(IDrawableContainerList listOfdrawableContainer)
+ {
+ _listOfdrawableContainer = listOfdrawableContainer;
+ StoreBounds();
+ }
+
+ public DrawableContainerBoundsChangeMemento(IDrawableContainer drawableContainer)
+ {
+ _listOfdrawableContainer = new DrawableContainerList
+ {
+ drawableContainer
+ };
+ _listOfdrawableContainer.Parent = drawableContainer.Parent;
+ StoreBounds();
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _listOfdrawableContainer?.Dispose();
+ }
+ _listOfdrawableContainer = null;
+ }
+
+ public bool Merge(IMemento otherMemento)
+ {
+ var other = otherMemento as DrawableContainerBoundsChangeMemento;
+ if (other != null)
+ {
+ if (ObjectExtensions.CompareLists(_listOfdrawableContainer, other._listOfdrawableContainer))
+ {
+ // Lists are equal, as we have the state already we can ignore the new memento
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public IMemento Restore()
+ {
+ var oldState = new DrawableContainerBoundsChangeMemento(_listOfdrawableContainer);
+ for (int index = 0; index < _listOfdrawableContainer.Count; index++)
+ {
+ IDrawableContainer drawableContainer = _listOfdrawableContainer[index];
+ // Before
+ drawableContainer.Invalidate();
+ drawableContainer.Left = _points[index].X;
+ drawableContainer.Top = _points[index].Y;
+ drawableContainer.Width = _sizes[index].Width;
+ drawableContainer.Height = _sizes[index].Height;
+ // After
+ drawableContainer.Invalidate();
+ drawableContainer.Parent.Modified = true;
+ }
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/IMemento.cs b/Greenshot/Memento/IMemento.cs
new file mode 100644
index 000000000..c0a28417c
--- /dev/null
+++ b/Greenshot/Memento/IMemento.cs
@@ -0,0 +1,51 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using Greenshot.Configuration;
+
+namespace Greenshot.Memento {
+ ///
+ /// Description of IMemento.
+ ///
+ public interface IMemento : IDisposable {
+ ///
+ /// Restores target to the state memorized by this memento.
+ ///
+ ///
+ /// A memento of the state before restoring
+ ///
+ IMemento Restore();
+
+ ///
+ /// Try to merge the current memento with another, preventing loads of items on the stack
+ ///
+ /// The memento to try to merge with
+ ///
+ bool Merge(IMemento other);
+
+ ///
+ /// Returns the language key for the action which is performed
+ ///
+ LangKey ActionLanguageKey {
+ get;
+ }
+ }
+}
diff --git a/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs b/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs
new file mode 100644
index 000000000..ea0752c68
--- /dev/null
+++ b/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs
@@ -0,0 +1,72 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace Greenshot.Memento {
+ ///
+ /// The SurfaceCropMemento makes it possible to undo-redo an surface crop
+ ///
+ public class SurfaceBackgroundChangeMemento : IMemento {
+ private Image _image;
+ private Surface _surface;
+ private Matrix _matrix;
+
+ public SurfaceBackgroundChangeMemento(Surface surface, Matrix matrix) {
+ _surface = surface;
+ _image = surface.Image;
+ _matrix = matrix.Clone();
+ // Make sure the reverse is applied
+ _matrix.Invert();
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_matrix != null) {
+ _matrix.Dispose();
+ _matrix = null;
+ }
+ if (_image != null) {
+ _image.Dispose();
+ _image = null;
+ }
+ _surface = null;
+ }
+ }
+
+ public bool Merge(IMemento otherMemento) {
+ return false;
+ }
+
+ public IMemento Restore() {
+ SurfaceBackgroundChangeMemento oldState = new SurfaceBackgroundChangeMemento(_surface, _matrix);
+ _surface.UndoBackgroundChange(_image, _matrix);
+ _surface.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Memento/TextChangeMemento.cs b/Greenshot/Memento/TextChangeMemento.cs
new file mode 100644
index 000000000..04d467716
--- /dev/null
+++ b/Greenshot/Memento/TextChangeMemento.cs
@@ -0,0 +1,68 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Drawing;
+
+namespace Greenshot.Memento {
+ ///
+ /// The TextChangeMemento makes it possible to undo-redo an IDrawableContainer move
+ ///
+ public class TextChangeMemento : IMemento {
+ private TextContainer textContainer;
+ private readonly string oldText;
+
+ public TextChangeMemento(TextContainer textContainer) {
+ this.textContainer = textContainer;
+ oldText = textContainer.Text;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ textContainer = null;
+ }
+ }
+
+ public bool Merge(IMemento otherMemento) {
+ TextChangeMemento other = otherMemento as TextChangeMemento;
+ if (other != null) {
+ if (other.textContainer.Equals(textContainer)) {
+ // Match, do not store anything as the initial state is what we want.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public IMemento Restore() {
+ // Before
+ textContainer.Invalidate();
+ TextChangeMemento oldState = new TextChangeMemento(textContainer);
+ textContainer.ChangeText(oldText, false);
+ // After
+ textContainer.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/Greenshot/Processors/TitleFixProcessor.cs b/Greenshot/Processors/TitleFixProcessor.cs
new file mode 100644
index 000000000..25495901e
--- /dev/null
+++ b/Greenshot/Processors/TitleFixProcessor.cs
@@ -0,0 +1,93 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace Greenshot.Processors {
+ ///
+ /// Description of TitleFixProcessor.
+ ///
+ public class TitleFixProcessor : AbstractProcessor {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(TitleFixProcessor));
+ private static readonly CoreConfiguration config = IniConfig.GetIniSection();
+
+ public TitleFixProcessor() {
+ List corruptKeys = new List();
+ foreach(string key in config.ActiveTitleFixes) {
+ if (!config.TitleFixMatcher.ContainsKey(key)) {
+ LOG.WarnFormat("Key {0} not found, configuration is broken! Disabling this key!");
+ corruptKeys.Add(key);
+ }
+ }
+
+ // Fix configuration if needed
+ if(corruptKeys.Count > 0) {
+ foreach(string corruptKey in corruptKeys) {
+ // Removing any reference to the key
+ config.ActiveTitleFixes.Remove(corruptKey);
+ config.TitleFixMatcher.Remove(corruptKey);
+ config.TitleFixReplacer.Remove(corruptKey);
+ }
+ config.IsDirty = true;
+ }
+ }
+
+ public override string Designation {
+ get {
+ return "TitleFix";
+ }
+ }
+
+ public override string Description {
+ get {
+ return Designation;
+ }
+ }
+
+ public override bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails) {
+ bool changed = false;
+ string title = captureDetails.Title;
+ if (!string.IsNullOrEmpty(title)) {
+ title = title.Trim();
+ foreach(string titleIdentifier in config.ActiveTitleFixes) {
+ string regexpString = config.TitleFixMatcher[titleIdentifier];
+ string replaceString = config.TitleFixReplacer[titleIdentifier];
+ if (replaceString == null) {
+ replaceString = "";
+ }
+ if (!string.IsNullOrEmpty(regexpString)) {
+ Regex regex = new Regex(regexpString);
+ title = regex.Replace(title, replaceString);
+ changed = true;
+ }
+ }
+ }
+ captureDetails.Title = title;
+ return changed;
+ }
+ }
+}
diff --git a/src/Greenshot/Sounds.resx b/Greenshot/Sounds.resx
similarity index 98%
rename from src/Greenshot/Sounds.resx
rename to Greenshot/Sounds.resx
index 1b69c685e..56901a7fe 100644
--- a/src/Greenshot/Sounds.resx
+++ b/Greenshot/Sounds.resx
@@ -112,12 +112,12 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
UklGRiRAAABXQVZFZm10IBAAAAABAAEAESsAACJWAAACABAAZGF0YQBAAAAAAAAAAAAAAAAAAAAAAAAA
diff --git a/Greenshot/greenshot.manifest b/Greenshot/greenshot.manifest
new file mode 100644
index 000000000..919fcb895
--- /dev/null
+++ b/Greenshot/greenshot.manifest
@@ -0,0 +1,44 @@
+
+
+
+
+
+ True/PM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Greenshot/icons/applicationIcon/16.ico b/Greenshot/icons/applicationIcon/16.ico
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/16.ico
rename to Greenshot/icons/applicationIcon/16.ico
diff --git a/src/Greenshot/icons/applicationIcon/16.png b/Greenshot/icons/applicationIcon/16.png
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/16.png
rename to Greenshot/icons/applicationIcon/16.png
diff --git a/src/Greenshot/icons/applicationIcon/32.ico b/Greenshot/icons/applicationIcon/32.ico
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/32.ico
rename to Greenshot/icons/applicationIcon/32.ico
diff --git a/src/Greenshot/icons/applicationIcon/32.png b/Greenshot/icons/applicationIcon/32.png
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/32.png
rename to Greenshot/icons/applicationIcon/32.png
diff --git a/src/Greenshot/icons/applicationIcon/48.ico b/Greenshot/icons/applicationIcon/48.ico
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/48.ico
rename to Greenshot/icons/applicationIcon/48.ico
diff --git a/src/Greenshot/icons/applicationIcon/48.png b/Greenshot/icons/applicationIcon/48.png
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/48.png
rename to Greenshot/icons/applicationIcon/48.png
diff --git a/src/Greenshot/icons/applicationIcon/90.png b/Greenshot/icons/applicationIcon/90.png
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/90.png
rename to Greenshot/icons/applicationIcon/90.png
diff --git a/src/Greenshot/icons/applicationIcon/icon.ico b/Greenshot/icons/applicationIcon/icon.ico
similarity index 100%
rename from src/Greenshot/icons/applicationIcon/icon.ico
rename to Greenshot/icons/applicationIcon/icon.ico
diff --git a/src/Greenshot/icons/arrow_redo.png b/Greenshot/icons/arrow_redo.png
similarity index 100%
rename from src/Greenshot/icons/arrow_redo.png
rename to Greenshot/icons/arrow_redo.png
diff --git a/src/Greenshot/icons/arrow_rollback.png b/Greenshot/icons/arrow_rollback.png
similarity index 100%
rename from src/Greenshot/icons/arrow_rollback.png
rename to Greenshot/icons/arrow_rollback.png
diff --git a/src/Greenshot/icons/arrow_undo.png b/Greenshot/icons/arrow_undo.png
similarity index 100%
rename from src/Greenshot/icons/arrow_undo.png
rename to Greenshot/icons/arrow_undo.png
diff --git a/src/Greenshot.Editor/icons/balloon.png b/Greenshot/icons/balloon.png
similarity index 100%
rename from src/Greenshot.Editor/icons/balloon.png
rename to Greenshot/icons/balloon.png
diff --git a/src/Greenshot/icons/cancel.png b/Greenshot/icons/cancel.png
similarity index 100%
rename from src/Greenshot/icons/cancel.png
rename to Greenshot/icons/cancel.png
diff --git a/src/Greenshot/icons/cross.png b/Greenshot/icons/cross.png
similarity index 100%
rename from src/Greenshot/icons/cross.png
rename to Greenshot/icons/cross.png
diff --git a/src/Greenshot/icons/cut.png b/Greenshot/icons/cut.png
similarity index 100%
rename from src/Greenshot/icons/cut.png
rename to Greenshot/icons/cut.png
diff --git a/src/Greenshot/icons/delete.png b/Greenshot/icons/delete.png
similarity index 100%
rename from src/Greenshot/icons/delete.png
rename to Greenshot/icons/delete.png
diff --git a/src/Greenshot/icons/filter_blur.png b/Greenshot/icons/filter_blur.png
similarity index 100%
rename from src/Greenshot/icons/filter_blur.png
rename to Greenshot/icons/filter_blur.png
diff --git a/src/Greenshot/icons/filter_pixelate.png b/Greenshot/icons/filter_pixelate.png
similarity index 100%
rename from src/Greenshot/icons/filter_pixelate.png
rename to Greenshot/icons/filter_pixelate.png
diff --git a/src/Greenshot/icons/folder-open-image.png b/Greenshot/icons/folder-open-image.png
similarity index 100%
rename from src/Greenshot/icons/folder-open-image.png
rename to Greenshot/icons/folder-open-image.png
diff --git a/src/Greenshot/icons/folder_explore.png b/Greenshot/icons/folder_explore.png
similarity index 100%
rename from src/Greenshot/icons/folder_explore.png
rename to Greenshot/icons/folder_explore.png
diff --git a/src/Greenshot/icons/font_color.png b/Greenshot/icons/font_color.png
similarity index 100%
rename from src/Greenshot/icons/font_color.png
rename to Greenshot/icons/font_color.png
diff --git a/src/Greenshot/icons/freehand.png b/Greenshot/icons/freehand.png
similarity index 100%
rename from src/Greenshot/icons/freehand.png
rename to Greenshot/icons/freehand.png
diff --git a/src/Greenshot/icons/fugue/arrow-resize.png b/Greenshot/icons/fugue/arrow-resize.png
similarity index 100%
rename from src/Greenshot/icons/fugue/arrow-resize.png
rename to Greenshot/icons/fugue/arrow-resize.png
diff --git a/src/Greenshot/icons/fugue/clipboard-paste-image.png b/Greenshot/icons/fugue/clipboard-paste-image.png
similarity index 100%
rename from src/Greenshot/icons/fugue/clipboard-paste-image.png
rename to Greenshot/icons/fugue/clipboard-paste-image.png
diff --git a/src/Greenshot/icons/fugue/clipboard.png b/Greenshot/icons/fugue/clipboard.png
similarity index 100%
rename from src/Greenshot/icons/fugue/clipboard.png
rename to Greenshot/icons/fugue/clipboard.png
diff --git a/src/Greenshot/icons/fugue/color-swatch.png b/Greenshot/icons/fugue/color-swatch.png
similarity index 100%
rename from src/Greenshot/icons/fugue/color-swatch.png
rename to Greenshot/icons/fugue/color-swatch.png
diff --git a/src/Greenshot/icons/fugue/cross.png b/Greenshot/icons/fugue/cross.png
similarity index 100%
rename from src/Greenshot/icons/fugue/cross.png
rename to Greenshot/icons/fugue/cross.png
diff --git a/src/Greenshot/icons/fugue/cursor.png b/Greenshot/icons/fugue/cursor.png
similarity index 100%
rename from src/Greenshot/icons/fugue/cursor.png
rename to Greenshot/icons/fugue/cursor.png
diff --git a/src/Greenshot/icons/fugue/disk-black.png b/Greenshot/icons/fugue/disk-black.png
similarity index 100%
rename from src/Greenshot/icons/fugue/disk-black.png
rename to Greenshot/icons/fugue/disk-black.png
diff --git a/src/Greenshot/icons/fugue/edit-alignment-center.png b/Greenshot/icons/fugue/edit-alignment-center.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-alignment-center.png
rename to Greenshot/icons/fugue/edit-alignment-center.png
diff --git a/src/Greenshot/icons/fugue/edit-alignment-right.png b/Greenshot/icons/fugue/edit-alignment-right.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-alignment-right.png
rename to Greenshot/icons/fugue/edit-alignment-right.png
diff --git a/src/Greenshot/icons/fugue/edit-alignment.png b/Greenshot/icons/fugue/edit-alignment.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-alignment.png
rename to Greenshot/icons/fugue/edit-alignment.png
diff --git a/src/Greenshot/icons/fugue/edit-blur.png b/Greenshot/icons/fugue/edit-blur.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-blur.png
rename to Greenshot/icons/fugue/edit-blur.png
diff --git a/src/Greenshot/icons/fugue/edit-bold.png b/Greenshot/icons/fugue/edit-bold.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-bold.png
rename to Greenshot/icons/fugue/edit-bold.png
diff --git a/src/Greenshot/icons/fugue/edit-italic.png b/Greenshot/icons/fugue/edit-italic.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-italic.png
rename to Greenshot/icons/fugue/edit-italic.png
diff --git a/src/Greenshot/icons/fugue/edit-pixelate.png b/Greenshot/icons/fugue/edit-pixelate.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-pixelate.png
rename to Greenshot/icons/fugue/edit-pixelate.png
diff --git a/src/Greenshot/icons/fugue/edit-underline.png b/Greenshot/icons/fugue/edit-underline.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-underline.png
rename to Greenshot/icons/fugue/edit-underline.png
diff --git a/src/Greenshot/icons/fugue/edit-vertical-alignment-middle.png b/Greenshot/icons/fugue/edit-vertical-alignment-middle.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-vertical-alignment-middle.png
rename to Greenshot/icons/fugue/edit-vertical-alignment-middle.png
diff --git a/src/Greenshot/icons/fugue/edit-vertical-alignment-top.png b/Greenshot/icons/fugue/edit-vertical-alignment-top.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-vertical-alignment-top.png
rename to Greenshot/icons/fugue/edit-vertical-alignment-top.png
diff --git a/src/Greenshot/icons/fugue/edit-vertical-alignment.png b/Greenshot/icons/fugue/edit-vertical-alignment.png
similarity index 100%
rename from src/Greenshot/icons/fugue/edit-vertical-alignment.png
rename to Greenshot/icons/fugue/edit-vertical-alignment.png
diff --git a/src/Greenshot/icons/fugue/filter_base.pdn b/Greenshot/icons/fugue/filter_base.pdn
similarity index 100%
rename from src/Greenshot/icons/fugue/filter_base.pdn
rename to Greenshot/icons/fugue/filter_base.pdn
diff --git a/src/Greenshot/icons/fugue/filter_highlight_area.png b/Greenshot/icons/fugue/filter_highlight_area.png
similarity index 100%
rename from src/Greenshot/icons/fugue/filter_highlight_area.png
rename to Greenshot/icons/fugue/filter_highlight_area.png
diff --git a/src/Greenshot/icons/fugue/filter_highlight_grayscale.png b/Greenshot/icons/fugue/filter_highlight_grayscale.png
similarity index 100%
rename from src/Greenshot/icons/fugue/filter_highlight_grayscale.png
rename to Greenshot/icons/fugue/filter_highlight_grayscale.png
diff --git a/src/Greenshot/icons/fugue/filter_highlight_text.png b/Greenshot/icons/fugue/filter_highlight_text.png
similarity index 100%
rename from src/Greenshot/icons/fugue/filter_highlight_text.png
rename to Greenshot/icons/fugue/filter_highlight_text.png
diff --git a/src/Greenshot/icons/fugue/gear.png b/Greenshot/icons/fugue/gear.png
similarity index 100%
rename from src/Greenshot/icons/fugue/gear.png
rename to Greenshot/icons/fugue/gear.png
diff --git a/src/Greenshot/icons/fugue/highlighter-color.png b/Greenshot/icons/fugue/highlighter-color.png
similarity index 100%
rename from src/Greenshot/icons/fugue/highlighter-color.png
rename to Greenshot/icons/fugue/highlighter-color.png
diff --git a/src/Greenshot/icons/fugue/highlighter-text.png b/Greenshot/icons/fugue/highlighter-text.png
similarity index 100%
rename from src/Greenshot/icons/fugue/highlighter-text.png
rename to Greenshot/icons/fugue/highlighter-text.png
diff --git a/src/Greenshot/icons/fugue/image-blur.png b/Greenshot/icons/fugue/image-blur.png
similarity index 100%
rename from src/Greenshot/icons/fugue/image-blur.png
rename to Greenshot/icons/fugue/image-blur.png
diff --git a/src/Greenshot/icons/fugue/image-pixelate.png b/Greenshot/icons/fugue/image-pixelate.png
similarity index 100%
rename from src/Greenshot/icons/fugue/image-pixelate.png
rename to Greenshot/icons/fugue/image-pixelate.png
diff --git a/src/Greenshot/icons/fugue/images.png b/Greenshot/icons/fugue/images.png
similarity index 100%
rename from src/Greenshot/icons/fugue/images.png
rename to Greenshot/icons/fugue/images.png
diff --git a/src/Greenshot/icons/fugue/layer-shape-arrow.png b/Greenshot/icons/fugue/layer-shape-arrow.png
similarity index 100%
rename from src/Greenshot/icons/fugue/layer-shape-arrow.png
rename to Greenshot/icons/fugue/layer-shape-arrow.png
diff --git a/src/Greenshot/icons/fugue/layer-shape-ellipse.png b/Greenshot/icons/fugue/layer-shape-ellipse.png
similarity index 100%
rename from src/Greenshot/icons/fugue/layer-shape-ellipse.png
rename to Greenshot/icons/fugue/layer-shape-ellipse.png
diff --git a/src/Greenshot/icons/fugue/layer-shape-line.png b/Greenshot/icons/fugue/layer-shape-line.png
similarity index 100%
rename from src/Greenshot/icons/fugue/layer-shape-line.png
rename to Greenshot/icons/fugue/layer-shape-line.png
diff --git a/src/Greenshot/icons/fugue/layer-shape-text.png b/Greenshot/icons/fugue/layer-shape-text.png
similarity index 100%
rename from src/Greenshot/icons/fugue/layer-shape-text.png
rename to Greenshot/icons/fugue/layer-shape-text.png
diff --git a/src/Greenshot/icons/fugue/layer-shape.png b/Greenshot/icons/fugue/layer-shape.png
similarity index 100%
rename from src/Greenshot/icons/fugue/layer-shape.png
rename to Greenshot/icons/fugue/layer-shape.png
diff --git a/src/Greenshot/icons/fugue/magnifier.png b/Greenshot/icons/fugue/magnifier.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier.png
rename to Greenshot/icons/fugue/magnifier.png
diff --git a/src/Greenshot/icons/fugue/mail-open-image.png b/Greenshot/icons/fugue/mail-open-image.png
similarity index 100%
rename from src/Greenshot/icons/fugue/mail-open-image.png
rename to Greenshot/icons/fugue/mail-open-image.png
diff --git a/src/Greenshot/icons/fugue/minus-circle.png b/Greenshot/icons/fugue/minus-circle.png
similarity index 100%
rename from src/Greenshot/icons/fugue/minus-circle.png
rename to Greenshot/icons/fugue/minus-circle.png
diff --git a/src/Greenshot/icons/fugue/money-coin.png b/Greenshot/icons/fugue/money-coin.png
similarity index 100%
rename from src/Greenshot/icons/fugue/money-coin.png
rename to Greenshot/icons/fugue/money-coin.png
diff --git a/src/Greenshot/icons/fugue/paint-can-color-bg.png b/Greenshot/icons/fugue/paint-can-color-bg.png
similarity index 100%
rename from src/Greenshot/icons/fugue/paint-can-color-bg.png
rename to Greenshot/icons/fugue/paint-can-color-bg.png
diff --git a/src/Greenshot/icons/fugue/paint-can-color.png b/Greenshot/icons/fugue/paint-can-color.png
similarity index 100%
rename from src/Greenshot/icons/fugue/paint-can-color.png
rename to Greenshot/icons/fugue/paint-can-color.png
diff --git a/src/Greenshot/icons/fugue/pencil-color-bg.png b/Greenshot/icons/fugue/pencil-color-bg.png
similarity index 100%
rename from src/Greenshot/icons/fugue/pencil-color-bg.png
rename to Greenshot/icons/fugue/pencil-color-bg.png
diff --git a/src/Greenshot/icons/fugue/pencil-color.png b/Greenshot/icons/fugue/pencil-color.png
similarity index 100%
rename from src/Greenshot/icons/fugue/pencil-color.png
rename to Greenshot/icons/fugue/pencil-color.png
diff --git a/src/Greenshot/icons/fugue/printer.png b/Greenshot/icons/fugue/printer.png
similarity index 100%
rename from src/Greenshot/icons/fugue/printer.png
rename to Greenshot/icons/fugue/printer.png
diff --git a/src/Greenshot/icons/fugue/question.png b/Greenshot/icons/fugue/question.png
similarity index 100%
rename from src/Greenshot/icons/fugue/question.png
rename to Greenshot/icons/fugue/question.png
diff --git a/src/Greenshot/icons/fugue/ruler-crop.png b/Greenshot/icons/fugue/ruler-crop.png
similarity index 100%
rename from src/Greenshot/icons/fugue/ruler-crop.png
rename to Greenshot/icons/fugue/ruler-crop.png
diff --git a/src/Greenshot/icons/fugue/scissors.png b/Greenshot/icons/fugue/scissors.png
similarity index 100%
rename from src/Greenshot/icons/fugue/scissors.png
rename to Greenshot/icons/fugue/scissors.png
diff --git a/src/Greenshot/icons/fugue/slash.png b/Greenshot/icons/fugue/slash.png
similarity index 100%
rename from src/Greenshot/icons/fugue/slash.png
rename to Greenshot/icons/fugue/slash.png
diff --git a/src/Greenshot/icons/fugue/tick.png b/Greenshot/icons/fugue/tick.png
similarity index 100%
rename from src/Greenshot/icons/fugue/tick.png
rename to Greenshot/icons/fugue/tick.png
diff --git a/src/Greenshot/icons/heart.png b/Greenshot/icons/heart.png
similarity index 100%
rename from src/Greenshot/icons/heart.png
rename to Greenshot/icons/heart.png
diff --git a/src/Greenshot/icons/help.png b/Greenshot/icons/help.png
similarity index 100%
rename from src/Greenshot/icons/help.png
rename to Greenshot/icons/help.png
diff --git a/src/Greenshot/icons/highlighter.png b/Greenshot/icons/highlighter.png
similarity index 100%
rename from src/Greenshot/icons/highlighter.png
rename to Greenshot/icons/highlighter.png
diff --git a/src/Greenshot/icons/layer-rotate-left.png b/Greenshot/icons/layer-rotate-left.png
similarity index 100%
rename from src/Greenshot/icons/layer-rotate-left.png
rename to Greenshot/icons/layer-rotate-left.png
diff --git a/src/Greenshot/icons/layer-rotate.png b/Greenshot/icons/layer-rotate.png
similarity index 100%
rename from src/Greenshot/icons/layer-rotate.png
rename to Greenshot/icons/layer-rotate.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-01.png b/Greenshot/icons/notification-counter-01.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-01.png
rename to Greenshot/icons/notification-counter-01.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-02.png b/Greenshot/icons/notification-counter-02.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-02.png
rename to Greenshot/icons/notification-counter-02.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-03.png b/Greenshot/icons/notification-counter-03.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-03.png
rename to Greenshot/icons/notification-counter-03.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-04.png b/Greenshot/icons/notification-counter-04.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-04.png
rename to Greenshot/icons/notification-counter-04.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-05.png b/Greenshot/icons/notification-counter-05.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-05.png
rename to Greenshot/icons/notification-counter-05.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-06.png b/Greenshot/icons/notification-counter-06.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-06.png
rename to Greenshot/icons/notification-counter-06.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-07.png b/Greenshot/icons/notification-counter-07.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-07.png
rename to Greenshot/icons/notification-counter-07.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-08.png b/Greenshot/icons/notification-counter-08.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-08.png
rename to Greenshot/icons/notification-counter-08.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-09.png b/Greenshot/icons/notification-counter-09.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-09.png
rename to Greenshot/icons/notification-counter-09.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-10.png b/Greenshot/icons/notification-counter-10.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-10.png
rename to Greenshot/icons/notification-counter-10.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-11.png b/Greenshot/icons/notification-counter-11.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-11.png
rename to Greenshot/icons/notification-counter-11.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-12.png b/Greenshot/icons/notification-counter-12.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-12.png
rename to Greenshot/icons/notification-counter-12.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-13.png b/Greenshot/icons/notification-counter-13.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-13.png
rename to Greenshot/icons/notification-counter-13.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-14.png b/Greenshot/icons/notification-counter-14.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-14.png
rename to Greenshot/icons/notification-counter-14.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-15.png b/Greenshot/icons/notification-counter-15.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-15.png
rename to Greenshot/icons/notification-counter-15.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-16.png b/Greenshot/icons/notification-counter-16.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-16.png
rename to Greenshot/icons/notification-counter-16.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-17.png b/Greenshot/icons/notification-counter-17.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-17.png
rename to Greenshot/icons/notification-counter-17.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-18.png b/Greenshot/icons/notification-counter-18.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-18.png
rename to Greenshot/icons/notification-counter-18.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-19.png b/Greenshot/icons/notification-counter-19.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-19.png
rename to Greenshot/icons/notification-counter-19.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-20-plus.png b/Greenshot/icons/notification-counter-20-plus.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-20-plus.png
rename to Greenshot/icons/notification-counter-20-plus.png
diff --git a/src/Greenshot.Editor/icons/notification-counter-20.png b/Greenshot/icons/notification-counter-20.png
similarity index 100%
rename from src/Greenshot.Editor/icons/notification-counter-20.png
rename to Greenshot/icons/notification-counter-20.png
diff --git a/src/Greenshot/icons/page_copy.png b/Greenshot/icons/page_copy.png
similarity index 100%
rename from src/Greenshot/icons/page_copy.png
rename to Greenshot/icons/page_copy.png
diff --git a/src/Greenshot/icons/palette.png b/Greenshot/icons/palette.png
similarity index 100%
rename from src/Greenshot/icons/palette.png
rename to Greenshot/icons/palette.png
diff --git a/src/Greenshot/icons/picture_save.png b/Greenshot/icons/picture_save.png
similarity index 100%
rename from src/Greenshot/icons/picture_save.png
rename to Greenshot/icons/picture_save.png
diff --git a/src/Greenshot/icons/picture_saveas.png b/Greenshot/icons/picture_saveas.png
similarity index 100%
rename from src/Greenshot/icons/picture_saveas.png
rename to Greenshot/icons/picture_saveas.png
diff --git a/src/Greenshot/icons/picture_to_clipboard.png b/Greenshot/icons/picture_to_clipboard.png
similarity index 100%
rename from src/Greenshot/icons/picture_to_clipboard.png
rename to Greenshot/icons/picture_to_clipboard.png
diff --git a/src/Greenshot/icons/pipette.png b/Greenshot/icons/pipette.png
similarity index 100%
rename from src/Greenshot/icons/pipette.png
rename to Greenshot/icons/pipette.png
diff --git a/src/Greenshot/icons/printer.png b/Greenshot/icons/printer.png
similarity index 100%
rename from src/Greenshot/icons/printer.png
rename to Greenshot/icons/printer.png
diff --git a/src/Greenshot/icons/propertyitemcontainer.gif b/Greenshot/icons/propertyitemcontainer.gif
similarity index 100%
rename from src/Greenshot/icons/propertyitemcontainer.gif
rename to Greenshot/icons/propertyitemcontainer.gif
diff --git a/src/Greenshot/icons/redo.png b/Greenshot/icons/redo.png
similarity index 100%
rename from src/Greenshot/icons/redo.png
rename to Greenshot/icons/redo.png
diff --git a/src/Greenshot.Editor/icons/resize.png b/Greenshot/icons/resize.png
similarity index 100%
rename from src/Greenshot.Editor/icons/resize.png
rename to Greenshot/icons/resize.png
diff --git a/src/Greenshot/icons/ruler-crop.png b/Greenshot/icons/ruler-crop.png
similarity index 100%
rename from src/Greenshot/icons/ruler-crop.png
rename to Greenshot/icons/ruler-crop.png
diff --git a/src/Greenshot/icons/shadow.png b/Greenshot/icons/shadow.png
similarity index 100%
rename from src/Greenshot/icons/shadow.png
rename to Greenshot/icons/shadow.png
diff --git a/src/Greenshot/icons/shape_arrow_add.png b/Greenshot/icons/shape_arrow_add.png
similarity index 100%
rename from src/Greenshot/icons/shape_arrow_add.png
rename to Greenshot/icons/shape_arrow_add.png
diff --git a/src/Greenshot/icons/shape_arrowheads.png b/Greenshot/icons/shape_arrowheads.png
similarity index 100%
rename from src/Greenshot/icons/shape_arrowheads.png
rename to Greenshot/icons/shape_arrowheads.png
diff --git a/src/Greenshot/icons/shape_copy.png b/Greenshot/icons/shape_copy.png
similarity index 100%
rename from src/Greenshot/icons/shape_copy.png
rename to Greenshot/icons/shape_copy.png
diff --git a/src/Greenshot/icons/shape_ellipse_add.png b/Greenshot/icons/shape_ellipse_add.png
similarity index 100%
rename from src/Greenshot/icons/shape_ellipse_add.png
rename to Greenshot/icons/shape_ellipse_add.png
diff --git a/src/Greenshot/icons/shape_ellipse_delete.png b/Greenshot/icons/shape_ellipse_delete.png
similarity index 100%
rename from src/Greenshot/icons/shape_ellipse_delete.png
rename to Greenshot/icons/shape_ellipse_delete.png
diff --git a/src/Greenshot/icons/shape_line.png b/Greenshot/icons/shape_line.png
similarity index 100%
rename from src/Greenshot/icons/shape_line.png
rename to Greenshot/icons/shape_line.png
diff --git a/src/Greenshot/icons/shape_paste.png b/Greenshot/icons/shape_paste.png
similarity index 100%
rename from src/Greenshot/icons/shape_paste.png
rename to Greenshot/icons/shape_paste.png
diff --git a/src/Greenshot/icons/shape_square_add.png b/Greenshot/icons/shape_square_add.png
similarity index 100%
rename from src/Greenshot/icons/shape_square_add.png
rename to Greenshot/icons/shape_square_add.png
diff --git a/src/Greenshot/icons/shape_square_bordercolor.png b/Greenshot/icons/shape_square_bordercolor.png
similarity index 100%
rename from src/Greenshot/icons/shape_square_bordercolor.png
rename to Greenshot/icons/shape_square_bordercolor.png
diff --git a/src/Greenshot/icons/shape_square_delete.png b/Greenshot/icons/shape_square_delete.png
similarity index 100%
rename from src/Greenshot/icons/shape_square_delete.png
rename to Greenshot/icons/shape_square_delete.png
diff --git a/src/Greenshot/icons/shape_square_fillcolor.png b/Greenshot/icons/shape_square_fillcolor.png
similarity index 100%
rename from src/Greenshot/icons/shape_square_fillcolor.png
rename to Greenshot/icons/shape_square_fillcolor.png
diff --git a/src/Greenshot/icons/text_bold.png b/Greenshot/icons/text_bold.png
similarity index 100%
rename from src/Greenshot/icons/text_bold.png
rename to Greenshot/icons/text_bold.png
diff --git a/src/Greenshot/icons/text_dropcaps.png b/Greenshot/icons/text_dropcaps.png
similarity index 100%
rename from src/Greenshot/icons/text_dropcaps.png
rename to Greenshot/icons/text_dropcaps.png
diff --git a/src/Greenshot/icons/text_italic.png b/Greenshot/icons/text_italic.png
similarity index 100%
rename from src/Greenshot/icons/text_italic.png
rename to Greenshot/icons/text_italic.png
diff --git a/src/Greenshot/icons/text_underline.png b/Greenshot/icons/text_underline.png
similarity index 100%
rename from src/Greenshot/icons/text_underline.png
rename to Greenshot/icons/text_underline.png
diff --git a/src/Greenshot/icons/textfield_delete.png b/Greenshot/icons/textfield_delete.png
similarity index 100%
rename from src/Greenshot/icons/textfield_delete.png
rename to Greenshot/icons/textfield_delete.png
diff --git a/src/Greenshot/icons/undo.png b/Greenshot/icons/undo.png
similarity index 100%
rename from src/Greenshot/icons/undo.png
rename to Greenshot/icons/undo.png
diff --git a/src/Greenshot/icons/wand-hat.png b/Greenshot/icons/wand-hat.png
similarity index 100%
rename from src/Greenshot/icons/wand-hat.png
rename to Greenshot/icons/wand-hat.png
diff --git a/src/Greenshot/icons/wrench.png b/Greenshot/icons/wrench.png
similarity index 100%
rename from src/Greenshot/icons/wrench.png
rename to Greenshot/icons/wrench.png
diff --git a/src/Greenshot/icons/wrench_orange.png b/Greenshot/icons/wrench_orange.png
similarity index 100%
rename from src/Greenshot/icons/wrench_orange.png
rename to Greenshot/icons/wrench_orange.png
diff --git a/src/Greenshot/icons/zoom.png b/Greenshot/icons/zoom.png
similarity index 100%
rename from src/Greenshot/icons/zoom.png
rename to Greenshot/icons/zoom.png
diff --git a/src/Greenshot/log4net-debug.xml b/Greenshot/log4net-debug.xml
similarity index 86%
rename from src/Greenshot/log4net-debug.xml
rename to Greenshot/log4net-debug.xml
index 2ccf81918..554edbeb3 100644
--- a/src/Greenshot/log4net-debug.xml
+++ b/Greenshot/log4net-debug.xml
@@ -1,12 +1,12 @@
-
+
-
+
diff --git a/src/Greenshot/log4net-portable.xml b/Greenshot/log4net-portable.xml
similarity index 100%
rename from src/Greenshot/log4net-portable.xml
rename to Greenshot/log4net-portable.xml
diff --git a/src/Greenshot/log4net-zip.xml b/Greenshot/log4net-zip.xml
similarity index 100%
rename from src/Greenshot/log4net-zip.xml
rename to Greenshot/log4net-zip.xml
diff --git a/src/Greenshot/log4net.xml b/Greenshot/log4net.xml
similarity index 81%
rename from src/Greenshot/log4net.xml
rename to Greenshot/log4net.xml
index 17f1beb4f..364756dbf 100644
--- a/src/Greenshot/log4net.xml
+++ b/Greenshot/log4net.xml
@@ -1,12 +1,12 @@
-
+
-
+
diff --git a/Greenshot/packages.config b/Greenshot/packages.config
new file mode 100644
index 000000000..12343fb16
--- /dev/null
+++ b/Greenshot/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/installer/additional_files/installer.txt b/Greenshot/releases/additional_files/installer.txt
similarity index 100%
rename from installer/additional_files/installer.txt
rename to Greenshot/releases/additional_files/installer.txt
diff --git a/installer/additional_files/license.txt b/Greenshot/releases/additional_files/license.txt
similarity index 100%
rename from installer/additional_files/license.txt
rename to Greenshot/releases/additional_files/license.txt
diff --git a/installer/additional_files/readme.txt b/Greenshot/releases/additional_files/readme.txt.template
similarity index 74%
rename from installer/additional_files/readme.txt
rename to Greenshot/releases/additional_files/readme.txt.template
index bdb64e2c4..af435f2b2 100644
--- a/installer/additional_files/readme.txt
+++ b/Greenshot/releases/additional_files/readme.txt.template
@@ -7,120 +7,7 @@ CHANGE LOG:
All details to our tickets can be found here: https://greenshot.atlassian.net
-# Greenshot 1.3.xxx
-
-Bugs fixed:
-* greenshot.ini: Exclude Plugins and Include Plugins setting broken [#648](https://github.com/greenshot/greenshot/issues/648) [#642](https://github.com/greenshot/greenshot/issues/642) thanks to @Christian-Schulz for providing the fix
-
-Features added:
-
-# Greenshot 1.3.296
-
-Bugs fixed
-* Fix Administrative installation via user interface [#546](https://github.com/greenshot/greenshot/issues/546) [#611](https://github.com/greenshot/greenshot/issues/611) [#598](https://github.com/greenshot/greenshot/issues/598)
-
-Features added:
-* Installer: Allow Choice between All-Users (Administrative) and Current-User Installation [#625](https://github.com/greenshot/greenshot/pull/625)
-
-# Greenshot 1.3.292
-
-Bugs fixed:
-* Fix Administrative installation via command line using /ALLUSERS [#601](https://github.com/greenshot/greenshot/issues/601) [#619](https://github.com/greenshot/greenshot/issues/619)
-
-# Greenshot 1.3.290
-
-Note: the version information for the first 1.3 release is outdated/incomplete. Due to the long timespan and large amount of changes between 1.2 and 1.3 we lost track. Sorry.
-
-Greenshot 1.3 is the first Greenshot which targets .NET 4.7.2 which just by doing to solves some general issues in the area of Internet Explorer capturing, TLS communication and some other minor issues.
-
-We've also added some new Windows 10 functions, like notifications, OCR and sharing with Windows 10 apps.
-
-## Supported platforms:
-As always Greenshot comes "as-is" with no guarantee whatsoever, we are not paid enough to make this possible.
-Due to the amount of work involved in testing Greenshot on different platforms, and needing hardware to do so, we cannot support all of them. What does this mean?
-
-* Windows 10 "current" - We develop & test Greenshot on the latest available version of Windows 10, which means you can pretty much assume it works on there and if not we can work on it.
-* Windows 10 "previous" - We don't have the hardware to have all supported Windows versions side-by-side, we try to keep the compatibility high. If there are very Windows specific bugs, we can look at it. In general we add new Windows features with a check for the version, preventing issues with older versions.
-* Windows 10 insiders - If someone is on an insider, and wants to use Greenshot, there is no guarantee. But please do report issues, and make sure you mention the build you are on. As insiders are the next "current", we will try to look at this.
-* Windows 7 - this is no longer supported by Microsoft, and we will not buy extended support licenses for older Windows, we rather motivate people to upgrade to a normal supported version. It should still work on Windows 7, but we can't guarantee this and functionality will be degraded compared to that on Windows 10.
-* Windows 8 - Greenshot 1.2 mostly worked on it, thus we assume 1.3 will do so too, but we cannot support this.
-* Windows Server version XYZ- We do not have the hardware nor licenses to test on this, do so at your own risk. You can report issues, but we cannot support specific Windows Server issues, unless someone wants to pay for the time, hardware & licenses.
-* Linux via Wine or CrossOver - Although we made some small changes to Greenshot to get basics working, it's not supported and to be honest it's a lot of work to get it running, and the result is very disappointed.
-* MacOS - We have a version of Greenshot for MacOS in the appstore [here](https://apps.apple.com/us/app/greenshot/id1103915944).
-
-## Support for other software?
-We have many request, mainly from companies in form of "we use an eMail client from this company, and have a tool which does this cool thing, can you support this?" This depends, if it's something which benefits the masses, we can look at it. An example is PowerToys, where we [interact with the maintainers](https://github.com/microsoft/PowerToys/wiki/Application-Compatibility) to see how we can make Greenshot work together and not have PowerToys break us. We can't support all, and we cannot buy licenses & install every product.
-
-## Let us see the changes:
-
-### New features
-* The editor now has a zoom, completely build by our awesome community member @KillyMXI PR #201
-* Windows 10 has out of the box OCR support, this can now be used from Greenshot. We added functionality which is on par with that we provided via an old Microsoft component called "MODI". To reduce our maintenance, we removed the old functionality. This is the first step with Windows 10 OCR, we have some great plans with this.
-* Greenshot can now use the Windows 10 app sharing, share screenshots with app which support bitmaps.
-* Greenshot now can use the Windows 10 notifications system, which looks better. We will add more user friendly functionality for this later.
-* [FEATURE-1110](https://greenshot.atlassian.net/browse/FEATURE-1110): Making it possible to use a hotkey to open the clipboard, for details look at the issue.
-
-### General improvements:
-* Improved the about and error details with better version information, and OS name.
-* Upgraded the .NET Framework dependency to 4.7.2, any lower version would cause a lot of additional work and make the installer even bigger.
-* Used more recent versions of software components, which make it easier to find bugs.
-* DPI improvements, so people can use Greenshot with high DPI screens.
-* Made the selection boxes (grippers) bigger and reize with the DPI settings
-* Update check should have less impact with us and for the user
-* Added Italian to the installer, a lof of PR's from @bovirus e.g. PR #224, #230
-* Added support to generate random characters in the filename PR #216
-* Changed the cloud services Box, DropBox and Imgur to use the default browser in combination with getgreenshot.org instead of the embedded, solving incompatibility issues.
-
-### Bug fixes
-
-#### Functionality fixes:
-* [BUG-2693](https://greenshot.atlassian.net/browse/BUG-2693), [BUG-2693](https://greenshot.atlassian.net/browse/BUG-2693), [BUG-2743](https://greenshot.atlassian.net/browse/BUG-2743): Greenshot doesn't recoginize a MAPI client
-* [BUG-2535](https://greenshot.atlassian.net/browse/BUG-2535): Greenshot selects invisible windows fix was suggested by Raymond Chen [here](https://devblogs.microsoft.com/oldnewthing/20200302-00/?p=103507)
-* [BUG-2544](https://greenshot.atlassian.net/browse/BUG-2544): Enabled TLS1.1 & 1.2 to fix jira connectivity and do not use the JIRA session support as this was deprecated.
-* [BUG-2529](https://greenshot.atlassian.net/browse/BUG-2529): This should most likely fix the excessive update checks.
-* [BUG-1919](https://greenshot.atlassian.net/browse/BUG-1919): Screenshot works once on Internet Explorer
-* [BUG-1943](https://greenshot.atlassian.net/browse/BUG-1943): Picassa no longer supported by Google - Picassa plugin update to Google Photos
-* [BUG-2127](https://greenshot.atlassian.net/browse/BUG-2127): Incorrect link image to picasa
-* [BUG-2170](https://greenshot.atlassian.net/browse/BUG-2170): Editor buttons are too small on high-resolution PC
-* [BUG-2300](https://greenshot.atlassian.net/browse/BUG-2300): User need to do a lot of CTRL + Z to undo the ellipse/rectangle modification
-* [BUG-2736](https://greenshot.atlassian.net/browse/BUG-2736): Cropping a capture where a speech bubble is shown doesn't move the bubble tail
-* PR #157 -- Fixing textbox issue with polish letter "ą"
-* Bug #124, some minor issues with the EmailDestination
-* Bug #149: If using a full screen capture of the current monitor, not the default, the mouse cursor is not visible.
-* Bug #279 External commands where duplicated in the editor and dynamic destination picker
-* Bug #283 Fixed an issue with drawing Unicode icons in the editor
-
-#### Stability fixes:
-* [BUG-2644](https://greenshot.atlassian.net/browse/BUG-2644): Fixed a NPRE when exporting to Powerpoint when it's not running yet.
-* [BUG-2542](https://greenshot.atlassian.net/browse/BUG-2542): Fix for shutdown issue (ImgurPlugin)
-* [BUG-2249](https://greenshot.atlassian.net/browse/BUG-2249): Error after switching between colors
-* [BUG-2303](https://greenshot.atlassian.net/browse/BUG-2303): Greenshot 1.2.10 Build 6 (64 bit) - Dotnet 4.0 framework crash.
-* [BUG-2307](https://greenshot.atlassian.net/browse/BUG-2307): Using the pencil tool, changing colors, undo, pencil tool again, produces error dump.
-* [BUG-2309](https://greenshot.atlassian.net/browse/BUG-2309): Exception while editing screen shot
-* [BUG-2403](https://greenshot.atlassian.net/browse/BUG-2403): error message came up immediately after a restart of Windows.
-* [BUG-2435](https://greenshot.atlassian.net/browse/BUG-2435): Crash
-* [BUG-2463](https://greenshot.atlassian.net/browse/BUG-2463): Crash on moving freehand drawing
-* [BUG-2484](https://greenshot.atlassian.net/browse/BUG-2484): Unexpected error pop-up after DRIVER VERIFIER IOMANAGER VIOLATION Blue Screen of Death
-* [BUG-2486](https://greenshot.atlassian.net/browse/BUG-2486): program window goes white with red x through it
-* [BUG-2552](https://greenshot.atlassian.net/browse/BUG-2552): Crashed when drawing new colored line after a ctrl+z undo.
-* [BUG-2557](https://greenshot.atlassian.net/browse/BUG-2557): sudden shut down due to error , Error
-* [BUG-2567](https://greenshot.atlassian.net/browse/BUG-2567): Automatic error, tells me to report a bug
-* [BUG-2577](https://greenshot.atlassian.net/browse/BUG-2577): Erreur inattendue
-* [BUG-2592](https://greenshot.atlassian.net/browse/BUG-2592): Crash when copying to clipboard
-* [BUG-2615](https://greenshot.atlassian.net/browse/BUG-2615): Greenshot crashed while changing line color
-* [BUG-2642](https://greenshot.atlassian.net/browse/BUG-2642): Greenshot Image Editor crashed when I clicked "undo"
-* [BUG-2654](https://greenshot.atlassian.net/browse/BUG-2654): GS crashing when logging off from a Windows account right after logging-on
-* [BUG-2669](https://greenshot.atlassian.net/browse/BUG-2669): Exception on startup of Greenshot
-* [BUG-2684](https://greenshot.atlassian.net/browse/BUG-2684): Freehand tool causes crash after color change & undo
-* [BUG-2698](https://greenshot.atlassian.net/browse/BUG-2698): Imgur: Object reference not set to an instance of an object.
-* [BUG-2699](https://greenshot.atlassian.net/browse/BUG-2699): Crash on deleting a line path
-* [BUG-2700](https://greenshot.atlassian.net/browse/BUG-2700): Imgur: Continued Error
-* [BUG-2703](https://greenshot.atlassian.net/browse/BUG-2703): Crash dump: "Message: The notification platform is unavailable."
-* [BUG-2707](https://greenshot.atlassian.net/browse/BUG-2707): Moving or editing object (usually cursor object) occasionally crashes Greenshot
-* #246,[BUG-2448](https://greenshot.atlassian.net/browse/BUG-2448), [BUG-2593](https://greenshot.atlassian.net/browse/BUG-2593), [BUG-2427](https://greenshot.atlassian.net/browse/BUG-2427), [BUG-2444](https://greenshot.atlassian.net/browse/BUG-2444), [BUG-2272](https://greenshot.atlassian.net/browse/BUG-2272): Inconsistent scale behavior when scaling objects with shift modifier
-
-
-Greenshot 1.2.10 RELEASE
+@DETAILVERSION@
Bugs fixed:
* [BUG-2235] - Imgur authentication issues due to imgur api change
@@ -668,5 +555,3 @@ Features added:
* when clicking two overlapping elements, the one created later gets selected [ 1725175 ]
* created textboxes can now be edited with a doubleclick [ 1704408 ]
* selected font is now stored in the application config file [ 1704411 ]
-
-
diff --git a/installer/appinfo.ini.template b/Greenshot/releases/appinfo.ini.template
similarity index 100%
rename from installer/appinfo.ini.template
rename to Greenshot/releases/appinfo.ini.template
diff --git a/installer/innosetup/IssProc/IssProc.dll b/Greenshot/releases/innosetup/IssProc/IssProc.dll
similarity index 100%
rename from installer/innosetup/IssProc/IssProc.dll
rename to Greenshot/releases/innosetup/IssProc/IssProc.dll
diff --git a/installer/innosetup/IssProc/IssProcLanguage.ini b/Greenshot/releases/innosetup/IssProc/IssProcLanguage.ini
similarity index 100%
rename from installer/innosetup/IssProc/IssProcLanguage.ini
rename to Greenshot/releases/innosetup/IssProc/IssProcLanguage.ini
diff --git a/Greenshot/releases/innosetup/Languages/ChineseSimplified.isl b/Greenshot/releases/innosetup/Languages/ChineseSimplified.isl
new file mode 100644
index 000000000..9cf26394d
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/ChineseSimplified.isl
@@ -0,0 +1,336 @@
+; *** Inno Setup version 5.5.0+ Chinese (Simplified) messages ***
+; by Mack Zhang (hua_wuxin@21cn.com)
+;
+; To download user-contributed translations of this file, go to:
+; http://www.jrsoftware.org/files/istrans/
+;
+; Note: When translating this text, do not add periods (.) to the end of
+; messages that didn't have them already, because on those messages Inno
+; Setup adds the periods automatically (appending a period would result in
+; two periods being displayed).
+
+[LangOptions]
+; The following three entries are very important. Be sure to read and
+; understand the '[LangOptions] section' topic in the help file.
+LanguageName=<4E2D><6587><7B80><4F53>
+LanguageID=$0804
+LanguageCodePage=936
+; If the language you are translating to requires special font faces or
+; sizes, uncomment any of the following entries and change them accordingly.
+DialogFontName=
+DialogFontSize=9
+;WelcomeFontName=Verdana
+;WelcomeFontSize=12
+;TitleFontName=Arial
+;TitleFontSize=29
+;CopyrightFontName=Arial
+;CopyrightFontSize=8
+
+[Messages]
+
+; *** Application titles
+SetupAppTitle=װ
+SetupWindowTitle=װ - %1
+UninstallAppTitle=ж
+UninstallAppFullTitle=%1 ж
+
+; *** Misc. common
+InformationTitle=Ϣ
+ConfirmTitle=ȷ
+ErrorTitle=
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=װĵϰװ %1ȷҪ
+LdrCannotCreateTemp=ʱļװֹ
+LdrCannotExecTemp=ʱļеļװֹ
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%n %2%3
+SetupFileMissing=װļȱļ %1ȡ°汾
+SetupFileCorrupt=װļȡ°汾
+SetupFileCorruptOrWrongVer=װļ뱾װİ汾ݡȡ°汾
+InvalidParameter=һIJݵУ%n%n%1
+SetupAlreadyRunning=װѾС
+WindowsVersionNotSupported=֧ĵе Windows 汾
+WindowsServicePackRequired=Ҫ %1 Service Pack %2 µİ汾
+NotOnThisPlatform= %1 С
+OnlyOnThisPlatform= %1 С
+OnlyOnTheseArchitectures=ֻܰװΪдܹƵ Windows 汾У%n%n%1
+MissingWOW64APIs=ǰ Windows 汾ûаִ 64 λװĺҪ⣬밲װ Service Pack %1
+WinVersionTooLowError=Ҫ %1 v%2 ߰汾
+WinVersionTooHighError=ܰװ %1 v%2 ߰汾ϡ
+AdminPrivilegesRequired=װʱԹԱݵ¼
+PowerUserPrivilegesRequired=װʱԹԱ Power Users Աݵ¼
+SetupAppRunningError=װ %1 С%n%nرʵȻȷȡ˳
+UninstallAppRunningError=ж %1 С%n%nرʵȻȷȡ˳
+
+; *** Misc. errors
+ErrorCreatingDir=װļС%1
+ErrorTooManyFilesInDir=ļС%1дļΪ̫ļ
+
+; *** Setup common messages
+ExitSetupTitle=˳װ
+ExitSetupMessage=װδɡ˳ᰲװ%n%nʱаװɰװ%n%n˳װ
+AboutSetupMenuItem=ڰװ(&A)
+AboutSetupTitle=ڰװ
+AboutSetupMessage=%1 汾 %2%n%3%n%n%1 ҳ%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< һ(&B)
+ButtonNext=һ(&N) >
+ButtonInstall=װ(&I)
+ButtonOK=ȷ
+ButtonCancel=ȡ
+ButtonYes=(&Y)
+ButtonYesToAll=ȫ(&A)
+ButtonNo=(&N)
+ButtonNoToAll=ȫ(&O)
+ButtonFinish=(&F)
+ButtonBrowse=(&B)
+ButtonWizardBrowse=(&R)
+ButtonNewFolder=ļ(&M)
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=ѡװ
+SelectLanguageLabel=ѡװڼҪʹõԣ
+
+; *** Common wizard text
+ClickNext=һȡ˳װ
+BeveledLabel=
+BrowseDialogTitle=ļ
+BrowseDialogLabel=ѡһļУȻȷ
+NewFolderName=½ļ
+
+; *** "Welcome" wizard page
+WelcomeLabel1=ӭʹ [name] װ
+WelcomeLabel2=װĵϰװ [name/ver]%n%nڼ֮ǰرӦó
+
+; *** "Password" wizard page
+WizardPassword=
+PasswordLabel1=װ뱣
+PasswordLabel3=룬ȻһһִСд
+PasswordEditLabel=(&P)
+IncorrectPassword=벻ȷԡ
+
+; *** "License Agreement" wizard page
+WizardLicense=Э
+LicenseLabel=ڼ֮ǰĶҪϢ
+LicenseLabel3=ĶЭ顣ڼװ֮ǰܴЭ
+LicenseAccepted=ҽЭ(&A)
+LicenseNotAccepted=ҲЭ(&D)
+
+; *** "Information" wizard pages
+WizardInfoBefore=Ϣ
+InfoBeforeLabel=ڼ֮ǰĶҪϢ
+InfoBeforeClickLabel=üװ뵥һ
+WizardInfoAfter=Ϣ
+InfoAfterLabel=ڼ֮ǰĶҪϢ
+InfoAfterClickLabel=üװ뵥һ
+
+; *** "User Information" wizard page
+WizardUserInfo=ûϢ
+UserInfoDesc=Ϣ
+UserInfoName=û(&U)
+UserInfoOrg=֯(&O)
+UserInfoSerial=к(&S)
+UserInfoNameRequired=û
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=ѡĿλ
+SelectDirDesc= [name] װ
+SelectDirLabel3=װ [name] װļС
+SelectDirBrowseLabel=ҪһҪѡͬļУ뵥
+DiskSpaceMBLabel=Ҫ [mb] MB Ŀд̿ռ䡣
+CannotInstallToNetworkDrive=װ
+CannotInstallToUNCPath=װ UNC ·
+InvalidPath=̷·磺%n%nC:\APP%n%n UNC ·ʽ%n%n\\server\share
+InvalidDrive=ѡ UNC ڻɷʡѡ
+DiskSpaceWarningTitle=û㹻Ĵ̿ռ
+DiskSpaceWarning=װҪ %1 KB ʣռ䣬ѡֻ %2 KB á%n%nȻҪ
+DirNameTooLong=ļƻ·̫
+InvalidDirName=ļЧ
+BadDirName32=ļƲַܰ%n%n%1
+DirExistsTitle=ļѴ
+DirExists=ļУ%n%n%1%n%nѴڡȷҪװļ
+DirDoesntExistTitle=ļв
+DirDoesntExist=ļУ%n%n%1%n%nڡļ
+
+; *** "Select Components" wizard page
+WizardSelectComponents=ѡ
+SelectComponentsDesc=ҪװЩ
+SelectComponentsLabel2=ѡҪװ㲻밲װúһ
+FullInstallation=װ
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=లװ
+CustomInstallation=ưװ
+NoUninstallWarningTitle=Ѵ
+NoUninstallWarning=װѾװ%n%n%1%n%nȡѡжЩ%n%nװ
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=ǰѡҪ [mb] MB ̿ռ䡣
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=ѡ
+SelectTasksDesc=ҪִЩ
+SelectTasksLabel2=ѡڰװ [name] ڼ䰲װҪִеĸȻһ
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=ѡʼ˵ļ
+SelectStartMenuFolderDesc=ѳݷʽŵ
+SelectStartMenuFolderLabel3=װ¿ʼ˵ļдݷʽ
+SelectStartMenuFolderBrowseLabel=һһҪѡͬļУ
+MustEnterGroupName=ļ
+GroupNameTooLong=ļƻ·̫
+InvalidGroupName=ļЧ
+BadGroupName=ļƲַܰ%n%n%1
+NoProgramGroupCheck2=ʼ˵ļ(&D)
+
+; *** "Ready to Install" wizard page
+WizardReady=װ
+ReadyLabel1=װʼװ [name]
+ReadyLabel2a=װװҪ鿴߸һ
+ReadyLabel2b=װװ
+ReadyMemoUserInfo=ûϢ
+ReadyMemoDir=Ŀλã
+ReadyMemoType=װͣ
+ReadyMemoComponents=ѡ
+ReadyMemoGroup=ʼ˵ļУ
+ReadyMemoTasks=
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=װ
+PreparingDesc=װװ [name]
+PreviousInstallNotCompleted=ǰİװ/жδɡҪɰװ%n%n֮аװ [name] İװ
+CannotContinue=װܼȡ˳
+ApplicationsFound=װҪ±ӦóռõļԶرЩӦó
+ApplicationsFound2=װҪ±ӦóռõļԶرЩӦóװɺװ᳢ЩӦó
+CloseApplications=ԶرӦó(&A)
+DontCloseApplications=ԶرӦó(&D)
+
+; *** "Installing" wizard page
+WizardInstalling=ڰװ
+InstallingLabel=ļаװ [name]Եȡ
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel= [name] װ
+FinishedLabelNoIcons=װ [name] İװ
+FinishedLabel=װ [name] İװͨѡѰװͼӦó
+ClickFinish=ɡ˳װ
+FinishedRestartLabel=Ϊ [name] İװװԡҪ
+FinishedRestartMessage=Ϊ [name] İװװԡ%n%nҪ
+ShowReadmeCheck=ǣҪ鿴ļ
+YesRadio=ǣ(&Y)
+NoRadio=Ժ(&N)
+; used for example as 'Run MyProg.exe'
+RunEntryExec= %1
+; used for example as 'View Readme.txt'
+RunEntryShellExec=鿴 %1
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=װҪһ
+SelectDiskLabel2= %1 ȷ%n%nڳʾļļҲôϵļȷ·
+PathLabel=·(&P)
+FileNotInDir2=ļ%1ڡ%2СȷĴ̻ѡļС
+SelectDirectoryLabel=ָһ̵λá
+
+; *** Installation phase messages
+SetupAborted=װδɡ%n%nⲢаװ
+EntryAbortRetryIgnore=ԡ³ԣԡװֹȡװ
+
+; *** Installation status messages
+StatusClosingApplications=ڹرӦó
+StatusCreateDirs=ڴļС
+StatusExtractFiles=ȡļ
+StatusCreateIcons=ڴݷʽ
+StatusCreateIniEntries=ڴ INI Ŀ
+StatusCreateRegistryEntries=ڴעĿ
+StatusRegisterFiles=עļ
+StatusSavingUninstall=ڱжϢ
+StatusRunProgram=ɰװ
+StatusRestartingApplications=Ӧó
+StatusRollback=ڻعġ
+
+; *** Misc. errors
+ErrorInternal2=ڲ%1
+ErrorFunctionFailedNoCode=%1 ʧ
+ErrorFunctionFailed=%1 ʧܡ %2
+ErrorFunctionFailedWithMessage=%1 ʧܡ %2%n%3
+ErrorExecutingProgram=ִļ%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=עʱ%n%1\%2
+ErrorRegCreateKey=עʱ%n%1\%2
+ErrorRegWriteKey=дעʱ%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=ļ%1д INI Ŀʱ
+
+; *** File copying errors
+FileAbortRetryIgnore=ԡ³ԣԡļƼֹȡװ
+FileAbortRetryIgnore2=ԡ³ԣԡװƼֹȡװ
+SourceIsCorrupted=Դļ
+SourceDoesntExist=Դļ%1
+ExistingFileReadOnly=ļΪֻ%n%nԡƳֻԲԣԡļֹȡװ
+ErrorReadingExistingDest=ȡļʱ
+FileExists=ļѴڡ%n%nҪ
+ExistingFileNewer=ļȰװҪװĻ¡㱣ļ%n%nļ
+ErrorChangingAttr=ļʱ
+ErrorCreatingTemp=Ŀļдļʱ
+ErrorReadingSource=ȡԴļʱ
+ErrorCopying=ļʱ
+ErrorReplacingExistingFile=滻ļʱ
+ErrorRestartReplace=滻ʧܣ
+ErrorRenamingTemp=Ŀļеļʱ
+ErrorRegisterServer=ע DLL/OCX%1
+ErrorRegSvr32Failed=RegSvr32 ʧܡֵ%1
+ErrorRegisterTypeLib=עͿ⣺%1
+
+; *** Post-installation errors
+ErrorOpeningReadme=ļʱ
+ErrorRestartingComputer=װԡֶ
+
+; *** Uninstaller messages
+UninstallNotFound=ļ%1ڡжء
+UninstallOpenError=ļ%1ܴж
+UninstallUnsupportedVer=ж־ļ%1ĸʽܱ˰汾жʶ𡣲ж
+UninstallUnknownEntry=ж־һδ֪Ŀ (%1)
+ConfirmUninstall=ǷȷҪȫɾ %1
+UninstallOnlyOnWin64=˰װֻ 64 λ Windows жء
+OnlyAdminCanUninstall=˰װֻɾ߱ԱȨûжء
+UninstallStatusLabel=ɾ %1Եȡ
+UninstalledAll=%1 ѳɹɾ
+UninstalledMost=%1 жɡ%n%nijЩĿɾֶɾ
+UninstalledAndNeedsRestart=Ҫ %1 жأԡ%n%nҪ
+UninstallDataCorrupted=ļ%1ж
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=ɾļ
+ConfirmDeleteSharedFile2=йļٱκγʹáҪɾùļ%n%nгʹøļѱɾЩС㲻ȷѡ¸ļϵͳκΣ
+SharedFileNameLabel=ļ
+SharedFileLocationLabel=λã
+WizardUninstalling=ж״̬
+StatusUninstalling=ж %1
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=ڰװ %1
+ShutdownBlockReasonUninstallingApp=ж %1
+
+; The custom messages below aren't used by Setup itself, but if you make
+; use of them in your scripts, you'll want to translate them.
+
+[CustomMessages]
+
+NameAndVersion=%1 汾 %2
+AdditionalIcons=ͼ꣺
+CreateDesktopIcon=ͼ(&D)
+CreateQuickLaunchIcon=ͼ(&Q)
+ProgramOnTheWeb=%1 վ
+UninstallProgram=ж %1
+LaunchProgram= %1
+AssocFileExtension= %1 %2 ļչ(&A)
+AssocingFileExtension=ڽ %1 %2 ļչ
+AutoStartProgramGroupDescription=
+AutoStartProgram=Զ %1
+AddonHostProgramNotFound=ѡļҲ %1%n%nǷȻ
diff --git a/installer/innosetup/Languages/Latvian.isl b/Greenshot/releases/innosetup/Languages/Latvian.isl
similarity index 100%
rename from installer/innosetup/Languages/Latvian.isl
rename to Greenshot/releases/innosetup/Languages/Latvian.isl
diff --git a/installer/innosetup/Languages/NorwegianNynorsk.isl b/Greenshot/releases/innosetup/Languages/NorwegianNynorsk.isl
similarity index 100%
rename from installer/innosetup/Languages/NorwegianNynorsk.isl
rename to Greenshot/releases/innosetup/Languages/NorwegianNynorsk.isl
diff --git a/installer/innosetup/Languages/Swedish.isl b/Greenshot/releases/innosetup/Languages/Swedish.isl
similarity index 81%
rename from installer/innosetup/Languages/Swedish.isl
rename to Greenshot/releases/innosetup/Languages/Swedish.isl
index f458ca651..6a942b267 100644
--- a/installer/innosetup/Languages/Swedish.isl
+++ b/Greenshot/releases/innosetup/Languages/Swedish.isl
@@ -1,526 +1,339 @@
-; *** Inno Setup version 6.1.0+ Swedish messages ***
-;
-; To download user-contributed translations of this file, go to:
-; http://www.jrsoftware.org/files/istrans/
-;
-; Note: When translating this text, do not add periods (.) to the end of
-; messages that didn't have them already, because on those messages Inno
-; Setup adds the periods automatically (appending a period would result in
-; two periods being displayed).
-;
-; Translated by stefan@bodingh.se (Stefan Bodingh)
-;
-
-; The following three entries are very important. Be sure to read and
-; understand the '[LangOptions] section' topic in the help file.
-
-
-[LangOptions]
-LanguageName=Svenska
-LanguageID=$041D
-LanguageCodePage=1252
-; If the language you are translating to requires special font faces or
-; sizes, uncomment any of the following entries and change them accordingly.
-;DialogFontName=
-;DialogFontSize=8
-;WelcomeFontName=Verdana
-;WelcomeFontSize=12
-;TitleFontName=Arial
-;TitleFontSize=29
-;CopyrightFontName=Arial
-;CopyrightFontSize=8
-
-
-; *** Application titles
-
-
-[Messages]
-SetupAppTitle=Installationsprogram
-SetupWindowTitle=Installationsprogram fr %1
-UninstallAppTitle=Avinstallation
-UninstallAppFullTitle=%1 Avinstallation
-
-; *** Misc. common
-
-
-InformationTitle=Information
-ConfirmTitle=Bekrfta
-ErrorTitle=Fel
-
-; *** SetupLdr messages
-
-
-SetupLdrStartupMessage=%1 kommer att installeras. Vill du fortstta?
-LdrCannotCreateTemp=Kan inte skapa en temporr fil. Installationen avbryts
-LdrCannotExecTemp=Kan inte kra fil i temporr katalog. Installationen avbryts
-HelpTextNote=
-
-; *** Startup error messages
-
-
-LastErrorMessage=%1.%n%nFel %2: %3
-SetupFileMissing=Filen %1 saknas i installationskatalogen. Rtta till problemet eller hmta en ny kopia av programmet.
-SetupFileCorrupt=Installationsfilerna r felaktiga. Hmta en ny kopia av programmet
-SetupFileCorruptOrWrongVer=Installationsfilerna r felaktiga, eller stmmer ej verens med denna version av installationsprogrammet. Rtta till felet eller hmta en ny programkopia.
-InvalidParameter=En ogiltig parameter angavs p kommandoraden:%n%n%1
-SetupAlreadyRunning=Setup krs redan.
-WindowsVersionNotSupported=Programmet stdjer inte den version av Windows som krs p datorn.
-WindowsServicePackRequired=Programmet krver %1 Service Pack %2 eller nyare.
-NotOnThisPlatform=Detta program kan ej kras p %1.
-OnlyOnThisPlatform=Detta program mste ha %1.
-OnlyOnTheseArchitectures=Detta program kan bara installeras p Windows versioner med fljande processorarkitekturer:%n%n%1
-WinVersionTooLowError=Detta program krver %1, version %2 eller senare.
-WinVersionTooHighError=Programmet kan inte installeras p %1 version %2 eller senare.
-AdminPrivilegesRequired=Du mste vara inloggad som administratr nr du installerar detta program.
-PowerUserPrivilegesRequired=Du mste vara inloggad som administratr eller medlem av gruppen Privilegierade anvndare (Power Users) nr du installerar detta program.
-SetupAppRunningError=Installationsprogrammet har upptckt att %1 r igng.%n%nAvsluta det angivna programmet nu. Klicka sedan p OK fr att g vidare, eller p Avbryt fr att avsluta.
-UninstallAppRunningError=Avinstalleraren har upptckt att %1 krs fr tillfllet.%n%nStng all ppna instanser av det nu, klicka sedan p OK fr att g vidare, eller p Avbryt fr att avsluta.
-PrivilegesRequiredOverrideTitle=Installationstyp
-PrivilegesRequiredOverrideInstruction=Vlj installationstyp
-PrivilegesRequiredOverrideText1=%1 kan installeras fr alla anvndare (krver administratons-rttigheter), eller bara fr dig.
-PrivilegesRequiredOverrideText2=%1 kan installeras bara fr dig, eller fr alla anvndare (krver administratons-rttigheter).
-PrivilegesRequiredOverrideAllUsers=Installera fr &alla anvndare
-PrivilegesRequiredOverrideAllUsersRecommended=Installera fr &alla anvndare (rekommenderas)
-PrivilegesRequiredOverrideCurrentUser=Installera fr &mig enbart
-PrivilegesRequiredOverrideCurrentUserRecommended=Installera fr &mig enbart (rekommenderas)
-
-; *** Misc. errors
-
-
-ErrorCreatingDir=Kunde inte skapa katalogen "%1"
-ErrorTooManyFilesInDir=Kunde inte skapa en fil i katalogen "%1" drfr att den innehller fr mnga filer
-
-; *** Setup common messages
-
-
-ExitSetupTitle=Avsluta installationen
-ExitSetupMessage=Installationen r inte frdig. Om du avslutar nu, kommer programmet inte att installeras.%n%nDu kan kra installationsprogrammet vid ett senare tillflle fr att slutfra installationen.%n%nVill du avbryta installationen?
-AboutSetupMenuItem=&Om installationsprogrammet...
-AboutSetupTitle=Om installationsprogrammet
-AboutSetupMessage=%1 version %2%n%3%n%n%1 hemsida:%n%4
-AboutSetupNote=Svensk versttning r gjord av dickg@go.to 1999, 2002%n%nUppdatering till 3.0.2+ av peter@peterandlinda.com, 4.+ av stefan@bodingh.se
-TranslatorNote=
-
-; *** Buttons
-
-
-ButtonBack=< &Tillbaka
-ButtonNext=&Nsta >
-ButtonInstall=&Installera
-ButtonOK=OK
-ButtonCancel=Avbryt
-ButtonYes=&Ja
-ButtonYesToAll=Ja till &Allt
-ButtonNo=&Nej
-ButtonNoToAll=N&ej till allt
-ButtonFinish=&Slutfr
-ButtonBrowse=&Blddra...
-ButtonWizardBrowse=&Blddra...
-ButtonNewFolder=Skapa ny katalog
-
-; *** "Select Language" dialog messages
-
-
-SelectLanguageTitle=Vlj sprk fr installationen
-SelectLanguageLabel=Vlj sprk som skall anvndas under installationen:
-
-; *** Common wizard text
-
-
-ClickNext=Klicka p Nsta fr att fortstta eller p Avbryt fr att avsluta installationen.
-BeveledLabel=
-BrowseDialogTitle=Vlj katalog
-BrowseDialogLabel=Vlj en katalog i listan nedan, klicka sedan p OK.
-NewFolderName=Ny katalog
-
-; *** "Welcome" wizard page
-
-
-WelcomeLabel1=Vlkommen till installationsprogrammet fr [name].
-WelcomeLabel2=Detta kommer att installera [name/ver] p din dator.%n%nDet rekommenderas att du avslutar alla andra program innan du fortstter. Det frebygger konflikter under installationens gng.
-
-; *** "Password" wizard page
-
-
-WizardPassword=Lsenord
-PasswordLabel1=Denna installation r skyddad med lsenord.
-PasswordLabel3=Var god ange lsenordet, klicka sedan p Nsta fr att fortstta. Lsenord skiljer p versaler/gemener.
-PasswordEditLabel=&Lsenord:
-IncorrectPassword=Lsenordet du angav r inkorrekt. Frsk igen.
-
-; *** "License Agreement" wizard page
-
-
-
-
-
-WizardLicense=Licensavtal
-LicenseLabel=Var god och ls fljande viktiga information innan du fortstter.
-LicenseLabel3=Var god och ls fljande licensavtal. Du mste acceptera villkoren i avtalet innan du kan fortstta med installationen.
-LicenseAccepted=Jag &accepterar avtalet
-LicenseNotAccepted=Jag accepterar &inte avtalet
-
-; *** "Information" wizard pages
-
-
-
-
-
-WizardInfoBefore=Information
-InfoBeforeLabel=Var god ls fljande viktiga information innan du fortstter.
-InfoBeforeClickLabel=Nr du r klar att fortstta med installationen klickar du p Nsta.
-WizardInfoAfter=Information
-InfoAfterLabel=Var god ls fljande viktiga information innan du fortstter.
-InfoAfterClickLabel=Nr du r klar att fortstta med installationen klickar du p Nsta.
-
-; *** "User Information" wizard page
-
-
-
-
-
-WizardUserInfo=Anvndarinformation
-UserInfoDesc=Var god och fyll i fljande uppgifter.
-UserInfoName=&Namn:
-UserInfoOrg=&Organisation:
-UserInfoSerial=&Serienummer:
-UserInfoNameRequired=Du mste fylla i ett namn.
-
-; *** "Select Destination Directory" wizard page
-
-
-
-
-
-WizardSelectDir=Vlj installationsplats
-SelectDirDesc=Var skall [name] installeras?
-SelectDirLabel3=Installationsprogrammet kommer att installera [name] i fljande katalog
-SelectDirBrowseLabel=Fr att fortstta klickar du p Nsta. Om du vill vlja en annan katalog klickar du p Blddra.
-DiskSpaceGBLabel=Programmet krver minst [gb] MB hrddiskutrymme.
-DiskSpaceMBLabel=Programmet krver minst [mb] MB hrddiskutrymme.
-CannotInstallToNetworkDrive=Setup kan inte installeras p ntverksdisk.
-CannotInstallToUNCPath=Setup kan inte installeras p UNC skvg.
-InvalidPath=Du mste skriva en fullstndig skvg med enhetsbeteckning; till exempel:%n%nC:\Program%n%neller en UNC-skvg i formatet:%n%n\\server\resurs
-InvalidDrive=Enheten du har valt finns inte eller r inte tillgnglig. Vlj en annan.
-DiskSpaceWarningTitle=Ej tillrckligt med diskutrymme
-DiskSpaceWarning=Installationsprogrammet behver tminstone %1 KB ledigt diskutrymme fr installationen, men den valda enheten har bara %2 KB tillgngligt.%n%nVill du fortstta nd?
-DirNameTooLong=Katalogens namn eller skvg r fr lng.
-InvalidDirName=Katalogen du har valt r inte tillgnglig.
-BadDirName32=Katalogens namn fr ej innehlla ngot av fljande tecken:%n%n%1
-DirExistsTitle=Katalogen finns
-DirExists=Katalogen:%n%n%1%n%nfinns redan. Vill du nd fortstta installationen till den valda katalogen?
-DirDoesntExistTitle=Katalogen finns inte
-DirDoesntExist=Katalogen:%n%n%1%n%nfinns inte. Vill du skapa den?
-
-; *** "Select Components" wizard page
-
-
-
-
-
-WizardSelectComponents=Vlj komponenter
-SelectComponentsDesc=Vilka komponenter skall installeras?
-SelectComponentsLabel2=Vlj de komponenter som du vill ska installeras; avmarkera de komponenter som du inte vill ha. Klicka sedan p Nsta nr du r klar att fortstta.
-FullInstallation=Fullstndig installation
-; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
-
-
-
-
-
-CompactInstallation=Kompakt installation
-CustomInstallation=Anpassad installation
-NoUninstallWarningTitle=Komponenter finns
-NoUninstallWarning=Installationsprogrammet har upptckt att fljande komponenter redan finns installerade p din dator:%n%n%1%n%nAtt avmarkera dessa komponenter kommer inte att avinstallera dom.%n%nVill du fortstta nd?
-ComponentSize1=%1 KB
-ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=Aktuella val krver minst [gb] GB diskutrymme.
-ComponentsDiskSpaceMBLabel=Aktuella val krver minst [mb] MB diskutrymme.
-
-; *** "Select Additional Tasks" wizard page
-
-
-
-
-
-WizardSelectTasks=Vlj extra uppgifter
-SelectTasksDesc=Vilka extra uppgifter skall utfras?
-SelectTasksLabel2=Markera ytterligare uppgifter att utfra vid installation av [name], tryck sedan p Nsta.
-
-; *** "Select Start Menu Folder" wizard page
-
-
-
-
-
-WizardSelectProgramGroup=Vlj Startmenykatalogen
-SelectStartMenuFolderDesc=Var skall installationsprogrammet placera programmets genvgar?
-SelectStartMenuFolderLabel3=Installationsprogrammet kommer att skapa programmets genvgar i fljande katalog.
-SelectStartMenuFolderBrowseLabel=Fr att fortstta klickar du p Nsta. Om du vill vlja en annan katalog, klickar du p Blddra.
-MustEnterGroupName=Du mste ange en katalog.
-GroupNameTooLong=Katalogens namn eller skvg r fr lng.
-InvalidGroupName=Katalogen du har valt r inte tillgnglig.
-BadGroupName=Katalognamnet kan inte innehlla ngon av fljande tecken:%n%n%1
-NoProgramGroupCheck2=&Skapa ingen Startmenykatalog
-
-; *** "Ready to Install" wizard page
-
-
-
-
-
-WizardReady=Redo att installera
-ReadyLabel1=Installationsprogrammet r nu redo att installera [name] p din dator.
-ReadyLabel2a=Tryck p Installera om du vill fortstta, eller p g Tillbaka om du vill granska eller ndra p ngot.
-ReadyLabel2b=Vlj Installera fr att pbrja installationen.
-ReadyMemoUserInfo=Anvndarinformation:
-ReadyMemoDir=Installationsplats:
-ReadyMemoType=Installationstyp:
-ReadyMemoComponents=Valda komponenter:
-ReadyMemoGroup=Startmenykatalog:
-ReadyMemoTasks=Extra uppgifter:
-DownloadingLabel=Laddar ner ytterligare filer...
-ButtonStopDownload=&Stoppa nedladdning
-StopDownload=r du sker p att du vill stoppa nedladdningen?
-ErrorDownloadAborted=Nedladdningen avbruten
-ErrorDownloadFailed=Nedladdningen misslyckades: %1 %2
-ErrorDownloadSizeFailed=F storlek misslyckades: %1 %2
-ErrorFileHash1=Filhash misslyckades: %1
-ErrorFileHash2=Ogiltig filhash: frvntat %1, hittat %2
-ErrorProgress=Ogiltig framfart: %1 of %2
-ErrorFileSize=Ogiltig filstorlek: frvntad %1, hittad %2
-
-; *** "Preparing to Install" wizard page
-
-
-
-
-
-WizardPreparing=Frbereder installationen
-PreparingDesc=Installationsprogrammet frbereder installationen av [name] p din dator.
-PreviousInstallNotCompleted=Installationen/avinstallationen av ett tidigare program har inte slutfrts. Du mste starta om datorn fr att avsluta den installationen.%n%nEfter att ha startat om datorn kr du installationsprogrammet igen fr att slutfra installationen av [name].
-CannotContinue=Installationsprogrammet kan inte fortstta. Klicka p Avbryt fr att avsluta.
-ApplicationsFound=Fljande program anvnder filer som mste uppdateras av Setup. Vi rekommenderar att du lter Setup automatiskt stnga dessa program.
-ApplicationsFound2=Fljande program anvnder filer som mste uppdateras av Setup. Vi rekommenderar att du lter Setup automatiskt stnga dessa program. Efter installationen kommer Setup att frska starta programmen igen.
-CloseApplications=&Stng programmen automatiskt
-DontCloseApplications=&Stng inte programmen
-ErrorCloseApplications=Installationsprogrammet kunde inte stnga alla program. Innan installationen fortstter rekommenderar vi att du stnger alla program som anvnder filer som Setup behver uppdatera.
-PrepareToInstallNeedsRestart=Installationen mste starta om din dator. Nr du har startat om datorn kr du Setup igen fr att slutfra installationen av [name].%n%nVill du starta om nu?
-
-; *** "Installing" wizard page
-
-
-
-
-
-WizardInstalling=Installerar
-InstallingLabel=Vnta medan [name] installeras p din dator.
-
-; *** "Setup Completed" wizard page
-
-
-
-
-
-FinishedHeadingLabel=Avslutar installationen av [name]
-FinishedLabelNoIcons=[name] har nu installerats p din dator.
-FinishedLabel=[name] har nu installerats p din dator. Programmet kan startas genom att vlja ngon av ikonerna.
-ClickFinish=Vlj Slutfr fr att avsluta installationen.
-FinishedRestartLabel=Fr att slutfra installationen av [name], mste datorn startas om. Vill du starta om nu?
-FinishedRestartMessage=Fr att slutfra installationen av [name], mste datorn startas om.%n%nVill du starta om datorn nu?
-ShowReadmeCheck=Ja, jag vill se filen LS MIG
-YesRadio=&Ja, jag vill starta om datorn nu
-NoRadio=&Nej, jag startar sjlv om datorn senare
-; used for example as 'Run MyProg.exe'
-
-
-
-
-
-RunEntryExec=Kr %1
-; used for example as 'View Readme.txt'
-
-
-
-
-
-RunEntryShellExec=Ls %1
-
-; *** "Setup Needs the Next Disk" stuff
-
-
-
-
-
-ChangeDiskTitle=Installationsprogrammet behver nsta diskett
-SelectDiskLabel2=Var god stt i diskett %1 och tryck OK.%n%nOm filerna kan hittas i en annan katalog n den som visas nedan, skriv in rtt skvg eller vlj Blddra.
-PathLabel=&Skvg:
-FileNotInDir2=Kunde inte hitta filen "%1" i "%2". Var god stt i korrekt diskett eller vlj en annan katalog.
-SelectDirectoryLabel=Var god ange skvgen fr nsta diskett.
-
-; *** Installation phase messages
-
-
-
-
-
-SetupAborted=Installationen slutfrdes inte.%n%nVar god rtta till felet och kr installationen igen.
-AbortRetryIgnoreSelectAction=Vlj tgrd
-AbortRetryIgnoreRetry=&Frsk igen
-AbortRetryIgnoreIgnore=&Ignorera felet och fortstt
-AbortRetryIgnoreCancel=Avbryt installationen
-
-; *** Installation status messages
-
-
-
-
-
-StatusClosingApplications=Stnger program...
-StatusCreateDirs=Skapar kataloger...
-StatusExtractFiles=Packar upp filer...
-StatusCreateIcons=Skapar programikoner...
-StatusCreateIniEntries=Skriver INI-vrden...
-StatusCreateRegistryEntries=Skriver register-vrden...
-StatusRegisterFiles=Registrerar filer...
-StatusSavingUninstall=Sparar information fr avinstallation...
-StatusRunProgram=Slutfr installationen...
-StatusRestartingApplications=Startar om program...
-StatusRollback=terstller ndringar...
-
-; *** Misc. errors
-
-
-
-
-
-ErrorInternal2=Internt fel: %1
-ErrorFunctionFailedNoCode=%1 misslyckades
-ErrorFunctionFailed=%1 misslyckades; kod %2
-ErrorFunctionFailedWithMessage=%1 misslyckades; kod %2.%n%3
-ErrorExecutingProgram=Kan inte kra filen:%n%1
-
-; *** Registry errors
-
-
-
-
-
-ErrorRegOpenKey=Fel vid ppning av registernyckel:%n%1\%2
-ErrorRegCreateKey=Kan ej skapa registernyckel:%n%1\%2
-ErrorRegWriteKey=Kan ej skriva till registernyckel:%n%1\%2
-
-; *** INI errors
-
-
-
-
-
-ErrorIniEntry=Kan inte skriva nytt INI-vrde i filen "%1".
-FileAbortRetryIgnoreSkipNotRecommended=&Hoppa ver den hr filen (rekommenderas inte)
-FileAbortRetryIgnoreIgnoreNotRecommended=&Ignorera felet och fortstt (rekommenderas inte)
-SourceIsCorrupted=Kllfilen r felaktig
-SourceDoesntExist=Kllfilen "%1" finns inte
-ExistingFileReadOnly2=Den befintliga filen kunde inte bytas ut eftersom den r markerad skrivskyddad.
-ExistingFileReadOnlyRetry=&Ta bort skrivskyddad attributet och frsk igen
-ExistingFileReadOnlyKeepExisting=&Behll den befintliga filen
-ErrorReadingExistingDest=Ett fel uppstod vid frsk att lsa den befintliga filen:
-FileExistsSelectAction=Vlj tgrd
-FileExists2=Filen finns redan.
-FileExistsOverwriteExisting=&Skriv ver den befintliga filen
-FileExistsKeepExisting=&Behll befintlig fil
-FileExistsOverwriteOrKeepAll=&Gr detta fr nsta konflikt
-ExistingFileNewerSelectAction=Vlj tgrd
-ExistingFileNewer2=Den befintliga filen r nyare n den som Setup frsker installera.
-ExistingFileNewerOverwriteExisting=&Skriv ver den befintliga filen
-ExistingFileNewerKeepExisting=&Behll befintlig fil (rekommenderas)
-ExistingFileNewerOverwriteOrKeepAll=&Gr detta fr nsta konflikt
-ErrorChangingAttr=Ett fel uppstod vid frsk att ndra attribut p den befintliga filen:
-ErrorCreatingTemp=Ett fel uppstod vid ett frsk att skapa installationskatalogen:
-ErrorReadingSource=Ett fel uppstod vid ett frsk att lsa kllfilen:
-ErrorCopying=Ett fel uppstod vid kopiering av filen:
-ErrorReplacingExistingFile=Ett fel uppstod vid ett frsk att erstta den befintliga filen:
-ErrorRestartReplace=terstartaErstt misslyckades:
-ErrorRenamingTemp=Ett fel uppstod vid ett frsk att byta namn p en fil i installationskatalogen:
-ErrorRegisterServer=Kunde inte registrera DLL/OCX: %1
-ErrorRegSvr32Failed=RegSvr32 misslyckades med felkod %1
-ErrorRegisterTypeLib=Kunde inte registrera typbibliotek: %1
-UninstallDisplayNameMark=%1 (%2)
-UninstallDisplayNameMarks=%1 (%2, %3)
-UninstallDisplayNameMark32Bit=32-bit
-UninstallDisplayNameMark64Bit=64-bit
-UninstallDisplayNameMarkAllUsers=Alla anvndare
-UninstallDisplayNameMarkCurrentUser=Nuvarande anvndare
-
-; *** Post-installation errors
-
-
-
-
-
-ErrorOpeningReadme=Ett fel uppstod vid ppnandet av LS MIG-filen.
-ErrorRestartingComputer=Installationsprogrammet kunde inte starta om datorn. Var god gr det manuellt.
-
-; *** Uninstaller messages
-
-
-
-
-
-UninstallNotFound=Filen "%1" finns inte. Kan inte avinstallera.
-UninstallOpenError=Filen "%1" kan inte ppnas. Kan inte avinstallera.
-UninstallUnsupportedVer=Avinstallationsloggen "%1" r i ett format som denna version inte knner igen. Kan ej avinstallera
-UninstallUnknownEntry=En oknd rad (%1) hittades i avinstallationsloggen
-ConfirmUninstall=r du sker p att du vill ta bort %1 och alla tillhrande komponenter?
-UninstallOnlyOnWin64=Denna installation kan endast avinstalleras p en 64-bitarsversion av Windows.
-OnlyAdminCanUninstall=Denna installation kan endast avinstalleras av en anvndare med administrativa rttigheter.
-UninstallStatusLabel=Var god och vnta medan %1 tas bort frn din dator.
-UninstalledAll=%1 r nu borttaget frn din dator.
-UninstalledMost=Avinstallationen av %1 r nu klar.%n%nEn del filer/kataloger gick ej att ta bort. Dessa kan tas bort manuellt.
-UninstalledAndNeedsRestart=Fr att slutfra avinstallationen av %1 mste datorn startas om.%n%nVill du starta om nu?
-UninstallDataCorrupted=Filen "%1" r felaktig. Kan inte avinstallera
-
-; *** Uninstallation phase messages
-
-
-
-
-
-ConfirmDeleteSharedFileTitle=Ta bort delad fil?
-ConfirmDeleteSharedFile2=Systemet indikerar att fljande delade fil inte lngre anvnds av ngra program. Vill du ta bort den delade filen?%n%n%1%n%nOm ngot program fortfarande anvnder denna fil och den raderas, kommer programmet kanske att sluta fungera. Om du r osker, vlj Nej. Att lta filen ligga kvar i systemet kommer inte att orsaka ngon skada.
-SharedFileNameLabel=Filnamn:
-SharedFileLocationLabel=Plats:
-WizardUninstalling=Avinstallationsstatus
-StatusUninstalling=Avinstallerar %1...
-
-; *** Shutdown block reasons
-
-
-
-
-
-ShutdownBlockReasonInstallingApp=Installerar %1.
-ShutdownBlockReasonUninstallingApp=Avinstallerar %1.
-
-; The custom messages below aren't used by Setup itself, but if you make
-; use of them in your scripts, you'll want to translate them.
-
-
-
-
-
-
-
-[CustomMessages]
-NameAndVersion=%1 version %2
-AdditionalIcons=terstende ikoner:
-CreateDesktopIcon=Skapa en genvg p skrivbordet
-CreateQuickLaunchIcon=Skapa en genvg i Snabbstartfltet
-ProgramOnTheWeb=%1 p Webben
-UninstallProgram=Avinstallera %1
-LaunchProgram=Starta %1
-AssocFileExtension=Associera %1 med %2 filnamnstillgg
-AssocingFileExtension=Associerar %1 med %2 filnamnstillgg...
-AutoStartProgramGroupDescription=Autostart:
-AutoStartProgram=Starta automatiskt %1
-AddonHostProgramNotFound=%1 kunde inte hittas i katalogen du valde.%n%nVill du fortstta nd?
+; *** Inno Setup version 5.5.3+ Swedish messages ***
+;
+; To download user-contributed translations of this file, go to:
+; http://www.jrsoftware.org/files/istrans/
+;
+; Note: When translating this text, do not add periods (.) to the end of
+; messages that didn't have them already, because on those messages Inno
+; Setup adds the periods automatically (appending a period would result in
+; two periods being displayed).
+;
+; Translated by christer_1@hotmail.com (Christer Toivonen)
+;
+
+[LangOptions]
+; The following three entries are very important. Be sure to read and
+; understand the '[LangOptions] section' topic in the help file.
+LanguageName=Svenska
+LanguageID=$041D
+LanguageCodePage=1252
+; If the language you are translating to requires special font faces or
+; sizes, uncomment any of the following entries and change them accordingly.
+;DialogFontName=
+;DialogFontSize=8
+;WelcomeFontName=Verdana
+;WelcomeFontSize=12
+;TitleFontName=Arial
+;TitleFontSize=29
+;CopyrightFontName=Arial
+;CopyrightFontSize=8
+
+[Messages]
+
+; *** Application titles
+SetupAppTitle=Installationsprogram
+SetupWindowTitle=Installationsprogram fr %1
+UninstallAppTitle=Avinstallation
+UninstallAppFullTitle=%1 Avinstallation
+
+; *** Misc. common
+InformationTitle=Information
+ConfirmTitle=Bekrfta
+ErrorTitle=Fel
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=%1 kommer att installeras. Vill du fortstta?
+LdrCannotCreateTemp=Kan ej skapa en temporr fil. Installationen avbryts
+LdrCannotExecTemp=Kan inte kra fil i temporr katalog. Installationen avbryts
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%nFel %2: %3
+SetupFileMissing=Filen %1 saknas i installationskatalogen. Rtta till problemet eller hmta en ny kopia av programmet.
+SetupFileCorrupt=Installationsfilerna r felaktiga. Hmta en ny kopia av programmet
+SetupFileCorruptOrWrongVer=Installationsfilerna r felaktiga, eller stmmer ej verens med denna version av installationsprogrammet. Rtta till felet eller hmta en ny programkopia.
+InvalidParameter=En ogiltig parameter angavs p kommandoraden:%n%n%1
+SetupAlreadyRunning=Setup krs redan.
+WindowsVersionNotSupported=Programmet stdjer inte den version av Windows som krs p datorn.
+WindowsServicePackRequired=Programmet krver %1 Service Pack %2 eller nyare.
+NotOnThisPlatform=Detta program kan ej kras p %1.
+OnlyOnThisPlatform=Detta program mste ha %1.
+OnlyOnTheseArchitectures=Detta program kan bara installeras p Windows versioner med fljande processorarkitekturer:%n%n%1
+MissingWOW64APIs=Den versionen av Windows du kr har inte den funktionalitet installationsprogrammet behver fr att genomfra en 64-bitars installation. Rtta till problemet genom att installera Service Pack %1.
+WinVersionTooLowError=Detta program krver %1, version %2 eller senare.
+WinVersionTooHighError=Programmet kan inte installeras p %1 version %2 eller senare.
+AdminPrivilegesRequired=Du mste vara inloggad som administratr nr du installerar detta program.
+PowerUserPrivilegesRequired=Du mste vara inloggad som administratr eller medlem av gruppen Privilegierade anvndare (Power Users) nr du installerar detta program.
+SetupAppRunningError=Installationsprogrammet har upptckt att %1 r igng.%n%nAvsluta det angivna programmet nu. Klicka sedan p OK fr att g vidare, eller p Avbryt fr att avsluta.
+UninstallAppRunningError=Avinstalleraren har upptckt att %1 krs fr tillfllet.%n%nStng all ppna instanser av det nu, klicka sedan p OK fr att g vidare, eller p Avbryt fr att avsluta.
+
+; *** Misc. errors
+ErrorCreatingDir=Kunde inte skapa katalogen "%1"
+ErrorTooManyFilesInDir=Kunde inte skapa en fil i katalogen "%1" drfr att den innehller fr mnga filer
+
+; *** Setup common messages
+ExitSetupTitle=Avsluta installationen
+ExitSetupMessage=Installationen r inte frdig. Om du avslutar nu, kommer programmet inte att installeras.%n%nDu kan kra installationsprogrammet vid ett senare tillflle fr att slutfra installationen.%n%nVill du avbryta installationen?
+AboutSetupMenuItem=&Om installationsprogrammet...
+AboutSetupTitle=Om installationsprogrammet
+AboutSetupMessage=%1 version %2%n%3%n%n%1 hemsida:%n%4
+AboutSetupNote=Svensk versttning r gjord av dickg@go.to 1999, 2002%n%nUppdatering till 3.0.2+ av peter@peterandlinda.com, 4.+ av stefan@bodingh.se
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< &Tillbaka
+ButtonNext=&Nsta >
+ButtonInstall=&Installera
+ButtonOK=OK
+ButtonCancel=Avbryt
+ButtonYes=&Ja
+ButtonYesToAll=Ja till &Allt
+ButtonNo=&Nej
+ButtonNoToAll=N&ej till allt
+ButtonFinish=&Slutfr
+ButtonBrowse=&Blddra...
+ButtonWizardBrowse=&Blddra...
+ButtonNewFolder=Skapa ny katalog
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=Vlj sprk fr installationen
+SelectLanguageLabel=Vlj sprk som skall anvndas under installationen:
+
+; *** Common wizard text
+ClickNext=Klicka p Nsta fr att fortstta eller p Avbryt fr att avsluta installationen.
+BeveledLabel=
+BrowseDialogTitle=Vlj katalog
+BrowseDialogLabel=Vlj en katalog i listan nedan, klicka sedan p OK.
+NewFolderName=Ny katalog
+
+; *** "Welcome" wizard page
+WelcomeLabel1=Vlkommen till installationsprogrammet fr [name].
+WelcomeLabel2=Detta kommer att installera [name/ver] p din dator.%n%nDet rekommenderas att du avslutar alla andra program innan du fortstter. Det frebygger konflikter under installationens gng.
+
+; *** "Password" wizard page
+WizardPassword=Lsenord
+PasswordLabel1=Denna installation r skyddad med lsenord.
+PasswordLabel3=Var god ange lsenordet, klicka sedan p Nsta fr att fortstta. Lsenord skiljer p versaler/gemener.
+PasswordEditLabel=&Lsenord:
+IncorrectPassword=Lsenordet du angav r inkorrekt. Frsk igen.
+
+; *** "License Agreement" wizard page
+WizardLicense=Licensavtal
+LicenseLabel=Var god och ls fljande viktiga information innan du fortstter.
+LicenseLabel3=Var god och ls fljande licensavtal. Du mste acceptera villkoren i avtalet innan du kan fortstta med installationen.
+LicenseAccepted=Jag &accepterar avtalet
+LicenseNotAccepted=Jag accepterar &inte avtalet
+
+; *** "Information" wizard pages
+WizardInfoBefore=Information
+InfoBeforeLabel=Var god ls fljande viktiga information innan du fortstter.
+InfoBeforeClickLabel=Nr du r klar att fortstta med installationen klickar du p Nsta.
+WizardInfoAfter=Information
+InfoAfterLabel=Var god ls fljande viktiga information innan du fortstter.
+InfoAfterClickLabel=Nr du r klar att fortstta med installationen klickar du p Nsta.
+
+; *** "User Information" wizard page
+WizardUserInfo=Anvndarinformation
+UserInfoDesc=Var god och fyll i fljande uppgifter.
+UserInfoName=&Namn:
+UserInfoOrg=&Organisation:
+UserInfoSerial=&Serienummer:
+UserInfoNameRequired=Du mste fylla i ett namn.
+
+; *** "Select Destination Directory" wizard page
+WizardSelectDir=Vlj installationsplats
+SelectDirDesc=Var skall [name] installeras?
+SelectDirLabel3=Installationsprogrammet kommer att installera [name] i fljande katalog
+SelectDirBrowseLabel=Fr att fortstta klickar du p Nsta. Om du vill vlja en annan katalog klickar du p Blddra.
+DiskSpaceMBLabel=Programmet krver minst [mb] MB hrddiskutrymme.
+CannotInstallToNetworkDrive=Setup kan inte installeras p ntverksdisk.
+CannotInstallToUNCPath=Setup kan inte installeras p UNC skvg.
+InvalidPath=Du mste skriva en fullstndig skvg med enhetsbeteckning; till exempel:%n%nC:\Program%n%neller en UNC-skvg i formatet:%n%n\\server\resurs
+InvalidDrive=Enheten du har valt finns inte eller r inte tillgnglig. Vlj en annan.
+DiskSpaceWarningTitle=Ej tillrckligt med diskutrymme
+DiskSpaceWarning=Installationsprogrammet behver tminstone %1 KB ledigt diskutrymme fr installationen, men den valda enheten har bara %2 KB tillgngligt.%n%nVill du fortstta nd?
+DirNameTooLong=Katalogens namn eller skvg r fr lng.
+InvalidDirName=Katalogen du har valt r inte tillgnglig.
+BadDirName32=Katalogens namn fr ej innehlla ngot av fljande tecken:%n%n%1
+DirExistsTitle=Katalogen finns
+DirExists=Katalogen:%n%n%1%n%nfinns redan. Vill du nd fortstta installationen till den valda katalogen?
+DirDoesntExistTitle=Katalogen finns inte
+DirDoesntExist=Katalogen:%n%n%1%n%nfinns inte. Vill du skapa den?
+
+; *** "Select Components" wizard page
+WizardSelectComponents=Vlj komponenter
+SelectComponentsDesc=Vilka komponenter skall installeras?
+SelectComponentsLabel2=Vlj de komponenter som du vill ska installeras; avmarkera de komponenter som du inte vill ha. Klicka sedan p Nsta nr du r klar att fortstta.
+FullInstallation=Fullstndig installation
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=Kompakt installation
+CustomInstallation=Anpassad installation
+NoUninstallWarningTitle=Komponenter finns
+NoUninstallWarning=Installationsprogrammet har upptckt att fljande komponenter redan finns installerade p din dator:%n%n%1%n%nAtt avmarkera dessa komponenter kommer inte att avinstallera dom.%n%nVill du fortstta nd?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=Aktuella val krver minst [mb] MB diskutrymme.
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=Vlj extra uppgifter
+SelectTasksDesc=Vilka extra uppgifter skall utfras?
+SelectTasksLabel2=Markera ytterligare uppgifter att utfra vid installation av [name], tryck sedan p Nsta.
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=Vlj Startmenykatalogen
+SelectStartMenuFolderDesc=Var skall installationsprogrammet placera programmets genvgar?
+SelectStartMenuFolderLabel3=Installationsprogrammet kommer att skapa programmets genvgar i fljande katalog.
+SelectStartMenuFolderBrowseLabel=Fr att fortstta klickar du p Nsta. Om du vill vlja en annan katalog, klickar du p Blddra.
+MustEnterGroupName=Du mste ange en katalog.
+GroupNameTooLong=Katalogens namn eller skvg r fr lng.
+InvalidGroupName=Katalogen du har valt r inte tillgnglig.
+BadGroupName=Katalognamnet kan inte innehlla ngon av fljande tecken:%n%n%1
+NoProgramGroupCheck2=&Skapa ingen Startmenykatalog
+
+; *** "Ready to Install" wizard page
+WizardReady=Redo att installera
+ReadyLabel1=Installationsprogrammet r nu redo att installera [name] p din dator.
+ReadyLabel2a=Tryck p Installera om du vill fortstta, eller p g Tillbaka om du vill granska eller ndra p ngot.
+ReadyLabel2b=Vlj Installera fr att pbrja installationen.
+ReadyMemoUserInfo=Anvndarinformation:
+ReadyMemoDir=Installationsplats:
+ReadyMemoType=Installationstyp:
+ReadyMemoComponents=Valda komponenter:
+ReadyMemoGroup=Startmenykatalog:
+ReadyMemoTasks=Extra uppgifter:
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=Frbereder installationen
+PreparingDesc=Installationsprogrammet frbereder installationen av [name] p din dator.
+PreviousInstallNotCompleted=Installationen/avinstallationen av ett tidigare program har inte slutfrts. Du mste starta om datorn fr att avsluta den installationen.%n%nEfter att ha startat om datorn kr du installationsprogrammet igen fr att slutfra installationen av [name].
+CannotContinue=Installationsprogrammet kan inte fortstta. Klicka p Avbryt fr att avsluta.
+ApplicationsFound=Fljande program anvnder filer som mste uppdateras av Setup. Vi rekommenderar att du lter Setup automatiskt stnga dessa program.
+ApplicationsFound2=Fljande program anvnder filer som mste uppdateras av Setup. Vi rekommenderar att du lter Setup automatiskt stnga dessa program. Efter installationen kommer Setup att frska starta programmen igen.
+CloseApplications=&Stng programmen automatiskt
+DontCloseApplications=&Stng inte programmen
+ErrorCloseApplications=Installationsprogrammet kunde inte stnga alla program. Innan installationen fortstter rekommenderar vi att du stnger alla program som anvnder filer som Setup behver uppdatera.
+
+; *** "Installing" wizard page
+WizardInstalling=Installerar
+InstallingLabel=Vnta medan [name] installeras p din dator.
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel=Avslutar installationen av [name]
+FinishedLabelNoIcons=[name] har nu installerats p din dator.
+FinishedLabel=[name] har nu installerats p din dator. Programmet kan startas genom att vlja ngon av ikonerna.
+ClickFinish=Vlj Slutfr fr att avsluta installationen.
+FinishedRestartLabel=Fr att slutfra installationen av [name], mste datorn startas om. Vill du starta om nu?
+FinishedRestartMessage=Fr att slutfra installationen av [name], mste datorn startas om.%n%nVill du starta om datorn nu?
+ShowReadmeCheck=Ja, jag vill se filen LS MIG
+YesRadio=&Ja, jag vill starta om datorn nu
+NoRadio=&Nej, jag startar sjlv om datorn senare
+; used for example as 'Run MyProg.exe'
+RunEntryExec=Kr %1
+; used for example as 'View Readme.txt'
+RunEntryShellExec=Ls %1
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=Installationsprogrammet behver nsta diskett
+SelectDiskLabel2=Var god stt i diskett %1 och tryck OK.%n%nOm filerna kan hittas i en annan katalog n den som visas nedan, skriv in rtt skvg eller vlj Blddra.
+PathLabel=&Skvg:
+FileNotInDir2=Kunde inte hitta filen "%1" i "%2". Var god stt i korrekt diskett eller vlj en annan katalog.
+SelectDirectoryLabel=Var god ange skvgen fr nsta diskett.
+
+; *** Installation phase messages
+SetupAborted=Installationen slutfrdes inte.%n%nVar god rtta till felet och kr installationen igen.
+EntryAbortRetryIgnore=Vlj Frsk igen eller Ignorera fr att fortstta nd, eller vlj Avbryt fr att avbryta installationen.
+
+; *** Installation status messages
+StatusClosingApplications=Stnger program...
+StatusCreateDirs=Skapar kataloger...
+StatusExtractFiles=Packar upp filer...
+StatusCreateIcons=Skapar programikoner...
+StatusCreateIniEntries=Skriver INI-vrden...
+StatusCreateRegistryEntries=Skriver register-vrden...
+StatusRegisterFiles=Registrerar filer...
+StatusSavingUninstall=Sparar information fr avinstallation...
+StatusRunProgram=Slutfr installationen...
+StatusRestartingApplications=Startar om program...
+StatusRollback=terstller ndringar...
+
+; *** Misc. errors
+ErrorInternal2=Internt fel: %1
+ErrorFunctionFailedNoCode=%1 misslyckades
+ErrorFunctionFailed=%1 misslyckades; kod %2
+ErrorFunctionFailedWithMessage=%1 misslyckades; kod %2.%n%3
+ErrorExecutingProgram=Kan inte kra filen:%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=Fel vid ppning av registernyckel:%n%1\%2
+ErrorRegCreateKey=Kan ej skapa registernyckel:%n%1\%2
+ErrorRegWriteKey=Kan ej skriva till registernyckel:%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=Kan inte skriva nytt INI-vrde i filen "%1".
+
+; *** File copying errors
+FileAbortRetryIgnore=Vlj Frsk igen eller Ignorera fr att hoppa ver denna fil (ej rekommenderat), eller vlj Avbryt installationen.
+FileAbortRetryIgnore2=Vlj Frsk igen eller Ignorera och fortstt nd (ej rekommenderat), eller vlj Avbryt installationen.
+SourceIsCorrupted=Kllfilen r felaktig
+SourceDoesntExist=Kllfilen "%1" finns inte
+ExistingFileReadOnly=Den nuvarande filen r skrivskyddad.%n%nVlj Frsk igen fr att ta bort skrivskyddet, Ignorera fr att hoppa ver denna fil, eller vlj Avbryt installationen.
+ErrorReadingExistingDest=Ett fel uppstod vid frsk att lsa den befintliga filen:
+FileExists=Filen finns redan.%n%nVill du skriva ver den?
+ExistingFileNewer=Den befintliga filen r nyare n den som ska installeras. Du rekommenderas att behlla den befintliga filen. %n%nVill Du behlla den befintliga filen?
+ErrorChangingAttr=Ett fel uppstod vid frsk att ndra attribut p den befintliga filen:
+ErrorCreatingTemp=Ett fel uppstod vid ett frsk att skapa installationskatalogen:
+ErrorReadingSource=Ett fel uppstod vid ett frsk att lsa kllfilen:
+ErrorCopying=Ett fel uppstod vid kopiering av filen:
+ErrorReplacingExistingFile=Ett fel uppstod vid ett frsk att erstta den befintliga filen:
+ErrorRestartReplace=terstartaErstt misslyckades:
+ErrorRenamingTemp=Ett fel uppstod vid ett frsk att byta namn p en fil i installationskatalogen:
+ErrorRegisterServer=Kunde inte registrera DLL/OCX: %1
+ErrorRegSvr32Failed=RegSvr32 misslyckades med felkod %1
+ErrorRegisterTypeLib=Kunde inte registrera typbibliotek: %1
+
+; *** Post-installation errors
+ErrorOpeningReadme=Ett fel uppstod vid ppnandet av LS MIG-filen.
+ErrorRestartingComputer=Installationsprogrammet kunde inte starta om datorn. Var god gr det manuellt.
+
+; *** Uninstaller messages
+UninstallNotFound=Filen "%1" finns inte. Kan inte avinstallera.
+UninstallOpenError=Filen "%1" kan inte ppnas. Kan inte avinstallera.
+UninstallUnsupportedVer=Avinstallationsloggen "%1" r i ett format som denna version inte knner igen. Kan ej avinstallera
+UninstallUnknownEntry=En oknd rad (%1) hittades i avinstallationsloggen
+ConfirmUninstall=r du sker p att du vill ta bort %1 och alla tillhrande komponenter?
+UninstallOnlyOnWin64=Denna installation kan endast avinstalleras p en 64-bitarsversion av Windows.
+OnlyAdminCanUninstall=Denna installation kan endast avinstalleras av en anvndare med administrativa rttigheter.
+UninstallStatusLabel=Var god och vnta medan %1 tas bort frn din dator.
+UninstalledAll=%1 r nu borttaget frn din dator.
+UninstalledMost=Avinstallationen av %1 r nu klar.%n%nEn del filer/kataloger gick ej att ta bort. Dessa kan tas bort manuellt.
+UninstalledAndNeedsRestart=Fr att slutfra avinstallationen av %1 mste datorn startas om.%n%nVill du starta om nu?
+UninstallDataCorrupted=Filen "%1" r felaktig. Kan inte avinstallera
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=Ta bort delad fil?
+ConfirmDeleteSharedFile2=Systemet indikerar att fljande delade fil inte lngre anvnds av ngra program. Vill du ta bort den delade filen?%n%n%1%n%nOm ngot program fortfarande anvnder denna fil och den raderas, kommer programmet kanske att sluta fungera. Om du r osker, vlj Nej. Att lta filen ligga kvar i systemet kommer inte att orsaka ngon skada.
+SharedFileNameLabel=Filnamn:
+SharedFileLocationLabel=Plats:
+WizardUninstalling=Avinstallationsstatus
+StatusUninstalling=Avinstallerar %1...
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=Installerar %1.
+ShutdownBlockReasonUninstallingApp=Avinstallerar %1.
+
+; The custom messages below aren't used by Setup itself, but if you make
+; use of them in your scripts, you'll want to translate them.
+
+[CustomMessages]
+
+NameAndVersion=%1 version %2
+AdditionalIcons=terstende ikoner:
+CreateDesktopIcon=Skapa en ikon p skrivbordet
+CreateQuickLaunchIcon=Skapa en ikon i Snabbstartfltet
+ProgramOnTheWeb=%1 p Webben
+UninstallProgram=Avinstallera %1
+LaunchProgram=Starta %1
+AssocFileExtension=Associera %1 med %2 filnamnstillgg
+AssocingFileExtension=Associerar %1 med %2 filnamnstillgg...
+AutoStartProgramGroupDescription=Autostart:
+AutoStartProgram=Starta automatiskt %1
+AddonHostProgramNotFound=%1 kunde inte hittas i katalogen du valde.%n%nVill du fortstta nd?
diff --git a/installer/innosetup/installer-large.bmp b/Greenshot/releases/innosetup/installer-large.bmp
similarity index 100%
rename from installer/innosetup/installer-large.bmp
rename to Greenshot/releases/innosetup/installer-large.bmp
diff --git a/installer/innosetup/installer-small.bmp b/Greenshot/releases/innosetup/installer-small.bmp
similarity index 100%
rename from installer/innosetup/installer-small.bmp
rename to Greenshot/releases/innosetup/installer-small.bmp
diff --git a/installer/innosetup/scripts/isxdl/czech.ini b/Greenshot/releases/innosetup/scripts/isxdl/czech.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/czech.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/czech.ini
diff --git a/installer/innosetup/scripts/isxdl/dutch.ini b/Greenshot/releases/innosetup/scripts/isxdl/dutch.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/dutch.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/dutch.ini
diff --git a/installer/innosetup/scripts/isxdl/english.ini b/Greenshot/releases/innosetup/scripts/isxdl/english.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/english.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/english.ini
diff --git a/installer/innosetup/scripts/isxdl/french.ini b/Greenshot/releases/innosetup/scripts/isxdl/french.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/french.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/french.ini
diff --git a/installer/innosetup/scripts/isxdl/french2.ini b/Greenshot/releases/innosetup/scripts/isxdl/french2.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/french2.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/french2.ini
diff --git a/installer/innosetup/scripts/isxdl/french3.ini b/Greenshot/releases/innosetup/scripts/isxdl/french3.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/french3.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/french3.ini
diff --git a/installer/innosetup/scripts/isxdl/german.ini b/Greenshot/releases/innosetup/scripts/isxdl/german.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/german.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/german.ini
diff --git a/Greenshot/releases/innosetup/scripts/isxdl/german2.ini b/Greenshot/releases/innosetup/scripts/isxdl/german2.ini
new file mode 100644
index 000000000..0a4bf0c86
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/isxdl/german2.ini
@@ -0,0 +1,45 @@
+[strings]
+; General
+100=Datei herunterladen
+101=Mchten Sie das Herunterladen der Datei abbrechen?
+102=%1 (%2 von %3)
+103=%1 KB
+104=%1 KB von %2 KB (%3%)
+
+; Status information
+110=Dateiinformationen werden ermittelt...
+111=Weitervermittlung zu %1
+112=Anforderung wird gesendet...
+113=Auflsen von %1
+114=Mit %1 verbunden
+115=Empfang...
+116=Verbinden mit %1
+
+; Error messages
+120=Fehler beim Verbinden mit dem Internet.\n\n%1
+121=Fehler beim ffnen von %1.\n\nDer Server hat folgenden Statuscode gemeldet %2.
+122=Fehler beim Lesen der URL.\n\n%1
+123=Fehler beim Schreiben der Datei %1.\n\n%2
+124=Fehler beim ffnen der Datei %1.\n\n%2
+125='%1' ist eine ungltige URL.
+126=Fehler beim ffnen von %1.\n\n%2
+127=Fehler beim Senden der Anforderung.\n\n%1
+128=Protokoll wird nicht untersttzt. Nur HTTP und FTP werden untersttzt.
+129=Verbindung zu %1 fehlgeschlagen.\n\n%2
+130=Fehler bei der Abfrage des Statuscodes.\n\n%1
+131=Fehler bei der Anforderung der Datei.\n\n%1
+
+; Other
+144=ber...
+146=Download
+147=Das Setup ldt nun zustzliche Dateien auf Ihren Computer.
+
+; labels
+160=Datei:
+161=Geschwindigkeit:
+162=Status:
+163=Bisherige Zeit:
+164=Verbleibende Zeit:
+165=Derzeitige Datei:
+166=Gesamter Vorgang:
+167=Abbrechen
diff --git a/Greenshot/releases/innosetup/scripts/isxdl/german3.ini b/Greenshot/releases/innosetup/scripts/isxdl/german3.ini
new file mode 100644
index 000000000..58f1b716d
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/isxdl/german3.ini
@@ -0,0 +1,45 @@
+[strings]
+; General
+100=Datei-Download
+101=Mchten Sie das Herunterladen abbrechen?
+102=%1 (%2 von %3)
+103=%1 KB
+104=%1 KB von %2 KB (%3%)
+
+; Status information
+110=Ermittle Datei-Informationen...
+111=Leite um nach %1
+112=Sende Anforderung...
+113=Auflsen %1
+114=Verbunden mit %1
+115=Empfange...
+116=Verbinde mit %1
+
+; Error messages
+120=Fehler beim Verbinden mit dem Internet.\n\n%1
+121=Fehler beim ffnen von %1.\n\nDer Server meldet Statuscode %2.
+122=Fehler beim Lesen der URL.\n\n%1
+123=Fehler beim Schreiben der Datei %1.\n\n%2
+124=Fehler beim ffnen der Datei %1.\n\n%2
+125='%1' ist eine ungltige URL.
+126=Fehler beim ffnen von %1.\n\n%2
+127=Fehler beim Senden der Anforderung.\n\n%1
+128=Nicht untersttztes Protokoll. Nur HTTP- and FTP-Protokolle werden untersttzt.
+129=Verbindung fehlgeschlagen: %1.\n\n%2
+130=Abfragen des Statuscodes fehlgeschlagen.\n\n%1
+131=Fehler beim Anfordern der Datei.\n\n%1
+
+; Other
+144=ber...
+146=Download
+147=Setup ldt nun weitere Dateien aus dem Internet auf Ihren Computer herunter.
+
+; labels
+160=Datei:
+161=Geschwindigkeit:
+162=Status:
+163=Verstrichene Zeit:
+164=Verbleibende Zeit:
+165=Aktuelle Datei:
+166=Gesamter Download:
+167=Abbrechen
diff --git a/installer/innosetup/scripts/isxdl/isxdl.dll b/Greenshot/releases/innosetup/scripts/isxdl/isxdl.dll
similarity index 100%
rename from installer/innosetup/scripts/isxdl/isxdl.dll
rename to Greenshot/releases/innosetup/scripts/isxdl/isxdl.dll
diff --git a/installer/innosetup/scripts/isxdl/isxdl.iss b/Greenshot/releases/innosetup/scripts/isxdl/isxdl.iss
similarity index 100%
rename from installer/innosetup/scripts/isxdl/isxdl.iss
rename to Greenshot/releases/innosetup/scripts/isxdl/isxdl.iss
diff --git a/Greenshot/releases/innosetup/scripts/isxdl/italian.ini b/Greenshot/releases/innosetup/scripts/isxdl/italian.ini
new file mode 100644
index 000000000..7729f3ac4
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/isxdl/italian.ini
@@ -0,0 +1,49 @@
+[strings]
+; Generale
+100=Download del file
+101=Vuoi annullare il download?
+102=%1 (%2 di %3)
+103=%1 KB
+104=%1 KB di %2 KB (%3%)
+
+; informazioni di stato
+110=Ottenere informazioni sul file ...
+111=reindirizzamento a %1
+112=Invio richiesta...
+113=Risoluzione %1
+114=Connesso al %1
+115=Ricezione...
+116=Collegamento a %1
+
+; Messaggio di errore
+120=Errore di connessione a Internet.\n\n%1
+121=Errore di apertura %1.\n\nIl server ha restituito codice di stato %2.
+122=Errore di lettura del URL.\n\n%1
+123=Errore scrittura del file %1.\n\n%2
+124=Errore apertura del file %1.\n\n%2
+125='%1' è un URL non valido.
+126=Errore d'apertura %1.\n\n%2
+127=Errore d'invio richiesta.\n\n%1
+128=Protocollo non supportato. Sono supportati solo i protocolli HTTP e FTP.
+129=Connessione non riuscita a %1.\n\n%2
+130=Impossibile eseguire la query codice di stato.\n\n%1
+131=Errore file di richiedente.\n\n%1
+
+; Altro
+144=A proposito di ...
+146=Download
+147=L'installazione è ora scaricando i file aggiuntive al computer.
+
+; etichette
+160=File:
+161=Velocità:
+162=Stato:
+163=Tempo trascorso:
+164=Tempo rimanente:
+165=File corrente:
+166=Avanzamento generale:
+167=Annulla
+168=OK
+169=Nome utente e password
+170=Nome Utente:
+171=Password:
diff --git a/installer/innosetup/scripts/isxdl/japanese.ini b/Greenshot/releases/innosetup/scripts/isxdl/japanese.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/japanese.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/japanese.ini
diff --git a/installer/innosetup/scripts/isxdl/korean.ini b/Greenshot/releases/innosetup/scripts/isxdl/korean.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/korean.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/korean.ini
diff --git a/installer/innosetup/scripts/isxdl/norwegian.ini b/Greenshot/releases/innosetup/scripts/isxdl/norwegian.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/norwegian.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/norwegian.ini
diff --git a/installer/innosetup/scripts/isxdl/polish.ini b/Greenshot/releases/innosetup/scripts/isxdl/polish.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/polish.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/polish.ini
diff --git a/installer/innosetup/scripts/isxdl/portugues.ini b/Greenshot/releases/innosetup/scripts/isxdl/portugues.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/portugues.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/portugues.ini
diff --git a/installer/innosetup/scripts/isxdl/portuguese.ini b/Greenshot/releases/innosetup/scripts/isxdl/portuguese.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/portuguese.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/portuguese.ini
diff --git a/installer/innosetup/scripts/isxdl/russian.ini b/Greenshot/releases/innosetup/scripts/isxdl/russian.ini
similarity index 61%
rename from installer/innosetup/scripts/isxdl/russian.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/russian.ini
index f5791cde0..5cfae9227 100644
--- a/installer/innosetup/scripts/isxdl/russian.ini
+++ b/Greenshot/releases/innosetup/scripts/isxdl/russian.ini
@@ -1,7 +1,7 @@
[strings]
; General
100=
-101= ?
+101= ?
102=%1 (%2 %3)
103=%1 KB
104=%1 KB %2 KB (%3%)
@@ -10,29 +10,30 @@
110= ...
111= %1
112= ...
-113= %1
-114= %1
+113= %1
+114= %1
115=...
116= %1
; Error messages
-120= .\n\n%1
+120= .\n\n%1
121= %1.\n\n %2.
122= .\n\n%1
123= %1.\n\n%2
124= %1.\n\n%2
-125='%1' .
+125='%1' .
126= %1.\n\n%2
-127= .\n\n%1
-128= . HTTP FTP.
+127= .\n\n%1
+128= . HTTP FTP
+.
129= %1.\n\n%2
-130= .\n\n%1
+130= .\n\n%1
131= .\n\n%1
; Other
-144= ...
+144=...
146=
-147= .
+147= .
; labels
160=:
diff --git a/installer/innosetup/scripts/isxdl/spanish.ini b/Greenshot/releases/innosetup/scripts/isxdl/spanish.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/spanish.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/spanish.ini
diff --git a/installer/innosetup/scripts/isxdl/swedish.ini b/Greenshot/releases/innosetup/scripts/isxdl/swedish.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/swedish.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/swedish.ini
diff --git a/installer/innosetup/scripts/products.pas b/Greenshot/releases/innosetup/scripts/products.iss
similarity index 50%
rename from installer/innosetup/scripts/products.pas
rename to Greenshot/releases/innosetup/scripts/products.iss
index 3335007e7..b7b12d6a3 100644
--- a/installer/innosetup/scripts/products.pas
+++ b/Greenshot/releases/innosetup/scripts/products.iss
@@ -1,329 +1,294 @@
-{
- --- TYPES AND VARIABLES ---
-}
-type
- TProduct = record
- File: String;
- Title: String;
- Parameters: String;
- ForceSuccess : boolean;
- InstallClean : boolean;
- MustRebootAfter : boolean;
- end;
-
- InstallResult = (InstallSuccessful, InstallRebootRequired, InstallError);
-
-var
- installMemo, downloadMessage: string;
- products: array of TProduct;
- delayedReboot, isForcedX86: boolean;
- DependencyPage: TOutputProgressWizardPage;
-
-procedure AddProduct(filename, parameters, title, size, url: string; forceSuccess, installClean, mustRebootAfter : boolean);
-{
- Adds a product to the list of products to download.
- Parameters:
- filename: the file name under which to save the file
- parameters: the parameters with which to run the file
- title: the product title
- size: the file size
- url: the URL to download from
- forceSuccess: whether to continue in case of setup failure
- installClean: whether the product needs a reboot before installing
- mustRebootAfter: whether the product needs a reboot after installing
-}
-var
- path: string;
- i: Integer;
-begin
- installMemo := installMemo + '%1' + title + #13;
-
- path := ExpandConstant('{src}{\}') + CustomMessage('DependenciesDir') + '\' + filename;
- if not FileExists(path) then begin
- path := ExpandConstant('{tmp}{\}') + filename;
-
- if not FileExists(path) then begin
- isxdl_AddFile(url, path);
-
- downloadMessage := downloadMessage + '%1' + title + ' (' + size + ')' + #13;
- end;
- end;
-
- i := GetArrayLength(products);
- SetArrayLength(products, i + 1);
- products[i].File := path;
- products[i].Title := title;
- products[i].Parameters := parameters;
- products[i].ForceSuccess := forceSuccess;
- products[i].InstallClean := installClean;
- products[i].MustRebootAfter := mustRebootAfter;
-end;
-
-function SmartExec(product : TProduct; var resultcode : Integer): boolean;
-{
- Executes a product and returns the exit code.
- Parameters:
- product: the product to install
- resultcode: the exit code
-}
-begin
- if (LowerCase(Copy(product.File, Length(product.File) - 2, 3)) = 'exe') then begin
- Result := Exec(product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode);
- end else begin
- Result := ShellExec('', product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode);
- end;
-end;
-
-function PendingReboot: boolean;
-{
- Checks whether the machine has a pending reboot.
-}
-var names: String;
-begin
- if (RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations', names)) then begin
- Result := true;
- end else if ((RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'SetupExecute', names)) and (names <> '')) then begin
- Result := true;
- end else begin
- Result := false;
- end;
-end;
-
-function InstallProducts: InstallResult;
-{
- Installs the downloaded products
-}
-var
- resultCode, i, productCount, finishCount: Integer;
-begin
- Result := InstallSuccessful;
- productCount := GetArrayLength(products);
-
- if productCount > 0 then begin
- DependencyPage := CreateOutputProgressPage(CustomMessage('depinstall_title'), CustomMessage('depinstall_description'));
- DependencyPage.Show;
-
- for i := 0 to productCount - 1 do begin
- if (products[i].InstallClean and (delayedReboot or PendingReboot())) then begin
- Result := InstallRebootRequired;
- break;
- end;
-
- DependencyPage.SetText(FmtMessage(CustomMessage('depinstall_status'), [products[i].Title]), '');
- DependencyPage.SetProgress(i, productCount);
-
- while true do begin
- // set 0 as used code for shown error if SmartExec fails
- resultCode := 0;
- if SmartExec(products[i], resultCode) then begin
- // setup executed; resultCode contains the exit code
- if (products[i].MustRebootAfter) then begin
- // delay reboot after install if we installed the last dependency anyways
- if (i = productCount - 1) then begin
- delayedReboot := true;
- end else begin
- Result := InstallRebootRequired;
- end;
- break;
- end else if (resultCode = 0) or (products[i].ForceSuccess) then begin
- finishCount := finishCount + 1;
- break;
- end else if (resultCode = 3010) then begin
- // Windows Installer resultCode 3010: ERROR_SUCCESS_REBOOT_REQUIRED
- delayedReboot := true;
- finishCount := finishCount + 1;
- break;
- end;
- end;
-
- case MsgBox(FmtMessage(SetupMessage(msgErrorFunctionFailed), [products[i].Title, IntToStr(resultCode)]), mbError, MB_ABORTRETRYIGNORE) of
- IDABORT: begin
- Result := InstallError;
- break;
- end;
- IDIGNORE: begin
- break;
- end;
- end;
- end;
-
- if Result <> InstallSuccessful then begin
- break;
- end;
- end;
-
- // only leave not installed products for error message
- for i := 0 to productCount - finishCount - 1 do begin
- products[i] := products[i+finishCount];
- end;
- SetArrayLength(products, productCount - finishCount);
-
- DependencyPage.Hide;
- end;
-end;
-
-{
- --------------------
- INNO EVENT FUNCTIONS
- --------------------
-}
-
-function PrepareToInstall(var NeedsRestart: boolean): String;
-{
- Before the "preparing to install" page.
- See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents
-}
-var
- i: Integer;
- s: string;
-begin
- delayedReboot := false;
-
- case InstallProducts() of
- InstallError: begin
- s := CustomMessage('depinstall_error');
-
- for i := 0 to GetArrayLength(products) - 1 do begin
- s := s + #13 + ' ' + products[i].Title;
- end;
-
- Result := s;
- end;
- InstallRebootRequired: begin
- Result := products[0].Title;
- NeedsRestart := true;
-
- // write into the registry that the installer needs to be executed again after restart
- RegWriteStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'InstallBootstrap', ExpandConstant('{srcexe}'));
- end;
- end;
-end;
-
-function NeedRestart : boolean;
-{
- Checks whether a restart is needed at the end of install
- See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents
-}
-begin
- Result := delayedReboot;
-end;
-
-function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
-{
- Just before the "ready" page.
- See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents
-}
-var
- s: string;
-begin
- if downloadMessage <> '' then
- s := s + CustomMessage('depdownload_memo_title') + ':' + NewLine + FmtMessage(downloadMessage, [Space]) + NewLine;
- if installMemo <> '' then
- s := s + CustomMessage('depinstall_memo_title') + ':' + NewLine + FmtMessage(installMemo, [Space]) + NewLine;
-
- if MemoDirInfo <> '' then
- s := s + MemoDirInfo + NewLine + NewLine;
- if MemoGroupInfo <> '' then
- s := s + MemoGroupInfo + NewLine + NewLine;
- if MemoTasksInfo <> '' then
- s := s + MemoTasksInfo;
-
- Result := s
-end;
-
-function NextButtonClick(CurPageID: Integer): boolean;
-{
- At each "next" button click
- See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents
-}
-begin
- Result := true;
-
- if CurPageID = wpReady then begin
- if downloadMessage <> '' then begin
- // change isxdl language only if it is not english because isxdl default language is already english
- if (ActiveLanguage() <> 'en') then begin
- ExtractTemporaryFile(CustomMessage('isxdl_langfile'));
- isxdl_SetOption('language', ExpandConstant('{tmp}{\}') + CustomMessage('isxdl_langfile'));
- end;
- //isxdl_SetOption('title', FmtMessage(SetupMessage(msgSetupWindowTitle), [CustomMessage('appname')]));
-
- //if SuppressibleMsgBox(FmtMessage(CustomMessage('depdownload_msg'), [FmtMessage(downloadMessage, [''])]), mbConfirmation, MB_YESNO, IDYES) = IDNO then
- // Result := false
- //else if
- if isxdl_DownloadFiles(StrToInt(ExpandConstant('{wizardhWnd}'))) = 0 then
- Result := false;
- end;
- end;
-end;
-
-{
- -----------------------------
- ARCHITECTURE HELPER FUNCTIONS
- -----------------------------
-}
-
-function IsX86: boolean;
-{
- Gets whether the computer is x86 (32 bits).
-}
-begin
- Result := isForcedX86 or (ProcessorArchitecture = paX86) or (ProcessorArchitecture = paUnknown);
-end;
-
-function IsX64: boolean;
-{
- Gets whether the computer is x64 (64 bits).
-}
-begin
- Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paX64);
-end;
-
-function IsIA64: boolean;
-{
- Gets whether the computer is IA64 (Itanium 64 bits).
-}
-begin
- Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paIA64);
-end;
-
-function GetString(x86, x64, ia64: String): String;
-{
- Gets a string depending on the computer architecture.
- Parameters:
- x86: the string if the computer is x86
- x64: the string if the computer is x64
- ia64: the string if the computer is IA64
-}
-begin
- if IsX64() and (x64 <> '') then begin
- Result := x64;
- end else if IsIA64() and (ia64 <> '') then begin
- Result := ia64;
- end else begin
- Result := x86;
- end;
-end;
-
-function GetArchitectureString(): String;
-{
- Gets the "standard" architecture suffix string.
- Returns either _x64, _ia64 or nothing.
-}
-begin
- if IsX64() then begin
- Result := '_x64';
- end else if IsIA64() then begin
- Result := '_ia64';
- end else begin
- Result := '';
- end;
-end;
-
-procedure SetForceX86(value: boolean);
-{
- Forces the setup to use X86 products
-}
-begin
- isForcedX86 := value;
-end;
+#include "isxdl\isxdl.iss"
+
+[CustomMessages]
+DependenciesDir=MyProgramDependencies
+
+en.depdownload_msg=The following applications are required before setup can continue:%n%n%1%nDownload and install now?
+de.depdownload_msg=Die folgenden Programme werden bentigt bevor das Setup fortfahren kann:%n%n%1%nJetzt downloaden und installieren?
+fr.depdownload_msg=Les applications suivantes sont ncessaires avant l'installation peut continuer:%n%n%1%nTlchargement et installer maintenant?
+nl.depdownload_msg=De volgende toepassingen zijn nodig vr de installatie kunt doorgaan:%n%n%1%nDownload en installeer nu?
+
+en.depdownload_memo_title=Download dependencies
+de.depdownload_memo_title=Abhngigkeiten downloaden
+fr.depdownload_memo_title=Tlcharger les dpendances
+nl.depdownload_memo_title=Download afhankelijkheden
+
+en.depinstall_memo_title=Install dependencies
+de.depinstall_memo_title=Abhngigkeiten installieren
+fr.depinstall_memo_title=Installez les dpendances
+nl.depinstall_memo_title=Installeer afhankelijkheden
+
+en.depinstall_title=Installing dependencies
+de.depinstall_title=Installiere Abhngigkeiten
+fr.depinstall_title=Installation des dpendances
+nl.depinstall_title=Installeer afhankelijkheden
+
+en.depinstall_description=Please wait while Setup installs dependencies on your computer.
+de.depinstall_description=Warten Sie bitte whrend Abhngigkeiten auf Ihrem Computer installiert wird.
+fr.depinstall_description=S'il vous plat patienter pendant que le programme d'installation installe les dpendances sur votre ordinateur.
+nl.depinstall_description=Een moment geduld aub Setup installeert afhankelijkheden op uw computer.
+
+en.depinstall_status=Installing %1...
+de.depinstall_status=Installiere %1...
+fr.depinstall_status=Installation %1...
+nl.depinstall_status=Installeren %1...
+
+en.depinstall_missing=%1 must be installed before setup can continue. Please install %1 and run Setup again.
+de.depinstall_missing=%1 muss installiert werden bevor das Setup fortfahren kann. Bitte installieren Sie %1 und starten Sie das Setup erneut.
+fr.depinstall_missing=%1 doit tre install avant l'installation peut continuer. S'il vous plat installer %1 et excutez nouveau le programme d'installation.
+nl.depinstall_missing=%1 moet worden genstalleerd vr de installatie kan worden voortgezet. Installeer %1 en voer Setup opnieuw uit.
+
+en.depinstall_error=An error occured while installing the dependencies. Please restart the computer and run the setup again or install the following dependencies manually:%n
+de.depinstall_error=Ein Fehler ist whrend der Installation der Abghngigkeiten aufgetreten. Bitte starten Sie den Computer neu und fhren Sie das Setup erneut aus oder installieren Sie die folgenden Abhngigkeiten per Hand:%n
+fr.depinstall_error=Une erreur est survenue lors de l'installation des dpendances . S'il vous plat redmarrer l'ordinateur et excuter nouveau le programme d'installation ou installer les dpendances suivantes manuellement:%n
+nl.depinstall_error=Er is een fout opgetreden tijdens het installeren van de afhankelijkheden. Gelieve de computer opnieuw op en voer de installatie opnieuw uit of de volgende afhankelijkheden handmatig installeren:%n
+
+en.isxdl_langfile=
+de.isxdl_langfile=german.ini
+fr.isxdl_langfile=french3.ini
+nl.isxdl_langfile=dutch.ini
+
+[Files]
+Source: "scripts\isxdl\german.ini"; Flags: dontcopy
+Source: "scripts\isxdl\french3.ini"; Flags: dontcopy
+Source: "scripts\isxdl\dutch.ini"; Flags: dontcopy
+
+[Code]
+type
+ TProduct = record
+ File: String;
+ Title: String;
+ Parameters: String;
+ ForceSuccess : boolean;
+ InstallClean : boolean;
+ MustRebootAfter : boolean;
+ end;
+
+ InstallResult = (InstallSuccessful, InstallRebootRequired, InstallError);
+
+var
+ installMemo, downloadMemo, downloadMessage: string;
+ products: array of TProduct;
+ delayedReboot, isForcedX86: boolean;
+ DependencyPage: TOutputProgressWizardPage;
+
+
+procedure AddProduct(filename, parameters, title, size, url: string; forceSuccess, installClean, mustRebootAfter : boolean);
+var
+ path: string;
+ i: Integer;
+begin
+ installMemo := installMemo + '%1' + title + #13;
+
+ path := ExpandConstant('{src}{\}') + CustomMessage('DependenciesDir') + '\' + filename;
+ if not FileExists(path) then begin
+ path := ExpandConstant('{tmp}{\}') + filename;
+
+ if not FileExists(path) then begin
+ isxdl_AddFile(url, path);
+
+ downloadMemo := downloadMemo + '%1' + title + #13;
+ downloadMessage := downloadMessage + ' ' + title + ' (' + size + ')' + #13;
+ end;
+ end;
+
+ i := GetArrayLength(products);
+ SetArrayLength(products, i + 1);
+ products[i].File := path;
+ products[i].Title := title;
+ products[i].Parameters := parameters;
+ products[i].ForceSuccess := forceSuccess;
+ products[i].InstallClean := installClean;
+ products[i].MustRebootAfter := mustRebootAfter;
+end;
+
+function SmartExec(product : TProduct; var resultcode : Integer): boolean;
+begin
+ if (LowerCase(Copy(product.File, Length(product.File) - 2, 3)) = 'exe') then begin
+ Result := Exec(product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode);
+ end else begin
+ Result := ShellExec('', product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode);
+ end;
+end;
+
+function PendingReboot: boolean;
+var names: String;
+begin
+ if (RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations', names)) then begin
+ Result := true;
+ end else if ((RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'SetupExecute', names)) and (names <> '')) then begin
+ Result := true;
+ end else begin
+ Result := false;
+ end;
+end;
+
+function InstallProducts: InstallResult;
+var
+ resultCode, i, productCount, finishCount: Integer;
+begin
+ Result := InstallSuccessful;
+ productCount := GetArrayLength(products);
+
+ if productCount > 0 then begin
+ DependencyPage := CreateOutputProgressPage(CustomMessage('depinstall_title'), CustomMessage('depinstall_description'));
+ DependencyPage.Show;
+
+ for i := 0 to productCount - 1 do begin
+ if (products[i].InstallClean and (delayedReboot or PendingReboot())) then begin
+ Result := InstallRebootRequired;
+ break;
+ end;
+
+ DependencyPage.SetText(FmtMessage(CustomMessage('depinstall_status'), [products[i].Title]), '');
+ DependencyPage.SetProgress(i, productCount);
+
+ if SmartExec(products[i], resultCode) then begin
+ //setup executed; resultCode contains the exit code
+ if (products[i].MustRebootAfter) then begin
+ //delay reboot after install if we installed the last dependency anyways
+ if (i = productCount - 1) then begin
+ delayedReboot := true;
+ end else begin
+ Result := InstallRebootRequired;
+ end;
+ break;
+ end else if (resultCode = 0) or (products[i].ForceSuccess) then begin
+ finishCount := finishCount + 1;
+ end else if (resultCode = 3010) then begin
+ //Windows Installer resultCode 3010: ERROR_SUCCESS_REBOOT_REQUIRED
+ delayedReboot := true;
+ finishCount := finishCount + 1;
+ end else begin
+ Result := InstallError;
+ break;
+ end;
+ end else begin
+ Result := InstallError;
+ break;
+ end;
+ end;
+
+ //only leave not installed products for error message
+ for i := 0 to productCount - finishCount - 1 do begin
+ products[i] := products[i+finishCount];
+ end;
+ SetArrayLength(products, productCount - finishCount);
+
+ DependencyPage.Hide;
+ end;
+end;
+
+function PrepareToInstall(var NeedsRestart: boolean): String;
+var
+ i: Integer;
+ s: string;
+begin
+ delayedReboot := false;
+
+ case InstallProducts() of
+ InstallError: begin
+ s := CustomMessage('depinstall_error');
+
+ for i := 0 to GetArrayLength(products) - 1 do begin
+ s := s + #13 + ' ' + products[i].Title;
+ end;
+
+ Result := s;
+ end;
+ InstallRebootRequired: begin
+ Result := products[0].Title;
+ NeedsRestart := true;
+
+ //write into the registry that the installer needs to be executed again after restart
+ RegWriteStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'InstallBootstrap', ExpandConstant('{srcexe}'));
+ end;
+ end;
+end;
+
+function NeedRestart : boolean;
+begin
+ Result := delayedReboot;
+end;
+
+function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
+var
+ s: string;
+begin
+ if downloadMemo <> '' then
+ s := s + CustomMessage('depdownload_memo_title') + ':' + NewLine + FmtMessage(downloadMemo, [Space]) + NewLine;
+ if installMemo <> '' then
+ s := s + CustomMessage('depinstall_memo_title') + ':' + NewLine + FmtMessage(installMemo, [Space]) + NewLine;
+
+ s := s + MemoDirInfo + NewLine + NewLine + MemoGroupInfo
+
+ if MemoTasksInfo <> '' then
+ s := s + NewLine + NewLine + MemoTasksInfo;
+
+ Result := s
+end;
+
+function NextButtonClick(CurPageID: Integer): boolean;
+begin
+ Result := true;
+
+ if CurPageID = wpReady then begin
+ if downloadMemo <> '' then begin
+ //change isxdl language only if it is not english because isxdl default language is already english
+ if (ActiveLanguage() <> 'en') then begin
+ ExtractTemporaryFile(CustomMessage('isxdl_langfile'));
+ isxdl_SetOption('language', ExpandConstant('{tmp}{\}') + CustomMessage('isxdl_langfile'));
+ end;
+ //isxdl_SetOption('title', FmtMessage(SetupMessage(msgSetupWindowTitle), [CustomMessage('appname')]));
+
+ if SuppressibleMsgBox(FmtMessage(CustomMessage('depdownload_msg'), [downloadMessage]), mbConfirmation, MB_YESNO, IDYES) = IDNO then
+ Result := false
+ else if isxdl_DownloadFiles(StrToInt(ExpandConstant('{wizardhwnd}'))) = 0 then
+ Result := false;
+ end;
+ end;
+end;
+
+function IsX86: boolean;
+begin
+ Result := isForcedX86 or (ProcessorArchitecture = paX86) or (ProcessorArchitecture = paUnknown);
+end;
+
+function IsX64: boolean;
+begin
+ Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paX64);
+end;
+
+function IsIA64: boolean;
+begin
+ Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paIA64);
+end;
+
+function GetString(x86, x64, ia64: String): String;
+begin
+ if IsX64() and (x64 <> '') then begin
+ Result := x64;
+ end else if IsIA64() and (ia64 <> '') then begin
+ Result := ia64;
+ end else begin
+ Result := x86;
+ end;
+end;
+
+function GetArchitectureString(): String;
+begin
+ if IsX64() then begin
+ Result := '_x64';
+ end else if IsIA64() then begin
+ Result := '_ia64';
+ end else begin
+ Result := '';
+ end;
+end;
+
+procedure SetForceX86(value: boolean);
+begin
+ isForcedX86 := value;
+end;
+
+[Setup]
diff --git a/installer/innosetup/scripts/products/directxruntime.iss b/Greenshot/releases/innosetup/scripts/products/directxruntime.iss
similarity index 92%
rename from installer/innosetup/scripts/products/directxruntime.iss
rename to Greenshot/releases/innosetup/scripts/products/directxruntime.iss
index 845699f1c..7e8811283 100644
--- a/installer/innosetup/scripts/products/directxruntime.iss
+++ b/Greenshot/releases/innosetup/scripts/products/directxruntime.iss
@@ -5,7 +5,8 @@
en.directxruntime_title=DirectX End-User Runtime
de.directxruntime_title=DirectX Endbenutzer Runtime
-directxruntime_size=1 MB - 95.6 MB
+en.directxruntime_size=1 MB - 95.6 MB
+de.directxruntime_size=1 MB - 95,6 MB
[Files]
;includes dxwebsetup.exe in setup executable so that we don't need to download it
diff --git a/installer/innosetup/scripts/products/dotnetfx11.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11.iss
similarity index 93%
rename from installer/innosetup/scripts/products/dotnetfx11.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11.iss
index 6f7732bb7..955469b6a 100644
--- a/installer/innosetup/scripts/products/dotnetfx11.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx11.iss
@@ -5,7 +5,8 @@
[CustomMessages]
dotnetfx11_title=.NET Framework 1.1
-dotnetfx11_size=23.1 MB
+en.dotnetfx11_size=23.1 MB
+de.dotnetfx11_size=23,1 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/dotnetfx11lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11lp.iss
similarity index 64%
rename from installer/innosetup/scripts/products/dotnetfx11lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11lp.iss
index 0cf4d085f..a2415cfa2 100644
--- a/installer/innosetup/scripts/products/dotnetfx11lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx11lp.iss
@@ -1,16 +1,18 @@
[CustomMessages]
de.dotnetfx11lp_title=.NET Framework 1.1 Sprachpaket: Deutsch
-dotnetfx11lp_size=1.4 MB
+de.dotnetfx11lp_size=1,4 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx11lp_lcid=1031
-dotnetfx11lp_url=
de.dotnetfx11lp_url=http://download.microsoft.com/download/6/8/2/6821e687-526a-4ef8-9a67-9a402ec5ac9e/langpack.exe
[Code]
procedure dotnetfx11lp();
begin
- if (CustomMessage('dotnetfx11lp_url') <> '') then begin
- if (IsX86() and not netfxinstalled(NetFx11, CustomMessage('lcid'))) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (IsX86() and not netfxinstalled(NetFx11, CustomMessage('dotnetfx11lp_lcid'))) then
AddProduct('dotnetfx11' + ActiveLanguage() + '.exe',
'/q:a /c:"inst.exe /qb /l"',
CustomMessage('dotnetfx11lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx11sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11sp1.iss
similarity index 95%
rename from installer/innosetup/scripts/products/dotnetfx11sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11sp1.iss
index 0b514f811..f7197d67e 100644
--- a/installer/innosetup/scripts/products/dotnetfx11sp1.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx11sp1.iss
@@ -5,7 +5,8 @@
[CustomMessages]
dotnetfx11sp1_title=.NET Framework 1.1 Service Pack 1
-dotnetfx11sp1_size=10.5 MB
+en.dotnetfx11sp1_size=10.5 MB
+de.dotnetfx11sp1_size=10,5 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/dotnetfx20.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx20.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx20lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20lp.iss
similarity index 77%
rename from installer/innosetup/scripts/products/dotnetfx20lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20lp.iss
index 6a08d0d44..fb13e4103 100644
--- a/installer/innosetup/scripts/products/dotnetfx20lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx20lp.iss
@@ -3,9 +3,11 @@
[CustomMessages]
de.dotnetfx20lp_title=.NET Framework 2.0 Sprachpaket: Deutsch
-dotnetfx20lp_size=1.8 MB
+de.dotnetfx20lp_size=1,8 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx20lp_lcid=1031
-dotnetfx20lp_url=
de.dotnetfx20lp_url=http://download.microsoft.com/download/2/9/7/29768238-56c3-4ea6-abba-4c5246f2bc81/langpack.exe
de.dotnetfx20lp_url_x64=http://download.microsoft.com/download/2/e/f/2ef250ba-a868-4074-a4c9-249004866f87/langpack.exe
de.dotnetfx20lp_url_ia64=http://download.microsoft.com/download/8/9/8/898c5670-5e74-41c4-82fc-68dd837af627/langpack.exe
@@ -13,8 +15,8 @@ de.dotnetfx20lp_url_ia64=http://download.microsoft.com/download/8/9/8/898c5670-5
[Code]
procedure dotnetfx20lp();
begin
- if (CustomMessage('dotnetfx20lp_url') <> '') then begin
- if (not netfxinstalled(NetFx20, CustomMessage('lcid'))) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (not netfxinstalled(NetFx20, CustomMessage('dotnetfx20lp_lcid'))) then
AddProduct('dotnetfx20' + GetArchitectureString() + '_' + ActiveLanguage() + '.exe',
'/passive /norestart /lang:ENU',
CustomMessage('dotnetfx20lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1.iss
similarity index 92%
rename from installer/innosetup/scripts/products/dotnetfx20sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1.iss
index 57ff4ea1e..6ee4ef540 100644
--- a/installer/innosetup/scripts/products/dotnetfx20sp1.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1.iss
@@ -5,7 +5,8 @@
[CustomMessages]
dotnetfx20sp1_title=.NET Framework 2.0 Service Pack 1
-dotnetfx20sp1_size=23.6 MB
+en.dotnetfx20sp1_size=23.6 MB
+de.dotnetfx20sp1_size=23,6 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp1lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1lp.iss
similarity index 77%
rename from installer/innosetup/scripts/products/dotnetfx20sp1lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1lp.iss
index 0e7c6f324..67111c59f 100644
--- a/installer/innosetup/scripts/products/dotnetfx20sp1lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1lp.iss
@@ -3,9 +3,11 @@
[CustomMessages]
de.dotnetfx20sp1lp_title=.NET Framework 2.0 SP1 Sprachpaket: Deutsch
-dotnetfx20sp1lp_size=3.4 MB
+de.dotnetfx20sp1lp_size=3,4 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx20sp1lp_lcid=1031
-dotnetfx20sp1lp_url=
de.dotnetfx20sp1lp_url=http://download.microsoft.com/download/8/a/a/8aab7e6a-5e58-4e83-be99-f5fb49fe811e/NetFx20SP1_x86de.exe
de.dotnetfx20sp1lp_url_x64=http://download.microsoft.com/download/1/4/2/1425872f-c564-4ab2-8c9e-344afdaecd44/NetFx20SP1_x64de.exe
de.dotnetfx20sp1lp_url_ia64=http://download.microsoft.com/download/a/0/b/a0bef431-19d8-433c-9f42-6e2824a8cb90/NetFx20SP1_ia64de.exe
@@ -13,8 +15,8 @@ de.dotnetfx20sp1lp_url_ia64=http://download.microsoft.com/download/a/0/b/a0bef43
[Code]
procedure dotnetfx20sp1lp();
begin
- if (CustomMessage('dotnetfx20sp1lp_url') <> '') then begin
- if (netfxspversion(NetFx20, CustomMessage('lcid')) < 1) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (netfxspversion(NetFx20, CustomMessage('dotnetfx20sp1lp_lcid')) < 1) then
AddProduct('dotnetfx20sp1' + GetArchitectureString() + '_' + ActiveLanguage() + '.exe',
'/passive /norestart /lang:ENU',
CustomMessage('dotnetfx20sp1lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp2.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2.iss
similarity index 90%
rename from installer/innosetup/scripts/products/dotnetfx20sp2.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2.iss
index 58703d24a..0a9e48e5a 100644
--- a/installer/innosetup/scripts/products/dotnetfx20sp2.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2.iss
@@ -3,7 +3,8 @@
[CustomMessages]
dotnetfx20sp2_title=.NET Framework 2.0 Service Pack 2
-dotnetfx20sp2_size=24 MB - 52 MB
+en.dotnetfx20sp2_size=24 MB - 52 MB
+de.dotnetfx20sp2_size=24 MB - 52 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp2lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2lp.iss
similarity index 77%
rename from installer/innosetup/scripts/products/dotnetfx20sp2lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2lp.iss
index 616199aad..b8aad1565 100644
--- a/installer/innosetup/scripts/products/dotnetfx20sp2lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2lp.iss
@@ -3,9 +3,11 @@
[CustomMessages]
de.dotnetfx20sp2lp_title=.NET Framework 2.0 SP2 Sprachpaket: Deutsch
-dotnetfx20sp2lp_size=3.4 MB
+de.dotnetfx20sp2lp_size=3,4 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx20sp2lp_lcid=1031
-dotnetfx20sp2lp_url=
de.dotnetfx20sp2lp_url=http://download.microsoft.com/download/0/b/1/0b175c8e-34bd-46c0-bfcd-af8d33770c58/netfx20sp2_x86de.exe
de.dotnetfx20sp2lp_url_x64=http://download.microsoft.com/download/4/e/c/4ec67a11-879d-4550-9c25-fd9ab4261b46/netfx20sp2_x64de.exe
de.dotnetfx20sp2lp_url_ia64=http://download.microsoft.com/download/a/3/3/a3349a2d-36e4-4797-8297-4394e6fbd677/NetFx20SP2_ia64de.exe
@@ -13,8 +15,8 @@ de.dotnetfx20sp2lp_url_ia64=http://download.microsoft.com/download/a/3/3/a3349a2
[Code]
procedure dotnetfx20sp2lp();
begin
- if (CustomMessage('dotnetfx20sp2lp_url') <> '') then begin
- if (netfxspversion(NetFx20, CustomMessage('lcid')) < 2) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (netfxspversion(NetFx20, CustomMessage('dotnetfx20sp2lp_lcid')) < 2) then
AddProduct('dotnetfx20sp2' + GetArchitectureString() + '_' + ActiveLanguage() + '.exe',
'/lang:enu /passive /norestart"',
CustomMessage('dotnetfx20sp2lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx35.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx35.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx35lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35lp.iss
similarity index 65%
rename from installer/innosetup/scripts/products/dotnetfx35lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35lp.iss
index 6afe4580d..818e7eebb 100644
--- a/installer/innosetup/scripts/products/dotnetfx35lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx35lp.iss
@@ -1,16 +1,18 @@
[CustomMessages]
de.dotnetfx35lp_title=.NET Framework 3.5 Sprachpaket: Deutsch
-dotnetfx35lp_size=13 MB - 51 MB
+de.dotnetfx35lp_size=13 MB - 51 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx35lp_lcid=1031
-dotnetfx35lp_url=
de.dotnetfx35lp_url=http://download.microsoft.com/download/d/1/e/d1e617c3-c7f4-467e-a7de-af832450efd3/dotnetfx35langpack_x86de.exe
[Code]
procedure dotnetfx35lp();
begin
- if (CustomMessage('dotnetfx35lp_url') <> '') then begin
- if (not netfxinstalled(NetFx35, CustomMessage('lcid'))) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (not netfxinstalled(NetFx35, CustomMessage('dotnetfx35lp_lcid'))) then
AddProduct('dotnetfx35_' + ActiveLanguage() + '.exe',
'/lang:enu /passive /norestart',
CustomMessage('dotnetfx35lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx35sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1.iss
similarity index 90%
rename from installer/innosetup/scripts/products/dotnetfx35sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1.iss
index f7b564ef8..5eee9f7c7 100644
--- a/installer/innosetup/scripts/products/dotnetfx35sp1.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1.iss
@@ -6,7 +6,8 @@
[CustomMessages]
dotnetfx35sp1_title=.NET Framework 3.5 Service Pack 1
-dotnetfx35sp1_size=3 MB - 232 MB
+en.dotnetfx35sp1_size=3 MB - 232 MB
+de.dotnetfx35sp1_size=3 MB - 232 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/dotnetfx35sp1lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1lp.iss
similarity index 66%
rename from installer/innosetup/scripts/products/dotnetfx35sp1lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1lp.iss
index de6eb4ce1..38319504e 100644
--- a/installer/innosetup/scripts/products/dotnetfx35sp1lp.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1lp.iss
@@ -1,16 +1,18 @@
[CustomMessages]
de.dotnetfx35sp1lp_title=.NET Framework 3.5 SP1 Sprachpaket: Deutsch
-dotnetfx35sp1lp_size=22 MB - 98 MB
+de.dotnetfx35sp1lp_size=22 MB - 98 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+de.dotnetfx35sp1lp_lcid=1031
-dotnetfx35sp1lp_url=
de.dotnetfx35sp1lp_url=http://download.microsoft.com/download/d/7/2/d728b7b9-454b-4b57-8270-45dac441b0ec/dotnetfx35langpack_x86de.exe
[Code]
procedure dotnetfx35sp1lp();
begin
- if (CustomMessage('dotnetfx35sp1lp_url') <> '') then begin
- if (netfxspversion(NetFx35, CustomMessage('lcid')) < 1) then
+ if (ActiveLanguage() <> 'en') then begin
+ if (netfxspversion(NetFx35, CustomMessage('dotnetfx35sp1lp_lcid')) < 1) then
AddProduct('dotnetfx35sp1_' + ActiveLanguage() + '.exe',
'/lang:enu /passive /norestart',
CustomMessage('dotnetfx35sp1lp_title'),
diff --git a/installer/innosetup/scripts/products/dotnetfx40client.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx40client.iss
similarity index 83%
rename from installer/innosetup/scripts/products/dotnetfx40client.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx40client.iss
index 6e3ad4d59..db6441cb4 100644
--- a/installer/innosetup/scripts/products/dotnetfx40client.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx40client.iss
@@ -9,6 +9,10 @@ dotnetfx40client_title=.NET Framework 4.0 Client
dotnetfx40client_size=3 MB - 197 MB
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+en.dotnetfx40client_lcid=
+de.dotnetfx40client_lcid=/lcid 1031
+
[Code]
const
dotnetfx40client_url = 'http://download.microsoft.com/download/7/B/6/7B629E05-399A-4A92-B5BC-484C74B5124B/dotNetFx40_Client_setup.exe';
@@ -17,7 +21,7 @@ procedure dotnetfx40client();
begin
if (not netfxinstalled(NetFx40Client, '')) then
AddProduct('dotNetFx40_Client_setup.exe',
- '/lcid ' + CustomMessage('lcid') + ' /passive /norestart',
+ CustomMessage('dotnetfx40client_lcid') + ' /passive /norestart',
CustomMessage('dotnetfx40client_title'),
CustomMessage('dotnetfx40client_size'),
dotnetfx40client_url,
diff --git a/installer/innosetup/scripts/products/dotnetfx40full.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx40full.iss
similarity index 83%
rename from installer/innosetup/scripts/products/dotnetfx40full.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx40full.iss
index 2a8d79e2b..917bc2c5b 100644
--- a/installer/innosetup/scripts/products/dotnetfx40full.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx40full.iss
@@ -9,6 +9,10 @@ dotnetfx40full_title=.NET Framework 4.0 Full
dotnetfx40full_size=3 MB - 197 MB
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+en.dotnetfx40full_lcid=
+de.dotnetfx40full_lcid=/lcid 1031
+
[Code]
const
dotnetfx40full_url = 'http://download.microsoft.com/download/1/B/E/1BE39E79-7E39-46A3-96FF-047F95396215/dotNetFx40_Full_setup.exe';
@@ -17,7 +21,7 @@ procedure dotnetfx40full();
begin
if (not netfxinstalled(NetFx40Full, '')) then
AddProduct('dotNetFx40_Full_setup.exe',
- '/lcid ' + CustomMessage('lcid') + ' /passive /norestart',
+ CustomMessage('dotnetfx40full_lcid') + ' /passive /norestart',
CustomMessage('dotnetfx40full_title'),
CustomMessage('dotnetfx40full_size'),
dotnetfx40full_url,
diff --git a/Greenshot/releases/innosetup/scripts/products/dotnetfx46.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx46.iss
new file mode 100644
index 000000000..25ff2029a
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfx46.iss
@@ -0,0 +1,29 @@
+; requires Windows 10, Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2
+; WARNING: express setup (downloads and installs the components depending on your OS) if you want to deploy it on cd or network download the full bootsrapper on website below
+; https://www.microsoft.com/en-US/download/details.aspx?id=49982
+
+[CustomMessages]
+dotnetfx46_title=.NET Framework 4.6.1
+
+dotnetfx46_size=1 MB - 65 MB
+
+;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
+en.dotnetfx46_lcid=
+de.dotnetfx46_lcid=/lcid 1031
+
+[Code]
+const
+ dotnetfx461_url = 'http://download.microsoft.com/download/3/5/9/35980F81-60F4-4DE3-88FC-8F962B97253B/NDP461-KB3102438-Web.exe';
+
+procedure dotnetfx46(minVersion: integer);
+begin
+ if (not netfxinstalled(NetFx4x, '') or (netfxspversion(NetFx4x, '') < minVersion)) then
+ AddProduct('dotnetfx46.exe',
+ CustomMessage('dotnetfx46_lcid') + ' /passive /norestart',
+ CustomMessage('dotnetfx46_title'),
+ CustomMessage('dotnetfx46_size'),
+ dotnetfx461_url,
+ false, false, false);
+end;
+
+[Setup]
diff --git a/installer/innosetup/scripts/products/dotnetfxversion.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfxversion.iss
similarity index 86%
rename from installer/innosetup/scripts/products/dotnetfxversion.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfxversion.iss
index 1e7b80ed3..613fdf19a 100644
--- a/installer/innosetup/scripts/products/dotnetfxversion.iss
+++ b/Greenshot/releases/innosetup/scripts/products/dotnetfxversion.iss
@@ -50,7 +50,7 @@ begin
case version of
NetFx10:
- // not supported
+ //not supported
regVersion := -1;
NetFx11:
if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v1.1.4322' + lcid, 'SP', regVersion)) then
@@ -72,15 +72,7 @@ begin
regVersion := -1;
NetFx4x:
if (RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Release', regVersion)) then begin
- if (regVersion >= 528040) then
- regVersion := 80 // 4.8+
- else if (regVersion >= 461808) then
- regVersion := 72 // 4.7.2+
- else if (regVersion >= 461308) then
- regVersion := 71 // 4.7.1+
- else if (regVersion >= 460798) then
- regVersion := 70 // 4.7+
- else if (regVersion >= 394802) then
+ if (regVersion >= 394747) then
regVersion := 62 // 4.6.2+
else if (regVersion >= 394254) then
regVersion := 61 // 4.6.1+
@@ -91,7 +83,7 @@ begin
else if (regVersion >= 378675) then
regVersion := 51 // 4.5.1+
else if (regVersion >= 378389) then
- regVersion := 50 // 4.5+
+ regVersion := 50 // 4.5.0+
else
regVersion := -1;
end;
diff --git a/installer/innosetup/scripts/products/fileversion.iss b/Greenshot/releases/innosetup/scripts/products/fileversion.iss
similarity index 100%
rename from installer/innosetup/scripts/products/fileversion.iss
rename to Greenshot/releases/innosetup/scripts/products/fileversion.iss
diff --git a/installer/innosetup/scripts/products/ie6.iss b/Greenshot/releases/innosetup/scripts/products/ie6.iss
similarity index 90%
rename from installer/innosetup/scripts/products/ie6.iss
rename to Greenshot/releases/innosetup/scripts/products/ie6.iss
index 6dc872541..954940b7e 100644
--- a/installer/innosetup/scripts/products/ie6.iss
+++ b/Greenshot/releases/innosetup/scripts/products/ie6.iss
@@ -5,7 +5,8 @@
[CustomMessages]
ie6_title=Internet Explorer 6
-ie6_size=1 MB - 77.5 MB
+en.ie6_size=1 MB - 77.5 MB
+de.ie6_size=1 MB - 77,5 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/iis.iss b/Greenshot/releases/innosetup/scripts/products/iis.iss
similarity index 100%
rename from installer/innosetup/scripts/products/iis.iss
rename to Greenshot/releases/innosetup/scripts/products/iis.iss
diff --git a/installer/innosetup/scripts/products/jet4sp8.iss b/Greenshot/releases/innosetup/scripts/products/jet4sp8.iss
similarity index 82%
rename from installer/innosetup/scripts/products/jet4sp8.iss
rename to Greenshot/releases/innosetup/scripts/products/jet4sp8.iss
index 480dc6cd0..5b76e5ab8 100644
--- a/installer/innosetup/scripts/products/jet4sp8.iss
+++ b/Greenshot/releases/innosetup/scripts/products/jet4sp8.iss
@@ -3,7 +3,8 @@
[CustomMessages]
jet4sp8_title=Jet 4
-jet4sp8_size=3.7 MB
+en.jet4sp8_size=3.7 MB
+de.jet4sp8_size=3,7 MB
[Code]
const
@@ -11,7 +12,7 @@ const
procedure jet4sp8(minVersion: string);
begin
- // check for Jet4 Service Pack 8 installation
+ //check for Jet4 Service Pack 8 installation
if (compareversion(fileversion(ExpandConstant('{sys}{\}msjet40.dll')), minVersion) < 0) then
AddProduct('jet4sp8.exe',
'/q:a /c:"install /qb /l"',
diff --git a/installer/innosetup/scripts/products/kb835732.iss b/Greenshot/releases/innosetup/scripts/products/kb835732.iss
similarity index 92%
rename from installer/innosetup/scripts/products/kb835732.iss
rename to Greenshot/releases/innosetup/scripts/products/kb835732.iss
index 5b69cd1b4..13a0a183d 100644
--- a/installer/innosetup/scripts/products/kb835732.iss
+++ b/Greenshot/releases/innosetup/scripts/products/kb835732.iss
@@ -6,7 +6,8 @@
en.kb835732_title=Windows 2000 Security Update (KB835732)
de.kb835732_title=Windows 2000 Sicherheitsupdate (KB835732)
-kb835732_size=6.8 MB
+en.kb835732_size=6.8 MB
+de.kb835732_size=6,8 MB
[Code]
const
diff --git a/Greenshot/releases/innosetup/scripts/products/kb886903.iss b/Greenshot/releases/innosetup/scripts/products/kb886903.iss
new file mode 100644
index 000000000..207973a10
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/kb886903.iss
@@ -0,0 +1,32 @@
+// WARNING: Windows Update is better because there are different versions for different OS
+// (optional) critical security hotfix for .NET Framework 1.1 Service Pack 1 on Windows 2000/XP/2003
+// http://support.microsoft.com/default.aspx?scid=kb;en-us;886903
+// http://www.microsoft.com/downloads/details.aspx?familyid=8EC6FB8A-29EB-49CF-9DBC-1A0DC2273FF9
+
+[CustomMessages]
+en.kb886903_title=.NET Framework 1.1 SP1 Security Update (KB886903)
+de.kb886903_title=.NET Framework 1.1 SP1 Sicherheitsupdate (KB886903)
+nl.kb886903_title=.NET Framework 1.1 SP1 Veiligheidsupdate (KB886903)
+
+kb886903_size=1.5 MB
+
+
+[Code]
+const
+ kb886903_url = 'http://download.microsoft.com/download/e/1/4/e14c0c02-591b-4696-8552-eb710c26a3cd/NDP1.1sp1-KB886903-X86.exe';
+
+procedure kb886903();
+var
+ version: cardinal;
+begin
+ RegQueryDWordValue(HKLM, 'Software\Microsoft\NET Framework Setup\NDP\v1.1.4322', 'SP', version);
+ if version = 1 then begin
+ RegQueryDWordValue(HKLM, 'Software\Microsoft\Updates\.NETFramework\1.1\M886903', 'Installed', version);
+ if version <> 1 then
+ AddProduct('kb886903.exe',
+ '/q',
+ CustomMessage('kb886903_title'),
+ CustomMessage('kb886903_size'),
+ kb886903_url);
+ end;
+end;
\ No newline at end of file
diff --git a/Greenshot/releases/innosetup/scripts/products/kb928366.iss b/Greenshot/releases/innosetup/scripts/products/kb928366.iss
new file mode 100644
index 000000000..127237f2a
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/kb928366.iss
@@ -0,0 +1,32 @@
+// WARNING: Windows Update is better because there are different versions for different OS
+// (optional) critical security hotfix for .NET Framework 1.1 Service Pack 1 on Windows 2000/XP
+// http://support.microsoft.com/?id=928366
+// http://www.microsoft.com/downloads/details.aspx?familyid=281FB2CD-C715-4F05-A01F-0455D2D9EBFB
+
+[CustomMessages]
+en.kb928366_title=.NET Framework 1.1 SP1 Security Update (KB928366)
+de.kb928366_title=.NET Framework 1.1 SP1 Sicherheitsupdate (KB928366)
+nl.kb928366_title=.NET Framework 1.1 SP1 Veiligheidsupdate (KB928366)
+
+kb928366_size=8.8 MB
+
+
+[Code]
+const
+ kb928366_url = 'http://download.microsoft.com/download/6/d/0/6d0e5797-91eb-401a-a61f-58b369302018/NDP1.1sp1-KB928366-X86.exe';
+
+procedure kb928366();
+var
+ version: cardinal;
+begin
+ RegQueryDWordValue(HKLM, 'Software\Microsoft\NET Framework Setup\NDP\v1.1.4322', 'SP', version);
+ if version = 1 then begin
+ RegQueryDWordValue(HKLM, 'Software\Microsoft\Updates\.NETFramework\1.1\M928366', 'Installed', version);
+ if version <> 1 then
+ AddProduct('kb928366.exe',
+ '/q',
+ CustomMessage('kb928366_title'),
+ CustomMessage('kb928366_size'),
+ kb928366_url);
+ end;
+end;
\ No newline at end of file
diff --git a/installer/innosetup/scripts/products/mdac28.iss b/Greenshot/releases/innosetup/scripts/products/mdac28.iss
similarity index 85%
rename from installer/innosetup/scripts/products/mdac28.iss
rename to Greenshot/releases/innosetup/scripts/products/mdac28.iss
index 8c5c021a6..63d5b88ba 100644
--- a/installer/innosetup/scripts/products/mdac28.iss
+++ b/Greenshot/releases/innosetup/scripts/products/mdac28.iss
@@ -1,7 +1,8 @@
[CustomMessages]
mdac28_title=Microsoft Data Access Components 2.8
-mdac28_size=5.4 MB
+en.mdac28_size=5.4 MB
+de.mdac28_size=5,4 MB
[Code]
const
@@ -11,7 +12,7 @@ procedure mdac28(minVersion: string);
var
version: string;
begin
- // check for MDAC installation
+ //check for MDAC installation
RegQueryStringValue(HKLM, 'Software\Microsoft\DataAccess', 'FullInstallVer', version);
if (compareversion(version, minVersion) < 0) then
AddProduct('mdac28.exe',
diff --git a/installer/innosetup/scripts/products/msi20.iss b/Greenshot/releases/innosetup/scripts/products/msi20.iss
similarity index 90%
rename from installer/innosetup/scripts/products/msi20.iss
rename to Greenshot/releases/innosetup/scripts/products/msi20.iss
index 208218594..e44f74b3d 100644
--- a/installer/innosetup/scripts/products/msi20.iss
+++ b/Greenshot/releases/innosetup/scripts/products/msi20.iss
@@ -1,7 +1,8 @@
[CustomMessages]
msi20_title=Windows Installer 2.0
-msi20_size=1.7 MB
+en.msi20_size=1.7 MB
+de.msi20_size=1,7 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/msi31.iss b/Greenshot/releases/innosetup/scripts/products/msi31.iss
similarity index 90%
rename from installer/innosetup/scripts/products/msi31.iss
rename to Greenshot/releases/innosetup/scripts/products/msi31.iss
index 6885e73ba..0ea175dd9 100644
--- a/installer/innosetup/scripts/products/msi31.iss
+++ b/Greenshot/releases/innosetup/scripts/products/msi31.iss
@@ -1,7 +1,8 @@
[CustomMessages]
msi31_title=Windows Installer 3.1
-msi31_size=2.5 MB
+en.msi31_size=2.5 MB
+de.msi31_size=2,5 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/msi45.iss b/Greenshot/releases/innosetup/scripts/products/msi45.iss
similarity index 86%
rename from installer/innosetup/scripts/products/msi45.iss
rename to Greenshot/releases/innosetup/scripts/products/msi45.iss
index c4fe0703a..e97de18a9 100644
--- a/installer/innosetup/scripts/products/msi45.iss
+++ b/Greenshot/releases/innosetup/scripts/products/msi45.iss
@@ -1,9 +1,14 @@
[CustomMessages]
msi45_title=Windows Installer 4.5
-msi45win60_size=1.7 MB
-msi45win52_size=3.0 MB
-msi45win51_size=3.2 MB
+en.msi45win60_size=1.7 MB
+de.msi45win60_size=1,7 MB
+
+en.msi45win52_size=3.0 MB
+de.msi45win52_size=3,0 MB
+
+en.msi45win51_size=3.2 MB
+de.msi45win51_size=3,2 MB
[Code]
const
diff --git a/Greenshot/releases/innosetup/scripts/products/msiproduct.iss b/Greenshot/releases/innosetup/scripts/products/msiproduct.iss
new file mode 100644
index 000000000..b5135c6fb
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/msiproduct.iss
@@ -0,0 +1,25 @@
+[Code]
+#IFDEF UNICODE
+ #DEFINE AW "W"
+#ELSE
+ #DEFINE AW "A"
+#ENDIF
+
+type
+ INSTALLSTATE = Longint;
+const
+ INSTALLSTATE_INVALIDARG = -2; // An invalid parameter was passed to the function.
+ INSTALLSTATE_UNKNOWN = -1; // The product is neither advertised or installed.
+ INSTALLSTATE_ADVERTISED = 1; // The product is advertised but not installed.
+ INSTALLSTATE_ABSENT = 2; // The product is installed for a different user.
+ INSTALLSTATE_DEFAULT = 5; // The product is installed for the current user.
+
+function MsiQueryProductState(szProduct: string): INSTALLSTATE;
+external 'MsiQueryProductState{#AW}@msi.dll stdcall';
+
+function msiproduct(const ProductID: string): boolean;
+begin
+ Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
+end;
+
+[Setup]
diff --git a/installer/innosetup/scripts/products/sql2005express.iss b/Greenshot/releases/innosetup/scripts/products/sql2005express.iss
similarity index 83%
rename from installer/innosetup/scripts/products/sql2005express.iss
rename to Greenshot/releases/innosetup/scripts/products/sql2005express.iss
index aef489e10..626aebeca 100644
--- a/installer/innosetup/scripts/products/sql2005express.iss
+++ b/Greenshot/releases/innosetup/scripts/products/sql2005express.iss
@@ -6,8 +6,11 @@
[CustomMessages]
sql2005express_title=SQL Server 2005 Express SP3
-sql2005express_size=38.1 MB
-sql2005express_size_x64=58.1 MB
+en.sql2005express_size=38.1 MB
+de.sql2005express_size=38,1 MB
+
+en.sql2005express_size_x64=58.1 MB
+de.sql2005express_size_x64=58,1 MB
[Code]
const
@@ -18,12 +21,12 @@ procedure sql2005express();
var
version: string;
begin
- // CHECK NOT FINISHED YET
- // RTM: 9.00.1399.06
- // Service Pack 1: 9.1.2047.00
- // Service Pack 2: 9.2.3042.00
+ //CHECK NOT FINISHED YET
+ //RTM: 9.00.1399.06
+ //Service Pack 1: 9.1.2047.00
+ //Service Pack 2: 9.2.3042.00
// TODO: Newer detection method required for SP3 and x64
- // Service Pack 3: 9.00.4035.00
+ //Service Pack 3: 9.00.4035.00
//RegQueryDWordValue(HKLM, 'Software\Microsoft\Microsoft SQL Server\90\DTS\Setup', 'Install', version);
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server\SQLEXPRESS\MSSQLServer\CurrentVersion', 'CurrentVersion', version);
if (version < '9.00.4035') then begin
diff --git a/installer/innosetup/scripts/products/sql2008express.iss b/Greenshot/releases/innosetup/scripts/products/sql2008express.iss
similarity index 91%
rename from installer/innosetup/scripts/products/sql2008express.iss
rename to Greenshot/releases/innosetup/scripts/products/sql2008express.iss
index 4708f8474..9e59b4a09 100644
--- a/installer/innosetup/scripts/products/sql2008express.iss
+++ b/Greenshot/releases/innosetup/scripts/products/sql2008express.iss
@@ -8,8 +8,11 @@
[CustomMessages]
sql2008expressr2_title=SQL Server 2008 Express R2
-sql2008expressr2_size=58.2 MB
-sql2008expressr2_size_x64=74.1 MB
+en.sql2008expressr2_size=58.2 MB
+de.sql2008expressr2_size=58,2 MB
+
+en.sql2008expressr2_size_x64=74.1 MB
+de.sql2008expressr2_size_x64=74,1 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/sqlcompact35sp2.iss b/Greenshot/releases/innosetup/scripts/products/sqlcompact35sp2.iss
similarity index 86%
rename from installer/innosetup/scripts/products/sqlcompact35sp2.iss
rename to Greenshot/releases/innosetup/scripts/products/sqlcompact35sp2.iss
index af5380632..b1b889def 100644
--- a/installer/innosetup/scripts/products/sqlcompact35sp2.iss
+++ b/Greenshot/releases/innosetup/scripts/products/sqlcompact35sp2.iss
@@ -1,7 +1,8 @@
[CustomMessages]
sqlcompact35sp2_title=SQL Server Compact 3.5 Service Pack 2
-sqlcompact35sp2_size=5.3 MB
+en.sqlcompact35sp2_size=5.3 MB
+de.sqlcompact35sp2_size=5,3 MB
[Code]
const
diff --git a/installer/innosetup/scripts/products/stringversion.iss b/Greenshot/releases/innosetup/scripts/products/stringversion.iss
similarity index 86%
rename from installer/innosetup/scripts/products/stringversion.iss
rename to Greenshot/releases/innosetup/scripts/products/stringversion.iss
index 4cb114f71..9379d1136 100644
--- a/installer/innosetup/scripts/products/stringversion.iss
+++ b/Greenshot/releases/innosetup/scripts/products/stringversion.iss
@@ -54,9 +54,9 @@ var
temp1, temp2: String;
begin
- temp1 := versionA;
- temp2 := versionB;
- Result := compareinnerversion(temp1, temp2);
+ temp1 := versionA;
+ temp2 := versionB;
+ Result := compareinnerversion(temp1, temp2);
end;
[Setup]
diff --git a/Greenshot/releases/innosetup/scripts/products/vcredist2005.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2005.iss
new file mode 100644
index 000000000..0425d9777
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2005.iss
@@ -0,0 +1,40 @@
+; requires Windows 2000 Service Pack 3, Windows 98, Windows 98 Second Edition, Windows ME, Windows Server 2003, Windows XP Service Pack 2
+; requires Windows Installer 3.0
+; http://www.microsoft.com/en-us/download/details.aspx?id=3387
+
+[CustomMessages]
+vcredist2005_title=Visual C++ 2005 Redistributable
+vcredist2005_title_x64=Visual C++ 2005 64-Bit Redistributable
+vcredist2005_title_ia64=Visual C++ 2005 Itanium Redistributable
+
+en.vcredist2005_size=2.6 MB
+de.vcredist2005_size=2,6 MB
+
+en.vcredist2005_size_x64=4.1 MB
+de.vcredist2005_size_x64=4,1 MB
+
+en.vcredist2005_size_ia64=8.8 MB
+de.vcredist2005_size_ia64=8,8 MB
+
+[Code]
+const
+ vcredist2005_url = 'http://download.microsoft.com/download/d/3/4/d342efa6-3266-4157-a2ec-5174867be706/vcredist_x86.exe';
+ vcredist2005_url_x64 = 'http://download.microsoft.com/download/9/1/4/914851c6-9141-443b-bdb4-8bad3a57bea9/vcredist_x64.exe';
+ vcredist2005_url_ia64 = 'http://download.microsoft.com/download/8/1/6/816129e4-7f2f-4ba6-b065-684223e2fe1e/vcredist_IA64.exe';
+
+ vcredist2005_productcode = '{A49F249F-0C91-497F-86DF-B2585E8E76B7}';
+ vcredist2005_productcode_x64 = '{6E8E85E8-CE4B-4FF5-91F7-04999C9FAE6A}';
+ vcredist2005_productcode_ia64 = '{03ED71EA-F531-4927-AABD-1C31BCE8E187}';
+
+procedure vcredist2005();
+begin
+ if (not msiproduct(GetString(vcredist2005_productcode, vcredist2005_productcode_x64, vcredist2005_productcode_ia64))) then
+ AddProduct('vcredist2005' + GetArchitectureString() + '.exe',
+ '/q:a /c:"install /qb /l',
+ CustomMessage('vcredist2005_title' + GetArchitectureString()),
+ CustomMessage('vcredist2005_size' + GetArchitectureString()),
+ GetString(vcredist2005_url, vcredist2005_url_x64, vcredist2005_url_ia64),
+ false, false, false);
+end;
+
+[Setup]
diff --git a/Greenshot/releases/innosetup/scripts/products/vcredist2008.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2008.iss
new file mode 100644
index 000000000..b29ba0b73
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2008.iss
@@ -0,0 +1,40 @@
+; requires Windows 2000 Service Pack 4, Windows Server 2003, Windows Vista, Windows XP
+; requires Windows Installer 3.0
+; http://www.microsoft.com/en-us/download/details.aspx?id=29
+
+[CustomMessages]
+vcredist2008_title=Visual C++ 2008 Redistributable
+vcredist2008_title_x64=Visual C++ 2008 64-Bit Redistributable
+vcredist2008_title_ia64=Visual C++ 2008 Itanium Redistributable
+
+en.vcredist2008_size=1.7 MB
+de.vcredist2008_size=1,7 MB
+
+en.vcredist2008_size_x64=2.3 MB
+de.vcredist2008_size_x64=2,3 MB
+
+en.vcredist2008_size_ia64=4.0 MB
+de.vcredist2008_size_ia64=4,0 MB
+
+[Code]
+const
+ vcredist2008_url = 'http://download.microsoft.com/download/1/1/1/1116b75a-9ec3-481a-a3c8-1777b5381140/vcredist_x86.exe';
+ vcredist2008_url_x64 = 'http://download.microsoft.com/download/d/2/4/d242c3fb-da5a-4542-ad66-f9661d0a8d19/vcredist_x64.exe';
+ vcredist2008_url_ia64 = 'http://download.microsoft.com/download/a/1/a/a1a4996b-ed78-4c2b-9589-8edd81b8df39/vcredist_IA64.exe';
+
+ vcredist2008_productcode = '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}';
+ vcredist2008_productcode_x64 = '{350AA351-21FA-3270-8B7A-835434E766AD}';
+ vcredist2008_productcode_ia64 = '{2B547B43-DB50-3139-9EBE-37D419E0F5FA}';
+
+procedure vcredist2008();
+begin
+ if (not msiproduct(GetString(vcredist2008_productcode, vcredist2008_productcode_x64, vcredist2008_productcode_ia64))) then
+ AddProduct('vcredist2008' + GetArchitectureString() + '.exe',
+ '/q',
+ CustomMessage('vcredist2008_title' + GetArchitectureString()),
+ CustomMessage('vcredist2008_size' + GetArchitectureString()),
+ GetString(vcredist2008_url, vcredist2008_url_x64, vcredist2008_url_ia64),
+ false, false, false);
+end;
+
+[Setup]
diff --git a/Greenshot/releases/innosetup/scripts/products/vcredist2010.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2010.iss
new file mode 100644
index 000000000..3d7e58a7e
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2010.iss
@@ -0,0 +1,39 @@
+; requires Windows 7, Windows Server 2003 R2 (32-Bit x86), Windows Server 2003 Service Pack 2, Windows Server 2008 R2, Windows Server 2008 Service Pack 2, Windows Vista Service Pack 2, Windows XP Service Pack 3
+; http://www.microsoft.com/en-us/download/details.aspx?id=5555
+
+[CustomMessages]
+vcredist2010_title=Visual C++ 2010 Redistributable
+vcredist2010_title_x64=Visual C++ 2010 64-Bit Redistributable
+vcredist2010_title_ia64=Visual C++ 2010 Itanium Redistributable
+
+en.vcredist2010_size=4.8 MB
+de.vcredist2010_size=4,8 MB
+
+en.vcredist2010_size_x64=5.5 MB
+de.vcredist2010_size_x64=5,5 MB
+
+en.vcredist2010_size_ia64=2.2 MB
+de.vcredist2010_size_ia64=2,2 MB
+
+[Code]
+const
+ vcredist2010_url = 'http://download.microsoft.com/download/5/B/C/5BC5DBB3-652D-4DCE-B14A-475AB85EEF6E/vcredist_x86.exe';
+ vcredist2010_url_x64 = 'http://download.microsoft.com/download/3/2/2/3224B87F-CFA0-4E70-BDA3-3DE650EFEBA5/vcredist_x64.exe';
+ vcredist2010_url_ia64 = 'http://download.microsoft.com/download/3/3/A/33A75193-2CBC-424E-A886-287551FF1EB5/vcredist_IA64.exe';
+
+ vcredist2010_productcode = '{196BB40D-1578-3D01-B289-BEFC77A11A1E}';
+ vcredist2010_productcode_x64 = '{DA5E371C-6333-3D8A-93A4-6FD5B20BCC6E}';
+ vcredist2010_productcode_ia64 = '{C1A35166-4301-38E9-BA67-02823AD72A1B}';
+
+procedure vcredist2010();
+begin
+ if (not msiproduct(GetString(vcredist2010_productcode, vcredist2010_productcode_x64, vcredist2010_productcode_ia64))) then
+ AddProduct('vcredist2010' + GetArchitectureString() + '.exe',
+ '/passive /norestart',
+ CustomMessage('vcredist2010_title' + GetArchitectureString()),
+ CustomMessage('vcredist2010_size' + GetArchitectureString()),
+ GetString(vcredist2010_url, vcredist2010_url_x64, vcredist2010_url_ia64),
+ false, false, false);
+end;
+
+[Setup]
diff --git a/Greenshot/releases/innosetup/scripts/products/vcredist2010sp1.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2010sp1.iss
new file mode 100644
index 000000000..91dc8ed7e
--- /dev/null
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2010sp1.iss
@@ -0,0 +1,41 @@
+; Requires Windows 7, Windows Server 2003 R2 (32-bit x86), Windows Server 2003 Service Pack 2, Windows Server 2008 R2, Windows Server 2008 Service Pack 2, Windows Vista Service Pack 2, Windows XP Service Pack 3
+; x86 download page: https://www.microsoft.com/en-us/download/details.aspx?id=8328
+; x64 download page: https://www.microsoft.com/en-us/download/details.aspx?id=13523
+; IA64 download page: https://www.microsoft.com/en-us/download/details.aspx?id=21051
+
+[CustomMessages]
+vcredist2010_title=Visual C++ 2010 SP1 Redistributable
+vcredist2010_title_x64=Visual C++ 2010 SP1 64-Bit Redistributable
+vcredist2010_title_ia64=Visual C++ 2010 SP1 Itanium Redistributable
+
+en.vcredist2010_size=4.8 MB
+de.vcredist2010_size=4,8 MB
+
+en.vcredist2010_size_x64=5.4 MB
+de.vcredist2010_size_x64=5,4 MB
+
+en.vcredist2010_size_ia64=2.2 MB
+de.vcredist2010_size_ia64=2,2 MB
+
+[Code]
+const
+ vcredist2010_url_x86 = 'http://download.microsoft.com/download/C/6/D/C6D0FD4E-9E53-4897-9B91-836EBA2AACD3/vcredist_x86.exe';
+ vcredist2010_url_x64 = 'http://download.microsoft.com/download/A/8/0/A80747C3-41BD-45DF-B505-E9710D2744E0/vcredist_x64.exe';
+ vcredist2010_url_ia64 = 'http://download.microsoft.com/download/7/7/3/77332C03-CC6C-45E5-A7B6-E02504B93847/vcredist_IA64.exe';
+
+ vcredist2010_productcode_x86 = '{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}';
+ vcredist2010_productcode_x64 = '{1D8E6291-B0D5-35EC-8441-6616F567A0F7}';
+ vcredist2010_productcode_ia64 = '{88C73C1C-2DE5-3B01-AFB8-B46EF4AB41CD}';
+
+procedure vcredist2010();
+begin
+ if (not msiproduct(GetString(vcredist2010_productcode_x86, vcredist2010_productcode_x64, vcredist2010_productcode_ia64))) then
+ AddProduct('vcredist2010' + GetArchitectureString() + '.exe',
+ '/passive /norestart',
+ CustomMessage('vcredist2010_title' + GetArchitectureString()),
+ CustomMessage('vcredist2010_size' + GetArchitectureString()),
+ GetString(vcredist2010_url_x86, vcredist2010_url_x64, vcredist2010_url_ia64),
+ false, false, false);
+end;
+
+[Setup]
diff --git a/installer/innosetup/scripts/products/vcredist2012.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2012.iss
similarity index 72%
rename from installer/innosetup/scripts/products/vcredist2012.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2012.iss
index 3d5a21bee..9f2ea00da 100644
--- a/installer/innosetup/scripts/products/vcredist2012.iss
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2012.iss
@@ -5,21 +5,24 @@
vcredist2012_title=Visual C++ 2012 Redistributable
vcredist2012_title_x64=Visual C++ 2012 64-Bit Redistributable
-vcredist2012_size=6.3 MB
-vcredist2012_size_x64=6.9 MB
+en.vcredist2012_size=6.3 MB
+de.vcredist2012_size=6,3 MB
+
+en.vcredist2012_size_x64=6.4 MB
+de.vcredist2012_size_x64=6,4 MB
[Code]
const
vcredist2012_url = 'http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe';
vcredist2012_url_x64 = 'http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe';
- vcredist2012_upgradecode = '{4121ED58-4BD9-3E7B-A8B5-9F8BAAE045B7}';
- vcredist2012_upgradecode_x64 = '{EFA6AFA1-738E-3E00-8101-FD03B86B29D1}';
+ vcredist2012_productcode = '{BD95A8CD-1D9F-35AD-981A-3E7925026EBB}';
+ vcredist2012_productcode_x64 = '{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}';
-procedure vcredist2012(minVersion: string);
+procedure vcredist2012();
begin
if (not IsIA64()) then begin
- if (not msiproductupgrade(GetString(vcredist2012_upgradecode, vcredist2012_upgradecode_x64, ''), minVersion)) then
+ if (not msiproduct(GetString(vcredist2012_productcode, vcredist2012_productcode_x64, ''))) then
AddProduct('vcredist2012' + GetArchitectureString() + '.exe',
'/passive /norestart',
CustomMessage('vcredist2012_title' + GetArchitectureString()),
diff --git a/installer/innosetup/scripts/products/vcredist2013.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2013.iss
similarity index 68%
rename from installer/innosetup/scripts/products/vcredist2013.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2013.iss
index 1efaa3d18..d55b3651b 100644
--- a/installer/innosetup/scripts/products/vcredist2013.iss
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2013.iss
@@ -1,25 +1,28 @@
; requires Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2, Windows XP
-; http://www.microsoft.com/en-us/download/details.aspx?id=40784
+; http://www.microsoft.com/en-US/download/details.aspx?id=40784
[CustomMessages]
vcredist2013_title=Visual C++ 2013 Redistributable
vcredist2013_title_x64=Visual C++ 2013 64-Bit Redistributable
-vcredist2013_size=6.2 MB
-vcredist2013_size_x64=6.9 MB
+en.vcredist2013_size=6.2 MB
+de.vcredist2013_size=6,2 MB
+
+en.vcredist2013_size_x64=6.9 MB
+de.vcredist2013_size_x64=6,9 MB
[Code]
const
vcredist2013_url = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe';
vcredist2013_url_x64 = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe';
- vcredist2013_upgradecode = '{B59F5BF1-67C8-3802-8E59-2CE551A39FC5}';
- vcredist2013_upgradecode_x64 = '{20400CF0-DE7C-327E-9AE4-F0F38D9085F8}';
+ vcredist2013_productcode = '{13A4EE12-23EA-3371-91EE-EFB36DDFFF3E}';
+ vcredist2013_productcode_x64 = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}';
-procedure vcredist2013(minVersion: string);
+procedure vcredist2013();
begin
if (not IsIA64()) then begin
- if (not msiproductupgrade(GetString(vcredist2013_upgradecode, vcredist2013_upgradecode_x64, ''), minVersion)) then
+ if (not msiproduct(GetString(vcredist2013_productcode, vcredist2013_productcode_x64, ''))) then
AddProduct('vcredist2013' + GetArchitectureString() + '.exe',
'/passive /norestart',
CustomMessage('vcredist2013_title' + GetArchitectureString()),
diff --git a/installer/innosetup/scripts/products/vcredist2015.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2015.iss
similarity index 56%
rename from installer/innosetup/scripts/products/vcredist2015.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2015.iss
index 9499a988d..e98b268f6 100644
--- a/installer/innosetup/scripts/products/vcredist2015.iss
+++ b/Greenshot/releases/innosetup/scripts/products/vcredist2015.iss
@@ -1,25 +1,28 @@
; requires Windows 10, Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003 Service Pack 2, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Vista Service Pack 2, Windows XP Service Pack 3
-; http://www.microsoft.com/en-us/download/details.aspx?id=48145
+; http://www.microsoft.com/en-US/download/details.aspx?id=48145
[CustomMessages]
vcredist2015_title=Visual C++ 2015 Redistributable
vcredist2015_title_x64=Visual C++ 2015 64-Bit Redistributable
-vcredist2015_size=13.8 MB
-vcredist2015_size_x64=14.6 MB
+en.vcredist2015_size=12.8 MB
+de.vcredist2015_size=12,8 MB
+
+en.vcredist2015_size_x64=13.9 MB
+de.vcredist2015_size_x64=13,9 MB
[Code]
const
- vcredist2015_url = 'http://download.microsoft.com/download/d/e/c/dec58546-c2f5-40a7-b38e-4df8d60b9764/vc_redist.x86.exe';
- vcredist2015_url_x64 = 'http://download.microsoft.com/download/2/c/6/2c675af0-2155-4961-b32e-289d7addfcec/vc_redist.x64.exe';
+ vcredist2015_url = 'http://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe';
+ vcredist2015_url_x64 = 'http://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe';
- vcredist2015_upgradecode = '{65E5BD06-6392-3027-8C26-853107D3CF1A}';
- vcredist2015_upgradecode_x64 = '{36F68A90-239C-34DF-B58C-64B30153CE35}';
+ vcredist2015_productcode = '{74D0E5DB-B326-4DAE-A6B2-445B9DE1836E}';
+ vcredist2015_productcode_x64 = '{0D3E9E15-DE7A-300B-96F1-B4AF12B96488}';
-procedure vcredist2015(minVersion: string);
+procedure vcredist2015();
begin
if (not IsIA64()) then begin
- if (not msiproductupgrade(GetString(vcredist2015_upgradecode, vcredist2015_upgradecode_x64, ''), minVersion)) then
+ if (not msiproduct(GetString(vcredist2015_productcode, vcredist2015_productcode_x64, ''))) then
AddProduct('vcredist2015' + GetArchitectureString() + '.exe',
'/passive /norestart',
CustomMessage('vcredist2015_title' + GetArchitectureString()),
diff --git a/installer/innosetup/scripts/products/wic.iss b/Greenshot/releases/innosetup/scripts/products/wic.iss
similarity index 78%
rename from installer/innosetup/scripts/products/wic.iss
rename to Greenshot/releases/innosetup/scripts/products/wic.iss
index 579066f68..bd1abb7d8 100644
--- a/installer/innosetup/scripts/products/wic.iss
+++ b/Greenshot/releases/innosetup/scripts/products/wic.iss
@@ -3,7 +3,8 @@
[CustomMessages]
wic_title=Windows Imaging Component
-wic_size=1.2 MB
+en.wic_size=1.2 MB
+de.wic_size=1,2 MB
[Code]
const
@@ -12,25 +13,26 @@ const
function GetConvertedLanguageID(): string;
begin
- Result := 'enu';
case ActiveLanguage() of
- 'zh': // Chinese
+ 'en': //English
+ Result := 'enu';
+ 'zh': //Chinese
Result := 'chs';
- 'de': // German
+ 'de': //German
Result := 'deu';
- 'es': // Spanish
+ 'es': //Spanish
Result := 'esn';
- 'fr': // French
+ 'fr': //French
Result := 'fra';
- 'it': // Italian
+ 'it': //Italian
Result := 'ita';
- 'ja': // Japanese
+ 'ja': //Japanese
Result := 'jpn';
- 'nl': // Dutch
+ 'nl': //Dutch
Result := 'nld';
- 'pt': // Portuguese
+ 'pt': //Portuguese
Result := 'ptb';
- 'ru': // Russian
+ 'ru': //Russian
Result := 'rus';
end;
end;
@@ -38,7 +40,7 @@ end;
procedure wic();
begin
if (not IsIA64()) then begin
- // only needed on Windows XP SP2 or Windows Server 2003
+ //only needed on Windows XP SP2 or Windows Server 2003
if ((exactwinversion(5, 1) and exactwinspversion(5, 1, 2)) or (exactwinversion(5, 2))) then begin
if (not FileExists(GetEnv('windir') + '\system32\windowscodecs.dll')) then
AddProduct('wic' + GetArchitectureString() + '_' + GetConvertedLanguageID() + '.exe',
diff --git a/installer/innosetup/scripts/products/winversion.iss b/Greenshot/releases/innosetup/scripts/products/winversion.iss
similarity index 100%
rename from installer/innosetup/scripts/products/winversion.iss
rename to Greenshot/releases/innosetup/scripts/products/winversion.iss
diff --git a/Greenshot/releases/innosetup/setup.iss.template b/Greenshot/releases/innosetup/setup.iss.template
new file mode 100644
index 000000000..55449f635
--- /dev/null
+++ b/Greenshot/releases/innosetup/setup.iss.template
@@ -0,0 +1,661 @@
+#define ExeName "Greenshot"
+#define Version "@VERSION@"
+#define FileVersion "@FILEVERSION@"
+
+; Include the scripts to install .NET Framework
+; See http://www.codeproject.com/KB/install/dotnetfx_innosetup_instal.aspx
+#include "scripts\products.iss"
+#include "scripts\products\stringversion.iss"
+#include "scripts\products\winversion.iss"
+#include "scripts\products\fileversion.iss"
+#include "scripts\products\msi20.iss"
+#include "scripts\products\msi31.iss"
+#include "scripts\products\dotnetfxversion.iss"
+#include "scripts\products\dotnetfx35sp1.iss"
+
+[Files]
+Source: ..\..\bin\Release\Greenshot.exe; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: ..\..\bin\Release\GreenshotPlugin.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: ..\..\bin\Release\Greenshot.exe.config; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: ..\..\bin\Release\log4net.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: ..\..\bin\Release\LinqBridge.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion
+Source: ..\..\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion
+Source: ..\..\bin\Release\checksum.MD5; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion
+Source: ..\additional_files\installer.txt; DestDir: {app}; Components: greenshot; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion
+Source: ..\additional_files\license.txt; DestDir: {app}; Components: greenshot; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion
+Source: ..\additional_files\readme.txt; DestDir: {app}; Components: greenshot; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion
+
+; Core language files
+Source: ..\..\Languages\*nl-NL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*en-US*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*de-DE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
+
+; Additional language files
+Source: ..\..\Languages\*ar-SY*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\arSY; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*ca-CA*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\caCA; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*cs-CZ*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\csCZ; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*da-DK*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\daDK; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*de-x-franconia*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\dexfranconia; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*el-GR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\elGR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*es-ES*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\esES; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*et-EE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\etEE; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*fa-IR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\faIR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*fi-FI*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\fiFI; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*fr-FR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\frFR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*fr-QC*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\frQC; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*he-IL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\heIL; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*hu-HU*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\huHU; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*id-ID*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\idID; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*it-IT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\itIT; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*ja-JP*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\jaJP; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*ko-KR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\koKR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*kab-DZ*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\kabDZ; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*lt-LT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ltLT; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*lv-LV*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\lvLV; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*nn-NO*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\nnNO; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*pl-PL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\plPL; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*pt-BR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ptBR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*pt-PT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ptPT; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*ro-RO*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\roRO; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*ru-RU*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ruRU; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*sk-SK*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\skSK; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*sl-SI*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\slSI; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*sr-RS*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\srRS; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*sv-SE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\svSE; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*tr-TR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\trTR; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*uk-UA*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ukUA; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*vi-VN*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\viVN; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*zh-CN*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhCN; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: ..\..\Languages\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhTW; Flags: overwritereadonly ignoreversion replacesameversion;
+
+;Office Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotOfficePlugin\GreenshotOfficePlugin.gsp; DestDir: {app}\Plugins\GreenshotOfficePlugin; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+;OCR Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotOCRPlugin\GreenshotOCRPlugin.gsp; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Plugins\GreenshotOCRPlugin\GreenshotOCRCommand.exe; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Plugins\GreenshotOCRPlugin\GreenshotOCRCommand.exe.config; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotOCRPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly ignoreversion replacesameversion;
+;JIRA Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotJiraPlugin\GreenshotJiraPlugin.gsp; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotJiraPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
+;Imgur Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotImgurPlugin\GreenshotImgurPlugin.gsp; DestDir: {app}\Plugins\GreenshotImgurPlugin; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotImgurPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotImgurPlugin; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion;
+;Box Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotBoxPlugin\GreenshotBoxPlugin.gsp; DestDir: {app}\Plugins\GreenshotBoxPlugin; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotBoxPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotBoxPlugin; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion;
+;DropBox Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotDropBoxPlugin\GreenshotDropboxPlugin.gsp; DestDir: {app}\Plugins\GreenshotDropBoxPlugin; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotDropBoxPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotDropBoxPlugin; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion;
+;Flickr Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotFlickrPlugin\GreenshotFlickrPlugin.gsp; DestDir: {app}\Plugins\GreenshotFlickrPlugin; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotFlickrPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotFlickrPlugin; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion;
+;Photobucket Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotPhotobucketPlugin\GreenshotPhotobucketPlugin.gsp; DestDir: {app}\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotPhotobucketPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion;
+;Picasa Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotPicasaPlugin\GreenshotPicasaPlugin.gsp; DestDir: {app}\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotPicasaPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly ignoreversion replacesameversion;
+;Confluence Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotConfluencePlugin\GreenshotConfluencePlugin.gsp; DestDir: {app}\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotConfluencePlugin\*; DestDir: {app}\Languages\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion;
+;ExternalCommand Plugin
+Source: ..\..\bin\Release\Plugins\GreenshotExternalCommandPlugin\GreenshotExternalCommandPlugin.gsp; DestDir: {app}\Plugins\GreenshotExternalCommandPlugin; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: ..\..\bin\Release\Languages\Plugins\GreenshotExternalCommandPlugin\*; DestDir: {app}\Languages\Plugins\GreenshotExternalCommandPlugin; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion;
+;Win 10 Plugin
+;Source: ..\..\bin\Release\Plugins\GreenshotWin10Plugin\GreenshotWin10Plugin.gsp; DestDir: {app}\Plugins\GreenshotWin10Plugin; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+[Setup]
+; changes associations is used when the installer installs new extensions, it clears the explorer icon cache
+ChangesAssociations=yes
+AppId={#ExeName}
+AppName={#ExeName}
+AppMutex=F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08
+AppPublisher={#ExeName}
+AppPublisherURL=http://getgreenshot.org
+AppSupportURL=http://getgreenshot.org
+AppUpdatesURL=http://getgreenshot.org
+AppVerName={#ExeName} {#Version}
+AppVersion={#Version}
+ArchitecturesInstallIn64BitMode=x64
+Compression=lzma2/ultra64
+SolidCompression=yes
+DefaultDirName={code:DefDirRoot}\{#ExeName}
+DefaultGroupName={#ExeName}
+InfoBeforeFile=..\additional_files\readme.txt
+LicenseFile=..\additional_files\license.txt
+LanguageDetectionMethod=uilanguage
+MinVersion=0,5.01.2600
+OutputBaseFilename={#ExeName}-INSTALLER-{#FileVersion}
+OutputDir=..\
+PrivilegesRequired=none
+SetupIconFile=..\..\icons\applicationIcon\icon.ico
+; Create a SHA1 signature
+SignTool=SignTool sign /debug /fd sha1 /tr http://time.certum.pl /td sha1 $f
+; Append a SHA256 to the previous SHA1 signature (this is what as does)
+SignTool=SignTool sign /debug /as /fd sha256 /tr http://time.certum.pl /td sha256 $f
+SignedUninstaller=yes
+UninstallDisplayIcon={app}\{#ExeName}.exe
+Uninstallable=true
+VersionInfoCompany={#ExeName}
+VersionInfoProductName={#ExeName}
+VersionInfoTextVersion={#Version}
+VersionInfoVersion={#Version}
+; Reference a bitmap, max size 164x314
+WizardImageFile=installer-large.bmp
+; Reference a bitmap, max size 55x58
+WizardSmallImageFile=installer-small.bmp
+[Registry]
+; Delete all startup entries, so we don't have leftover values
+Root: HKCU; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+Root: HKLM; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+Root: HKCU32; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror; Check: IsWin64()
+Root: HKLM32; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror; Check: IsWin64()
+
+; delete filetype mappings
+; HKEY_LOCAL_USER - for current user only
+Root: HKCU; Subkey: Software\Classes\.greenshot; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+Root: HKCU; Subkey: Software\Classes\Greenshot; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+; HKEY_LOCAL_MACHINE - for all users when admin (with the noerror this doesn't matter)
+Root: HKLM; Subkey: Software\Classes\.greenshot; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+Root: HKLM; Subkey: Software\Classes\Greenshot; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
+
+; Create the startup entries if requested to do so
+; HKEY_LOCAL_USER - for current user only
+Root: HKCU; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: {#ExeName}; ValueData: {app}\{#ExeName}.exe; Permissions: users-modify; Flags: uninsdeletevalue noerror; Tasks: startup; Check: IsRegularUser
+; HKEY_LOCAL_MACHINE - for all users when admin
+Root: HKLM; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: {#ExeName}; ValueData: {app}\{#ExeName}.exe; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Tasks: startup; Check: not IsRegularUser
+
+; Register our own filetype for all users
+; HKEY_LOCAL_USER - for current user only
+Root: HKCU; Subkey: Software\Classes\.greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot"; Permissions: users-modify; Flags: uninsdeletevalue noerror; Check: IsRegularUser
+Root: HKCU; Subkey: Software\Classes\Greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot File"; Permissions: users-modify; Flags: uninsdeletevalue noerror; Check: IsRegularUser
+Root: HKCU; Subkey: Software\Classes\Greenshot\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\Greenshot.EXE,0"; Permissions: users-modify; Flags: uninsdeletevalue noerror; Check: IsRegularUser
+Root: HKCU; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Permissions: users-modify; Flags: uninsdeletevalue noerror; Check: IsRegularUser
+; HKEY_LOCAL_MACHINE - for all users when admin
+Root: HKLM; Subkey: Software\Classes\.greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot"; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
+Root: HKLM; Subkey: Software\Classes\Greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot File"; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
+Root: HKLM; Subkey: Software\Classes\Greenshot\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\Greenshot.EXE,0"; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
+Root: HKLM; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
+
+[Icons]
+Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}
+Name: {group}\Uninstall {#ExeName}; Filename: {uninstallexe}; WorkingDir: {app}; AppUserModelID: "{#ExeName}.{#ExeName}"
+Name: {group}\Readme.txt; Filename: {app}\readme.txt; WorkingDir: {app}
+Name: {group}\License.txt; Filename: {app}\license.txt; WorkingDir: {app}
+[Languages]
+Name: en; MessagesFile: compiler:Default.isl
+Name: cn; MessagesFile: Languages\ChineseSimplified.isl
+Name: de; MessagesFile: compiler:Languages\German.isl
+Name: es; MessagesFile: compiler:Languages\Spanish.isl
+Name: fi; MessagesFile: compiler:Languages\Finnish.isl
+Name: fr; MessagesFile: compiler:Languages\French.isl
+Name: nl; MessagesFile: compiler:Languages\Dutch.isl
+Name: lt; MessagesFile: Languages\Latvian.isl
+Name: nn; MessagesFile: Languages\NorwegianNynorsk.isl
+Name: sr; MessagesFile: compiler:Languages\SerbianCyrillic.isl
+Name: sv; MessagesFile: Languages\Swedish.isl
+Name: uk; MessagesFile: compiler:Languages\Ukrainian.isl
+
+[Tasks]
+Name: startup; Description: {cm:startup}
+
+[CustomMessages]
+
+de.confluence=Confluence Plug-in
+de.default=Standard installation
+en.office=Microsoft Office Plug-in
+de.externalcommand=Externes Kommando Plug-in
+de.imgur=Imgur Plug-in (Siehe: http://imgur.com)
+de.jira=Jira Plug-in
+de.language=Zusätzliche Sprachen
+de.ocr=OCR Plug-in (benötigt Microsoft Office Document Imaging (MODI))
+de.optimize=Optimierung der Leistung, kann etwas dauern.
+de.startgreenshot={#ExeName} starten
+de.startup={#ExeName} starten wenn Windows hochfährt
+de.win10=Windows 10 Plug-in
+
+en.confluence=Confluence plug-in
+en.default=Default installation
+en.office=Microsoft Office plug-in
+en.externalcommand=Open with external command plug-in
+en.imgur=Imgur plug-in (See: http://imgur.com)
+en.jira=Jira plug-in
+en.language=Additional languages
+en.ocr=OCR plug-in (needs Microsoft Office Document Imaging (MODI))
+en.optimize=Optimizing performance, this may take a while.
+en.startgreenshot=Start {#ExeName}
+en.startup=Start {#ExeName} with Windows start
+en.win10=Windows 10 plug-in
+
+es.confluence=Extensión para Confluence
+es.default=${default}
+es.externalcommand=Extensión para abrir con programas externos
+es.imgur=Extensión para Imgur (Ver http://imgur.com)
+es.jira=Extensión para Jira
+es.language=Idiomas adicionales
+es.ocr=Extensión para OCR (necesita Microsoft Office Document Imaging (MODI))
+es.optimize=Optimizando rendimiento; por favor, espera.
+es.startgreenshot=Lanzar {#ExeName}
+es.startup=Lanzar {#ExeName} al iniciarse Windows
+es.win10=Extensión para Windows 10
+
+fi.confluence=Confluence-liitännäinen
+fi.default=${default}
+fi.office=Microsoft-Office-liitännäinen
+fi.externalcommand=Avaa Ulkoinen komento-liitännäisellä
+fi.imgur=Imgur-liitännäinen (Katso: http://imgur.com)
+fi.jira=Jira-liitännäinen
+fi.language=Lisäkielet
+fi.ocr=OCR-liitännäinen (Tarvitaan: Microsoft Office Document Imaging (MODI))
+fi.optimize=Optimoidaan suorituskykyä, tämä voi kestää hetken.
+fi.startgreenshot=Käynnistä {#ExeName}
+fi.startup=Käynnistä {#ExeName} Windowsin käynnistyessä
+fi.win10=Windows 10-liitännäinen
+
+fr.confluence=Greffon Confluence
+fr.default=${default}
+fr.office=Greffon Microsoft Office
+fr.externalcommand=Ouvrir avec le greffon de commande externe
+fr.imgur=Greffon Imgur (Voir: http://imgur.com)
+fr.jira=Greffon Jira
+fr.language=Langues additionnelles
+fr.ocr=Greffon OCR (nécessite Document Imaging de Microsoft Office [MODI])
+fr.optimize=Optimisation des performances, Ceci peut prendre un certain temps.
+fr.startgreenshot=Démarrer {#ExeName}
+fr.startup=Lancer {#ExeName} au démarrage de Windows
+fr.win10=Greffon Windows 10
+
+lt.confluence=Confluence spraudnis
+lt.default=${default}
+lt.office=Microsoft Office spraudnis
+lt.externalcommand=Pielāgotu darbību spraudnis
+lt.imgur=Imgur spraudnis (Vairāk šeit: http://imgur.com)
+lt.jira=Jira spraudnis
+lt.language=Papildus valodas
+lt.ocr=OCR spraudnis (nepieciešams Microsoft Office Document Imaging (MODI))
+lt.optimize=Uzlaboju veikstpēju, tas prasīs kādu laiciņu.
+lt.startgreenshot=Palaist {#ExeName}
+lt.startup=Palaist {#ExeName} uzsākot darbus
+lt.win10=Windows 10 spraudnis
+
+nl.confluence=Confluence plug-in
+nl.default=Standaardinstallatie
+nl.office=Microsoft Office plug-in
+nl.externalcommand=Openen met extern commando plug-in
+nl.imgur=Imgur plug-in (zie: http://imgur.com)
+nl.jira=Jira plug-in
+nl.language=Extra talen
+nl.ocr=OCR plug-in (vereist Microsoft Office Document Imaging (MODI))
+nl.optimize=Prestaties verbeteren, even geduld.
+nl.startgreenshot={#ExeName} starten
+nl.startup={#ExeName} automatisch starten met Windows
+nl.win10=Windows 10 plug-in
+
+nn.confluence=Confluence-tillegg
+nn.default=Default installation
+nn.office=Microsoft Office Tillegg
+nn.externalcommand=Tillegg for å opne med ekstern kommando
+nn.imgur=Imgur-tillegg (sjå http://imgur.com)
+nn.jira=Jira-tillegg
+nn.language=Andre språk
+nn.ocr=OCR-tillegg (krev Microsoft Office Document Imaging (MODI))
+nn.optimize=Optimaliserar ytelse, dette kan ta litt tid...
+nn.startgreenshot=Start {#ExeName}
+nn.startup=Start {#ExeName} når Windows startar
+nn.win10=Windows 10 Tillegg
+
+sr.confluence=Прикључак за Конфлуенс
+sr.default=${default}
+sr.externalcommand=Отвори са прикључком за спољне наредбе
+sr.imgur=Прикључак за Имиџер (http://imgur.com)
+sr.jira=Прикључак за Џиру
+sr.language=Додатни језици
+sr.ocr=OCR прикључак (захтева Microsoft Office Document Imaging (MODI))
+sr.optimize=Оптимизујем перформансе…
+sr.startgreenshot=Покрени Гриншот
+sr.startup=Покрени програм са системом
+sr.win10=Прикључак за Windows 10
+
+sv.startup=Starta {#ExeName} med Windows
+sv.startgreenshot=Starta {#ExeName}
+sv.jira=Jira-insticksprogram
+sv.confluence=Confluence-insticksprogram
+sv.externalcommand=Öppna med externt kommando-insticksprogram
+sv.ocr=OCR-insticksprogram (kräver Microsoft Office Document Imaging (MODI))
+sv.imgur=Imgur-insticksprogram (Se: http://imgur.com)
+sv.language=Ytterligare språk
+sv.optimize=Optimerar prestanda, detta kan ta en stund.
+sv.win10=Windows 10-insticksprogram
+
+uk.confluence=Плагін Confluence
+uk.default=${default}
+uk.externalcommand=Плагін запуску зовнішньої команди
+uk.imgur=Плагін Imgur (див.: http://imgur.com)
+uk.jira=Плагін Jira
+uk.language=Додаткові мови
+uk.ocr=Плагін OCR (потребує Microsoft Office Document Imaging (MODI))
+uk.optimize=Оптимізація продуктивності, це може забрати час.
+uk.startgreenshot=Запустити {#ExeName}
+uk.startup=Запускати {#ExeName} під час запуску Windows
+uk.win10=Плагін Windows 10
+
+cn.confluence=Confluence插件
+cn.default=${default}
+cn.externalcommand=使用外部命令打开插件
+cn.imgur=Imgur插件( (请访问: http://imgur.com))
+cn.jira=Jira插件
+cn.language=其它语言
+cn.ocr=OCR插件(需要Microsoft Office Document Imaging (MODI)的支持)
+cn.optimize=正在优化性能,这可能需要一点时间。
+cn.startgreenshot=启动{#ExeName}
+cn.startup=让{#ExeName}随Windows一起启动
+cn.win10=Windows 10插件
+
+[Types]
+Name: "default"; Description: "{cm:default}"
+Name: "full"; Description: "{code:FullInstall}"
+Name: "compact"; Description: "{code:CompactInstall}"
+Name: "custom"; Description: "{code:CustomInstall}"; Flags: iscustom
+
+[Components]
+Name: "greenshot"; Description: "Greenshot"; Types: default full compact custom; Flags: fixed
+Name: "plugins\office"; Description: {cm:office}; Types: default full custom; Flags: disablenouninstallwarning
+Name: "plugins\ocr"; Description: {cm:ocr}; Types: default full custom; Flags: disablenouninstallwarning
+Name: "plugins\jira"; Description: {cm:jira}; Types: full custom; Flags: disablenouninstallwarning; Check: hasDotNet45OrHigher()
+Name: "plugins\imgur"; Description: {cm:imgur}; Types: default full custom; Flags: disablenouninstallwarning
+Name: "plugins\confluence"; Description: {cm:confluence}; Types: full custom; Flags: disablenouninstallwarning; Check: hasDotNet35FullOrHigher()
+Name: "plugins\externalcommand"; Description: {cm:externalcommand}; Types: default full custom; Flags: disablenouninstallwarning
+;Name: "plugins\networkimport"; Description: "Network Import Plugin"; Types: full
+Name: "plugins\box"; Description: "Box Plugin"; Types: full custom; Flags: disablenouninstallwarning; Check: hasDotNet35FullOrHigher()
+Name: "plugins\dropbox"; Description: "Dropbox Plugin"; Types: full custom; Flags: disablenouninstallwarning
+Name: "plugins\flickr"; Description: "Flickr Plugin"; Types: full custom; Flags: disablenouninstallwarning
+Name: "plugins\picasa"; Description: "Picasa Plugin"; Types: full custom; Flags: disablenouninstallwarning
+Name: "plugins\photobucket"; Description: "Photobucket Plugin"; Types: full custom; Flags: disablenouninstallwarning
+;Name: "plugins\win10"; Description: "Windows 10 Plugin"; Types: default full custom; Flags: disablenouninstallwarning; Check: IsWindows10OrNewer()
+Name: "languages"; Description: {cm:language}; Types: full custom; Flags: disablenouninstallwarning
+Name: "languages\arSY"; Description: "العربية"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('d')
+Name: "languages\caCA"; Description: "Català"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\csCZ"; Description: "Ceština"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\daDK"; Description: "Dansk"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\dexfranconia"; Description: "Frängisch (Deutsch)"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\elGR"; Description: "ελληνικά"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('4')
+Name: "languages\esES"; Description: "Español"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\etEE"; Description: "Eesti"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\faIR"; Description: "پارسی"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('d')
+Name: "languages\fiFI"; Description: "Suomi"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\frFR"; Description: "Français"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\frQC"; Description: "Français - Québec"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\heIL"; Description: "עִבְרִית"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('c')
+Name: "languages\huHU"; Description: "Magyar"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\idID"; Description: "Bahasa Indonesia"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\itIT"; Description: "Italiano"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\jaJP"; Description: "日本語"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('7')
+Name: "languages\koKR"; Description: "한국어"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('8')
+Name: "languages\kabDZ"; Description: "Taqbaylit"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('8')
+Name: "languages\ltLT"; Description: "Lietuvių"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('3')
+Name: "languages\lvLV"; Description: "Latviski"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('3')
+Name: "languages\nnNO"; Description: "Nynorsk"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\plPL"; Description: "Polski"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\ptBR"; Description: "Português do Brasil"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\ptPT"; Description: "Português de Portugal"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\ruRU"; Description: "Pусский"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('5')
+Name: "languages\roRO"; Description: "Română"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\skSK"; Description: "Slovenčina"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\slSI"; Description: "Slovenščina"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('2')
+Name: "languages\srRS"; Description: "Српски"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('5')
+Name: "languages\svSE"; Description: "Svenska"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('1')
+Name: "languages\trTR"; Description: "Türk"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('6')
+Name: "languages\ukUA"; Description: "Українська"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('5')
+Name: "languages\viVN"; Description: "Việt"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('e')
+Name: "languages\zhCN"; Description: "简体中文"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('a')
+Name: "languages\zhTW"; Description: "繁體中文"; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('9')
+[Code]
+// Do we have a regular user trying to install this?
+function IsRegularUser(): Boolean;
+begin
+ Result := not (IsAdminLoggedOn or IsPowerUserLoggedOn);
+end;
+
+// The following code is used to select the installation path, this is localappdata if non poweruser
+function DefDirRoot(Param: String): String;
+begin
+ if IsRegularUser then
+ Result := ExpandConstant('{localappdata}')
+ else
+ Result := ExpandConstant('{pf}')
+end;
+
+
+function FullInstall(Param : String) : String;
+begin
+ result := SetupMessage(msgFullInstallation);
+end;
+
+function CustomInstall(Param : String) : String;
+begin
+ result := SetupMessage(msgCustomInstallation);
+end;
+
+function CompactInstall(Param : String) : String;
+begin
+ result := SetupMessage(msgCompactInstallation);
+end;
+/////////////////////////////////////////////////////////////////////
+// The following uninstall code was found at:
+// http://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version
+// and than modified to work in a 32/64 bit environment
+/////////////////////////////////////////////////////////////////////
+function GetUninstallStrings(): array of String;
+var
+ sUnInstPath: String;
+ sUnInstallString: String;
+ asUninstallStrings : array of String;
+ index : Integer;
+begin
+ sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
+ sUnInstallString := '';
+ index := 0;
+
+ // Retrieve uninstall string from HKLM32 or HKCU32
+ if RegQueryStringValue(HKLM32, sUnInstPath, 'UninstallString', sUnInstallString) then
+ begin
+ SetArrayLength(asUninstallStrings, index + 1);
+ asUninstallStrings[index] := sUnInstallString;
+ index := index +1;
+ end;
+
+ if RegQueryStringValue(HKCU32, sUnInstPath, 'UninstallString', sUnInstallString) then
+ begin
+ SetArrayLength(asUninstallStrings, index + 1);
+ asUninstallStrings[index] := sUnInstallString;
+ index := index +1;
+ end;
+
+ // Only for Windows with 64 bit support: Retrieve uninstall string from HKLM64 or HKCU64
+ if IsWin64 then
+ begin
+ if RegQueryStringValue(HKLM64, sUnInstPath, 'UninstallString', sUnInstallString) then
+ begin
+ SetArrayLength(asUninstallStrings, index + 1);
+ asUninstallStrings[index] := sUnInstallString;
+ index := index +1;
+ end;
+
+ if RegQueryStringValue(HKCU64, sUnInstPath, 'UninstallString', sUnInstallString) then
+ begin
+ SetArrayLength(asUninstallStrings, index + 1);
+ asUninstallStrings[index] := sUnInstallString;
+ index := index +1;
+ end;
+ end;
+ Result := asUninstallStrings;
+end;
+
+/////////////////////////////////////////////////////////////////////
+procedure UnInstallOldVersions();
+var
+ sUnInstallString: String;
+ index: Integer;
+ isUninstallMade: Boolean;
+ iResultCode : Integer;
+ asUninstallStrings : array of String;
+begin
+ isUninstallMade := false;
+ asUninstallStrings := GetUninstallStrings();
+ for index := 0 to (GetArrayLength(asUninstallStrings) -1) do
+ begin
+ sUnInstallString := RemoveQuotes(asUninstallStrings[index]);
+ if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
+ isUninstallMade := true;
+ end;
+
+ // Wait a few seconds to prevent installation issues, otherwise files are removed in one process while the other tries to link to them
+ if (isUninstallMade) then
+ Sleep(2000);
+end;
+
+/////////////////////////////////////////////////////////////////////
+procedure CurStepChanged(CurStep: TSetupStep);
+begin
+ if (CurStep=ssInstall) then
+ begin
+ UnInstallOldVersions();
+ end;
+end;
+/////////////////////////////////////////////////////////////////////
+// End of unstall code
+/////////////////////////////////////////////////////////////////////
+
+// Build a list of greenshot parameters from the supplied installer parameters
+function GetParamsForGS(argument: String): String;
+var
+ i: Integer;
+ parametersString: String;
+ currentParameter: String;
+ foundStart: Boolean;
+ foundNoRun: Boolean;
+ foundLanguage: Boolean;
+begin
+ foundNoRun := false;
+ foundLanguage := false;
+ foundStart := false;
+ for i:= 0 to ParamCount() do begin
+ currentParameter := ParamStr(i);
+
+ // check if norun is supplied
+ if Lowercase(currentParameter) = '/norun' then begin
+ foundNoRun := true;
+ continue;
+ end;
+
+ if foundStart then begin
+ parametersString := parametersString + ' ' + currentParameter;
+ foundStart := false;
+ end
+ else begin
+ if Lowercase(currentParameter) = '/language' then begin
+ foundStart := true;
+ foundLanguage := true;
+ parametersString := parametersString + ' ' + currentParameter;
+ end;
+ end;
+ end;
+ if not foundLanguage then begin
+ parametersString := parametersString + ' /language ' + ExpandConstant('{language}');
+ end;
+ if foundNoRun then begin
+ parametersString := parametersString + ' /norun';
+ end;
+ // For debugging comment out the following
+ //MsgBox(parametersString, mbInformation, MB_OK);
+
+ Result := parametersString;
+end;
+
+// Check if language group is installed
+function hasLanguageGroup(argument: String): Boolean;
+var
+ keyValue: String;
+ returnValue: Boolean;
+begin
+ returnValue := true;
+ if (RegQueryStringValue( HKLM, 'SYSTEM\CurrentControlSet\Control\Nls\Language Groups', argument, keyValue)) then begin
+ if Length(keyValue) = 0 then begin
+ returnValue := false;
+ end;
+ end;
+ Result := returnValue;
+end;
+
+function hasDotNet() : boolean;
+begin
+ // .NET 4.5 = 4.0 full (with a "Release" key, but this is not interresting!)
+ Result := netfxinstalled(NetFX20, '') or netfxinstalled(NetFX30, '') or netfxinstalled(NetFX35, '') or netfxinstalled(NetFX40Client, '') or netfxinstalled(NetFX40Full, '');
+end;
+
+function hasDotNet35FullOrHigher() : boolean;
+begin
+ Result := netfxinstalled(NetFX35, '') or netfxinstalled(NetFX40Full, '');
+end;
+
+function hasDotNet45OrHigher() : boolean;
+begin
+ Result := netfxinstalled(NetFX4x, '');
+end;
+
+function getNGENPath(argument: String) : String;
+var
+ installPath: string;
+begin
+ if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'InstallPath', installPath) then begin
+ if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client', 'InstallPath', installPath) then begin
+ // 3.5 doesn't have NGEN and is using the .net 2.0 installation
+ installPath := ExpandConstant('{dotnet20}');
+ end;
+ end;
+ Result := installPath;
+end;
+
+// Initialize the setup
+function InitializeSetup(): Boolean;
+begin
+ // Check for .NET and install 3.5 if we don't have it
+ if not hasDotNet() then
+ begin
+ // Enhance installer, if needed, otherwise .NET installations won't work
+ msi20('2.0');
+ msi31('3.0');
+
+ //install .net 3.5
+ dotnetfx35sp1();
+ end;
+ Result := true;
+end;
+
+function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;
+var
+ Version: TWindowsVersion;
+begin
+ GetWindowsVersionEx(Version);
+ Result :=
+ (Version.Major > Major) or
+ ((Version.Major = Major) and (Version.Minor >= Minor));
+end;
+
+function IsWindows10OrNewer: Boolean;
+begin
+ Result := IsWindowsVersionOrNewer(10, 0);
+end;
+[Run]
+Filename: "{code:getNGENPath}\ngen.exe"; Parameters: "install ""{app}\{#ExeName}.exe"""; StatusMsg: "{cm:optimize}"; Flags: runhidden runasoriginaluser
+Filename: "{code:getNGENPath}\ngen.exe"; Parameters: "install ""{app}\GreenshotPlugin.dll"""; StatusMsg: "{cm:optimize}"; Flags: runhidden runasoriginaluser
+Filename: "{app}\{#ExeName}.exe"; Description: "{cm:startgreenshot}"; Parameters: "{code:GetParamsForGS}"; WorkingDir: "{app}"; Flags: nowait postinstall runasoriginaluser
+Filename: "http://getgreenshot.org/thank-you/?language={language}&version={#Version}"; Flags: shellexec runasoriginaluser
+
+[InstallDelete]
+Name: {app}; Type: dirifempty;
+
+[UninstallRun]
+Filename: "{code:GetNGENPath}\ngen.exe"; Parameters: "uninstall ""{app}\{#ExeName}.exe"""; StatusMsg: "Cleanup"; Flags: runhidden
+Filename: "{code:GetNGENPath}\ngen.exe"; Parameters: "uninstall ""{app}\GreenshotPlugin.dll"""; StatusMsg: "Cleanup"; Flags: runhidden
diff --git a/installer/portable/App/AppInfo/appicon.ico b/Greenshot/releases/portable/App/AppInfo/appicon.ico
similarity index 100%
rename from installer/portable/App/AppInfo/appicon.ico
rename to Greenshot/releases/portable/App/AppInfo/appicon.ico
diff --git a/installer/portable/App/AppInfo/appicon_16.png b/Greenshot/releases/portable/App/AppInfo/appicon_16.png
similarity index 100%
rename from installer/portable/App/AppInfo/appicon_16.png
rename to Greenshot/releases/portable/App/AppInfo/appicon_16.png
diff --git a/installer/portable/App/AppInfo/appicon_32.png b/Greenshot/releases/portable/App/AppInfo/appicon_32.png
similarity index 100%
rename from installer/portable/App/AppInfo/appicon_32.png
rename to Greenshot/releases/portable/App/AppInfo/appicon_32.png
diff --git a/installer/portable/App/DefaultData/Greenshots/dummy.txt b/Greenshot/releases/portable/App/DefaultData/Greenshots/dummy.txt
similarity index 100%
rename from installer/portable/App/DefaultData/Greenshots/dummy.txt
rename to Greenshot/releases/portable/App/DefaultData/Greenshots/dummy.txt
diff --git a/installer/portable/App/DefaultData/Settings/dummy.txt b/Greenshot/releases/portable/App/DefaultData/Settings/dummy.txt
similarity index 100%
rename from installer/portable/App/DefaultData/Settings/dummy.txt
rename to Greenshot/releases/portable/App/DefaultData/Settings/dummy.txt
diff --git a/installer/portable/Data/Greenshot/dummy.txt b/Greenshot/releases/portable/Data/Greenshot/dummy.txt
similarity index 100%
rename from installer/portable/Data/Greenshot/dummy.txt
rename to Greenshot/releases/portable/Data/Greenshot/dummy.txt
diff --git a/installer/portable/Data/Settings/dummy.txt b/Greenshot/releases/portable/Data/Settings/dummy.txt
similarity index 100%
rename from installer/portable/Data/Settings/dummy.txt
rename to Greenshot/releases/portable/Data/Settings/dummy.txt
diff --git a/installer/portable/Other/Source/PortableApps.comInstallerCustom.nsh b/Greenshot/releases/portable/Other/Source/PortableApps.comInstallerCustom.nsh
similarity index 100%
rename from installer/portable/Other/Source/PortableApps.comInstallerCustom.nsh
rename to Greenshot/releases/portable/Other/Source/PortableApps.comInstallerCustom.nsh
diff --git a/src/Greenshot/sounds/camera.wav b/Greenshot/sounds/camera.wav
similarity index 100%
rename from src/Greenshot/sounds/camera.wav
rename to Greenshot/sounds/camera.wav
diff --git a/Greenshot/tools/7zip/7za.exe b/Greenshot/tools/7zip/7za.exe
new file mode 100644
index 000000000..12b9499a2
Binary files /dev/null and b/Greenshot/tools/7zip/7za.exe differ
diff --git a/Greenshot/tools/ILMerge/ILMerge License.rtf b/Greenshot/tools/ILMerge/ILMerge License.rtf
new file mode 100644
index 000000000..41f5b6ada
--- /dev/null
+++ b/Greenshot/tools/ILMerge/ILMerge License.rtf
@@ -0,0 +1,104 @@
+{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}
+{\f39\froman\fcharset0\fprq2{\*\panose 02040602050305030304}Book Antiqua;}{\f40\fswiss\fcharset0\fprq2{\*\panose 020b0706030402020204}Franklin Gothic Demi Cond;}{\f41\fswiss\fcharset0\fprq2{\*\panose 020b0503020102020204}Franklin Gothic Book;}
+{\f42\froman\fcharset238\fprq2 Times New Roman CE;}{\f43\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f45\froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\froman\fcharset162\fprq2 Times New Roman Tur;}
+{\f47\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f48\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f49\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\f412\fswiss\fcharset238\fprq2 Tahoma CE;}{\f413\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f415\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f416\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f417\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}
+{\f418\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f419\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f420\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f421\fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f432\froman\fcharset238\fprq2 Book Antiqua CE;}
+{\f433\froman\fcharset204\fprq2 Book Antiqua Cyr;}{\f435\froman\fcharset161\fprq2 Book Antiqua Greek;}{\f436\froman\fcharset162\fprq2 Book Antiqua Tur;}{\f439\froman\fcharset186\fprq2 Book Antiqua Baltic;}
+{\f442\fswiss\fcharset238\fprq2 Franklin Gothic Demi Cond CE;}{\f443\fswiss\fcharset204\fprq2 Franklin Gothic Demi Cond Cyr;}{\f445\fswiss\fcharset161\fprq2 Franklin Gothic Demi Cond Greek;}{\f446\fswiss\fcharset162\fprq2 Franklin Gothic Demi Cond Tur;}
+{\f449\fswiss\fcharset186\fprq2 Franklin Gothic Demi Cond Baltic;}{\f452\fswiss\fcharset238\fprq2 Franklin Gothic Book CE;}{\f453\fswiss\fcharset204\fprq2 Franklin Gothic Book Cyr;}{\f455\fswiss\fcharset161\fprq2 Franklin Gothic Book Greek;}
+{\f456\fswiss\fcharset162\fprq2 Franklin Gothic Book Tur;}{\f459\fswiss\fcharset186\fprq2 Franklin Gothic Book Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;
+\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
+\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \fi-274\li274\ri0\sb120\sl460\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin274\itap0 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \styrsid9786739 1sectionhead;}{\s16\ql \li0\ri0\sb120\sl200\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \caps\f40\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext16 \styrsid9786739 4laparahead;}{\s17\ql \li0\ri-18\sb120\sl240\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-18\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \styrsid9786739 2lasubhead;}{\s18\ql \fi-187\li187\ri0\sb60\sl180\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin187\itap0 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext18 \styrsid9786739 3cnumbered;}{\s19\ql \fi-340\li624\ri0\sb60\sl160\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin624\itap0 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext19 \styrsid9786739 3inumbered2ndlevel;}{\s20\ql \li0\ri0\sb240\sl240\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext20 \styrsid9786739 2afrenchsubhead;}{\s21\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0
+\cbpat9 \f37\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext21 \ssemihidden \styrsid7154712 Document Map;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\pgptbl {\pgp\ipgp2\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20 }{\pgp\ipgp0
+\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid2099452\rsid4207571\rsid5465292\rsid5510097\rsid5510644\rsid7154712\rsid7241305\rsid7672529\rsid7735936\rsid9179139\rsid9786739\rsid10440675\rsid11303133\rsid13130884\rsid14028235\rsid14100361\rsid14113652
+\rsid15276140\rsid16213514}{\*\generator Microsoft Word 11.0.6359;}{\info{\title ILMerge EULA}{\author Ken Leppert}{\operator mbarnett}{\creatim\yr2005\mo3\dy16\hr15\min43}{\revtim\yr2005\mo3\dy16\hr15\min43}{\printim\yr2004\mo4\dy30\hr13\min9}{\version2}
+{\edmins0}{\nofpages3}{\nofwords1188}{\nofchars6775}{\*\company Microsoft Corporation}{\nofcharsws7948}{\vern24703}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180
+\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1\jexpand\viewkind1\viewscale68\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel
+\wrppunct\asianbrkrule\rsidroot9786739\newtblstyruls\nogrowautofit \fet0\sectd \linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang
+{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain
+\s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid7154712 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\fs28\insrsid9786739 MICROSOFT }{
+\b\f39\fs28\insrsid5465292 ILMerge}{\insrsid9786739
+\par }{\b\f39\fs22\insrsid9786739 END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE}{\insrsid9786739
+\par }\pard\plain \s17\qj \li0\ri-17\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-17\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\insrsid9786739 IMPORTANT\emdash
+READ CAREFULLY: }{\f39\insrsid9786739 This End-User License Agreement (\'93EULA\'94) is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation (\'93Microsoft\'94) for th
+e Microsoft software that accompanies this EULA, which includes computer software and may include associated media, printed materials, \'93online\'94 or electronic documentation, and Internet-based services (\'93Software\'94).\~
+ An amendment or addendum to this EULA may accompany the Software.\~ }{\b\f39\insrsid9786739
+YOU AGREE TO BE BOUND BY THE TERMS OF THIS EULA BY INSTALLING, COPYING, OR OTHERWISE USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT INSTALL, COPY, OR USE THE SOFTWARE.}{\insrsid9786739
+\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\insrsid9786739 GRANTS OF LICENSE}{\f39\fs22\insrsid9786739 . Microsoft grants you the rights described in this EULA provided that you comply with all terms and conditions of this EULA.\~ }{\insrsid9786739
+\par }\pard\plain \s19\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 1.1\~\~\~\~\~\~ }{
+\b\i\f39\fs22\cf0\insrsid9786739 License Grant}{\f39\fs22\cf0\insrsid9786739 . Microsoft grants to you a personal, nonexclusive, nontransferable, limited license to }{\f39\fs22\insrsid9786739 install and use a reasonable number of copies of
+the Software on computers residing on your premises }{\f39\fs22\cf0\insrsid9786739 for the purposes of designing, developing, and testing, your software product(s), provided that you are the only individual using the Software.\~ }{\insrsid9786739
+\par }\pard\plain \s18\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.2\~\~\~\~\~\~ }{
+\b\i\f39\fs22\insrsid9786739 Documentation}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~ }{\f39\fs22\insrsid9786739 You may make and use a reasonabl
+e number of copies of any documentation, provided that such copies shall be used only for your personal purposes and are not to be republished or distributed (either in hard copy or electronic form) beyond your premises.}{\insrsid9786739
+\par }\pard \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 {\f39\fs22\insrsid9786739 2.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 RESERVATION OF RIGHTS AND OWNERSHIP.\~ }{
+\f39\fs22\insrsid9786739 The Software is licensed as a single product.\~ Its component parts may not be separated. Microsoft reserves all rights not expressly granted to you in this EULA.\~
+ The Software is protected by copyright and other intellectual property laws and treaties}{\f39\fs22\insrsid14028235 , and}{\f39\fs22\insrsid9786739 Microsoft }{\f39\fs22\insrsid14028235 (}{\f39\fs22\insrsid9786739 or its suppliers}{
+\f39\fs22\insrsid14028235 , where applicable)}{\f39\fs22\insrsid9786739 own }{\f39\fs22\insrsid14028235 all right, }{\f39\fs22\insrsid9786739 title, }{\f39\fs22\insrsid14028235 and interest in all }{\f39\fs22\insrsid9786739
+intellectual property rights in the Software.\~ }{\b\f39\fs22\insrsid9786739 The Software is licensed, not sold.}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 3.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\cf0\insrsid9786739 LIMITATIONS ON REVERSE ENGINEERING, DECOMPILATION, AND DISASSEMBLY}{\b\i\f39\fs22\cf0\insrsid9786739 .}{\f39\fs22\cf0\insrsid9786739 \~
+ You may not reverse engineer, decompile, or disassemble the Software, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.}{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 4.\~\~\~\~\~\~\~\~
+}{\b\f39\fs22\insrsid9786739 NO RENTAL/COMMERCIAL HOSTING.}{\b\i\f39\fs22\insrsid9786739 }{\f39\fs22\insrsid9786739 You may not rent, lease, lend or provide commercial hosting services with the Software.}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 5.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\cf0\insrsid9786739 NO SOFTWARE TRANSFER.\~ }{\f39\fs22\cf0\insrsid9786739 You may not assign or otherwise transfer the SOFTWARE or any of your rights hereunder to any third party.}{\insrsid9786739
+\par }{\f39\fs22\cf0\insrsid9786739 6.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 CONSENT TO USE OF DATA.\~ }{\f39\fs22\cf0\insrsid9786739 You
+ agree that Microsoft and its affiliates may collect and use technical information gathered as part of the product support services provided to you, if any, related to the Software.\~
+ Microsoft may use this information solely to improve our products or to provide customized services or technologies to you and will not disclose this information in a form that personally identifies you.\~\~ }{\insrsid9786739
+\par }{\f39\fs22\cf0\insrsid5510644 7}{\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 ADDITIONAL SOFTWARE/SERVICES.\~ }{\f39\fs22\insrsid9786739 Microsoft is not obligated to provide maintenance, technical supplements}{
+\f39\fs22\insrsid14028235 , updates,}{\f39\fs22\insrsid9786739 or other support to you for the Software licensed under this EULA. }{\f39\fs22\insrsid7241305 }{\f39\fs22\insrsid9786739 In the event that Microsoft does provide such supplements or updates}
+{\b\f39\fs22\insrsid9786739 , }{\f39\fs22\insrsid9786739 this EULA applies to such updates, supplements, or add-on components of the Software that Microsoft may provide to
+you or make available to you after the date you obtain your initial copy of the Software, unless we provide other terms along with the update, supplement, or add-on component}{\f39\fs22\cf0\insrsid9786739 .\~
+ Microsoft reserves the right to discontinue any Internet-based services provided to you or made available to you through the use of the Software.\~ }{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid5510644 8}{
+\f39\fs22\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 EXPORT RESTRICTIONS}{\f39\fs22\insrsid9786739 .\~ }{\f39\fs22\cgrid0\insrsid9786739 You acknowledge that the Software is subject to U.S. export jurisdiction.\~
+ You agree to comply with all applicable international and national laws that apply to the Software, including the U.S. Export Administration Regulations, as well as end-user, end-use, and destination restrictions issued by U.S. and other governments.\~\~
+ For additional information see }{\f39\fs22\ul\cgrid0\insrsid9786739 http://www.microsoft.com/exporting/}{\f39\fs22\cgrid0\insrsid9786739 .}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid14113652 9}{
+\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 TERMINATION.}{\f39\fs22\cf0\insrsid9786739 \~ Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with }{\f39\fs22\cf0\insrsid7241305
+any }{\f39\fs22\cf0\insrsid9786739 term}{\f39\fs22\cf0\insrsid7241305 or}{\f39\fs22\cf0\insrsid9786739 condition of this EULA. }{\f39\fs22\cf0\insrsid7241305 }{\f39\fs22\cf0\insrsid9786739
+In such event, you must destroy all copies of the Software and all of its component parts.}{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1}{
+\f39\fs22\insrsid14113652 0}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 DISCLAIMER OF WARRANTIES}{\b\f39\fs22\insrsid9786739 .\~
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND ITS SUPPLIERS PROVIDE THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 AND SUPPORT SERVICES (IF ANY) }{\b\i\f39\fs22\insrsid9786739 AS IS AND WITH ALL FAULTS}{
+\b\f39\fs22\insrsid9786739 , AND HEREBY DISCLAIM ALL OTHER WARRANTIES AND CONDITIONS, WHETHER EXPRESS, IMPLIED
+ OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF RELIABILITY OR AVAILABILITY, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF WORKMANLI
+K
+E EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE, ALL WITH REGARD TO THE SOFTWARE, AND THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT OR OTHER SERVICES, INFORMATION, SOFTWARE, AND RELATED CONTENT THROUGH THE SOFTWARE OR OTHERWISE ARISING OUT OF THE
+ USE OF THE SOFTWARE.\~ ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT WITH REGARD TO THE SOFTWARE.}{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 1}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 EXCLUSION OF INCIDENTAL, CONSEQUENTIAL AND CERTAIN OTHER DAMAGES}{\b\f39\fs22\insrsid9786739 .\~
+ }{\b\caps\f39\fs22\insrsid9786739
+To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any special, incidental, punitive, indirect, or consequential damages whatsoever (including, but not limited to, damages for loss of profit
+s, LOSS OF DATA, or confidential or other information}{\b\f39\fs22\insrsid9786739 , }{\b\caps\f39\fs22\insrsid9786739
+for business interruption, for personal injury, for loss of privacy, for failure to meet any duty including of good faith or of reasonable care, for negligence, and}{\b\f39\fs22\insrsid9786739 }{\b\caps\f39\fs22\insrsid9786739
+for any other pecuniary or other los
+s whatsoever) arising out of or in any way related to the use of or inability to use the SOFTWARE, the provision of or failure to provide Support OR OTHER Services, informatIon, software, and related CONTENT through the software or otherwise arising out o
+f
+ the use of the software, or otherwise under or in connection with any provision of this EULA, even in the event of the fault, tort (including negligence), misrepresentation, strict liability, breach of contract or breach of warranty of Microsoft or any s
+upplier, and even if Microsoft or any supplier has been advised of the possibility of such damages. }{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 2}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 LIMITATION OF LIABILITY AND REMEDIES}{\b\f39\fs22\insrsid9786739
+. NOTWITHSTANDING ANY DAMAGES THAT YOU MIGHT INCUR FOR ANY REASON WHATSOEVER (INCLUDING, WITHOUT LIMITATION, A
+LL DAMAGES REFERENCED HEREIN AND ALL DIRECT OR GENERAL DAMAGES IN CONTRACT OR ANYTHING ELSE), THE ENTIRE LIABILITY OF MICROSOFT AND ANY OF ITS SUPPLIERS UNDER ANY PROVISION OF THIS EULA AND YOUR EXCLUSIVE REMEDY HEREUNDER SHALL BE LIMITED TO THE GREATER O
+F THE ACTUAL DAMAGES YOU INCUR IN REASONABLE RELIANCE ON THE SOFTWARE UP TO THE AMOUNT ACTUALLY PAID BY YOU FOR THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 OR US$5.00.\~
+ THE FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS ITS ESSENTIAL PURPOSE.}{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 3}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 APPLICABLE LAW.\~ }{\f39\fs22\insrsid7735936 T}{\f39\fs22\insrsid9786739 his EULA }{\f39\fs22\insrsid7735936
+shall be construed under and }{\f39\fs22\insrsid9786739 governed by the laws of the State of Washington}{\f39\fs22\insrsid7735936 , without regard to conflicts of law principles}{\f39\fs22\insrsid9786739 .\~ }{\insrsid9786739
+\par }\pard\plain \s20\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl240\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\insrsid9786739 1}{\f39\insrsid14113652
+4}{\f39\insrsid9786739 .\~\~\~\~ }{\b\f39\insrsid9786739 ENTIRE AGREEMENT; SEVERABILITY.\~ }{\f39\insrsid9786739 This
+EULA (including any addendum or amendment to this EULA which is included with the Software) are the entire agreement between you and Microsoft relating to the Software and the support services (if any) and they supersede all prior or contemporaneous oral
+or written communications,\~proposals and representations with respect to the Software or any other subject matter covered by this EULA.\~
+ If any provision of this EULA is held to be void, invalid, unenforceable or illegal, the other provisions shall continue in full force and effect}{\insrsid9786739
+\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\insrsid10440675
+\par }}
\ No newline at end of file
diff --git a/Greenshot/tools/ILMerge/ILMerge.doc b/Greenshot/tools/ILMerge/ILMerge.doc
new file mode 100644
index 000000000..f3ac50149
Binary files /dev/null and b/Greenshot/tools/ILMerge/ILMerge.doc differ
diff --git a/Greenshot/tools/ILMerge/ILMerge.exe b/Greenshot/tools/ILMerge/ILMerge.exe
new file mode 100644
index 000000000..bdd546a86
Binary files /dev/null and b/Greenshot/tools/ILMerge/ILMerge.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.dll b/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.dll
new file mode 100644
index 000000000..48bd32f24
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.exe b/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.exe
new file mode 100644
index 000000000..5ec90671e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/7zip/7z.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon.ico b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon.ico
new file mode 100644
index 000000000..d0981620d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_128.png b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_128.png
new file mode 100644
index 000000000..b7fcd1d8f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_128.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_16.png b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_16.png
new file mode 100644
index 000000000..3a7151ffe
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_16.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_32.png b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_32.png
new file mode 100644
index 000000000..5830fd50a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appicon_32.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appinfo.ini b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appinfo.ini
new file mode 100644
index 000000000..694557244
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/AppInfo/appinfo.ini
@@ -0,0 +1,29 @@
+[Format]
+Type=PortableApps.comFormat
+Version=3.0
+
+[Details]
+Name=PortableApps.com Installer
+AppID=PortableApps.comInstaller
+Publisher=PortableApps.com
+Homepage=PortableApps.com/go/PortableApps.comInstaller
+Category=Development
+Description=PortableApps.com Format installer creator
+Language=Multilingual
+
+[License]
+Shareable=true
+OpenSource=true
+Freeware=true
+CommercialUse=true
+
+[Version]
+PackageVersion=3.0.6.0
+DisplayVersion=3.0.6
+
+[Control]
+Icons=1
+Start=PortableApps.comInstaller.exe
+
+[Associations]
+SendTo=true
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/DefaultData/settings.ini b/Greenshot/tools/PortableApps.comInstaller/App/DefaultData/settings.ini
new file mode 100644
index 000000000..8a4e3981d
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/DefaultData/settings.ini
@@ -0,0 +1 @@
+[InstallerWizard]
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/bin/MakeHeader.exe b/Greenshot/tools/PortableApps.comInstaller/App/bin/MakeHeader.exe
new file mode 100644
index 000000000..dc8ec8e7e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/bin/MakeHeader.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeader.bmp b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeader.bmp
new file mode 100644
index 000000000..c592db187
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeader.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeaderRTL.bmp b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeaderRTL.bmp
new file mode 100644
index 000000000..d5eef3fe1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/PortableApps.comInstallerHeaderRTL.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon.ico b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon.ico
new file mode 100644
index 000000000..d17e7fb97
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_16.png b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_16.png
new file mode 100644
index 000000000..31a96bf01
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_16.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_32.png b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_32.png
new file mode 100644
index 000000000..5c742d60d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appicon_32.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appinfo.ini b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appinfo.ini
new file mode 100644
index 000000000..844686deb
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/default_bits/appinfo.ini
@@ -0,0 +1,12 @@
+[Format]
+Type=PortableApps.comFormat
+Version=X.XX
+
+[Details]
+
+[License]
+
+[Version]
+
+[Control]
+Icons=1
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.bmp b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.bmp
new file mode 100644
index 000000000..220f605c3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.ico b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.ico
new file mode 100644
index 000000000..d0981620d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.nsi b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.nsi
new file mode 100644
index 000000000..a6e80f7f3
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstaller.nsi
@@ -0,0 +1,1358 @@
+;Copyright 2007-2013 John T. Haller of PortableApps.com
+;Website: http://PortableApps.com/
+
+;This software is OSI Certified Open Source Software.
+;OSI Certified is a certification mark of the Open Source Initiative.
+
+;This program is free software; you can redistribute it and/or
+;modify it under the terms of the GNU General Public License
+;as published by the Free Software Foundation; either version 2
+;of the License, or (at your option) any later version.
+
+;This program is distributed in the hope that it will be useful,
+;but WITHOUT ANY WARRANTY; without even the implied warranty of
+;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;GNU General Public License for more details.
+
+;You should have received a copy of the GNU General Public License
+;along with this program; if not, write to the Free Software
+;Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+;EXCEPTION: The PortableApps.com Installer can be used with open source
+;applications licensed under OSI-approved licenses as well as freeware provided
+;it is unmodified and it adheres to the current PortableApps.com Format Specification
+;as published at PortableApps.com/development. It may also be used with commercial
+;software by contacting PortableApps.com.
+
+!define PORTABLEAPPSINSTALLERVERSION "3.0.6.0"
+!define PORTABLEAPPS.COMFORMATVERSION "3.0.6"
+
+!if ${__FILE__} == "PortableApps.comInstallerPlugin.nsi"
+ !include PortableApps.comInstallerPluginConfig.nsh
+ !define PLUGININSTALLER
+!else
+ !include PortableApps.comInstallerConfig.nsh
+!endif
+
+!define MAINSECTIONIDX 0
+!ifdef MAINSECTIONTITLE
+ !define OPTIONALSECTIONIDX 1
+!endif
+
+;=== Program Details
+Name "${PORTABLEAPPNAME}" "${PORTABLEAPPNAMEDOUBLEDAMPERSANDS}"
+OutFile "..\..\..\${FILENAME}.paf.exe"
+!ifdef COMMONFILESPLUGIN
+ InstallDir "\CommonFiles\${APPID}"
+!else
+ InstallDir "\${APPID}"
+!endif
+Caption "${PORTABLEAPPNAME} | PortableApps.com Installer"
+VIProductVersion "${VERSION}"
+VIAddVersionKey ProductName "${PORTABLEAPPNAME}"
+VIAddVersionKey Comments "${INSTALLERCOMMENTS}"
+VIAddVersionKey CompanyName "PortableApps.com"
+VIAddVersionKey LegalCopyright "PortableApps.com Installer Copyright 2007-2012 PortableApps.com."
+VIAddVersionKey FileDescription "${PORTABLEAPPNAME}"
+VIAddVersionKey FileVersion "${VERSION}"
+VIAddVersionKey ProductVersion "${VERSION}"
+VIAddVersionKey InternalName "${PORTABLEAPPNAME}"
+VIAddVersionKey LegalTrademarks "${INSTALLERADDITIONALTRADEMARKS}PortableApps.com is a registered trademark of Rare Ideas, LLC."
+VIAddVersionKey OriginalFilename "${FILENAME}.paf.exe"
+VIAddVersionKey PortableApps.comInstallerVersion "${PORTABLEAPPSINSTALLERVERSION}"
+VIAddVersionKey PortableApps.comFormatVersion "${PORTABLEAPPS.COMFORMATVERSION}"
+VIAddVersionKey PortableApps.comAppID "${APPID}"
+!ifdef DownloadURL ;advertise the needed bits to the PA.c Updater
+ VIAddVersionKey PortableApps.comDownloadURL "${DownloadURL}"
+ VIAddVersionKey PortableApps.comDownloadName "${DownloadName}"
+ VIAddVersionKey PortableApps.comDownloadFileName "${DownloadFileName}"
+ VIAddVersionKey PortableApps.comDownloadMD5 "${DownloadMD5}"
+!endif
+
+;=== Runtime Switches
+SetCompress Auto
+SetCompressor /SOLID lzma
+SetCompressorDictSize 32
+SetDatablockOptimize On
+CRCCheck on
+AutoCloseWindow True
+RequestExecutionLevel user
+AllowRootDirInstall true
+
+;=== Include
+!include MUI.nsh
+!include FileFunc.nsh
+!include LogicLib.nsh
+!ifdef PRESERVEFILE1
+ !include PortableApps.comInstallerMoveFiles.nsh
+!endif
+!ifdef COPYLOCALFILES
+ !include Registry.nsh
+!endif
+!include TextFunc.nsh
+!include WordFunc.nsh
+!include PortableApps.comInstallerDumpLogToFile.nsh
+!include PortableApps.comInstallerTBProgress.nsh
+
+;=== Program Icon
+Icon "PortableApps.comInstaller.ico"
+!define MUI_ICON "PortableApps.comInstaller.ico"
+!define MUI_UNICON "PortableApps.comInstaller.ico"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "PortableApps.comInstallerHeader.bmp"
+!define MUI_HEADERIMAGE_BITMAP_RTL "PortableApps.comInstallerHeaderRTL.bmp"
+!define MUI_HEADERIMAGE_RIGHT
+
+;=== Icon & Stye ===
+BrandingText "PortableApps.com®"
+
+;=== Pages
+!ifdef COPYLOCALFILES
+ !define MUI_CUSTOMFUNCTION_ABORT CustomAbortFunction
+!endif
+!define MUI_LANGDLL_WINDOWTITLE "${PORTABLEAPPNAME}"
+!define MUI_LANGDLL_INFO "Please select a language for the installer."
+!define MUI_WELCOMEFINISHPAGE_BITMAP "PortableApps.comInstaller.bmp"
+!ifdef PLUGINNAME
+ !define MUI_WELCOMEPAGE_TITLE "${PORTABLEAPPNAMEDOUBLEDAMPERSANDS}"
+!else
+ !define MUI_WELCOMEPAGE_TITLE "${PORTABLEAPPNAMEDOUBLEDAMPERSANDS}"
+!endif
+!define MUI_WELCOMEPAGE_TEXT "$(welcome)"
+!define MUI_PAGE_CUSTOMFUNCTION_PRE PreWelcome
+!define MUI_COMPONENTSPAGE_SMALLDESC
+!insertmacro MUI_PAGE_WELCOME
+!ifdef LICENSEAGREEMENT
+ ;!define MUI_LICENSEPAGE_CHECKBOX
+ !define MUI_PAGE_CUSTOMFUNCTION_PRE PreLicense
+ !define MUI_PAGE_CUSTOMFUNCTION_SHOW ShowLicense
+ !define MUI_PAGE_CUSTOMFUNCTION_LEAVE LeaveLicense
+ !insertmacro MUI_PAGE_LICENSE "..\..\App\AppInfo\${LICENSEAGREEMENT}"
+!endif
+!ifdef MAINSECTIONTITLE
+ !define MUI_PAGE_CUSTOMFUNCTION_PRE PreComponents
+ !insertmacro MUI_PAGE_COMPONENTS
+!endif
+!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
+!define MUI_PAGE_CUSTOMFUNCTION_PRE PreDirectory
+!define MUI_PAGE_CUSTOMFUNCTION_LEAVE LeaveDirectory
+!insertmacro MUI_PAGE_DIRECTORY
+!define MUI_PAGE_CUSTOMFUNCTION_SHOW ShowInstFiles
+!insertmacro MUI_PAGE_INSTFILES
+!define MUI_FINISHPAGE_TEXT "$(finish)"
+!define MUI_PAGE_CUSTOMFUNCTION_PRE PreFinish
+!define MUI_FINISHPAGE_TITLE_3LINES
+!define MUI_FINISHPAGE_CANCEL_ENABLED
+!ifndef PLUGINNAME
+ !define MUI_FINISHPAGE_RUN_NOTCHECKED
+ !define MUI_FINISHPAGE_RUN "$INSTDIR\${FINISHPAGERUN}"
+!endif
+!insertmacro MUI_PAGE_FINISH
+
+;=== Languages
+!ifndef INSTALLERMULTILINGUAL
+ !insertmacro MUI_LANGUAGE "${INSTALLERLANGUAGE}"
+ !include PortableApps.comInstallerLanguages\${INSTALLERLANGUAGE}.nsh
+!else
+ !tempfile LangAutoDetectFile
+ !macro IncludeLang _LANG_NAME
+ ; define and filename are all uppercase but both case insensitive
+ !ifdef USES_${_LANG_NAME}
+ !insertmacro MUI_LANGUAGE "${_LANG_NAME}"
+ !include PortableApps.comInstallerLanguages\${_LANG_NAME}.nsh
+ !appendfile "${LangAutoDetectFile}" "${Case} ${LANG_${_LANG_NAME}}$\n"
+ !endif
+ !macroend
+ !define IncludeLang "!insertmacro IncludeLang"
+
+ ${IncludeLang} English
+ ${IncludeLang} EnglishGB
+ ${IncludeLang} Afrikaans
+ ${IncludeLang} Albanian
+ ${IncludeLang} Arabic
+ ${IncludeLang} Armenian
+ ${IncludeLang} Basque
+ ${IncludeLang} Belarusian
+ ${IncludeLang} Bosnian
+ ${IncludeLang} Breton
+ ${IncludeLang} Bulgarian
+ ${IncludeLang} Catalan
+ ${IncludeLang} Cibemba
+ ${IncludeLang} Croatian
+ ${IncludeLang} Czech
+ ${IncludeLang} Danish
+ ${IncludeLang} Dutch
+ ${IncludeLang} Efik
+ ${IncludeLang} Esperanto
+ ${IncludeLang} Estonian
+ ${IncludeLang} Farsi
+ ${IncludeLang} Finnish
+ ${IncludeLang} French
+ ${IncludeLang} Galician
+ ${IncludeLang} Georgian
+ ${IncludeLang} German
+ ${IncludeLang} Greek
+ ${IncludeLang} Hebrew
+ ${IncludeLang} Hungarian
+ ${IncludeLang} Icelandic
+ ${IncludeLang} Igbo
+ ${IncludeLang} Indonesian
+ ${IncludeLang} Irish
+ ${IncludeLang} Italian
+ ${IncludeLang} Japanese
+ ${IncludeLang} Khmer
+ ${IncludeLang} Korean
+ ${IncludeLang} Kurdish
+ ${IncludeLang} Latvian
+ ${IncludeLang} Lithuanian
+ ${IncludeLang} Luxembourgish
+ ${IncludeLang} Macedonian
+ ${IncludeLang} Malagasy
+ ${IncludeLang} Malay
+ ${IncludeLang} Mongolian
+ ${IncludeLang} Norwegian
+ ${IncludeLang} NorwegianNynorsk
+ ${IncludeLang} Pashto
+ ${IncludeLang} Polish
+ ${IncludeLang} Portuguese
+ ${IncludeLang} PortugueseBR
+ ${IncludeLang} Romanian
+ ${IncludeLang} Russian
+ ${IncludeLang} Serbian
+ ${IncludeLang} SerbianLatin
+ ${IncludeLang} SimpChinese
+ ${IncludeLang} Slovak
+ ${IncludeLang} Slovenian
+ ${IncludeLang} Spanish
+ ${IncludeLang} SpanishInternational
+ ${IncludeLang} Swahili
+ ${IncludeLang} Swedish
+ ${IncludeLang} Thai
+ ${IncludeLang} TradChinese
+ ${IncludeLang} Turkish
+ ${IncludeLang} Ukrainian
+ ${IncludeLang} Uzbek
+ ${IncludeLang} Valencia
+ ${IncludeLang} Vietnamese
+ ${IncludeLang} Welsh
+ ${IncludeLang} Yoruba
+
+ !insertmacro MUI_RESERVEFILE_LANGDLL
+!endif
+
+;=== Macros
+!macro !insertmacro1-10 _m
+!insertmacro ${_m} 1
+!insertmacro ${_m} 2
+!insertmacro ${_m} 3
+!insertmacro ${_m} 4
+!insertmacro ${_m} 5
+!insertmacro ${_m} 6
+!insertmacro ${_m} 7
+!insertmacro ${_m} 8
+!insertmacro ${_m} 9
+!insertmacro ${_m} 10
+!macroend
+!define !insertmacro1-10 "!insertmacro !insertmacro1-10"
+
+;=== Variables
+Var FOUNDPORTABLEAPPSPATH
+!ifdef MAINSECTIONTITLE
+ Var OPTIONAL1DONE
+!endif
+Var AUTOMATEDINSTALL
+Var AUTOCLOSE
+Var SILENTLANGUAGEMODE
+Var HIDEINSTALLER
+Var MINIMIZEINSTALLER
+!ifdef LICENSEAGREEMENT
+ Var EULAVERSIONMATCH
+!endif
+!ifdef COPYLOCALFILES
+ Var CopyLocalFilesFrom
+ Var CopyLocalFilesTo
+ Var MISSINGFILEORPATH
+!endif
+!ifdef DOWNLOADURL
+ Var MD5MISMATCH
+ Var DOWNLOADRESULT
+ Var DOWNLOADEDFILE
+ Var DOWNLOADALREADYEXISTED
+ Var SECONDDOWNLOADATTEMPT
+ Var DownloadURLActual
+!endif
+Var INTERNALEULAVERSION
+Var InstallingStatusString
+Var bolAppUpgrade
+Var bolLogFile
+
+;=== Custom Code
+!ifdef USESCUSTOMCODE
+ !if ${__FILE__} == "PortableApps.comInstallerPlugin.nsi"
+ !include PortableApps.comInstallerPluginCustom.nsh
+ !else
+ !include PortableApps.comInstallerCustom.nsh
+ !endif
+!endif
+
+!ifdef INSTALLERMULTILINGUAL
+ !macro CaseLang _LANG_NAME _LANG_ID
+ !ifdef USES_${_LANG_NAME}
+ ${Case} ${_LANG_ID}
+ !endif
+ !macroend
+ !define CaseLang "!insertmacro CaseLang"
+!endif
+
+Function .onInit
+ SetSilent normal
+
+ !ifdef DownloadURL
+ StrCpy $R0 $EXEFILE "" -15
+ ${If} $R0 != "_online.paf.exe"
+ ${AndIf} $R0 != "line.paf[1].exe" ;Handle IE's renaming of files when run directly from a download
+ ${AndIf} $R0 != "line.paf[2].exe"
+ ${AndIf} $R0 != "line.paf[3].exe"
+ ${AndIf} $R0 != "line.paf[4].exe"
+ ${AndIf} $R0 != "line.paf[5].exe"
+ ${AndIf} $R0 != "line.paf[6].exe"
+ ${AndIf} $R0 != "line.paf[7].exe"
+ ${AndIf} $R0 != "line.paf[8].exe"
+ ${AndIf} $R0 != "line.paf[9].exe"
+ MessageBox MB_OK|MB_ICONSTOP `PortableApps.com Installers that download files must end with "_online.paf.exe". This is to ensure that users always know that an installer downloads files before it is run. Please rename the file to end in _online.paf.exe before running.`
+ Abort
+ ${EndIf}
+ !endif
+
+ InitPluginsDir
+
+ !ifdef INSTALLERMULTILINGUAL
+ ReadEnvStr $0 "PortableApps.comLocaleID"
+ ${Switch} $0
+ ; Use the Case statements formed earlier.
+ !include "${LangAutoDetectFile}"
+ !delfile "${LangAutoDetectFile}"
+ !undef LangAutoDetectFile
+ StrCpy $LANGUAGE $0
+ ${Break}
+ ${Default}
+ !insertmacro MUI_LANGDLL_DISPLAY
+ ${EndSwitch}
+ !endif
+
+ ;=== Check for logging mode
+ ${GetOptions} $CMDLINE "/LOG=" $0
+
+ ${IfNot} ${Errors}
+ ${AndIf} $0 == "true"
+ StrCpy $bolLogFile true
+ ${Else}
+ ClearErrors
+ ${EndIf}
+
+ ;=== Check for a specified installation directory
+ ${GetOptions} $CMDLINE "/DESTINATION=" $0
+
+ ${IfNot} ${Errors}
+ !ifdef COMMONFILESPLUGIN
+ StrCpy $INSTDIR "$0CommonFiles\${APPID}"
+ !else
+ ${GetOptions} $CMDLINE "/COPYNUMBER=" $1
+ ${IfNot} ${Errors}
+ StrCpy $INSTDIR "$0${APPID}_Copy_$1"
+ ${Else}
+ StrCpy $INSTDIR "$0${APPID}"
+ ${EndIf}
+ !endif
+
+ !ifdef LICENSEAGREEMENT
+ !ifndef EULAVERSION
+ StrCpy $INTERNALEULAVERSION "1"
+ !else
+ StrCpy $INTERNALEULAVERSION ${EULAVERSION}
+ !endif
+ ${If} ${FileExists} "$INSTDIR\Data\PortableApps.comInstaller\license.ini"
+ ReadINIStr $0 "$INSTDIR\Data\PortableApps.comInstaller\license.ini" "PortableApps.comInstaller" "EULAVersion"
+ ClearErrors
+ ${If} $0 == $INTERNALEULAVERSION
+ StrCpy $EULAVERSIONMATCH "true"
+ ${EndIf}
+ ${EndIf}
+ !endif
+
+ ;=== Check for PortableApps.com Platform
+ ${GetParent} $INSTDIR $0
+ !ifdef COMMONFILESPLUGIN
+ ${GetParent} $0 $0
+ !endif
+
+ ;=== Check that it exists at the right location
+ DetailPrint '$(checkforplatform)'
+
+ ${If} ${FileExists} `$0\PortableApps.com\PortableAppsPlatform.exe`
+ ;=== Check that it's the real deal
+ MoreInfo::GetProductName `$0\PortableApps.com\PortableAppsPlatform.exe`
+ Pop $1
+ ${If} $1 == "PortableApps.com Platform"
+ MoreInfo::GetCompanyName `$0\PortableApps.com\PortableAppsPlatform.exe`
+ Pop $1
+ ${If} $1 == "PortableApps.com"
+ ;=== Check that it's running
+ FindProcDLL::FindProc "PortableAppsPlatform.exe"
+ ${If} $R0 == 1
+ ;=== Do a partially automated install
+ StrCpy $AUTOMATEDINSTALL "true"
+
+ ClearErrors
+ ${GetOptions} $CMDLINE "/AUTOCLOSE=" $R0
+ ${IfNot} ${Errors}
+ ${AndIf} $R0 == "true"
+ StrCpy $AUTOCLOSE "true"
+ ${EndIf}
+
+ ClearErrors
+ ${GetOptions} $CMDLINE "/HIDEINSTALLER=" $R0
+ ${IfNot} ${Errors}
+ ${AndIf} $R0 == "true"
+ StrCpy $HIDEINSTALLER "true"
+ ${EndIf}
+
+ ClearErrors
+ ${GetOptions} $CMDLINE "/MINIMIZEINSTALLER=" $R0
+ ${IfNot} ${Errors}
+ ${AndIf} $R0 == "true"
+ StrCpy $MINIMIZEINSTALLER "true"
+ ${EndIf}
+
+ ClearErrors
+ ${GetOptions} $CMDLINE "/SILENT=" $R0
+ ${IfNot} ${Errors}
+ ${AndIf} $R0 == "true"
+ ;Duplicate of the size calculation code, to be functionalized later
+ SectionGetSize ${MAINSECTIONIDX} $1 ;=== Space Required for App
+ !ifdef MAINSECTIONTITLE
+ SectionGetFlags ${OPTIONALSECTIONIDX} $9
+ IntOp $9 $9 & ${SF_SELECTED}
+ ${If} $9 >= ${SF_SELECTED}
+ SectionGetSize ${OPTIONALSECTIONIDX} $2 ;=== Space Required for App
+ IntOp $1 $1 + $2
+ ${EndIf}
+ !endif
+ ${GetRoot} $INSTDIR $2
+ ${DriveSpace} `$2\` "/D=F /S=M" $3 ;=== Space Free on Device
+
+ IntOp $1 $1 / 1024
+
+ ${If} $3 <= $1
+ IntOp $1 $1 * 1024
+ IntOp $3 $3 * 1024
+ !ifndef PLUGININSTALLER ;=== If not a plugin installer, add the current install size to free space
+ ${If} ${FileExists} $INSTDIR
+ ${GetSize} `$INSTDIR` "/M=*.* /S=0K /G=0" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Root Install Size
+ ${GetSize} `$INSTDIR\App` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current App Install Size
+ ${GetSize} `$INSTDIR\Other` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Other Install Size
+
+ ${If} `${ADDONSDIRECTORYPRESERVE}` != "NONE"
+ ${AndIf} ${FileExists} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}`
+ ${GetSize} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Size of Data directory
+ IntOp $3 $3 - $4 ;=== Remove the plugins directory from the free space calculation
+ ${EndIf}
+ ${EndIf}
+ !else
+ !ifdef COMMONFILESPLUGIN ;Duplicate code for now, to do above for CommonFiles as well
+ ${If} ${FileExists} $INSTDIR
+ ${GetSize} `$INSTDIR` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Install Size
+ ${EndIf}
+ !endif
+ !endif
+ ${If} $3 <= $1
+ MessageBox MB_OK|MB_ICONEXCLAMATION $(notenoughspace)
+ Abort
+ ${EndIf}
+ ${EndIf}
+
+ !ifdef LICENSEAGREEMENT
+ ${If} $EULAVERSIONMATCH == "true"
+ SetSilent silent
+ ${EndIf}
+ !else
+ SetSilent silent
+ !endif
+ ${EndIf}
+
+ ClearErrors
+ ${GetOptions} $CMDLINE "/SILENTLANGUAGEMODE=" $R0
+ ${IfNot} ${Errors}
+ ${If} $R0 == "auto"
+ ${OrIf} $R0 == "never"
+ ${OrIf} $R0 == "always"
+ StrCpy $SILENTLANGUAGEMODE $R0
+ ${Else}
+ StrCpy $SILENTLANGUAGEMODE "auto"
+ ${EndIf}
+ ${Else}
+ StrCpy $SILENTLANGUAGEMODE "auto"
+ ${EndIf}
+
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ ${Else}
+ ClearErrors
+ ;=== Check legacy location
+ ${GetOptions} $CMDLINE "-o" $R0
+ ${IfNot} ${Errors}
+ !ifdef COMMONFILESPLUGIN
+ StrCpy $INSTDIR "$R0CommonFiles\${APPID}"
+ !else
+ StrCpy $INSTDIR "$R0${APPID}"
+ !endif
+ ${Else}
+ ;=== No installation directory found
+ ClearErrors
+ ${If} ${FileExists} "$PROFILE\PortableApps\*.*"
+ StrCpy $FOUNDPORTABLEAPPSPATH "$Profile\PortableApps"
+ ${Else}
+ ${GetDrives} "HDD+FDD" GetDrivesCallBack
+ ${EndIf}
+ ${If} $FOUNDPORTABLEAPPSPATH != ""
+ !ifdef COMMONFILESPLUGIN
+ StrCpy $INSTDIR "$FOUNDPORTABLEAPPSPATH\CommonFiles\${APPID}"
+ !else
+ StrCpy $INSTDIR "$FOUNDPORTABLEAPPSPATH\${APPID}"
+ !endif
+ ${Else}
+ !ifdef COMMONFILESPLUGIN
+ StrCpy $INSTDIR "$EXEDIR\CommonFiles\${APPID}"
+ !else
+ StrCpy $INSTDIR "$EXEDIR\${APPID}"
+ !endif
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+
+ !ifdef MAINSECTIONTITLE
+ !ifdef OPTIONALSECTIONPRESELECTEDIFNONENGLISHINSTALL
+ ;=== If it's not English, select the optional component (languages) by default
+ ${IfThen} $LANGUAGE != 1033 ${|} SectionSetFlags 1 ${OPTIONALSECTIONIDX} ${|}
+ !endif
+ ${If} ${Silent}
+ ${If} "${OPTIONALSECTIONINSTALLEDWHENSILENT}" == "true"
+ SectionSetFlags 1 ${OPTIONALSECTIONIDX}
+ ${ElseIf} "${OptionalSectionSelectedInstallType}" == "Multilingual"
+ ${If} $SILENTLANGUAGEMODE != "never"
+ ${If} $SILENTLANGUAGEMODE == "always"
+ SectionSetFlags 1 ${OPTIONALSECTIONIDX}
+ ${Else}
+ ${IfThen} $LANGUAGE != 1033 ${|} SectionSetFlags 1 ${OPTIONALSECTIONIDX} ${|}
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+
+ !endif
+
+ !ifdef COPYLOCALFILES
+ StrCpy $CopyLocalFilesFrom ""
+
+ ${If} "${CopyFromRegPath}" != ""
+ ${registry::Read} "${CopyFromRegPath}" "${CopyFromRegKey}" $R0 $R1
+ ${If} $R0 != ""
+ ;Strip trailing slash if there
+ StrCpy $1 $R0 "" -1
+ ${If} $1 == "\"
+ StrCpy $R0 $R0 -1
+ ${EndIf}
+
+ ;Go up directories if needed
+ ${If} "${CopyFromRegRemoveDirectories}" != ""
+ StrCpy $1 1
+ ${Do}
+ ${GetParent} $R0 $R0
+ IntOp $1 $1 + 1
+ ${LoopUntil} $1 > "${CopyFromRegRemoveDirectories}"
+ ${EndIf}
+
+ ;Check for existence
+ ${If} ${FileExists} "$R0\*.*"
+ StrCpy $CopyLocalFilesFrom $R0
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+
+ ;Fallback to direct entry
+ ${If} $CopyLocalFilesFrom == ""
+ ${AndIf} "${CopyFromDirectory}" != ""
+ StrCpy $CopyLocalFilesFrom "${CopyFromDirectory}"
+ ${WordReplace} $CopyLocalFilesFrom "%PROGRAMFILES%" $PROGRAMFILES + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%PROGRAMFILES32%" $PROGRAMFILES32 + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%PROGRAMFILES64%" $PROGRAMFILES64 + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%COMMONFILES%" $COMMONFILES + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%COMMONFILES32%" $COMMONFILES32 + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%COMMONFILES64%" $COMMONFILES64 + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%DESKTOP%" $DESKTOP + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%WINDIR%" $WINDIR + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%SYSDIR%" $SYSDIR + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%APPDATA%" $APPDATA + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%LOCALAPPDATA%" $LOCALAPPDATA + $CopyLocalFilesFrom
+ ${WordReplace} $CopyLocalFilesFrom "%TEMP%" $TEMP + $CopyLocalFilesFrom
+ ${EndIf}
+ ${If} ${FileExists} "$CopyLocalFilesFrom\*.*"
+ SectionGetSize ${MAINSECTIONIDX} $0
+ ${GetSize} $CopyLocalFilesFrom "/M=*.* /S=0K /G=1" $1 $2 $3
+ IntOp $0 $0 + $1
+ SectionSetSize ${MAINSECTIONIDX} $0
+ ${EndIf}
+ !endif
+ !ifdef AdditionalInstallSize
+ SectionGetSize ${MAINSECTIONIDX} $0
+ IntOp $0 $0 + ${AdditionalInstallSize}
+ SectionSetSize ${MAINSECTIONIDX} $0
+ !endif
+
+ ${If} "${CHECKRUNNING}" != "NONE"
+ ;=== Check if app is running?
+ RunningTryAgain:
+ FindProcDLL::FindProc "${CHECKRUNNING}"
+ ${If} $R0 == 1
+ MessageBox MB_OKCANCEL|MB_ICONINFORMATION $(runwarning) IDOK RunningTryAgain IDCANCEL RunningCancel
+
+ RunningCancel:
+ Abort
+ ${EndIf}
+ ${EndIf}
+FunctionEnd
+
+Function PreWelcome
+ ${IfThen} $AUTOMATEDINSTALL == "true" ${|} Abort ${|}
+FunctionEnd
+
+!ifdef LICENSEAGREEMENT
+Function PreLicense
+ ${If} $AUTOMATEDINSTALL == "true"
+ ${AndIf} $EULAVERSIONMATCH == "true"
+ Abort
+ ${EndIf}
+
+ !ifndef EULAVERSION
+ StrCpy $INTERNALEULAVERSION "1"
+ !else
+ StrCpy $INTERNALEULAVERSION "${EULAVERSION}"
+ !endif
+ ${If} ${FileExists} "$INSTDIR\Data\PortableApps.comInstaller\license.ini"
+ ReadINIStr $0 "$INSTDIR\Data\PortableApps.comInstaller\license.ini" "PortableApps.comInstaller" "EULAVersion"
+ ClearErrors
+ ${If} $0 == $INTERNALEULAVERSION
+ ${AndIf} $AUTOMATEDINSTALL == "true"
+ Abort
+ ${EndIf}
+ ${EndIf}
+FunctionEnd
+Function ShowLicense
+ ${If} $AUTOMATEDINSTALL == "true"
+ ${TBProgress} 20
+ ${TBProgress_State} Paused
+ ${EndIf}
+FunctionEnd
+Function LeaveLicense
+ ${If} $AUTOMATEDINSTALL == "true"
+ ${TBProgress_State} NoProgress
+ ${EndIf}
+FunctionEnd
+!endif
+
+Function ShowInstFiles
+ w7tbp::Start
+FunctionEnd
+
+!ifdef MAINSECTIONTITLE
+ Function PreComponents
+ ${If} $AUTOCLOSE != "true"
+ ${OrIfNot} ${FileExists} "$INSTDIR\App\AppInfo\appinfo.ini"
+ Return
+ ${EndIf}
+
+ ReadINIStr $0 "$INSTDIR\App\AppInfo\appinfo.ini" "Details" "InstallType"
+ ClearErrors
+ ${If} $0 == "${OPTIONALSECTIONSELECTEDINSTALLTYPE}"
+ SectionSetFlags 1 ${OPTIONALSECTIONIDX}
+ Abort
+ ${EndIf}
+
+ ;=== Check not selected
+ ${If} $0 == "${OPTIONALSECTIONNOTSELECTEDINSTALLTYPE}"
+ SectionSetFlags 0 ${OPTIONALSECTIONIDX}
+ Abort
+ ${EndIf}
+ FunctionEnd
+!endif
+
+Function PreDirectory
+ ${IfThen} $AUTOMATEDINSTALL != "true" ${|} Return ${|}
+
+ SectionGetSize ${MAINSECTIONIDX} $1 ;=== Space Required for App
+ !ifdef MAINSECTIONTITLE
+ SectionGetFlags ${OPTIONALSECTIONIDX} $9
+ IntOp $9 $9 & ${SF_SELECTED}
+ ${If} $9 >= ${SF_SELECTED}
+ SectionGetSize ${OPTIONALSECTIONIDX} $2 ;=== Space Required for App
+ IntOp $1 $1 + $2
+ ${EndIf}
+ !endif
+ ${GetRoot} $INSTDIR $2
+ ${DriveSpace} `$2\` "/D=F /S=M" $3 ;=== Space Free on Device
+
+ IntOp $1 $1 / 1024
+
+ ${If} $3 <= $1
+ IntOp $1 $1 * 1024
+ IntOp $3 $3 * 1024
+
+ !ifndef PLUGININSTALLER ;=== If not a plugin installer, add the current install size to free space
+ ${If} ${FileExists} $INSTDIR
+ ${GetSize} $INSTDIR "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Install Size
+
+ ${If} ${FileExists} `$INSTDIR\Data`
+ ${GetSize} `$INSTDIR\Data` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Size of Data directory
+ IntOp $3 $3 - $4 ;=== Remove the data directory from the free space calculation
+ ${EndIf}
+
+ ${If} `${ADDONSDIRECTORYPRESERVE}` != "NONE"
+ ${AndIf} ${FileExists} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}`
+ ${GetSize} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Size of Data directory
+ IntOp $3 $3 - $4 ;=== Remove the plugins directory from the free space calculation
+ ${EndIf}
+ ${EndIf}
+ !else
+ !ifdef COMMONFILESPLUGIN ;Duplicate code for now, to do above for CommonFiles as well
+ ${If} ${FileExists} $INSTDIR
+ ${GetSize} `$INSTDIR` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Install Size
+ ${EndIf}
+ !endif
+ !endif
+
+ ${If} $3 <= $1
+ MessageBox MB_OK|MB_ICONEXCLAMATION "$(notenoughspace)"
+ Return
+ ${EndIf}
+ ${EndIf}
+
+ ;=== Check if app is running?
+ ${IfThen} "${CHECKRUNNING}" == "NONE" ${|} Abort ${|}
+ FindProcDLL::FindProc "${CHECKRUNNING}"
+ ${IfThen} $R0 != "1" ${|} Abort ${|}
+ MessageBox MB_OK|MB_ICONINFORMATION $(runwarning)
+FunctionEnd
+
+Function LeaveDirectory
+ GetInstDirError $0
+
+ ;=== Does it already exist? (upgrade)
+ ${If} ${FileExists} $INSTDIR
+ ${AndIf} "${CHECKRUNNING}" != "NONE"
+ ;=== Check if app is running?
+ FindProcDLL::FindProc "${CHECKRUNNING}"
+ ${If} $R0 = 1
+ MessageBox MB_OK|MB_ICONINFORMATION $(runwarning)
+ Abort
+ ${EndIf}
+ ${EndIf}
+
+ ; 0 is valid, enough space, all fine
+ ${Select} $0
+ ${Case} 1
+ MessageBox MB_OK|MB_ICONINFORMATION $(invaliddirectory)
+ Abort
+
+ ${Case} 2
+ ${IfNot} ${FileExists} $INSTDIR ;=== Is upgrade
+ MessageBox MB_OK|MB_ICONEXCLAMATION $(notenoughspace)
+ Abort
+ ${EndIf}
+
+ SectionGetSize ${MAINSECTIONIDX} $1 ;=== Space Required for App
+ !ifdef MAINSECTIONTITLE
+ SectionGetFlags ${OPTIONALSECTIONIDX} $9
+ IntOp $9 $9 & ${SF_SELECTED}
+ ${If} $9 >= ${SF_SELECTED}
+ SectionGetSize ${OPTIONALSECTIONIDX} $2 ;=== Space Required for App
+ IntOp $1 $1 + $2
+ ${EndIf}
+ !endif
+ ${GetRoot} $INSTDIR $2
+ ${DriveSpace} `$2\` "/D=F /S=K" $3 ;=== Space Free on Device
+
+
+ !ifndef PLUGININSTALLER ;=== If not a plugin installer, add the current install size to free space
+ ${GetSize} `$INSTDIR` "/M=*.* /S=0K /G=0" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Root Install Size
+ ${GetSize} `$INSTDIR\App` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current App Install Size
+ ${GetSize} `$INSTDIR\Other` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Other Install Size
+
+ ${If} `${ADDONSDIRECTORYPRESERVE}` != "NONE"
+ ${AndIf} ${FileExists} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}`
+ ${GetSize} `$INSTDIR\${ADDONSDIRECTORYPRESERVE}` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Size of Data directory
+ IntOp $3 $3 - $4 ;=== Remove the plugins directory from the free space calculation
+ ${EndIf}
+ !else
+ !ifdef COMMONFILESPLUGIN ;Duplicate code for now, to do above for CommonFiles as well
+ ${GetSize} `$INSTDIR` "/M=*.* /S=0K /G=1" $4 $5 $6 ;=== Current installation size
+ IntOp $3 $3 + $4 ;=== Space Free + Current Install Size
+ !endif
+ !endif
+
+ ${If} $3 <= $1
+ MessageBox MB_OK|MB_ICONEXCLAMATION "$(notenoughspace)"
+ Abort
+ ${EndIf}
+ ${EndSelect}
+
+ ;Check for Program Files
+ ReadEnvStr $0 IPromiseNotToComplainWhenPortableAppsDontWorkRightInProgramFiles
+ ${If} $0 != "I understand that this may not work and that I can not ask for help with any of my apps when operating in this fashion."
+ ${WordFind} "$INSTDIR\" "$PROGRAMFILES\" "*" $R0
+ ${If} $R0 > 0
+ MessageBox MB_OK|MB_ICONINFORMATION "$(invaliddirectory) [$PROGRAMFILES or sub-directories]"
+ Abort
+ ${EndIf}
+ ${WordFind} "$INSTDIR\" "$PROGRAMFILES64\" "*" $R0
+ ${If} $R0 > 0
+ MessageBox MB_OK|MB_ICONINFORMATION "$(invaliddirectory) [$PROGRAMFILES64 or sub-directories]"
+ Abort
+ ${EndIf}
+ ${EndIf}
+FunctionEnd
+
+Function PreFinish
+ ${IfThen} $AUTOCLOSE == "true" ${|} Abort ${|}
+FunctionEnd
+
+Function GetDrivesCallBack
+ ;=== Skip usual floppy letters
+ ${If} $8 == "FDD"
+ ${If} $9 == "A:\"
+ ${OrIf} $9 == "B:\"
+ Push $0
+ Return
+ ${EndIf}
+ ${EndIf}
+
+ ${If} ${FileExists} $9PortableApps
+ StrCpy $FOUNDPORTABLEAPPSPATH $9PortableApps
+ ${EndIf}
+
+ Push $0
+FunctionEnd
+
+!ifdef MAINSECTIONTITLE
+ Section "${MAINSECTIONTITLE}"
+!else
+ Section "App Portable (required)"
+!endif
+
+ ${If} $MINIMIZEINSTALLER == "true"
+ ShowWindow $HWNDPARENT ${SW_MINIMIZE}
+ ${EndIf}
+ ${If} $HIDEINSTALLER == "true"
+ ShowWindow $HWNDPARENT ${SW_HIDE}
+ ${EndIf}
+
+ ${If} ${FileExists} "$INSTDIR\*.*"
+ StrCpy $bolAppUpgrade true
+ ${EndIf}
+
+ ${If} $(installingstatus) != ""
+ StrCpy $InstallingStatusString "$(installingstatus)"
+ ${Else}
+ StrCpy $InstallingStatusString "$(MUI_TEXT_INSTALLING_TITLE)"
+ ${EndIf}
+
+ SectionIn RO
+ SetOutPath $INSTDIR
+
+ ${If} $bolAppUpgrade == true
+ ${If} $(prepareupgrade) == ""
+ DetailPrint $InstallingStatusString
+ ${Else}
+ DetailPrint $(prepareupgrade)
+ ${EndIf}
+ ${Else}
+ DetailPrint $InstallingStatusString
+ ${EndIf}
+ SetDetailsPrint ListOnly
+
+ ;=== Download Files
+!ifdef DownloadURL
+ ${If} ${FileExists} `$EXEDIR\${DownloadFileName}`
+ !ifdef DownloadMD5
+ md5dll::GetMD5File "$EXEDIR\${DownloadFileName}"
+ Pop $R0
+ ${If} $R0 == ${DownloadMD5}
+ StrCpy $DOWNLOADALREADYEXISTED "true"
+ StrCpy $DOWNLOADRESULT "OK"
+ ${EndIf}
+ !else
+ StrCpy $DOWNLOADALREADYEXISTED "true"
+ StrCpy $DOWNLOADRESULT "OK"
+ !endif
+ ${EndIf}
+
+ ${If} $DOWNLOADALREADYEXISTED == "true"
+ StrCpy $DOWNLOADEDFILE "$EXEDIR\${DownloadFileName}"
+ ${Else}
+ StrCpy $DownloadURLActual ${DownloadURL}
+ DownloadTheFile:
+ CreateDirectory `$PLUGINSDIR\Downloaded`
+ SetDetailsPrint both
+ ${If} $(downloading) != ""
+ DetailPrint $(downloading)
+ ${Else}
+ DetailPrint "Downloading ${DownloadName}..."
+ ${EndIf}
+
+ SetDetailsPrint none
+ Delete "$PLUGINSDIR\Downloaded\${DownloadName}"
+ Delete "$PLUGINSDIR\Downloaded\${DownloadFilename}"
+
+ ${If} $(downloading) != ""
+ inetc::get /CONNECTTIMEOUT 30 /NOCOOKIES /TRANSLATE $(downloading) $(downloadconnecting) $(downloadsecond) $(downloadminute) $(downloadhour) $(downloadplural) "%dkB (%d%%) of %dkB @ %d.%01dkB/s" " (%d %s%s $(downloadremaining))" "$DownloadURLActual" "$PLUGINSDIR\Downloaded\${DownloadName}" /END
+ ${Else}
+ inetc::get /CONNECTTIMEOUT 30 /NOCOOKIES /TRANSLATE "Downloading %s..." "Connecting..." second minute hour s "%dkB (%d%%) of %dkB @ %d.%01dkB/s" " (%d %s%s remaining)" "$DownloadURLActual" "$PLUGINSDIR\Downloaded\${DownloadName}" /END
+ ${EndIf}
+ SetDetailsPrint both
+ DetailPrint $InstallingStatusString
+ SetDetailsPrint ListOnly
+ Pop $DOWNLOADRESULT
+ ${If} $DOWNLOADRESULT == "OK"
+ Rename "$PLUGINSDIR\Downloaded\${DownloadName}" "$PLUGINSDIR\Downloaded\${DownloadFilename}"
+ StrCpy $DOWNLOADEDFILE "$PLUGINSDIR\Downloaded\${DownloadFilename}"
+ !ifdef DownloadMD5
+ md5dll::GetMD5File "$DOWNLOADEDFILE"
+ Pop $R0
+ ${If} $R0 != ${DownloadMD5}
+ ${If} $SECONDDOWNLOADATTEMPT != true
+ StrCpy $SECONDDOWNLOADATTEMPT true
+ Goto DownloadTheFile
+ ${EndIf}
+ StrCpy $MD5MISMATCH "true"
+
+ Delete "$INTERNET_CACHE\${DownloadFileName}"
+ Delete "$PLUGINSDIR\Downloaded\${DownloadFilename}"
+ SetDetailsPrint textonly
+ DetailPrint ""
+ SetDetailsPrint listonly
+ ${TBProgress_State} Error
+ ${If} $(downloadfilemismatch) != ""
+ MessageBox MB_OK|MB_ICONEXCLAMATION $(downloadfilemismatch)
+ DetailPrint $(downloadfilemismatch)
+ ${Else}
+ MessageBox MB_OK|MB_ICONEXCLAMATION `The downloaded copy of ${DownloadName} is not valid and can not be installed. Please try installing again.`
+ DetailPrint `The downloaded copy of ${DownloadName} is not valid and can not be installed. Please try installing again.`
+ ${EndIf}
+ ${TBProgress_State} NoProgress
+ Abort
+ ${EndIf}
+ !endif
+ ${Else}
+ Delete "$INTERNET_CACHE\${DownloadFileName}"
+ Delete "$PLUGINSDIR\Downloaded\${DownloadFilename}"
+ StrCpy $0 $DownloadURLActual
+
+ ;Use backup PA.c download server if necessary
+ ${WordFind} "$DownloadURLActual" "http://download2.portableapps.com" "#" $R0
+ ${If} $R0 == 1
+ ${WordReplace} "$DownloadURLActual" "http://download2.portableapps.com" "http://download.portableapps.com" "+" $DownloadURLActual
+ Goto DownloadTheFile
+ ${EndIf}
+
+ ${If} $SECONDDOWNLOADATTEMPT != true
+ ${AndIf} $DOWNLOADRESULT != "Cancelled"
+ StrCpy $SECONDDOWNLOADATTEMPT true
+ Goto DownloadTheFile
+ ${EndIf}
+ SetDetailsPrint textonly
+ DetailPrint ""
+ SetDetailsPrint listonly
+ ${TBProgress_State} Error
+ ${If} $(downloadfailed) != ""
+ MessageBox MB_OK|MB_ICONEXCLAMATION $(downloadfailed)
+ DetailPrint $(downloadfailed)
+ ${Else}
+ MessageBox MB_OK|MB_ICONEXCLAMATION `The installer was unable to download ${DownloadName}. The installation of the portable app will be incomplete without it. Please try installing again. (ERROR: $DOWNLOADRESULT)`
+ DetailPrint `The installer was unable to download ${DownloadName}. The installation of the portable app will be incomplete without it. Please try installing again. (ERROR: $DOWNLOADRESULT)`
+ ${EndIf}
+ ${TBProgress_State} NoProgress
+ Abort
+ ${EndIf}
+ ${EndIf}
+!endif
+
+!ifdef MAINSECTIONTITLE
+ SectionGetFlags 1 $0
+ IntOp $0 $0 & ${SF_SELECTED}
+ ${If} $0 != ${SF_SELECTED}
+ ;=== BEGIN: OPTIONAL NOT SELECTED CLEANUP CODE ===
+ ;This will be executed before install if the optional section (additional languages, etc) is not selected
+ !ifmacrodef CustomCodeOptionalCleanup
+ !insertmacro CustomCodeOptionalCleanup
+ !endif
+ ;=== END: OPTIONAL NOT SELECTED CLEANUP CODE ===
+ ${EndIf}
+!endif
+
+ ;=== BEGIN: PRE-INSTALL CODE ===
+ ;This will be executed before the app is installed. Useful for cleaning up files no longer used.
+ !ifmacrodef CustomCodePreInstall
+ !insertmacro CustomCodePreInstall
+ !endif
+ ;=== END: PRE-INSTALL CODE ===
+
+ ;=== Remove specific files
+ !macro RemoveFile _n
+ !ifdef REMOVEFILE${_n}
+ Delete `$INSTDIR\${REMOVEFILE${_n}}`
+ !endif
+ !macroend
+ ${!insertmacro1-10} RemoveFile
+
+ ;=== Rename the preserved files so they're not deleted in the next part
+ !macro PreserveFilePre _n
+ !ifdef PRESERVEFILE${_n}
+ ${GetFileName} `$INSTDIR\${PRESERVEFILE${_n}}` $1
+ ${GetParent} `$INSTDIR\${PRESERVEFILE${_n}}` $2
+ CreateDirectory `$INSTDIR\~PRESERVEFILE${_n}`
+ ${MoveFiles} DOS $1 $2 `$INSTDIR\~PRESERVEFILE${_n}`
+ !endif
+ !macroend
+ ${!insertmacro1-10} PreserveFilePre
+
+ ;=== Remove specific directories
+ !macro RemoveDirectory _n
+ !ifdef REMOVEDIRECTORY${_n}
+ RMDir /r `$INSTDIR\${REMOVEDIRECTORY${_n}}`
+ !endif
+ !macroend
+ ${!insertmacro1-10} RemoveDirectory
+
+ ;=== Rename the preserved directories so they're not deleted in the next part
+ !macro PreserveDirectoryPre _n
+ !ifdef PRESERVEDIRECTORY${_n}
+ Rename `$INSTDIR\${PRESERVEDIRECTORY${_n}}\` `$INSTDIR\~PRESERVEDIRECTORY${_n}\`
+ !endif
+ !macroend
+ ${!insertmacro1-10} PreserveDirectoryPre
+
+ ;=== Remove main directories if necessary
+ !ifdef REMOVEAPPDIRECTORY
+ !ifdef COMMONFILESPLUGIN
+ ${GetParent} $INSTDIR $0
+ ${For} $1 1 10
+ Rename `$INSTDIR\~PRESERVEFILE$1\` `$0\~PRESERVEFILE$1\`
+ Rename `$INSTDIR\~PRESERVEDIRECTORY$1\` `$0\~PRESERVEDIRECTORY$1\`
+ ${Next}
+ RMDir /r $INSTDIR
+ CreateDirectory $INSTDIR
+ ${For} $1 1 10
+ Rename `$0\~PRESERVEFILE$1\` `$INSTDIR\~PRESERVEFILE$1\`
+ Rename `$0\~PRESERVEDIRECTORY$1\` `$INSTDIR\~PRESERVEDIRECTORY$1\`
+ ${Next}
+ !else
+ RMDir /r `$INSTDIR\App`
+ !endif
+ !endif
+ !ifdef REMOVEDATADIRECTORY
+ RMDir /r `$INSTDIR\Data`
+ !endif
+ !ifdef REMOVEOTHERDIRECTORY
+ RMDir /r `$INSTDIR\Other`
+ !endif
+
+ ;=== Rename the preserved directories back to their proper names
+ !macro PreserveDirectoryPost _n
+ !ifdef PRESERVEDIRECTORY${_n}
+ ${GetParent} `$INSTDIR\${PRESERVEDIRECTORY${_n}}\` $R0
+ CreateDirectory $R0
+ Rename `$INSTDIR\~PRESERVEDIRECTORY${_n}\` `$INSTDIR\${PRESERVEDIRECTORY${_n}}\`
+ !endif
+ !macroend
+ ${!insertmacro1-10} PreserveDirectoryPost
+
+ ;=== Rename the preserved files back to their proper names
+ !macro PreserveFilePost _n
+ !ifdef PRESERVEFILE${_n}
+ ${GetFileName} `$INSTDIR\${PRESERVEFILE${_n}}` $1
+ ${GetParent} `$INSTDIR\${PRESERVEFILE${_n}}` $2
+ CreateDirectory $2
+ ${MoveFiles} DOS $1 `$INSTDIR\~PRESERVEFILE${_n}` $2
+ RMDir `$INSTDIR\~PRESERVEFILE${_n}`
+ !endif
+ !macroend
+ ${!insertmacro1-10} PreserveFilePost
+
+ ${If} $bolAppUpgrade == true
+ SetDetailsPrint both
+ DetailPrint $InstallingStatusString
+ SetDetailsPrint ListOnly
+ ${EndIf}
+
+ !ifndef PLUGININSTALLER
+ File /x thumbs.db "..\..\*.exe"
+ File /x thumbs.db "..\..\*.html"
+ SetOutPath $INSTDIR\App
+ File /r /x thumbs.db "..\..\App\*.*"
+ !else ifdef COMMONFILESPLUGIN
+ SetOutPath $INSTDIR
+ File /r /x thumbs.db /x PortableApps.comInstaller*.* "..\..\*.*"
+ !else ; non-CommonFiles plugin installer
+ SetOutPath $INSTDIR\Data
+ File /nonfatal /r /x thumbs.db "..\..\Data\*.*"
+ SetOutPath $INSTDIR\App
+ File /nonfatal /r /x thumbs.db "..\..\App\*.*"
+ !endif
+
+ SetOutPath $INSTDIR\Other
+ File /nonfatal /r /x thumbs.db /x PortableApps.comInstaller*.* "..\..\Other\*.*"
+
+ SetOutPath $INSTDIR\Other\Source
+ !ifdef USESCUSTOMCODE
+ !if ${__FILE__} == "PortableApps.comInstallerPlugin.nsi"
+ File "..\..\Other\Source\PortableApps.comInstallerPluginCustom.nsh"
+ !else
+ File "..\..\Other\Source\PortableApps.comInstallerCustom.nsh"
+ !endif
+ !endif
+ !ifndef PLUGININSTALLER
+ CreateDirectory "$INSTDIR\Data"
+ !endif
+
+ !ifdef INCLUDEINSTALLERSOURCE
+ File /r /x PortableApps.comInstallerCustom.nsh /x PortableApps.comInstallerPluginCustom.nsh "..\..\Other\Source\PortableApps.comInstaller*.*"
+ !endif
+
+ ;=== Extract Download Files
+ !ifdef DownloadURL
+ !ifdef DownloadTo
+ ;Just copy the file
+ CopyFiles /SILENT "$DOWNLOADEDFILE" "$INSTDIR\${DownloadTo}"
+ !else
+ ;Process the file
+ !ifdef Extract1To
+ ;Standard extract
+
+ !macro ExtractTo _n
+ !ifdef Extract${_n}To
+ CreateDirectory "$INSTDIR\${Extract${_n}To}"
+ nsisunz::UnzipToLog /file "${Extract${_n}File}" "$DOWNLOADEDFILE" "$INSTDIR\${Extract${_n}To}"
+ Pop $R0
+ ${If} $R0 <> "OK"
+ DetailPrint "ERROR: $R0 (${DownloadFilename} - ${Extract${_n}File})"
+ Abort
+ ${EndIf}
+ !endif
+ !macroend
+ ${!insertmacro1-10} ExtractTo
+ !endif
+ !ifdef AdvancedExtract1To
+ ;Advanced extract with 7zip
+ CreateDirectory "$INSTDIR\7zTemp"
+ SetOutPath "$INSTDIR\7zTemp"
+ File "${NSISDIR}\..\7zip\7z.exe"
+ File "${NSISDIR}\..\7zip\7z.dll"
+ SetOutPath $INSTDIR
+
+ ; The original code didn't have a !ifdef for 1, but we
+ ; know it will be defined, and it doesn't matter if we
+ ; check if it is because it will be.
+ !macro AdvancedExtractFilter _n
+ !ifdef AdvancedExtract${_n}To
+ CreateDirectory "$INSTDIR\${AdvancedExtract${_n}To}"
+ ${If} "${AdvancedExtract${_n}Filter}" == "**"
+ ExecDOS::exec `"$INSTDIR\7zTemp\7z.exe" x -r "$DOWNLOADEDFILE" -o"$INSTDIR\${AdvancedExtract${_n}To}" * -aoa -y` "" ""
+ ${Else}
+ ExecDOS::exec `"$INSTDIR\7zTemp\7z.exe" x "$DOWNLOADEDFILE" -o"$INSTDIR\${AdvancedExtract${_n}To}" "${AdvancedExtract${_n}Filter}" -aoa -y` "" ""
+ ${EndIf}
+ Pop $R0
+ ${If} $R0 <> 0
+ DetailPrint "ERROR: (${DownloadFilename} > ${AdvancedExtract${_n}To})"
+ Abort
+ ${EndIf}
+ !endif
+ !macroend
+ ${!insertmacro1-10} AdvancedExtractFilter
+
+ Delete "$INSTDIR\7zTemp\7z.dll"
+ Delete "$INSTDIR\7zTemp\7z.exe"
+ RMDir "$INSTDIR\7zTemp"
+ !endif
+ !ifdef DoubleExtractFilename
+ ;Double extract using 7zip
+ CreateDirectory "$INSTDIR\7zTemp"
+ SetOutPath "$INSTDIR\7zTemp"
+ File "${NSISDIR}\..\7zip\7z.exe"
+ File "${NSISDIR}\..\7zip\7z.dll"
+ SetOutPath $INSTDIR
+
+ CreateDirectory "$PLUGINSDIR\Downloaded2"
+ ExecDOS::exec `"$INSTDIR\7zTemp\7z.exe" x "$DOWNLOADEDFILE" -o"$PLUGINSDIR\Downloaded2" "${DoubleExtractFilename}" -aoa -y` "" ""
+ Pop $R0
+ ${If} $R0 <> 0
+ DetailPrint "ERROR: (${DownloadFilename} > ${DoubleExtractFilename})"
+ Abort
+ ${EndIf}
+
+ ; The original code didn't have a !ifdef for 1, but we
+ ; know it will be defined, and it doesn't matter if we
+ ; check if it is because it will be.
+ !macro DoubleExtractTo _n
+ !ifdef DoubleExtract${_n}To
+ CreateDirectory "$INSTDIR\${DoubleExtract${_n}To}"
+ ${If} "${DoubleExtract${_n}Filter}" == "**"
+ ExecDOS::exec `"$INSTDIR\7zTemp\7z.exe" x -r "$PLUGINSDIR\Downloaded2\${DoubleExtractFilename}" -o"$INSTDIR\${DoubleExtract${_n}To}" * -aoa -y` "" ""
+ ${Else}
+ ExecDOS::exec `"$INSTDIR\7zTemp\7z.exe" x "$PLUGINSDIR\Downloaded2\${DoubleExtractFilename}" -o"$INSTDIR\${DoubleExtract${_n}To}" "${DoubleExtract${_n}Filter}" -aoa -y` "" ""
+ ${EndIf}
+ Pop $R0
+ ${If} $R0 <> 0
+ DetailPrint "ERROR: (${DoubleExtractFilename} > ${DoubleExtract${_n}To})"
+ Abort
+ ${EndIf}
+ !endif
+ !macroend
+ ${!insertmacro1-10} DoubleExtractTo
+
+ Delete "$INSTDIR\7zTemp\7z.exe"
+ Delete "$INSTDIR\7zTemp\7z.dll"
+ RMDir "$INSTDIR\7zTemp"
+ !endif
+ !endif
+ !endif
+
+ ;=== Copy Local Files
+ !ifdef COPYLOCALFILES
+ ${If} ${FileExists} "$CopyLocalFilesFrom\*.*"
+ CreateDirectory "$INSTDIR\${CopyToDirectory}"
+ CopyFiles /SILENT "$CopyLocalFilesFrom\*.*" "$INSTDIR\${CopyToDirectory}"
+ ${Else}
+ StrCpy $MISSINGFILEORPATH $CopyLocalFilesFrom
+ ${If} $(copylocalfilesnotfound) != ""
+ MessageBox MB_OK|MB_ICONINFORMATION $(copylocalfilesnotfound)
+ ${Else}
+ MessageBox MB_OK|MB_ICONINFORMATION `This installer copies a local version of the application and makes it portable. Unfortunately, a local copy of the application was not found. You may reinstall or copy the files yourself to complete the installation at a later time. (ERROR: $MISSINGFILEORPATH could not be found.)`
+ ${EndIf}
+ ${EndIf}
+ !endif
+
+ ;=== BEGIN: POST-INSTALL CODE ===
+ ;This will be executed after the app is installed. Useful for updating configuration files.
+ !ifmacrodef CustomCodePostInstall
+ !insertmacro CustomCodePostInstall
+ !endif
+ ;=== END: POST-INSTALL CODE ===
+
+ !ifndef PLUGININSTALLER
+ ;=== Refresh PortableApps.com Menu (not final version)
+ ${GetParent} $INSTDIR $0
+ ;=== Check that it exists at the right location
+ SetDetailsPrint both
+ DetailPrint '$(checkforplatform)'
+ ${If} ${FileExists} `$0\PortableApps.com\PortableAppsPlatform.exe`
+ ;=== Check that it's the real deal so we aren't hanging with no response
+ MoreInfo::GetProductName `$0\PortableApps.com\PortableAppsPlatform.exe`
+ Pop $1
+ ${If} $1 == "PortableApps.com Platform"
+ MoreInfo::GetCompanyName `$0\PortableApps.com\PortableAppsPlatform.exe`
+ Pop $1
+ ${If} $1 == "PortableApps.com"
+
+ ;=== Check that it's running
+ FindProcDLL::FindProc "PortableAppsPlatform.exe"
+ ${If} $R0 == "1"
+
+ ;=== Send message for the Menu to refresh
+ CreateDirectory "$0\PortableApps.com\Data"
+ WriteINIStr "$0\PortableApps.com\Data\NewApp.ini" "NewApp" "AppID" "${APPID}"
+
+ DetailPrint '$(refreshmenu)'
+ ${IfNot} ${FileExists} `$0\PortableApps.com\App\PortableAppsPlatform.exe`
+ StrCpy $2 'PortableApps.comPlatformWindowMessageToRefresh$0\PortableApps.com\PortableAppsPlatform.exe'
+ System::Call "user32::RegisterWindowMessage(t r2) i .r3"
+ SendMessage 65535 $3 0 0 /TIMEOUT=1
+ ${Else} ; old message
+ StrCpy $2 'PortableApps.comPlatformWindowMessageToRefresh$0\PortableApps.com\App\PortableAppsPlatform.exe'
+ System::Call "user32::RegisterWindowMessage(t r2) i .r3"
+ SendMessage 65535 $3 0 0 /TIMEOUT=1
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+ !endif
+ DetailPrint $InstallingStatusString
+ SetDetailsPrint listonly
+ Delete "$INSTDIR\7zTemp\7z.exe"
+ Delete "$INSTDIR\7zTemp\7z.dll"
+ RMDir "$INSTDIR\7zTemp"
+
+!ifdef LICENSEAGREEMENT
+ CreateDirectory "$INSTDIR\Data\PortableApps.comInstaller"
+ WriteINIStr "$INSTDIR\Data\PortableApps.comInstaller\license.ini" "PortableApps.comInstaller" "EULAVersion" $INTERNALEULAVERSION
+ ClearErrors
+!endif
+
+!ifdef DownloadURL
+ Delete "$INTERNET_CACHE\${DownloadFileName}"
+!endif
+ ${If} $bolLogFile == true
+ ${DumpLogToFile} "$EXEDIR\$EXEFILE.log"
+ ${EndIf}
+ SetOutPath $INSTDIR
+SectionEnd
+
+!ifdef MAINSECTIONTITLE
+ Section /o "${OPTIONALSECTIONTITLE}"
+ SetOutPath $INSTDIR
+ File /r "..\..\Optional1\*.*"
+ StrCpy $OPTIONAL1DONE "true"
+ SectionEnd
+
+ Section "-UpdateAppInfo" SecUpdateAppInfo
+ !ifndef PLUGININSTALLER
+ ${If} $OPTIONAL1DONE != "true"
+ ${AndIf} "${OPTIONALSECTIONNOTSELECTEDINSTALLTYPE}" != ""
+ WriteINIStr "$INSTDIR\App\AppInfo\appinfo.ini" "Details" "InstallType" "${OPTIONALSECTIONNOTSELECTEDINSTALLTYPE}"
+ ${ElseIf} "${OPTIONALSECTIONSELECTEDINSTALLTYPE}" != ""
+ WriteINIStr "$INSTDIR\App\AppInfo\appinfo.ini" "Details" "InstallType" "${OPTIONALSECTIONSELECTEDINSTALLTYPE}"
+ ${EndIf}
+ !endif
+ SectionEnd
+
+ !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${MAINSECTIONIDX} "${MAINSECTIONDESCRIPTION}"
+ !insertmacro MUI_DESCRIPTION_TEXT ${OPTIONALSECTIONIDX} "${OPTIONALSECTIONDESCRIPTION}"
+ !insertmacro MUI_FUNCTION_DESCRIPTION_END
+!endif
+
+Function .onInstFailed
+ !ifdef COPYLOCALFILES
+ ${registry::Unload}
+ !endif
+ RMDir $INSTDIR ;remove directory if empty
+FunctionEnd
+
+!ifdef COPYLOCALFILES
+ Function .onInstSuccess
+ ${registry::Unload}
+ FunctionEnd
+ Function CustomAbortFunction
+ ${registry::Unload}
+ FunctionEnd
+!endif
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerConfig.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerConfig.nsh
new file mode 100644
index 000000000..bbf1e31c7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerConfig.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerCustom.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerCustom.nsh
new file mode 100644
index 000000000..25dbbad43
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerCustom.nsh
@@ -0,0 +1,5 @@
+!macro CustomCodePostInstall
+CopyFiles /SILENT "$INSTDIR\App\Greenshot\Greenshot.exe.config" "$INSTDIR\"
+ReadINIStr $0 "$INSTDIR\App\AppInfo\appinfo.ini" "Version" "PackageVersion"
+ExecShell "open" "http://getgreenshot.org/thank-you/?language=en-US&version=$0"
+!macroend
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerDumpLogToFile.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerDumpLogToFile.nsh
new file mode 100644
index 000000000..180cd81a8
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerDumpLogToFile.nsh
@@ -0,0 +1,62 @@
+;http://nsis.sourceforge.net/Docs/AppendixD.html#D.4
+;Define added by John T. Haller of PortableApps.com
+
+;NOTE - Not yet used. Added for future reference.
+
+!ifndef DumpLogToFile
+
+!define DumpLogToFile "!insertmacro DumpLogToFile"
+!macro DumpLogToFile logfilename
+ Delete `${logfilename}`
+ push `${logfilename}`
+ call DumpLog
+!macroend
+
+!define LVM_GETITEMCOUNT 0x1004
+!define LVM_GETITEMTEXT 0x1073
+
+Function DumpLog
+ Exch $5
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $6
+
+ FindWindow $0 "#32770" "" $HWNDPARENT
+ GetDlgItem $0 $0 1016
+ StrCmp $0 0 error
+ FileOpen $5 $5 "w"
+ FileWriteWord $5 0xfeff ; Write the BOM
+ StrCmp $5 0 error
+ SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
+ System::StrAlloc ${NSIS_MAX_STRLEN}
+ Pop $3
+ StrCpy $2 0
+ System::Call "*(i, i, i, i, i, i, i, i, i) i \
+ (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
+ loop: StrCmp $2 $6 done
+ System::Call "User32::SendMessageW(i, i, i, i) i \
+ ($0, ${LVM_GETITEMTEXT}, $2, r1)"
+ System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
+ FileWriteUTF16LE $5 "$4$\r$\n"
+ IntOp $2 $2 + 1
+ Goto loop
+ done:
+ FileClose $5
+ System::Free $1
+ System::Free $3
+ Goto exit
+ error:
+ ;MessageBox MB_OK error
+ exit:
+ Pop $6
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $5
+FunctionEnd
+!endif
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Afrikaans.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Afrikaans.nsh
new file mode 100644
index 000000000..1ab502355
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Afrikaans.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Albanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Albanian.nsh
new file mode 100644
index 000000000..e08e0c985
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Albanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Arabic.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Arabic.nsh
new file mode 100644
index 000000000..961c7ec12
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Arabic.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Armenian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Armenian.nsh
new file mode 100644
index 000000000..be22d1312
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Armenian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Basque.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Basque.nsh
new file mode 100644
index 000000000..549999952
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Basque.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Belarusian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Belarusian.nsh
new file mode 100644
index 000000000..5c453841c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Belarusian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bosnian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bosnian.nsh
new file mode 100644
index 000000000..60e537169
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bosnian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Breton.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Breton.nsh
new file mode 100644
index 000000000..ceda00b58
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Breton.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bulgarian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bulgarian.nsh
new file mode 100644
index 000000000..29f08efaa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Bulgarian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Catalan.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Catalan.nsh
new file mode 100644
index 000000000..e648e87f8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Catalan.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Cibemba.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Cibemba.nsh
new file mode 100644
index 000000000..27414b458
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Cibemba.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Croatian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Croatian.nsh
new file mode 100644
index 000000000..a05268fad
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Croatian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Czech.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Czech.nsh
new file mode 100644
index 000000000..e59f3cfdb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Czech.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Danish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Danish.nsh
new file mode 100644
index 000000000..2806d4835
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Danish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Dutch.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Dutch.nsh
new file mode 100644
index 000000000..31ceeba6c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Dutch.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Efik.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Efik.nsh
new file mode 100644
index 000000000..08f2d22e8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Efik.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/English.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/English.nsh
new file mode 100644
index 000000000..f78c3ee50
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/English.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/EnglishGB.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/EnglishGB.nsh
new file mode 100644
index 000000000..ea4278e08
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/EnglishGB.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Esperanto.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Esperanto.nsh
new file mode 100644
index 000000000..5bcff5e2f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Esperanto.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Estonian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Estonian.nsh
new file mode 100644
index 000000000..fd68a3416
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Estonian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Farsi.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Farsi.nsh
new file mode 100644
index 000000000..9ccedd431
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Farsi.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Finnish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Finnish.nsh
new file mode 100644
index 000000000..1229b5be8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Finnish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/French.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/French.nsh
new file mode 100644
index 000000000..c1bff71ff
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/French.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Galician.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Galician.nsh
new file mode 100644
index 000000000..35162c3f3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Galician.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Georgian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Georgian.nsh
new file mode 100644
index 000000000..8980079b4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Georgian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/German.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/German.nsh
new file mode 100644
index 000000000..c36e18416
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/German.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Greek.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Greek.nsh
new file mode 100644
index 000000000..e999dc67d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Greek.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hebrew.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hebrew.nsh
new file mode 100644
index 000000000..dcbbea08a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hebrew.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hungarian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hungarian.nsh
new file mode 100644
index 000000000..be2ce378b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Hungarian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Icelandic.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Icelandic.nsh
new file mode 100644
index 000000000..894c08b3b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Icelandic.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Igbo.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Igbo.nsh
new file mode 100644
index 000000000..f98f7476e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Igbo.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Indonesian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Indonesian.nsh
new file mode 100644
index 000000000..ee41db8c0
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Indonesian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Irish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Irish.nsh
new file mode 100644
index 000000000..a50c78bd1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Irish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Italian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Italian.nsh
new file mode 100644
index 000000000..1e2f2d1b2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Italian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Japanese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Japanese.nsh
new file mode 100644
index 000000000..43274e06d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Japanese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Khmer.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Khmer.nsh
new file mode 100644
index 000000000..4397ebb1b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Khmer.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Korean.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Korean.nsh
new file mode 100644
index 000000000..b88ef5510
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Korean.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Kurdish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Kurdish.nsh
new file mode 100644
index 000000000..0deedd644
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Kurdish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Latvian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Latvian.nsh
new file mode 100644
index 000000000..ee02c8429
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Latvian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Lithuanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Lithuanian.nsh
new file mode 100644
index 000000000..eeff7057d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Lithuanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Luxembourgish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Luxembourgish.nsh
new file mode 100644
index 000000000..a674cf2d2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Luxembourgish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Macedonian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Macedonian.nsh
new file mode 100644
index 000000000..43363ebc0
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Macedonian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malagasy.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malagasy.nsh
new file mode 100644
index 000000000..498b87dcf
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malagasy.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malay.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malay.nsh
new file mode 100644
index 000000000..d128c19fc
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Malay.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Mongolian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Mongolian.nsh
new file mode 100644
index 000000000..8155e94a4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Mongolian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Norwegian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Norwegian.nsh
new file mode 100644
index 000000000..98fffbd43
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Norwegian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/NorwegianNynorsk.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/NorwegianNynorsk.nsh
new file mode 100644
index 000000000..12aed3819
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/NorwegianNynorsk.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Pashto.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Pashto.nsh
new file mode 100644
index 000000000..732b06e37
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Pashto.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Polish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Polish.nsh
new file mode 100644
index 000000000..04a98f24d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Polish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Portuguese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Portuguese.nsh
new file mode 100644
index 000000000..9fadcd98f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Portuguese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/PortugueseBR.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/PortugueseBR.nsh
new file mode 100644
index 000000000..3e96593a6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/PortugueseBR.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Romanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Romanian.nsh
new file mode 100644
index 000000000..fa6bfea23
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Romanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Russian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Russian.nsh
new file mode 100644
index 000000000..772cc4ff6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Russian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Serbian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Serbian.nsh
new file mode 100644
index 000000000..36db0a76a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Serbian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SerbianLatin.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SerbianLatin.nsh
new file mode 100644
index 000000000..0042eada3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SerbianLatin.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SimpChinese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SimpChinese.nsh
new file mode 100644
index 000000000..373016efa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SimpChinese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovak.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovak.nsh
new file mode 100644
index 000000000..338bb0dc4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovak.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovenian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovenian.nsh
new file mode 100644
index 000000000..6ac04ea3d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Slovenian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Spanish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Spanish.nsh
new file mode 100644
index 000000000..962549440
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Spanish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SpanishInternational.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SpanishInternational.nsh
new file mode 100644
index 000000000..be9738f74
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/SpanishInternational.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swahili.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swahili.nsh
new file mode 100644
index 000000000..9659d04e5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swahili.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swedish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swedish.nsh
new file mode 100644
index 000000000..4519c17d7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Swedish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Thai.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Thai.nsh
new file mode 100644
index 000000000..d0578b00f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Thai.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/TradChinese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/TradChinese.nsh
new file mode 100644
index 000000000..914c4ce64
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/TradChinese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Turkish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Turkish.nsh
new file mode 100644
index 000000000..eb3ece757
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Turkish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Ukrainian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Ukrainian.nsh
new file mode 100644
index 000000000..6ad7c263e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Ukrainian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Uzbek.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Uzbek.nsh
new file mode 100644
index 000000000..297e6a3bd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Uzbek.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Valencian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Valencian.nsh
new file mode 100644
index 000000000..05e1e1366
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Valencian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Vietnamese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Vietnamese.nsh
new file mode 100644
index 000000000..59afdcdef
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Vietnamese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Welsh.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Welsh.nsh
new file mode 100644
index 000000000..f00460a44
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Welsh.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Yoruba.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Yoruba.nsh
new file mode 100644
index 000000000..be845c758
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerLanguages/Yoruba.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerMoveFiles.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerMoveFiles.nsh
new file mode 100644
index 000000000..451ab65ee
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerMoveFiles.nsh
@@ -0,0 +1,104 @@
+; Copyright (c) 2008, Harold E Austin Jr
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are met:
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+; * Neither the name of the organization nor the
+; names of its contributors may be used to endorse or promote products
+; derived from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY Harold E Austin Jr ``AS IS'' AND ANY
+; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL Harold E Austin Jr BE LIABLE FOR ANY
+; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+ MoveFiles.nsh -- version 1.0 (May 5, 2008)
+ move files matching "filespec" from "source-directory" to "destination-directory"
+
+ usage:
+ !include MoveFiles.nsh
+
+ ${MoveFiles} mode "filespec" "source-directory" "destination-directory"
+
+ where:
+ mode can be DOS, DIR, FORCE or DIR+FORCE (anything else = DOS):
+ DOS means act like the DOS MOVE command (move only files)
+ DIR means move files AND directories
+ FORCE means overwrite destination files (like MOVE/Y)
+
+ example:
+ CreateDirectory "C:\NEW\DIR"
+ DetailPrint "Moving files and directories..."
+ ${MoveFiles} DIR+FORCE "*" "C:\OLD\DIR" "C:\NEW\DIR"
+ DetailPrint `"Processing"...`
+ Sleep 2000
+ DetailPrint "Moving only the files back..."
+ ${MoveFiles} DOS "*" "C:\NEW\DIR" "C:\OLD\DIR"
+ DetailPrint "Moving the directories back..."
+ ${MoveFiles} DIR "*" "C:\NEW\DIR" "C:\OLD\DIR"
+*/
+!ifndef MoveFiles
+!define MoveFiles "!insertmacro MoveFiles"
+!macro MoveFiles mode filespec sourcedir destdir
+ push `${destdir}`
+ push `${sourcedir}`
+ push `${filespec}`
+ push `${mode}`
+ call MoveFiles
+!macroend
+
+Function MoveFiles ; mode filespec sourcedir destdir
+ Exch $0 ; mode, directory mode
+ Exch
+ Exch $1 ; filespec, force mode
+ Exch 2
+ Exch $2 ; source directory
+ Exch 3
+ Exch $3 ; destination directory
+ Push $4 ; FindFirst/FindNext search handle
+ Push $5 ; current filename matching filespec in sourcedir
+ FindFirst $4 $5 "$2\$1"
+ StrCpy $1 "" ; FORCE mode disabled by default
+ StrCmp $0 FORCE 0 +2
+ StrCpy $1 FORCE
+ StrCmp $0 DIR+FORCE 0 +3
+ StrCpy $0 DIR
+ StrCpy $1 FORCE
+ loop:
+ StrCmp $5 "" done ; $5 == "", if no more matching files
+ StrCmp $5 . next
+ StrCmp $5 .. next
+ StrCmp $0 DIR +2
+ ; DIR mode disabled: ignore directories that match ${filespec}
+ IfFileExists "$2\$5\*.*" next
+ StrCmp $1 FORCE 0 +4
+ ; FORCE mode: make sure destination doesn't exist
+ Delete "$3\$5"
+ StrCmp $0 DIR 0 +2
+ RMDir /R "$3\$5"
+ Rename "$2\$5" "$3\$5"
+ next:
+ FindNext $4 $5
+ Goto loop
+ done:
+ FindClose $4 ; finished with this search; close handle
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $0
+ Pop $1
+ Pop $2
+FunctionEnd
+!endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerTBProgress.nsh b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerTBProgress.nsh
new file mode 100644
index 000000000..7fa976961
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/installer/PortableApps.comInstallerTBProgress.nsh
@@ -0,0 +1,59 @@
+!include "LogicLib.nsh"
+
+!ifndef CLSCTX_INPROC_SERVER
+ !define CLSCTX_INPROC_SERVER 1
+!endif
+
+!define CLSID_ITaskbarList {56fdf344-fd6d-11d0-958a-006097c9a090}
+
+!define IID_ITaskbarList3 {ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}
+!define ITaskbarList3->SetProgressState $ITaskbarList3->10
+!define ITaskbarList3->SetProgressValue $ITaskbarList3->9
+
+!define TBPF_NOPROGRESS 0x00000000 ; Normal state / no progress bar
+!define TBPF_INDETERMINATE 0x00000001 ; Marquee style progress bar
+!define TBPF_NORMAL 0x00000002 ; Standard progress bar
+!define TBPF_ERROR 0x00000004 ; Red taskbar button to indicate an error occurred
+!define TBPF_PAUSED 0x00000008 ; Yellow taskbar button to indicate user attention
+ ; (input) is required to resume progress
+
+Var ITaskbarList3
+
+!macro TBProgress_Init
+ !ifndef TBProgressInitialized
+ !define TBProgressInitialized
+ ${Unless} ${Silent}
+ System::Call "ole32::CoCreateInstance( \
+ g '${CLSID_ITaskbarList}', \
+ i 0, \
+ i ${CLSCTX_INPROC_SERVER}, \
+ g '${IID_ITaskbarList3}', \
+ *i .s)"
+ Pop $ITaskbarList3
+ ${Else}
+ StrCpy $ITaskbarList3 0
+ ${EndIf}
+ !endif
+!macroend
+!define TBProgress_Init `!insertmacro TBProgress_Init`
+
+!macro TBProgress_Progress Val Max
+ ${TBProgress_Init}
+ ${If} $ITaskbarList3 <> 0
+ System::Call "${ITaskbarList3->SetProgressValue}(i$HWNDPARENT, l${Val}, l${Max})"
+ ${EndIf}
+!macroend
+!define TBProgress_Progress `!insertmacro TBProgress_Progress`
+
+!macro TBProgress Val
+ ${TBProgress_Progress} ${Val} 100
+!macroend
+!define TBProgress `!insertmacro TBProgress`
+
+!macro TBProgress_State State
+ ${TBProgress_Init}
+ ${If} $ITaskbarList3 <> 0
+ System::Call "${ITaskbarList3->SetProgressState}(i$HWNDPARENT, i${TBPF_${State}})"
+ ${EndIf}
+!macroend
+!define TBProgress_State `!insertmacro TBProgress_State`
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/GenPat.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/GenPat.exe
new file mode 100644
index 000000000..04373fcb5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/GenPat.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/LibraryLocal.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/LibraryLocal.exe
new file mode 100644
index 000000000..39063e90a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/LibraryLocal.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/MakeLangId.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/MakeLangId.exe
new file mode 100644
index 000000000..16ade1390
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/MakeLangId.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/RegTool.bin b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/RegTool.bin
new file mode 100644
index 000000000..5d11756f2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/RegTool.bin differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/zip2exe.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/zip2exe.exe
new file mode 100644
index 000000000..6a3354093
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Bin/zip2exe.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/COPYING b/Greenshot/tools/PortableApps.comInstaller/App/nsis/COPYING
new file mode 100644
index 000000000..afd4902ab
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/COPYING differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/ExDll/exdll.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/ExDll/exdll.h
new file mode 100644
index 000000000..0e69c1cdd
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/ExDll/exdll.h
@@ -0,0 +1,116 @@
+#ifndef _EXDLL_H_
+#define _EXDLL_H_
+
+// only include this file from one place in your DLL.
+// (it is all static, if you use it in two places it will fail)
+
+#define EXDLL_INIT() { \
+ g_stringsize=string_size; \
+ g_stacktop=stacktop; \
+ g_variables=variables; }
+
+// For page showing plug-ins
+#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
+#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)
+#define NOTIFY_BYE_BYE 'x'
+
+typedef struct _stack_t {
+ struct _stack_t *next;
+ TCHAR text[1]; // this should be the length of string_size
+} stack_t;
+
+
+static unsigned int g_stringsize;
+static stack_t **g_stacktop;
+static TCHAR *g_variables;
+
+static int __stdcall popstring(TCHAR *str); // 0 on success, 1 on empty stack
+static void __stdcall pushstring(const TCHAR *str);
+
+enum
+{
+INST_0, // $0
+INST_1, // $1
+INST_2, // $2
+INST_3, // $3
+INST_4, // $4
+INST_5, // $5
+INST_6, // $6
+INST_7, // $7
+INST_8, // $8
+INST_9, // $9
+INST_R0, // $R0
+INST_R1, // $R1
+INST_R2, // $R2
+INST_R3, // $R3
+INST_R4, // $R4
+INST_R5, // $R5
+INST_R6, // $R6
+INST_R7, // $R7
+INST_R8, // $R8
+INST_R9, // $R9
+INST_CMDLINE, // $CMDLINE
+INST_INSTDIR, // $INSTDIR
+INST_OUTDIR, // $OUTDIR
+INST_EXEDIR, // $EXEDIR
+INST_LANG, // $LANGUAGE
+__INST_LAST
+};
+
+typedef struct {
+ int autoclose;
+ int all_user_var;
+ int exec_error;
+ int abort;
+ int exec_reboot;
+ int reboot_called;
+ int cur_insttype;
+ int insttype_changed;
+ int silent;
+ int instdir_error;
+ int rtl;
+ int errlvl;
+} exec_flags;
+
+typedef struct {
+ exec_flags *exec_flags;
+ int (__stdcall *ExecuteCodeSegment)(int, HWND);
+} extra_parameters;
+
+// utility functions (not required but often useful)
+static int __stdcall popstring(TCHAR *str)
+{
+ stack_t *th;
+ if (!g_stacktop || !*g_stacktop) return 1;
+ th=(*g_stacktop);
+ lstrcpy(str,th->text);
+ *g_stacktop = th->next;
+ GlobalFree((HGLOBAL)th);
+ return 0;
+}
+
+static void __stdcall pushstring(const TCHAR *str)
+{
+ stack_t *th;
+ if (!g_stacktop) return;
+ th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize*sizeof(TCHAR));
+ lstrcpyn(th->text,str,g_stringsize);
+ th->next=*g_stacktop;
+ *g_stacktop=th;
+}
+
+static TCHAR * __stdcall getuservariable(const int varnum)
+{
+ if (varnum < 0 || varnum >= __INST_LAST) return NULL;
+ return g_variables+varnum*g_stringsize;
+}
+
+static void __stdcall setuservariable(const int varnum, const TCHAR *var)
+{
+ if (var != NULL && varnum >= 0 && varnum < __INST_LAST)
+ lstrcpy(g_variables + varnum*g_stringsize, var);
+}
+
+
+
+#endif//_EXDLL_H_
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/big.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/big.bmp
new file mode 100644
index 000000000..d6db07793
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/big.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic-cross.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic-cross.bmp
new file mode 100644
index 000000000..a4d37a14a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic-cross.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic.bmp
new file mode 100644
index 000000000..83e3cf565
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/classic.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/colorful.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/colorful.bmp
new file mode 100644
index 000000000..7713942e0
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/colorful.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey-cross.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey-cross.bmp
new file mode 100644
index 000000000..b28b59bbc
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey-cross.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey.bmp
new file mode 100644
index 000000000..b374432b7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/grey.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/modern.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/modern.bmp
new file mode 100644
index 000000000..62468dedc
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/modern.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red-round.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red-round.bmp
new file mode 100644
index 000000000..31d3c0252
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red-round.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red.bmp
new file mode 100644
index 000000000..e14e6b4a0
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/red.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round.bmp
new file mode 100644
index 000000000..695023224
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round2.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round2.bmp
new file mode 100644
index 000000000..ee1ec8427
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple-round2.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple.bmp
new file mode 100644
index 000000000..c687a1d92
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Checks/simple.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis-r.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis-r.bmp
new file mode 100644
index 000000000..eb3650f7d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis-r.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis.bmp
new file mode 100644
index 000000000..cbb52312f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-nsis.bmp
new file mode 100644
index 000000000..b4a0cf94b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r-nsis.bmp
new file mode 100644
index 000000000..2da34f174
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r.bmp
new file mode 100644
index 000000000..c74fbdd51
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-r.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-nsis.bmp
new file mode 100644
index 000000000..635596b20
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r-nsis.bmp
new file mode 100644
index 000000000..5f215d774
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r.bmp
new file mode 100644
index 000000000..1672afa6d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall-r.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall.bmp
new file mode 100644
index 000000000..97be6746e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange-uninstall.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange.bmp
new file mode 100644
index 000000000..4ac1413b3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/orange.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/win.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/win.bmp
new file mode 100644
index 000000000..6612357a3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Header/win.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-install.ico
new file mode 100644
index 000000000..0441d5cef
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-uninstall.ico
new file mode 100644
index 000000000..f3e7bfed3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-install.ico
new file mode 100644
index 000000000..e047f7db4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-uninstall.ico
new file mode 100644
index 000000000..fa6064fab
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/arrow2-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-install.ico
new file mode 100644
index 000000000..fd6c7c1f3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-uninstall.ico
new file mode 100644
index 000000000..bc275415f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/box-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-install.ico
new file mode 100644
index 000000000..5afcc62e8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-uninstall.ico
new file mode 100644
index 000000000..09532909e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/classic-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-blue.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-blue.ico
new file mode 100644
index 000000000..08288b6dd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-blue.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-grey.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-grey.ico
new file mode 100644
index 000000000..4749479fa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/llama-grey.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue-full.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue-full.ico
new file mode 100644
index 000000000..8f1c51222
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue-full.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue.ico
new file mode 100644
index 000000000..fecdc2739
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-blue.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-colorful.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-colorful.ico
new file mode 100644
index 000000000..2908f58be
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-colorful.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-full.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-full.ico
new file mode 100644
index 000000000..3aa83e9f4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install-full.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install.ico
new file mode 100644
index 000000000..f8fbd5ffa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue-full.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue-full.ico
new file mode 100644
index 000000000..cd9227971
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue-full.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue.ico
new file mode 100644
index 000000000..77031b58e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-blue.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-colorful.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-colorful.ico
new file mode 100644
index 000000000..461035cc2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-colorful.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-full.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-full.ico
new file mode 100644
index 000000000..a134f586c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall-full.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall.ico
new file mode 100644
index 000000000..6c7410c2f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/modern-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-install.ico
new file mode 100644
index 000000000..e18044928
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-uninstall.ico
new file mode 100644
index 000000000..a37774cf3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/nsis1-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install-nsis.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install-nsis.ico
new file mode 100644
index 000000000..ef3975f56
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install-nsis.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install.ico
new file mode 100644
index 000000000..1db75f8e4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall-nsis.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall-nsis.ico
new file mode 100644
index 000000000..431eb2e0f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall-nsis.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall.ico
new file mode 100644
index 000000000..59c79f32b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/orange-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-install.ico
new file mode 100644
index 000000000..f2106d611
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-uninstall.ico
new file mode 100644
index 000000000..2003b2df8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/pixel-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-install.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-install.ico
new file mode 100644
index 000000000..a5eb774b3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-install.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-uninstall.ico b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-uninstall.ico
new file mode 100644
index 000000000..932917696
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Icons/win-uninstall.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/arrow.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/arrow.bmp
new file mode 100644
index 000000000..9f7426bc8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/arrow.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/llama.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/llama.bmp
new file mode 100644
index 000000000..1e1d94251
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/llama.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nsis.bmp
new file mode 100644
index 000000000..dcc38094c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nullsoft.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nullsoft.bmp
new file mode 100644
index 000000000..d4145d4ff
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/nullsoft.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-nsis.bmp
new file mode 100644
index 000000000..ec46bd852
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall-nsis.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall-nsis.bmp
new file mode 100644
index 000000000..661e70232
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall-nsis.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall.bmp
new file mode 100644
index 000000000..097d09429
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange-uninstall.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange.bmp
new file mode 100644
index 000000000..196a5b7a7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/orange.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/win.bmp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/win.bmp
new file mode 100644
index 000000000..5524eef94
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Graphics/Wizard/win.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Example.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Example.nsi
new file mode 100644
index 000000000..2f95e06b6
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Example.nsi
@@ -0,0 +1,53 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc plug-in Test"
+OutFile "inetc.exe"
+;SilentInstall silent
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_WELCOME
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+;SetFont 14
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+ SetDetailsView hide
+
+; two files download, popup mode
+ inetc::get /caption "2003-2004 reports" /popup "" "http://ineum.narod.ru/spr_2003.htm" "$EXEDIR\spr3.htm" "http://ineum.narod.ru/spr_2004.htm" "$EXEDIR\spr4.htm" /end
+ Pop $0 # return value = exit code, "OK" means OK
+
+; single file, NSISdl-style embedded progress bar with specific cancel button text
+ inetc::get /caption "2005 report" /canceltext "interrupt!" "http://ineum.narod.ru/spr_2005.htm" "$EXEDIR\spr5.htm" /end
+ Pop $1 # return value = exit code, "OK" means OK
+
+; banner with 2 text lines and disabled Cancel button
+ inetc::get /caption "2006 report" /banner "Banner mode with /nocancel option setten$\nSecond Line" /nocancel "http://ineum.narod.ru/spr_2006.htm" "$EXEDIR\spr6.htm" /end
+ Pop $2 # return value = exit code, "OK" means OK
+
+ MessageBox MB_OK "Download Status: $0, $1, $2"
+SectionEnd
+
+
+;--------------------------------
+;Installer Functions
+
+Function .onInit
+
+; plug-in auto-recognizes 'no parent dlg' in onInit and works accordingly
+; inetc::head /RESUME "Network error. Retry?" "http://ineum.narod.ru/spr_2003.htm" "$EXEDIR\spr3.txt"
+; Pop $4
+
+FunctionEnd
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Readme.htm b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Readme.htm
new file mode 100644
index 000000000..40e0f4766
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/Readme.htm
@@ -0,0 +1,140 @@
+
+
Contents
+
+1 Links
+ 2 Description
+ 3 Command line
+
+3.1 get DLL Function
+ 3.2 post DLL Function
+ 3.3 head DLL Function
+ 3.4 put DLL Function
+
+ 4 Examples
+ 5 Credits
+
+
+
+Links
+Download: http://nsis.sourceforge.net/Inetc_plug-in
+
+Description
+Internet client plug-in for files download and upload. Based on the InetLoad plug-in.
+Network implementation uses MS WinInet API, supports http/https and ftp protocols.
+Plugin has better proxy support compare to NSISdl plug-in. Command line may include
+few URL/File pairs to be transfered. If server or proxy login/password are not setten in the script,
+displays IE-style authentication dialog (except silent mode). Plug-in supports 3
+"transfer in progress" display modes:
+
+old NSISdl style - additional embedded progress bar and text on the INSTFILES page;
+ POPUP dialog mode with detailed info;
+ BANNER mode with simple popup window.
+
+Plug-in recognizes Installer's Silent mode and this case hides any output (this feature
+requires NSIS 2.03 or later). Program implements simple re-get functionality - host
+reconnect and download from current position after short pause. While program depends on IE settings,
+it changes current IE mode to online. NSISdl code fragment was used for progress bar displaying
+in the "old style" mode. For ftp use "host/path" for file location relative to user's home dir and
+"host//path" for absolute path.
+
+Command line
+
+Plug-in DLL functions (entry points): get, post, head, put
+
+get DLL Function
+
+inetc::get [/PROXY IP:PORT] [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD] [/NOCOOKIES]
+ [/NOPROXY] [/NOCANCEL] [/CONNECTTIMEOUT TO_SEC] [/RECEIVETIMEOUT TO_SEC] [/SILENT]
+ [/CAPTION TEXT] [/NOCOOKIES] [/RESUME RETRY_QUESTION] [/POPUP HOST_ALIAS | /BANNER TEXT]
+ [/CANCELTEXT CANCEL_TEXT] [/QUESTION CANCEL_QUESTION] [/USER_AGENT USER_AGENT_TEXT]
+ [/HEADER HEADER_TEXT] [/TRANSLATE LANG_PARAMS]
+ URL1 local_file1 [URL2 local_file2 [...]] [/END]
+This call returns "OK" string if successful, error description string if failed (see included InetLoad.cpp file for a full set of status strings). Usage and result processing samples are included to the package.
+
/PROXY -
+Overwrites current proxy settings, not required in most cases. IE settings will be used by default.
+
/USERNAME -
+Proxy username (http only).
+
/PASSWORD -
+Proxy password (http only). For server (http/ftp) authentication it is possible to use URL encoded name and password, for example http://username:password@nsis.sourceforge.net.
+
/NOPROXY -
+Disables proxy settings for this connection (if any)
+
/NOCANCEL -
+Prevents download from being interrupted by user (locks Esc, Alt-F4, Cancel handling, removes sysmenu)
+
/CONNECTTIMEOUT -
+Sets INTERNET_OPTION_CONNECT_TIMEOUT, seconds, default - IE current parameter value.
+
/RECEIVETIMEOUT -
+Sets INTERNET_OPTION_RECEIVE_TIMEOUT, seconds, default - IE current parameter value.
+
/SILENT -
+Key hides plug-in' output (both popup dialog and embedded progress bar). Not required if 'SilentInstall silent' mode was defined in script (NSIS 2.03 or later).
+
/RESUME -
+On the permanent connection/transfer error instead of exit first displays message box with "resume download" question. Useful for dial-up connections and big files - allows user to restore connection and resume download. Default is "Your internet connection seems to have dropped out!\nPlease reconnect and click Retry to resume downloading...".
+
/CAPTION -
+Defines caption text for /BANNER mode, caption prefix (left of '-') for /POPUP mode and caption for RESUME MessageBox. Default is "InetLoad plug-in" if not set or "". 127 chars maximum.
+
/POPUP -
+This mode displays detailed download dialog instead of embedded progress bar. Also useful in .onInit function (i.e. not in Section). If HOST_ALIAS is not "", text will replace URL in the dialog - this allows to hide real URL (including password).
+
/BANNER -
+Displays simple popup dialog (MSI Banner mode) and sets dialog TEXT (up to 3 lines using $\n).
+
/CANCELTEXT -
+Text for the Cancel button in the NSISdl mode. Default is NSIS dialog Cancel button text (current lang).
+
/QUESTION -
+Text for the optional MessageBox if user tries to cancel download. If /QUESTION "" was used default
+"Are you sure that you want to stop download?" will be substituted.
+
/USERAGENT -
+UserAgent http request header value. Default is "NSIS_Inetc (Mozilla)". 256 chars maximum.
+
/HEADER -
+Adds or replaces http request header. Common HEADER_TEXT format is "header: value".
+
/NOCOOKIES -
+Removes cookies from http request
+
/END -
+Allows to limit plug-in stack reading (optional, required if you stores other vars in the stack).
+
/TRANSLATE -
+Allows translating plug-in text in the POPUP or NSISdl modes. 8 parameters both cases.
+
+NSISdl mode parameters:
+ /TRANSLATE downloading connecting second minute hour plural progress remaining
+With default values:
+ "Downloading %s" "Connecting ..." second minute hour s "%dkB (%d%%) of %dkB @ %d.%01dkB/s" "(%d %s%s remaining)"
+
+POPUP mode parameters:
+ /TRANSLATE url downloading connecting file_name received file_size remaining_time total_time
+With default values:
+ URL Downloading Connecting "File Name" Received "File Size" "Remaining Time" "Total Time"
+
+
post DLL Function
+
+inetc::post TEXT2POST [/FILE] [/PROXY IP:PORT] [/NOPROXY] [/NOCANCEL]
+ [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD] [/TIMEOUT INT_MS] [/SILENT]
+ [/CAPTION TEXT] [/POPUP | /BANNER TEXT] [/CANCELTEXT CANCEL_TEXT]
+ [/USER_AGENT USER_AGENT_TEXT] [/TRANSLATE LANG_PARAMS]
+ URL1 local_file1 [URL2 local_file2 [...]] [/END]
+Sets POST http mode and defines text string to be used in the POST (http only). Disables auto re-get. No char replaces used (%20 and others).
+If /FILE presents in command line, TEXT2POST is filename to be sent in POST request. Also 'Filename:' header will be added to HTTP headers.
+
+
head DLL Function
+
+The same as get, but requests http headers only. Writes raw headers to file.
+
+put DLL Function
+
+inetc::put [/PROXY IP:PORT] [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD] [/NOPROXY]
+ [/NOCANCEL] [/TIMEOUT INT_MS] [/SILENT] [/CAPTION TEXT] [/POPUP | /BANNER TEXT]
+ [/CANCELTEXT CANCEL_TEXT] [/USER_AGENT USER_AGENT_TEXT]
+ [/TRANSLATE LANG_PARAMS] URL1 local_file1 [URL2 local_file2 [...]] [/END]
+Return value and parameters (if applicable) are the same as for previous entry point.
+
+
Examples
+ inetc::get "http://dl.zvuki.ru/6306/mp3/12.mp3" "$EXEDIR\12.mp3" \
+ "ftp://dl.zvuki.ru/6306/mp3/11.mp3" "$EXEDIR\11.mp3"
+ Pop $0
+ inetc::put /BANNER "Cameron Diaz upload in progress..." \
+ "http://www.dreamgirlswallpaper.co.uk/fiveyearsonline/wallpaper/Cameron_Diaz/camerond09big.JPG" \
+ "$EXEDIR\cd.jpg"
+ Pop $0
+ StrCmp $0 "OK" dlok
+ MessageBox MB_OK|MB_ICONEXCLAMATION "http upload Error, click OK to abort installation" /SD IDOK
+ Abort
+dlok:
+ ...
+
+Credits
+Many thanks to Backland who offered a simple way to fix NSISdl mode crashes and added 'center parent' function.
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/auth_dlg.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/auth_dlg.nsi
new file mode 100644
index 000000000..b322f421b
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/auth_dlg.nsi
@@ -0,0 +1,31 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc http auth Test"
+OutFile "auth_dlg.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; Displays IE auth dialog.
+; Both server and proxy auth.
+; Please test this with your own link.
+
+ inetc::get "http://www.cnt.ru/personal" "$EXEDIR\auth.html"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/ftp_auth.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/ftp_auth.nsi
new file mode 100644
index 000000000..5e15776f1
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/ftp_auth.nsi
@@ -0,0 +1,31 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc ftp authentication Test"
+OutFile "ftp_auth.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; use your own URL and login@pwd. Password hidden from user with /popup "ALIAS"
+
+ inetc::get /caption "service pack download" /popup "ftp://localhost/" "ftp://login:pwd@localhost/W2Ksp3.exe" "$EXEDIR\sp3.exe"
+; inetc::put /caption "service pack upload" /popup "" "ftp://login:pwd@localhost/W2Ksp3.bu.exe" "$EXEDIR\sp3.exe"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/head.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/head.nsi
new file mode 100644
index 000000000..2ad7ff702
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/head.nsi
@@ -0,0 +1,29 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Head Test"
+OutFile "head.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+ DetailPrint "New version check out (internet connection)"
+ inetc::head /silent "http://ineum.narod.ru/spr_2006.htm" "$EXEDIR\head.txt"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.nsi
new file mode 100644
index 000000000..1eb77c2a0
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.nsi
@@ -0,0 +1,31 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Headers Test"
+OutFile "headers.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; additional headers. Sample php returns raw headers
+ inetc::get /useragent "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)" /header "SOAPAction: urn:anonOutInOpe" "http://localhost/headers.php" "$EXEDIR\headers.html"
+ Pop $0
+
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.php b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.php
new file mode 100644
index 000000000..e33b0d8ed
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/headers.php
@@ -0,0 +1,7 @@
+ $value) {
+ echo "$header: $value \n";
+}
+?>
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/https.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/https.nsi
new file mode 100644
index 000000000..ccf7c58b3
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/https.nsi
@@ -0,0 +1,26 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc https Test"
+OutFile "https.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+ inetc::get /POPUP "" /CAPTION "bending_property_demo.zip" "https://secure.codeproject.com/cs/miscctrl/bending_property/bending_property_src.zip" "$EXEDIR\bending_property_src.zip"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.cpp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.cpp
new file mode 100644
index 000000000..fcea2778b
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.cpp
@@ -0,0 +1,1622 @@
+/*******************************************************
+* FILE NAME: inetc.cpp
+*
+* Copyright 2004 - Present NSIS
+*
+* PURPOSE:
+* ftp/http file download plug-in
+* on the base of MS Inet API
+* 4 GB limit (http support?)
+*
+* CHANGE HISTORY
+*
+* Author Date Modifications
+* Takhir Bedertdinov
+* Nov 11, 2004 Original
+* Dec 17, 2004 Embedded edition -
+* NSISdl GUI style as default
+* (nsisdl.cpp code was partly used)
+* Dec 17, 2004 MSI Banner style
+* Feb 20, 2005 Resume download
+* feature for big files and bad connections
+* Mar 05, 2005 Proxy authentication
+* and /POPUP caption prefix option
+* Mar 25, 2005 Connect timeout option
+* and FTP switched to passive mode
+* Apr 18, 2005 Crack URL buffer size
+* bug fixed (256->string_size)
+* HTTP POST added
+* Jun 06, 2005 IDOK on "Enter" key locked
+* POST HTTP header added
+* Jun 22, 2005 non-interaptable mode /nocancel
+* and direct connect /noproxy
+* Jun 29, 2005 post.php written and tested
+* Jul 05, 2005 60 sec delay on WinInet detach problem
+* solved (not fine, but works including
+* installer exit and system reboot)
+* Jul 08, 2005 'set foreground' finally removed
+* Jul 26, 2005 POPUP translate option
+* Aug 23, 2005 https service type in InternetConnect
+* and "ignore certificate" flags
+* Sep 30, 2005 https with bad certificate from old OS;
+* Forbidden handling
+* Dec 23, 2005 'put' entry point, new names, 12003
+* ftp error handling (on ftp write permission)
+* 405 http error (method not allowed)
+* Mar 12, 2006 Internal authorization via InternetErrorDlg()
+* and Unauthorized (401) handling.
+* Jun 10, 2006 Caption text option for Resume download
+* MessageBox
+* Jun 24, 2006 HEAD method, silent mode clean up
+* Sep 05, 2006 Center dialog code from Backland
+* Sep 07, 2006 NSISdl crash fix /Backland idea/
+* Sep 08, 2006 POST as dll entry point.
+* Sep 21, 2006 parent dlg progr.bar style and font,
+* nocancel via ws_sysmenu
+* Sep 22, 2006 current lang IDCANCEL text, /canceltext
+* and /useragent options
+* Sep 24, 2006 .onInit improvements and defaults
+* Nov 11, 2006 FTP path creation, root|current dir mgmt
+* Jan 01, 2007 Global char[] cleanup, GetLastError() to
+* status string on ERR_DIALOG, few MSVCRT replaces
+* Jan 13, 2007 /HEADER option added
+* Jan 28, 2007 _open -> CreateFile and related
+* Feb 18, 2007 Speed calculating improved (pauses),
+* /popup text parameter to hide URL
+* Jun 07, 2007 Local file truncation added for download
+* (CREATE_ALWAYS)
+* Jun 11, 2007 FTP download permitted even if server rejects
+* SIZE request (ProFTPD).
+* Aug 11, 2007 Backland' fix for progress bar redraw/style
+* issue in NSISdl display mode.
+* Jan 09, 2008 {_trueparuex^}' fix - InternetSetFilePointer()
+* returns -1 on error.
+* /question option added for cancel question.
+* Feb 15, 2008 PUT content-length file size fix
+* Feb 17, 2008 char -> TCHAR replace for UNICODE option
+* Feb 19, 2008 janekschwarz fix for HTTP PUT with auth
+* CreateFile INVALID_HANDLE_VALUE on error fix
+* Feb 20, 2008 base64 encoder update for unicode
+* Feb 27, 2008 Unicode configurations added to VS 6 dsp
+* Mar 20, 2008 HTTP PUT with proxy auth finally fixed
+* FTP errors handling improved.
+* HEAD bug fixed
+* Mar 27, 2008 Details window hide/show in NSISdl mode
+* Apr 10, 2008 Auth test method changed to HEAD for
+* old proxy's
+* Apr 30, 2008 InternetErrorDlg() ERROR_SUCESS on cancel
+* click patched
+* 3xx errors added to status list.
+* May 20, 2008 InternetReadFile on cable disconnect patched
+* May 20, 2008 Reply status "0" patch (name resolution?)
+* Jul 15, 2008 HTTP 304 parsing. Incorrect size reported fix.
+* Aug 21, 2009 Escape sequence convertion removed (caused
+* error in signature with %2b requests)
+* Marqueue progess bar style for unknown file size.
+* Feb 04, 2010 Unicode POST patch - body converted to multibyte
+* Jul 11, 2010 /FILE POST option added
+* Nov 04, 2010 Disabled cookies and cache for cleanliness
+* Feb 14, 2011 Fixed reget bug introduced in previous commit
+* Feb 18, 2011 /NOCOOKIES option added
+* Mar 02, 2011 User-agent buffer increased. Small memory leak fix
+* Mar 23, 2011 Use caption on embedded progressbar - zenpoy
+* Apr 05, 2011 reget fix - INTERNET_FLAG_RELOAD for first connect only
+* Apr 27, 2011 /receivetimeout option added for big files and antivirus
+* Jun 15, 2011 Stack clean up fix on cancel - zenpoy
+* Oct 19, 2011 FTP PUT error parsing fix - tperquin
+*******************************************************/
+
+
+#define _WIN32_WINNT 0x0500
+
+#include
+#include
+#include
+#include
+#include "exdll.h"
+#include "resource.h"
+
+#ifndef PBM_SETMARQUEE
+#define PBM_SETMARQUEE (WM_USER + 10)
+#define PBS_MARQUEE 0x08
+#endif
+
+// IE 4 safety and VS 6 compatibility
+typedef BOOL (__stdcall *FTP_CMD)(HINTERNET,BOOL,DWORD,LPCTSTR,DWORD,HINTERNET *);
+FTP_CMD myFtpCommand;
+
+#define PLUGIN_NAME _T("Inetc plug-in")
+#define INETC_USERAGENT _T("NSIS_Inetc (Mozilla)")
+#define PB_RANGE 400 // progress bar values range
+#define PAUSE1_SEC 2 // transfer error indication time, for reget only
+#define PAUSE2_SEC 3 // paused state time, increase this if need (60?)
+#define PAUSE3_SEC 1 // pause after resume button pressed
+#define NOT_AVAILABLE 0xffffffff
+#define POST_HEADER _T("Content-Type: application/x-www-form-urlencoded")
+#define PUT_HEADER _T("Content-Type: octet-stream\nContent-Length: %d")
+#define INTERNAL_OK 0xFFEE
+#define PROGRESS_MS 1000 // screen values update interval
+#define DEF_QUESTION _T("Are you sure that you want to stop download?")
+#define HOST_AUTH_HDR _T("Authorization: basic %s")
+#define PROXY_AUTH_HDR _T("Proxy-authorization: basic %s")
+
+//#define MY_CERT_FLAGS SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_REVOCATION | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID
+#define MY_CERT_FLAGS SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_REVOCATION
+#define MY_REDIR_FLAGS INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS
+#define MY_HTTPS_FLAGS (MY_CERT_FLAGS | MY_REDIR_FLAGS | INTERNET_FLAG_SECURE)
+
+enum STATUS_CODES {
+ ST_OK = 0,
+ ST_CONNECTING,
+ ST_DOWNLOAD,
+ ST_CANCELLED,
+ ST_URLOPEN,
+ // ST_OPENING,
+ ST_PAUSE,
+ ERR_TERMINATED,
+ ERR_DIALOG,
+ ERR_INETOPEN,
+ ERR_URLOPEN,
+ ERR_TRANSFER,
+ ERR_FILEOPEN,
+ ERR_FILEWRITE,
+ ERR_FILEREAD,
+ ERR_REGET,
+ ERR_CONNECT,
+ ERR_OPENREQUEST,
+ ERR_SENDREQUEST,
+ ERR_CRACKURL,
+ ERR_NOTFOUND,
+ ERR_THREAD,
+ ERR_PROXY,
+ ERR_FORBIDDEN,
+ ERR_NOTALLOWED,
+ ERR_REQUEST,
+ ERR_SERVER,
+ ERR_AUTH,
+ ERR_CREATEDIR,
+ ERR_PATH,
+ ERR_NOTMODIFIED,
+ ERR_REDIRECTION
+};
+
+
+static TCHAR szStatus[][32] = {
+ _T("OK"),_T("Connecting"),_T("Downloading"),_T("Cancelled"),_T("Connecting"), //_T("Opening URL")),
+ _T("Reconnect Pause"),_T("Terminated"),_T("Dialog Error"),_T("Open Internet Error"),
+ _T("Open URL Error"),_T("Transfer Error"),_T("File Open Error"),_T("File Write Error"),_T("File Read Error"),
+ _T("Reget Error"),_T("Connection Error"),_T("OpenRequest Error"),_T("SendRequest Error"),
+ _T("URL Parts Error"),_T("File Not Found (404)"),_T("CreateThread Error"),_T("Proxy Error (407)"),
+ _T("Access Forbidden (403)"),_T("Not Allowed (405)"),_T("Request Error"),_T("Server Error"),
+ _T("Unauthorized (401)"),_T("FtpCreateDir failed (550)"),_T("Error FTP path (550)"),_T("Not Modified"),
+ _T("Redirection")
+};
+
+HINSTANCE g_hInstance;
+TCHAR fn[MAX_PATH]=_T(""),
+*url = NULL,
+*szAlias = NULL,
+*szProxy = NULL,
+*szHeader = NULL,
+*szBanner = NULL,
+*szQuestion = NULL,
+szCancel[64]=_T(""),
+szCaption[128]=_T(""),
+szUserAgent[256]=_T(""),
+szResume[256] = _T("Your internet connection seems to be not permitted or dropped out!\nPlease reconnect and click Retry to resume installation.");
+CHAR *szPost = NULL,
+post_fname[MAX_PATH] = "";
+DWORD fSize = 0;
+
+int status;
+DWORD cnt = 0,
+fs = 0,
+timeout = 0,
+receivetimeout = 0;
+DWORD startTime, transfStart, openType;
+bool silent, popup, resume, nocancel, noproxy, nocookies;
+
+HWND childwnd;
+HWND hDlg;
+bool fput = false, fhead = false;
+
+
+/*****************************************************
+* FUNCTION NAME: sf(HWND)
+* PURPOSE:
+* moves HWND to top and activates it
+* SPECIAL CONSIDERATIONS:
+* commented because annoying
+*****************************************************/
+/*
+void sf(HWND hw)
+{
+DWORD ctid = GetCurrentThreadId();
+DWORD ftid = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
+AttachThreadInput(ftid, ctid, TRUE);
+SetForegroundWindow(hw);
+AttachThreadInput(ftid, ctid, FALSE);
+}
+*/
+
+static TCHAR szUrl[64] = _T("");
+static TCHAR szDownloading[64] = _T("Downloading %s");
+static TCHAR szConnecting[64] = _T("Connecting ...");
+static TCHAR szSecond[64] = _T("second");
+static TCHAR szMinute[32] = _T("minute");
+static TCHAR szHour[32] = _T("hour");
+static TCHAR szPlural[32] = _T("s");
+static TCHAR szProgress[128] = _T("%dkB (%d%%) of %dkB @ %d.%01dkB/s");
+static TCHAR szRemaining[64] = _T(" (%d %s%s remaining)");
+static TCHAR szBasic[128] = _T("");
+static TCHAR szAuth[128] = _T("");
+
+// is it possible to make it working with unicode strings?
+
+/* Base64 encode one byte */
+static TCHAR encode(unsigned char u) {
+
+ if(u < 26) return _T('A')+u;
+ if(u < 52) return _T('a')+(u-26);
+ if(u < 62) return _T('0')+(u-52);
+ if(u == 62) return _T('+');
+ return _T('/');
+}
+
+TCHAR *encode_base64(int size, TCHAR *src, TCHAR *dst) {
+
+ int i;
+ TCHAR *p;
+
+ if(!src)
+ return NULL;
+
+ if(!size)
+ size= lstrlen(src);
+
+ p = dst;
+
+ for(i=0; i>2;
+ b5= ((b1&0x3)<<4)|(b2>>4);
+ b6= ((b2&0xf)<<2)|(b3>>6);
+ b7= b3&0x3f;
+
+ *p++= encode(b4);
+ *p++= encode(b5);
+
+ if(i+1 0)
+ {
+ dw = data_buf;
+ if(!InternetWriteFile(hFile, dw, bytesDone, &rslt) || rslt == 0)
+ {
+ status = ERR_TRANSFER;
+ break;
+ }
+ dw += rslt;
+ cnt += rslt;
+ bytesDone -= rslt;
+ }
+ }
+ else
+ {
+ if(!InternetReadFile(hFile, data_buf, sizeof(data_buf), &rslt))
+ {
+ status = ERR_TRANSFER;
+ break;
+ }
+ if(rslt == 0) // EOF reached or cable disconnect
+ {
+// on cable disconnect returns TRUE and 0 bytes. is cnt == 0 OK (zero file size)?
+// cannot check this if reply is chunked (no content-length, http 1.1)
+ status = (fs != NOT_AVAILABLE && cnt < fs) ? ERR_TRANSFER : ST_OK;
+ break;
+ }
+ if(!WriteFile(localFile, data_buf, rslt, &bytesDone, NULL) ||
+ rslt != bytesDone)
+ {
+ status = ERR_FILEWRITE;
+ break;
+ }
+ cnt += rslt;
+ }
+ }
+}
+
+/*****************************************************
+* FUNCTION NAME: mySendRequest()
+* PURPOSE:
+* HttpSendRequestEx() sends headers only - for PUT
+* We also can use InetWriteFile for POST body I guess
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+int mySendRequest(HINTERNET hFile)
+{
+ INTERNET_BUFFERS BufferIn = {0};
+ if(fput)
+ {
+ BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
+ BufferIn.dwBufferTotal = fs;
+ return HttpSendRequestEx( hFile, &BufferIn, NULL, HSR_INITIATE, 0);
+ }
+ return HttpSendRequest(hFile, NULL, 0, szPost, fSize);
+}
+
+/*****************************************************
+* FUNCTION NAME: queryStatus()
+* PURPOSE:
+* http status code comes before download (get) and
+* after upload (put), so this is called from 2 places
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+bool queryStatus(HINTERNET hFile)
+{
+ TCHAR buf[256] = _T("");
+ DWORD rslt;
+ if(HttpQueryInfo(hFile, HTTP_QUERY_STATUS_CODE,
+ buf, &(rslt = sizeof(buf)), NULL))
+ {
+ buf[3] = 0;
+ if(lstrcmp(buf, _T("0")) == 0 || *buf == 0)
+ status = ERR_SENDREQUEST;
+ else if(lstrcmp(buf, _T("401")) == 0)
+ status = ERR_AUTH;
+ else if(lstrcmp(buf, _T("403")) == 0)
+ status = ERR_FORBIDDEN;
+ else if(lstrcmp(buf, _T("404")) == 0)
+ status = ERR_NOTFOUND;
+ else if(lstrcmp(buf, _T("407")) == 0)
+ status = ERR_PROXY;
+ else if(lstrcmp(buf, _T("405")) == 0)
+ status = ERR_NOTALLOWED;
+ else if(lstrcmp(buf, _T("304")) == 0)
+ status = ERR_NOTMODIFIED;
+ else if(*buf == _T('3'))
+ {
+ status = ERR_REDIRECTION;
+ wsprintf(szStatus[status] + lstrlen(szStatus[status]), _T(" (%s)"), buf);
+ }
+ else if(*buf == _T('4'))
+ {
+ status = ERR_REQUEST;
+ wsprintf(szStatus[status] + lstrlen(szStatus[status]), _T(" (%s)"), buf);
+ }
+ else if(*buf == _T('5'))
+ {
+ status = ERR_SERVER;
+ wsprintf(szStatus[status] + lstrlen(szStatus[status]), _T(" (%s)"), buf);
+ }
+ return true;
+ }
+ return false;
+}
+
+/*****************************************************
+* FUNCTION NAME: openFtpFile()
+* PURPOSE:
+* control connection, size request, re-get lseek
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+HINTERNET openFtpFile(HINTERNET hConn,
+ TCHAR *path)
+{
+ TCHAR buf[256] = _T(""), *movp;
+ HINTERNET hFile;
+ DWORD rslt, err, gle;
+ bool https_req_ok = false;
+
+ /* reads connection / auth responce info and cleares 'control' buffer this way */
+ InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf)));
+ if(cnt == 0)
+ {
+ if(!fput) // we know local file size already
+ {
+ /* too clever myFtpCommand returnes false on the valid _T("550 Not found/Not permitted" server answer,
+ to read answer I had to ignory returned false (!= 999999) :-(
+ GetLastError also possible, but MSDN description of codes is very limited */
+ wsprintf(buf, _T("SIZE %s"), path + 1);
+ if(myFtpCommand != NULL &&
+ myFtpCommand(hConn, false, FTP_TRANSFER_TYPE_ASCII, buf, 0, &hFile) != 9999 &&
+ memset(buf, 0, sizeof(buf)) != NULL &&
+ InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf))))
+ {
+ if(_tcsstr(buf, _T("213 ")))
+ {
+ fs = _tcstol(_tcschr(buf, _T(' ')) + 1, NULL, 0);
+ }
+ /* stupid ProFTPD returns error on SIZE request. let's continue without size.
+ But IE knows some trick to get size from ProFTPD......
+ else if(_tcsstr(buf, _T("550 _T("))
+ {
+ status = ERR_SIZE_NOT_PERMITTED;
+ return NULL;
+ }
+ */
+ }
+ if(fs == 0)
+ {
+ fs = NOT_AVAILABLE;
+ }
+
+ }
+ }
+ else
+ {
+ wsprintf(buf, _T("REST %d"), cnt);
+ if(myFtpCommand == NULL ||
+ !myFtpCommand(hConn, false, FTP_TRANSFER_TYPE_BINARY, buf, 0, &hFile) ||
+ memset(buf, 0, sizeof(buf)) == NULL ||
+ !InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf))) ||
+ (_tcsstr(buf, _T("350")) == NULL && _tcsstr(buf, _T("110")) == NULL))
+ {
+ status = ERR_REGET;
+ return NULL;
+ }
+ }
+ if((hFile = FtpOpenFile(hConn, path + 1, fput ? GENERIC_WRITE : GENERIC_READ,
+ FTP_TRANSFER_TYPE_BINARY|INTERNET_FLAG_RELOAD,0)) == NULL)
+ {
+ gle = GetLastError();
+ *buf = 0;
+ InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf)));
+ // wrong path - dir may not exist or upload may be not allowed
+ // we use ftp://host//path (double /) to define path from FS root
+ if(fput && (_tcsstr(buf, _T("550")) != NULL || _tcsstr(buf, _T("553")) != NULL))
+ {
+
+ movp = path + 1;
+ if(*movp == _T('/')) movp++; // don't need to creat root
+ while(_tcschr(movp, _T('/')))
+ {
+ *_tcschr(movp,_T('/')) = 0;
+ FtpCreateDirectory(hConn, path + 1);
+ InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf)));
+ *(movp + lstrlen(movp)) = _T('/');
+ movp = _tcschr(movp, _T('/')) + 1;
+ }
+ if(status != ERR_CREATEDIR &&
+ (hFile = FtpOpenFile(hConn, path + 1, GENERIC_WRITE,
+ FTP_TRANSFER_TYPE_BINARY|INTERNET_FLAG_RELOAD,0)) == NULL)
+ {
+ status = ERR_PATH;
+ if(InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf))))
+ lstrcpyn(szStatus[status], _tcsstr(buf, _T("550")), sizeof(szStatus[0]) / sizeof(TCHAR));
+ }
+ }
+ // may be firewall related error, let's give user time to disable it
+ else if(gle == 12003)
+ {
+ if(_tcsstr(buf, _T("550")))
+ {
+ status = ERR_NOTFOUND;
+ lstrcpyn(szStatus[status], _tcsstr(buf, _T("550")), sizeof(szStatus[0]) / sizeof(TCHAR));
+ }
+ else
+ {
+ lstrcpyn(szStatus[status], buf, sizeof(szStatus[0]) / sizeof(TCHAR));
+ }
+ }
+ // timeout (firewall or dropped connection problem)
+ else if(gle == 12002)
+ {
+ if(!silent)
+ resume = true;
+ status = ERR_URLOPEN;
+ }
+ }
+ else InternetGetLastResponseInfo(&err, buf, &(rslt = sizeof(buf)));
+ return hFile;
+}
+
+
+/*****************************************************
+* FUNCTION NAME: openHttpFile()
+* PURPOSE:
+* file open, size request, re-get lseek
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+HINTERNET openHttpFile(HINTERNET hConn,
+ INTERNET_SCHEME nScheme,
+ TCHAR *path)
+{
+ TCHAR buf[256] = _T("");
+ HINTERNET hFile;
+ DWORD rslt, err;
+ bool first_attempt = true;;
+
+// test connection for PUT, the only way to do this before sending data
+// OPTIONS fails on HttpOpenRequest step for HTTPS
+// but works for HEAD I guess
+ if(fput)// && nScheme != INTERNET_SCHEME_HTTPS)
+ {
+// old proxy's may not support OPTIONS request, so changed to HEAD....
+ if((hFile = HttpOpenRequest(hConn, _T("HEAD"), path, NULL, NULL, NULL,
+// if((hFile = HttpOpenRequest(hConn, _T("OPTIONS"), path, NULL, NULL, NULL,
+ INTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION |
+ (nocookies ? (INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES) : 0), 0)) != NULL)
+ {
+ if(*szAuth)
+ {
+ wsprintf(buf, PROXY_AUTH_HDR, szAuth);
+ HttpAddRequestHeaders(hFile, buf, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ }
+resend_proxy1:
+ if(*szBasic)
+ {
+ wsprintf(buf, HOST_AUTH_HDR, szBasic);
+ HttpAddRequestHeaders(hFile, buf, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ }
+resend_auth1:
+ if(HttpSendRequest(hFile, NULL, 0, NULL, 0))
+ {
+ queryStatus(hFile);
+// may be don't need to read all from socket, but this looks safer
+ while(InternetReadFile(hFile, buf, sizeof(buf), &rslt) && rslt > 0) {}
+ if(!silent && (status == ERR_PROXY || status == ERR_AUTH))// || status == ERR_FORBIDDEN))
+ {
+ rslt = InternetErrorDlg(hDlg, hFile,
+ ERROR_INTERNET_INCORRECT_PASSWORD,
+ FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
+ FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
+ FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
+ NULL);
+ if (rslt == ERROR_INTERNET_FORCE_RETRY)
+ {
+ status = ST_URLOPEN;
+ if(status == ERR_PROXY) goto resend_proxy1;
+ else goto resend_auth1;
+ }
+ else
+ {
+ status = ST_CANCELLED;
+ }
+
+ }
+ // no such file is OK for PUT. server first checks authentication
+ if(status == ERR_NOTFOUND || status == ERR_FORBIDDEN || status == ERR_NOTALLOWED)
+ {
+// MessageBox(childwnd, _T("NOT_FOUND"), "", 0);
+ status = ST_URLOPEN;
+ }
+ // parameters might be updated during dialog popup
+ if(status == ST_URLOPEN)
+ {
+ *buf = 0;
+ if(HttpQueryInfo(hFile, HTTP_QUERY_AUTHORIZATION, buf, &(rslt = sizeof(buf)), NULL) && *buf)
+ lstrcpyn(szBasic, buf, rslt);
+ *buf = 0;
+ if(HttpQueryInfo(hFile, HTTP_QUERY_PROXY_AUTHORIZATION, buf, &(rslt = sizeof(buf)), NULL) && *buf)
+ lstrcpyn(szAuth, buf, rslt);
+ }
+ }
+ else status = ERR_SENDREQUEST;
+ InternetCloseHandle(hFile);
+ }
+ else status = ERR_OPENREQUEST;
+ }
+// request itself
+ if(status == ST_URLOPEN)
+ {
+ if((hFile = HttpOpenRequest(hConn, fput ? _T("PUT") : (fhead ? _T("HEAD") : (szPost ? _T("POST") : NULL)),
+ path, NULL, NULL, NULL,
+ // INTERNET_FLAG_RELOAD conflicts with reget - hidden re-read from beginning has place
+ // INTERNET_FLAG_RESYNCHRONIZE // note - sync may not work with some http servers
+ // reload on first connect (and any req. except GET), just continue on resume.
+ // HTTP Proxy still is a problem for reget
+ (cnt ? 0 : INTERNET_FLAG_RELOAD)
+ | INTERNET_FLAG_KEEP_CONNECTION |
+ (nocookies ? (INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES) : 0) |
+ (nScheme == INTERNET_SCHEME_HTTPS ? MY_HTTPS_FLAGS : 0), 0)) != NULL)
+ {
+ if(*szAuth)
+ {
+ wsprintf(buf, PROXY_AUTH_HDR, szAuth);
+ HttpAddRequestHeaders(hFile, buf, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ }
+resend_proxy2:
+ if(szPost != NULL)
+ HttpAddRequestHeaders(hFile, POST_HEADER,
+ -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ if(*post_fname)
+ HttpAddRequestHeadersA(hFile, post_fname,
+ -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ if(szHeader != NULL)
+ HttpAddRequestHeaders(hFile, szHeader, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ if(*szBasic)
+ {
+ wsprintf(buf, HOST_AUTH_HDR, szBasic);
+ HttpAddRequestHeaders(hFile, buf, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ }
+ if(fput)
+ {
+ wsprintf(buf, PUT_HEADER, fs);
+ HttpAddRequestHeaders(hFile, buf, -1,
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+ }
+resend_auth2:
+ first_attempt = true;
+ if(nScheme == INTERNET_SCHEME_HTTPS)
+ {
+ if(!mySendRequest(hFile))
+ {
+ InternetQueryOption (hFile, INTERNET_OPTION_SECURITY_FLAGS,
+ (LPVOID)&rslt, &(err = sizeof(rslt)));
+ rslt |= MY_CERT_FLAGS;
+ InternetSetOption (hFile, INTERNET_OPTION_SECURITY_FLAGS,
+ &rslt, sizeof(rslt) );
+ }
+ else first_attempt = false;
+ }
+// https Request answer may be after optional second Send only on Win98
+ if(!first_attempt || mySendRequest(hFile))
+ {
+// no status for PUT - headers were sent only. And not need to get size / set position
+ if(!fput)
+ {
+ queryStatus(hFile);
+ if(!silent && (status == ERR_PROXY || status == ERR_AUTH))
+ {
+ rslt = InternetErrorDlg(hDlg, hFile,
+ ERROR_INTERNET_INCORRECT_PASSWORD,
+ FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
+ FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
+ FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
+ NULL);
+ if (rslt == ERROR_INTERNET_FORCE_RETRY)
+ {
+ status = ST_URLOPEN;
+ if(status == ERR_PROXY) goto resend_proxy2;
+ else goto resend_auth2;
+ }
+ else
+ status = ST_CANCELLED;
+
+ }
+// get size / set position
+ if(status == ST_URLOPEN)
+ {
+ if(cnt == 0)
+ {
+ if(HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH, buf,
+ &(rslt = sizeof(buf)), NULL))
+ fs = _tcstoul(buf, NULL, 0);
+ else fs = NOT_AVAILABLE;
+ }
+ else
+ {
+ if((int)InternetSetFilePointer(hFile, cnt, NULL, FILE_BEGIN, 0) == -1)
+ status = ERR_REGET;
+ }
+ }
+ }
+
+ }
+ else
+ {
+ if(!queryStatus(hFile))
+ status = ERR_SENDREQUEST;
+ }
+ }
+ else status = ERR_OPENREQUEST;
+ }
+ return hFile;
+}
+
+/*****************************************************
+* FUNCTION NAME: inetTransfer()
+* PURPOSE:
+* http/ftp file transfer
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+DWORD __stdcall inetTransfer(void *hw)
+{
+ HINTERNET hSes, hConn, hFile;
+ HINSTANCE hInstance = NULL;
+ HANDLE localFile = NULL;
+ HWND hDlg = (HWND)hw;
+ DWORD lastCnt, rslt, err;
+ TCHAR hdr[2048];
+ TCHAR *host = (TCHAR*)GlobalAlloc(GPTR, g_stringsize * sizeof(TCHAR)),
+ *path = (TCHAR*)GlobalAlloc(GPTR, g_stringsize * sizeof(TCHAR)),
+ *params = (TCHAR*)GlobalAlloc(GPTR, g_stringsize * sizeof(TCHAR)),
+ *user = (TCHAR*)GlobalAlloc(GPTR, g_stringsize * sizeof(TCHAR)),
+ *passwd = (TCHAR*)GlobalAlloc(GPTR, g_stringsize * sizeof(TCHAR));
+
+ URL_COMPONENTS uc = {sizeof(URL_COMPONENTS), NULL, 0,
+ (INTERNET_SCHEME)0, host, g_stringsize, 0 , user, g_stringsize,
+ passwd, g_stringsize, path, g_stringsize, params, g_stringsize};
+
+ if((hSes = InternetOpen(szUserAgent, openType, szProxy, NULL, 0)) != NULL)
+ {
+ if(InternetQueryOption(hSes, INTERNET_OPTION_CONNECTED_STATE, &(rslt=0),
+ &(lastCnt=sizeof(DWORD))) &&
+ (rslt & INTERNET_STATE_DISCONNECTED_BY_USER))
+ {
+ INTERNET_CONNECTED_INFO ci = {INTERNET_STATE_CONNECTED, 0};
+ InternetSetOption(hSes,
+ INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
+ }
+ if(timeout > 0)
+ lastCnt = InternetSetOption(hSes, INTERNET_OPTION_CONNECT_TIMEOUT, &timeout, sizeof(timeout));
+ if(receivetimeout > 0)
+ InternetSetOption(hSes, INTERNET_OPTION_RECEIVE_TIMEOUT, &receivetimeout, sizeof(receivetimeout));
+ // 60 sec WinInet.dll detach delay on socket time_wait fix
+ // if(hInstance = GetModuleHandle("wininet.dll"))
+ if(hInstance = LoadLibrary(_T("wininet.dll")))
+ myFtpCommand = (FTP_CMD)GetProcAddress(hInstance,
+#ifdef UNICODE
+ "FtpCommandW"
+#else
+ "FtpCommandA"
+#endif
+ );
+ while(!popstring(url) && lstrcmpi(url, _T("/end")) != 0)
+ {
+ // too many customers requested not to do this
+ // sf(hDlg);
+ if(popstring(fn) != 0 || lstrcmpi(url, _T("/end")) == 0) break;
+ status = ST_CONNECTING;
+ cnt = fs = *host = *user = *passwd = *path = *params = 0;
+ PostMessage(hDlg, WM_TIMER, 1, 0); // show url & fn, do it sync
+ if((localFile = CreateFile(fn, fput ? GENERIC_READ : GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, fput ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL)) != INVALID_HANDLE_VALUE)
+ {
+ uc.dwHostNameLength = uc.dwUserNameLength = uc.dwPasswordLength =
+ uc.dwUrlPathLength = uc.dwExtraInfoLength = g_stringsize;
+ if(fput)
+ {
+ fs = GetFileSize(localFile, NULL);
+ }
+ if(InternetCrackUrl(url, 0, 0/*ICU_ESCAPE*/ , &uc))
+ {
+ // auth headers for HTTP PUT seems to be lost, preparing encoded login:password
+ if(*user && *passwd)
+ {
+ wsprintf(hdr, _T("%s:%s"), user, passwd);
+ // does unicode version of encoding works correct?
+ // are user and passwd ascii only?
+ encode_base64(lstrlen(hdr), hdr, szBasic);
+ *hdr = 0;
+ }
+ lstrcat(path, params);
+ transfStart = GetTickCount();
+ do
+ {
+ // re-PUT to already deleted tmp file on http server is not possible.
+ // the same with POST - must re-send data to server. for 'resume' loop
+ if((fput && uc.nScheme != INTERNET_SCHEME_FTP) || szPost)
+ {
+ cnt = 0;
+ SetFilePointer(localFile, 0, NULL, SEEK_SET);
+ }
+ status = ST_CONNECTING;
+ lastCnt = cnt;
+ if((hConn = InternetConnect(hSes, host, uc.nPort,
+ lstrlen(user) > 0 ? user : NULL,
+ lstrlen(passwd) > 0 ? passwd : NULL,
+ uc.nScheme == INTERNET_SCHEME_FTP ? INTERNET_SERVICE_FTP : INTERNET_SERVICE_HTTP,
+ uc.nScheme == INTERNET_SCHEME_FTP ? INTERNET_FLAG_PASSIVE : 0, 0)) != NULL)
+ {
+ status = ST_URLOPEN;
+ hFile = uc.nScheme == INTERNET_SCHEME_FTP ?
+ openFtpFile(hConn, path) : openHttpFile(hConn, uc.nScheme, path);
+ if(status != ST_URLOPEN && hFile != NULL)
+ {
+ InternetCloseHandle(hFile);
+ hFile = NULL;
+ }
+ if(hFile != NULL)
+ {
+ if(fhead)
+ {// repeating calls clear headers..
+ if(HttpQueryInfo(hFile, HTTP_QUERY_RAW_HEADERS_CRLF, hdr, &(rslt=2048), NULL))
+ WriteFile(localFile, hdr, rslt, &lastCnt, NULL);
+ status = ST_OK;
+ }
+ else
+ {
+ HWND hBar = GetDlgItem(hDlg, IDC_PROGRESS1);
+ SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, 0, 0);
+ SetWindowText(GetDlgItem(hDlg, IDC_STATIC5), fs == NOT_AVAILABLE ? _T("Not Available") : _T(""));
+ SetWindowText(GetDlgItem(hDlg, IDC_STATIC4), fs == NOT_AVAILABLE ? _T("Unknown") : _T(""));
+ SetWindowLong(hBar, GWL_STYLE, fs == NOT_AVAILABLE ?
+ (GetWindowLong(hBar, GWL_STYLE) | PBS_MARQUEE) : (GetWindowLong(hBar, GWL_STYLE) & ~PBS_MARQUEE));
+ SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETMARQUEE, (WPARAM)(fs == NOT_AVAILABLE ? 1 : 0), (LPARAM)50 );
+ fileTransfer(localFile, hFile);
+ if(fput && uc.nScheme != INTERNET_SCHEME_FTP)
+ {
+ rslt = HttpEndRequest(hFile, NULL, 0, 0);
+ queryStatus(hFile);
+ }
+ }
+ InternetCloseHandle(hFile);
+ }
+ InternetCloseHandle(hConn);
+ }
+ else
+ {
+ status = ERR_CONNECT;
+ if(uc.nScheme == INTERNET_SCHEME_FTP &&
+ InternetGetLastResponseInfo(&err, hdr, &(rslt = sizeof(hdr))) &&
+ _tcsstr(hdr, _T("530")))
+ {
+ lstrcpyn(szStatus[status], _tcsstr(hdr, _T("530")), sizeof(szStatus[0]) / sizeof(TCHAR));
+ }
+ else
+ {
+ rslt = GetLastError();
+ if((rslt == 12003 || rslt == 12002) && !silent)
+ resume = true;
+ }
+ }
+ } while(((!fput || uc.nScheme == INTERNET_SCHEME_FTP) &&
+ cnt > lastCnt &&
+ status == ERR_TRANSFER &&
+ SleepEx(PAUSE1_SEC * 1000, false) == 0 &&
+ (status = ST_PAUSE) != ST_OK &&
+ SleepEx(PAUSE2_SEC * 1000, false) == 0)
+ || (resume &&
+ status != ST_OK &&
+ status != ST_CANCELLED &&
+ status != ERR_NOTFOUND &&
+ ShowWindow(hDlg, SW_HIDE) != -1 &&
+ MessageBox(GetParent(hDlg), szResume, *szCaption ? szCaption : PLUGIN_NAME, MB_RETRYCANCEL|MB_ICONWARNING) == IDRETRY &&
+ (status = ST_PAUSE) != ST_OK &&
+ ShowWindow(hDlg, silent ? SW_HIDE : SW_SHOW) == false &&
+ SleepEx(PAUSE3_SEC * 1000, false) == 0));
+ }
+ else status = ERR_CRACKURL;
+ CloseHandle(localFile);
+ if(!fput && status != ST_OK)
+ {
+ rslt = DeleteFile(fn);
+ break;
+ }
+ }
+ else status = ERR_FILEOPEN;
+ }
+ InternetCloseHandle(hSes);
+ if (lstrcmpi(url, _T("/end"))==0)
+ pushstring(url);
+ }
+ else status = ERR_INETOPEN;
+ GlobalFree(host);
+ GlobalFree(path);
+ GlobalFree(user);
+ GlobalFree(passwd);
+ GlobalFree(params);
+ if(IsWindow(hDlg))
+ PostMessage(hDlg, WM_COMMAND, MAKELONG(IDOK, INTERNAL_OK), 0);
+ return status;
+}
+
+/*****************************************************
+* FUNCTION NAME: fsFormat()
+* PURPOSE:
+* formats DWORD (max 4 GB) file size for dialog, big MB
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+void fsFormat(DWORD bfs,
+ TCHAR *b)
+{
+ if(bfs == NOT_AVAILABLE)
+ lstrcpy(b, _T("???"));
+ else if(bfs == 0)
+ lstrcpy(b, _T("0"));
+ else if(bfs < 10 * 1024)
+ wsprintf(b, _T("%u bytes"), bfs);
+ else if(bfs < 10 * 1024 * 1024)
+ wsprintf(b, _T("%u kB"), bfs / 1024);
+ else wsprintf(b, _T("%u MB"), (bfs / 1024 / 1024));
+}
+
+
+/*****************************************************
+* FUNCTION NAME: progress_callback
+* PURPOSE:
+* old-style progress bar text updates
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+
+void progress_callback(void)
+{
+ TCHAR buf[1024] = _T(""), b[1024] = _T("");
+ int time_sofar = max(1, (GetTickCount() - transfStart) / 1000);
+ int bps = cnt / time_sofar;
+ int remain = (cnt > 0 && fs != NOT_AVAILABLE) ? (MulDiv(time_sofar, fs, cnt) - time_sofar) : 0;
+ TCHAR *rtext=szSecond;
+ if(remain < 0) remain = 0;
+ if (remain >= 60)
+ {
+ remain/=60;
+ rtext=szMinute;
+ if (remain >= 60)
+ {
+ remain/=60;
+ rtext=szHour;
+ }
+ }
+ wsprintf(buf,
+ szProgress,
+ cnt/1024,
+ fs > 0 && fs != NOT_AVAILABLE ? MulDiv(100, cnt, fs) : 0,
+ fs != NOT_AVAILABLE ? fs/1024 : 0,
+ bps/1024,((bps*10)/1024)%10
+ );
+ if (remain) wsprintf(buf + lstrlen(buf),
+ szRemaining,
+ remain,
+ rtext,
+ remain==1?_T(""):szPlural
+ );
+ SetDlgItemText(hDlg, IDC_STATIC1, (cnt == 0 || status == ST_CONNECTING) ? szConnecting : buf);
+ if(fs > 0 && fs != NOT_AVAILABLE)
+ SendMessage(GetDlgItem(hDlg, IDC_PROGRESS1), PBM_SETPOS, MulDiv(cnt, PB_RANGE, fs), 0);
+ if (*szCaption == 0)
+ wsprintf(buf, szDownloading,
+ _tcschr(fn, _T('\\')) ? _tcsrchr(fn, _T('\\')) + 1 : fn);
+ else wsprintf(buf, _T("%s"),szCaption);
+ HWND hwndS = GetDlgItem(childwnd, 1006);
+ if(!silent && hwndS != NULL && IsWindow(hwndS))
+ {
+ GetWindowText(hwndS, b, sizeof(b));
+ if(lstrcmp(b, buf) != 0)
+ SetWindowText(hwndS, buf);
+ }
+}
+
+/*****************************************************
+* FUNCTION NAME: onTimer()
+* PURPOSE:
+* updates text fields every second
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+void onTimer(HWND hDlg)
+{
+ TCHAR b[128];
+ DWORD ct = (GetTickCount() - transfStart) / 1000,
+ tt = (GetTickCount() - startTime) / 1000;
+ // dialog window caption
+ wsprintf(b, _T("%s - %s"), *szCaption ? szCaption : PLUGIN_NAME, szStatus[status]);
+ if(fs > 0 && fs != NOT_AVAILABLE && status == ST_DOWNLOAD)
+ {
+ wsprintf(b + lstrlen(b), _T(" %d%%"), MulDiv(100, cnt, fs));
+ }
+ if(szBanner == NULL) SetWindowText(hDlg, b);
+ // current file and url
+ SetDlgItemText(hDlg, IDC_STATIC1, (szAlias && *szAlias) ? szAlias : url);
+ SetDlgItemText(hDlg, IDC_STATIC2, /*_tcschr(fn, '\\') ? _tcsrchr(fn, '\\') + 1 : */fn);
+ // bytes done and rate
+ if(cnt > 0)
+ {
+ fsFormat(cnt, b);
+ if(ct > 1 && status == ST_DOWNLOAD)
+ {
+ lstrcat(b, _T(" ( "));
+ fsFormat(cnt / ct, b + lstrlen(b));
+ lstrcat(b, _T("/sec )"));
+ }
+ }
+ else *b = 0;
+ SetDlgItemText(hDlg, IDC_STATIC3, b);
+ // total download time
+ wsprintf(b, _T("%d:%02d:%02d"), tt / 3600, (tt / 60) % 60, tt % 60);
+ SetDlgItemText(hDlg, IDC_STATIC6, b);
+ // file size, time remaining, progress bar
+ if(fs > 0 && fs != NOT_AVAILABLE)
+ {
+ fsFormat(fs, b);
+ SetDlgItemText(hDlg, IDC_STATIC5, b);
+ SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, MulDiv(cnt, PB_RANGE, fs), 0);
+ if(cnt > 5000)
+ {
+ ct = MulDiv(fs - cnt, ct, cnt);
+ wsprintf(b, _T("%d:%02d:%02d"), ct / 3600, (ct / 60) % 60, ct % 60);
+ }
+ else *b = 0;
+ SetWindowText(GetDlgItem(hDlg, IDC_STATIC4), b);
+ }
+}
+
+/*****************************************************
+* FUNCTION NAME: centerDlg()
+* PURPOSE:
+* centers dlg on NSIS parent
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+void centerDlg(HWND hDlg)
+{
+ HWND hwndParent = GetParent(hDlg);
+ RECT nsisRect, dlgRect, waRect;
+ int dlgX, dlgY, dlgWidth, dlgHeight;
+
+ if(hwndParent == NULL || silent)
+ return;
+ if(popup)
+ GetWindowRect(hwndParent, &nsisRect);
+ else GetClientRect(hwndParent, &nsisRect);
+ GetWindowRect(hDlg, &dlgRect);
+
+ dlgWidth = dlgRect.right - dlgRect.left;
+ dlgHeight = dlgRect.bottom - dlgRect.top;
+ dlgX = (nsisRect.left + nsisRect.right - dlgWidth) / 2;
+ dlgY = (nsisRect.top + nsisRect.bottom - dlgHeight) / 2;
+
+ if(popup)
+ {
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &waRect, 0);
+ if(dlgX > waRect.right - dlgWidth)
+ dlgX = waRect.right - dlgWidth;
+ if(dlgX < waRect.left) dlgX = waRect.left;
+ if(dlgY > waRect.bottom - dlgHeight)
+ dlgY = waRect.bottom - dlgHeight;
+ if(dlgY < waRect.top) dlgY = waRect.top;
+ }
+ else dlgY += 20;
+
+ SetWindowPos(hDlg, HWND_TOP, dlgX, dlgY, 0, 0, SWP_NOSIZE);
+}
+
+/*****************************************************
+* FUNCTION NAME: onInitDlg()
+* PURPOSE:
+* dlg init
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+void onInitDlg(HWND hDlg)
+{
+ HFONT hFont;
+ HWND hPrbNew;
+ HWND hPrbOld;
+ HWND hCan = GetDlgItem(hDlg, IDCANCEL);
+
+ if(childwnd)
+ {
+ hPrbNew = GetDlgItem(hDlg, IDC_PROGRESS1);
+ hPrbOld = GetDlgItem(childwnd, 0x3ec);
+
+ // Backland' fix for progress bar redraw/style issue.
+ // Original bar may be hidden because of interfernce with other plug-ins.
+ LONG prbStyle = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ if(hPrbOld != NULL)
+ {
+ prbStyle |= GetWindowLong(hPrbOld, GWL_STYLE);
+ }
+ SetWindowLong(hPrbNew, GWL_STYLE, prbStyle);
+
+ if(!popup)
+ {
+ if((hFont = (HFONT)SendMessage(childwnd, WM_GETFONT, 0, 0)) != NULL)
+ {
+ SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)hFont, 0);
+ SendDlgItemMessage(hDlg, IDCANCEL, WM_SETFONT, (WPARAM)hFont, 0);
+ }
+ if(*szCancel == 0)
+ GetWindowText(GetDlgItem(GetParent(childwnd), IDCANCEL), szCancel, sizeof(szCancel));
+ SetWindowText(hCan, szCancel);
+ SetWindowPos(hPrbNew, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ }
+ }
+
+ if(nocancel)
+ {
+ if(hCan != NULL)
+ ShowWindow(hCan, SW_HIDE);
+ if(popup)
+ SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) ^ WS_SYSMENU);
+ }
+ SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETRANGE,
+ 0, MAKELPARAM(0, PB_RANGE));
+ if(szBanner != NULL)
+ {
+ SendDlgItemMessage(hDlg, IDC_STATIC13, STM_SETICON,
+ (WPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(103)), 0);
+ SetDlgItemText(hDlg, IDC_STATIC12, szBanner);
+ SetWindowText(hDlg, *szCaption ? szCaption : PLUGIN_NAME);
+ }
+ SetTimer(hDlg, 1, 1000, NULL);
+ if(*szUrl != 0)
+ {
+ SetDlgItemText(hDlg, IDC_STATIC20, szUrl);
+ SetDlgItemText(hDlg, IDC_STATIC21, szDownloading);
+ SetDlgItemText(hDlg, IDC_STATIC22, szConnecting);
+ SetDlgItemText(hDlg, IDC_STATIC23, szProgress);
+ SetDlgItemText(hDlg, IDC_STATIC24, szSecond);
+ SetDlgItemText(hDlg, IDC_STATIC25, szRemaining);
+ }
+}
+
+/*****************************************************
+* FUNCTION NAME: dlgProc()
+* PURPOSE:
+* dlg message handling procedure
+* SPECIAL CONSIDERATIONS:
+* todo: better dialog design
+*****************************************************/
+BOOL WINAPI dlgProc(HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam ) {
+ switch(message) {
+ case WM_INITDIALOG:
+ onInitDlg(hDlg);
+ centerDlg(hDlg);
+ break;
+ case WM_PAINT:
+ // child dialog redraw problem. return false is important
+ RedrawWindow(GetDlgItem(hDlg, IDC_STATIC1), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hDlg, IDCANCEL), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hDlg, IDC_PROGRESS1), NULL, NULL, RDW_INVALIDATE);
+ UpdateWindow(GetDlgItem(hDlg, IDC_STATIC1));
+ UpdateWindow(GetDlgItem(hDlg, IDCANCEL));
+ UpdateWindow(GetDlgItem(hDlg, IDC_PROGRESS1));
+ return false;
+ case WM_TIMER:
+ if(!silent && IsWindow(hDlg))
+ {
+ // long connection period and paused state updates
+ if(status != ST_DOWNLOAD && GetTickCount() - transfStart > PROGRESS_MS)
+ transfStart += PROGRESS_MS;
+ if(popup) onTimer(hDlg);
+ else progress_callback();
+ RedrawWindow(GetDlgItem(hDlg, IDC_STATIC1), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hDlg, IDCANCEL), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hDlg, IDC_PROGRESS1), NULL, NULL, RDW_INVALIDATE);
+ }
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ if(nocancel) break;
+ if(szQuestion &&
+ MessageBox(hDlg, szQuestion, *szCaption ? szCaption : PLUGIN_NAME, MB_ICONWARNING|MB_YESNO) == IDNO)
+ break;
+ status = ST_CANCELLED;
+ case IDOK:
+ if(status != ST_CANCELLED && HIWORD(wParam) != INTERNAL_OK) break;
+ // otherwise in the silent mode next banner windows may go to background
+ // if(silent) sf(hDlg);
+ KillTimer(hDlg, 1);
+ DestroyWindow(hDlg);
+ break;
+ }
+ default: return false;
+ }
+ return true;
+}
+
+/*****************************************************
+* FUNCTION NAME: get()
+* PURPOSE:
+* http/https/ftp file download entry point
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+extern "C"
+void __declspec(dllexport) get(HWND hwndParent,
+ int string_size,
+ TCHAR *variables,
+ stack_t **stacktop,
+ extra_parameters *extra
+ )
+{
+ HANDLE hThread;
+ DWORD dwThreadId;
+ MSG msg;
+ TCHAR szUsername[64]=_T(""), // proxy params
+ szPassword[64]=_T("");
+
+
+ EXDLL_INIT();
+
+// for repeating /nounload plug-un calls - global vars clean up
+ silent = popup = resume = nocancel = noproxy = nocookies = false;
+ myFtpCommand = NULL;
+ openType = INTERNET_OPEN_TYPE_PRECONFIG;
+ status = ST_CONNECTING;
+ *szCaption = *szCancel = *szUserAgent = *szBasic = *szAuth = 0;
+
+ url = (TCHAR*)GlobalAlloc(GPTR, string_size * sizeof(TCHAR));
+ if(szPost)
+ {
+ popstring(url);
+#ifdef UNICODE
+ WideCharToMultiByte(CP_ACP, 0, url, -1, szPost, string_size, NULL, NULL);
+#else
+ lstrcpy(szPost, url);
+#endif
+ fSize = strlen(szPost);
+ }
+ // global silent option
+ if(extra->exec_flags->silent != 0)
+ silent = true;
+ // we must take this from stack, or push url back
+ while(!popstring(url) && *url == _T('/'))
+ {
+ if(lstrcmpi(url, _T("/silent")) == 0)
+ silent = true;
+ else if(lstrcmpi(url, _T("/caption")) == 0)
+ popstring(szCaption);
+ else if(lstrcmpi(url, _T("/username")) == 0)
+ popstring(szUsername);
+ else if(lstrcmpi(url, _T("/password")) == 0)
+ popstring(szPassword);
+ else if(lstrcmpi(url, _T("/nocancel")) == 0)
+ nocancel = true;
+ else if(lstrcmpi(url, _T("/nocookies")) == 0)
+ nocookies = true;
+ else if(lstrcmpi(url, _T("/noproxy")) == 0)
+ openType = INTERNET_OPEN_TYPE_DIRECT;
+ else if(lstrcmpi(url, _T("/popup")) == 0)
+ {
+ popup = true;
+ szAlias = (TCHAR*)GlobalAlloc(GPTR, string_size);
+ popstring(szAlias);
+ }
+ else if(lstrcmpi(url, _T("/resume")) == 0)
+ {
+ popstring(url);
+ if(lstrlen(url) > 0)
+ lstrcpy(szResume, url);
+ resume = true;
+ }
+ else if(lstrcmpi(url, _T("/translate")) == 0)
+ {
+ if(popup)
+ {
+ popstring(szUrl);
+ popstring(szStatus[ST_DOWNLOAD]); // Downloading
+ popstring(szStatus[ST_CONNECTING]); // Connecting
+ lstrcpy(szStatus[ST_URLOPEN], szStatus[ST_CONNECTING]);
+ popstring(szDownloading);// file name
+ popstring(szConnecting);// received
+ popstring(szProgress);// file size
+ popstring(szSecond);// remaining time
+ popstring(szRemaining);// total time
+ }
+ else
+ {
+ popstring(szDownloading);
+ popstring(szConnecting);
+ popstring(szSecond);
+ popstring(szMinute);
+ popstring(szHour);
+ popstring(szPlural);
+ popstring(szProgress);
+ popstring(szRemaining);
+ }
+ }
+ else if(lstrcmpi(url, _T("/banner")) == 0)
+ {
+ popup = true;
+ szBanner = (TCHAR*)GlobalAlloc(GPTR, string_size);
+ popstring(szBanner);
+ }
+ else if(lstrcmpi(url, _T("/canceltext")) == 0)
+ {
+ popstring(szCancel);
+ }
+ else if(lstrcmpi(url, _T("/question")) == 0)
+ {
+ szQuestion = (TCHAR*)GlobalAlloc(GPTR, string_size);
+ popstring(szQuestion);
+ if(*szQuestion == 0) lstrcpy(szQuestion, DEF_QUESTION);
+ }
+ else if(lstrcmpi(url, _T("/useragent")) == 0)
+ {
+ popstring(szUserAgent);
+ }
+ else if(lstrcmpi(url, _T("/proxy")) == 0)
+ {
+ szProxy = (TCHAR*)GlobalAlloc(GPTR, string_size * sizeof(TCHAR));
+ popstring(szProxy);
+ openType = INTERNET_OPEN_TYPE_PROXY;
+ }
+ else if(lstrcmpi(url, _T("/connecttimeout")) == 0)
+ {
+ popstring(url);
+ timeout = _tcstol(url, NULL, 10) * 1000;
+ }
+ else if(lstrcmpi(url, _T("/receivetimeout")) == 0)
+
+ {
+ popstring(url);
+ receivetimeout = _tcstol(url, NULL, 10) * 1000;
+ }
+ else if(lstrcmpi(url, _T("/header")) == 0)
+ {
+ szHeader = (TCHAR*)GlobalAlloc(GPTR, string_size);
+ popstring(szHeader);
+ }
+ else if(lstrcmpi(url, _T("/file")) == 0)
+ {
+ HANDLE hFile = CreateFileA(szPost, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ DWORD rslt;
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ status = ERR_FILEOPEN;
+ goto cleanup;
+ }
+ if((fSize = GetFileSize(hFile, NULL)) == 0)
+ {
+ CloseHandle(hFile);
+ status = ERR_FILEREAD;
+ goto cleanup;
+ }
+ wsprintfA(post_fname, "Filename: %s",
+ strchr(szPost, '\\') ? strrchr(szPost, '\\') + 1 : szPost);
+ GlobalFree(szPost);
+ szPost = (char*)GlobalAlloc(GPTR, fSize);
+ if(ReadFile(hFile, szPost, fSize, &rslt, NULL) == 0 || rslt != fSize)
+ {
+ CloseHandle(hFile);
+ status = ERR_FILEREAD;
+ goto cleanup;
+ }
+ CloseHandle(hFile);
+ }
+ }
+ pushstring(url);
+// if(*szCaption == 0) lstrcpy(szCaption, PLUGIN_NAME);
+ if(*szUserAgent == 0) lstrcpy(szUserAgent, INETC_USERAGENT);
+ if(*szPassword && *szUsername)
+ {
+ wsprintf(url, _T("%s:%s"), szUsername, szPassword);
+ encode_base64(lstrlen(url), url, szAuth);
+ }
+ // may be silent for plug-in, but not so for installer itself - let's try to define 'progress text'
+ if(hwndParent != NULL &&
+ (childwnd = FindWindowEx(hwndParent, NULL, _T("#32770"), NULL)) != NULL &&
+ !silent)
+ SetDlgItemText(childwnd, 1006, *szCaption ? szCaption : PLUGIN_NAME);
+ else InitCommonControls(); // or NSIS do this before .onInit?
+ // cannot embed child dialog to non-existing parent. Using 'silent' to hide it
+ if(childwnd == NULL && !popup) silent = true;
+ // let's use hidden popup dlg in the silent mode - works both on .onInit and Page
+ if(silent) { resume = false; popup = true; }
+ // google says WS_CLIPSIBLINGS helps to redraw... not in my tests...
+ if(!popup)
+ {
+ unsigned int wstyle = GetWindowLong(childwnd, GWL_STYLE);
+ wstyle |= WS_CLIPSIBLINGS;
+ SetWindowLong(childwnd, GWL_STYLE, wstyle);
+ }
+ startTime = GetTickCount();
+ if((hDlg = CreateDialog(g_hInstance,
+ MAKEINTRESOURCE(szBanner ? IDD_DIALOG2 : (popup ? IDD_DIALOG1 : IDD_DIALOG3)),
+ (popup ? hwndParent : childwnd), dlgProc)) != NULL)
+ {
+
+ if((hThread = CreateThread(NULL, 0, inetTransfer, (LPVOID)hDlg, 0,
+ &dwThreadId)) != NULL)
+ {
+ HWND hButton = GetDlgItem(childwnd, 0x403);
+ HWND hList = GetDlgItem(childwnd, 0x3f8);
+ DWORD dwStyleButton = 0;
+ BOOL fVisibleList = false;
+ if(!silent)
+ {
+ ShowWindow(hDlg, SW_NORMAL);
+ if(childwnd && !popup)
+ {
+ if(hButton)
+ {
+ dwStyleButton = GetWindowLong(hButton, GWL_STYLE);
+ EnableWindow(hButton, false);
+ }
+ if(hList)
+ {
+ fVisibleList = IsWindowVisible(hList);
+ ShowWindow(hList, SW_HIDE);
+ }
+ }
+ }
+
+ while(IsWindow(hDlg) &&
+ GetMessage(&msg, NULL, 0, 0) > 0)
+ {
+ if(!IsDialogMessage(hDlg, &msg) &&
+ !IsDialogMessage(hwndParent, &msg) &&
+ !TranslateMessage(&msg))
+ DispatchMessage(&msg);
+ }
+
+ if(WaitForSingleObject(hThread, 3000) == WAIT_TIMEOUT)
+ {
+ TerminateThread(hThread, 1);
+ status = ERR_TERMINATED;
+ }
+ CloseHandle(hThread);
+ if(!silent && childwnd)
+ {
+ SetDlgItemText(childwnd, 1006, _T(""));
+ if(!popup)
+ {
+ if(hButton)
+ SetWindowLong(hButton, GWL_STYLE, dwStyleButton);
+ if(hList && fVisibleList)
+ ShowWindow(hList, SW_SHOW);
+ }
+ // RedrawWindow(childwnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE);
+ }
+ }
+ else
+ {
+ status = ERR_THREAD;
+ DestroyWindow(hDlg);
+ }
+ }
+ else {
+ status = ERR_DIALOG;
+ wsprintf(szStatus[status] + lstrlen(szStatus[status]), _T(" (Err=%d)"), GetLastError());
+ }
+cleanup:
+ // we need to clean up stack from remaining url/file pairs.
+ // this multiple files download head pain and may be not safe
+ while(!popstring(url) && lstrcmpi(url, _T("/end")) != 0)
+ {
+ /* nothing MessageBox(NULL, url, _T(""), 0);*/
+ }
+ GlobalFree(url);
+ if(szAlias) GlobalFree(szAlias);
+ if(szBanner) GlobalFree(szAlias);
+ if(szQuestion) GlobalFree(szQuestion);
+ if(szProxy) GlobalFree(szProxy);
+ if(szPost) GlobalFree(szPost);
+ if(szHeader) GlobalFree(szHeader);
+
+ url = szProxy = szHeader = szAlias = szQuestion = NULL;
+ szPost = NULL;
+ fput = fhead = false;
+
+ pushstring(szStatus[status]);
+}
+
+/*****************************************************
+* FUNCTION NAME: put()
+* PURPOSE:
+* http/ftp file upload entry point
+* SPECIAL CONSIDERATIONS:
+* re-put not works with http, but ftp REST - may be.
+*****************************************************/
+extern "C"
+void __declspec(dllexport) put(HWND hwndParent,
+ int string_size,
+ TCHAR *variables,
+ stack_t **stacktop,
+ extra_parameters *extra
+ )
+{
+ fput = true;
+ lstrcpy(szDownloading, _T("Uploading %s"));
+ lstrcpy(szStatus[2], _T("Uploading"));
+ get(hwndParent, string_size, variables, stacktop, extra);
+}
+
+/*****************************************************
+* FUNCTION NAME: post()
+* PURPOSE:
+* http post entry point
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+extern "C"
+void __declspec(dllexport) post(HWND hwndParent,
+ int string_size,
+ TCHAR *variables,
+ stack_t **stacktop,
+ extra_parameters *extra
+ )
+{
+ szPost = (CHAR*)GlobalAlloc(GPTR, string_size);
+ get(hwndParent, string_size, variables, stacktop, extra);
+}
+
+/*****************************************************
+* FUNCTION NAME: head()
+* PURPOSE:
+* http/ftp file upload entry point
+* SPECIAL CONSIDERATIONS:
+* re-put not works with http, but ftp REST - may be.
+*****************************************************/
+extern "C"
+void __declspec(dllexport) head(HWND hwndParent,
+ int string_size,
+ TCHAR *variables,
+ stack_t **stacktop,
+ extra_parameters *extra
+ )
+{
+ fhead = true;
+ get(hwndParent, string_size, variables, stacktop, extra);
+}
+
+/*****************************************************
+* FUNCTION NAME: DllMain()
+* PURPOSE:
+* Dll main (initialization) entry point
+* SPECIAL CONSIDERATIONS:
+*
+*****************************************************/
+BOOL WINAPI DllMain(HANDLE hInst,
+ ULONG ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ g_hInstance=(HINSTANCE)hInst;
+ return TRUE;
+}
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsp b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsp
new file mode 100644
index 000000000..2a4d46410
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsp
@@ -0,0 +1,175 @@
+# Microsoft Developer Studio Project File - Name="inetc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=inetc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "inetc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "inetc.mak" CFG="inetc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "inetc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "inetc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "inetc - Win32 Release_Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "inetc - Win32 Debug_Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "inetc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /I "..\ExDll" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 msvcrt.lib kernel32.lib user32.lib gdi32.lib wininet.lib comctl32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib /out:"..\..\plugins\inetc.dll" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "inetc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\ExDll" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib wininet.lib comctl32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\plugins\inetc.dll" /pdbtype:sept
+# SUBTRACT LINK32 /incremental:no /debug
+
+!ELSEIF "$(CFG)" == "inetc - Win32 Release_Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_Unicode"
+# PROP BASE Intermediate_Dir "Release_Unicode"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /I "..\ExDll" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 msvcrt.lib kernel32.lib user32.lib gdi32.lib wininet.lib comctl32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib /out:"..\..\Unicode\plugins\inetc.dll" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "inetc - Win32 Debug_Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_Unicode"
+# PROP BASE Intermediate_Dir "Debug_Unicode"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\ExDll" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "inetc_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib wininet.lib comctl32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Unicode\plugins\inetc.dll" /pdbtype:sept
+# SUBTRACT LINK32 /incremental:no /debug
+
+!ENDIF
+
+# Begin Target
+
+# Name "inetc - Win32 Release"
+# Name "inetc - Win32 Debug"
+# Name "inetc - Win32 Release_Unicode"
+# Name "inetc - Win32 Debug_Unicode"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\inetc.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE="..\Graphics\Icons\classic-install.ico"
+# End Source File
+# Begin Source File
+
+SOURCE=.\inetc.rc
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsw b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsw
new file mode 100644
index 000000000..98a25c5b2
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ftpc"=".\inetc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.rc b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.rc
new file mode 100644
index 000000000..6a29a56f3
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc.rc
@@ -0,0 +1,170 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOGEX 0, 0, 286, 71
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Inetc plug-in"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "",IDC_STATIC1,50,4,230,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ LTEXT "",IDC_STATIC2,50,18,230,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ CTEXT "",IDC_STATIC3,50,32,102,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ CTEXT "",IDC_STATIC4,220,32,60,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",NOT
+ WS_VISIBLE,5,62,275,7
+ CTEXT "",IDC_STATIC5,50,46,102,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ CTEXT "",IDC_STATIC6,220,46,60,12,SS_CENTERIMAGE,
+ WS_EX_STATICEDGE
+ CONTROL "URL",IDC_STATIC20,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,
+ 5,6,44,10
+ CONTROL "File name",IDC_STATIC21,"Static",SS_LEFTNOWORDWRAP |
+ WS_GROUP,5,20,44,10
+ CONTROL "Transfered",IDC_STATIC22,"Static",SS_LEFTNOWORDWRAP |
+ WS_GROUP,5,34,44,10
+ CONTROL "File size",IDC_STATIC23,"Static",SS_LEFTNOWORDWRAP |
+ WS_GROUP,5,48,44,10
+ CONTROL "Remaining time",IDC_STATIC24,"Static",SS_LEFTNOWORDWRAP |
+ WS_GROUP,164,34,55,10
+ CONTROL "Total time",IDC_STATIC25,"Static",SS_LEFTNOWORDWRAP |
+ WS_GROUP,164,48,55,10
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 226, 62
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Inetc plug-in"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON 103,IDC_STATIC13,4,4,20,20
+ LTEXT "Please wait",IDC_STATIC12,35,6,184,28
+ CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",NOT
+ WS_VISIBLE,12,40,201,11
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 266, 62
+STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",0x0,0,23,
+ 266,11
+ CTEXT "",IDC_STATIC1,0,8,266,11
+ PUSHBUTTON "Cancel",IDCANCEL,166,41,80,16
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 279
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 64
+ END
+
+ IDD_DIALOG2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 219
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 55
+ END
+
+ IDD_DIALOG3, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 259
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 55
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc_local.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc_local.nsi
new file mode 100644
index 000000000..845a18d64
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/inetc_local.nsi
@@ -0,0 +1,80 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Local Test"
+OutFile "inetc_local.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+
+; PUT test
+
+; FTP requires anonymous access in sample below.
+; HTTP sample put.php included to package. Stores test.jpg as m2.bmp
+; check server files present after upload
+
+ inetc::put "http://localhost/put.php" "$EXEDIR\test.jpg"
+ Pop $0
+
+ inetc::put "ftp://localhost/test.jpg" "$EXEDIR\test.jpg"
+; not anonymous format
+; inetc::put "ftp://login:password@localhost/test.jpg" "$EXEDIR\test.jpg"
+ Pop $1
+
+ DetailPrint "PUT: HTTP $0, FTP $1 (verify server files)"
+
+
+; POST test
+
+; HTTP sample post.php and post_form.htm (to compare results) included
+
+ inetc::post "login=ami&passwd=333" "http://localhost/post.php?lg=iam&pw=44" "$EXEDIR\post_reply.htm"
+ Pop $2
+
+ DetailPrint "POST: $2 (post_reply.htm)"
+
+
+; HEAD test
+
+; uses uploaded earlier test.jpg
+
+ inetc::head /silent "http://localhost/m2.bmp" "$EXEDIR\head.txt"
+ Pop $3
+
+ DetailPrint "HEAD: $3 (head.txt)"
+
+
+; GET test
+
+; 2 files download in nsisdl mode
+ inetc::get "http://localhost/m2.bmp" "$EXEDIR\get1.jpg" "http://localhost/m2.bmp" "$EXEDIR\get2.jpg"
+ Pop $4
+
+ inetc::get /popup "Localhost:GET with Popup" "http://localhost/m2.bmp" "$EXEDIR\get3.jpg"
+ Pop $5
+
+ inetc::get /banner "Local Test GET with Banner" "http://localhost/m2.bmp" "$EXEDIR\get4.jpg"
+ Pop $6
+
+ inetc::get /silent "ftp://localhost/test.jpg" "$EXEDIR\get5.jpg"
+ Pop $7
+
+ DetailPrint "GET: NSISDL $4, POPUP $5, BANNER $6, FTP $7 (get1-5.jpg)"
+
+ SetDetailsView show
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.nsi
new file mode 100644
index 000000000..9dcf0d2bb
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.nsi
@@ -0,0 +1,30 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Post Test"
+OutFile "post.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; this is my LAN sample, use your own URL for tests. Sample post.php included
+
+ inetc::post "login=ami&passwd=333" "http://localhost/post.php?lg=iam&pw=44" "$EXEDIR\post_reply.htm"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.php b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.php
new file mode 100644
index 000000000..f6a894964
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post.php
@@ -0,0 +1,13 @@
+
+
+
+
+";
+echo "post.passwd=".$_POST['passwd']." ";
+echo "get.lg=".$_GET['lg']." ";
+echo "get.pw=".$_GET['pw']." ";
+?>
+
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.nsi
new file mode 100644
index 000000000..7bb7b7704
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.nsi
@@ -0,0 +1,30 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Post Test"
+OutFile "post_file.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; this is my LAN sample, use your own URL for tests. Sample post.php included
+
+ inetc::post "$EXEDIR\inetc.cpp" /file "http://localhost/post_file.php" "$EXEDIR\post_file.htm"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.php b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.php
new file mode 100644
index 000000000..07ab4fbf2
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_file.php
@@ -0,0 +1,10 @@
+ $value) {
+ echo "$header: $value \n";
+}
+echo "new ";
+foreach ($_FILES as $key => $value) echo $key . "<>" . $value . " \n";
+echo file_get_contents('php://input');
+?>
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_form.html b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_form.html
new file mode 100644
index 000000000..046d60533
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/post_form.html
@@ -0,0 +1,18 @@
+
+
+Registration form for post.php test
+
+
+This form sends POST request to server. It was interesting to compare server echo
+reply (by included post.php) for this form and InetLoad plug-in - in my
+tests server did not see any difference between them :)
+
+
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.nsi
new file mode 100644
index 000000000..95cc8dda4
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.nsi
@@ -0,0 +1,30 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Test"
+OutFile "put.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; this is my LAN sample, use your own URL for tests. Login/pwd hidden from user. Sample put.php (for http request) included
+
+ inetc::put "http://localhost/put.php" "$EXEDIR\test.jpg"
+; inetc::put /POPUP "ftp://localhost/" /CAPTION "my local ftp upload" "ftp://localhost/test.jpg" "$EXEDIR\test.jpg"
+ Pop $0
+ MessageBox MB_OK "Upload Status: $0"
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.php b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.php
new file mode 100644
index 000000000..7bb2bf526
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/put.php
@@ -0,0 +1,19 @@
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/recursive.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/recursive.nsi
new file mode 100644
index 000000000..52e032663
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/recursive.nsi
@@ -0,0 +1,64 @@
+Name "Inetc Recursive Dir Upload Test"
+OutFile "recursive.exe"
+
+!include "MUI.nsh"
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_LANGUAGE "English"
+!include "FileFunc.nsh"
+!insertmacro GetFileAttributes
+
+var url
+var path
+
+Function dirul
+
+ Push $0 ; search handle
+ Push $1 ; file name
+ Push $2 ; attributes
+
+ FindFirst $0 $1 "$path\*"
+loop:
+ StrCmp $1 "" done
+ ${GetFileAttributes} "$path\$1" DIRECTORY $2
+ IntCmp $2 1 isdir
+retry:
+ Inetc::put $url/$1 "$path\$1" /end
+ Pop $2
+ DetailPrint "$2 $path\$1"
+ StrCmp $2 "OK" cont
+ MessageBox MB_YESNO "$path\$1 file upload failed. Retry?" IDYES retry
+ Abort "terminated by user"
+ Goto cont
+isdir:
+ StrCmp $1 . cont
+ StrCmp $1 .. cont
+ Push $path
+ Push $url
+ StrCpy $path "$path\$1"
+ StrCpy $url "$url/$1"
+ Call dirul
+ Pop $url
+ Pop $path
+cont:
+ FindNext $0 $1
+ Goto loop
+done:
+ FindClose $0
+
+ Pop $2
+ Pop $1
+ Pop $0
+
+FunctionEnd
+
+
+Section "Dummy Section" SecDummy
+
+ SetDetailsView hide
+ StrCpy $path "$EXEDIR"
+; put is dir in the user's ftp home, use //put for root-relative path
+ StrCpy $url ftp://takhir:pwd@localhost/put
+ Call dirul
+ SetDetailsView show
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.nsi
new file mode 100644
index 000000000..cd2943420
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.nsi
@@ -0,0 +1,30 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Redirect Test"
+OutFile "redirect.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+ SetDetailsView hide
+
+ inetc::get "http://localhost/redirect.php" "$EXEDIR\redirect.htm" /end
+ Pop $1
+
+ MessageBox MB_OK "Download Status: $1"
+
+SectionEnd
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.php b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.php
new file mode 100644
index 000000000..afe455283
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/redirect.php
@@ -0,0 +1,6 @@
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/resource.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/resource.h
new file mode 100644
index 000000000..d7fc835a6
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/resource.h
@@ -0,0 +1,47 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by inetc.rc
+//
+#define IDC_SLOGIN 8
+#define IDC_PROGRESS 10
+#define IDC_SUBTEXT 11
+#define IDC_SPWD 11
+#define IDC_ICON1 12
+#define IDD_DIALOG1 101
+#define IDI_ICON1 102
+#define IDI_ICON2 103
+#define IDD_AUTH 104
+#define IDI_ICON3 105
+#define IDI_ICON4 106
+#define IDI_ICON5 107
+#define IDD_DIALOG2 108
+#define IDI_ICON6 109
+#define IDD_DIALOG3 110
+#define IDC_STATIC1 1001
+#define IDC_STATIC2 1002
+#define IDC_STATIC3 1003
+#define IDC_STATIC4 1004
+#define IDC_PROGRESS1 1005
+#define IDC_STATIC5 1006
+#define IDC_STATIC6 1007
+#define IDC_STATIC12 1008
+#define IDC_STATIC13 1009
+#define IDC_STATIC20 1009
+#define IDC_STATIC21 1010
+#define IDC_STATIC22 1011
+#define IDC_STATIC23 1012
+#define IDC_STATIC24 1013
+#define IDC_STATIC25 1014
+#define IDC_ELOGIN 1015
+#define IDC_EPWD 1016
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 111
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1018
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/timeout.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/timeout.nsi
new file mode 100644
index 000000000..7ff5688af
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/timeout.nsi
@@ -0,0 +1,31 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Timeout Test"
+OutFile "to.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "English"
+
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; additional headers. Sample php returns raw headers
+ inetc::get /receivetimeout 12 "http://localhost/to.php" "$EXEDIR\to.html"
+ Pop $0
+
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
+
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/translate.nsi b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/translate.nsi
new file mode 100644
index 000000000..053a8155e
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/translate.nsi
@@ -0,0 +1,32 @@
+
+;--------------------------------
+; General Attributes
+
+Name "Inetc Translate Test"
+OutFile "Translate.exe"
+
+
+;--------------------------------
+;Interface Settings
+
+ !include "MUI.nsh"
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-colorful.ico"
+ !insertmacro MUI_PAGE_WELCOME
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_PAGE_FINISH
+ !insertmacro MUI_LANGUAGE "Russian"
+
+
+;--------------------------------
+;Installer Sections
+
+Section "Dummy Section" SecDummy
+
+; This is russian variant. See Readme.txt for a list of parameters.
+; Use LangStrings as TRANSLATE parameters for multilang options
+
+ inetc::load /POPUP "" /CAPTION " " /TRANSLATE "URL" "" " " " " "" "" "" "http://ineum.narod.ru/g06s.htm" "$EXEDIR\g06s.htm"
+ Pop $0 # return value = exit code, "OK" if OK
+ MessageBox MB_OK "Download Status: $0"
+
+SectionEnd
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/wiki.txt b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/wiki.txt
new file mode 100644
index 000000000..f7fccb58e
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Inetc/wiki.txt
@@ -0,0 +1,169 @@
+{{PageAuthor|Takhir}}
+
+== Links ==
+
+Download:
+Inetc.zip
+
+[http://forums.winamp.com/showthread.php?threadid=198596 Forum thread]
+
+== Description ==
+
+Internet client plug-in for files download and upload. Based on the InetLoad plug-in. Network implementation uses MS WinInet API, supports http/https and ftp protocols. Plugin has better proxy support compared to NSISdl plug-in. Command line may include few URL/File pairs to be transfered. If server or proxy login/password are not set in the script, it displays IE-style authentication dialog (except silent mode). Plug-in supports 3 "transfer in progress" display modes:
+
+# old NSISdl style - additional embedded progress bar and text on the INSTFILES page;
+# POPUP dialog mode with detailed info;
+# BANNER mode with simple popup window.
+
+Plug-in recognizes Installer's Silent mode and this case hides any output (this feature requires NSIS 2.03 or later). Program implements simple re-get functionality - host reconnect and download from current position after short pause. While program depends on IE settings, it changes current IE mode to online. NSISdl code fragment was used for progress bar displaying in the "old style" mode.
+For ftp use "host/path" for file location relative to user's home dir and
+"host//path" for absolute path.
+
+== Command line ==
+
+Plug-in DLL functions (entry points): get, post, head, put
+
+=== get DLL Function ===
+
+inetc::get [/PROXY IP:PORT] [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD]
+ [/NOPROXY] [/NOCANCEL] [/CONNECTTIMEOUT TO_SEC] [/RECEIVETIMEOUT TO_SEC] [/SILENT]
+ [/CAPTION TEXT] [/NOCOOKIES] [/RESUME RETRY_QUESTION] [/POPUP HOST_ALIAS | /BANNER TEXT]
+ [/CANCELTEXT CANCEL_TEXT] [/QUESTION CANCEL_QUESTION] [/USER_AGENT USER_AGENT_TEXT]
+ [/HEADER HEADER_TEXT] [/TRANSLATE LANG_PARAMS]
+ URL1 local_file1 [URL2 local_file2 [...]] [/END]
+This call returns "OK" string if successful, error description string if failed (see included InetLoad.cpp file for a full set of status strings). Usage and result processing samples are included to the package.
+
+; /PROXY
+: Overwrites current proxy settings, not required in most cases. IE settings will be used by default.
+
+; /USERNAME
+: Proxy username (http only).
+
+; /PASSWORD
+: Proxy password (http only). For server (http/ftp) authentication it is possible to use URL encoded name and password, for example http://username:password@nsis.sourceforge.net .
+
+;/NOPROXY
+: Disables proxy settings for this connection (if any)
+
+;/NOCANCEL
+: Prevents download from being interrupted by user (locks Esc, Alt-F4, Cancel handling)
+
+;/CONNECTTIMEOUT -
+:Sets INTERNET_OPTION_CONNECT_TIMEOUT, seconds, default - IE current parameter value.
+
+;/RECEIVETIMEOUT -
+:Sets INTERNET_OPTION_RECEIVE_TIMEOUT, seconds, default - IE current parameter value.
+
+; /SILENT
+: Key hides plug-in' output (both popup dialog and embedded progress bar). Not required if 'SilentInstall silent' mode was defined in script (NSIS 2.03 or later).
+
+; /RESUME
+: On the permanent connection/transfer error instead of exit first displays message box with "resume download" question. Useful for dial-up connections and big files - allows user to restore connection and resume download. Default is "Your internet connection seems to have dropped out!\nPlease reconnect and click Retry to resume downloading...".
+
+; /CAPTION
+: Defines caption text for /BANNER mode, caption prefix (left of '-') for /POPUP mode and caption for RESUME MessageBox. Default is "InetLoad plug-in" if not set or "".
+
+; /POPUP
+: This mode displays detailed download dialog instead of embedded progress bar. Also useful in .onInit function (i.e. not in Section). If HOST_ALIAS is not "", text will replace URL in the dialog - this allows to hide real URL (including password).
+
+; /BANNER
+: Displays simple popup dialog (MSI Banner mode) and sets dialog TEXT (up to 3 lines using $\n).
+
+; /CANCELTEXT
+: Text for the Cancel button in the NSISdl mode. Default is NSIS dialog Cancel button text (current lang).
+
+; /QUESTION
+: Text for the optional MessageBox if user tries to cancel download. If /QUESTION "" was used default "Are you sure that you want to stop download?" will be substituted.
+
+; /USERAGENT
+: UserAgent http request header value. Default is "NSIS_Inetc (Mozilla)".
+
+; /HEADER
+: Adds or replaces http request header. Common HEADER_TEXT format is "header: value".
+
+; /NOCOOKIES
+: Removes cookies from http request
+
+; /END
+: Allows to limit plug-in stack reading (optional, required if you stores other vars in the stack).
+
+; /TRANSLATE
+: Allows translating plug-in text in the POPUP or "old style" (NSISdl) modes (see Readme for parameters). In the BANNER mode text is also customizable.
+
+=== post DLL Function ===
+
+inetc::post TEXT2POST [/PROXY IP:PORT] [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD]
+ [/NOPROXY] [/NOCANCEL] [/CONNECTTIMEOUT TO_SEC] [/RECEIVETIMEOUT TO_SEC] [/SILENT]
+ [/FILE] [/CAPTION TEXT] [/NOCOOKIES] [/POPUP HOST_ALIAS | /BANNER TEXT]
+ [/CANCELTEXT CANCEL_TEXT] [/USER_AGENT USER_AGENT_TEXT] [/TRANSLATE LANG_PARAMS]
+ URL1 local_file1 [URL2 local_file2 [...]] [/END]
+Sets POST http mode and defines text string or file name to be used in the POST (http only). Disables auto re-get. No char replaces used (%20 and others). /FILE option allows to send TEXT2POST file content to server, additional 'Filename:' header added to request this case.
+
+=== head DLL Function ===
+
+The same as get, but requests http headers only. Writes raw headers to file.
+
+=== put DLL Function ===
+
+inetc::put [/PROXY IP:PORT] [/USERNAME PROXY_LOGIN /PASSWORD PROXY_PASSWD] [/NOPROXY]
+ [/NOCANCEL] [/CONNECTTIMEOUT TO_SEC] [/RECEIVETIMEOUT TO_SEC] [/SILENT] [/CAPTION TEXT]
+ [/POPUP HOST_ALIAS | /BANNER TEXT] [/CANCELTEXT CANCEL_TEXT] [/USER_AGENT USER_AGENT_TEXT]
+ [/TRANSLATE LANG_PARAMS] [/NOCOOKIES]
+ URL1 local_file1 [URL2 local_file2 [...]] [/END]
+Return value and parameters (if applicable) are the same as for previous entry point.
+
+== Examples ==
+
+
+inetc::get "http://dl.zvuki.ru/6306/mp3/12.mp3" "$EXEDIR\12.mp3" \
+ "ftp://dl.zvuki.ru/6306/mp3/11.mp3" "$EXEDIR\11.mp3"
+Pop $0
+
+
+
+inetc::put /BANNER "Cameron Diaz upload in progress..." \
+"http://www.dreamgirlswallpaper.co.uk/fiveyearsonline/wallpaper/Cameron_Diaz/camerond09big.JPG" \
+"$EXEDIR\cd.jpg"
+ Pop $0
+ StrCmp $0 "OK" dlok
+ MessageBox MB_OK|MB_ICONEXCLAMATION "http upload Error, click OK to abort installation" /SD IDOK
+ Abort
+dlok:
+ ...
+
+
+
+;installer window restoring after silent calls from .onGUIInit
+;by Edward Marshall & Jonathan Beddoes
+;temporarily makes the installer window topmost so that inetc doesn't drop our focus
+
+Function .onGUIInit
+
+ ; Get window handle of installer into register 0.
+ ; This only works in onGUIInit! (so you still can't silently call inetc from onInit)
+ StrCpy $0 $HWNDPARENT
+
+ ; Make window always-on-top. Yes, this is bad but we are only doing it temporarily!
+ ; This prevents inetc's hidden dialog from getting foreground precedence over the installer.
+ ; This must be done before any inetc calls.
+ ; -1 = HWND_TOPMOST, 3 = SWP_NOSIZE|SWP_NOMOVE
+ System::Call "user32::SetWindowPos(i r0, i -1, i 0, i 0, i 0, i 0, i 3)"
+
+ ; Now do whatever you want with inetc.
+ inetc::head /silent "http://ineum.narod.ru/spr_2006.htm" "$EXEDIR\head.txt"
+
+ ; Now set the installer window back to normal (not always-on-top).
+ ; -2 = HWND_NOTOPMOST, 3 = SWP_NOSIZE|SWP_NOMOVE
+ System::Call "user32::SetWindowPos(i r0, i -2, i 0, i 0, i 0, i 0, i 3)"
+
+FunctionEnd
+
+
+; Following attribute also can restore installer Window
+; BGGradient 000000 000080 FFFFFF
+
+== Credits ==
+
+Many thanks to Backland who offered a simple way to fix NSISdl mode crashes, added 'center parent' function, offers few nice design ideas and spent a lot of time testing the plug-in.
+
+[[Category:Plugins]]
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nlf
new file mode 100644
index 000000000..1ec535899
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nsh
new file mode 100644
index 000000000..154afb60a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Afrikaans.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nlf
new file mode 100644
index 000000000..a27dbd8d6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nsh
new file mode 100644
index 000000000..faf9224e7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Albanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nlf
new file mode 100644
index 000000000..e8ba22303
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nsh
new file mode 100644
index 000000000..1f6f3b51c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Arabic.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nlf
new file mode 100644
index 000000000..182ce50a9
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nsh
new file mode 100644
index 000000000..67884c57a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Armenian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nlf
new file mode 100644
index 000000000..2f46f500e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nsh
new file mode 100644
index 000000000..bf5939bcd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Basque.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nlf
new file mode 100644
index 000000000..3730e75a5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nsh
new file mode 100644
index 000000000..57089408c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Belarusian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nlf
new file mode 100644
index 000000000..d7d7ebb34
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nsh
new file mode 100644
index 000000000..e9df25470
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bosnian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nlf
new file mode 100644
index 000000000..a908febc6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nsh
new file mode 100644
index 000000000..e80cb1b94
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Breton.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nlf
new file mode 100644
index 000000000..de8fe4ad3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nsh
new file mode 100644
index 000000000..d8d9fdbc8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Bulgarian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nlf
new file mode 100644
index 000000000..8800ef074
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nsh
new file mode 100644
index 000000000..931cc43ce
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Catalan.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nlf
new file mode 100644
index 000000000..8faaec4bf
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nsh
new file mode 100644
index 000000000..038825ddb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Cibemba.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nlf
new file mode 100644
index 000000000..97a7f2b14
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nsh
new file mode 100644
index 000000000..0670d63b6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Croatian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nlf
new file mode 100644
index 000000000..2a337ea73
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nsh
new file mode 100644
index 000000000..ae1f19b10
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Czech.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nlf
new file mode 100644
index 000000000..943749e5d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nsh
new file mode 100644
index 000000000..ae4ebd45f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Danish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nlf
new file mode 100644
index 000000000..a556efa3a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nsh
new file mode 100644
index 000000000..b3fb5c232
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Dutch.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nlf
new file mode 100644
index 000000000..70b9cd88c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nsh
new file mode 100644
index 000000000..bf8ae0ee3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Efik.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nlf
new file mode 100644
index 000000000..09cc0b80c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nsh
new file mode 100644
index 000000000..cc8cdc911
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/English.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nlf
new file mode 100644
index 000000000..61d26c34c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nsh
new file mode 100644
index 000000000..771eb24ab
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/EnglishGB.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nlf
new file mode 100644
index 000000000..2636fce9d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nsh
new file mode 100644
index 000000000..c01b319f7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Esperanto.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nlf
new file mode 100644
index 000000000..5317a1c8b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nsh
new file mode 100644
index 000000000..b75660f6c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Estonian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nlf
new file mode 100644
index 000000000..0f62cf696
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nsh
new file mode 100644
index 000000000..44f6b4e64
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Farsi.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nlf
new file mode 100644
index 000000000..8d64dd3c1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nsh
new file mode 100644
index 000000000..2c003fbde
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Finnish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nlf
new file mode 100644
index 000000000..613491767
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nsh
new file mode 100644
index 000000000..81b6b2afc
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/French.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nlf
new file mode 100644
index 000000000..456b9d878
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nsh
new file mode 100644
index 000000000..ac5b8846d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Galician.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nlf
new file mode 100644
index 000000000..8f49e35ad
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nsh
new file mode 100644
index 000000000..730b550be
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Georgian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nlf
new file mode 100644
index 000000000..16969cb68
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nsh
new file mode 100644
index 000000000..807bc8fbe
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/German.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nlf
new file mode 100644
index 000000000..a7fbcd542
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nsh
new file mode 100644
index 000000000..c8b07c661
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Greek.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nlf
new file mode 100644
index 000000000..22781ff24
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nsh
new file mode 100644
index 000000000..b95289f81
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hebrew.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nlf
new file mode 100644
index 000000000..5f95e49e8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nsh
new file mode 100644
index 000000000..f68f90697
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hindi.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nlf
new file mode 100644
index 000000000..dde9b3191
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nsh
new file mode 100644
index 000000000..e117f7fb4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Hungarian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nlf
new file mode 100644
index 000000000..565d05a5d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nsh
new file mode 100644
index 000000000..5806041d4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Icelandic.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nlf
new file mode 100644
index 000000000..f7c914238
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nsh
new file mode 100644
index 000000000..80ef89868
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Igbo.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nlf
new file mode 100644
index 000000000..2e18276f1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nsh
new file mode 100644
index 000000000..daaba7f34
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Indonesian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nlf
new file mode 100644
index 000000000..a89970ab7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nsh
new file mode 100644
index 000000000..fe46098eb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Irish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nlf
new file mode 100644
index 000000000..617d4af82
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nsh
new file mode 100644
index 000000000..5f7077881
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Italian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nlf
new file mode 100644
index 000000000..9b94418ba
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nsh
new file mode 100644
index 000000000..d52b12c27
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Japanese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nlf
new file mode 100644
index 000000000..17010c2f0
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nlf
@@ -0,0 +1,191 @@
+# Header, don't edit
+NLF v6
+# Start editing here
+# Language ID
+10311
+# Font and size - dash (-) means default
+-
+-
+# Codepage - dash (-) means ANSI code page
+1200
+# RTL - anything else than RTL means LTR
+-
+# Translation by .....សុផល្លី (yi sophally, yi.sophally at gmail dot com)
+# ^Branding
+Nullsoft Install System %s
+# ^SetupCaption
+ដំឡើងកម្មវិធី $(^Name)
+# ^UninstallCaption
+លុប $(^Name) ចេញ
+#^LicenseSubCaption
+: កិច្ចសន្យាអាជ្ញាបប័ណ្ណ
+# ^ComponentsSubCaption
+: ជំរើសនៃការដំឡើង
+# ^DirSubCaption
+: ថតដើម្បីដំឡើង
+# ^InstallingSubCaption
+: កំពុងដំឡើង
+# ^CompletedSubCaption
+: ដំឡើងរួចរាល់
+# ^UnComponentsSubCaption
+: ជំរើសនៃការលុបកម្មវិធីចេញ
+# ^UnDirSubCaption
+: ថតដែលត្រូវលុបកម្មវិធីចេញ
+# ^ConfirmSubCaption
+: ការបញ្ជាក់ទទួលយក
+# ^UninstallingSubCaption
+: កំពុងលុបចេញ
+# ^UnCompletedSubCaption
+: លុបចេញរួចរាល់
+# ^BackBtn
+< &ត្រលប់ក្រោយ
+# ^NextBtn
+&ទៅមុខ >
+# ^AgreeBtn
+I &យល់ព្រម
+# ^AcceptBtn
+ខ្ញុំ &យល់ព្រមតាមកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណ
+# ^DontAcceptBtn
+&ខ្ញុំមិនយល់ព្រមតាមកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណទេ
+# ^InstallBtn
+&ដំឡើង
+# ^UninstallBtn
+&លុបចេញ
+# ^CancelBtn
+បដិសេធ
+# ^CloseBtn
+&បិទ
+# ^BrowseBtn
+ស្វែង&រក...
+# ^ShowDetailsBtn
+បង្ហាញ &លំអិតសេចក្តី
+# ^ClickNext
+ចុចទៅមុខដើម្បីបន្ត
+# ^ClickInstall
+ចុចលើដំឡើងដើម្បីចាប់ផ្តើមដំណើរការ
+# ^ClickUninstall
+ចុចលើលុបចេញដើម្បីចាប់ផ្តើមលុប
+# ^Name
+ឈ្មោះ
+# ^Completed
+រួចរាល់
+# ^LicenseText
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលដំឡើងកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមចុចយក ខ្ញុំយល់ព្រម
+# ^LicenseTextCB
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលដំឡើងកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមធិកយកប្រអប់ខាងក្រោម$_CLICK
+# ^LicenseTextRB
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលដំឡើងកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមជ្រើសយកជំរើសទីមួយខាងក្រោម $_CLICK
+# ^UnLicenseText
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលលុបកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមចុចយក ខ្ញុំយល់ព្រម
+# ^UnLicenseTextCB
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលលុបកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមធិកយកប្រអប់ខាងក្រោម$_CLICK
+# ^UnLicenseTextRB
+សូមអានកិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណមុនពេលលុបកម្មវិធី $(^NameDA) នេះ។ ប្រសិនបើអ្នកយល់ស្របសូមជ្រើសយកជំរើសទីមួយខាងក្រោម $_CLICK
+# ^Custom
+ជំរើសផ្ទាល់ខ្លួន
+# ^ComponentsText
+ធិកយកសមាសភាគដែលអ្នកចង់ដំឡើងនិងដោះធិកពីសមាសភាគដែលអ្នកមិនចង់ដំឡើង $_CLICK
+# ^ComponentsSubText1
+សូមជ្រើសរើសប្រភេទនៃការដំឡើង:
+# ^ComponentsSubText2_NoInstTypes
+សូមជ្រើសរើសសមាសភាគដើម្បីដំឡើង:
+# ^ComponentsSubText2
+ឬ ជ្រើសរើសសមាសភាគជាជំរើសណាមួយដែលអ្នកចង់ដំឡើង:
+# ^UnComponentsText
+ធិកយកសមាសភាគដែលអ្នកចង់លុបចេញនិងដោះធិកពីសមាសភាគដែលអ្នកមិនចង់លុបចេញ $_CLICK
+# ^UnComponentsSubText1
+សូមជ្រើសរើសប្រភេទនៃការលុបកម្មវិធី:
+# ^UnComponentsSubText2_NoInstTypes
+សូមជ្រើសរើសសមាសភាគដើម្បីកាត់ចេញ:
+# ^UnComponentsSubText2
+ឬ ជ្រើសរើសសមាសភាគជាជំរើសណាមួយដែលអ្នកចង់កាត់ចេញ:
+# ^DirText
+កម្មវិធីជំនួយនេះនឹងដំឡើង$(^NameDA)នៅក្នុងថតខាងក្រោមនេះ។ ដើម្បីដំឡើងនៅក្នុងថតដទៃទៀតសូមចុចលើស្វែងរក ហើយជ្រើសរើសថតផ្សេងទៀត។ $_CLICK
+# ^DirSubText
+ថតគោលដៅ
+# ^DirBrowseText
+ជ្រើសរើសថតដើម្បីដំឡើងកម្មវិធី$(^NameDA):
+# ^UnDirText
+កម្មវិធីជំនួយនេះនឹងលុប$(^NameDA)ចេញពីថតខាងក្រោមនេះ។ ដើម្បីចេញពីក្នុងថតដទៃទៀតសូមចុចលើស្វែងរក ហើយជ្រើសរើសថតផ្សេងទៀត។ $_CLICK
+# ^UnDirSubText
+""
+# ^UnDirBrowseText
+ជ្រើសរើសថតដើម្បីលុបកម្មវិធី$(^NameDA)ចេញ:
+# ^SpaceAvailable
+"ចណ្លោះទំហំដែលអាចប្រើប្រាស់បាន: "
+# ^SpaceRequired
+"តំរូវការទំហំ: "
+# ^UninstallingText
+$(^NameDA) នឹងត្រូវបានលុបចេញពីថតខាងក្រោមនេះ។ $_CLICK
+# ^UninstallingSubText
+កំពុងលុបចេញពី:
+# ^FileError
+មានកំហុសក្នុងការបើកឯកសារដើម្បីសរសេរចូល:\r\n\r\n$0\r\n\r\n សូមចុចលើ បញ្ឈប់ ដើម្បីបញ្ចប់ការដំឡើង \r\n Retry ដើម្បីព្យាយាមម្តងទៀត ឫ បដិសេធដើម្បីបញ្ឈប់ឯកសារនេះ។
+# ^FileError_NoIgnore
+មានកំហុសក្នុងការបើកឯកសារដើម្បីសរសេរចូល:\r\n\r\n$0\r\n\r\n សូមចុចលើ Retry ដើម្បីព្យាយាមម្តងទៀត ឫ \r\nបដិសេធ ដើម្បីបញ្ឈប់ការដំឡើង។
+# ^CantWrite
+"មិនអាចសរសេរចូលបាន: "
+# ^CopyFailed
+ការចំលងបរាជ័យ
+# ^CopyTo
+"ចំលងទៅកាន់ "
+# ^Registering
+"កំពុងចុះឈ្មោះ: "
+# ^Unregistering
+"កំពុងលុបឈ្មោះ: "
+# ^SymbolNotFound
+"មិនអាចរកនិមិត្តសញ្ញាឃើញ: "
+# ^CouldNotLoad
+"មិនអាចទាញមកបាន: "
+# ^CreateFolder
+"បង្កើតថត: "
+# ^CreateShortcut
+"បង្កើតផ្លូវកាត់: "
+# ^CreatedUninstaller
+"កម្មវិធីដើម្បីលុបត្រូវបានបង្កើត: "
+# ^Delete
+"លុបឯកសា: "
+# ^DeleteOnReboot
+"លុបពេលកុំព្យូទ័រដំណើរការឡើងវិញ: "
+# ^ErrorCreatingShortcut
+"មានកំហុសក្នុងការបង្កើតផ្លូវកាត់: "
+# ^ErrorCreating
+"មានកំហុសក្នុងការបង្កើត: "
+# ^ErrorDecompressing
+មានកំហុសក្នុងការពន្លាទិន្នន័យ! កម្មវិធីដំឡើងមានបញ្ហា?
+# ^ErrorRegistering
+មានកំហុសក្នុងការចុះឈ្មោះ ឌីអិលអិល
+# ^ExecShell
+"ប្រតិប័ត្តសែល: "
+# ^Exec
+"ប្រតិប័ត្ត: "
+# ^Extract
+"ពន្លា: "
+# ^ErrorWriting
+"ពន្លាឯកសារ: មានបញ្ហាពេលសរសេរចូលឯកសារ "
+# ^InvalidOpcode
+កម្មវិធីដំឡើងមានបញ្ហា: opcode មិនត្រឹមត្រូវ
+# ^NoOLE
+"អត់មាន OLE សំរាប់: "
+# ^OutputFolder
+"ថតសំរាប់ដាក់ទិន្នផល: "
+# ^RemoveFolder
+"លុបថតឯកសារ: "
+# ^RenameOnReboot
+"ប្តូរឈ្មោះនៅពេលកុំព្យូទ័រដំណើរការឡើងវិញ: "
+# ^Rename
+"ប្តូរឈ្មោះ: "
+# ^Skipped
+"ត្រូវបានរំលង: "
+# ^CopyDetails
+ចំលងពិពណ៌នាទៅ Clipboard
+# ^LogInstall
+កត់ត្រាដំណើរការដំឡើង
+# ^Byte
+B
+# ^Kilo
+K
+# ^Mega
+M
+# ^Giga
+G
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nsh
new file mode 100644
index 000000000..ec33eead1
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Khmer.nsh
@@ -0,0 +1,129 @@
+;Language: Khmer (1033)
+;By yi.sophally
+
+!insertmacro LANGFILE "Khmer" "ភាសាខ្មែរ"
+
+!ifdef MUI_WELCOMEPAGE
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE "សូមស្វាគមន៍ចំពោះការដំឡើងកម្មវិធី $(^NameDA)"
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "កម្មវិធីជំនួយនេះនឹងនាំអ្នកដល់ការដំឡើងកម្មវិធីនៃកម្មវិធី $(^NameDA).$\r$\n$\r$\nIt ដែលសូមអោយអ្នកបិទនូវកម្មវិធីទាំងឡាយផ្សេងទៀតមុនពេលចាប់ផ្តើមការដំឡើង។ ដើម្បីងាយស្រួលក្នុងការកែប្រែឯកសារនៃប្រព័ន្ធប្រតិបត្តការដោយមិនចាំបាច់ចាប់ផ្តើមដំណើរការម៉ាស៊ីនរបស់អ្នកសារជាថ្មី។ $\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_UNWELCOMEPAGE
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE "ស្វាគមន៍ចំពោះការលុបកម្មវិធី $(^NameDA) នេះ"
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "កម្មវិធីជំនួយនេះនឹងនាំអ្នកដល់ការលុបចេញនៃកម្មវិធី$(^NameDA).$\r$\n$\r$\n មុនពេលចាប់ផ្តើមលុបចេញ សូមអោយប្រាកដថាកម្មវិធី $(^NameDA) មិនមែនកំពុងដំណើរការ$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE
+ ${LangFileString} MUI_TEXT_LICENSE_TITLE "កិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណ"
+ ${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "សូមអានអាជ្ញាប័ណ្ណអោយបានត្រឹមត្រូវមុនពេលដំឡើងកម្មវិធី $(^NameDA)។"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាង សូមចុច ខ្ញុំយល់ព្រម ដើម្បីដំណើរការបន្ត។ ដើម្បីដំឡើងកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង។"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាងសូមចុចធិចប្រអប់ខាងក្រោម។ ដើម្បីដំឡើងកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង $_CLICK"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាងសូមជ្រើសរើសជំរើសទីមួយខាងក្រោម។ ដើម្បីដំឡើងកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង $_CLICK"
+!endif
+
+!ifdef MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_UNTEXT_LICENSE_TITLE "កិច្ចព្រមព្រាងអាជ្ញាប័ណ្ណ"
+ ${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE "សូមអានអាជ្ញាប័ណ្ណអោយបានត្រឹមត្រូវមុនពេលលុបកម្មវិធី $(^NameDA)ចេញ។"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាង សូមចុច I Agree ដើម្បីដំណើរការបន្ត។ ដើម្បីលុបកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាងសូមចុចធិចប្រអប់ខាងក្រោម។ ដើម្បីលុបកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "ប្រសិនបើអ្នកយល់ព្រមតាមកិច្ចព្រមព្រាងសូមជ្រើសរើសជំរើសទីមួយខាងក្រោម។ ដើម្បីលុបកម្មវិធី $(^NameDA) នេះអ្នកត្រូវតែយល់ព្រមតាមកិច្ចព្រមព្រាង $_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_INNERTEXT_LICENSE_TOP "សូមចុច Page Down ដើម្បីមើលកិច្ចព្រមព្រាងដែលនៅសល់"
+!endif
+
+!ifdef MUI_COMPONENTSPAGE
+ ${LangFileString} MUI_TEXT_COMPONENTS_TITLE "ជ្រើសរើសសមាសភាគ"
+ ${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "ជ្រើសរើសដំណើរការនៃកម្មវិធី $(^NameDA) ដែលអ្នកចង់ដំឡើង"
+!endif
+
+!ifdef MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "ជ្រើសរើសសមាសភាគ"
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "ជ្រើសរើសដំណើរការនៃកម្មវិធី $(^NameDA) ដែលអ្នកចង់លប់"
+!endif
+
+!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "ការពិពណ័នា"
+ !ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "ដាក់កណ្តុរបញ្ជារបស់អ្នកលើសមាសភាគណាមួយដើម្បីមើលការពិពណ៍នារបស់វា។"
+ !else
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "ដាក់កណ្តុរបញ្ជារបស់អ្នកលើសមាសភាគណាមួយដើម្បីមើលការពិពណ៍នារបស់វា។"
+ !endif
+!endif
+
+!ifdef MUI_DIRECTORYPAGE
+ ${LangFileString} MUI_TEXT_DIRECTORY_TITLE "ជ្រើសរើសកន្លែងដើម្បីដំឡើង"
+ ${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "ជ្រើសរើសថតដើម្បីដំឡើងកម្មវិធី $(^NameDA) ។"
+!endif
+
+!ifdef MUI_UNDIRECTORYPAGE
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE "ជ្រើសរើសកន្លែងដែលត្រូវលប់ចេញ"
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "ជ្រើសរើសថតដើម្បីលប់កម្មវិធី $(^NameDA) ចេញ។"
+!endif
+
+!ifdef MUI_INSTFILESPAGE
+ ${LangFileString} MUI_TEXT_INSTALLING_TITLE "កំពុងដំឡើង"
+ ${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "សូមមេត្តារង់ចាំខណះដែលកម្មវិធី $(^NameDA) កំពុងត្រូវបានដំឡើង។"
+ ${LangFileString} MUI_TEXT_FINISH_TITLE "ការដំឡើងរួចរាល់"
+ ${LangFileString} MUI_TEXT_FINISH_SUBTITLE "ការដំឡើងត្រូវបានបញ្ចប់ដោយជោគជ័យ"
+ ${LangFileString} MUI_TEXT_ABORT_TITLE "ការដំឡើងត្រូវបានបញ្ឈប់"
+ ${LangFileString} MUI_TEXT_ABORT_SUBTITLE "ការដំឡើងត្រូវបានបរាជ័យ។"
+!endif
+
+!ifdef MUI_UNINSTFILESPAGE
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "កំពុងដំណើរការលុប"
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_SUBTITLE "សូមមេត្តារង់ចាំខណះដែលកម្មវិធី $(^NameDA) កំពុងត្រូវបានលុប។"
+ ${LangFileString} MUI_UNTEXT_FINISH_TITLE "ការលុបចេញរួចរាល់"
+ ${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "ការលុបចេញត្រូវបានបរាជ័យ។"
+ ${LangFileString} MUI_UNTEXT_ABORT_TITLE "ការលុបចេញត្រូវបានបញ្ឈប់"
+ ${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "ការលុបចេញត្រូវបានបរាជ័យ"
+!endif
+
+!ifdef MUI_FINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "កម្មវិធីជំនួយក្នុងការដំឡើង $(^NameDA) កំពុងត្រូវបានបញ្ចប់"
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "កម្មវិធី $(^NameDA) បានត្រូវដំឡើងរួចរាល់នៅក្នុងកុំព្យូទ័ររបស់អ្នក។ $\r$\n$\r$\nចុច Finish ដើម្បីបិទកម្មវិធីជំនួយនេះ"
+ ${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT "កុំព្យូទ័ររបស់អ្នកត្រូវតែចាប់ដំណើរការសារជាថ្មីដើម្បីបំពេញការដំឡើងកម្មវិធី $(^NameDA) នេះ។ តើអ្នកចង់ចាប់ផ្តើមដំណើរការកុំព្យូទ័រអ្នកឡើងវិញពេលនេះ?"
+!endif
+
+!ifdef MUI_UNFINISHPAGE
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "កម្មវិធីជំនួយក្នុងការលុប $(^NameDA) កំពុងត្រូវបានបញ្ចប់"
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "កម្មវិធី $(^NameDA) បានត្រូវលុបរួចរាល់ពីក្នុងកុំព្យូទ័ររបស់អ្នក។ $\r$\n$\r$\nចុច Finish ដើម្បីបិទកម្មវិធីជំនួយនេះ"
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT "កុំព្យូទ័ររបស់អ្នកត្រូវតែចាប់ដំណើរការសារជាថ្មីដើម្បីបំពេញការដំឡើងកម្មវិធី $(^NameDA) នេះ។ តើអ្នកចង់ចាប់ផ្តើមដំណើរការកុំព្យូទ័រអ្នកឡើងវិញពេលនេះ?"
+!endif
+
+!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "ចាប់ផ្តើមដំណើរការកុំព្យូទ័រឡើងវិញពេលនេះ"
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "ចង់ដំណើរការកុំព្យូទ័រដោយខ្លួនឯងពេលក្រោយ"
+ ${LangFileString} MUI_TEXT_FINISH_RUN "&Run $(^NameDA)"
+ ${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&Show Readme"
+ ${LangFileString} MUI_BUTTONTEXT_FINISH "&Finish"
+!endif
+
+!ifdef MUI_STARTMENUPAGE
+ ${LangFileString} MUI_TEXT_STARTMENU_TITLE "ជ្រើសរើសថតម៉ឺនុយ Start "
+ ${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "ជ្រើសរើសថតម៉ឺនុយ Start ដើម្បីបង្កើតផ្លូវកាត់ទៅកម្មវិធី $(^NameDA) ។"
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "ជ្រើសរើសថតម៉ឺនុយ Start ដែលអ្នកចង់បង្កើតផ្លូវកាត់ទៅកម្មវិធីនេះ។ អ្នកក៏អាចបញ្ចូលឈ្មោះមួយដើម្បីបង្កើតថតថ្មីមួយទៀត។"
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "មិនបាច់បង្កើតផ្លូវកាត់"
+!endif
+
+!ifdef MUI_UNCONFIRMPAGE
+ ${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "លុបកម្មវិធី $(^NameDA) ចេញ"
+ ${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "លុបកម្មវិធី $(^NameDA) ចេញពីកុំព្យូទ័ររបស់អ្នក។"
+!endif
+
+!ifdef MUI_ABORTWARNING
+ ${LangFileString} MUI_TEXT_ABORTWARNING "តើអ្នកប្រាកដថានឹងចាកចេញពីការដំឡើងកម្មវិធី $(^Name) នេះមែនទេ?"
+!endif
+
+!ifdef MUI_UNABORTWARNING
+ ${LangFileString} MUI_UNTEXT_ABORTWARNING "តើអ្នកប្រាកដថានឹងចាកចេញពីការលុបកម្មវិធី $(^Name) នេះមែនទេ?"
+!endif
+
+!ifdef MULTIUSER_INSTALLMODEPAGE
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "ជ្រើសរើសអ្នកប្រើប្រាស់"
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE "ជ្រើសរើសអ្នកប្រើប្រាស់ទាំងឡាយណាដែលអ្នកចង់អោយប្រើកម្មវិធី $(^NameDA) នេះ។"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP "សូមជ្រើសរើសថាតើអ្នកចង់ដំឡើងកម្មវិធី $(^NameDA) សំរាប់តែខ្លួនអ្នក រឺ សំរាប់អ្នករាល់គ្នាដែលប្រើកុំព្យូទ័រនេះ។ $(^ClickNext)"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "ដំឡើងសំរាប់អ្នកទាំងឡាយដែលប្រើកុំព្យូទ័រនេះ"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "ដំឡើងសំរាប់តែខ្ញុំម្នាក់"
+!endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nlf
new file mode 100644
index 000000000..6160fd837
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nsh
new file mode 100644
index 000000000..615227f7b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Korean.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nlf
new file mode 100644
index 000000000..5f244548d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nsh
new file mode 100644
index 000000000..c5d33d2be
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Kurdish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nlf
new file mode 100644
index 000000000..03a5baeff
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nsh
new file mode 100644
index 000000000..273331eae
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Latvian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nlf
new file mode 100644
index 000000000..bc3dd775f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nsh
new file mode 100644
index 000000000..78880deac
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Lithuanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nlf
new file mode 100644
index 000000000..20c879bc3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nsh
new file mode 100644
index 000000000..c18a407ed
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Luxembourgish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nlf
new file mode 100644
index 000000000..69bd7d890
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nsh
new file mode 100644
index 000000000..f1d4fae8d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Macedonian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nlf
new file mode 100644
index 000000000..dd73961a1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nsh
new file mode 100644
index 000000000..d84573eda
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malagasy.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nlf
new file mode 100644
index 000000000..8072d5454
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nsh
new file mode 100644
index 000000000..feaea4134
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Malay.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nlf
new file mode 100644
index 000000000..c9f7fe38f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nsh
new file mode 100644
index 000000000..b9a6d4938
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Mongolian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nlf
new file mode 100644
index 000000000..eef204b46
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nsh
new file mode 100644
index 000000000..4ae470a68
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Norwegian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nlf
new file mode 100644
index 000000000..4536a8c8a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nsh
new file mode 100644
index 000000000..dd6f8fb6c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/NorwegianNynorsk.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nlf
new file mode 100644
index 000000000..884e2b7d6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nsh
new file mode 100644
index 000000000..4cabf6b90
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Pashto.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nlf
new file mode 100644
index 000000000..491629bc6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nsh
new file mode 100644
index 000000000..d92e470e5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Polish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nlf
new file mode 100644
index 000000000..082fb1b4e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nsh
new file mode 100644
index 000000000..2974313fa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Portuguese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nlf
new file mode 100644
index 000000000..505844b70
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nsh
new file mode 100644
index 000000000..01d6183f9
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/PortugueseBR.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nlf
new file mode 100644
index 000000000..b69ebe91f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nsh
new file mode 100644
index 000000000..9898022f1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Romanian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nlf
new file mode 100644
index 000000000..253fa5995
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nsh
new file mode 100644
index 000000000..df536bb51
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Russian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nlf
new file mode 100644
index 000000000..32404fd08
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nsh
new file mode 100644
index 000000000..aa3d93edb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Serbian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nlf
new file mode 100644
index 000000000..5ef26d210
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nsh
new file mode 100644
index 000000000..66b443176
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SerbianLatin.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nlf
new file mode 100644
index 000000000..ad66c887b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nsh
new file mode 100644
index 000000000..59a5e295d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sesotho.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nlf
new file mode 100644
index 000000000..344bb35fd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nsh
new file mode 100644
index 000000000..68d1dcc00
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SimpChinese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nlf
new file mode 100644
index 000000000..8020787ae
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nsh
new file mode 100644
index 000000000..eac523832
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovak.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nlf
new file mode 100644
index 000000000..ba985650c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nsh
new file mode 100644
index 000000000..52db6a368
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Slovenian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nlf
new file mode 100644
index 000000000..f78148893
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nsh
new file mode 100644
index 000000000..15281a0d3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Spanish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nlf
new file mode 100644
index 000000000..6134f11fd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nsh
new file mode 100644
index 000000000..4a4b59010
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/SpanishInternational.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nlf
new file mode 100644
index 000000000..143ba7a9d
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nlf
@@ -0,0 +1,191 @@
+# Header, Ulah diropa
+NLF v6
+# mimitian ti dieu
+# ID Sundanese
+33
+# Font and size - dash (-) means default
+-
+-
+# Codepage - dash (-) means ANSI code page
+-
+# RTL - anything else than RTL means LTR
+-
+# Translation sukma gemala [http://facebook.com/sukma.gemala]
+# ^Branding
+Sistem Pamasang Nullsoft %s
+# ^SetupCaption
+Masangkeun $(^Name)
+# ^UninstallCaption
+Miceun $(^Name)
+# ^LicenseSubCaption
+: Aturan jeung Kasapukan
+# ^ComponentsSubCaption
+: Pilihan Instalasi
+# ^DirSubCaption
+: Map Instalasi
+# ^InstallingSubCaption
+: Masangkeun
+# ^CompletedSubCaption
+: Rngs
+# ^UnComponentsSubCaption
+: Pilihan Miceun
+# ^UnDirSubCaption
+: Map Miceun
+# ^ConfirmSubCaption
+: Muguhkeun
+# ^UninstallingSubCaption
+: Miceun instalasi
+# ^UnCompletedSubCaption
+: Rngs
+# ^BackBtn
+< Sam&mhna
+# ^NextBtn
+Tulu&ykeun >
+# ^AgreeBtn
+&Sapuk
+# ^AcceptBtn
+S&apuk
+# ^DontAcceptBtn
+Te&u sapuk
+# ^InstallBtn
+&Pasang
+# ^UninstallBtn
+Pi&ceun
+# ^CancelBtn
+&Bolay
+# ^CloseBtn
+&Tutup
+# ^BrowseBtn
+Pili&h...
+# ^ShowDetailsBtn
+&Detil
+# ^ClickNext
+Klik Tuluykeun pikeun nuluykeun.
+# ^ClickInstall
+Klik Pasang pikeun ngamimitian masang $(^Name).
+# ^ClickUninstall
+Klik Piceun pikeun ngamimitian miceun $(^Name).
+# ^Name
+Ngaran
+# ^Completed
+Rngs
+# ^LicenseText
+Imeutan ieu kasapukan sammh masangkeun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, klik Sapuk.
+# ^LicenseTextCB
+Imeutan ieu kasapukan sammh masangkeun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, br contrng. $_CLICK
+# ^LicenseTextRB
+Imeutan ieu kasapukan sammh masangkeun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, pilih salah sahiji anu aya di handap. $_CLICK
+# ^UnLicenseText
+Imeutan ieu kasapukan sammh miceun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, klik Sapuk.
+# ^UnLicenseTextCB
+Imeutan ieu kasapukan sammh miceun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, br contrng. $_CLICK
+# ^UnLicenseTextRB
+Imeutan ieu kasapukan sammh miceun $(^NameDA). Lamun anjeun narima sakabh anu dipedar dina kasapukan, pilih salah sahiji anu aya di handap. $_CLICK
+# ^Custom
+Reka
+# ^ComponentsText
+Contrng dina komponn anu rk dipasang atawa piceun contrngna lamun teu pati perlu. $_CLICK
+# ^ComponentsSubText1
+Pilih tipeu instalasi:
+# ^ComponentsSubText2_NoInstTypes
+Pilih komponn-komponn anu bakal dipasang:
+# ^ComponentsSubText2
+Atawa, pilih ieu komponn anu bakal dipasang:
+# ^UnComponentsText
+Contrng dina komponn anu rk dipiceun. $_CLICK
+# ^UnComponentsSubText1
+Pilih tipeu miceun:
+# ^UnComponentsSubText2_NoInstTypes
+Pilih komponn-komponn anu rk dipiceun:
+# ^UnComponentsSubText2
+Atawa, pilih ieu komponn anu rk dipiceun:
+# ^DirText
+$(^NameDA) bakal dipasang dina ieu map. Pikeun milih map sjn, klik Pilih tuluy tangtukeun map nu dipikahayang ku ajeun. $_CLICK
+# ^DirSubText
+Map anu dituju
+# ^DirBrowseText
+Pilih map pikeun tempat masangkeun $(^NameDA):
+# ^UnDirText
+$(^NameDA) bakal dipiceun tina ieu map. Pikeun milih map sjn, klik Pilih tuluy tangtukeun map nu dipikahayang ku ajeun. $_CLICK
+# ^UnDirSubText
+""
+# ^UnDirBrowseText
+Pilih map pikeun tempat miceun $(^NameDA):
+# ^SpaceAvailable
+"Rohang disk anu nyampak: "
+# ^SpaceRequired
+"Rohang disk anu dibutuhkeun: "
+# ^UninstallingText
+$(^NameDA) bakal dipiceun tina ieu map. $_CLICK
+# ^UninstallingSubText
+Miceun instalasi:
+# ^FileError
+Henteu bisa nulis koropak: \r\n\t"$0"\r\nKlik abort pikeun ngabolaykeun instalasi,\r\nretry pikeun nyoba deui, atawa\r\nignore lamun moal dipalir.
+# ^FileError_NoIgnore
+Henteu bisa nulis koropak: \r\n\t"$0"\r\nKlik retry pikeun nyobaan deui, atawa\r\ncancel pikeun ngabolaykeun instalasi
+# ^CantWrite
+"Henteu bisa nulis dina: "
+# ^CopyFailed
+Pross niron gagal
+# ^CopyTo
+"Ditiron kana "
+# ^Registering
+"Ngadaftarkeun modul: "
+# ^Unregistering
+"Ngudar modul: "
+# ^SymbolNotFound
+"Henteu manggih : "
+# ^CouldNotLoad
+"Henteu bisa muka: "
+# ^CreateFolder
+"Nyieun map: "
+# ^CreateShortcut
+"Nyieun tumbu: "
+# ^CreatedUninstaller
+"Nyieun aplikasi pamiceun instalasi: "
+# ^Delete
+"Mupus koropak: "
+# ^DeleteOnReboot
+"Bakal dipupus nalika komputer dimimitian-deui: "
+# ^ErrorCreatingShortcut
+"Henteu bisa nyieun tumbu: "
+# ^ErrorCreating
+"Kasalahan dina nyieun: "
+# ^ErrorDecompressing
+Kasalahan nalika muka gmbolan data! Aplikasi Pamasang ruksak
+# ^ErrorRegistering
+Kasalahan nalika ngadaftarkeun modul DLL
+# ^ExecShell
+"ExecShell: "
+# ^Exec
+"Ngajalankeun: "
+# ^Extract
+"Muka gmbolan: "
+# ^ErrorWriting
+"Gmbolan: kasalahan nalika nulis koropak "
+# ^InvalidOpcode
+Program Pamasang: opcode henteu lengkep
+# ^NoOLE
+"OLE henteu kapanggih: "
+# ^OutputFolder
+"Map anu dituju: "
+# ^RemoveFolder
+"Mupus map: "
+# ^RenameOnReboot
+"Bakal diganti ngaranna nalika dimimitian-deui (restart): "
+# ^Rename
+"Ngaganti ngaran: "
+# ^Skipped
+Diliwat: "
+# ^CopyDetails
+Tiron Detil kana Clipboard
+# ^LogInstall
+Catet pross instalasi
+# ^Byte
+B
+# ^Kilo
+K
+# ^Mega
+M
+# ^Giga
+G
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nsh
new file mode 100644
index 000000000..2397ec9ad
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Sundanese.nsh
@@ -0,0 +1,129 @@
+;Language: Sundanese (33)
+;By sukma gemala - http://facebook.com/sukma.gemala
+
+!insertmacro LANGFILE "Sundanese" "Basa Sunda"
+
+!ifdef MUI_WELCOMEPAGE
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE "Baga, ieu th Apingan Masang $(^NameDA)"
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Apingan Masang bakal ngaping anjeun dina pross masangkeun $(^NameDA).$\r$\n$\r$\nAlusna mah tutupkeun heula program sjn anu ayeuna keur dijalankeun sammh nuluykeun masang ieu program. Eta hal aya patalina jeung kaperluan ngarobah file anu keur dipak ku sistem tanpa kudu ngamimitian-deui (restart) komputer anjeun.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_UNWELCOMEPAGE
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE "Baga, ieu th Apingan Miceun $(^NameDA)"
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Apingan Miceun bakal ngaping anjeun dina pross miceun $(^NameDA).$\r$\n$\r$\nSamemeh ngamimitian miceun instalasina, anjeun kudu yakin heula yn $(^NameDA) henteu eukeur dijalankeun.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE
+ ${LangFileString} MUI_TEXT_LICENSE_TITLE "Aturan jeung Kasapukan"
+ ${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "Imeutan ieu aturan jeung kasapukan sammh masangkeun $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "Lamun anjeun narima sakabh anu dipedar, klik Sapuk pikeun nuluykeun. Anjeun kudu satuju sangkan bisa masangkeun $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "Lamun anjeun narima sakabh anu dipedar dina kasapukan, br contrng. Anjeun kudu satuju sangkan bisa masangkeun $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "Lamun anjeun narima sakabh anu dipedar dina kasapukan, pilih salah sahiji anu aya dihandap. Anjeun kudu satuju sangkan bisa masangkeun $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_UNTEXT_LICENSE_TITLE "Aturan jeung Kasapukan"
+ ${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE "Imeutan ieu aturan jeung kasapukan sammh miceun $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "Lamun anjeun narima sakabh anu dipedar, klik Sapuk pikeun nuluykeun. Anjeun kudu satuju sangkan bisa miceun $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "Lamun anjeun narima sakabh anu dipedar dina kasapukan, br contrng. Anjeun kudu satuju sangkan bisa miceun $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "Lamun anjeun narima sakabh anu dipedar dina kasapukan, pilih salah sahiji anu aya dihandap. Anjeun kudu satuju sangkan bisa miceun $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_INNERTEXT_LICENSE_TOP "Penct Page Down pikeun ningali tuluyanana."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE
+ ${LangFileString} MUI_TEXT_COMPONENTS_TITLE "Milih Komponn"
+ ${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "Pilih fitur ti $(^NameDA) anu rk dipasang."
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "Wangenan"
+!endif
+
+!ifdef MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "Milih Komponn"
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "Pilih fitur ti $(^NameDA) anu rk dipiceun."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
+ !ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Tunjuk salah sahiji pikeun ningali kateranganana."
+ !else
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Tunjuk salah sahiji pikeun ningali kateranganana."
+ !endif
+!endif
+
+!ifdef MUI_DIRECTORYPAGE
+ ${LangFileString} MUI_TEXT_DIRECTORY_TITLE "Milih Lokasi Masang"
+ ${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "Pilih map pikeun tempat masangkeun $(^NameDA)."
+!endif
+
+!ifdef MUI_UNDIRECTORYSPAGE
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE "Milih Lokasi Miceun"
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "Pilih map pikeun tempat miceun $(^NameDA)."
+!endif
+
+!ifdef MUI_INSTFILESPAGE
+ ${LangFileString} MUI_TEXT_INSTALLING_TITLE "Masang"
+ ${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "Tungguan, $(^NameDA) eukeur dipasangkeun."
+ ${LangFileString} MUI_TEXT_FINISH_TITLE "Pross Masangkeun Rngs"
+ ${LangFileString} MUI_TEXT_FINISH_SUBTITLE "$(^NameDA) rngs dipasangkeun."
+ ${LangFileString} MUI_TEXT_ABORT_TITLE "Pross Masang Dibolaykeun"
+ ${LangFileString} MUI_TEXT_ABORT_SUBTITLE "Masangkeun rngs tapi can sampurna."
+!endif
+
+!ifdef MUI_UNINSTFILESPAGE
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "Miceun"
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_SUBTITLE "Tungguan, $(^NameDA) eukeur dipiceun."
+ ${LangFileString} MUI_UNTEXT_FINISH_TITLE "Pross Miceun Rngs"
+ ${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "$(^NameDA) rngs dipiceun."
+ ${LangFileString} MUI_UNTEXT_ABORT_TITLE "Pross Miceun Dibolaykeun"
+ ${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "Miceun rngs tapi can sampurna."
+!endif
+
+!ifdef MUI_FINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "Ngarngskeun Apingan Masang $(^NameDA)"
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "$(^NameDA) geus dipasangkeun kana komputer anjeun.$\r$\n$\r$\nKlik Rngs pikeun nutup Apingan Masang."
+ ${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT "Komputer anjeun kudu dimimitian-deui (restart) pikeun ngarngskeun pross instalasi $(^NameDA). Mmimitian-deui ayeuna?"
+!endif
+
+!ifdef MUI_UNFINISHPAGE
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "Ngarngskeun Apingan Miceun $(^NameDA)"
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "$(^NameDA) geus dipiceun tina komputer anjeun.$\r$\n$\r$\nKlik Rngs pikeun nutup Apingan Miceun."
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT "Komputer anjeun kudu dimimitian-deui (restart) pikeun ngarngskeun pross uninstall $(^NameDA). Mmimitian-deui ayeuna?"
+!endif
+
+!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "Mimitian-deui"
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "Moal waka"
+ ${LangFileString} MUI_TEXT_FINISH_RUN "&Jalankeun $(^NameDA)"
+ ${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&Buka Koropak Bacaheula"
+ ${LangFileString} MUI_BUTTONTEXT_FINISH "&Rngs"
+!endif
+
+!ifdef MUI_STARTMENUPAGE
+ ${LangFileString} MUI_TEXT_STARTMENU_TITLE "Milih Menu Mimiti"
+ ${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "Pilih map Menu Mimiti (Start Menu) pikeun nempatkeun tumbu $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "Pilih map Menu Mimiti (Start Menu) pikeun nempatkeun tumbu ieu program. Og bisa nyieun ngaran map anyar."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "Ulah nyieun tumbu"
+!endif
+
+!ifdef MUI_UNCONFIRMPAGE
+ ${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "Miceun $(^NameDA)"
+ ${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "Miceun $(^NameDA) tina komputer anjeun."
+!endif
+
+!ifdef MUI_ABORTWARNING
+ ${LangFileString} MUI_TEXT_ABORTWARNING "Bener, rk kaluar tina pross masangkeun $(^Name)?"
+!endif
+
+!ifdef MUI_UNABORTWARNING
+ ${LangFileString} MUI_UNTEXT_ABORTWARNING "Bener, rk kaluar tina pross miceun $(^Name)?"
+!endif
+
+!ifdef MULTIUSER_INSTALLMODEPAGE
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "Milih Pamak"
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE "Milih pamak anu rk dipasangkeun $(^NameDA)."
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP "Pilih tujuan masangkeun $(^NameDA) keur soranganeun atawa keur kabh pamak komputer ieu. $(^ClickNext)"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "Pasangkeun keur kabh pamak komputer ieu"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "Kuring wungkul"
+!endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nlf
new file mode 100644
index 000000000..4a498ed90
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nsh
new file mode 100644
index 000000000..0bb6cbceb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swahili.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nlf
new file mode 100644
index 000000000..20e1b4ee0
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nsh
new file mode 100644
index 000000000..f1525fc8d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Swedish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nlf
new file mode 100644
index 000000000..d1dce0540
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nsh
new file mode 100644
index 000000000..b47ad88e7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Tamil.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nlf
new file mode 100644
index 000000000..34ec33370
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nsh
new file mode 100644
index 000000000..29e74dce9
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Thai.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nlf
new file mode 100644
index 000000000..90700348b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nsh
new file mode 100644
index 000000000..b46dd6fd5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/TradChinese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nlf
new file mode 100644
index 000000000..bd1968b4b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nsh
new file mode 100644
index 000000000..2f5586df2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Turkish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nlf
new file mode 100644
index 000000000..5d2a6bc2c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nsh
new file mode 100644
index 000000000..8aeea8f4e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Twi.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nlf
new file mode 100644
index 000000000..e556221fd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nsh
new file mode 100644
index 000000000..7111d5193
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Ukrainian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nlf
new file mode 100644
index 000000000..6d0aed542
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nlf
@@ -0,0 +1,191 @@
+# Header, don't edit
+NLF v6
+# Start editing here
+# Language ID
+1152
+# Font and size - dash (-) means default فونت نامى ۋە چوڭلىقى
+Arial
+9
+# Codepage - dash (-) means ANSI code page كودبېتى
+65001
+# RTL - anything else than RTL means LTR ئوڭدىن سولغا يېزىش
+RTL
+# Translation by Yasinjan Ghupur (yasenghupur@sina.com) 26 April 2012
+# ^Branding
+Nullsoft Install System %s
+# ^SetupCaption
+$(^Name) قاچىلاش
+# ^UninstallCaption
+$(^Name) ئۆچۈرۈش
+# ^LicenseSubCaption
+: ئىجازەت كېلىشىمى
+# ^ComponentsSubCaption
+: قاچىلاش تاللاشلىرى
+# ^DirSubCaption
+: قاچىلايدىغان قىسقۇچ
+# ^InstallingSubCaption
+: قاچىلاۋاتىدۇ
+# ^CompletedSubCaption
+: تاماملاندى
+# ^UnComponentsSubCaption
+: ئۆچۈرۈش تاللاشلىرى
+# ^UnDirSubCaption
+: ئۆچۈرۈدىغان قىسقۇچ
+# ^ConfirmSubCaption
+: جەزىملەش
+# ^UninstallingSubCaption
+: ئۆچۈرۈۋاتىدۇ
+# ^UnCompletedSubCaption
+: تاماملاندى
+# ^BackBtn
+< &كەينىگە
+# ^NextBtn
+&ئالدىغا >
+# ^AgreeBtn
+قوشۇلىمەن
+# ^AcceptBtn
+ ئىجازەت كېلىشىمىدىكى تۈرلەرگە قوشۇلىمەن
+# ^DontAcceptBtn
+ ئىجازەت كېلىشىمىدىكى تۈرلەرگە قوشۇلمايمەن
+# ^InstallBtn
+&قاچىلاش
+# ^UninstallBtn
+& ئۆچۈرۈش
+# ^CancelBtn
+قالدۇرۇش
+# ^CloseBtn
+&يېپىش
+# ^BrowseBtn
+كۆرۈش...
+# ^ShowDetailsBtn
+تەپسىلاتىنى كۆرۈش
+# ^ClickNext
+ئالدىغا نى چېكىپ داۋاملاشتۇرۇڭ.
+# ^ClickInstall
+قاچىلاش نى چېكىپ قاچىلاشنى باشلاڭ.
+# ^ClickUninstall
+ئۆچۈرۈش نى چېكىپ ئۆچۈرۈشنى باشلاڭ.
+# ^Name
+نامى
+# ^Completed
+تاماملاندى
+# ^LicenseText
+$(^NameDA) نى قاچىلاشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ چىقىڭ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،قوشۇلىمەن نى بېسىڭ .
+# ^LicenseTextCB
+$(^NameDA) نى قاچىلاشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ چىقىڭ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،تاللاش كاتەكچىسى نى چېكىڭ . $_CLICK
+# ^LicenseTextRB
+$(^NameDA) نى قاچىلاشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ چىقىڭ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،بىرىنجى تاللاش نى تاللاڭ . $_CLICK
+# ^UnLicenseText
+$(^NameDA) نى ئۆچۈرۈشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،قوشۇلىمەن نى بېسىڭ .
+# ^UnLicenseTextCB
+$(^NameDA) نى ئۆچۈرۈشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ چىقىڭ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،تاللاش كاتەكچىسى نى چېكىڭ . $_CLICK
+# ^UnLicenseTextRB
+$(^NameDA) نى ئۆچۈرۈشتىن بۇرۇن ئىجازەت كېلىشىمىنى كۆرۈپ چىقىڭ. كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،بىرىنجى تاللاش نى تاللاڭ . $_CLICK
+# ^Custom
+ئۆزى بېكىتىش
+# ^ComponentsText
+قاچىلايدىغان بۆلەكلەرنى تاللاڭ ۋە قاچىلىمايدىغان بۆلەكلەرنى تاللىماڭ. $_CLICK
+# ^ComponentsSubText1
+قاچىلاش ئۇسلۇبىنى تاللاڭ:
+# ^ComponentsSubText2_NoInstTypes
+قاچىلاش بۆلىكىنى تاللاڭ:
+# ^ComponentsSubText2
+ياكى قاچىلىماقچى بولغان بۆلەكنى تاللاڭ:
+# ^UnComponentsText
+ئۆچۈرمەكچى بولغان بۆلەكنى تاللاڭ ھەمدە ئۆچۈرمەيدىغان بۆلەكنى تاللىماڭ. $_CLICK
+# ^UnComponentsSubText1
+ئۆچۈرۈش ئۇسلۇبىنى تاللاڭ:
+# ^UnComponentsSubText2_NoInstTypes
+ئۆچۈرۈش بۆلىكىنى تاللاڭ:
+# ^UnComponentsSubText2
+ياكى ئۆچۈرمەكچى بولغان بۆلەكنى تاللاڭ:
+# ^DirText
+ قاچىلاش يېتەكچىسى $(^NameDA) نى بۇ قىسقۇچنىڭ ئاستىغا قاچىلايدۇ.باشقا قىسقۇچقا قاچىلماقچى بولسىڭىز،كۆرۈش نى چېكىپ باشقا قىسقۇچنى تاللاڭ . $_CLICK
+# ^DirSubText
+نىشان قىسقۇچ
+# ^DirBrowseText
+نى قاچىلايدىغان قىسقۇچنى تاللاڭ $(^NameDA):
+# ^UnDirText
+قاچىلاش يېتەكچىسى $(^NameDA) نى بۇ قىسقۇچنىڭ ئاستىدىن ئۆچۈرۈدۇ.باشقا قىسقۇچتىن ئۆچۈرمەكچى بولسىڭىز،كۆرۈش نى چېكىپ باشقا قىسقۇچنى تاللاڭ . $_CLICK
+# ^UnDirSubText
+""
+# ^UnDirBrowseText
+ $(^NameDA) نى ئۆچۈرۈدىغان قىسقۇچنى تاللاڭ :
+# ^SpaceAvailable
+"قاچىلاش بوشلۇقى يېتەرلىك: "
+# ^SpaceRequired
+" ئېھتىياجلىق قاچىلاش بوشلۇقى : "
+# ^UninstallingText
+$(^NameDA) نى تۆۋەندىكى قىسقۇچتىن ئۆچۈرۈدۇ. $_CLICK
+# ^UninstallingSubText
+دىن ئۆچۈرۈۋاتىدۇ:
+# ^FileError
+يازىدىغان ھۆججەتنى ئېچىش خاتالىقى: \r\n\r\n$0\r\n\r\nتوختىتۇش نى بېسىپ قاچىلاشنى توختۇتۇش,\r\nقايتىلاش ياكى \r\nبۇ ھۆججەتتىن ئاتلاپ ئۆتۈپ كېتىش.
+# ^FileError_NoIgnore
+يازىدىغان ھۆججەتنى ئېچىش خاتالىقى: \r\n\r\n$0\r\n\r\nقايتىلاش نى بېسىپ قاچىلاشنى قايتىلاش ياكى \r\n قاچىلاشنى قالدۇرۇش .
+# ^CantWrite
+"يازالمىدى: "
+# ^CopyFailed
+كۆچۈرەلمىدى
+# ^CopyTo
+"گە كۆچۈرۈش "
+# ^Registering
+"رۇيخەتكە ئېلىۋاتىدۇ: "
+# ^Unregistering
+"رۇيخەتتىن ئۆچۈرۈۋاتىدۇ: "
+# ^SymbolNotFound
+"بەلگىنى تاپالمىدى: "
+# ^CouldNotLoad
+"يۈكلىيەلمىدى: "
+# ^CreateFolder
+"قىسقۇچ قۇرۇش: "
+# ^CreateShortcut
+"تېزكۆرگۈچ قۇرۇش: "
+# ^CreatedUninstaller
+" ئۆچۈرۈش يېتەكچىسى ياسالدى: "
+# ^Delete
+"ھۆججەت ئۆچۈرۈش: "
+# ^DeleteOnReboot
+"قايتا قوزغالغاندا ئۆچۈرۈش: "
+# ^ErrorCreatingShortcut
+"تېزكۆرگۈچ قۇرۇش خاتالىقى: "
+# ^ErrorCreating
+"قۇرۇش خاتالىقى: "
+# ^ErrorDecompressing
+مەلۇماتلارنى ئەسلىگە قايتۇرۇش خاتالىقى! قاچىلاش يېتەكچىسى بۇزۇلغانمۇ؟
+# ^ErrorRegistering
+DLL نى رۇيخەتكە ئېلىش خاتالىقى
+# ^ExecShell
+"قاپلىنىش بۇيرۇقى ئىجرا قىلىش : "
+# ^Exec
+"ئىجرا قىلىش: "
+# ^Extract
+"يېيىش: "
+# ^ErrorWriting
+"يېيىش : ھۆججەتكە يېزىش خاتالىقى "
+# ^InvalidOpcode
+قاچىلاش يېتەكچىسى بۇزۇلغان : ئىناۋەتسىز كود
+# ^NoOLE
+"گە OLE يوق : "
+# ^OutputFolder
+"چىقىرىدىغان قىسقۇچ: "
+# ^RemoveFolder
+"قىسقۇچنى ئۆچۈرۈش: "
+# ^RenameOnReboot
+" قايتا قوزغالغاندا نامىنى ئۆزگەرتىش: "
+# ^Rename
+"نامىنى ئۆزگەرتىش: "
+# ^Skipped
+"ئاتلاپ ئۆتتى: "
+# ^CopyDetails
+تەپسىلاتىنى ئىشتاختىغا كۆچۈرۈش
+# ^LogInstall
+قاچىلاش جەريانى خاتىرسى
+# ^Byte
+بايىت
+# ^Kilo
+ كىلو
+# ^Mega
+ مېگا
+# ^Giga
+ گىگا
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nsh
new file mode 100644
index 000000000..76bf6a615
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uyghur.nsh
@@ -0,0 +1,129 @@
+;Language: Uyghur (1152)
+;Uyghur(China), Translated By Yasinjan Ghupur (yasenghupur@sina.com)
+
+!insertmacro LANGFILE "Uyghur" "Uyghur"
+
+!ifdef MUI_WELCOMEPAGE
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE " $(^NameDA) نى قاچىلاش يېتەكچىسىنى ئىشلىتىشىڭىزنى قارشى ئالىدۇ"
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "قاچىلاش يېتەكچىسى $(^NameDA)نى قاچىلاش جەريانىغا يېتەكچىلىك قىلىدۇ .$\r$\n$\r$\nقاچىلاشتىن بۇرۇن بارلىق پروگراممىلارنى يېپىۋېتىشنى تەۋسىيە قىلىدۇ،بۇنىڭ بىلەن قاچىلاپ بولغاندىن كېيىن كومپيۇتېرىڭىزنى قايتا قوزغاتمىسىڭىزمۇ بولىدۇ.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_UNWELCOMEPAGE
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE " $(^NameDA) نى ئۆچۈرۈش يېتەكچىسىنى ئىشلىتىشىڭىزنى قارشى ئالىدۇ"
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "ئۆچۈرۈش يېتەكچىسى$(^NameDA)نى ئۆچۈرۈش جەريانىغا يېتەكچىلىك قىلىدۇ .$\r$\n$\r$\n ئۆچۈرۈشتىن بۇرۇن $(^NameDA)نىڭ قوزغىتىلمىغانلىقىنى جەزىملەشتۈرۈڭ.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE
+ ${LangFileString} MUI_TEXT_LICENSE_TITLE "ئىجازەت كېلىشىمى"
+ ${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "$(^NameDA)نى قاچىلىشتىن بۇرۇن ئىجازەت تۈرلىرىنى كۆرۈپ چىقىڭ ."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "$(^NameDA)نى قاچىلىش ئۈچۈن،كېلىشىم تۈرلىرىگە قوشۇلىشىڭىز كېرەك. قوشۇلسىڭىز،قوشۇلىمەن نى بېسىپ داۋاملاشتۇرۇڭ ."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "$(^NameDA)نى قاچىلاش ئۈچۈن كېلىشىمگە قوشۇلىشىڭىز كېرەك كېلىشىم تۈرلىرىگە قوشۇلسىڭىز،تاللاش كاتىكىنى بېسىڭ. $_CLICK"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "$(^NameDA)نى قاچىلىش ئۈچۈن،كېلىشىم تۈرلىرىگە قوشۇلىشىڭىز كېرەك. قوشۇلسىڭىز،بىرىنجى تاللاشنى تاللاڭ. $_CLICK"
+!endif
+
+!ifdef MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_UNTEXT_LICENSE_TITLE "ئىجازەت كېلىشىمى"
+ ${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE " $(^NameDA)نى ئۆچۈرۈشتىن بۇرۇن ئىجازەت كېلىشىم تۈرلىرىنى كۆرۈپ چىقىڭ ."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "$(^NameDA)نى ئۆچۈرۈش ئۈچۈن، كېلىشىمگە قوشۇلىشىڭىز كېرەك .كېلىشىم تۈرلىرىگە قوشۇلسىڭىز, قوشۇلىمەن نى بېسىپ داۋاملاشتۇرۇڭ ."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "$(^NameDA) نى ئۆچۈرۈش ئۈچۈن كېلىشىم تۈرلىرىگە قوشۇلىشىڭىز كېرەك .قوشۇلسىڭىز, تاللاش كاتەكچىسىنى چېكىڭ. $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "$(^NameDA)نى ئۆچۈرۈش ئۈچۈن كېلىشىم تۈرلىرىگە قوشۇلىشىڭىز كېرەك. قوشۇلسىڭىز،بىرىنجى تاللاشنى تاللاڭ . $_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_INNERTEXT_LICENSE_TOP "كېلىشىمنىڭ قالغان قىسمىنى كۆرۈش ئۈچۈن Page Down نى بېسىڭ ."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE
+ ${LangFileString} MUI_TEXT_COMPONENTS_TITLE "بۆلەك تاللاش"
+ ${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "$(^NameDA) نى قاچىلاش ئۈچۈن ،ئېھتىياجىلىق ئىقتىدارلارنى تاللاڭ"
+!endif
+
+!ifdef MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "بۆلەك تاللاش"
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "$(^NameDA) نى ئۆچۈرۈش ئۈچۈن ،ئېھتىياجىلىق ئىقتىدارلارنى تاللاڭ."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "چۈشەندۈرۈش"
+ !ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "بۆلەكنىڭ چۈشەندۈرۈشىنى كۆرۈش ئۈچۈن،مائوسنى بۆلەكنىڭ ئۈستىگە ئاپىرىڭ."
+ !else
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "بۆلەكنىڭ چۈشەندۈرۈشىنى كۆرۈش ئۈچۈن،مائوسنى بۆلەكنىڭ ئۈستىگە ئاپىرىڭ."
+ !endif
+!endif
+
+!ifdef MUI_DIRECTORYPAGE
+ ${LangFileString} MUI_TEXT_DIRECTORY_TITLE "قاچىلايدىغان ئورۇننى تاللاڭ"
+ ${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "$(^NameDA)نى قاچىلاش ئۈچۈن قاچىلايدىغان قىسقۇچنى تاللاڭ."
+!endif
+
+!ifdef MUI_UNDIRECTORYPAGE
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE " ئۆچۈرۈدىغان ئورۇننى تاللاڭ"
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "$(^NameDA)نى ئۆچۈرۈش ئۈچۈن ئۆچۈرۈدىغان قىسقۇچنى تاللاڭ."
+!endif
+
+!ifdef MUI_INSTFILESPAGE
+ ${LangFileString} MUI_TEXT_INSTALLING_TITLE "قاچىلاۋاتىدۇ"
+ ${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "$(^NameDA)نى قاچىلاۋاتىدۇ...تەخىر قىلىڭ ."
+ ${LangFileString} MUI_TEXT_FINISH_TITLE "قاچىلاش تاماملاندى"
+ ${LangFileString} MUI_TEXT_FINISH_SUBTITLE "مۇۋەپپىقىيەتلىك قاچىلاندى."
+ ${LangFileString} MUI_TEXT_ABORT_TITLE "قاچىليالمىدى"
+ ${LangFileString} MUI_TEXT_ABORT_SUBTITLE "قاچىلاش مەغلۇپ بولدى."
+!endif
+
+!ifdef MUI_UNINSTFILESPAGE
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "ئۆچۈرۈش"
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_SUBTITLE " $(^NameDA)نى ئۆچۈرۈۋاتىدۇ... تەخىر قىلىڭ ."
+ ${LangFileString} MUI_UNTEXT_FINISH_TITLE "ئۆچۈرۈش تاماملاندى"
+ ${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "مۇۋەپپىقىيەتلىك ئۆچۈرۈلدى."
+ ${LangFileString} MUI_UNTEXT_ABORT_TITLE "ئۆچۈرەلمىدى"
+ ${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "ئۆچۈرۈش مەغلۇپ بولدى."
+!endif
+
+!ifdef MUI_FINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "قاچىلاش يېتەكچىسى$(^NameDA)نى قاچىلاشنى تاماملىدى "
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "$(^NameDA)كومپيۇتېرىڭىزغا قاچىلاندى .$\r$\n$\r$\nتامام نى بېسىپ قاچىلاش يېتەكچىسىنى يېپىڭ."
+ ${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT " $(^NameDA) نى قاچىلاشنى تاماملاش ئۈچۈن،كومپيۇتېرىڭىزنى قايتا قوزغىتىڭ كومپيۇتېرىڭىزنى قايتا قوزغىتامسىز؟ ."
+!endif
+
+!ifdef MUI_UNFINISHPAGE
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "ئۆچۈرۈش يېتەكچىسى$(^NameDA)نى ئۆچۈرۈشنى تاماملىدى "
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "$(^NameDA)كومپيۇتېرىڭىزدىن ئۆچۈرۈلدى .$\r$\n$\r$\nئۆچۈرۈش يېتەكچىسىنى يېپىش ئۈچۈن تامام نى بېسىڭ."
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT " $(^NameDA) نى ئۆچۈرۈشنى تاماملاش ئۈچۈن،كومپيۇتېرىڭىزنى قايتا قوزغىتىڭ كومپيۇتېرىڭىزنى قايتا قوزغىتامسىز؟ "
+!endif
+
+!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "ھازىرلا قايتا قوزغۇتۇش"
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "كېيىنرەك كومپيۇتېرنى قولدا قايتا قوزغىتاي"
+ ${LangFileString} MUI_TEXT_FINISH_RUN "&$(^NameDA)نى ئىجرا قىلىش "
+ ${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&ياردەمنى كۆرۈش"
+ ${LangFileString} MUI_BUTTONTEXT_FINISH "&تامام"
+!endif
+
+!ifdef MUI_STARTMENUPAGE
+ ${LangFileString} MUI_TEXT_STARTMENU_TITLE "باشلاش تىزىملىكى قىسقۇچى تاللاش"
+ ${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "$(^NameDA)تېزكۆرگۈچى ئۈچۈن باشلاش تىزىملىكى قىسقۇچى تاللاش ."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "پروگراممىنىڭ تېزكۆرگۈچىنى ياسايدىغان باشلاش تىزىملىك قىسقۇچىنى تاللاڭ ھەم يېڭى قىسقۇچقا ئىسىم كىرگۈزۈڭ."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "تېزكۆرگۈچ ياسىمىسۇن"
+!endif
+
+!ifdef MUI_UNCONFIRMPAGE
+ ${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "$(^NameDA)نى ئۆچۈرۈش "
+ ${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "$(^NameDA)نى كومپيۇتېردىن ئۆچۈرۈش ."
+!endif
+
+!ifdef MUI_ABORTWARNING
+ ${LangFileString} MUI_TEXT_ABORTWARNING " $(^NameDA)نى قاچىلاشتىن چېكىنەمسىز؟"
+!endif
+
+!ifdef MUI_UNABORTWARNING
+ ${LangFileString} MUI_UNTEXT_ABORTWARNING " $(^NameDA)نى ئۆچۈرۈشتىن چېكىنەمسىز؟"
+!endif
+
+!ifdef MULTIUSER_INSTALLMODEPAGE
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "ئىشلەتكۈچى تاللاش"
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE " $(^NameDA) نى قاچىلاش ئۈچۈن ئىشلەتكۈچىلەرنى تاللاڭ."
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP " $(^NameDA) نى ئۆزى ئۈچۈنلا قاچىلاش ياكى بارلىق ئىشلەتكۈچىلەر ئۈچۈن قاچىلاشنى تاللاش. $(^ClickNext)"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "بارلىق ئىشلەتكۈچىلەرگە قاچىلاش"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "ماڭىلا قاچىلاش"
+!endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nlf
new file mode 100644
index 000000000..e5c40ce72
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nsh
new file mode 100644
index 000000000..79beed70a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Uzbek.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nlf
new file mode 100644
index 000000000..79609e1c4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nsh
new file mode 100644
index 000000000..84a8f7def
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Valencian.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nlf
new file mode 100644
index 000000000..d5bb8e8b2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nsh
new file mode 100644
index 000000000..7c0850adf
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Vietnamese.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nlf
new file mode 100644
index 000000000..d28bf3221
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nsh
new file mode 100644
index 000000000..8af9f1bc5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Welsh.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nlf
new file mode 100644
index 000000000..c22f1af84
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nsh
new file mode 100644
index 000000000..a2782cff3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Yoruba.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nlf b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nlf
new file mode 100644
index 000000000..d2de2f204
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nlf differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nsh
new file mode 100644
index 000000000..113d7d138
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Language files/Zulu.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Deprecated.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Deprecated.nsh
new file mode 100644
index 000000000..ddde664e8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Deprecated.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Interface.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Interface.nsh
new file mode 100644
index 000000000..2fba6a0d8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Interface.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Localization.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Localization.nsh
new file mode 100644
index 000000000..aa7fc2a70
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Localization.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/MUI2.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/MUI2.nsh
new file mode 100644
index 000000000..e571bd028
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/MUI2.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages.nsh
new file mode 100644
index 000000000..76b033f41
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Components.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Components.nsh
new file mode 100644
index 000000000..eeeeb5714
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Components.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Directory.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Directory.nsh
new file mode 100644
index 000000000..dafe19494
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Directory.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Finish.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Finish.nsh
new file mode 100644
index 000000000..1f6250d54
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Finish.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/InstallFiles.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/InstallFiles.nsh
new file mode 100644
index 000000000..00796c16b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/InstallFiles.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/License.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/License.nsh
new file mode 100644
index 000000000..2979cc9ca
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/License.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/StartMenu.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/StartMenu.nsh
new file mode 100644
index 000000000..b1403b205
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/StartMenu.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh
new file mode 100644
index 000000000..9b01ed378
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Welcome.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Welcome.nsh
new file mode 100644
index 000000000..b80beb92f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI 2/Pages/Welcome.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/System.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/System.nsh
new file mode 100644
index 000000000..e58d6d214
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/System.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/ioSpecial.ini b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/ioSpecial.ini
new file mode 100644
index 000000000..9dba15455
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/Modern UI/ioSpecial.ini differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/api.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/api.h
new file mode 100644
index 000000000..7418b873c
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/api.h
@@ -0,0 +1,83 @@
+/*
+ * apih
+ *
+ * This file is a part of NSIS.
+ *
+ * Copyright (C) 1999-2009 Nullsoft and Contributors
+ *
+ * Licensed under the zlib/libpng license (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ * Licence details can be found in the file COPYING.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.
+ */
+
+#ifndef _NSIS_EXEHEAD_API_H_
+#define _NSIS_EXEHEAD_API_H_
+
+// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version
+// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x))
+// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {}
+
+#define NSISPIAPIVER_1_0 0x00010000
+#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0
+
+// NSIS Plug-In Callback Messages
+enum NSPIM
+{
+ NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup
+ NSPIM_GUIUNLOAD, // Called after .onGUIEnd
+};
+
+// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback()
+// Return NULL for unknown messages
+// Should always be __cdecl for future expansion possibilities
+typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
+
+// extra_parameters data structures containing other interesting stuff
+// but the stack, variables and HWND passed on to plug-ins.
+typedef struct
+{
+ int autoclose;
+ int all_user_var;
+ int exec_error;
+ int abort;
+ int exec_reboot; // NSIS_SUPPORT_REBOOT
+ int reboot_called; // NSIS_SUPPORT_REBOOT
+ int XXX_cur_insttype; // depreacted
+ int plugin_api_version; // see NSISPIAPIVER_CURR
+ // used to be XXX_insttype_changed
+ int silent; // NSIS_CONFIG_SILENT_SUPPORT
+ int instdir_error;
+ int rtl;
+ int errlvl;
+ int alter_reg_view;
+ int status_update;
+} exec_flags_t;
+
+#ifndef NSISCALL
+# define NSISCALL __stdcall
+#endif
+
+typedef struct {
+ exec_flags_t *exec_flags;
+ int (NSISCALL *ExecuteCodeSegment)(int, HWND);
+ void (NSISCALL *validate_filename)(char *);
+ int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors
+} extra_parameters;
+
+// Definitions for page showing plug-ins
+// See Ui.c to understand better how they're used
+
+// sent to the outer window to tell it to go to the next inner window
+#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
+
+// custom pages should send this message to let NSIS know they're ready
+#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)
+
+// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning
+#define NOTIFY_BYE_BYE 'x'
+
+#endif /* _PLUGIN_H_ */
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.h
new file mode 100644
index 000000000..63b8b8467
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.h
@@ -0,0 +1,74 @@
+#ifndef ___NSIS_PLUGIN__H___
+#define ___NSIS_PLUGIN__H___
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "api.h"
+
+#ifndef NSISCALL
+# define NSISCALL __stdcall
+#endif
+
+#define EXDLL_INIT() { \
+ g_stringsize=string_size; \
+ g_stacktop=stacktop; \
+ g_variables=variables; }
+
+typedef struct _stack_t {
+ struct _stack_t *next;
+ char text[1]; // this should be the length of string_size
+} stack_t;
+
+enum
+{
+INST_0, // $0
+INST_1, // $1
+INST_2, // $2
+INST_3, // $3
+INST_4, // $4
+INST_5, // $5
+INST_6, // $6
+INST_7, // $7
+INST_8, // $8
+INST_9, // $9
+INST_R0, // $R0
+INST_R1, // $R1
+INST_R2, // $R2
+INST_R3, // $R3
+INST_R4, // $R4
+INST_R5, // $R5
+INST_R6, // $R6
+INST_R7, // $R7
+INST_R8, // $R8
+INST_R9, // $R9
+INST_CMDLINE, // $CMDLINE
+INST_INSTDIR, // $INSTDIR
+INST_OUTDIR, // $OUTDIR
+INST_EXEDIR, // $EXEDIR
+INST_LANG, // $LANGUAGE
+__INST_LAST
+};
+
+extern unsigned int g_stringsize;
+extern stack_t **g_stacktop;
+extern char *g_variables;
+
+int NSISCALL popstring(char *str); // 0 on success, 1 on empty stack
+int NSISCALL popstringn(char *str, int maxlen); // with length limit, pass 0 for g_stringsize
+int NSISCALL popint(); // pops an integer
+int NSISCALL popint_or(); // with support for or'ing (2|4|8)
+int NSISCALL myatoi(const char *s); // converts a string to an integer
+unsigned NSISCALL myatou(const char *s); // converts a string to an unsigned integer, decimal only
+int NSISCALL myatoi_or(const char *s); // with support for or'ing (2|4|8)
+void NSISCALL pushstring(const char *str);
+void NSISCALL pushint(int value);
+char * NSISCALL getuservariable(const int varnum);
+void NSISCALL setuservariable(const int varnum, const char *var);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//!___NSIS_PLUGIN__H___
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.lib b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.lib
new file mode 100644
index 000000000..ea64b80d8
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_ansi/pluginapi.lib differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/api.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/api.h
new file mode 100644
index 000000000..bab952224
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/api.h
@@ -0,0 +1,83 @@
+/*
+ * apih
+ *
+ * This file is a part of NSIS.
+ *
+ * Copyright (C) 1999-2009 Nullsoft and Contributors
+ *
+ * Licensed under the zlib/libpng license (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ * Licence details can be found in the file COPYING.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.
+ */
+
+#ifndef _NSIS_EXEHEAD_API_H_
+#define _NSIS_EXEHEAD_API_H_
+
+// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version
+// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x))
+// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {}
+
+#define NSISPIAPIVER_1_0 0x00010000
+#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0
+
+// NSIS Plug-In Callback Messages
+enum NSPIM
+{
+ NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup
+ NSPIM_GUIUNLOAD, // Called after .onGUIEnd
+};
+
+// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback()
+// Return NULL for unknown messages
+// Should always be __cdecl for future expansion possibilities
+typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
+
+// extra_parameters data structures containing other interesting stuff
+// but the stack, variables and HWND passed on to plug-ins.
+typedef struct
+{
+ int autoclose;
+ int all_user_var;
+ int exec_error;
+ int abort;
+ int exec_reboot; // NSIS_SUPPORT_REBOOT
+ int reboot_called; // NSIS_SUPPORT_REBOOT
+ int XXX_cur_insttype; // depreacted
+ int plugin_api_version; // see NSISPIAPIVER_CURR
+ // used to be XXX_insttype_changed
+ int silent; // NSIS_CONFIG_SILENT_SUPPORT
+ int instdir_error;
+ int rtl;
+ int errlvl;
+ int alter_reg_view;
+ int status_update;
+} exec_flags_t;
+
+#ifndef NSISCALL
+# define NSISCALL __stdcall
+#endif
+
+typedef struct {
+ exec_flags_t *exec_flags;
+ int (NSISCALL *ExecuteCodeSegment)(int, HWND);
+ void (NSISCALL *validate_filename)(TCHAR *);
+ int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors
+} extra_parameters;
+
+// Definitions for page showing plug-ins
+// See Ui.c to understand better how they're used
+
+// sent to the outer window to tell it to go to the next inner window
+#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
+
+// custom pages should send this message to let NSIS know they're ready
+#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)
+
+// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning
+#define NOTIFY_BYE_BYE 'x'
+
+#endif /* _PLUGIN_H_ */
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/nsis_tchar.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/nsis_tchar.h
new file mode 100644
index 000000000..9532d4e4c
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/nsis_tchar.h
@@ -0,0 +1,214 @@
+/*
+ * nsis_tchar.h
+ *
+ * This file is a part of NSIS.
+ *
+ * Copyright (C) 1999-2007 Nullsoft and Contributors
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.
+ *
+ * For Unicode support by Jim Park -- 08/30/2007
+ */
+
+// Jim Park: Only those we use are listed here.
+
+#pragma once
+
+#ifdef _UNICODE
+
+#ifndef _T
+#define __T(x) L ## x
+#define _T(x) __T(x)
+#define _TEXT(x) __T(x)
+#endif
+typedef wchar_t TCHAR;
+typedef wchar_t _TUCHAR;
+
+// program
+#define _tmain wmain
+#define _tWinMain wWinMain
+#define _tenviron _wenviron
+#define __targv __wargv
+
+// printfs
+#define _ftprintf fwprintf
+#define _sntprintf _snwprintf
+#define _stprintf _swprintf
+#define _tprintf wprintf
+#define _vftprintf vfwprintf
+#define _vsntprintf _vsnwprintf
+#define _vstprintf _vswprintf
+
+// scanfs
+#define _tscanf wscanf
+#define _stscanf swscanf
+
+// string manipulations
+#define _tcscat wcscat
+#define _tcschr wcschr
+#define _tcsclen wcslen
+#define _tcscpy wcscpy
+#define _tcsdup _wcsdup
+#define _tcslen wcslen
+#define _tcsnccpy wcsncpy
+#define _tcsncpy wcsncpy
+#define _tcsrchr wcsrchr
+#define _tcsstr wcsstr
+#define _tcstok wcstok
+
+// string comparisons
+#define _tcscmp wcscmp
+#define _tcsicmp _wcsicmp
+#define _tcsncicmp _wcsnicmp
+#define _tcsncmp wcsncmp
+#define _tcsnicmp _wcsnicmp
+
+// upper / lower
+#define _tcslwr _wcslwr
+#define _tcsupr _wcsupr
+#define _totlower towlower
+#define _totupper towupper
+
+// conversions to numbers
+#define _tcstoi64 _wcstoi64
+#define _tcstol wcstol
+#define _tcstoul wcstoul
+#define _tstof _wtof
+#define _tstoi _wtoi
+#define _tstoi64 _wtoi64
+#define _ttoi _wtoi
+#define _ttoi64 _wtoi64
+#define _ttol _wtol
+
+// conversion from numbers to strings
+#define _itot _itow
+#define _ltot _ltow
+#define _i64tot _i64tow
+#define _ui64tot _ui64tow
+
+// file manipulations
+#define _tfopen _wfopen
+#define _topen _wopen
+#define _tremove _wremove
+#define _tunlink _wunlink
+
+// reading and writing to i/o
+#define _fgettc fgetwc
+#define _fgetts fgetws
+#define _fputts fputws
+#define _gettchar getwchar
+
+// directory
+#define _tchdir _wchdir
+
+// environment
+#define _tgetenv _wgetenv
+#define _tsystem _wsystem
+
+// time
+#define _tcsftime wcsftime
+
+#else // ANSI
+
+#ifndef _T
+#define _T(x) x
+#define _TEXT(x) x
+#endif
+typedef char TCHAR;
+typedef unsigned char _TUCHAR;
+
+// program
+#define _tmain main
+#define _tWinMain WinMain
+#define _tenviron environ
+#define __targv __argv
+
+// printfs
+#define _ftprintf fprintf
+#define _sntprintf _snprintf
+#define _stprintf sprintf
+#define _tprintf printf
+#define _vftprintf vfprintf
+#define _vsntprintf _vsnprintf
+#define _vstprintf vsprintf
+
+// scanfs
+#define _tscanf scanf
+#define _stscanf sscanf
+
+// string manipulations
+#define _tcscat strcat
+#define _tcschr strchr
+#define _tcsclen strlen
+#define _tcscnlen strnlen
+#define _tcscpy strcpy
+#define _tcsdup _strdup
+#define _tcslen strlen
+#define _tcsnccpy strncpy
+#define _tcsrchr strrchr
+#define _tcsstr strstr
+#define _tcstok strtok
+
+// string comparisons
+#define _tcscmp strcmp
+#define _tcsicmp _stricmp
+#define _tcsncmp strncmp
+#define _tcsncicmp _strnicmp
+#define _tcsnicmp _strnicmp
+
+// upper / lower
+#define _tcslwr _strlwr
+#define _tcsupr _strupr
+
+#define _totupper toupper
+#define _totlower tolower
+
+// conversions to numbers
+#define _tcstol strtol
+#define _tcstoul strtoul
+#define _tstof atof
+#define _tstoi atoi
+#define _tstoi64 _atoi64
+#define _tstoi64 _atoi64
+#define _ttoi atoi
+#define _ttoi64 _atoi64
+#define _ttol atol
+
+// conversion from numbers to strings
+#define _i64tot _i64toa
+#define _itot _itoa
+#define _ltot _ltoa
+#define _ui64tot _ui64toa
+
+// file manipulations
+#define _tfopen fopen
+#define _topen _open
+#define _tremove remove
+#define _tunlink _unlink
+
+// reading and writing to i/o
+#define _fgettc fgetc
+#define _fgetts fgets
+#define _fputts fputs
+#define _gettchar getchar
+
+// directory
+#define _tchdir _chdir
+
+// environment
+#define _tgetenv getenv
+#define _tsystem system
+
+// time
+#define _tcsftime strftime
+
+#endif
+
+// is functions (the same in Unicode / ANSI)
+#define _istgraph isgraph
+#define _istascii __isascii
+
+#define __TFILE__ _T(__FILE__)
+#define __TDATE__ _T(__DATE__)
+#define __TTIME__ _T(__TIME__)
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.h
new file mode 100644
index 000000000..e762bbfc4
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.h
@@ -0,0 +1,101 @@
+#ifndef ___NSIS_PLUGIN__H___
+#define ___NSIS_PLUGIN__H___
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "api.h"
+#include "nsis_tchar.h"
+
+#ifndef NSISCALL
+# define NSISCALL __stdcall
+#endif
+
+#define EXDLL_INIT() { \
+ g_stringsize=string_size; \
+ g_stacktop=stacktop; \
+ g_variables=variables; }
+
+typedef struct _stack_t {
+ struct _stack_t *next;
+ TCHAR text[1]; // this should be the length of string_size
+} stack_t;
+
+enum
+{
+INST_0, // $0
+INST_1, // $1
+INST_2, // $2
+INST_3, // $3
+INST_4, // $4
+INST_5, // $5
+INST_6, // $6
+INST_7, // $7
+INST_8, // $8
+INST_9, // $9
+INST_R0, // $R0
+INST_R1, // $R1
+INST_R2, // $R2
+INST_R3, // $R3
+INST_R4, // $R4
+INST_R5, // $R5
+INST_R6, // $R6
+INST_R7, // $R7
+INST_R8, // $R8
+INST_R9, // $R9
+INST_CMDLINE, // $CMDLINE
+INST_INSTDIR, // $INSTDIR
+INST_OUTDIR, // $OUTDIR
+INST_EXEDIR, // $EXEDIR
+INST_LANG, // $LANGUAGE
+__INST_LAST
+};
+
+extern unsigned int g_stringsize;
+extern stack_t **g_stacktop;
+extern TCHAR *g_variables;
+
+int NSISCALL popstring(TCHAR *str); // 0 on success, 1 on empty stack
+int NSISCALL popstringn(TCHAR *str, int maxlen); // with length limit, pass 0 for g_stringsize
+int NSISCALL popint(); // pops an integer
+int NSISCALL popint_or(); // with support for or'ing (2|4|8)
+int NSISCALL myatoi(const TCHAR *s); // converts a string to an integer
+unsigned NSISCALL myatou(const TCHAR *s); // converts a string to an unsigned integer, decimal only
+int NSISCALL myatoi_or(const TCHAR *s); // with support for or'ing (2|4|8)
+void NSISCALL pushstring(const TCHAR *str);
+void NSISCALL pushint(int value);
+TCHAR * NSISCALL getuservariable(const int varnum);
+void NSISCALL setuservariable(const int varnum, const TCHAR *var);
+
+#ifdef _UNICODE
+#define PopStringW(x) popstring(x)
+#define PushStringW(x) pushstring(x)
+#define SetUserVariableW(x,y) setuservariable(x,y)
+
+int NSISCALL PopStringA(char* ansiStr);
+void NSISCALL PushStringA(const char* ansiStr);
+void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
+void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
+void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr);
+
+#else
+// ANSI defs
+
+#define PopStringA(x) popstring(x)
+#define PushStringA(x) pushstring(x)
+#define SetUserVariableA(x,y) setuservariable(x,y)
+
+int NSISCALL PopStringW(wchar_t* wideStr);
+void NSISCALL PushStringW(wchar_t* wideStr);
+void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
+void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
+void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//!___NSIS_PLUGIN__H___
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.lib b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.lib
new file mode 100644
index 000000000..5a208423f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/nsis_unicode/pluginapi.lib differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/resource.h b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/resource.h
new file mode 100644
index 000000000..baf8b2829
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by selfdel.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.c b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.c
new file mode 100644
index 000000000..dbd88354b
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.c
@@ -0,0 +1,324 @@
+/***************************************************
+* FILE NAME: selfdel.c
+*
+* PURPOSE:
+* NSIS plug-in for self deleting uninstaller for
+* Win9x/WinNT (all versions)
+*
+* CONSIDERATIONS
+*
+* MSVC6: works with Release built only, because source
+* file must be compiled with /GZ turned OFF, but in
+* Debug builds it is always on (basically, disable
+* run-time stack checks)
+*
+* CHANGE HISTORY
+*
+* James Brown - Oct 01 2003
+* - Original http://www.catch22.net/tuts/selfdel.asp
+*
+* Takhir Bedertdinov - Jan 21 2006
+* - Converted to NSIS plug-in, rmdir implementation, MSVCRT
+* dependencies removed
+*
+* Stuart Welch - Jul 17 2011
+* - Fixed for x64 by specifying full path to explorer.exe
+* - Ensures WOW64 file system redirection is enabled
+* - Reduced deletion retry to 500ms
+* - Built with VS2010
+* - Added Unicode build
+* - Added version information resource
+* - Calls MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT on failure
+*
+* Stuart Welch - Aug 10 2011
+* - Added /REBOOT
+*
+**************************************************/
+
+#define WINVER 0x0400
+#define _WIN32_WINNT 0x0400
+#include
+
+#ifdef UNICODE
+#include "nsis_unicode\pluginapi.h"
+#else
+#include "nsis_ansi\pluginapi.h"
+#endif
+
+#ifdef MoveFileEx
+#undef MoveFileEx
+#endif
+
+#ifndef EWX_FORCEIFHUNG
+#define EWX_FORCEIFHUNG 0x00000010
+#endif
+
+#pragma pack(push, 1)
+
+#define CODESIZE 0x200
+#define SWITCH_RMDIR TEXT("/RMDIR")
+#define SWITCH_REBOOT TEXT("/REBOOT")
+
+//
+// Structure to inject into remote process. Contains
+// function pointers and code to execute.
+//
+typedef struct _SELFDEL
+{
+ struct _SELFDEL *Arg0; // pointer to self
+
+ BYTE opCodes[CODESIZE]; // code
+
+ HANDLE hParent; // parent process handle
+
+ FARPROC fnWaitForSingleObject;
+ FARPROC fnCloseHandle;
+ FARPROC fnDeleteFile;
+ FARPROC fnSleep;
+ FARPROC fnExitProcess;
+ FARPROC fnRemoveDirectory;
+ FARPROC fnGetLastError;
+ FARPROC fnExitWindowsEx;
+
+ TCHAR szFileName[MAX_PATH]; // file to delete
+ BOOL fRemDir;
+ BOOL fReboot;
+
+} SELFDEL;
+
+#pragma pack(pop)
+
+#define NSISFUNC(name) void __declspec(dllexport) name(HWND hWndParent, int string_size, TCHAR* variables, stack_t** stacktop, extra_parameters* extra)
+#define DLL_INIT() EXDLL_INIT();
+
+typedef BOOLEAN (WINAPI* PWow64EnableWow64FsRedirection)(BOOLEAN Wow64FsEnableRedirection);
+typedef BOOL (WINAPI* PMoveFileEx)(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags);
+
+#ifdef _DEBUG
+#define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))
+#else
+#define FUNC_ADDR(func) func
+#endif
+
+/*****************************************************
+ * FUNCTION NAME: remote_thread()
+ * PURPOSE:
+ * Routine to execute in remote process
+ * SPECIAL CONSIDERATIONS:
+ * Takhir: I hope it still less then CODESIZE after
+ * I added rmdir
+ *****************************************************/
+static void remote_thread(SELFDEL *remote)
+{
+ TCHAR *p = remote->szFileName, *e;
+
+ // Wait for parent process to terminate
+ remote->fnWaitForSingleObject(remote->hParent, INFINITE);
+ remote->fnCloseHandle(remote->hParent);
+
+ // Try to delete the executable file
+ while(!remote->fnDeleteFile(remote->szFileName))
+ {
+ // Failed - try again in a bit
+ remote->fnSleep(500);
+ }
+
+ // Takhir: my rmdir add-on :)
+ // Do we have at least one back slash in full path-name
+ // strrchr() implementation
+ if(remote->fRemDir)
+ {
+ while(*++p != 0)
+ {
+ if(*p == '\\')
+ e = p;
+ }
+
+ *e = 0;
+
+ // Root install safe, rmdir on Wins doesn't delete 'c:'
+ remote->fnRemoveDirectory(remote->szFileName);
+ }
+
+ // Afrow UK: reboot add-on
+ if (remote->fReboot)
+ {
+ remote->fnExitWindowsEx(EWX_REBOOT|EWX_FORCEIFHUNG, 0);
+ }
+
+ // Finished! Exit so that we don't execute garbage code
+ remote->fnExitProcess(0);
+}
+
+/*****************************************************
+ * FUNCTION NAME: my_memcpy()
+ * PURPOSE:
+ * msvcrt replacement
+ * SPECIAL CONSIDERATIONS:
+ *
+ *****************************************************/
+void my_memcpy(BYTE* dst, BYTE* src, int len)
+{
+ int i;
+ for(i=0;i
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=selfdel - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "selfdel.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "selfdel.mak" CFG="selfdel - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "selfdel - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "selfdel - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "selfdel - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../debug"
+# PROP Intermediate_Dir "../debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "selfdel_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "selfdel_EXPORTS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib /nologo /entry:"DllMain" /dll /machine:I386 /nodefaultlib /out:"..\..\plugins\SelfDel.dll" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "selfdel - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../Debug"
+# PROP Intermediate_Dir "../Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "selfdel_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "selfdel_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /machine:I386 /out:"..\..\plugins\selfdel.dll" /pdbtype:sept
+# SUBTRACT LINK32 /debug
+
+!ENDIF
+
+# Begin Target
+
+# Name "selfdel - Win32 Release"
+# Name "selfdel - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\selfdel.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.dsw b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.dsw
new file mode 100644
index 000000000..787b607df
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "selfdel"=".\selfdel.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.rc b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.rc
new file mode 100644
index 000000000..d22bc07fe
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.rc differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.sln b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.sln
new file mode 100644
index 000000000..a8b81b637
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.sln
@@ -0,0 +1,23 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "selfdel", "selfdel.vcxproj", "{7A296601-9716-5C64-8D09-09D1C67BF8B1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Debug|Win32.Build.0 = Debug|Win32
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Release|Win32.ActiveCfg = Release|Win32
+ {7A296601-9716-5C64-8D09-09D1C67BF8B1}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj
new file mode 100644
index 000000000..9ad1f4203
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj
@@ -0,0 +1,184 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release Unicode
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+ DynamicLibrary
+ false
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ Unicode
+
+
+ DynamicLibrary
+ false
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+ false
+ $(SolutionDir)..\..\Plugins\
+ false
+
+
+ false
+ $(SolutionDir)..\..\Unicode\Plugins\
+ false
+
+
+
+ MultiThreadedDebugDLL
+ Default
+ false
+ Disabled
+ true
+ Level3
+ true
+ EditAndContinue
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;selfdel_EXPORTS;%(PreprocessorDefinitions)
+ EnableFastChecks
+
+
+ true
+ _DEBUG;%(PreprocessorDefinitions)
+ .\../Debug\selfdel.tlb
+ true
+ Win32
+
+
+ 0x0409
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ .\../Debug\selfdel.bsc
+
+
+ true
+ true
+ true
+ nsis_ansi\pluginapi.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ MultiThreadedDLL
+ OnlyExplicitInline
+ true
+ true
+ MinSpace
+ true
+ Level3
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;selfdel_EXPORTS;%(PreprocessorDefinitions)
+ false
+
+
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+ .\../debug\selfdel.tlb
+ true
+ Win32
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ .\../debug\selfdel.bsc
+
+
+ true
+ true
+ true
+ nsis_ansi\pluginapi.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
+ DllMain
+
+
+
+
+ MultiThreadedDLL
+ OnlyExplicitInline
+ true
+ true
+ MinSpace
+ true
+ Level3
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;selfdel_EXPORTS;%(PreprocessorDefinitions)
+ false
+
+
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+ .\../debug\selfdel.tlb
+ true
+ Win32
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ .\../debug\selfdel.bsc
+
+
+ true
+ true
+ true
+ nsis_unicode\pluginapi.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
+ DllMain
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj.filters b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj.filters
new file mode 100644
index 000000000..34e02bd50
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/SelfDel/selfdel.vcxproj.filters
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/default.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/default.exe
new file mode 100644
index 000000000..fd11f0133
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/default.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern.exe
new file mode 100644
index 000000000..61dc1fb21
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmp.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmp.exe
new file mode 100644
index 000000000..a4393b1e1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmp.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmpr.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmpr.exe
new file mode 100644
index 000000000..eef8fa442
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_headerbmpr.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_nodesc.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_nodesc.exe
new file mode 100644
index 000000000..3b628a679
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_nodesc.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_smalldesc.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_smalldesc.exe
new file mode 100644
index 000000000..52000ad1b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/modern_smalldesc.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/sdbarker_tiny.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/sdbarker_tiny.exe
new file mode 100644
index 000000000..ec5b4ba6c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/UIs/sdbarker_tiny.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Base.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Base.nsh
new file mode 100644
index 000000000..47219c370
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Base.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Classic.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Classic.nsh
new file mode 100644
index 000000000..adfd8dfcd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Classic.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Modern.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Modern.nsh
new file mode 100644
index 000000000..1ed8c2a65
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Contrib/zip2exe/Modern.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Colors.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Colors.nsh
new file mode 100644
index 000000000..01f933793
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Colors.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/FileFunc.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/FileFunc.nsh
new file mode 100644
index 000000000..30307a544
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/FileFunc.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/InstallOptions.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/InstallOptions.nsh
new file mode 100644
index 000000000..c51b2ddde
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/InstallOptions.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LangFile.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LangFile.nsh
new file mode 100644
index 000000000..565ab7d05
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LangFile.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Library.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Library.nsh
new file mode 100644
index 000000000..9ba01258b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Library.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LogicLib.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LogicLib.nsh
new file mode 100644
index 000000000..295978f9c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/LogicLib.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI.nsh
new file mode 100644
index 000000000..79b53ac24
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI2.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI2.nsh
new file mode 100644
index 000000000..7a76129ec
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MUI2.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Memento.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Memento.nsh
new file mode 100644
index 000000000..cf9ca4853
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Memento.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MultiUser.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MultiUser.nsh
new file mode 100644
index 000000000..9feb3a7c5
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/MultiUser.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/NewTextReplace.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/NewTextReplace.nsh
new file mode 100644
index 000000000..584503c13
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/NewTextReplace.nsh
@@ -0,0 +1,77 @@
+/*****************************************************************
+ * NewTextReplace NSIS plugin v0.4 *
+ * by Gringoloco023, 2010 *
+ * http://portableapps.com/node/21840 *
+ * Based on: *
+ * TextReplace NSIS plugin v1.5 *
+ * *
+ * 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru) *
+ *****************************************************************/
+
+
+!define ReplaceInFileUTF16LECS '!insertmacro "ReplaceInFileUTF16LECS"' ;${ReplaceInFileUTF16LECS} SOURCE_FILE SEARCH_TEXT REPLACEMENT
+!define ReplaceInFileUTF16LE '!insertmacro "ReplaceInFileUTF16LE"' ;${ReplaceInFileUTF16LE} SOURCE_FILE SEARCH_TEXT REPLACEMENT
+
+
+!define textreplace::FindInFile `!insertmacro textreplace::FindInFile`
+
+!macro textreplace::FindInFile _INPUTFILE _FINDIT _OPTIONS _COUNT
+ newtextreplace::_FindInFile /NOUNLOAD `${_INPUTFILE}` `${_FINDIT}` `${_OPTIONS}`
+ Pop ${_COUNT}
+!macroend
+
+
+!define textreplace::ReplaceInFile `!insertmacro textreplace::ReplaceInFile`
+
+!macro textreplace::ReplaceInFile _INPUTFILE _OUTPUTFILE _REPLACEIT _REPLACEWITH _OPTIONS _COUNT
+ newtextreplace::_ReplaceInFile /NOUNLOAD `${_INPUTFILE}` `${_OUTPUTFILE}` `${_REPLACEIT}` `${_REPLACEWITH}` `${_OPTIONS}`
+ Pop ${_COUNT}
+!macroend
+
+
+!define textreplace::FillReadBuffer `!insertmacro textreplace::FillReadBuffer`
+
+!macro textreplace::FillReadBuffer _FILE _POINTER
+ newtextreplace::_FillReadBuffer /NOUNLOAD `${_FILE}`
+ Pop ${_POINTER}
+!macroend
+
+
+
+!define textreplace::FreeReadBuffer `!insertmacro textreplace::FreeReadBuffer`
+
+!macro textreplace::FreeReadBuffer _POINTER
+ newtextreplace::_FreeReadBuffer /NOUNLOAD `${_POINTER}`
+!macroend
+
+
+
+!define textreplace::Unload `!insertmacro textreplace::Unload`
+
+!macro textreplace::Unload
+ newtextreplace::_Unload
+!macroend
+
+/*****************************************************************
+ *** The following is meant to ***
+ *** be used in combination with ***
+ *** ReplaceInFileWithTextReplace.nsh ***
+ *****************************************************************/
+
+!macro ReplaceInFileUTF16LECS SOURCE_FILE SEARCH_TEXT REPLACEMENT
+ Push `/U=1 /S=1`
+ Push `${SOURCE_FILE}`
+ Push `${SEARCH_TEXT}`
+ Push `${REPLACEMENT}`
+ Call ReplaceInFile
+
+!macroend
+
+!macro ReplaceInFileUTF16LE SOURCE_FILE SEARCH_TEXT REPLACEMENT
+ Push `/U=1 /S=0`
+ Push `${SOURCE_FILE}`
+ Push `${SEARCH_TEXT}`
+ Push `${REPLACEMENT}`
+ Call ReplaceInFile
+!macroend
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Registry.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Registry.nsh
new file mode 100644
index 000000000..d6dfd138a
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Registry.nsh
@@ -0,0 +1,195 @@
+!define registry::Open `!insertmacro registry::Open`
+
+!macro registry::Open _PATH _OPTIONS _HANDLE
+ registry::_Open /NOUNLOAD `${_PATH}` `${_OPTIONS}`
+ Pop ${_HANDLE}
+!macroend
+
+
+!define registry::Find `!insertmacro registry::Find`
+
+!macro registry::Find _HANDLE _PATH _VALUEORKEY _STRING _TYPE
+ registry::_Find /NOUNLOAD `${_HANDLE}`
+ Pop ${_PATH}
+ Pop ${_VALUEORKEY}
+ Pop ${_STRING}
+ Pop ${_TYPE}
+!macroend
+
+
+!define registry::Close `!insertmacro registry::Close`
+
+!macro registry::Close _HANDLE
+ registry::_Close /NOUNLOAD `${_HANDLE}`
+!macroend
+
+
+!define registry::KeyExists `!insertmacro registry::KeyExists`
+
+!macro registry::KeyExists _PATH _ERR
+ registry::_KeyExists /NOUNLOAD `${_PATH}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::Read `!insertmacro registry::Read`
+
+!macro registry::Read _PATH _VALUE _STRING _TYPE
+ registry::_Read /NOUNLOAD `${_PATH}` `${_VALUE}`
+ Pop ${_STRING}
+ Pop ${_TYPE}
+!macroend
+
+
+!define registry::Write `!insertmacro registry::Write`
+
+!macro registry::Write _PATH _VALUE _STRING _TYPE _ERR
+ registry::_Write /NOUNLOAD `${_PATH}` `${_VALUE}` `${_STRING}` `${_TYPE}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::ReadExtra `!insertmacro registry::ReadExtra`
+
+!macro registry::ReadExtra _PATH _VALUE _NUMBER _STRING _TYPE
+ registry::_ReadExtra /NOUNLOAD `${_PATH}` `${_VALUE}` `${_NUMBER}`
+ Pop ${_STRING}
+ Pop ${_TYPE}
+!macroend
+
+
+!define registry::WriteExtra `!insertmacro registry::WriteExtra`
+
+!macro registry::WriteExtra _PATH _VALUE _STRING _ERR
+ registry::_WriteExtra /NOUNLOAD `${_PATH}` `${_VALUE}` `${_STRING}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::CreateKey `!insertmacro registry::CreateKey`
+
+!macro registry::CreateKey _PATH _ERR
+ registry::_CreateKey /NOUNLOAD `${_PATH}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::DeleteValue `!insertmacro registry::DeleteValue`
+
+!macro registry::DeleteValue _PATH _VALUE _ERR
+ registry::_DeleteValue /NOUNLOAD `${_PATH}` `${_VALUE}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::DeleteKey `!insertmacro registry::DeleteKey`
+
+!macro registry::DeleteKey _PATH _ERR
+ registry::_DeleteKey /NOUNLOAD `${_PATH}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::DeleteKeyEmpty `!insertmacro registry::DeleteKeyEmpty`
+
+!macro registry::DeleteKeyEmpty _PATH _ERR
+ registry::_DeleteKeyEmpty /NOUNLOAD `${_PATH}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::CopyValue `!insertmacro registry::CopyValue`
+
+!macro registry::CopyValue _PATH_SOURCE _VALUE_SOURCE _PATH_TARGET _VALUE_TARGET _ERR
+ registry::_CopyValue /NOUNLOAD `${_PATH_SOURCE}` `${_VALUE_SOURCE}` `${_PATH_TARGET}` `${_VALUE_TARGET}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::MoveValue `!insertmacro registry::MoveValue`
+
+!macro registry::MoveValue _PATH_SOURCE _VALUE_SOURCE _PATH_TARGET _VALUE_TARGET _ERR
+ registry::_MoveValue /NOUNLOAD `${_PATH_SOURCE}` `${_VALUE_SOURCE}` `${_PATH_TARGET}` `${_VALUE_TARGET}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::CopyKey `!insertmacro registry::CopyKey`
+
+!macro registry::CopyKey _PATH_SOURCE _PATH_TARGET _ERR
+ registry::_CopyKey /NOUNLOAD `${_PATH_SOURCE}` `${_PATH_TARGET}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::MoveKey `!insertmacro registry::MoveKey`
+
+!macro registry::MoveKey _PATH_SOURCE _PATH_TARGET _ERR
+ registry::_MoveKey /NOUNLOAD `${_PATH_SOURCE}` `${_PATH_TARGET}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::SaveKey `!insertmacro registry::SaveKey`
+
+!macro registry::SaveKey _PATH _FILE _OPTIONS _ERR
+ registry::_SaveKey /NOUNLOAD `${_PATH}` `${_FILE}` `${_OPTIONS}`
+ Pop ${_ERR}
+!macroend
+
+
+!define registry::RestoreKey `!insertmacro registry::RestoreKey`
+
+!macro registry::RestoreKey _FILE _ERR
+ registry::_RestoreKey /NOUNLOAD `${_FILE}`
+ Pop ${_ERR}
+ IntCmp ${_ERR} -2 0 0 +10 ;REGEDIT4 ansi file
+ SetDetailsPrint none
+ IfFileExists "$SYSDIR\reg.exe" 0 +4 ;reg.exe used in Windows2K/XP/Vista/7
+ nsExec::ExecToStack `"$SYSDIR\reg.exe" import "${_FILE}"`
+ Pop ${_ERR}
+ StrCmp ${_ERR} 0 +5 0
+ IfFileExists "$WINDIR\regedit.exe" 0 +3 ;regedit.exe used in Wine
+ ExecWait `"$WINDIR\regedit.exe" /s "${_FILE}"` ${_ERR}
+ IfErrors 0 +2
+ StrCpy ${_ERR} -1
+ SetDetailsPrint lastused
+!macroend
+
+!define registry::StrToHex `!insertmacro registry::StrToHex`
+
+!macro registry::StrToHex _STRING _HEX_STRING
+ registry::_StrToHex /NOUNLOAD `${_STRING}`
+ Pop ${_HEX_STRING}
+!macroend
+
+
+!define registry::HexToStr `!insertmacro registry::HexToStr`
+
+!macro registry::HexToStr _HEX_STRING _STRING
+ registry::_HexToStr /NOUNLOAD `${_HEX_STRING}`
+ Pop ${_STRING}
+!macroend
+
+
+!define registry::StrToHexUTF16LE `!insertmacro registry::StrToHexUTF16LE`
+
+!macro registry::StrToHexUTF16LE _STRING _HEX_STRING
+ registry::_StrToHexUTF16LE /NOUNLOAD `${_STRING}`
+ Pop ${_HEX_STRING}
+!macroend
+
+
+!define registry::HexToStrUTF16LE `!insertmacro registry::HexToStrUTF16LE`
+
+!macro registry::HexToStrUTF16LE _HEX_STRING _STRING
+ registry::_HexToStrUTF16LE /NOUNLOAD `${_HEX_STRING}`
+ Pop ${_STRING}
+!macroend
+
+
+!define registry::Unload `!insertmacro registry::Unload`
+
+!macro registry::Unload
+ registry::_Unload
+!macroend
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Sections.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Sections.nsh
new file mode 100644
index 000000000..f5ca6214a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Sections.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/StrFunc.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/StrFunc.nsh
new file mode 100644
index 000000000..41081643d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/StrFunc.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TBProgress.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TBProgress.nsh
new file mode 100644
index 000000000..f72eb616c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TBProgress.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextFunc.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextFunc.nsh
new file mode 100644
index 000000000..287631be2
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextFunc.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextReplace.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextReplace.nsh
new file mode 100644
index 000000000..e5bec680a
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/TextReplace.nsh
@@ -0,0 +1,77 @@
+/*****************************************************************
+ * NewTextReplace NSIS plugin v0.4 *
+ * by Gringoloco023, 2010 *
+ * http://portableapps.com/node/21840 *
+ * Based on: *
+ * TextReplace NSIS plugin v1.5 *
+ * *
+ * 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru) *
+ *****************************************************************/
+;This file named TextReplace.nsh, for compatibility of old scripts !
+
+!define ReplaceInFileUTF16LECS '!insertmacro "ReplaceInFileUTF16LECS"' ;${ReplaceInFileUTF16LECS} SOURCE_FILE SEARCH_TEXT REPLACEMENT
+!define ReplaceInFileUTF16LE '!insertmacro "ReplaceInFileUTF16LE"' ;${ReplaceInFileUTF16LE} SOURCE_FILE SEARCH_TEXT REPLACEMENT
+
+
+!define textreplace::FindInFile `!insertmacro textreplace::FindInFile`
+
+!macro textreplace::FindInFile _INPUTFILE _FINDIT _OPTIONS _COUNT
+ newtextreplace::_FindInFile /NOUNLOAD `${_INPUTFILE}` `${_FINDIT}` `${_OPTIONS}`
+ Pop ${_COUNT}
+!macroend
+
+
+!define textreplace::ReplaceInFile `!insertmacro textreplace::ReplaceInFile`
+
+!macro textreplace::ReplaceInFile _INPUTFILE _OUTPUTFILE _REPLACEIT _REPLACEWITH _OPTIONS _COUNT
+ newtextreplace::_ReplaceInFile /NOUNLOAD `${_INPUTFILE}` `${_OUTPUTFILE}` `${_REPLACEIT}` `${_REPLACEWITH}` `${_OPTIONS}`
+ Pop ${_COUNT}
+!macroend
+
+
+!define textreplace::FillReadBuffer `!insertmacro textreplace::FillReadBuffer`
+
+!macro textreplace::FillReadBuffer _FILE _POINTER
+ newtextreplace::_FillReadBuffer /NOUNLOAD `${_FILE}`
+ Pop ${_POINTER}
+!macroend
+
+
+
+!define textreplace::FreeReadBuffer `!insertmacro textreplace::FreeReadBuffer`
+
+!macro textreplace::FreeReadBuffer _POINTER
+ newtextreplace::_FreeReadBuffer /NOUNLOAD `${_POINTER}`
+!macroend
+
+
+
+!define textreplace::Unload `!insertmacro textreplace::Unload`
+
+!macro textreplace::Unload
+ newtextreplace::_Unload
+!macroend
+
+/*****************************************************************
+ *** The following is meant to ***
+ *** be used in combination with ***
+ *** ReplaceInFileWithTextReplace.nsh ***
+ *****************************************************************/
+
+!macro ReplaceInFileUTF16LECS SOURCE_FILE SEARCH_TEXT REPLACEMENT
+ Push `/U=1 /S=1`
+ Push `${SOURCE_FILE}`
+ Push `${SEARCH_TEXT}`
+ Push `${REPLACEMENT}`
+ Call ReplaceInFile
+
+!macroend
+
+!macro ReplaceInFileUTF16LE SOURCE_FILE SEARCH_TEXT REPLACEMENT
+ Push `/U=1 /S=0`
+ Push `${SOURCE_FILE}`
+ Push `${SEARCH_TEXT}`
+ Push `${REPLACEMENT}`
+ Call ReplaceInFile
+!macroend
+
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/UpgradeDLL.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/UpgradeDLL.nsh
new file mode 100644
index 000000000..8e88c3ce3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/UpgradeDLL.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Util.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Util.nsh
new file mode 100644
index 000000000..b05d9ea70
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Util.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VB6RunTime.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VB6RunTime.nsh
new file mode 100644
index 000000000..759124051
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VB6RunTime.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VPatchLib.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VPatchLib.nsh
new file mode 100644
index 000000000..42ed923b4
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/VPatchLib.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinDef.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinDef.nsh
new file mode 100644
index 000000000..db7b6c74a
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinDef.nsh
@@ -0,0 +1,74 @@
+!ifndef __WIN_WINDEF__INC
+!define __WIN_WINDEF__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_NOINC_WINDEF
+
+
+!ifndef MAX_PATH
+!define MAX_PATH 260
+!endif
+#define NULL 0
+
+
+!macro _Win_MINMAX _intcmp _j1 _j2 _outvar _a _b
+${_intcmp} "${_a}" "${_b}" ${_j1} ${_j1} ${_j2}
+StrCpy ${_outvar} "${_a}"
+goto +2
+StrCpy ${_outvar} "${_b}"
+!macroend
+!ifndef __WIN_MS_NOMINMAX & min & max & min_u & max_u
+!define min "!insertmacro _Win_MINMAX IntCmp +1 +3 "
+!define max "!insertmacro _Win_MINMAX IntCmp +3 +1 "
+!define min_u "!insertmacro _Win_MINMAX IntCmpU +1 +3 "
+!define max_u "!insertmacro _Win_MINMAX IntCmpU +3 +1 "
+!endif
+
+!macro _Win_LOBYTE _outvar _in
+IntOp ${_outvar} "${_in}" & 0xFF
+!macroend
+!define LOBYTE "!insertmacro _Win_LOBYTE "
+
+!macro _Win_HIBYTE _outvar _in
+IntOp ${_outvar} "${_in}" >> 8
+${LOBYTE} ${_outvar} ${_outvar}
+!macroend
+!define HIBYTE "!insertmacro _Win_HIBYTE "
+
+!macro _Win_LOWORD _outvar _in
+IntOp ${_outvar} "${_in}" & 0xFFFF
+!macroend
+!define LOWORD "!insertmacro _Win_LOWORD "
+
+!macro _Win_HIWORD _outvar _in
+IntOp ${outvar} "${_in}" >> 16 ;sign extended :(
+${LOWORD} ${_outvar} ${outvar} ;make sure we strip off the upper word
+!macroend
+!define HIWORD "!insertmacro _Win_HIWORD "
+
+!macro _Win_MAKEWORD _outvar _tmpvar _lo _hi
+${LOBYTE} ${_outvar} "${_hi}"
+${LOBYTE} ${_tmpvar} "${_lo}"
+IntOp ${_outvar} ${_outvar} << 8
+IntOp ${_outvar} ${_outvar} | ${_tmpvar}
+!macroend
+!define MAKEWORD "!insertmacro _Win_MAKEWORD "
+
+!macro _Win_MAKELONG32 _outvar _tmpvar _wlo _whi
+${LOWORD} ${_outvar} "${_wlo}"
+IntOp ${_tmpvar} "${_whi}" << 16
+IntOp ${_outvar} ${_outvar} | ${_tmpvar}
+!macroend
+!define MAKELONG "!insertmacro _Win_MAKELONG32 "
+!if "${__WIN_PTRSIZE}" <= 4
+!define MAKEWPARAM "${MAKELONG}"
+!define MAKELPARAM "${MAKELONG}"
+!define MAKELRESULT "${MAKELONG}"
+!else
+!error "Missing 64bit imp!"
+!endif
+
+
+!endif /* __WIN_NOINC_WINDEF */
+!verbose pop
+!endif /* __WIN_WINDEF__INC */
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinError.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinError.nsh
new file mode 100644
index 000000000..4fec78052
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinError.nsh
@@ -0,0 +1,64 @@
+!ifndef __WIN_WINERROR__INC
+!define __WIN_WINERROR__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_NOINC_WINERROR
+
+#define NO_ERROR 0
+!define ERROR_SUCCESS 0
+!define ERROR_INVALID_FUNCTION 1
+!define ERROR_FILE_NOT_FOUND 2
+!define ERROR_PATH_NOT_FOUND 3
+!define ERROR_TOO_MANY_OPEN_FILES 4
+!define ERROR_ACCESS_DENIED 5
+!define ERROR_INVALID_HANDLE 6
+!define ERROR_ARENA_TRASHED 7
+!define ERROR_NOT_ENOUGH_MEMORY 8
+!define ERROR_INVALID_BLOCK 9
+!define ERROR_BAD_ENVIRONMENT 10
+!define ERROR_BAD_FORMAT 11
+!define ERROR_INVALID_ACCESS 12
+!define ERROR_INVALID_DATA 13
+!define ERROR_OUTOFMEMORY 14
+!define ERROR_INVALID_DRIVE 15
+!define ERROR_CURRENT_DIRECTORY 16
+!define ERROR_NOT_SAME_DEVICE 17
+!define ERROR_NO_MORE_FILES 18
+!define ERROR_WRITE_PROTECT 19
+!define ERROR_BAD_UNIT 20
+!define ERROR_NOT_READY 21
+!define ERROR_BAD_COMMAND 22
+!define ERROR_CRC 23
+!define ERROR_BAD_LENGTH 24
+!define ERROR_SEEK 25
+!define ERROR_NOT_DOS_DISK 26
+!define ERROR_SECTOR_NOT_FOUND 27
+!define ERROR_OUT_OF_PAPER 28
+!define ERROR_WRITE_FAULT 29
+!define ERROR_READ_FAULT 30
+!define ERROR_GEN_FAILURE 31
+!define ERROR_SHARING_VIOLATION 32
+!define ERROR_LOCK_VIOLATION 33
+!define ERROR_WRONG_DISK 34
+!define ERROR_SHARING_BUFFER_EXCEEDED 36
+!define ERROR_HANDLE_EOF 38
+!define ERROR_HANDLE_DISK_FULL 39
+!define ERROR_NOT_SUPPORTED 50
+
+!define SEVERITY_SUCCESS 0
+!define SEVERITY_ERROR 1
+!define E_UNEXPECTED 0x8000FFFF
+!define E_NOTIMPL 0x80004001
+!define E_OUTOFMEMORY 0x8007000E
+!define E_INVALIDARG 0x80070057
+!define E_NOINTERFACE 0x80004002
+!define E_POINTER 0x80004003
+!define E_HANDLE 0x80070006
+!define E_ABORT 0x80004004
+!define E_FAIL 0x80004005
+!define E_ACCESSDENIED 0x80070005
+!define E_PENDING 0x8000000A
+
+!endif /* __WIN_NOINC_WINERROR */
+!verbose pop
+!endif /* __WIN_WINERROR__INC */
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinNT.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinNT.nsh
new file mode 100644
index 000000000..bec1c1445
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinNT.nsh
@@ -0,0 +1,209 @@
+!ifndef __WIN_WINNT__INC
+!define __WIN_WINNT__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_NOINC_WINNT
+
+
+#define MINCHAR 0x80
+#define MAXCHAR 0x7f
+!define MINSHORT 0x8000
+!define MAXSHORT 0x7fff
+!define MINLONG 0x80000000
+!define MAXLONG 0x7fffffff
+!define MAXBYTE 0xff
+!define MAXWORD 0xffff
+!define MAXDWORD 0xffffffff
+
+!ifndef WIN32_NO_STATUS
+!define STATUS_WAIT_0 0x00000000
+!define STATUS_ABANDONED_WAIT_0 0x00000080
+!define STATUS_USER_APC 0x000000C0
+!define STATUS_TIMEOUT 0x00000102
+!define STATUS_PENDING 0x00000103
+!define DBG_EXCEPTION_HANDLED 0x00010001
+!define DBG_CONTINUE 0x00010002
+!define STATUS_SEGMENT_NOTIFICATION 0x40000005
+!define DBG_TERMINATE_THREAD 0x40010003
+!define DBG_TERMINATE_PROCESS 0x40010004
+!define DBG_CONTROL_C 0x40010005
+!define DBG_CONTROL_BREAK 0x40010008
+!define DBG_COMMAND_EXCEPTION 0x40010009
+!define STATUS_GUARD_PAGE_VIOLATION 0x80000001
+!define STATUS_DATATYPE_MISALIGNMENT 0x80000002
+!define STATUS_BREAKPOINT 0x80000003
+!define STATUS_SINGLE_STEP 0x80000004
+!define DBG_EXCEPTION_NOT_HANDLED 0x80010001
+!define STATUS_ACCESS_VIOLATION 0xC0000005
+!define STATUS_IN_PAGE_ERROR 0xC0000006
+!define STATUS_INVALID_HANDLE 0xC0000008
+!define STATUS_NO_MEMORY 0xC0000017
+!define STATUS_ILLEGAL_INSTRUCTION 0xC000001D
+!define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
+!define STATUS_INVALID_DISPOSITION 0xC0000026
+!define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C
+!define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D
+!define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E
+!define STATUS_FLOAT_INEXACT_RESULT 0xC000008F
+!define STATUS_FLOAT_INVALID_OPERATION 0xC0000090
+!define STATUS_FLOAT_OVERFLOW 0xC0000091
+!define STATUS_FLOAT_STACK_CHECK 0xC0000092
+!define STATUS_FLOAT_UNDERFLOW 0xC0000093
+!define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
+!define STATUS_INTEGER_OVERFLOW 0xC0000095
+!define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
+!define STATUS_STACK_OVERFLOW 0xC00000FD
+!define STATUS_CONTROL_C_EXIT 0xC000013A
+!define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
+!define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
+!define STATUS_REG_NAT_CONSUMPTION 0xC00002C9
+!define STATUS_SXS_EARLY_DEACTIVATION 0xC015000F
+!define STATUS_SXS_INVALID_DEACTIVATION 0xC0150010
+!endif /*WIN32_NO_STATUS*/
+
+#define MAXIMUM_WAIT_OBJECTS 64
+
+!define DELETE 0x00010000
+!define READ_CONTROL 0x00020000
+!define WRITE_DAC 0x00040000
+!define WRITE_OWNER 0x00080000
+!define SYNCHRONIZE 0x00100000
+!define STANDARD_RIGHTS_REQUIRED 0x000F0000
+!define STANDARD_RIGHTS_READ ${READ_CONTROL}
+!define STANDARD_RIGHTS_WRITE ${READ_CONTROL}
+!define STANDARD_RIGHTS_EXECUTE ${READ_CONTROL}
+!define STANDARD_RIGHTS_ALL 0x001F0000
+!define SPECIFIC_RIGHTS_ALL 0x0000FFFF
+!define ACCESS_SYSTEM_SECURITY 0x01000000
+!define MAXIMUM_ALLOWED 0x02000000
+!define GENERIC_READ 0x80000000
+!define GENERIC_WRITE 0x40000000
+!define GENERIC_EXECUTE 0x20000000
+!define GENERIC_ALL 0x10000000
+
+!define SE_PRIVILEGE_ENABLED_BY_DEFAULT 0x00000001
+!define SE_PRIVILEGE_ENABLED 0x00000002
+!define SE_PRIVILEGE_REMOVED 0x00000004
+!define SE_PRIVILEGE_USED_FOR_ACCESS 0x80000000
+
+!define SE_CREATE_TOKEN_NAME "SeCreateTokenPrivilege"
+!define SE_ASSIGNPRIMARYTOKEN_NAME "SeAssignPrimaryTokenPrivilege"
+!define SE_LOCK_MEMORY_NAME "SeLockMemoryPrivilege"
+!define SE_INCREASE_QUOTA_NAME "SeIncreaseQuotaPrivilege"
+!define SE_UNSOLICITED_INPUT_NAME "SeUnsolicitedInputPrivilege"
+!define SE_MACHINE_ACCOUNT_NAME "SeMachineAccountPrivilege"
+!define SE_TCB_NAME "SeTcbPrivilege"
+!define SE_SECURITY_NAME "SeSecurityPrivilege"
+!define SE_TAKE_OWNERSHIP_NAME "SeTakeOwnershipPrivilege"
+!define SE_LOAD_DRIVER_NAME "SeLoadDriverPrivilege"
+!define SE_SYSTEM_PROFILE_NAME "SeSystemProfilePrivilege"
+!define SE_SYSTEMTIME_NAME "SeSystemtimePrivilege"
+!define SE_PROF_SINGLE_PROCESS_NAME "SeProfileSingleProcessPrivilege"
+!define SE_INC_BASE_PRIORITY_NAME "SeIncreaseBasePriorityPrivilege"
+!define SE_CREATE_PAGEFILE_NAME "SeCreatePagefilePrivilege"
+!define SE_CREATE_PERMANENT_NAME "SeCreatePermanentPrivilege"
+!define SE_BACKUP_NAME "SeBackupPrivilege"
+!define SE_RESTORE_NAME "SeRestorePrivilege"
+!define SE_SHUTDOWN_NAME "SeShutdownPrivilege"
+!define SE_DEBUG_NAME "SeDebugPrivilege"
+!define SE_AUDIT_NAME "SeAuditPrivilege"
+!define SE_SYSTEM_ENVIRONMENT_NAME "SeSystemEnvironmentPrivilege"
+!define SE_CHANGE_NOTIFY_NAME "SeChangeNotifyPrivilege"
+!define SE_REMOTE_SHUTDOWN_NAME "SeRemoteShutdownPrivilege"
+!define SE_UNDOCK_NAME "SeUndockPrivilege"
+!define SE_SYNC_AGENT_NAME "SeSyncAgentPrivilege"
+!define SE_ENABLE_DELEGATION_NAME "SeEnableDelegationPrivilege"
+!define SE_MANAGE_VOLUME_NAME "SeManageVolumePrivilege"
+!define SE_IMPERSONATE_NAME "SeImpersonatePrivilege"
+!define SE_CREATE_GLOBAL_NAME "SeCreateGlobalPrivilege"
+
+!define TOKEN_ASSIGN_PRIMARY 0x0001
+!define TOKEN_DUPLICATE 0x0002
+!define TOKEN_IMPERSONATE 0x0004
+!define TOKEN_QUERY 0x0008
+!define TOKEN_QUERY_SOURCE 0x0010
+!define TOKEN_ADJUST_PRIVILEGES 0x0020
+!define TOKEN_ADJUST_GROUPS 0x0040
+!define TOKEN_ADJUST_DEFAULT 0x0080
+!define TOKEN_ADJUST_SESSIONID 0x0100
+!define TOKEN_ALL_ACCESS_P 0xF00FF
+!define /math TOKEN_ALL_ACCESS ${TOKEN_ALL_ACCESS_P} | ${TOKEN_ADJUST_SESSIONID}
+!define /math TOKEN_READ ${STANDARD_RIGHTS_READ} | ${TOKEN_QUERY}
+!define TOKEN_WRITE 0x200E0 ;(STANDARD_RIGHTS_WRITE|TOKEN_ADJUST_PRIVILEGES|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_DEFAULT)
+!define TOKEN_EXECUTE ${STANDARD_RIGHTS_EXECUTE}
+
+!define PROCESS_TERMINATE 0x0001
+!define PROCESS_CREATE_THREAD 0x0002
+!define PROCESS_SET_SESSIONID 0x0004
+!define PROCESS_VM_OPERATION 0x0008
+!define PROCESS_VM_READ 0x0010
+!define PROCESS_VM_WRITE 0x0020
+!define PROCESS_DUP_HANDLE 0x0040
+!define PROCESS_CREATE_PROCESS 0x0080
+!define PROCESS_SET_QUOTA 0x0100
+!define PROCESS_SET_INFORMATION 0x0200
+!define PROCESS_QUERY_INFORMATION 0x0400
+!define PROCESS_SUSPEND_RESUME 0x0800
+!define PROCESS_ALL_ACCESS 0x1F0FFF ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
+!define THREAD_TERMINATE 0x0001
+!define THREAD_SUSPEND_RESUME 0x0002
+!define THREAD_GET_CONTEXT 0x0008
+!define THREAD_SET_CONTEXT 0x0010
+!define THREAD_SET_INFORMATION 0x0020
+!define THREAD_QUERY_INFORMATION 0x0040
+!define THREAD_SET_THREAD_TOKEN 0x0080
+!define THREAD_IMPERSONATE 0x0100
+!define THREAD_DIRECT_IMPERSONATION 0x0200
+!define THREAD_ALL_ACCESS 0x1F03FF ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
+!define JOB_OBJECT_ASSIGN_PROCESS 0x0001
+!define JOB_OBJECT_SET_ATTRIBUTES 0x0002
+!define JOB_OBJECT_QUERY 0x0004
+!define JOB_OBJECT_TERMINATE 0x0008
+!define JOB_OBJECT_SET_SECURITY_ATTRIBUTES 0x0010
+!define JOB_OBJECT_ALL_ACCESS 0x1F001F ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1F )
+!define EVENT_MODIFY_STATE 0x0002
+!define EVENT_ALL_ACCESS 0x1F0003 ;(STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+!define MUTANT_QUERY_STATE 0x0001
+!define MUTANT_ALL_ACCESS 0x1F0001 ;(STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|MUTANT_QUERY_STATE)
+
+!define FILE_SHARE_READ 0x00000001
+!define FILE_SHARE_WRITE 0x00000002
+!define FILE_SHARE_DELETE 0x00000004
+!define FILE_ATTRIBUTE_READONLY 0x00000001
+!define FILE_ATTRIBUTE_HIDDEN 0x00000002
+!define FILE_ATTRIBUTE_SYSTEM 0x00000004
+!define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+!define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+!define FILE_ATTRIBUTE_DEVICE 0x00000040
+!define FILE_ATTRIBUTE_NORMAL 0x00000080
+!define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+!define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+!define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+!define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+!define FILE_ATTRIBUTE_OFFLINE 0x00001000
+!define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+!define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
+
+!define DUPLICATE_CLOSE_SOURCE 0x00000001
+!define DUPLICATE_SAME_ACCESS 0x00000002
+
+!define VER_PLATFORM_WIN32s 0
+!define VER_PLATFORM_WIN32_WINDOWS 1
+!define VER_PLATFORM_WIN32_NT 2
+
+!ifndef REG_SZ & NSIS_WINDOWS__NO_REGTYPES
+!define REG_NONE 0
+!define REG_SZ 1
+!define REG_EXPAND_SZ 2
+!define REG_BINARY 3
+!define REG_DWORD 4
+!define REG_DWORD_LITTLE_ENDIAN 4
+!define REG_DWORD_BIG_ENDIAN 5
+!define REG_LINK 6
+!define REG_MULTI_SZ 7
+!endif
+
+
+!endif /* __WIN_NOINC_WINNT */
+!verbose pop
+!endif /* __WIN_WINNT__INC */
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinUser.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinUser.nsh
new file mode 100644
index 000000000..7a217c27d
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/Win/WinUser.nsh
@@ -0,0 +1,199 @@
+!ifndef __WIN_WINUSER__INC
+!define __WIN_WINUSER__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_MS_NOUSER & __WIN_NOINC_WINUSER
+
+!ifndef __WIN_MS_NOVIRTUALKEYCODES
+!define VK_LBUTTON 0x01
+!define VK_RBUTTON 0x02
+!define VK_CANCEL 0x03
+!define VK_MBUTTON 0x04 /* NOT contiguous with L & RBUTTON */
+!define VK_XBUTTON1 0x05 /* NOT contiguous with L & RBUTTON */
+!define VK_XBUTTON2 0x06 /* NOT contiguous with L & RBUTTON */
+!define VK_BACK 0x08
+!define VK_TAB 0x09
+!define VK_CLEAR 0x0C
+!define VK_RETURN 0x0D
+!define VK_SHIFT 0x10
+!define VK_CONTROL 0x11
+!define VK_MENU 0x12
+!define VK_PAUSE 0x13
+!define VK_CAPITAL 0x14
+!define VK_ESCAPE 0x1B
+!define VK_CONVERT 0x1C
+!define VK_NONCONVERT 0x1D
+!define VK_ACCEPT 0x1E
+!define VK_MODECHANGE 0x1F
+!define VK_SPACE 0x20
+!define VK_PRIOR 0x21
+!define VK_NEXT 0x22
+!define VK_END 0x23
+!define VK_HOME 0x24
+!define VK_LEFT 0x25
+!define VK_UP 0x26
+!define VK_RIGHT 0x27
+!define VK_DOWN 0x28
+!define VK_SELECT 0x29
+!define VK_PRINT 0x2A
+!define VK_EXECUTE 0x2B
+!define VK_SNAPSHOT 0x2C
+!define VK_INSERT 0x2D
+!define VK_DELETE 0x2E
+!define VK_HELP 0x2F
+; VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+; VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+!define VK_LWIN 0x5B
+!define VK_RWIN 0x5C
+!define VK_APPS 0x5D
+!define VK_SLEEP 0x5F
+!define VK_NUMPAD0 0x60
+!define VK_NUMPAD1 0x61
+!define VK_NUMPAD2 0x62
+!define VK_NUMPAD3 0x63
+!define VK_NUMPAD4 0x64
+!define VK_NUMPAD5 0x65
+!define VK_NUMPAD6 0x66
+!define VK_NUMPAD7 0x67
+!define VK_NUMPAD8 0x68
+!define VK_NUMPAD9 0x69
+!define VK_MULTIPLY 0x6A
+!define VK_ADD 0x6B
+!define VK_SEPARATOR 0x6C
+!define VK_SUBTRACT 0x6D
+!define VK_DECIMAL 0x6E
+!define VK_DIVIDE 0x6F
+!define VK_F1 0x70
+!define VK_F2 0x71
+!define VK_F3 0x72
+!define VK_F4 0x73
+!define VK_F5 0x74
+!define VK_F6 0x75
+!define VK_F7 0x76
+!define VK_F8 0x77
+!define VK_F9 0x78
+!define VK_F10 0x79
+!define VK_F11 0x7A
+!define VK_F12 0x7B
+!define VK_NUMLOCK 0x90
+!define VK_SCROLL 0x91
+!define VK_OEM_NEC_EQUAL 0x92 ; '=' key on numpad
+!define VK_LSHIFT 0xA0
+!define VK_RSHIFT 0xA1
+!define VK_LCONTROL 0xA2
+!define VK_RCONTROL 0xA3
+!define VK_LMENU 0xA4
+!define VK_RMENU 0xA5
+!endif
+
+!ifndef __WIN_MS_NOWINOFFSETS
+/* in nsDialogs.nsh...
+!define GWL_STYLE -16
+!define GWL_EXSTYLE -20 */
+!define GWLP_WNDPROC -4
+!define GWLP_HINSTANCE -6
+!define GWLP_HWNDPARENT -8
+!define GWLP_USERDATA -21
+!define GWLP_ID -12
+!define DWLP_MSGRESULT 0
+!define /math DWLP_DLGPROC ${DWLP_MSGRESULT} + ${__WIN_PTRSIZE} ;DWLP_MSGRESULT + sizeof(LRESULT)
+!define /math DWLP_USER ${DWLP_DLGPROC} + ${__WIN_PTRSIZE} ;DWLP_DLGPROC + sizeof(DLGPROC)
+!endif
+
+!ifndef __WIN_MS_NONCMESSAGES
+!define HTERROR -2
+!define HTTRANSPARENT -1
+!define HTNOWHERE 0
+!define HTCLIENT 1
+!define HTCAPTION 2
+!define HTSYSMENU 3
+!define HTGROWBOX 4
+!define HTSIZE ${HTGROWBOX}
+!define HTMENU 5
+!define HTHSCROLL 6
+!define HTVSCROLL 7
+!define HTMINBUTTON 8
+!define HTMAXBUTTON 9
+!define HTLEFT 10
+!define HTRIGHT 11
+!define HTTOP 12
+!define HTTOPLEFT 13
+!define HTTOPRIGHT 14
+!define HTBOTTOM 15
+!define HTBOTTOMLEFT 16
+!define HTBOTTOMRIGHT 17
+!define HTBORDER 18
+!define HTREDUCE ${HTMINBUTTON}
+!define HTZOOM ${HTMAXBUTTON}
+!define HTSIZEFIRST ${HTLEFT}
+!define HTSIZELAST ${HTBOTTOMRIGHT}
+!define HTOBJECT 19
+!define HTCLOSE 20
+!define HTHELP 21
+!endif
+
+!ifndef __WIN_MS_NOSYSCOMMANDS
+!define SC_SIZE 0xF000
+!define SC_MOVE 0xF010
+!define SC_MINIMIZE 0xF020
+!define SC_MAXIMIZE 0xF030
+!define SC_NEXTWINDOW 0xF040
+!define SC_PREVWINDOW 0xF050
+!define SC_CLOSE 0xF060
+!define SC_VSCROLL 0xF070
+!define SC_HSCROLL 0xF080
+!define SC_MOUSEMENU 0xF090
+!define SC_KEYMENU 0xF100
+!define SC_ARRANGE 0xF110
+!define SC_RESTORE 0xF120
+!define SC_TASKLIST 0xF130
+!define SC_SCREENSAVE 0xF140
+!define SC_HOTKEY 0xF150
+!define SC_DEFAULT 0xF160
+!define SC_MONITORPOWER 0xF170
+!define SC_CONTEXTHELP 0xF180
+!define SC_SEPARATOR 0xF00F
+!endif
+
+!define IDC_ARROW 32512
+!define IDC_IBEAM 32513
+!define IDC_WAIT 32514
+!define IDC_CROSS 32515
+!define IDC_UPARROW 32516
+!define IDC_SIZENWSE 32642
+!define IDC_SIZENESW 32643
+!define IDC_SIZEWE 32644
+!define IDC_SIZENS 32645
+!define IDC_SIZEALL 32646
+!define IDC_NO 32648
+!define IDC_HAND 32649
+!define IDC_APPSTARTING 32650
+!define IDC_HELP 32651
+
+/* in nsDialogs.nsh...
+!define IMAGE_BITMAP 0
+!define IMAGE_ICON 1
+!define IMAGE_CURSOR 2*/
+
+/* in nsDialogs.nsh...
+!define LR_DEFAULTCOLOR 0x0000
+!define LR_MONOCHROME 0x0001
+!define LR_COLOR 0x0002
+!define LR_COPYRETURNORG 0x0004
+!define LR_COPYDELETEORG 0x0008
+!define LR_LOADFROMFILE 0x0010
+!define LR_LOADTRANSPARENT 0x0020
+!define LR_DEFAULTSIZE 0x0040
+!define LR_VGACOLOR 0x0080
+!define LR_LOADMAP3DCOLORS 0x1000
+!define LR_CREATEDIBSECTION 0x2000
+!define LR_COPYFROMRESOURCE 0x4000
+!define LR_SHARED 0x8000*/
+
+!define GA_PARENT 1
+!define GA_ROOT 2
+!define GA_ROOTOWNER 3
+
+!endif /* __WIN_MS_NOUSER & __WIN_NOINC_WINUSER */
+!verbose pop
+!endif /* __WIN_WINUSER__INC */
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinCore.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinCore.nsh
new file mode 100644
index 000000000..6767847fe
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinCore.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinMessages.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinMessages.nsh
new file mode 100644
index 000000000..cbfb54a8b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinMessages.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinVer.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinVer.nsh
new file mode 100644
index 000000000..91640c6e7
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WinVer.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WordFunc.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WordFunc.nsh
new file mode 100644
index 000000000..875a00b65
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/WordFunc.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/dialogs.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/dialogs.nsh
new file mode 100644
index 000000000..555b0226d
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/dialogs.nsh
@@ -0,0 +1,56 @@
+# "Dialogs header file by Joel Almeida Garca"
+
+#include once this header file
+!ifndef DIALOGS_NSH
+ !define DIALOGS_NSH
+ !verbose push
+ !verbose 3
+
+ !ifndef LOGICLIB
+ #Add logic library
+ !include "LogicLib.nsh"
+ !endif
+
+ # Global stuff
+ !define ISTRUE 1
+ !define ISFALSE 0
+ !define NULL ""
+
+ # Returning Vars
+ !define VAR_0 0 # $0
+ !define VAR_1 1 # $1
+ !define VAR_2 2 # $2
+ !define VAR_3 3 # $3
+ !define VAR_4 4 # $4
+ !define VAR_5 5 # $5
+ !define VAR_6 6 # $6
+ !define VAR_7 7 # $7
+ !define VAR_8 8 # $8
+ !define VAR_9 9 # $9
+ !define VAR_R0 10 # $R0
+ !define VAR_R1 11 # $R1
+ !define VAR_R2 12 # $R2
+ !define VAR_R3 13 # $R3
+ !define VAR_R4 14 # $R4
+ !define VAR_R5 15 # $R5
+ !define VAR_R6 16 # $R6
+ !define VAR_R7 17 # $R7
+ !define VAR_R8 18 # $R8
+ !define VAR_R9 19 # $R9
+ !define VAR_CMDLINE 20 # $CMDLINE
+ !define VAR_INSTDIR 21 # $INSTDIR
+ !define VAR_OUTDIR 22 # $OUTDIR
+ !define VAR_EXEDIR 23 # $EXEDIR
+ !define VAR_LANG 24 # $LANGUAGE
+
+ # Function prototypes
+ !define OpenBox 'dialogsEx::FileBox ""'
+ !define SaveBox 'dialogsEx::FileBox "1"'
+ !define ClassicFolderBox 'dialogsEx::FolderBox ""'
+ !define ModernFolderBox 'dialogsEx::FolderBox "1"'
+ !define InputTextBox 'dialogsEx::InputBox ""'
+ !define InputPwdBox 'dialogsEx::InputBox "1"'
+ !define InputRegBox 'dialogsEx::InputRegBox'
+
+ !verbose pop
+!endif
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/nsDialogs.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/nsDialogs.nsh
new file mode 100644
index 000000000..ef4e17861
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/nsDialogs.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/x64.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/x64.nsh
new file mode 100644
index 000000000..5f78a1d91
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Include/x64.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/AdvSplash.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/AdvSplash.dll
new file mode 100644
index 000000000..9d40006fb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/AdvSplash.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Banner.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Banner.dll
new file mode 100644
index 000000000..7cbc3a1d9
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Banner.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/BgImage.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/BgImage.dll
new file mode 100644
index 000000000..d79334f97
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/BgImage.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Dialer.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Dialer.dll
new file mode 100644
index 000000000..4d163e1fd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Dialer.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EmbeddedLists.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EmbeddedLists.dll
new file mode 100644
index 000000000..5a27af02b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EmbeddedLists.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EnumINI.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EnumINI.dll
new file mode 100644
index 000000000..168cc5053
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/EnumINI.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/FindProcDLL.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/FindProcDLL.dll
new file mode 100644
index 000000000..22c8398f1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/FindProcDLL.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/InstallOptions.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/InstallOptions.dll
new file mode 100644
index 000000000..b6de1b684
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/InstallOptions.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/KillProcDLL.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/KillProcDLL.dll
new file mode 100644
index 000000000..8119afa2b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/KillProcDLL.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/LangDLL.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/LangDLL.dll
new file mode 100644
index 000000000..35b0b4611
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/LangDLL.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Math.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Math.dll
new file mode 100644
index 000000000..d5a6d4e52
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Math.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/MoreInfo.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/MoreInfo.dll
new file mode 100644
index 000000000..274d98198
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/MoreInfo.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/NSISdl.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/NSISdl.dll
new file mode 100644
index 000000000..5747dc6b6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/NSISdl.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/RealProgress.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/RealProgress.dll
new file mode 100644
index 000000000..12292166b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/RealProgress.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/SelfDel.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/SelfDel.dll
new file mode 100644
index 000000000..3cb288c2d
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/SelfDel.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Splash.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Splash.dll
new file mode 100644
index 000000000..bd1ec597c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/Splash.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/StartMenu.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/StartMenu.dll
new file mode 100644
index 000000000..0f69f3a98
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/StartMenu.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/System.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/System.dll
new file mode 100644
index 000000000..19a876efe
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/System.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/TypeLib.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/TypeLib.dll
new file mode 100644
index 000000000..b4440fdf3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/TypeLib.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/UserInfo.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/UserInfo.dll
new file mode 100644
index 000000000..586871cdb
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/UserInfo.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/VPatch.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/VPatch.dll
new file mode 100644
index 000000000..af1b4e69f
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/VPatch.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/dialogsEx.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/dialogsEx.dll
new file mode 100644
index 000000000..0a582159b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/dialogsEx.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/execDos.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/execDos.dll
new file mode 100644
index 000000000..0234253e6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/execDos.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/inetc.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/inetc.dll
new file mode 100644
index 000000000..f35cd6a08
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/inetc.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/md5dll.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/md5dll.dll
new file mode 100644
index 000000000..d265788b1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/md5dll.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newadvsplash.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newadvsplash.dll
new file mode 100644
index 000000000..5e58c3917
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newadvsplash.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newtextreplace.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newtextreplace.dll
new file mode 100644
index 000000000..206dc2c64
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/newtextreplace.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsDialogs.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsDialogs.dll
new file mode 100644
index 000000000..1f142a27b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsDialogs.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsExec.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsExec.dll
new file mode 100644
index 000000000..788bfe377
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/nsExec.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/registry.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/registry.dll
new file mode 100644
index 000000000..180598051
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/registry.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/w7tbp.dll b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/w7tbp.dll
new file mode 100644
index 000000000..0b71718ce
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Plugins/w7tbp.dll differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2 b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2
new file mode 100644
index 000000000..0a63d0556
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2 differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2_solid b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2_solid
new file mode 100644
index 000000000..313d679f6
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/bzip2_solid differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma
new file mode 100644
index 000000000..a4038f9fa
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma_solid b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma_solid
new file mode 100644
index 000000000..f992aec84
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/lzma_solid differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/uninst b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/uninst
new file mode 100644
index 000000000..90d7d2252
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/uninst differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib
new file mode 100644
index 000000000..ad55bb1dd
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib_solid b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib_solid
new file mode 100644
index 000000000..5855cff84
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/Stubs/zlib_solid differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/makensis.exe b/Greenshot/tools/PortableApps.comInstaller/App/nsis/makensis.exe
new file mode 100644
index 000000000..6845bb2ca
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/makensis.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/App/nsis/nsisconf.nsh b/Greenshot/tools/PortableApps.comInstaller/App/nsis/nsisconf.nsh
new file mode 100644
index 000000000..ded5b9aa3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/App/nsis/nsisconf.nsh differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Data/settings.ini b/Greenshot/tools/PortableApps.comInstaller/Data/settings.ini
new file mode 100644
index 000000000..8a4e3981d
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Data/settings.ini
@@ -0,0 +1 @@
+[InstallerWizard]
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/donation_button.png b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/donation_button.png
new file mode 100644
index 000000000..f19dea7a1
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/donation_button.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/favicon.ico b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/favicon.ico
new file mode 100644
index 000000000..ed849b2de
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/favicon.ico differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_footer.png b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_footer.png
new file mode 100644
index 000000000..5ebdc028c
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_footer.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_header.png b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_header.png
new file mode 100644
index 000000000..cf1ebf762
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_background_header.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_logo_top.png b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_logo_top.png
new file mode 100644
index 000000000..1a705050e
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Help/images/help_logo_top.png differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizard.nsi b/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizard.nsi
new file mode 100644
index 000000000..6432f87a6
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizard.nsi
@@ -0,0 +1,1141 @@
+;Copyright (C) 2006-2013 John T. Haller
+
+;Website: http://PortableApps.com/Installer
+
+;This software is OSI Certified Open Source Software.
+;OSI Certified is a certification mark of the Open Source Initiative.
+
+;This program is free software; you can redistribute it and/or
+;modify it under the terms of the GNU General Public License
+;as published by the Free Software Foundation; either version 2
+;of the License, or (at your option) any later version.
+
+;This program is distributed in the hope that it will be useful,
+;but WITHOUT ANY WARRANTY; without even the implied warranty of
+;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;GNU General Public License for more details.
+
+;You should have received a copy of the GNU General Public License
+;along with this program; if not, write to the Free Software
+;Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+!define APPNAME "PortableApps.com Installer"
+!define VER "3.0.6.0"
+!define WEBSITE "PortableApps.com/Installer"
+!define FRIENDLYVER "3.0.6"
+!define PORTABLEAPPS.COMFORMATVERSION "3.0"
+
+;=== Program Details
+Name "${APPNAME}"
+OutFile "..\..\PortableApps.comInstaller.exe"
+Caption "${APPNAME}"
+VIProductVersion "${VER}"
+VIAddVersionKey ProductName "${APPNAME}"
+VIAddVersionKey Comments "For additional details, visit ${WEBSITE}"
+VIAddVersionKey CompanyName "PortableApps.com"
+VIAddVersionKey LegalCopyright "John T. Haller"
+VIAddVersionKey FileDescription "${APPNAME}"
+VIAddVersionKey FileVersion "${VER}"
+VIAddVersionKey ProductVersion "${VER}"
+VIAddVersionKey InternalName "${APPNAME}"
+VIAddVersionKey LegalTrademarks "PortableApps.com is a trademark of Rare Ideas, LLC."
+VIAddVersionKey OriginalFilename "PortableApps.comInstaller.exe"
+
+;=== Runtime Switches
+CRCCheck On
+RequestExecutionLevel user
+
+; Best Compression
+SetCompress Auto
+SetCompressor /SOLID lzma
+SetCompressorDictSize 32
+SetDatablockOptimize On
+
+;=== Include
+;(Standard)
+!include WordFunc.nsh
+!insertmacro WordReplace
+!include FileFunc.nsh
+!insertmacro GetFileName
+!insertmacro GetParameters
+!insertmacro GetParent
+!insertmacro GetSize
+!include LogicLib.nsh
+!include MUI.nsh
+
+;(Addons)
+!include dialogs.nsh
+
+;(Custom)
+!include MoveFiles.nsh
+!include ReadINIStrWithDefault.nsh
+!include TBProgress.nsh
+
+;=== Icon & Stye ===
+!define MUI_ICON "..\..\App\AppInfo\appicon.ico"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_RIGHT
+!define MUI_HEADERIMAGE_BITMAP header.bmp
+!define MUI_HEADERIMAGE_BITMAP_RTL header_rtl.bmp
+
+BrandingText "PortableApps.com®"
+InstallButtonText "Go >"
+ShowInstDetails show
+SubCaption 3 " | Processing Files"
+
+;=== Variables
+Var FINISHTEXT
+Var FINISHTITLE
+Var INSTALLAPPDIRECTORY
+Var SKIPWELCOMEPAGE
+Var AUTOMATICCOMPILE
+
+Var INCLUDESOURCE
+Var PORTABLEAPPNAME
+Var PORTABLEAPPNAMEDOUBLEDAMPERSANDS
+Var PLUGINNAME
+Var APPID
+Var SHORTNAME
+Var APPLANGUAGE
+Var ALLLANGUAGES
+Var INSTALLERFILENAME
+Var OPTIONALCOMPONENTS
+Var DISPLAYVERSION
+Var COMMONFILESPLUGIN
+Var USEEXTRACTEDICON
+Var INTERACTIVEMODE
+Var EULAVERSION
+
+Var ERROROCCURED
+
+Var AppInfoINIFile
+Var InstallerINIFile
+Var PluginInstaller
+Var OptionalSectionSelectedInstallType
+
+;=== Pages
+!define MUI_WELCOMEFINISHPAGE_BITMAP welcomefinish.bmp
+!define MUI_WELCOMEPAGE_TITLE "PortableApps.com Installer ${FRIENDLYVER}"
+!define MUI_WELCOMEPAGE_TEXT "Welcome to the PortableApps.com Installer.\r\n\r\nThis utility allows you to create a PortableApps.com Installer package for an app in PortableApps.com Format. Just click next and select the application to package.\r\n\r\nLICENSE: The PortableApps.com Installer can be used with open source and freeware apps provided the installer is unmodified and the app adheres to the current PortableApps.com Format Specification as published at PortableApps.com/development. It may also be used with commercial software by contacting PortableApps.com."
+!define MUI_PAGE_CUSTOMFUNCTION_PRE ShowWelcomeWindow
+!insertmacro MUI_PAGE_WELCOME
+Page custom ShowOptionsWindow LeaveOptionsWindow " | Portable App Folder Selection"
+!insertmacro MUI_PAGE_INSTFILES
+!define MUI_PAGE_CUSTOMFUNCTION_PRE ShowFinishPage
+!define MUI_FINISHPAGE_TITLE "$FINISHTITLE"
+!define MUI_FINISHPAGE_TEXT "$FINISHTEXT"
+!define MUI_FINISHPAGE_RUN
+!define MUI_FINISHPAGE_RUN_NOTCHECKED
+!define MUI_FINISHPAGE_RUN_TEXT "Test Installer"
+!define MUI_FINISHPAGE_RUN_FUNCTION "RunOnFinish"
+!define MUI_FINISHPAGE_SHOWREADME "$EXEDIR\Data\PortableApps.comInstallerLog.txt"
+!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
+!define MUI_FINISHPAGE_SHOWREADME_TEXT "View log file"
+!define MUI_FINISHPAGE_CANCEL_ENABLED
+!insertmacro MUI_PAGE_FINISH
+
+;=== Languages
+!insertmacro MUI_LANGUAGE "English"
+
+Function .onInit
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "InstallerWizardForm.ini"
+
+ ;=== Check for settings.ini
+ ${IfNot} ${FileExists} $EXEDIR\Data\settings.ini
+ CreateDirectory $EXEDIR\Data
+ CopyFiles /SILENT $EXEDIR\App\DefaultData\settings.ini $EXEDIR\Data
+ ${EndIf}
+
+ ; Get settings
+ ReadINIStr $SKIPWELCOMEPAGE "$EXEDIR\Data\settings.ini" "InstallerWizard" "SkipWelcomePage"
+ ReadINIStr $INSTALLAPPDIRECTORY "$EXEDIR\Data\settings.ini" "InstallerWizard" "INSTALLAPPDIRECTORY"
+
+ ${GetParameters} $R0
+ ${If} $R0 != ""
+ StrCpy $INSTALLAPPDIRECTORY $R0
+ StrCpy $SKIPWELCOMEPAGE "true"
+ StrCpy $AUTOMATICCOMPILE "true"
+ ;Strip quotes from $INSTALLAPPDIRECTORY
+ StrCpy $R0 $INSTALLAPPDIRECTORY 1
+ ${If} $R0 == `"`
+ StrCpy $INSTALLAPPDIRECTORY $INSTALLAPPDIRECTORY "" 1
+ StrCpy $INSTALLAPPDIRECTORY $INSTALLAPPDIRECTORY -1
+ ${EndIf}
+ ${EndIf}
+
+ ;=== Pre-Fill Path with Directory
+ WriteINIStr $PLUGINSDIR\InstallerWizardForm.ini "Field 2" "State" "$INSTALLAPPDIRECTORY"
+FunctionEnd
+
+Function ShowWelcomeWindow
+ ${If} $SKIPWELCOMEPAGE == "true"
+ Abort
+ ${EndIf}
+FunctionEnd
+
+Function ShowOptionsWindow
+ !insertmacro MUI_HEADER_TEXT "PortableApps.com Installer ${FRIENDLYVER}" "the open portable software standard"
+ ${If} $AUTOMATICCOMPILE == "true"
+ ${If} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\installer.ini"
+ StrCpy $PluginInstaller "false"
+ Abort
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $PluginInstaller "true"
+ Abort
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\plugininstaller.ini"
+ CreateDirectory "$INSTALLAPPDIRECTORY\App"
+ CreateDirectory "$INSTALLAPPDIRECTORY\App\AppInfo"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\plugininstaller.ini" "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $PluginInstaller "true"
+ Abort
+ ${EndIf}
+ ${EndIf}
+ ${ReadINIStrWithDefault} $INTERACTIVEMODE "$EXEDIR\Data\settings.ini" "InstallerWizard" "InteractiveMode" "1"
+ WriteINIStr "$PLUGINSDIR\InstallerWizardForm.ini" "Field 3" "State" "$INTERACTIVEMODE"
+ InstallOptions::InitDialog /NOUNLOAD "$PLUGINSDIR\InstallerWizardForm.ini"
+ Pop $0
+ InstallOptions::Show
+FunctionEnd
+
+Function LeaveOptionsWindow
+ ;=== Blank
+ ReadINIStr $INSTALLAPPDIRECTORY $PLUGINSDIR\InstallerWizardForm.ini "Field 2" "State"
+ ReadINIStr $INTERACTIVEMODE "$PLUGINSDIR\InstallerWizardForm.ini" "Field 3" "State"
+
+ StrCmp $INSTALLAPPDIRECTORY "" NoInstallAppDirectoryError
+ ${If} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\installer.ini"
+ StrCpy $PluginInstaller "false"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $PluginInstaller "true"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\plugininstaller.ini"
+ CreateDirectory "$INSTALLAPPDIRECTORY\App"
+ CreateDirectory "$INSTALLAPPDIRECTORY\App\AppInfo"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\plugininstaller.ini" "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $AppInfoINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $InstallerINIFile "$INSTALLAPPDIRECTORY\App\AppInfo\plugininstaller.ini"
+ StrCpy $PluginInstaller "true"
+ ${ElseIf} $INTERACTIVEMODE = 1
+ ; No AppInfo found
+ ${IfNot} ${FileExists} "$INSTALLAPPDIRECTORY\*.exe"
+ ${AndIf} $PluginInstaller != "true"
+ Goto NoInstallAppDirectoryError
+ ${EndIf}
+
+ MessageBox MB_ICONQUESTION|MB_YESNO "The app does not appear to have the necessary files within the App\AppInfo directory required by PortableApps.com Format. Would you like to create the settings interactively and use a set of default icons for now for testing?" IDNO NoInstallAppDirectoryError
+
+ ;Find EXE file
+ FindFirst $2 $3 "$INSTALLAPPDIRECTORY\*.exe"
+ StrCpy $4 0
+
+ ${DoWhile} $3 != ""
+ StrCpy $5 $3
+ IntOp $4 $4 + 1
+ FindNext $2 $3
+ ${Loop}
+ FindClose $2
+
+ ${If} $4 > 1
+ MessageBox MB_OK|MB_ICONEXCLAMATION `Multiple EXEs were found in the directory you selected. The PortableApps.com Installer can only generate default information for applications with a single EXE. Please review the information at PortableApps.com/development for details on creating the configuration files.`
+ Abort
+ ${EndIf}
+
+ CreateDirectory "$INSTALLAPPDIRECTORY\App\AppInfo"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\appicon_16.png" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\appicon_32.png" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\appicon.ico" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\appinfo.ini" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ WriteINIStr "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini" "Format" "Version" "${PORTABLEAPPS.COMFORMATVERSION}"
+ WriteINIStr "$INSTALLAPPDIRECTORY\App\AppInfo\appinfo.ini" "Control" "Start" "$5"
+
+ MessageBox MB_ICONINFORMATION "Before releasing this application, please be sure to create a set of proper icons in App\AppInfo."
+ ${Else}
+ Goto NoInstallAppDirectoryError
+ ${EndIf}
+
+ ; Store settings
+ WriteINIStr "$EXEDIR\Data\settings.ini" "InstallerWizard" "INSTALLAPPDIRECTORY" $INSTALLAPPDIRECTORY
+ WriteINIStr "$EXEDIR\Data\settings.ini" "InstallerWizard" "InteractiveMode" $INTERACTIVEMODE
+ Goto EndLeaveOptionsWindow
+
+ NoInstallAppDirectoryError:
+ MessageBox MB_OK|MB_ICONEXCLAMATION `Please select a valid portable app's base directory to create an installer for.`
+ Abort
+
+ EndLeaveOptionsWindow:
+FunctionEnd
+
+!define SetIndividualLanguage "!insertmacro SetIndividualLanguage"
+
+!define WriteConfig "!insertmacro WriteConfig"
+
+!macro WriteConfig Variable Value
+ FileWriteUTF16LE $0 `!define ${Variable} "${Value}"$\r$\n`
+!macroend
+
+!macro SetIndividualLanguage IndividualLanguage
+ StrCpy $2 "${IndividualLanguage}"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "Languages" "$2" "false"
+ ${If} $1 == "true"
+ ${OrIf} $ALLLANGUAGES == "true"
+ ${WriteConfig} USES_$2 "true"
+ ${EndIf}
+!macroend
+
+!define WriteErrorToLog "!insertmacro WriteErrorToLog"
+
+!macro WriteErrorToLog ErrorToWrite
+ FileOpen $9 "$EXEDIR\Data\PortableApps.comInstallerLog.txt" a
+ FileSeek $9 0 END
+ FileWriteUTF16LE $9 `ERROR: ${ErrorToWrite}$\r$\n`
+ FileClose $9
+ StrCpy $ERROROCCURED "true"
+!macroend
+
+!define TransferInstallerINIToConfig "!insertmacro TransferInstallerINIToConfig"
+
+!macro TransferInstallerINIToConfig Section Key Required
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile ${Section} ${Key} ""
+ ${If} $1 != ""
+ ${WriteConfig} ${Key} "$1"
+ !if ${Required} == required
+ ${Else}
+ ${WriteErrorToLog} "Installer.ini - ${Section} - ${Key} is missing."
+ !endif
+ ${EndIf}
+!macroend
+
+Section Main
+ !insertmacro MUI_HEADER_TEXT "PortableApps.com Installer ${FRIENDLYVER}" "the open portable software standard"
+ ${TBProgress} 33
+ SetDetailsPrint ListOnly
+ DetailPrint "App: $INSTALLAPPDIRECTORY"
+ DetailPrint " "
+ ;FindWindow $0 "#32770" "" $HWNDPARENT
+ ;FindWindow $1 "msctls_progress32" "" $0
+
+ ;DetailPrint "Hanlde: $1"
+ RealProgress::SetProgress /NOUNLOAD 1
+ RealProgress::GradualProgress /NOUNLOAD 2 1 90 "Processing complete."
+ DetailPrint "Generating installer code..."
+ SetDetailsPrint none
+
+ ;Ensure the source directory exists
+ CreateDirectory "$INSTALLAPPDIRECTORY\Other\Source"
+
+ ;Remove any existing installer files (leaving custom intact)
+ RMDir /r "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerLanguages"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.ico"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.nsi"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig-EXAMPLE.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerDumpLogToFile.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerHeader.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerMoveFiles.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerStrRep.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerHeaderRTL.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPlugin.nsi"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPluginConfig.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerTBProgress.nsh"
+
+ ;Copy the current PortableApps.com Installer in
+ CopyFiles /SILENT "$EXEDIR\App\installer\*.*" "$INSTALLAPPDIRECTORY\Other\Source"
+ ${If} $PluginInstaller == "true"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.nsi" "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPlugin.nsi"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig.nsh" "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPluginConfig.nsh"
+ ${EndIf}
+
+ ;Generate the configuration file
+ Delete "$EXEDIR\Data\PortableApps.comInstallerLog.txt"
+
+ ;Determine icon type
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "Control" "ExtractIcon" ""
+ ${If} $1 != ""
+ StrCpy $USEEXTRACTEDICON "true"
+ ${EndIf}
+
+ ;Check for content
+ ${IfNot} ${FileExists} "$INSTALLAPPDIRECTORY\*.exe"
+ ${AndIf} $PluginInstaller != "true"
+ ${WriteErrorToLog} "No EXE in $INSTALLAPPDIRECTORY."
+ ${EndIf}
+
+ ${IfNot} ${FileExists} "$INSTALLAPPDIRECTORY\help.html"
+ ${AndIf} $PluginInstaller != "true"
+ ${WriteErrorToLog} "No help.html in $INSTALLAPPDIRECTORY."
+ ${EndIf}
+
+ !macro AppInfoFileMissingAskInsertDefault FileName FileDescription
+ ${IfNot} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\${FileName}"
+ ${AndIf} $PluginInstaller != "true"
+ ${If} $USEEXTRACTEDICON == "true"
+ !if ${FileName} == appicon.ico
+ ;Copy the default icon in (appicon_*.png don't get included)
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\${FileName}" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ !endif
+ ${ElseIf} $INTERACTIVEMODE = 1
+ ${AndIf} ${Cmd} ${|} MessageBox MB_ICONQUESTION|MB_YESNO "The app does not have ${FileDescription} (${FileName}) in the App\AppInfo directory. Would you like to use a default icon for test purposes for now?" IDYES ${|}
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\${FileName}" "$INSTALLAPPDIRECTORY\App\AppInfo"
+ MessageBox MB_ICONINFORMATION "Before releasing this application, please be sure to create a proper ${FileName} app icon in App\AppInfo."
+ ${Else}
+ ${WriteErrorToLog} "No ${FileName} in $INSTALLAPPDIRECTORY\App\AppInfo."
+ ${EndIf}
+ ${EndIf}
+ !macroend
+
+ !insertmacro AppInfoFileMissingAskInsertDefault appicon_16.png "a 16x16 PNG icon"
+ !insertmacro AppInfoFileMissingAskInsertDefault appicon_32.png "a 32x32 PNG icon"
+ !insertmacro AppInfoFileMissingAskInsertDefault appicon.ico "an icon"
+
+ ${If} $PluginInstaller == "true"
+ FileOpen $0 "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPluginConfig.nsh" a
+ ${Else}
+ FileOpen $0 "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig.nsh" a
+ ${EndIf}
+ FileSeek $0 0 END
+ FileWriteUTF16LE $0 `;Code generated by PortableApps.com Installer ${FRIENDLYVER}. DO NOT EDIT.$\r$\n$\r$\n`
+
+ ;PortableApps.comFormat Version
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "Format" "Version" ""
+ ${If} $1 == "0.9.8"
+ ;Preserve old installer config in case it's needed
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig.nsh" "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfigOld.nsh"
+
+ ;Autogenerate App ID is handled normally when interactive
+
+ ;Language selection is handled normally when in interactive
+
+ ;This brings it up to 0.90
+ StrCpy $1 "0.90"
+ ${EndIf}
+ ${If} $1 == "0.90"
+ ;0.90 to 0.91 needs no changes, so it brings it to 0.91
+ StrCpy $1 "0.91"
+ ${EndIf}
+ ${If} $1 == "0.91"
+ ;0.91 to 1.0 needs no changes, so it brings it to 1.0
+ StrCpy $1 "1.0"
+ ${EndIf}
+ ${If} $1 == "1.0"
+ ${OrIf} $1 == "2.0"
+ ;1.0 to 2.0 needs no changes, so it brings it to 2.0
+ WriteINIStr $AppInfoINIFile "Format" "Version" "${PORTABLEAPPS.COMFORMATVERSION}"
+ ${EndIf}
+
+ !macro GetValueFromAppInfo Section Key Prompt DefaultValue Variable Required
+ ReadINIStr ${Variable} $AppInfoINIFile ${Section} ${Key}
+ ${If} ${Variable} == ""
+ ${If} $INTERACTIVEMODE = 1
+ ${InputTextBox} "${APPNAME}" "${Prompt}" "${DefaultValue}" "255" "OK" "Cancel" 9
+ ${If} $9 != ""
+ StrCpy ${Variable} $9
+ WriteINIStr $AppInfoINIFile ${Section} ${Key} $9
+ !if ${Required} == required
+ ${Else}
+ ${WriteErrorToLog} "AppInfo.ini - ${Section} - ${Key} is missing."
+ !endif
+ ${EndIf}
+ !if ${Required} == required
+ ${Else}
+ ${WriteErrorToLog} "AppInfo.ini - ${Section} - ${Key} is missing."
+ !endif
+ ${EndIf}
+ ${EndIf}
+ !macroend
+
+ ;App Name
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Name \
+ "Enter the portable app's name (e.g. FileZilla Portable):" \
+ "AppName Portable" \
+ $PORTABLEAPPNAME \
+ required
+
+ ${If} $PluginInstaller != "true"
+ ${WriteConfig} PORTABLEAPPNAME "$PORTABLEAPPNAME"
+ ${WordReplace} $PORTABLEAPPNAME "&" "~~~@@@~~~" + $PORTABLEAPPNAMEDOUBLEDAMPERSANDS
+ ${WordReplace} $PORTABLEAPPNAMEDOUBLEDAMPERSANDS "~~~@@@~~~" "&&" + $PORTABLEAPPNAMEDOUBLEDAMPERSANDS
+ ${WriteConfig} PORTABLEAPPNAMEDOUBLEDAMPERSANDS "$PORTABLEAPPNAMEDOUBLEDAMPERSANDS"
+ ${EndIf}
+
+ ;Plugin Name
+ ${If} $PluginInstaller == "true"
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ PluginName \
+ "Enter the plugin's name (e.g. Acme Plugin):" \
+ "Plugin" \
+ $PLUGINNAME \
+ required
+
+ ${WriteConfig} PLUGINNAME "$PLUGINNAME"
+ ${WriteConfig} PORTABLEAPPNAME "$PLUGINNAME"
+ ${WordReplace} $PLUGINNAME "&" "~~~@@@~~~" + $PORTABLEAPPNAMEDOUBLEDAMPERSANDS
+ ${WordReplace} $PORTABLEAPPNAMEDOUBLEDAMPERSANDS "~~~@@@~~~" "&&" + $PORTABLEAPPNAMEDOUBLEDAMPERSANDS
+ ${WriteConfig} PORTABLEAPPNAMEDOUBLEDAMPERSANDS "$PORTABLEAPPNAMEDOUBLEDAMPERSANDS"
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "Details" "PluginType" "App"
+ ${If} $1 == "CommonFiles"
+ StrCpy $COMMONFILESPLUGIN "true"
+ ${WriteConfig} COMMONFILESPLUGIN "true"
+ ${EndIf}
+ ${EndIf}
+
+
+ ;App ID
+ ${WordReplace} $PORTABLEAPPNAME " " "" + $8
+ ${WordReplace} $8 " " "_" + $8
+ ${WordReplace} $8 "(" "" + $8
+ ${WordReplace} $8 ")" "" + $8
+ ${WordReplace} $8 "[" "" + $8
+ ${WordReplace} $8 "]" "" + $8
+ ${WordReplace} $8 "~" "-" + $8
+ ${WordReplace} $8 "&" "+" + $8
+ ${WordReplace} $8 "#" "+" + $8
+ ${WordReplace} $8 "$\"" "-" + $8
+ ${WordReplace} $8 "*" "+" + $8
+ ${WordReplace} $8 "/" "_" + $8
+ ${WordReplace} $8 "\" "_" + $8
+ ${WordReplace} $8 ":" "." + $8
+ ${WordReplace} $8 "<" "-" + $8
+ ${WordReplace} $8 ">" "-" + $8
+ ${WordReplace} $8 "?" "" + $8
+ ${WordReplace} $8 "|" "-" + $8
+ ${WordReplace} $8 "=" "-" + $8
+ ${WordReplace} $8 "," "." + $8
+ ${WordReplace} $8 ";" "." + $8
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ AppID \
+ "Enter the portable app's App ID (usually the name with no spaces or symbols):" \
+ $8 \
+ $APPID \
+ required
+
+ ${WriteConfig} APPID "$APPID"
+ StrCpy $SHORTNAME $APPID
+
+ ;Publisher
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Publisher \
+ "Enter the publisher ('App Developer && PortableApps.com' for our apps):" \
+ "No Publisher Specified" \
+ $1 \
+ optional
+
+ ;Homepage
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Homepage \
+ "Enter the app's homepage (e.g. portableapps.com):" \
+ "example.com" \
+ $1 \
+ optional
+
+ ;Category
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Category \
+ "Enter the app's category *exactly* (Accessibility, Development, Education, Games, Graphics && Pictures, Internet, Music && Video, Office, Operating Systems, Utilities):" \
+ "" \
+ $1 \
+ optional
+
+ ;Description
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Description \
+ "Enter the app's description (e.g. Simple FTP program.):" \
+ "" \
+ $1 \
+ optional
+
+ ;Language
+ !insertmacro GetValueFromAppInfo \
+ Details \
+ Language \
+ "Enter the portable app's language as expected by NSIS (e.g. English or Multilingual):" \
+ "English" \
+ $APPLANGUAGE \
+ optional
+ ${If} $APPLANGUAGE == ""
+ StrCpy $APPLANGUAGE "English"
+ ${EndIf}
+
+ !macro GetLicenseValueFromAppInfo Key Prompt
+ ReadINIStr $1 $AppInfoINIFile License ${Key}
+ ${If} $1 == ""
+ ${If} $INTERACTIVEMODE = 1
+ ${If} ${Cmd} ${|} MessageBox MB_ICONQUESTION|MB_YESNO "License Question: ${Prompt}" IDYES ${|}
+ StrCpy $1 "true"
+ ${Else}
+ StrCpy $1 "false"
+ ${EndIf}
+ WriteINIStr $AppInfoINIFile License ${Key} $1
+ ${EndIf}
+ ${EndIf}
+ !macroend
+
+ ;License
+ !insertmacro GetLicenseValueFromAppInfo Shareable "Can this application be legally shared from one user to another?"
+ !insertmacro GetLicenseValueFromAppInfo OpenSource "Is this application 100% open source under an OSI-approved license?"
+ !insertmacro GetLicenseValueFromAppInfo Freeware "Is this application freeware (it can be used without payment)?"
+ !insertmacro GetLicenseValueFromAppInfo CommercialUse "Can this app be used in a commercial environment?"
+
+ ;EULA Version
+ ${ReadINIStrWithDefault} $EULAVERSION $AppInfoINIFile "License" "EULAVersion" ""
+
+ ;Display Version
+ !insertmacro GetValueFromAppInfo \
+ Version \
+ DisplayVersion \
+ "Enter the portable app's display version (e.g. 1.0 or 2.2 Beta 1):" \
+ "0.1" \
+ $DISPLAYVERSION \
+ required
+
+ ;Package Version
+ !insertmacro GetValueFromAppInfo \
+ Version \
+ PackageVersion \
+ "Enter the portable app's package version as all numbers in the form X.X.X.X (e.g. 1.0.0.0 or 2.2.0.1):" \
+ "0.1.0.0" \
+ $1 \
+ required
+
+ ${WriteConfig} VERSION "$1"
+
+ ;Filename should only be alpha, numbers as well as: + . - _
+ ${If} $PluginInstaller == "true"
+ StrCpy $INSTALLERFILENAME "$PLUGINNAME_$DISPLAYVERSION"
+ ${Else}
+ StrCpy $INSTALLERFILENAME "$APPID_$DISPLAYVERSION"
+ ${EndIf}
+
+ ${If} $APPLANGUAGE != "Multilingual"
+ StrCpy $INSTALLERFILENAME "$INSTALLERFILENAME_$APPLANGUAGE"
+ ${EndIf}
+
+ ${WordReplace} $INSTALLERFILENAME " " "_" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "(" "" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME ")" "" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "[" "" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "]" "" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "~" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "&" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "#" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "$\"" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "*" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "/" "_" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "\" "_" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME ":" "." + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "<" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME ">" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "?" "" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "|" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "=" "-" + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "," "." + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME ";" "." + $INSTALLERFILENAME
+ ${WordReplace} $INSTALLERFILENAME "+" "Plus" + $INSTALLERFILENAME
+
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "DownloadURL" ""
+ ${If} $1 != ""
+ StrCpy $INSTALLERFILENAME "$INSTALLERFILENAME_online"
+ ${EndIf}
+
+ ${WriteConfig} FILENAME "$INSTALLERFILENAME"
+
+
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "Control" "Start" ""
+ ${If} $1 == ""
+ ${WriteErrorToLog} "AppInfo.ini - Control - Start is missing."
+ ${Else}
+ ${WriteConfig} FINISHPAGERUN "$1"
+ ${EndIf}
+ ${IfNot} ${FileExists} "$INSTALLAPPDIRECTORY\$1"
+ ${AndIf} $PluginInstaller != "true"
+ ${WriteErrorToLog} "AppInfo.ini - Control - Start=$1, file is missing."
+ ${EndIf}
+
+ ${ReadINIStrWithDefault} $2 $InstallerINIFile "CheckRunning" "CloseEXE" "$1"
+ ${WriteConfig} CHECKRUNNING "$2"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "CheckRunning" "CloseName" "$PORTABLEAPPNAME"
+ ${WriteConfig} CLOSENAME "$1"
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "SpecialPaths" "Plugins" "NONE"
+ ${WriteConfig} ADDONSDIRECTORYPRESERVE "$1"
+ ${WriteConfig} INSTALLERCOMMENTS "For additional details, visit PortableApps.com"
+ ${ReadINIStrWithDefault} $1 $AppInfoINIFile "Details" "Trademarks" ""
+ ${If} $1 != ""
+ StrCpy $1 "$1. "
+ ${EndIf}
+ ${WriteConfig} INSTALLERADDITIONALTRADEMARKS "$1"
+
+ ;Source Code
+ ${ReadINIStrWithDefault} $INCLUDESOURCE $InstallerINIFile "Source" "IncludeInstallerSource" "false"
+ ${If} $INCLUDESOURCE == "true"
+ ${WriteConfig} INCLUDEINSTALLERSOURCE "true"
+ ${EndIf}
+
+ ;Languages
+ ${If} $APPLANGUAGE != "Multilingual"
+ ${WriteConfig} INSTALLERLANGUAGE "$APPLANGUAGE"
+ ${Else}
+ ${WriteConfig} INSTALLERMULTILINGUAL "true"
+
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "Languages" "English" ""
+ ${If} $1 == ""
+ StrCpy $ALLLANGUAGES "true"
+ ${EndIf}
+
+ ${SetIndividualLanguage} "ENGLISH"
+ ${SetIndividualLanguage} "ENGLISHGB"
+ ${SetIndividualLanguage} "AFRIKAANS"
+ ${SetIndividualLanguage} "ALBANIAN"
+ ${SetIndividualLanguage} "ARABIC"
+ ${SetIndividualLanguage} "ARMENIAN"
+ ${SetIndividualLanguage} "BASQUE"
+ ${SetIndividualLanguage} "BELARUSIAN"
+ ${SetIndividualLanguage} "BOSNIAN"
+ ${SetIndividualLanguage} "BRETON"
+ ${SetIndividualLanguage} "BULGARIAN"
+ ${SetIndividualLanguage} "CATALAN"
+ ${SetIndividualLanguage} "CROATIAN"
+ ${SetIndividualLanguage} "CZECH"
+ ${SetIndividualLanguage} "DANISH"
+ ${SetIndividualLanguage} "DUTCH"
+ ${SetIndividualLanguage} "ESPERANTO"
+ ${SetIndividualLanguage} "ESTONIAN"
+ ${SetIndividualLanguage} "FARSI"
+ ${SetIndividualLanguage} "FINNISH"
+ ${SetIndividualLanguage} "FRENCH"
+ ${SetIndividualLanguage} "GALICIAN"
+ ${SetIndividualLanguage} "GERMAN"
+ ${SetIndividualLanguage} "GREEK"
+ ${SetIndividualLanguage} "HEBREW"
+ ${SetIndividualLanguage} "HUNGARIAN"
+ ${SetIndividualLanguage} "ICELANDIC"
+ ${SetIndividualLanguage} "INDONESIAN"
+ ${SetIndividualLanguage} "IRISH"
+ ${SetIndividualLanguage} "ITALIAN"
+ ${SetIndividualLanguage} "JAPANESE"
+ ${SetIndividualLanguage} "KOREAN"
+ ${SetIndividualLanguage} "KURDISH"
+ ${SetIndividualLanguage} "LATVIAN"
+ ${SetIndividualLanguage} "LITHUANIAN"
+ ${SetIndividualLanguage} "LUXEMBOURGISH"
+ ${SetIndividualLanguage} "MACEDONIAN"
+ ${SetIndividualLanguage} "MALAY"
+ ${SetIndividualLanguage} "MONGOLIAN"
+ ${SetIndividualLanguage} "NORWEGIAN"
+ ${SetIndividualLanguage} "NORWEGIANNYNORSK"
+ ${SetIndividualLanguage} "POLISH"
+ ${SetIndividualLanguage} "PORTUGUESE"
+ ${SetIndividualLanguage} "PORTUGUESEBR"
+ ${SetIndividualLanguage} "ROMANIAN"
+ ${SetIndividualLanguage} "RUSSIAN"
+ ${SetIndividualLanguage} "SERBIAN"
+ ${SetIndividualLanguage} "SERBIANLATIN"
+ ${SetIndividualLanguage} "SIMPCHINESE"
+ ${SetIndividualLanguage} "SLOVAK"
+ ${SetIndividualLanguage} "SLOVENIAN"
+ ${SetIndividualLanguage} "SPANISH"
+ ${SetIndividualLanguage} "SPANISHINTERNATIONAL"
+ ${SetIndividualLanguage} "SWEDISH"
+ ${SetIndividualLanguage} "THAI"
+ ${SetIndividualLanguage} "TRADCHINESE"
+ ${SetIndividualLanguage} "TURKISH"
+ ${SetIndividualLanguage} "UKRAINIAN"
+ ${SetIndividualLanguage} "UZBEK"
+ ${SetIndividualLanguage} "WELSH"
+ ${EndIf}
+
+ ;EULA
+ ${If} $PluginInstaller == "true"
+ ${If} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\PluginEULA.txt"
+ ${WriteConfig} LICENSEAGREEMENT "PluginEULA.txt"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\PluginEULA.txt"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\PluginEULA.txt" "$INSTALLAPPDIRECTORY\App\AppInfo\PluginEULA.txt"
+ ${WriteConfig} LICENSEAGREEMENT "PluginEULA.txt"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\PluginEULA.rtf"
+ ${WriteErrorToLog} "EULA - Other\Source\PluginEULA.rtf is no longer supported. Use App\AppInfo\PluginEULA.txt instead."
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\PluginEULA.rtf"
+ ${WriteErrorToLog} "EULA - App\AppInfo\PluginEULA.rtf is not supported. Use App\AppInfo\PluginEULA.txt instead."
+ ${EndIf}
+ ${Else}
+ ${If} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\EULA.txt"
+ ${WriteConfig} LICENSEAGREEMENT "eula.txt"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\EULA.txt"
+ Rename "$INSTALLAPPDIRECTORY\Other\Source\EULA.txt" "$INSTALLAPPDIRECTORY\App\AppInfo\EULA.txt"
+ ${WriteConfig} LICENSEAGREEMENT "eula.txt"
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\Other\Source\EULA.rtf"
+ ${WriteErrorToLog} "EULA - Other\Source\EULA.rtf is no longer supported. Use App\AppInfo\EULA.txt instead."
+ ${ElseIf} ${FileExists} "$INSTALLAPPDIRECTORY\App\AppInfo\EULA.rtf"
+ ${WriteErrorToLog} "EULA - App\AppInfo\EULA.rtf is not supported. Use App\AppInfo\EULA.txt instead."
+ ${EndIf}
+ ${EndIf}
+
+ ${If} $EULAVERSION != ""
+ ${WriteConfig} EULAVERSION "$EULAVERSION"
+ ${EndIf}
+
+ ;OptionalComponents
+ ${ReadINIStrWithDefault} $OPTIONALCOMPONENTS $InstallerINIFile "OptionalComponents" "OptionalComponents" "false"
+ ${If} $OPTIONALCOMPONENTS == "true"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "MainSectionTitle" "$PORTABLEAPPNAME (English) [Required]"
+ ${WriteConfig} MAINSECTIONTITLE "$1"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "MainSectionDescription" "Install the portable app"
+ ${WriteConfig} MAINSECTIONDESCRIPTION "$1"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionTitle" "Additional Languages"
+ ${WriteConfig} OPTIONALSECTIONTITLE "$1"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionDescription" "Add multilingual support for this app"
+ ${WriteConfig} OPTIONALSECTIONDESCRIPTION "$1"
+ ${ReadINIStrWithDefault} $OptionalSectionSelectedInstallType $InstallerINIFile "OptionalComponents" "OptionalSectionSelectedInstallType" "Multilingual"
+ ${WriteConfig} OPTIONALSECTIONSELECTEDINSTALLTYPE "$OptionalSectionSelectedInstallType"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionNotSelectedInstallType" "English"
+ ${WriteConfig} OPTIONALSECTIONNOTSELECTEDINSTALLTYPE "$1"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionPreSelectedIfNonEnglishInstall" "true"
+ ${If} $1 == "true"
+ ${WriteConfig} OPTIONALSECTIONPRESELECTEDIFNONENGLISHINSTALL "$1"
+ ${EndIf}
+
+ ${If} $OptionalSectionSelectedInstallType == "Multilingual"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionInstalledWhenSilent" "false"
+ ${Else}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalSectionInstalledWhenSilent" "true"
+ ${EndIf}
+
+ ${If} $1 == "true"
+ ${WriteConfig} OPTIONALSECTIONINSTALLEDWHENSILENT "$1"
+ ${EndIf}
+ ${EndIf}
+
+ ;Main directories
+ ${If} $PluginInstaller == "true"
+ ${AndIf} $COMMONFILESPLUGIN != "true"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "MainDirectories" "RemoveAppDirectory" "false"
+ ${Else}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "MainDirectories" "RemoveAppDirectory" "true"
+ ${EndIf}
+ ${If} $1 == "true"
+ ${WriteConfig} REMOVEAPPDIRECTORY "true"
+ ${EndIf}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "MainDirectories" "RemoveDataDirectory" "false"
+ ${If} $1 == "true"
+ ${WriteConfig} REMOVEDATADIRECTORY "true"
+ ${EndIf}
+ ${If} $PluginInstaller == "true"
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "MainDirectories" "RemoveOtherDirectory" "false"
+ ${Else}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "MainDirectories" "RemoveOtherDirectory" "true"
+ ${EndIf}
+ ${If} $1 == "true"
+ ${WriteConfig} REMOVEOTHERDIRECTORY "true"
+ ${EndIf}
+
+ ;Preserve directories
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DirectoriesToPreserve" "PreserveDirectory$R1" ""
+ ${If} $1 != ""
+ ${WriteConfig} PRESERVEDIRECTORY$R1 "$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $R1 > 10
+
+ ;Remove directories
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DirectoriesToRemove" "RemoveDirectory$R1" ""
+ ${If} $1 != ""
+ ${WriteConfig} REMOVEDIRECTORY$R1 "$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $R1 > 10
+
+ ;Preserve files
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "FilesToPreserve" "PreserveFile$R1" ""
+ ${If} $1 != ""
+ ${WriteConfig} PRESERVEFILE$R1 "$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $R1 > 10
+
+ ;Remove files
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "FilesToRemove" "RemoveFile$R1" ""
+ ${If} $1 != ""
+ ${WriteConfig} REMOVEFILE$R1 "$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $R1 > 10
+
+ ;Custom code
+ ${If} $PluginInstaller == "true"
+ StrCpy $9 "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPluginCustom.nsh"
+ ${Else}
+ StrCpy $9 "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerCustom.nsh"
+ ${EndIf}
+ ${If} ${FileExists} $9
+ ${WriteConfig} USESCUSTOMCODE "true"
+ ${EndIf}
+
+ ;Local Files
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "CopyLocalFiles" "CopyLocalFiles" "false"
+ ${If} $1 == "true"
+ ${WriteConfig} COPYLOCALFILES "true"
+
+ !insertmacro TransferInstallerINIToConfig CopyLocalFiles CopyFromRegPath -
+ !insertmacro TransferInstallerINIToConfig CopyLocalFiles CopyFromRegKey -
+ !insertmacro TransferInstallerINIToConfig CopyLocalFiles CopyFromRegRemoveDirectories -
+ !insertmacro TransferInstallerINIToConfig CopyLocalFiles CopyFromDirectory -
+ !insertmacro TransferInstallerINIToConfig CopyLocalFiles CopyToDirectory -
+ ${EndIf}
+
+ ;Download files
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "DownloadURL" ""
+ ${If} $1 != ""
+ StrCpy $2 $1 7
+
+ ${If} $2 == "http://"
+ ${WriteConfig} DownloadURL "$1"
+
+ !insertmacro TransferInstallerINIToConfig DownloadFiles DownloadName required
+ !insertmacro TransferInstallerINIToConfig DownloadFiles DownloadFilename required
+ !insertmacro TransferInstallerINIToConfig DownloadFiles DownloadMD5 -
+ !insertmacro TransferInstallerINIToConfig DownloadFiles DownloadTo -
+ !insertmacro TransferInstallerINIToConfig DownloadFiles AdditionalInstallSize required
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "Extract$R1To" ""
+ ${If} $1 != ""
+ ${If} $1 == ""
+ StrCpy $1 ""
+ ${EndIf}
+ ${WriteConfig} Extract$R1To "$1"
+ ${EndIf}
+ ${Next}
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "Extract$R1File" ""
+ ${If} $1 != ""
+ ${WriteConfig} Extract$R1File "$1"
+ ${EndIf}
+ ${Next}
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "AdvancedExtract$R1To" ""
+ ${If} $1 != ""
+ ${If} $1 == ""
+ StrCpy $1 ""
+ ${EndIf}
+ ${WriteConfig} AdvancedExtract$R1To "$1"
+ ${EndIf}
+ ${Next}
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "AdvancedExtract$R1Filter" ""
+ ${If} $1 != ""
+ ${WriteConfig} AdvancedExtract$R1Filter "$1"
+ ${EndIf}
+ ${Next}
+
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "DoubleExtractFilename" ""
+ ${If} $1 != ""
+ ${WriteConfig} DoubleExtractFilename "$1"
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "DoubleExtract$R1To" ""
+ ${If} $1 != ""
+ ${If} $1 == ""
+ StrCpy $1 ""
+ ${EndIf}
+ ${WriteConfig} DoubleExtract$R1To "$1"
+ ${EndIf}
+ ${Next}
+
+ ${For} $R1 1 10
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "DownloadFiles" "DoubleExtract$R1Filter" ""
+ ${If} $1 != ""
+ ${WriteConfig} DoubleExtract$R1Filter "$1"
+ ${EndIf}
+ ${Next}
+
+ ${EndIf}
+ ${Else}
+ ${WriteErrorToLog} "Installer.ini - DownloadFiles - DownloadURL must begin with http://"
+ ${EndIf}
+ ${EndIf}
+
+ FileClose $0
+
+ ; If errors have occurred, there's no point in going on to the actual generation of it.
+ ${If} $ERROROCCURED != "true"
+ ;Make the installer header
+ ${If} $USEEXTRACTEDICON == "true"
+ ${OrIf} $PluginInstaller == "true"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\PortableApps.comInstallerHeader.bmp" "$INSTALLAPPDIRECTORY\Other\Source"
+ CopyFiles /SILENT "$EXEDIR\App\default_bits\PortableApps.comInstallerHeaderRTL.bmp" "$INSTALLAPPDIRECTORY\Other\Source"
+ ${Else}
+ ExecWait `"$EXEDIR\App\bin\MakeHeader.exe" "$INSTALLAPPDIRECTORY"`
+ ${EndIf}
+
+ ;Move optional component files
+ ${If} $OPTIONALCOMPONENTS == "true"
+ CreateDirectory "$INSTALLAPPDIRECTORY\Optional1"
+
+ ;Move directories
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalDirectory$R1" "\COMPLETED\"
+ ${If} $1 != ""
+ ${AndIf} $1 != "\COMPLETED\"
+ ${GetParent} "$INSTALLAPPDIRECTORY\Optional1\$1" $2
+ CreateDirectory $2
+ Rename "$INSTALLAPPDIRECTORY\$1" "$INSTALLAPPDIRECTORY\Optional1\$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $1 == "\COMPLETED\"
+
+ ;Move files
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalFile$R1" "\COMPLETED\"
+ ${If} $1 != ""
+ ${AndIf} $1 != "\COMPLETED\"
+ ${GetParent} "$INSTALLAPPDIRECTORY\Optional1\$1" $2
+ CreateDirectory $2
+ ${GetParent} "$INSTALLAPPDIRECTORY\$1" $3
+ ${GetFileName} "$INSTALLAPPDIRECTORY\Optional1\$1" $4
+ ${MoveFiles} DOS "$4" "$3" "$2"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $1 == "\COMPLETED\"
+
+ ${EndIf}
+
+ ;Compile the installer
+ SetDetailsPrint ListOnly
+ ${If} $PluginInstaller == "true"
+ DetailPrint "Creating $PLUGINNAME installer..."
+ ${Else}
+ DetailPrint "Creating $PORTABLEAPPNAME installer..."
+ ${EndIf}
+ SetDetailsPrint none
+ ${TBProgress} 66
+
+ ;Delete existing installer if there is one
+ ${GetParent} $INSTALLAPPDIRECTORY $0
+ Delete "$0\$INSTALLERFILENAME.paf.exe"
+ ${If} ${FileExists} "$0\$INSTALLERFILENAME.paf.exe"
+ MessageBox MB_OK|MB_ICONEXCLAMATION "Unable to delete file: $0\$INSTALLERFILENAME.paf.exe. Please be sure the file is not in use"
+ ${WriteErrorToLog} "Unable to delete file: $0\$INSTALLERFILENAME.paf.exe. Please be sure the file is not in use."
+ ${Else}
+ SetOutPath "$EXEDIR\App\nsis"
+ ${If} $PluginInstaller == "true"
+ ExecDos::exec `"$EXEDIR\App\nsis\makensis.exe" /O"$EXEDIR\Data\PortableApps.comInstallerLog.txt" "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPlugin.nsi"` "" ""
+ ${Else}
+ ExecDos::exec `"$EXEDIR\App\nsis\makensis.exe" /O"$EXEDIR\Data\PortableApps.comInstallerLog.txt" "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.nsi"` "" ""
+ ${EndIf}
+ ${EndIf}
+
+ ;Move optional component files back
+ ${If} $OPTIONALCOMPONENTS == "true"
+ ;Move directories
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalDirectory$R1" "\COMPLETED\"
+ ${If} $1 != ""
+ ${AndIf} $1 != "\COMPLETED\"
+ Rename "$INSTALLAPPDIRECTORY\Optional1\$1" "$INSTALLAPPDIRECTORY\$1"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $1 == "\COMPLETED\"
+
+ ;Move files
+ StrCpy $R1 1
+ ${Do}
+ ${ReadINIStrWithDefault} $1 $InstallerINIFile "OptionalComponents" "OptionalFile$R1" "\COMPLETED\"
+ ${If} $1 != ""
+ ${AndIf} $1 != "\COMPLETED\"
+ ${GetParent} "$INSTALLAPPDIRECTORY\Optional1\$1" $2
+ ${GetParent} "$INSTALLAPPDIRECTORY\$1" $3
+ ${GetFileName} "$INSTALLAPPDIRECTORY\Optional1\$1" $4
+ ${MoveFiles} DOS "$4" "$2" "$3"
+ ${EndIf}
+ IntOp $R1 $R1 + 1
+ ${LoopUntil} $1 == "\COMPLETED\"
+
+ RMDir /r "$INSTALLAPPDIRECTORY\Optional1"
+ ${EndIf}
+ ${EndIf}
+
+ ; Done
+ SetDetailsPrint ListOnly
+ DetailPrint " "
+ DetailPrint "Processing complete."
+
+ ${If} ${FileExists} "$0\$INSTALLERFILENAME.paf.exe"
+ ${AndIf} $ERROROCCURED != "true"
+ StrCpy $FINISHTITLE "Installer Created"
+ StrCpy $FINISHTEXT "The installer has been created. Installer location:\r\n$0\r\n\r\nInstaller name:\r\n$INSTALLERFILENAME.paf.exe"
+ ${Else}
+ StrCpy $FINISHTITLE "An Error Occured"
+ StrCpy $FINISHTEXT "The installer was not created. You can view the log file for more information."
+ StrCpy $ERROROCCURED "true"
+ ${EndIf}
+
+ SetDetailsPrint none
+ ;Remove the installer files if not included
+ ${If} $INCLUDESOURCE != "true"
+ ${AndIf} $ERROROCCURED != "true"
+ RMDir /r "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerLanguages\"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.ico"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstaller.nsi"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerConfig.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerDumpLogToFile.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerHeader.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerHeaderRTL.bmp"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerMoveFiles.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPlugin.nsi"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerPluginConfig.nsh"
+ Delete "$INSTALLAPPDIRECTORY\Other\Source\PortableApps.comInstallerTBProgress.nsh"
+ ${EndIf}
+
+ ;Remove the Source and Other directories if empty
+ RMDir "$INSTALLAPPDIRECTORY\Other\Source"
+ RMDir "$INSTALLAPPDIRECTORY\Other"
+ ${TBProgress_State} NoProgress
+SectionEnd
+
+Function ShowFinishPage
+ ${If} $AUTOMATICCOMPILE == "true"
+ ${AndIf} $ERROROCCURED != "true"
+ Abort
+ ${ElseIf} $ERROROCCURED == "true"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "Field 4" "Flags" "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "Field 5" "State" "1"
+ ${EndIf}
+FunctionEnd
+
+Function RunOnFinish
+ Exec `"$0\$INSTALLERFILENAME.paf.exe"`
+FunctionEnd
+
+Function .onGUIEnd
+ RealProgress::Unload
+FunctionEnd
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizardForm.ini b/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizardForm.ini
new file mode 100644
index 000000000..3f3bc0b01
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Source/InstallerWizardForm.ini differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/License.txt b/Greenshot/tools/PortableApps.comInstaller/Other/Source/License.txt
new file mode 100644
index 000000000..d6a3987f4
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/License.txt
@@ -0,0 +1,344 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE,
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT
+PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED
+IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
+AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY
+OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM
+AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
+ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C) 19yy
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/MoveFiles.nsh b/Greenshot/tools/PortableApps.comInstaller/Other/Source/MoveFiles.nsh
new file mode 100644
index 000000000..451ab65ee
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/MoveFiles.nsh
@@ -0,0 +1,104 @@
+; Copyright (c) 2008, Harold E Austin Jr
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are met:
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+; * Neither the name of the organization nor the
+; names of its contributors may be used to endorse or promote products
+; derived from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY Harold E Austin Jr ``AS IS'' AND ANY
+; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL Harold E Austin Jr BE LIABLE FOR ANY
+; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+ MoveFiles.nsh -- version 1.0 (May 5, 2008)
+ move files matching "filespec" from "source-directory" to "destination-directory"
+
+ usage:
+ !include MoveFiles.nsh
+
+ ${MoveFiles} mode "filespec" "source-directory" "destination-directory"
+
+ where:
+ mode can be DOS, DIR, FORCE or DIR+FORCE (anything else = DOS):
+ DOS means act like the DOS MOVE command (move only files)
+ DIR means move files AND directories
+ FORCE means overwrite destination files (like MOVE/Y)
+
+ example:
+ CreateDirectory "C:\NEW\DIR"
+ DetailPrint "Moving files and directories..."
+ ${MoveFiles} DIR+FORCE "*" "C:\OLD\DIR" "C:\NEW\DIR"
+ DetailPrint `"Processing"...`
+ Sleep 2000
+ DetailPrint "Moving only the files back..."
+ ${MoveFiles} DOS "*" "C:\NEW\DIR" "C:\OLD\DIR"
+ DetailPrint "Moving the directories back..."
+ ${MoveFiles} DIR "*" "C:\NEW\DIR" "C:\OLD\DIR"
+*/
+!ifndef MoveFiles
+!define MoveFiles "!insertmacro MoveFiles"
+!macro MoveFiles mode filespec sourcedir destdir
+ push `${destdir}`
+ push `${sourcedir}`
+ push `${filespec}`
+ push `${mode}`
+ call MoveFiles
+!macroend
+
+Function MoveFiles ; mode filespec sourcedir destdir
+ Exch $0 ; mode, directory mode
+ Exch
+ Exch $1 ; filespec, force mode
+ Exch 2
+ Exch $2 ; source directory
+ Exch 3
+ Exch $3 ; destination directory
+ Push $4 ; FindFirst/FindNext search handle
+ Push $5 ; current filename matching filespec in sourcedir
+ FindFirst $4 $5 "$2\$1"
+ StrCpy $1 "" ; FORCE mode disabled by default
+ StrCmp $0 FORCE 0 +2
+ StrCpy $1 FORCE
+ StrCmp $0 DIR+FORCE 0 +3
+ StrCpy $0 DIR
+ StrCpy $1 FORCE
+ loop:
+ StrCmp $5 "" done ; $5 == "", if no more matching files
+ StrCmp $5 . next
+ StrCmp $5 .. next
+ StrCmp $0 DIR +2
+ ; DIR mode disabled: ignore directories that match ${filespec}
+ IfFileExists "$2\$5\*.*" next
+ StrCmp $1 FORCE 0 +4
+ ; FORCE mode: make sure destination doesn't exist
+ Delete "$3\$5"
+ StrCmp $0 DIR 0 +2
+ RMDir /R "$3\$5"
+ Rename "$2\$5" "$3\$5"
+ next:
+ FindNext $4 $5
+ Goto loop
+ done:
+ FindClose $4 ; finished with this search; close handle
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $0
+ Pop $1
+ Pop $2
+FunctionEnd
+!endif
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/ReadINIStrWithDefault.nsh b/Greenshot/tools/PortableApps.comInstaller/Other/Source/ReadINIStrWithDefault.nsh
new file mode 100644
index 000000000..2d3b3a10b
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/ReadINIStrWithDefault.nsh
@@ -0,0 +1,55 @@
+; ReadINIStrWithDefault 1.1 (2009-05-12)
+;
+; Substitutes a default value if the INI is undefined
+; Copyright 2008-2009 John T. Haller of PortableApps.com
+; Released under the BSD
+;
+; Usage: ${ReadINIStrWithDefault} OUTPUT_VALUE INI_FILENAME SECTION_NAME ENTRY_NAME DEFAULT_VALUE
+;
+; History:
+; 1.1 (2009-05-12): Fixed error with $0 and $2 being swapped
+
+Function ReadINIStrWithDefault
+ ;Start with a clean slate
+ ClearErrors
+
+ ;Get our parameters
+ Exch $0 ;DEFAULT_VALUE
+ Exch
+ Exch $1 ;ENTRY_NAME
+ Exch 2
+ Exch $2 ;SECTION_NAME
+ Exch 3
+ Exch $3 ;INI_FILENAME
+ Push $4 ;OUTPUT_VALUE
+
+ ;Read from the INI
+ ReadINIStr $4 $3 $2 $1
+ IfErrors 0 +3
+ StrCpy $4 $0
+ ClearErrors
+
+ ;Keep the variable for last
+ StrCpy $0 $4
+
+ ;Clear the stack
+ Pop $4
+ Pop $3
+ Exch 2
+ Pop $2
+ Pop $1
+
+ ;Reset the last variable and leave our result on the stack
+ Exch $0
+FunctionEnd
+
+!macro ReadINIStrWithDefault OUTPUT_VALUE INI_FILENAME SECTION_NAME ENTRY_NAME DEFAULT_VALUE
+ Push `${INI_FILENAME}`
+ Push `${SECTION_NAME}`
+ Push `${ENTRY_NAME}`
+ Push `${DEFAULT_VALUE}`
+ Call ReadINIStrWithDefault
+ Pop `${OUTPUT_VALUE}`
+!macroend
+
+!define ReadINIStrWithDefault '!insertmacro "ReadINIStrWithDefault"'
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/Readme.txt b/Greenshot/tools/PortableApps.comInstaller/Other/Source/Readme.txt
new file mode 100644
index 000000000..c725c6ea3
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/Readme.txt
@@ -0,0 +1,41 @@
+PortableApps.com Installer
+==========================
+Copyright 2006-2009 John T. Haller
+
+Website: http://PortableApps.com/Installer
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+About PortableApps.com Installer
+================================
+PortableApps.com Installer allows you to easily package apps in PortableApps.com
+Format as a PortableApps.com Installer.
+
+
+LICENSE
+=======
+This code is released under the GPL. Within the Other\Source directory
+you will find the code as well as the full GPL license (License.txt). If you use the
+code in your own product, please give proper and prominent attribution.
+
+
+PortableApps.com Installer CONFIGURATION
+========================================
+Configuration options are included in the appropriate appinfo.ini and installer.ini
+files in the app's AppInfo directory as detailed at PortableApps.com/development
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/TBProgress.nsh b/Greenshot/tools/PortableApps.comInstaller/Other/Source/TBProgress.nsh
new file mode 100644
index 000000000..7fa976961
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/Other/Source/TBProgress.nsh
@@ -0,0 +1,59 @@
+!include "LogicLib.nsh"
+
+!ifndef CLSCTX_INPROC_SERVER
+ !define CLSCTX_INPROC_SERVER 1
+!endif
+
+!define CLSID_ITaskbarList {56fdf344-fd6d-11d0-958a-006097c9a090}
+
+!define IID_ITaskbarList3 {ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}
+!define ITaskbarList3->SetProgressState $ITaskbarList3->10
+!define ITaskbarList3->SetProgressValue $ITaskbarList3->9
+
+!define TBPF_NOPROGRESS 0x00000000 ; Normal state / no progress bar
+!define TBPF_INDETERMINATE 0x00000001 ; Marquee style progress bar
+!define TBPF_NORMAL 0x00000002 ; Standard progress bar
+!define TBPF_ERROR 0x00000004 ; Red taskbar button to indicate an error occurred
+!define TBPF_PAUSED 0x00000008 ; Yellow taskbar button to indicate user attention
+ ; (input) is required to resume progress
+
+Var ITaskbarList3
+
+!macro TBProgress_Init
+ !ifndef TBProgressInitialized
+ !define TBProgressInitialized
+ ${Unless} ${Silent}
+ System::Call "ole32::CoCreateInstance( \
+ g '${CLSID_ITaskbarList}', \
+ i 0, \
+ i ${CLSCTX_INPROC_SERVER}, \
+ g '${IID_ITaskbarList3}', \
+ *i .s)"
+ Pop $ITaskbarList3
+ ${Else}
+ StrCpy $ITaskbarList3 0
+ ${EndIf}
+ !endif
+!macroend
+!define TBProgress_Init `!insertmacro TBProgress_Init`
+
+!macro TBProgress_Progress Val Max
+ ${TBProgress_Init}
+ ${If} $ITaskbarList3 <> 0
+ System::Call "${ITaskbarList3->SetProgressValue}(i$HWNDPARENT, l${Val}, l${Max})"
+ ${EndIf}
+!macroend
+!define TBProgress_Progress `!insertmacro TBProgress_Progress`
+
+!macro TBProgress Val
+ ${TBProgress_Progress} ${Val} 100
+!macroend
+!define TBProgress `!insertmacro TBProgress`
+
+!macro TBProgress_State State
+ ${TBProgress_Init}
+ ${If} $ITaskbarList3 <> 0
+ System::Call "${ITaskbarList3->SetProgressState}(i$HWNDPARENT, i${TBPF_${State}})"
+ ${EndIf}
+!macroend
+!define TBProgress_State `!insertmacro TBProgress_State`
\ No newline at end of file
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/header.bmp b/Greenshot/tools/PortableApps.comInstaller/Other/Source/header.bmp
new file mode 100644
index 000000000..46414e810
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Source/header.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/header_rtl.bmp b/Greenshot/tools/PortableApps.comInstaller/Other/Source/header_rtl.bmp
new file mode 100644
index 000000000..25b91490b
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Source/header_rtl.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/Other/Source/welcomefinish.bmp b/Greenshot/tools/PortableApps.comInstaller/Other/Source/welcomefinish.bmp
new file mode 100644
index 000000000..220f605c3
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/Other/Source/welcomefinish.bmp differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/PortableApps.comInstaller.exe b/Greenshot/tools/PortableApps.comInstaller/PortableApps.comInstaller.exe
new file mode 100644
index 000000000..ce6cb438a
Binary files /dev/null and b/Greenshot/tools/PortableApps.comInstaller/PortableApps.comInstaller.exe differ
diff --git a/Greenshot/tools/PortableApps.comInstaller/help.html b/Greenshot/tools/PortableApps.comInstaller/help.html
new file mode 100644
index 000000000..d4fe83fe2
--- /dev/null
+++ b/Greenshot/tools/PortableApps.comInstaller/help.html
@@ -0,0 +1,175 @@
+
+PortableApps.com Installer Help
+
+
+
+
+
+
+
+
PortableApps.com Installer Help
+
package your portable apps right
+
PortableApps.com Installer compiles PortableApps.com Format apps into easy-to-use installers. They're small, easy to use, automatically work with the PortableApps.com Platform and require no coding or compiling.
+Learn more about the PortableApps.com Installer...
+
+
- Support PortableApps.com's Hosting and Development
+
+
Go to the PortableApps.com Installer Homepage >>
+
+
Get more portable apps at PortableApps.com
+
+
This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative.
+
+
PortableApps.com Installer-Specific Issues
+
+
For support questions, see the PortableApps.com Installer Homepage
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Greenshot/tools/WinSCP/WinSCP.com b/Greenshot/tools/WinSCP/WinSCP.com
new file mode 100644
index 000000000..959299ecd
Binary files /dev/null and b/Greenshot/tools/WinSCP/WinSCP.com differ
diff --git a/Greenshot/tools/WinSCP/WinSCP.exe b/Greenshot/tools/WinSCP/WinSCP.exe
new file mode 100644
index 000000000..db0326b35
Binary files /dev/null and b/Greenshot/tools/WinSCP/WinSCP.exe differ
diff --git a/Greenshot/tools/WinSCP/WinSCPnet.dll b/Greenshot/tools/WinSCP/WinSCPnet.dll
new file mode 100644
index 000000000..fff0b8d83
Binary files /dev/null and b/Greenshot/tools/WinSCP/WinSCPnet.dll differ
diff --git a/Greenshot/tools/WinSCP/license-dotnet.txt b/Greenshot/tools/WinSCP/license-dotnet.txt
new file mode 100644
index 000000000..14e2f777f
--- /dev/null
+++ b/Greenshot/tools/WinSCP/license-dotnet.txt
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/LICENSE b/Greenshot/tools/WinSCP/license.txt
similarity index 93%
rename from LICENSE
rename to Greenshot/tools/WinSCP/license.txt
index 94a9ed024..3c03f9b59 100644
--- a/LICENSE
+++ b/Greenshot/tools/WinSCP/license.txt
@@ -1,9 +1,14 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
+ A. GNU General Public License
+ B. License of WinSCP Icon Set
+ C. Privacy Policy
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
+
+ A. GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
Preamble
@@ -672,3 +677,46 @@ may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
+
+
+ B. License of WinSCP Icon Set
+
+Note that all images distributed in or with WinSCP application are NOT
+published under the GNU General Public License. It means that it is not
+allowed to redistribute or reuse these images or parts of them or modifications
+of them without WinSCP separately or in or with another software.
+
+You agree that all ownership and copyright of the licensed stock icons remain
+the property of York Technologies Limited. WinSCP was granted a license to
+display this graphical media royalty-free in WinSCP software applications,
+web design, presentations, and multimedia projects that WinSCP creates and/or
+distributes.
+
+
+ C. WinSCP Privacy Policy
+
+Please take time to read WinSCP Privacy policy at
+http://winscp.net/eng/docs/privacy
+
+WinSCP includes functionality to collect and send non-personal WinSCP
+Usage statistics and to automatically check for application updates. The only
+potentially personal information sent to WinSCP is IP addresses. Users can
+opt-out from using this functionality in the installer or anytime later
+in WinSCP Preferences. WinSCP Usage statistics help improve future versions
+of WinSCP. Once sent, usage statistics are stored for analysis (except
+IP addresses) and made available to the core WinSCP team only.
+
+Before disabling WinSCP Usage statistics, be so kind and consider that it
+plays very important role in the WinSCP development. We work very hard
+to make WinSCP reliable and useful. We also love improving WinSCP with every
+release. And last but not least, we provide WinSCP application to you
+for free and we want this to stay so! However our resources and time are
+unfortunately very limited. We want to focus our effort on improving
+the right features for you. That is why we need to learn more about how you
+use WinSCP.
+
+If you still want to disable WinSCP Usage statistics already during
+installation, you may do so using Custom installation.
+
+Thank you!
+
diff --git a/Greenshot/tools/WinSCP/readme.txt b/Greenshot/tools/WinSCP/readme.txt
new file mode 100644
index 000000000..77f09feea
--- /dev/null
+++ b/Greenshot/tools/WinSCP/readme.txt
@@ -0,0 +1,11 @@
+This is the README file for standalone package of WinSCP for portable use.
+
+For portable use of WinSCP see
+http://winscp.net/eng/docs/portable
+
+The package includes two executables, .exe and .com. For details see
+http://winscp.net/eng/docs/executables
+
+WinSCP homepage is http://winscp.net/
+
+See the file 'license.txt' for the license conditions.
diff --git a/Greenshot/tools/WinSCP/readme_automation.txt b/Greenshot/tools/WinSCP/readme_automation.txt
new file mode 100644
index 000000000..efd8a7d60
--- /dev/null
+++ b/Greenshot/tools/WinSCP/readme_automation.txt
@@ -0,0 +1,19 @@
+This is the README file for automation package of WinSCP.
+
+For use of WinSCP automation package see
+http://winscp.net/eng/docs/library
+http://winscp.net/eng/docs/library_install
+
+To use this package you must unpack it to the WinSCP installation folder
+or to a folder, where you have already unpacked the WinSCP standalone package.
+http://winscp.net/eng/docs/installation or
+http://winscp.net/eng/docs/portable
+
+To use the WinSCP assembly via COM interop, register it using:
+%WINDIR%\Microsoft.NET\Framework\\RegAsm.exe WinSCPnet.dll /codebase /tlb
+where is typically either v4.0.30319 or v2.0.50727.
+http://winscp.net/eng/docs/library_install#registering
+
+WinSCP homepage is http://winscp.net/
+
+See the file 'license-dotnet.txt' for the license conditions.
\ No newline at end of file
diff --git a/Greenshot/web/htdocs/Help/index.de-DE.html b/Greenshot/web/htdocs/Help/index.de-DE.html
new file mode 100644
index 000000000..9f28a117d
--- /dev/null
+++ b/Greenshot/web/htdocs/Help/index.de-DE.html
@@ -0,0 +1,106 @@
+
+
+
+ Greenshot Hilfe
+
+
+
+
+
+
+
+ Greenshot Hilfe
+
+ Modi
+
+ Bereichsmodus
+
+
+ Aktivieren Sie den Bereichsmodus, indem Sie die Druck -Taste auf
+ Ihrer Tastatur betätigen oder Bereich abfotografieren aus dem
+ Kontextmenü wählen.
+ Drücken und halten Sie die linke Maustaste gedrückt, um einen rechteckigen
+ Bereich zu definieren, der abfotografiert werden soll.
+ Nach dem Loslassen der Maustaste öffnet sich das Bildbearbeitungsfenster
+ zur weiteren Bearbeitung Ihres Screenshots.
+ Um den Bereich später noch einmal abzufotografieren, wählen Sie Zuletzt
+ gewählten Bereich abfotografieren .
+
+
+ Fenstermodus
+
+
+ Aktivieren Sie den FensterModus, indem Sie Alt + Druck auf
+ Ihrer Tastatur betätigen oder Fenster abfotografieren aus dem
+ Kontextmenü wählen.
+ Klicken Sie auf das Fenster, dass abfotografiern werden soll.
+ Nachdem Sie geklickt haben öffnet sich das Bildbearbeitungsfenster
+ zur weiteren Bearbeitung Ihres Screenshots.
+
+
+ Bildschirmmodus
+
+
+ Wenn Sie den gesamten Bildschirm abfotografieren wollen, drücken Sie einfach
+ Ctrl + Print auf Ihrer Tastatur oder wählen Sie Kompletten
+ Bildschirm abfotografieren .
+ Der komplette Bildschirm wird sofort abfotografiert, das Bildbearbeitungsfenster
+ öffnet sich zur weiteren Bearbeitung Ihres Screenshots.
+
+
+ Bildbearbeitungsfenster
+
+
+ Wenn Sie das Bildbearbeitungsfenster nicht nutzen wollen knnen Sie im
+ Kontextmen oder im Einstellungsdialog festlegen, dass es nicht angezeigt
+ werden soll. In diesem Fall wird der Screenshot sofort in eine Datei
+ gespeichert. Speicherort, Dateiname und Bildformat sind dann abhngig von
+ den bevorzugten Ausgabedatei-Einstellungen im Einstellungsdialog.
+
+
+ Datei-Menü
+
+
+ Speichern : speichert die Grafik unter dem Pfad der beim letzten Speichern unter... Dialog gewählt wurde
+ Speichern unter... : öffnet einen Dialog zur Auswahl des Pfads und Dateinamens unter dem die Grafik gespeichert werden soll
+ Grafik in die Zwischenablage kopieren : kopiert die Grafik in die Zwischenablage, so dass sie in anderer Software verwendet werden kann
+
+
+ Bearbeiten-Menü
+
+
+ Gewähltes Element in die Zwischenablage ausschneiden : entfernt das ausgewähltes Element und kopiert es in die Zwischenablage, so dass es in ein anderes Bildbearbeitungsfenster eingefügt werden kann
+ Gewähltes Element in die Zwischenablage kopieren : kopiert das ausgewähltes Element in die Zwischenablage, so dass es in ein anderes Bildbearbeitungsfenster eingefügt werden kann
+ Element aus der Zwischenablage einfügen : fügt ein vorher ausgeschnittenes/kopiertes Element in das Bildbearbeitungsfenster ein
+ Gewähltes Element duplizieren : dupliziert das gewählte Element
+
+
+ Objekt-Menü
+
+
+ Rechteck hinzufügen : fügt ein Rechteck zur Grafik hinzu
+ Ellipse hinzufügen : fügt eine Ellipse zur Grafik hinzu
+ Textfeld hinzufügen : fügt ein Textfeld zur Grafik hinzu
+ Gewähltes Element löschen : entfernt das gewählte Element aus der Grafik
+
+
+
+ Klicken Sie ein Element an um es auszuwählen. Anschließend können Sie die Größe oder
+ Position verändern, oder es kopieren, ausschneiden oder entfernen. Die Größe
+ eines Elements kann durch Klicken und Ziehen der Anfasser (kleine schwarze
+ Quadrate) an der linken oberen oder der rechten unteren Ecke geändert werden.
+
+
+
+
+
diff --git a/Greenshot/web/htdocs/Help/index.en-US.html b/Greenshot/web/htdocs/Help/index.en-US.html
new file mode 100644
index 000000000..16bb57bc7
--- /dev/null
+++ b/Greenshot/web/htdocs/Help/index.en-US.html
@@ -0,0 +1,100 @@
+
+
+
+ Greenshot Help
+
+
+
+
+
+
+
+ Greenshot Help
+
+ Modes
+
+ Region mode
+
+
+ Activate region mode by hitting the Print key on your keyboard
+ or by choosing Capture region from the context menu.
+ Left-click and drag to define a rectangular area you want to be shot.
+ After releasing the mouse button, the image editor window will open for
+ further editing of your screenshot.
+ For shooting the region again later, choose Capture last region from
+ the context menu.
+
+
+ Window mode
+
+
+ Activate window mode by hitting Alt + Print on your keyboard
+ or by choosing Capture window from the context menu.
+ Click the window you want to be shot.
+ After clicking, the image editor window will open for
+ further editing of your screenshot.
+
+
+ Fullscreen mode
+
+
+ If you want to shoot the complete screen, just press Ctrl + Print on
+ your keyboard or choose Capture full screen from the context menu.
+ The complete screen will be shot instantly, the image editor window will open for
+ further editing of your screenshot.
+
+
+ Image Editor
+
+
+ If you do not want to use the image editor window you can choose to skip
+ in in the context menu or in the settings dialog. The screenshot will be
+ saved directly to a file then. Storage location, filename and image format
+ are defined by your preferred output file settings in the settings dialog.
+
+
+ File menu
+
+
+ Save : saves the image to the file specified in the last Save as... dialog
+ Save as... : lets you choose a path and filename to save the image to
+ Copy image to clipboard : copies the image to the clipboard, for pasting it to other software
+
+
+ Edit menu
+
+
+ Cut selected element to clipboard : removes the selected element and copies it to the clipboard, so that it can be pasted into another image editor window
+ Copy selected element to clipboard : copies it to the clipboard, so that it can be pasted into another image editor window
+ Paste element from clipboard : pastes a previously cut/copied element into the image editor window
+ Duplicate selected element : duplicates the selected element
+
+
+ Object menu
+
+
+ Add rectangle : adds a rectangle to the image
+ Add ellipse : adds an ellipse to the image
+ Add textbox : adds a textbox to the image
+ Delete selected element : removes the selected element from the image
+
+
+
+ Click an element to select it for resizing, moving, copying, cutting, or removal. The size of an
+ element can be defined by dragging the grippers (small black squares) at the top-left and the
+ bottom-right corner of the selected element.
+
+
+
+
+
diff --git a/Greenshot/web/htdocs/favicon.ico b/Greenshot/web/htdocs/favicon.ico
new file mode 100644
index 000000000..0a2ab97c1
Binary files /dev/null and b/Greenshot/web/htdocs/favicon.ico differ
diff --git a/Greenshot/web/htdocs/index.html b/Greenshot/web/htdocs/index.html
new file mode 100644
index 000000000..3ff31a08e
--- /dev/null
+++ b/Greenshot/web/htdocs/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+ Greenshot - Screenshot Tool
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Greenshot.Plugin.Box/Box.png b/GreenshotBoxPlugin/Box.png
similarity index 100%
rename from src/Greenshot.Plugin.Box/Box.png
rename to GreenshotBoxPlugin/Box.png
diff --git a/GreenshotBoxPlugin/BoxConfiguration.cs b/GreenshotBoxPlugin/BoxConfiguration.cs
new file mode 100644
index 000000000..4fb64cd2f
--- /dev/null
+++ b/GreenshotBoxPlugin/BoxConfiguration.cs
@@ -0,0 +1,79 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+using System;
+
+namespace GreenshotBoxPlugin {
+ ///
+ /// Description of ImgurConfiguration.
+ ///
+ [IniSection("Box", Description = "Greenshot Box Plugin configuration")]
+ public class BoxConfiguration : IniSection {
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Box link to clipboard.", DefaultValue = "true")]
+ public bool AfterUploadLinkToClipBoard { get; set; }
+
+ [IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
+ public bool UseSharedLink { get; set; }
+ [IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")]
+ public string FolderId { get; set; }
+
+ [IniProperty("RefreshToken", Description = "Box authorization refresh Token", Encrypted = true)]
+ public string RefreshToken { get; set; }
+
+ ///
+ /// Not stored
+ ///
+ public string AccessToken {
+ get;
+ set;
+ }
+
+ ///
+ /// Not stored
+ ///
+ public DateTimeOffset AccessTokenExpires {
+ get;
+ set;
+ }
+
+ ///
+ /// A form for token
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ DialogResult result = new SettingsForm().ShowDialog();
+ if (result == DialogResult.OK) {
+ return true;
+ }
+ return false;
+ }
+
+ }
+}
diff --git a/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.Credentials.template b/GreenshotBoxPlugin/BoxCredentials.cs
similarity index 79%
rename from src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.Credentials.template
rename to GreenshotBoxPlugin/BoxCredentials.cs
index da2dbc7ae..c2c625889 100644
--- a/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.Credentials.template
+++ b/GreenshotBoxPlugin/BoxCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.Box {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for Box integration.
- /// You can set your own values here
- ///
- public static class BoxCredentials {
- public static string ClientId = "${Box13_ClientId}";
- public static string ClientSecret = "${Box13_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotBoxPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for Box integration.
+ /// You can set your own values here
+ ///
+ public static class BoxCredentials {
+ public static string ClientId = "@credentials_box_client_id@";
+ public static string ClientSecret = "@credentials_box_client_secret@";
+ }
+}
diff --git a/GreenshotBoxPlugin/BoxDestination.cs b/GreenshotBoxPlugin/BoxDestination.cs
new file mode 100644
index 000000000..f76a8bf96
--- /dev/null
+++ b/GreenshotBoxPlugin/BoxDestination.cs
@@ -0,0 +1,63 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotBoxPlugin {
+ public class BoxDestination : AbstractDestination {
+ private readonly BoxPlugin _plugin;
+ public BoxDestination(BoxPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override string Designation {
+ get {
+ return "Box";
+ }
+ }
+
+ public override string Description {
+ get {
+ return Language.GetString("box", LangKey.upload_menu_item);
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(BoxPlugin));
+ return (Image)resources.GetObject("Box");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl = _plugin.Upload(captureDetails, surface);
+ if (uploadUrl != null) {
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = uploadUrl;
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotBoxPlugin/BoxEntities.cs b/GreenshotBoxPlugin/BoxEntities.cs
new file mode 100644
index 000000000..b07282adf
--- /dev/null
+++ b/GreenshotBoxPlugin/BoxEntities.cs
@@ -0,0 +1,59 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace GreenshotBoxPlugin {
+ [DataContract]
+ public class Authorization {
+ [DataMember(Name = "access_token")]
+ public string AccessToken { get; set; }
+ [DataMember(Name = "expires_in")]
+ public int ExpiresIn { get; set; }
+ [DataMember(Name = "refresh_token")]
+ public string RefreshToken { get; set; }
+ [DataMember(Name = "token_type")]
+ public string TokenType { get; set; }
+ }
+ [DataContract]
+ public class SharedLink {
+ [DataMember(Name = "url")]
+ public string Url { get; set; }
+ [DataMember(Name = "download_url")]
+ public string DownloadUrl { get; set; }
+ }
+
+ [DataContract]
+ public class FileEntry {
+ [DataMember(Name = "id")]
+ public string Id { get; set; }
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+ [DataMember(Name = "shared_link")]
+ public SharedLink SharedLink { get; set; }
+ }
+
+ [DataContract]
+ public class Upload {
+ [DataMember(Name = "entries")]
+ public List Entries { get; set; }
+ }
+}
diff --git a/GreenshotBoxPlugin/BoxPlugin.cs b/GreenshotBoxPlugin/BoxPlugin.cs
new file mode 100644
index 000000000..314d2a0d8
--- /dev/null
+++ b/GreenshotBoxPlugin/BoxPlugin.cs
@@ -0,0 +1,140 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotBoxPlugin {
+ ///
+ /// This is the Box base code
+ ///
+ public class BoxPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxPlugin));
+ private static BoxConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new BoxDestination(this);
+ }
+
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute pluginAttribute) {
+ _host = pluginHost;
+ Attributes = pluginAttribute;
+
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(BoxPlugin));
+
+ _itemPlugInConfig = new ToolStripMenuItem {
+ Image = (Image) _resources.GetObject("Box"),
+ Text = Language.GetString("box", LangKey.Configure)
+ };
+ _itemPlugInConfig.Click += ConfigMenuClick;
+
+ PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("box", LangKey.Configure);
+ }
+ }
+
+ public virtual void Shutdown() {
+ LOG.Debug("Box Plugin shutdown.");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ public void ConfigMenuClick(object sender, EventArgs eventArgs) {
+ _config.ShowConfigDialog();
+ }
+
+ ///
+ /// This will be called when the menu item in the Editor is clicked
+ ///
+ public string Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
+ try {
+ string url = null;
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
+ SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+
+ new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("box", LangKey.communication_wait),
+ delegate {
+ url = BoxUtils.UploadToBox(imageToUpload, captureDetails.Title, filename);
+ }
+ );
+
+ if (url != null && _config.AfterUploadLinkToClipBoard) {
+ ClipboardHelper.SetClipboardData(url);
+ }
+
+ return url;
+ } catch (Exception ex) {
+ LOG.Error("Error uploading.", ex);
+ MessageBox.Show(Language.GetString("box", LangKey.upload_failure) + " " + ex.Message);
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Box/BoxPlugin.resx b/GreenshotBoxPlugin/BoxPlugin.resx
similarity index 93%
rename from src/Greenshot.Plugin.Box/BoxPlugin.resx
rename to GreenshotBoxPlugin/BoxPlugin.resx
index d54439ba4..57b6289de 100644
--- a/src/Greenshot.Plugin.Box/BoxPlugin.resx
+++ b/GreenshotBoxPlugin/BoxPlugin.resx
@@ -112,13 +112,13 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
- box.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+ box.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
\ No newline at end of file
diff --git a/GreenshotBoxPlugin/BoxUtils.cs b/GreenshotBoxPlugin/BoxUtils.cs
new file mode 100644
index 000000000..4f375a28c
--- /dev/null
+++ b/GreenshotBoxPlugin/BoxUtils.cs
@@ -0,0 +1,151 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Runtime.Serialization.Json;
+using System.Text;
+
+namespace GreenshotBoxPlugin {
+
+ ///
+ /// Description of ImgurUtils.
+ ///
+ public static class BoxUtils {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils));
+ private static readonly BoxConfiguration Config = IniConfig.GetIniSection();
+ private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content";
+ private const string FilesUri = "https://www.box.com/api/2.0/files/{0}";
+
+ ///
+ /// Put string
+ ///
+ ///
+ ///
+ /// OAuth2Settings
+ /// response
+ public static string HttpPut(string url, string content, OAuth2Settings settings) {
+ var webRequest= OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.PUT, url, settings);
+
+ byte[] data = Encoding.UTF8.GetBytes(content);
+ using (var requestStream = webRequest.GetRequestStream()) {
+ requestStream.Write(data, 0, data.Length);
+ }
+ return NetworkHelper.GetResponseAsString(webRequest);
+ }
+
+ ///
+ /// Do the actual upload to Box
+ /// For more details on the available parameters, see: http://developers.box.net/w/page/12923951/ApiFunction_Upload%20and%20Download
+ ///
+ /// Image for box upload
+ /// Title of box upload
+ /// Filename of box upload
+ /// url to uploaded image
+ public static string UploadToBox(SurfaceContainer image, string title, string filename) {
+
+ // Fill the OAuth2Settings
+ var settings = new OAuth2Settings
+ {
+ AuthUrlPattern = "https://app.box.com/api/oauth2/authorize?client_id={ClientId}&response_type=code&state={State}&redirect_uri={RedirectUrl}",
+ TokenUrl = "https://api.box.com/oauth2/token",
+ CloudServiceName = "Box",
+ ClientId = BoxCredentials.ClientId,
+ ClientSecret = BoxCredentials.ClientSecret,
+ RedirectUrl = "https://www.box.com/home/",
+ BrowserSize = new Size(1060, 600),
+ AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser,
+ RefreshToken = Config.RefreshToken,
+ AccessToken = Config.AccessToken,
+ AccessTokenExpires = Config.AccessTokenExpires
+ };
+
+
+ // Copy the settings from the config, which is kept in memory and on the disk
+
+ try {
+ var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings);
+ IDictionary parameters = new Dictionary();
+ parameters.Add("file", image);
+ parameters.Add("parent_id", Config.FolderId);
+
+ NetworkHelper.WriteMultipartFormData(webRequest, parameters);
+
+ var response = NetworkHelper.GetResponseAsString(webRequest);
+
+ Log.DebugFormat("Box response: {0}", response);
+
+ var upload = JsonSerializer.Deserialize(response);
+ if (upload?.Entries == null || upload.Entries.Count == 0) return null;
+
+ if (Config.UseSharedLink) {
+ string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}", settings);
+ var file = JsonSerializer.Deserialize(filesResponse);
+ return file.SharedLink.Url;
+ }
+ return $"http://www.box.com/files/0/f/0/1/f_{upload.Entries[0].Id}";
+ } finally {
+ // Copy the settings back to the config, so they are stored.
+ Config.RefreshToken = settings.RefreshToken;
+ Config.AccessToken = settings.AccessToken;
+ Config.AccessTokenExpires = settings.AccessTokenExpires;
+ Config.IsDirty = true;
+ IniConfig.Save();
+ }
+ }
+ }
+ ///
+ /// A simple helper class for the DataContractJsonSerializer
+ ///
+ internal static class JsonSerializer {
+ ///
+ /// Helper method to serialize object to JSON
+ ///
+ /// JSON object
+ /// string
+ public static string Serialize(object jsonObject) {
+ var serializer = new DataContractJsonSerializer(jsonObject.GetType());
+ using (MemoryStream stream = new MemoryStream()) {
+ serializer.WriteObject(stream, jsonObject);
+ return Encoding.UTF8.GetString(stream.ToArray());
+ }
+ }
+
+ ///
+ /// Helper method to parse JSON to object
+ ///
+ ///
+ ///
+ ///
+ public static T Deserialize(string jsonString) {
+ var deserializer = new DataContractJsonSerializer(typeof(T));
+ using (MemoryStream stream = new MemoryStream()) {
+ byte[] content = Encoding.UTF8.GetBytes(jsonString);
+ stream.Write(content, 0, content.Length);
+ stream.Seek(0, SeekOrigin.Begin);
+ return (T)deserializer.ReadObject(stream);
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Forms/EditorForm.cs b/GreenshotBoxPlugin/Forms/BoxForm.cs
similarity index 69%
rename from src/Greenshot.Editor/Forms/EditorForm.cs
rename to GreenshotBoxPlugin/Forms/BoxForm.cs
index 402032d8e..51473ad06 100644
--- a/src/Greenshot.Editor/Forms/EditorForm.cs
+++ b/GreenshotBoxPlugin/Forms/BoxForm.cs
@@ -1,29 +1,26 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Editor.Forms
-{
- public class EditorForm : GreenshotForm
- {
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using GreenshotPlugin.Controls;
+
+namespace GreenshotBoxPlugin.Forms {
+ public class BoxForm : GreenshotForm {
+ }
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs b/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
similarity index 79%
rename from src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs
rename to GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
index 940eaccb6..2eaf2b790 100644
--- a/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs
+++ b/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Box.Forms {
+namespace GreenshotBoxPlugin {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,12 +46,12 @@ namespace Greenshot.Plugin.Box.Forms {
///
private void InitializeComponent()
{
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.label_AfterUpload = new GreenshotLabel();
- this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.SuspendLayout();
//
// buttonOK
@@ -87,7 +84,7 @@ namespace Greenshot.Plugin.Box.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(208, 12);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(BoxConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Box";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(215, 21);
this.combobox_uploadimageformat.TabIndex = 5;
@@ -112,10 +109,11 @@ namespace Greenshot.Plugin.Box.Forms {
// checkboxAfterUploadLinkToClipBoard
//
this.checkboxAfterUploadLinkToClipBoard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.checkboxAfterUploadLinkToClipBoard.AutoSize = true;
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "box.label_AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(208, 45);
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
- this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(BoxConfiguration.AfterUploadLinkToClipBoard);
+ this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Box";
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 10;
@@ -141,11 +139,11 @@ namespace Greenshot.Plugin.Box.Forms {
this.PerformLayout();
}
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotLabel label_AfterUpload;
- private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
}
}
diff --git a/GreenshotBoxPlugin/Forms/SettingsForm.cs b/GreenshotBoxPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..df1c50134
--- /dev/null
+++ b/GreenshotBoxPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,38 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotBoxPlugin.Forms;
+
+namespace GreenshotBoxPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : BoxForm {
+ public SettingsForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = buttonOK;
+ CancelButton = buttonCancel;
+ }
+ }
+}
diff --git a/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj
new file mode 100644
index 000000000..1df2862d1
--- /dev/null
+++ b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj
@@ -0,0 +1,90 @@
+
+
+
+
+ {697CF066-9077-4F22-99D9-D989CCE7282B}
+ Library
+ GreenshotBoxPlugin
+ GreenshotBoxPlugin
+ v3.5
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+
+
+
+
+
+ 3.5
+
+
+
+
+ False
+ ..\Greenshot\lib\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+ BoxPlugin.cs
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+ if exist "$(ProjectDir)BoxCredentials.orig.cs" (
+ rename "$(ProjectDir)BoxCredentials.cs" "BoxCredentials.private.cs"
+ rename "$(ProjectDir)BoxCredentials.orig.cs" "BoxCredentials.cs"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+if exist "$(ProjectDir)BoxCredentials.private.cs" (
+ rename "$(ProjectDir)BoxCredentials.cs" "BoxCredentials.orig.cs"
+ rename "$(ProjectDir)BoxCredentials.private.cs" "BoxCredentials.cs"
+)
+
+
\ No newline at end of file
diff --git a/GreenshotBoxPlugin/LanguageKeys.cs b/GreenshotBoxPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..a6e170688
--- /dev/null
+++ b/GreenshotBoxPlugin/LanguageKeys.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotBoxPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ settings_title,
+ label_upload_format,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ Configure,
+ label_AfterUpload,
+ label_AfterUploadLinkToClipBoard
+ }
+}
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-cs-CZ.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-cs-CZ.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-cs-CZ.xml
index cdd666573..855606bba 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-cs-CZ.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-cs-CZ.xml
@@ -1,24 +1,24 @@
-
-
-
- Zrušit
- Komunikace s Box. Počkejte prosím...
- Konfigurovat
- Jste si jistý, že chcete odstranit obrázek {0} z Box?
- Odstranit Box {0}
- Historie
- Po odeslání
- Odkaz do schránky
- Otevřít historii
- Ověření Token
- Výchozí velikost
- Formát obrázku
- OK
- Nastavení
- Prosím ověřit dostupnost aplikace Box. Nastavení přístupu.
- Odeslat
- Při odesílání do Box došlo k chybě:
- Odeslat do Box
- Obrázek úspěšně odeslán do Box!
-
+
+
+
+ Zrušit
+ Komunikace s Box. Počkejte prosím...
+ Konfigurovat
+ Jste si jistý, že chcete odstranit obrázek {0} z Box?
+ Odstranit Box {0}
+ Historie
+ Po odeslání
+ Odkaz do schránky
+ Otevřít historii
+ Ověření Token
+ Výchozí velikost
+ Formát obrázku
+ OK
+ Nastavení
+ Prosím ověřit dostupnost aplikace Box. Nastavení přístupu.
+ Odeslat
+ Při odesílání do Box došlo k chybě:
+ Odeslat do Box
+ Obrázek úspěšně odeslán do Box!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-de-DE.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-de-DE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-de-DE.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-de-DE.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-en-US.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-en-US.xml
similarity index 94%
rename from src/Greenshot.Plugin.Box/Languages/language_box-en-US.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-en-US.xml
index 5afc491b8..181603529 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-en-US.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-en-US.xml
@@ -20,7 +20,7 @@
Successfully uploaded image to Box!
- An error occurred while uploading to Box:
+ An error occured while uploading to Box:
Image format
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-fr-FR.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-fr-FR.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-fr-FR.xml
index fd274499c..fd8e7a72f 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-fr-FR.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-fr-FR.xml
@@ -1,14 +1,14 @@
-
-
-
- Communication en cours avec le service de stockage en ligne. Veuillez patientez...
- Configurer Box
- Après téléversement
- Copier le lien dans le presse-papier
- Format image
- Paramètres du stockage en ligne
- Une erreur s'est produite lors du téléversement vers le stockage en ligne :
- Téléverser vers le stockage en ligne
- Image téléversée aves succès vers le stockage en ligne !
-
+
+
+
+ Communication en cours avec le service de stockage en ligne. Veuillez patientez...
+ Configurer Box
+ Après téléversement
+ Copier le lien dans le presse-papier
+ Format image
+ Paramètres du stockage en ligne
+ Une erreur s'est produite lors du téléversement vers le stockage en ligne :
+ Téléverser vers le stockage en ligne
+ Image téléversée aves succès vers le stockage en ligne !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-id-ID.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-id-ID.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-id-ID.xml
index 717bf542e..350b948ee 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-id-ID.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-id-ID.xml
@@ -1,14 +1,14 @@
-
-
-
- Menyambungkan ke Box. Tunggu sebentar...
- Konfigurasi Box
- Setelah Diunggah
- Sambung ke papanklip
- Format gambar
- Setelan Box
- Kesalahan terjadi ketika mengunggah ke Box:
- Unggah ke Box
- Gambar telah berhasil diunggah ke Box!
-
+
+
+
+ Menyambungkan ke Box. Tunggu sebentar...
+ Konfigurasi Box
+ Setelah Diunggah
+ Sambung ke papanklip
+ Format gambar
+ Setelan Box
+ Kesalahan terjadi ketika mengunggah ke Box:
+ Unggah ke Box
+ Gambar telah berhasil diunggah ke Box!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-it-IT.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-it-IT.xml
similarity index 74%
rename from src/Greenshot.Plugin.Box/Languages/language_box-it-IT.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-it-IT.xml
index 786acfac8..e53e65909 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-it-IT.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-it-IT.xml
@@ -1,14 +1,14 @@
-
+
- Collegamento agli Appunti
+ Collegamento agli appunti
- Dopo il caricamento
+ Dopo il carico
- Impostazioni di Box
+ Configurazione di Box
Carica su Box
@@ -17,7 +17,7 @@
Impostazioni di Box
- caricamento immagine su Box completato!
+ Immagine caricata correttamente su Box!
Si è verificato un errore durante il caricamento su Box:
@@ -26,7 +26,7 @@
Formato immagine
- Comunicazione con Box...
+ Comunicazione con Box. Attendere prego...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-kab-DZ.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-kab-DZ.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-ko-KR.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-ko-KR.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-lv-LV.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-lv-LV.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-pl-PL.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-pl-PL.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-pl-PL.xml
index 283acee1b..d0a6833ef 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-pl-PL.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-pl-PL.xml
@@ -1,14 +1,14 @@
-
-
-
- Trwa komunikacja z Box. Proszę czekać...
- Konfiguruj Box
- Po wysłaniu
- Link do schowka
- Format obrazu
- Ustawienia Box
- Wystąpił błąd przy wysyłaniu do Box:
- Wyślij do Box
- Wysyłanie obrazu do Box powiodło się!
-
+
+
+
+ Trwa komunikacja z Box. Proszę czekać...
+ Konfiguruj Box
+ Po wysłaniu
+ Link do schowka
+ Format obrazu
+ Ustawienia Box
+ Wystąpił błąd przy wysyłaniu do Box:
+ Wyślij do Box
+ Wysyłanie obrazu do Box powiodło się!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-pt-PT.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-pt-PT.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-ru-RU.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-ru-RU.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-ru-RU.xml
index 0f3b06e95..ae9e33d94 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-ru-RU.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-ru-RU.xml
@@ -1,14 +1,14 @@
-
-
-
- Обмен данными с Box. Подождите...
- Настройка Box
- После загрузки
- Ссылка в буфер обмена
- Формат изображения
- Параметры Box
- Произошла ошибка при загрузке на Box:
- Загрузить на Box
- Изображение успешно загружено на Box!
-
+
+
+
+ Обмен данными с Box. Подождите...
+ Настройка Box
+ После загрузки
+ Ссылка в буфер обмена
+ Формат изображения
+ Параметры Box
+ Произошла ошибка при загрузке на Box:
+ Загрузить на Box
+ Изображение успешно загружено на Box!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-sr-RS.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-sr-RS.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-sr-RS.xml
index 802f69337..c29c77258 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-sr-RS.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-sr-RS.xml
@@ -1,14 +1,14 @@
-
-
-
- Комуницирам с Боксом. Сачекајте…
- Поставке Бокса
- Након отпремања:
- Веза ка остави
- Формат слике:
- Поставке Бокса
- Дошло је до грешке при отпремању на Бокс:
- Отпреми на Бокс
- Слика је успешно отпремљена на Бокс.
-
+
+
+
+ Комуницирам с Боксом. Сачекајте…
+ Поставке Бокса
+ Након отпремања:
+ Веза ка остави
+ Формат слике:
+ Поставке Бокса
+ Дошло је до грешке при отпремању на Бокс:
+ Отпреми на Бокс
+ Слика је успешно отпремљена на Бокс.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-sv-SE.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Box/Languages/language_box-sv-SE.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-uk-UA.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-uk-UA.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-uk-UA.xml
index 2e6e470d9..82a6d3aac 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-uk-UA.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-uk-UA.xml
@@ -1,14 +1,14 @@
-
-
-
- Посилання в буфер обміну
- Після вивантаження
- Налаштувати Box
- Вивантажити на Box
- Параметри Box
- Зображення вдало вивантажено на Box!
- Відбулась помилка під час вивантаження на Box:
- Формат зображення
- З’єднання з Box. Будь ласка, зачекайте...
-
-
+
+
+
+ Посилання в буфер обміну
+ Після вивантаження
+ Налаштувати Box
+ Вивантажити на Box
+ Параметри Box
+ Зображення вдало вивантажено на Box!
+ Відбулась помилка під час вивантаження на Box:
+ Формат зображення
+ З’єднання з Box. Будь ласка, зачекайте...
+
+
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-zh-CN.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-zh-CN.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-zh-CN.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-zh-CN.xml
index 2621bc688..1eb7f88f2 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-zh-CN.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-zh-CN.xml
@@ -1,14 +1,14 @@
-
-
-
- 正在连接Box。请稍后...
- 配置Box
- 上传之后
- 复制链接到剪贴板
- 图片格式
- Box设置
- 上传图片到Box时发生错误:
- 上传到Box
- 图片已成功上传到Box!
-
+
+
+
+ 正在连接Box。请稍后...
+ 配置Box
+ 上传之后
+ 复制链接到剪贴板
+ 图片格式
+ Box设置
+ 上传图片到Box时发生错误:
+ 上传到Box
+ 图片已成功上传到Box!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Languages/language_box-zh-TW.xml b/GreenshotBoxPlugin/Languages/language_boxplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Box/Languages/language_box-zh-TW.xml
rename to GreenshotBoxPlugin/Languages/language_boxplugin-zh-TW.xml
index 9b0f98e47..c8f9a2d61 100644
--- a/src/Greenshot.Plugin.Box/Languages/language_box-zh-TW.xml
+++ b/GreenshotBoxPlugin/Languages/language_boxplugin-zh-TW.xml
@@ -1,14 +1,14 @@
-
-
-
- 正在與 Box 通訊,請稍候...
- 組態 Box
- 上傳後
- 連結到剪貼簿
- 圖片格式
- Box 設定
- 上傳到 Box 時發生錯誤:
- 上傳到 Box
- 上傳圖片到 Box 成功!
-
+
+
+
+ 正在與 Box 通訊,請稍候...
+ 組態 Box
+ 上傳後
+ 連結到剪貼簿
+ 圖片格式
+ Box 設定
+ 上傳到 Box 時發生錯誤:
+ 上傳到 Box
+ 上傳圖片到 Box 成功!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Box/Properties/AssemblyInfo.cs b/GreenshotBoxPlugin/Properties/AssemblyInfo.cs
similarity index 58%
rename from src/Greenshot.Plugin.Box/Properties/AssemblyInfo.cs
rename to GreenshotBoxPlugin/Properties/AssemblyInfo.cs
index 0379e4a65..2eda350e4 100644
--- a/src/Greenshot.Plugin.Box/Properties/AssemblyInfo.cs
+++ b/GreenshotBoxPlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
+[assembly: AssemblyTitle("Greenshot-Box-Plugin")]
[assembly: AssemblyDescription("A plugin to upload images to Box")]
-[assembly: AssemblyPluginIdentifier("Box Plugin")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot & F. Noel")]
+[assembly: AssemblyProduct("Box Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotBoxPlugin.BoxPlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/GreenshotConfluencePlugin/Confluence.cs b/GreenshotConfluencePlugin/Confluence.cs
new file mode 100644
index 000000000..fdda7c31b
--- /dev/null
+++ b/GreenshotConfluencePlugin/Confluence.cs
@@ -0,0 +1,310 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotConfluencePlugin;
+using GreenshotConfluencePlugin.confluence;
+using GreenshotPlugin.Core;
+
+namespace Confluence {
+ #region transport classes
+ public class Page {
+ public Page(RemotePage page) {
+ Id = page.id;
+ Title = page.title;
+ SpaceKey = page.space;
+ Url = page.url;
+ Content = page.content;
+ }
+ public Page(RemoteSearchResult searchResult, string space) {
+ Id = searchResult.id;
+ Title = searchResult.title;
+ SpaceKey = space;
+ Url = searchResult.url;
+ Content = searchResult.excerpt;
+ }
+
+ public Page(RemotePageSummary pageSummary) {
+ Id = pageSummary.id;
+ Title = pageSummary.title;
+ SpaceKey = pageSummary.space;
+ Url =pageSummary.url;
+ }
+ public long Id {
+ get;
+ set;
+ }
+ public string Title {
+ get;
+ set;
+ }
+ public string Url {
+ get;
+ set;
+ }
+ public string Content {
+ get;
+ set;
+ }
+ public string SpaceKey {
+ get;
+ set;
+ }
+ }
+ public class Space {
+ public Space(RemoteSpaceSummary space) {
+ Key = space.key;
+ Name = space.name;
+ }
+ public string Key {
+ get;
+ set;
+ }
+ public string Name {
+ get;
+ set;
+ }
+ }
+ #endregion
+
+ ///
+ /// For details see the Confluence API site
+ /// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
+ ///
+ public class ConfluenceConnector : IDisposable {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceConnector));
+ private const string AuthFailedExceptionName = "com.atlassian.confluence.rpc.AuthenticationFailedException";
+ private const string V2Failed = "AXIS";
+ private static readonly ConfluenceConfiguration Config = IniConfig.GetIniSection();
+ private string _credentials;
+ private DateTime _loggedInTime = DateTime.Now;
+ private bool _loggedIn;
+ private ConfluenceSoapServiceService _confluence;
+ private readonly int _timeout;
+ private string _url;
+ private readonly Cache _pageCache = new Cache(60 * Config.Timeout);
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing) {
+ if (_confluence != null) {
+ Logout();
+ }
+ if (disposing) {
+ if (_confluence != null) {
+ _confluence.Dispose();
+ _confluence = null;
+ }
+ }
+ }
+
+ public ConfluenceConnector(string url, int timeout) {
+ _timeout = timeout;
+ Init(url);
+ }
+
+ private void Init(string url) {
+ _url = url;
+ _confluence = new ConfluenceSoapServiceService
+ {
+ Url = url,
+ Proxy = NetworkHelper.CreateProxy(new Uri(url))
+ };
+ }
+
+ ~ConfluenceConnector() {
+ Dispose(false);
+ }
+
+ ///
+ /// Internal login which catches the exceptions
+ ///
+ /// true if login was done sucessfully
+ private bool DoLogin(string user, string password) {
+ try {
+ _credentials = _confluence.login(user, password);
+ _loggedInTime = DateTime.Now;
+ _loggedIn = true;
+ } catch (Exception e) {
+ // Check if confluence-v2 caused an error, use v1 instead
+ if (e.Message.Contains(V2Failed) && _url.Contains("v2")) {
+ Init(_url.Replace("v2", "v1"));
+ return DoLogin(user, password);
+ }
+ // check if auth failed
+ if (e.Message.Contains(AuthFailedExceptionName)) {
+ return false;
+ }
+ // Not an authentication issue
+ _loggedIn = false;
+ _credentials = null;
+ e.Data.Add("user", user);
+ e.Data.Add("url", _url);
+ throw;
+ }
+ return true;
+ }
+
+ public void Login() {
+ Logout();
+ try {
+ // Get the system name, so the user knows where to login to
+ string systemName = _url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1,"");
+ systemName = systemName.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, "");
+ CredentialsDialog dialog = new CredentialsDialog(systemName)
+ {
+ Name = null
+ };
+ while (dialog.Show(dialog.Name) == DialogResult.OK) {
+ if (DoLogin(dialog.Name, dialog.Password)) {
+ if (dialog.SaveChecked) {
+ dialog.Confirm(true);
+ }
+ return;
+ } else {
+ try {
+ dialog.Confirm(false);
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+ // For every windows version after XP show an incorrect password baloon
+ dialog.IncorrectPassword = true;
+ // Make sure the dialog is display, the password was false!
+ dialog.AlwaysDisplay = true;
+ }
+ }
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+ }
+
+ public void Logout() {
+ if (_credentials != null) {
+ _confluence.logout(_credentials);
+ _credentials = null;
+ _loggedIn = false;
+ }
+ }
+
+ private void CheckCredentials() {
+ if (_loggedIn) {
+ if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
+ Logout();
+ Login();
+ }
+ } else {
+ Login();
+ }
+ }
+
+ public bool IsLoggedIn => _loggedIn;
+
+ public void AddAttachment(long pageId, string mime, string comment, string filename, IBinaryContainer image) {
+ CheckCredentials();
+ // Comment is ignored, see: http://jira.atlassian.com/browse/CONF-9395
+ var attachment = new RemoteAttachment
+ {
+ comment = comment,
+ fileName = filename,
+ contentType = mime
+ };
+ _confluence.addAttachment(_credentials, pageId, attachment, image.ToByteArray());
+ }
+
+ public Page GetPage(string spaceKey, string pageTitle) {
+ RemotePage page = null;
+ string cacheKey = spaceKey + pageTitle;
+ if (_pageCache.Contains(cacheKey)) {
+ page = _pageCache[cacheKey];
+ }
+ if (page == null) {
+ CheckCredentials();
+ page = _confluence.getPage(_credentials, spaceKey, pageTitle);
+ _pageCache.Add(cacheKey, page);
+ }
+ return new Page(page);
+ }
+
+ public Page GetPage(long pageId) {
+ RemotePage page = null;
+ string cacheKey = "" + pageId;
+
+ if (_pageCache.Contains(cacheKey)) {
+ page = _pageCache[cacheKey];
+ }
+ if (page == null) {
+ CheckCredentials();
+ page = _confluence.getPage(_credentials, pageId);
+ _pageCache.Add(cacheKey, page);
+ }
+ return new Page(page);
+ }
+
+ public Page GetSpaceHomepage(Space spaceSummary) {
+ CheckCredentials();
+ RemoteSpace spaceDetail = _confluence.getSpace(_credentials, spaceSummary.Key);
+ RemotePage page = _confluence.getPage(_credentials, spaceDetail.homePage);
+ return new Page(page);
+ }
+
+ public IEnumerable GetSpaceSummaries() {
+ CheckCredentials();
+ RemoteSpaceSummary [] spaces = _confluence.getSpaces(_credentials);
+ foreach(RemoteSpaceSummary space in spaces) {
+ yield return new Space(space);
+ }
+ }
+
+ public IEnumerable GetPageChildren(Page parentPage) {
+ CheckCredentials();
+ RemotePageSummary[] pages = _confluence.getChildren(_credentials, parentPage.Id);
+ foreach(RemotePageSummary page in pages) {
+ yield return new Page(page);
+ }
+ }
+
+ public IEnumerable GetPageSummaries(Space space) {
+ CheckCredentials();
+ RemotePageSummary[] pages = _confluence.getPages(_credentials, space.Key);
+ foreach(RemotePageSummary page in pages) {
+ yield return new Page(page);
+ }
+ }
+
+ public IEnumerable SearchPages(string query, string space) {
+ CheckCredentials();
+ foreach(var searchResult in _confluence.search(_credentials, query, 20)) {
+ Log.DebugFormat("Got result of type {0}", searchResult.type);
+ if ("page".Equals(searchResult.type))
+ {
+ yield return new Page(searchResult, space);
+ }
+ }
+ }
+ }
+}
diff --git a/GreenshotConfluencePlugin/ConfluenceConfiguration.cs b/GreenshotConfluencePlugin/ConfluenceConfiguration.cs
new file mode 100644
index 000000000..a64fbe8fd
--- /dev/null
+++ b/GreenshotConfluencePlugin/ConfluenceConfiguration.cs
@@ -0,0 +1,84 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Description of ConfluenceConfiguration.
+ ///
+ [Serializable]
+ [IniSection("Confluence", Description="Greenshot Confluence Plugin configuration")]
+ public class ConfluenceConfiguration : IniSection {
+ public const string DEFAULT_POSTFIX1 = "/rpc/soap-axis/confluenceservice-v1?wsdl";
+ public const string DEFAULT_POSTFIX2 = "/rpc/soap-axis/confluenceservice-v2?wsdl";
+ public const string DEFAULT_PREFIX = "http://";
+ private const string DEFAULT_URL = DEFAULT_PREFIX + "confluence";
+
+ [IniProperty("Url", Description="Url to Confluence system, including wsdl.", DefaultValue=DEFAULT_URL)]
+ public string Url {
+ get;
+ set;
+ }
+ [IniProperty("Timeout", Description="Session timeout in minutes", DefaultValue="30")]
+ public int Timeout {
+ get;
+ set;
+ }
+
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat {
+ get;
+ set;
+ }
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality {
+ get;
+ set;
+ }
+ [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
+ public bool UploadReduceColors {
+ get;
+ set;
+ }
+ [IniProperty("OpenPageAfterUpload", Description="Open the page where the picture is uploaded after upload", DefaultValue="True")]
+ public bool OpenPageAfterUpload {
+ get;
+ set;
+ }
+ [IniProperty("CopyWikiMarkupForImageToClipboard", Description="Copy the Wikimarkup for the recently uploaded image to the Clipboard", DefaultValue="True")]
+ public bool CopyWikiMarkupForImageToClipboard {
+ get;
+ set;
+ }
+ [IniProperty("SearchSpaceKey", Description="Key of last space that was searched for")]
+ public string SearchSpaceKey {
+ get;
+ set;
+ }
+ [IniProperty("IncludePersonSpaces", Description = "Include personal spaces in the search & browse spaces list", DefaultValue = "False")]
+ public bool IncludePersonSpaces {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotConfluencePlugin/ConfluenceDestination.cs b/GreenshotConfluencePlugin/ConfluenceDestination.cs
new file mode 100644
index 000000000..50330f109
--- /dev/null
+++ b/GreenshotConfluencePlugin/ConfluenceDestination.cs
@@ -0,0 +1,203 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Threading;
+using System.Windows;
+using Confluence;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Description of ConfluenceDestination.
+ ///
+ public class ConfluenceDestination : AbstractDestination {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceDestination));
+ private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly Image ConfluenceIcon;
+ private readonly Page _page;
+
+ public static bool IsInitialized {
+ get;
+ private set;
+ }
+ static ConfluenceDestination() {
+ IsInitialized = false;
+ try {
+ Uri confluenceIconUri = new Uri("/GreenshotConfluencePlugin;component/Images/Confluence.ico", UriKind.Relative);
+ using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
+ {
+ // TODO: Check what to do with the IImage
+ ConfluenceIcon = ImageHelper.FromStream(iconStream);
+ }
+ IsInitialized = true;
+ } catch (Exception ex) {
+ Log.ErrorFormat("Problem in the confluence static initializer: {0}", ex.Message);
+ }
+ }
+
+ public ConfluenceDestination() {
+ }
+
+ public ConfluenceDestination(Page page) {
+ _page = page;
+ }
+
+ public override string Designation {
+ get {
+ return "Confluence";
+ }
+ }
+
+ public override string Description {
+ get {
+ if (_page == null) {
+ return Language.GetString("confluence", LangKey.upload_menu_item);
+ } else {
+ return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + _page.Title + "\"";
+ }
+ }
+ }
+
+ public override bool IsDynamic {
+ get {
+ return true;
+ }
+ }
+
+ public override bool IsActive {
+ get {
+ return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url);
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return ConfluenceIcon;
+ }
+ }
+
+ public override IEnumerable DynamicDestinations() {
+ if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn) {
+ yield break;
+ }
+ List currentPages = ConfluenceUtils.GetCurrentPages();
+ if (currentPages == null || currentPages.Count == 0) {
+ yield break;
+ }
+ foreach(Page currentPage in currentPages) {
+ yield return new ConfluenceDestination(currentPage);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ // force password check to take place before the pages load
+ if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn) {
+ return exportInformation;
+ }
+
+ Page selectedPage = _page;
+ bool openPage = (_page == null) && ConfluenceConfig.OpenPageAfterUpload;
+ string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails);
+ if (selectedPage == null) {
+ ConfluenceUpload confluenceUpload = new ConfluenceUpload(filename);
+ bool? dialogResult = confluenceUpload.ShowDialog();
+ if (dialogResult.HasValue && dialogResult.Value) {
+ selectedPage = confluenceUpload.SelectedPage;
+ if (confluenceUpload.IsOpenPageSelected) {
+ openPage = false;
+ }
+ filename = confluenceUpload.Filename;
+ }
+ }
+ string extension = "." + ConfluenceConfig.UploadFormat;
+ if (!filename.ToLower().EndsWith(extension)) {
+ filename = filename + extension;
+ }
+ if (selectedPage != null) {
+ string errorMessage;
+ bool uploaded = Upload(surface, selectedPage, filename, out errorMessage);
+ if (uploaded) {
+ if (openPage) {
+ try
+ {
+ Process.Start(selectedPage.Url);
+ }
+ catch
+ {
+ // Ignore
+ }
+ }
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = selectedPage.Url;
+ } else {
+ exportInformation.ErrorMessage = errorMessage;
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+
+ private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors);
+ errorMessage = null;
+ try {
+ new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait),
+ delegate {
+ ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ }
+ );
+ Log.Debug("Uploaded to Confluence.");
+ if (!ConfluenceConfig.CopyWikiMarkupForImageToClipboard)
+ {
+ return true;
+ }
+ int retryCount = 2;
+ while (retryCount >= 0) {
+ try {
+ Clipboard.SetText("!" + filename + "!");
+ break;
+ } catch (Exception ee) {
+ if (retryCount == 0) {
+ Log.Error(ee);
+ } else {
+ Thread.Sleep(100);
+ }
+ } finally {
+ --retryCount;
+ }
+ }
+ return true;
+ } catch(Exception e) {
+ errorMessage = e.Message;
+ }
+ return false;
+ }
+ }
+}
diff --git a/GreenshotConfluencePlugin/ConfluencePlugin.cs b/GreenshotConfluencePlugin/ConfluencePlugin.cs
new file mode 100644
index 000000000..eabc34b19
--- /dev/null
+++ b/GreenshotConfluencePlugin/ConfluencePlugin.cs
@@ -0,0 +1,143 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Confluence;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using TranslationByMarkupExtension;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// This is the ConfluencePlugin base code
+ ///
+ public class ConfluencePlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluencePlugin));
+ private static ConfluenceConnector _confluenceConnector;
+ private static ConfluenceConfiguration _config;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ //if (disposing) {}
+ }
+
+ private static void CreateConfluenceConntector() {
+ if (_confluenceConnector == null) {
+ if (_config.Url.Contains("soap-axis")) {
+ _confluenceConnector = new ConfluenceConnector(_config.Url, _config.Timeout);
+ } else {
+ _confluenceConnector = new ConfluenceConnector(_config.Url + ConfluenceConfiguration.DEFAULT_POSTFIX2, _config.Timeout);
+ }
+ }
+ }
+
+ public static ConfluenceConnector ConfluenceConnectorNoLogin {
+ get {
+ return _confluenceConnector;
+ }
+ }
+
+ public static ConfluenceConnector ConfluenceConnector {
+ get {
+ if (_confluenceConnector == null) {
+ CreateConfluenceConntector();
+ }
+ try {
+ if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn) {
+ _confluenceConnector.Login();
+ }
+ } catch (Exception e) {
+ MessageBox.Show(Language.GetFormattedString("confluence", LangKey.login_error, e.Message));
+ }
+ return _confluenceConnector;
+ }
+ }
+
+ public IEnumerable Destinations() {
+ if (ConfluenceDestination.IsInitialized) {
+ yield return new ConfluenceDestination();
+ }
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+ if(_config.IsDirty) {
+ IniConfig.Save();
+ }
+ try {
+ TranslationManager.Instance.TranslationProvider = new LanguageXMLTranslationProvider();
+ //resources = new ComponentResourceManager(typeof(ConfluencePlugin));
+ } catch (Exception ex) {
+ LOG.ErrorFormat("Problem in ConfluencePlugin.Initialize: {0}", ex.Message);
+ return false;
+ }
+ return true;
+ }
+
+ public virtual void Shutdown() {
+ LOG.Debug("Confluence Plugin shutdown.");
+ if (_confluenceConnector != null) {
+ _confluenceConnector.Logout();
+ _confluenceConnector = null;
+ }
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ ConfluenceConfiguration clonedConfig = _config.Clone();
+ ConfluenceConfigurationForm configForm = new ConfluenceConfigurationForm(clonedConfig);
+ string url = _config.Url;
+ bool? dialogResult = configForm.ShowDialog();
+ if (dialogResult.HasValue && dialogResult.Value) {
+ // copy the new object to the old...
+ clonedConfig.CloneTo(_config);
+ IniConfig.Save();
+ if (_confluenceConnector != null) {
+ if (!url.Equals(_config.Url)) {
+ if (_confluenceConnector.IsLoggedIn) {
+ _confluenceConnector.Logout();
+ }
+ _confluenceConnector = null;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/GreenshotConfluencePlugin/ConfluenceUtils.cs b/GreenshotConfluencePlugin/ConfluenceUtils.cs
new file mode 100644
index 000000000..19c417136
--- /dev/null
+++ b/GreenshotConfluencePlugin/ConfluenceUtils.cs
@@ -0,0 +1,151 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Windows.Automation;
+
+using GreenshotPlugin.Core;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Description of ConfluenceUtils.
+ ///
+ public class ConfluenceUtils {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceUtils));
+
+ public static List GetCurrentPages() {
+ List pages = new List();
+ Regex pageIdRegex = new Regex(@"pageId=(\d+)");
+ Regex spacePageRegex = new Regex(@"\/display\/([^\/]+)\/([^#]+)");
+ foreach(string browserurl in GetBrowserUrls()) {
+ string url;
+ try {
+ url = Uri.UnescapeDataString(browserurl).Replace("+", " ");
+ } catch {
+ LOG.WarnFormat("Error processing URL: {0}", browserurl);
+ continue;
+ }
+ MatchCollection pageIdMatch = pageIdRegex.Matches(url);
+ if (pageIdMatch != null && pageIdMatch.Count > 0) {
+ long pageId = long.Parse(pageIdMatch[0].Groups[1].Value);
+ try {
+ bool pageDouble = false;
+ foreach(Confluence.Page page in pages) {
+ if (page.Id == pageId) {
+ pageDouble = true;
+ LOG.DebugFormat("Skipping double page with ID {0}", pageId);
+ break;
+ }
+ }
+ if (!pageDouble) {
+ Confluence.Page page = ConfluencePlugin.ConfluenceConnector.GetPage(pageId);
+ LOG.DebugFormat("Adding page {0}", page.Title);
+ pages.Add(page);
+ }
+ continue;
+ } catch (Exception ex) {
+ // Preventing security problems
+ LOG.DebugFormat("Couldn't get page details for PageID {0}", pageId);
+ LOG.Warn(ex);
+ }
+ }
+ MatchCollection spacePageMatch = spacePageRegex.Matches(url);
+ if (spacePageMatch != null && spacePageMatch.Count > 0) {
+ if (spacePageMatch[0].Groups.Count >= 2) {
+ string space = spacePageMatch[0].Groups[1].Value;
+ string title = spacePageMatch[0].Groups[2].Value;
+ if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(space)) {
+ continue;
+ }
+ if (title.EndsWith("#")) {
+ title = title.Substring(0, title.Length-1);
+ }
+ try {
+ bool pageDouble = false;
+ foreach(Confluence.Page page in pages) {
+ if (page.Title.Equals(title)) {
+ LOG.DebugFormat("Skipping double page with title {0}", title);
+ pageDouble = true;
+ break;
+ }
+ }
+ if (!pageDouble) {
+ Confluence.Page page = ConfluencePlugin.ConfluenceConnector.GetPage(space, title);
+ LOG.DebugFormat("Adding page {0}", page.Title);
+ pages.Add(page);
+
+ }
+ } catch (Exception ex) {
+ // Preventing security problems
+ LOG.DebugFormat("Couldn't get page details for space {0} / title {1}", space, title);
+ LOG.Warn(ex);
+ }
+ }
+ }
+ }
+ return pages;
+ }
+
+ private static IEnumerable GetBrowserUrls() {
+ HashSet urls = new HashSet();
+
+ // FireFox
+ foreach (WindowDetails window in WindowDetails.GetAllWindows("MozillaWindowClass")) {
+ if (window.Text.Length == 0) {
+ continue;
+ }
+ AutomationElement currentElement = AutomationElement.FromHandle(window.Handle);
+ Condition conditionCustom = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom), new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
+ for (int i = 5; i > 0 && currentElement != null; i--) {
+ currentElement = currentElement.FindFirst(TreeScope.Children, conditionCustom);
+ }
+ if (currentElement == null) {
+ continue;
+ }
+
+ Condition conditionDocument = new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document), new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
+ AutomationElement docElement = currentElement.FindFirst(TreeScope.Children, conditionDocument);
+ if (docElement == null) {
+ continue;
+ }
+ foreach (AutomationPattern pattern in docElement.GetSupportedPatterns()) {
+ if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern") {
+ continue;
+ }
+ string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value;
+ if (!string.IsNullOrEmpty(url)) {
+ urls.Add(url);
+ break;
+ }
+ }
+ }
+
+ foreach(string url in IEHelper.GetIEUrls().Distinct()) {
+ urls.Add(url);
+ }
+
+ return urls;
+ }
+
+ }
+}
diff --git a/GreenshotConfluencePlugin/EnumDisplayer.cs b/GreenshotConfluencePlugin/EnumDisplayer.cs
new file mode 100644
index 000000000..ca55afa40
--- /dev/null
+++ b/GreenshotConfluencePlugin/EnumDisplayer.cs
@@ -0,0 +1,104 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.Reflection;
+using System.Windows.Data;
+
+using GreenshotPlugin.Core;
+
+namespace GreenshotConfluencePlugin {
+ public class EnumDisplayer : IValueConverter {
+ private Type _type;
+ private IDictionary _displayValues;
+ private IDictionary _reverseValues;
+
+ public EnumDisplayer() {
+ }
+
+ public EnumDisplayer(Type type) {
+ Type = type;
+ }
+
+ public Type Type {
+ get { return _type; }
+ set {
+ if (!value.IsEnum) {
+ throw new ArgumentException("parameter is not an Enumerated type", nameof(value));
+ }
+ _type = value;
+ }
+ }
+
+ public ReadOnlyCollection DisplayNames {
+ get {
+ var genericTypeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
+ if (genericTypeDefinition != null)
+ {
+ _reverseValues = (IDictionary) Activator.CreateInstance(genericTypeDefinition.MakeGenericType(typeof(string),_type));
+ }
+
+ var typeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
+ if (typeDefinition != null)
+ {
+ _displayValues = (IDictionary)Activator.CreateInstance(typeDefinition.MakeGenericType(_type, typeof(string)));
+ }
+
+ var fields = _type.GetFields(BindingFlags.Public | BindingFlags.Static);
+ foreach (var field in fields) {
+ DisplayKeyAttribute[] a = (DisplayKeyAttribute[])field.GetCustomAttributes(typeof(DisplayKeyAttribute), false);
+
+ string displayKey = GetDisplayKeyValue(a);
+ object enumValue = field.GetValue(null);
+
+ string displayString;
+ if (displayKey != null && Language.HasKey(displayKey)) {
+ displayString = Language.GetString(displayKey);
+ }
+ displayString = displayKey ?? enumValue.ToString();
+
+ _displayValues.Add(enumValue, displayString);
+ _reverseValues.Add(displayString, enumValue);
+ }
+ return new List((IEnumerable)_displayValues.Values).AsReadOnly();
+ }
+ }
+
+ private static string GetDisplayKeyValue(DisplayKeyAttribute[] a) {
+ if (a == null || a.Length == 0) {
+ return null;
+ }
+ DisplayKeyAttribute dka = a[0];
+ return dka.Value;
+ }
+
+ object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) {
+ return _displayValues[value];
+ }
+
+ object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
+ return _reverseValues[value];
+ }
+ }
+}
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml
new file mode 100644
index 000000000..b22e55d9b
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs
new file mode 100644
index 000000000..4ce336f3c
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Interaction logic for ConfluenceConfigurationForm.xaml
+ ///
+ public partial class ConfluenceConfigurationForm : Window {
+ public ConfluenceConfiguration Config { get; }
+
+ public ConfluenceConfigurationForm(ConfluenceConfiguration config) {
+ DataContext = config;
+ Config = config;
+ InitializeComponent();
+ }
+
+ private void Button_OK_Click(object sender, RoutedEventArgs e) {
+ DialogResult = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluencePagePicker.xaml b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
similarity index 85%
rename from src/Greenshot.Plugin.Confluence/Forms/ConfluencePagePicker.xaml
rename to GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
index 194d31080..6455e86b5 100644
--- a/src/Greenshot.Plugin.Confluence/Forms/ConfluencePagePicker.xaml
+++ b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
@@ -1,4 +1,4 @@
-
diff --git a/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs
new file mode 100644
index 000000000..0d5f78bfb
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs
@@ -0,0 +1,57 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Confluence;
+using System.Collections.Generic;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Interaction logic for ConfluencePagePicker.xaml
+ ///
+ public partial class ConfluencePagePicker
+ {
+ private readonly ConfluenceUpload _confluenceUpload;
+
+ public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List pagesToPick) {
+ _confluenceUpload = confluenceUpload;
+ DataContext = pagesToPick;
+ InitializeComponent();
+ }
+
+ private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
+ SelectionChanged();
+ }
+
+ private void SelectionChanged() {
+ if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
+ _confluenceUpload.SelectedPage = (Page)PageListView.SelectedItem;
+ // Make sure the uploader knows we selected an already opened page
+ _confluenceUpload.IsOpenPageSelected = true;
+ } else {
+ _confluenceUpload.SelectedPage = null;
+ }
+ }
+
+ private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) {
+ SelectionChanged();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml
similarity index 75%
rename from src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml
rename to GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml
index f63185d34..e30f9ab6e 100644
--- a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml
@@ -1,9 +1,8 @@
-
+ xmlns:l="clr-namespace:TranslationByMarkupExtension" Loaded="Page_Loaded">
@@ -17,9 +16,9 @@
-
-
-
+
+
+
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs
new file mode 100644
index 000000000..815222ef7
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs
@@ -0,0 +1,93 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+using Greenshot.IniFile;
+
+namespace GreenshotConfluencePlugin {
+ public partial class ConfluenceSearch
+ {
+ private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection();
+ private readonly ConfluenceUpload _confluenceUpload;
+
+ public IEnumerable Spaces => _confluenceUpload.Spaces;
+
+ public ObservableCollection Pages { get; } = new ObservableCollection();
+
+ public ConfluenceSearch(ConfluenceUpload confluenceUpload) {
+ _confluenceUpload = confluenceUpload;
+ DataContext = this;
+ InitializeComponent();
+ if (ConfluenceConfig.SearchSpaceKey == null) {
+ SpaceComboBox.SelectedItem = Spaces.FirstOrDefault();
+ } else {
+ foreach(var space in Spaces) {
+ if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey)) {
+ SpaceComboBox.SelectedItem = space;
+ }
+ }
+ }
+ }
+
+ private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
+ SelectionChanged();
+ }
+
+ private void SelectionChanged() {
+ if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
+ _confluenceUpload.SelectedPage = (Confluence.Page)PageListView.SelectedItem;
+ } else {
+ _confluenceUpload.SelectedPage = null;
+ }
+ }
+
+ private void Search_Click(object sender, RoutedEventArgs e) {
+ DoSearch();
+ }
+
+ private void DoSearch() {
+ string spaceKey = (string)SpaceComboBox.SelectedValue;
+ ConfluenceConfig.SearchSpaceKey = spaceKey;
+ Pages.Clear();
+ foreach(var page in ConfluencePlugin.ConfluenceConnector.SearchPages(searchText.Text, spaceKey).OrderBy(p => p.Title)) {
+ Pages.Add(page);
+ }
+ }
+
+ private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
+ if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled) {
+ DoSearch();
+ e.Handled = true;
+ }
+ }
+
+ private void Page_Loaded(object sender, RoutedEventArgs e) {
+ SelectionChanged();
+ }
+
+ private void searchText_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) {
+ Search.IsEnabled = !string.IsNullOrEmpty(searchText.Text);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceTreePicker.xaml b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml
similarity index 78%
rename from src/Greenshot.Plugin.Confluence/Forms/ConfluenceTreePicker.xaml
rename to GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml
index 27e2a0004..97352d47e 100644
--- a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceTreePicker.xaml
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml
@@ -1,8 +1,8 @@
-
+ FontSize="18" FontWeight="Bold" Foreground="#7EFFFFFF" Text="{l:Translate loading}"/>
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs
new file mode 100644
index 000000000..6d3768973
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs
@@ -0,0 +1,131 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Linq;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Threading;
+
+using Confluence;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Interaction logic for ConfluenceTreePicker.xaml
+ ///
+ public partial class ConfluenceTreePicker
+ {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceTreePicker));
+ private readonly ConfluenceConnector _confluenceConnector;
+ private readonly ConfluenceUpload _confluenceUpload;
+ private bool _isInitDone;
+
+ public ConfluenceTreePicker(ConfluenceUpload confluenceUpload) {
+ _confluenceConnector = ConfluencePlugin.ConfluenceConnector;
+ _confluenceUpload = confluenceUpload;
+ InitializeComponent();
+ }
+
+ private void pageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs) {
+ Log.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!");
+ TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
+ Confluence.Page page = clickedItem?.Tag as Confluence.Page;
+ if (page == null) {
+ return;
+ }
+ if (clickedItem.HasItems)
+ {
+ return;
+ }
+ Log.Debug("Loading pages for page: " + page.Title);
+ new Thread(() => {
+ Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {ShowBusy.Visibility = Visibility.Visible;}));
+ var pages = _confluenceConnector.GetPageChildren(page).OrderBy(p => p.Title);
+ Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
+ foreach(var childPage in pages) {
+ Log.Debug("Adding page: " + childPage.Title);
+ var pageTreeViewItem = new TreeViewItem
+ {
+ Header = childPage.Title,
+ Tag = childPage
+ };
+ clickedItem.Items.Add(pageTreeViewItem);
+ pageTreeViewItem.PreviewMouseDoubleClick += pageTreeViewItem_DoubleClick;
+ pageTreeViewItem.PreviewMouseLeftButtonDown += pageTreeViewItem_Click;
+ }
+ ShowBusy.Visibility = Visibility.Collapsed;
+ }));
+ }) { Name = "Loading childpages for confluence page " + page.Title }.Start();
+ }
+
+ private void pageTreeViewItem_Click(object sender, MouseButtonEventArgs eventArgs) {
+ Log.Debug("pageTreeViewItem_PreviewMouseDoubleClick is called!");
+ TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
+ if (clickedItem ==null) {
+ return;
+ }
+ Confluence.Page page = clickedItem.Tag as Confluence.Page;
+ _confluenceUpload.SelectedPage = page;
+ if (page != null) {
+ Log.Debug("Page selected: " + page.Title);
+ }
+ }
+
+ private void Page_Loaded(object sender, RoutedEventArgs e) {
+ _confluenceUpload.SelectedPage = null;
+ if (_isInitDone) {
+ return;
+ }
+ ShowBusy.Visibility = Visibility.Visible;
+ new Thread(() => {
+ Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
+ foreach (Space space in _confluenceUpload.Spaces) {
+ TreeViewItem spaceTreeViewItem = new TreeViewItem
+ {
+ Header = space.Name,
+ Tag = space
+ };
+
+ // Get homepage
+ try {
+ Confluence.Page page = _confluenceConnector.GetSpaceHomepage(space);
+ TreeViewItem pageTreeViewItem = new TreeViewItem
+ {
+ Header = page.Title,
+ Tag = page
+ };
+ pageTreeViewItem.PreviewMouseDoubleClick += pageTreeViewItem_DoubleClick;
+ pageTreeViewItem.PreviewMouseLeftButtonDown += pageTreeViewItem_Click;
+ spaceTreeViewItem.Items.Add(pageTreeViewItem);
+ ConfluenceTreeView.Items.Add(spaceTreeViewItem);
+ } catch (Exception ex) {
+ Log.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")");
+ }
+ }
+ ShowBusy.Visibility = Visibility.Collapsed;
+ _isInitDone = true;
+ }));
+ }) { Name = "Loading spaces for confluence"}.Start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceUpload.xaml b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml
similarity index 52%
rename from src/Greenshot.Plugin.Confluence/Forms/ConfluenceUpload.xaml
rename to GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml
index e53ae07ac..aa97142a6 100644
--- a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceUpload.xaml
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml
@@ -1,17 +1,17 @@
-
+ xmlns:l="clr-namespace:TranslationByMarkupExtension"
+ Title="{l:Translate upload_menu_item}" Height="640" Width="500" Icon="/GreenshotConfluencePlugin;component/Images/Confluence.ico">
-
+
-
+
-
+
@@ -23,12 +23,12 @@
-
+
-
-
+
+
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs
new file mode 100644
index 000000000..82424d5c7
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs
@@ -0,0 +1,132 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace GreenshotConfluencePlugin {
+ ///
+ /// Interaction logic for ConfluenceUpload.xaml
+ ///
+ public partial class ConfluenceUpload : Window {
+ private Page _pickerPage;
+ public Page PickerPage {
+ get {
+ if (_pickerPage == null) {
+ List pages = ConfluenceUtils.GetCurrentPages();
+ if (pages != null && pages.Count > 0) {
+ _pickerPage = new ConfluencePagePicker(this, pages);
+ }
+ }
+ return _pickerPage;
+ }
+ }
+
+ private Page _searchPage;
+ public Page SearchPage {
+ get {
+ if (_searchPage == null) {
+ _searchPage = new ConfluenceSearch(this);
+ }
+ return _searchPage;
+ }
+ }
+
+ private Page _browsePage;
+ public Page BrowsePage {
+ get {
+ if (_browsePage == null) {
+ _browsePage = new ConfluenceTreePicker(this);
+ }
+ return _browsePage;
+ }
+ }
+
+ private Confluence.Page _selectedPage;
+ public Confluence.Page SelectedPage {
+ get {
+ return _selectedPage;
+ }
+ set {
+ _selectedPage = value;
+ if (_selectedPage != null) {
+ Upload.IsEnabled = true;
+ } else {
+ Upload.IsEnabled = false;
+ }
+ IsOpenPageSelected = false;
+ }
+ }
+
+ public bool IsOpenPageSelected {
+ get;
+ set;
+ }
+ public string Filename {
+ get;
+ set;
+ }
+
+ private static DateTime _lastLoad = DateTime.Now;
+ private static IList _spaces;
+ public IList Spaces {
+ get {
+ UpdateSpaces();
+ while (_spaces == null) {
+ Thread.Sleep(300);
+ }
+ return _spaces;
+ }
+ }
+
+ public ConfluenceUpload(string filename) {
+ Filename = filename;
+ InitializeComponent();
+ DataContext = this;
+ UpdateSpaces();
+ if (PickerPage == null) {
+ PickerTab.Visibility = Visibility.Collapsed;
+ SearchTab.IsSelected = true;
+ }
+ }
+
+ private void UpdateSpaces() {
+ if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0) {
+ // Reset
+ _spaces = null;
+ }
+ // Check if load is needed
+ if (_spaces == null) {
+ (new Thread(() => {
+ _spaces = ConfluencePlugin.ConfluenceConnector.GetSpaceSummaries().OrderBy(s => s.Name).ToList();
+ _lastLoad = DateTime.Now;
+ }) { Name = "Loading spaces for confluence"}).Start();
+ }
+ }
+
+ private void Upload_Click(object sender, RoutedEventArgs e) {
+ DialogResult = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs b/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs
new file mode 100644
index 000000000..a2b859414
--- /dev/null
+++ b/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs
@@ -0,0 +1,89 @@
+using System.Collections;
+using System.Windows.Forms;
+
+///
+/// This class is an implementation of the 'IComparer' interface.
+///
+public class ListViewColumnSorter : IComparer {
+ ///
+ /// Specifies the column to be sorted
+ ///
+ private int ColumnToSort;
+ ///
+ /// Specifies the order in which to sort (i.e. 'Ascending').
+ ///
+ private SortOrder OrderOfSort;
+ ///
+ /// Case insensitive comparer object
+ ///
+ private CaseInsensitiveComparer ObjectCompare;
+
+ ///
+ /// Class constructor. Initializes various elements
+ ///
+ public ListViewColumnSorter() {
+ // Initialize the column to '0'
+ ColumnToSort = 0;
+
+ // Initialize the sort order to 'none'
+ OrderOfSort = SortOrder.None;
+
+ // Initialize the CaseInsensitiveComparer object
+ ObjectCompare = new CaseInsensitiveComparer();
+ }
+
+ ///
+ /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
+ ///
+ /// First object to be compared
+ /// Second object to be compared
+ /// The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'
+ public int Compare(object x, object y) {
+ int compareResult;
+ ListViewItem listviewX, listviewY;
+
+ // Cast the objects to be compared to ListViewItem objects
+ listviewX = (ListViewItem)x;
+ listviewY = (ListViewItem)y;
+
+ // Compare the two items
+ compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
+
+ // Calculate correct return value based on object comparison
+ if (OrderOfSort == SortOrder.Ascending) {
+ // Ascending sort is selected, return normal result of compare operation
+ return compareResult;
+ } else if (OrderOfSort == SortOrder.Descending) {
+ // Descending sort is selected, return negative result of compare operation
+ return (-compareResult);
+ } else {
+ // Return '0' to indicate they are equal
+ return 0;
+ }
+ }
+
+ ///
+ /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
+ ///
+ public int SortColumn {
+ set {
+ ColumnToSort = value;
+ }
+ get {
+ return ColumnToSort;
+ }
+ }
+
+ ///
+ /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
+ ///
+ public SortOrder Order {
+ set {
+ OrderOfSort = value;
+ }
+ get {
+ return OrderOfSort;
+ }
+ }
+
+}
diff --git a/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj
new file mode 100644
index 000000000..c531a3499
--- /dev/null
+++ b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj
@@ -0,0 +1,152 @@
+
+
+
+
+ 1685
+ {C3052651-598A-44E2-AAB3-2E41311D50F9}
+ Library
+ GreenshotConfluencePlugin
+ GreenshotConfluencePlugin
+ v3.5
+ Properties
+ False
+ False
+ 4
+ false
+ OnBuildSuccess
+ Client
+
+
+
+
+ 3.5
+
+
+
+
+ ..\Greenshot\Lib\log4net.dll
+ False
+
+
+
+
+
+ 3.5
+
+
+
+
+
+
+ 3.5
+
+
+ 3.0
+
+
+ 3.0
+
+
+
+
+
+
+
+
+
+
+ ConfluenceConfigurationForm.xaml
+ Code
+
+
+
+ ConfluencePagePicker.xaml
+ Code
+
+
+ ConfluenceSearch.xaml
+ Code
+
+
+ ConfluenceTreePicker.xaml
+ Code
+
+
+ ConfluenceUpload.xaml
+ Code
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Reference.map
+
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+
+ MSDiscoCodeGenerator
+ Reference.cs
+
+
+
+
+
+ Static
+ http://confluence/rpc/soap-axis/confluenceservice-v1%3fwsdl
+ Web References\confluence
+ Confluence
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+ False
+
+
+
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Images/Confluence.ico b/GreenshotConfluencePlugin/Images/Confluence.ico
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Images/Confluence.ico
rename to GreenshotConfluencePlugin/Images/Confluence.ico
diff --git a/GreenshotConfluencePlugin/LanguageKeys.cs b/GreenshotConfluencePlugin/LanguageKeys.cs
new file mode 100644
index 000000000..5f4213764
--- /dev/null
+++ b/GreenshotConfluencePlugin/LanguageKeys.cs
@@ -0,0 +1,35 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotConfluencePlugin {
+ public enum LangKey {
+ login_error,
+ login_title,
+ label_url,
+ label_upload_format,
+ OK,
+ CANCEL,
+ upload_menu_item,
+ upload_success,
+ upload_failure,
+ communication_wait
+ }
+}
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-cs-CZ.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-cs-CZ.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-cs-CZ.xml
index e466bdd2d..fd8b03878 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-cs-CZ.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-cs-CZ.xml
@@ -1,29 +1,29 @@
-
-
-
- Prohlížet stránky
- Zrušit
- Kopírovat Wikimarkup do schránky
- Název souboru
- Zahrnout soukromého prostoru do hledání a prohlížení
- Heslo
- Časový limit
- Url
- Uživatel
- Data z Confluence se načítají, čekejte prosím ...
- Došlo k potížím během přihlášení: {0}
- Prosím zadejte vaše přihlašovací údaje k službě Confluence
- OK
- Otevřít stránky pro nahrání
- Otevřít stránky
- Nastavení Confluence
- Hledat
- Hledat stránky
- Hledat text
- Nahrát
- Nahrání obrázku do Confluence se nezdařilo:
- Nahrát formát
- Nahrát do Confluence
- Úspěšné nahrání obrázku do Confluence!
-
+
+
+
+ Prohlížet stránky
+ Zrušit
+ Kopírovat Wikimarkup do schránky
+ Název souboru
+ Zahrnout soukromého prostoru do hledání a prohlížení
+ Heslo
+ Časový limit
+ Url
+ Uživatel
+ Data z Confluence se načítají, čekejte prosím ...
+ Došlo k potížím během přihlášení: {0}
+ Prosím zadejte vaše přihlašovací údaje k službě Confluence
+ OK
+ Otevřít stránky pro nahrání
+ Otevřít stránky
+ Nastavení Confluence
+ Hledat
+ Hledat stránky
+ Hledat text
+ Nahrát
+ Nahrání obrázku do Confluence se nezdařilo:
+ Nahrát formát
+ Nahrát do Confluence
+ Úspěšné nahrání obrázku do Confluence!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-de-DE.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-de-DE.xml
similarity index 96%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-de-DE.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-de-DE.xml
index f7f081c78..3a659e5f0 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-de-DE.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-de-DE.xml
@@ -1,77 +1,77 @@
-
-
-
-
- Confluence einstellungen
-
-
- Es gab ein Problem während dem Login: {0}
-
-
- Bitte geben Sie ihr Confluence anmelde Daten ein
-
-
- Url
-
-
- Timeout
-
-
- Benutzer
-
-
- Password
-
-
- OK
-
-
- Abbrechen
-
-
- In Confluence hochladen
-
-
- Ein erfolg beim Hochladen zum Confluence!
-
-
- Es gab einen Fehler beim Hochladen zum Confluence:
-
-
- Seite nach dem upload öffnen
-
-
- Bildformat für Hochladen
-
-
- Kopiere Wikimarkup in der Zwischenablage
-
-
- Dateiname
-
-
- Hochladen
-
-
- Aktuelle Seiten
-
-
- Seiten suchen
-
-
- Seiten durchstöbern
-
-
- Text suchen
-
-
- Suchen
-
-
- Confluence Daten werden geladen, bitte warten!
-
-
- Übermittle Daten zu Confluence. Bitte warten...
-
-
+
+
+
+
+ Confluence einstellungen
+
+
+ Es gab ein Problem während dem Login: {0}
+
+
+ Bitte geben Sie ihr Confluence anmelde Daten ein
+
+
+ Url
+
+
+ Timeout
+
+
+ Benutzer
+
+
+ Password
+
+
+ OK
+
+
+ Abbrechen
+
+
+ In Confluence hochladen
+
+
+ Ein erfolg beim Hochladen zum Confluence!
+
+
+ Es gab einen Fehler beim Hochladen zum Confluence:
+
+
+ Seite nach dem upload öffnen
+
+
+ Bildformat für Hochladen
+
+
+ Kopiere Wikimarkup in der Zwischenablage
+
+
+ Dateiname
+
+
+ Hochladen
+
+
+ Aktuelle Seiten
+
+
+ Seiten suchen
+
+
+ Seiten durchstöbern
+
+
+ Text suchen
+
+
+ Suchen
+
+
+ Confluence Daten werden geladen, bitte warten!
+
+
+ Übermittle Daten zu Confluence. Bitte warten...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-en-US.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-en-US.xml
similarity index 93%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-en-US.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-en-US.xml
index ab49a8f94..033202226 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-en-US.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-en-US.xml
@@ -1,80 +1,80 @@
-
-
-
-
- Confluence settings
-
-
- There was a problem during the login: {0}
-
-
- Url
-
-
- Timeout
-
-
- User
-
-
- Password
-
-
- Please enter your Confluence login data
-
-
- OK
-
-
- Cancel
-
-
- Upload to Confluence
-
-
- Successfully uploaded image to Confluence!
-
-
- An error occurred while uploading to Confluence:
-
-
- Open page after upload
-
-
- Upload format
-
-
- Copy Wikimarkup to the Clipboard
-
-
- Filename
-
-
- Upload
-
-
- Open pages
-
-
- Search pages
-
-
- Browse pages
-
-
- Search text
-
-
- Search
-
-
- Confluence data is loading, please wait...
-
-
- Include personal spaces in search and browsing
-
-
- Transferring data to Confluence, please wait...
-
-
+
+
+
+
+ Confluence settings
+
+
+ There was a problem during the login: {0}
+
+
+ Url
+
+
+ Timeout
+
+
+ User
+
+
+ Password
+
+
+ Please enter your Confluence login data
+
+
+ OK
+
+
+ Cancel
+
+
+ Upload to Confluence
+
+
+ Successfully uploaded image to Confluence!
+
+
+ An error occured while uploading to Confluence:
+
+
+ Open page after upload
+
+
+ Upload format
+
+
+ Copy Wikimarkup to the Clipboard
+
+
+ Filename
+
+
+ Upload
+
+
+ Open pages
+
+
+ Search pages
+
+
+ Browse pages
+
+
+ Search text
+
+
+ Search
+
+
+ Confluence data is loading, please wait...
+
+
+ Include personal spaces in search and browsing
+
+
+ Transferring data to Confluence, please wait...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-fr-FR.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-fr-FR.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-fr-FR.xml
index 803512090..db2112609 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-fr-FR.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-fr-FR.xml
@@ -1,29 +1,29 @@
-
-
-
- Naviguer
- Annuler
- Copier Wikimarkup vers le presse-papier
- Fichier
- Inclure espaces personnels dans les recherches et la navigation
- Mot de passe
- Temps d'attente
- Url
- Utilisateur
- Récupération des données de Confluence, veuillez patienter...
- Une erreur s'est produite durant l'authentification : {0}
- Veuillez saisir vos données d'authentification Confluence
- Ok
- Ouvrir la page après le téléversement
- Ouvrir pages
- Paramètres Confluence
- Rechercher
- Rechercher dans les pages
- Rechercher texte
- Téléverser
- Une erreur s'est produite lors du téléversement vers Confluence :
- Téléverser format
- Téléverser vers Confluence
- Image téléversée aves succès vers Confluence !
-
+
+
+
+ Naviguer
+ Annuler
+ Copier Wikimarkup vers le presse-papier
+ Fichier
+ Inclure espaces personnels dans les recherches et la navigation
+ Mot de passe
+ Temps d'attente
+ Url
+ Utilisateur
+ Récupération des données de Confluence, veuillez patienter...
+ Une erreur s'est produite durant l'authentification : {0}
+ Veuillez saisir vos données d'authentification Confluence
+ Ok
+ Ouvrir la page après le téléversement
+ Ouvrir pages
+ Paramètres Confluence
+ Rechercher
+ Rechercher dans les pages
+ Rechercher texte
+ Téléverser
+ Une erreur s'est produite lors du téléversement vers Confluence :
+ Téléverser format
+ Téléverser vers Confluence
+ Image téléversée aves succès vers Confluence !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-id-ID.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-id-ID.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-id-ID.xml
index 74e7c2ed6..393d22787 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-id-ID.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-id-ID.xml
@@ -1,30 +1,30 @@
-
-
-
- Telusuri halaman
- Batal
- Mentransfer data ke Confluence, tunggu sebentar...
- Kopi Wikimarkup ke papanklip
- Nama berkas
- Sertakan personal space dalam pencarian dan penelusuran
- Sandi
- Waktu habis
- Url
- Pengguna
- Data Confluence sedang dimuat, tunggu sebentar...
- Ada masalah ketika login: {0}
- Harap masukkan login Confluence anda
- Oke
- Buka halaman setelah diunggah
- Buka halaman
- Setelan Confluence
- Cari
- Cari halaman
- Cari teks
- Unggah
- Kesalahan terjadi ketika mengunggah ke Confluence:
- Format unggah
- Unggah ke Confluence
- Gambar telah berhasil diunggah ke Confluence!
-
+
+
+
+ Telusuri halaman
+ Batal
+ Mentransfer data ke Confluence, tunggu sebentar...
+ Kopi Wikimarkup ke papanklip
+ Nama berkas
+ Sertakan personal space dalam pencarian dan penelusuran
+ Sandi
+ Waktu habis
+ Url
+ Pengguna
+ Data Confluence sedang dimuat, tunggu sebentar...
+ Ada masalah ketika login: {0}
+ Harap masukkan login Confluence anda
+ Oke
+ Buka halaman setelah diunggah
+ Buka halaman
+ Setelan Confluence
+ Cari
+ Cari halaman
+ Cari teks
+ Unggah
+ Kesalahan terjadi ketika mengunggah ke Confluence:
+ Format unggah
+ Unggah ke Confluence
+ Gambar telah berhasil diunggah ke Confluence!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-it-IT.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-it-IT.xml
similarity index 74%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-it-IT.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-it-IT.xml
index 197b212fe..1f145ac54 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-it-IT.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-it-IT.xml
@@ -1,80 +1,80 @@
-
-
-
-
- Impostazioni di Confluence
-
-
- Si è verificato un problema durante il caricamento: {0}
-
-
- Indirizzo URL
-
-
- Timeout
-
-
- Utente
-
-
- Password
-
-
- Inserisci le credenziali di accesso a Confluence
-
-
- OK
-
-
- Annulla
-
-
- Carica su Confluence
-
-
- Caricamento immagine su Confluence completato!
-
-
- Si è verificato un errore durante il caricamento su Confluence:
-
-
- Apri pagina dopo il caricamento
-
-
- Formato di caricamento
-
-
- Copia Wikimarkup negli Appunti
-
-
- Nome file
-
-
- Carica
-
-
- Apri pagine
-
-
- Cerca pagine
-
-
- Sfoglia pagine
-
-
- Cerca testo
-
-
- Cerca
-
-
- Caricamento dati di Confluence...
-
-
- Includi spazi personali in ricerca e navigazione
-
-
- Trasferimento dati su Confluence...
-
-
+
+
+
+
+ Impostazioni di Confluence
+
+
+ Si è verificato un problema durante il collegamento: {0}
+
+
+ Indirizzo Url
+
+
+ Timeout
+
+
+ Utente
+
+
+ Parola d'ordine
+
+
+ Inserisci le tue credenziali di collegamento a Confluence
+
+
+ OK
+
+
+ Annulla
+
+
+ Carica su Confluence
+
+
+ Immagine caricata correttamente su Confluence!
+
+
+ Si è verificato un errore durante il caricamento su Confluence:
+
+
+ Apri pagina dopo il caricamento
+
+
+ Formato di caricamento
+
+
+ Copia Wikimarkup sugli appunti
+
+
+ Nome File
+
+
+ Carica
+
+
+ Apri pagine
+
+
+ Cerca pagine
+
+
+ Naviga pagine
+
+
+ Cerca testo
+
+
+ Cerca
+
+
+ Caricamento dati di Confluence, attendere prego...
+
+
+ Includi spazi personali in ricerca e navigazione
+
+
+ Trasferimento dati verso Confluence, attendere prego...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-kab-DZ.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-kab-DZ.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-ko-KR.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-ko-KR.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-lv-LV.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-lv-LV.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-nl-NL.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-nl-NL.xml
similarity index 95%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-nl-NL.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-nl-NL.xml
index 206943bee..24700e882 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-nl-NL.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-nl-NL.xml
@@ -1,77 +1,77 @@
-
-
-
-
- Confluence instellingen
-
-
- Tijden de login is een fout opgetreden: {0}
-
-
- Url
-
-
- Timeout
-
-
- Gebruiker
-
-
- Password
-
-
- Geef uw Confluence login data
-
-
- OK
-
-
- Afbreken
-
-
- Upload naar Confluence
-
-
- Het uploaden naar Confluence is geslaagt!
-
-
- Tijdens het uploaden naar Confluence is een fout opgetreden:
-
-
- Open pagina na het uploaden
-
-
- Upload formaat
-
-
- Kopier Wikimarkup naar het klembord
-
-
- Filenaam
-
-
- Upload
-
-
- Open paginas
-
-
- Paginas zoeken
-
-
- Paginas browsen
-
-
- Zoek op text
-
-
- Zoeken
-
-
- Confluence daten worden geladen, wachten A.U.B.
-
-
- Gegevensoverdracht naar Confluence, wachten A.U.B...
-
-
+
+
+
+
+ Confluence instellingen
+
+
+ Tijden de login is een fout opgetreden: {0}
+
+
+ Url
+
+
+ Timeout
+
+
+ Gebruiker
+
+
+ Password
+
+
+ Geef uw Confluence login data
+
+
+ OK
+
+
+ Afbreken
+
+
+ Upload naar Confluence
+
+
+ Het uploaden naar Confluence is geslaagt!
+
+
+ Tijdens het uploaden naar Confluence is een fout opgetreden:
+
+
+ Open pagina na het uploaden
+
+
+ Upload formaat
+
+
+ Kopier Wikimarkup naar het klembord
+
+
+ Filenaam
+
+
+ Upload
+
+
+ Open paginas
+
+
+ Paginas zoeken
+
+
+ Paginas browsen
+
+
+ Zoek op text
+
+
+ Zoeken
+
+
+ Confluence daten worden geladen, wachten A.U.B.
+
+
+ Gegevensoverdracht naar Confluence, wachten A.U.B...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-pl-PL.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-pl-PL.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-pl-PL.xml
index b817da46f..0151181d3 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-pl-PL.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-pl-PL.xml
@@ -1,30 +1,30 @@
-
-
-
- Przeglądaj strony
- Anuluj
- Trwa komunikacja z Confluence. Proszę czekać...
- Kopiuj Wikimarkup do schowka
- Nazwa pliku
- Dołącz własne spacje przy wyszukiwaniu i przeglądaniu
- Hasło
- Czas
- URL
- Użytkownik
- Informacje z Confluence są wczytywane, proszę czekać...
- Wystąpił problem podczas logowania: {0}
- Wprowadź swoje dane logowania
- OK
- Otwórz stronę po wysłaniu
- Otwórz strony
- Ustawienia Confluence
- Szukaj
- Szukaj strony
- Szukaj tekst
- Wyślij
- Wystąpił błąd przy wysyłaniu do Confluence:
- Format wysyłania
- Wyślij do Confluence
- Wysyłanie obrazu do Confluence powiodło się!
-
+
+
+
+ Przeglądaj strony
+ Anuluj
+ Trwa komunikacja z Confluence. Proszę czekać...
+ Kopiuj Wikimarkup do schowka
+ Nazwa pliku
+ Dołącz własne spacje przy wyszukiwaniu i przeglądaniu
+ Hasło
+ Czas
+ URL
+ Użytkownik
+ Informacje z Confluence są wczytywane, proszę czekać...
+ Wystąpił problem podczas logowania: {0}
+ Wprowadź swoje dane logowania
+ OK
+ Otwórz stronę po wysłaniu
+ Otwórz strony
+ Ustawienia Confluence
+ Szukaj
+ Szukaj strony
+ Szukaj tekst
+ Wyślij
+ Wystąpił błąd przy wysyłaniu do Confluence:
+ Format wysyłania
+ Wyślij do Confluence
+ Wysyłanie obrazu do Confluence powiodło się!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-pt-PT.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-pt-PT.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-ru-RU.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-ru-RU.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-ru-RU.xml
index 7e5da7656..13ec37cd6 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-ru-RU.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-ru-RU.xml
@@ -1,30 +1,30 @@
-
-
-
- Обзор страниц
- Отмена
- Передача данных на Confluence, пожалуйста, подождите...
- Скопировать Wikimarkup в буфер обмена
- Имя файла
- Включите личное пространство в поиске и просмотре
- Пароль
- Время ожидания
- Url
- Пользователь
- Confluence данные загружаются, пожалуйста, подождите...
- Произошла ошибка во время входа: {0}
- Пожалуйста, введите ваши данные входа на Confluence
- OK
- Открыть страницу после загрузки
- Открыть страницы
- Параметры Confluence
- Искать
- Поиск страниц
- Поиск текста
- Загрузить
- Произошла ошибка при загрузке на Confluence:
- Формат загрузки
- Загрузка на Confluence
- Изображение успешно загружено на Confluence!
-
+
+
+
+ Обзор страниц
+ Отмена
+ Передача данных на Confluence, пожалуйста, подождите...
+ Скопировать Wikimarkup в буфер обмена
+ Имя файла
+ Включите личное пространство в поиске и просмотре
+ Пароль
+ Время ожидания
+ Url
+ Пользователь
+ Confluence данные загружаются, пожалуйста, подождите...
+ Произошла ошибка во время входа: {0}
+ Пожалуйста, введите ваши данные входа на Confluence
+ OK
+ Открыть страницу после загрузки
+ Открыть страницы
+ Параметры Confluence
+ Искать
+ Поиск страниц
+ Поиск текста
+ Загрузить
+ Произошла ошибка при загрузке на Confluence:
+ Формат загрузки
+ Загрузка на Confluence
+ Изображение успешно загружено на Confluence!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-sr-RS.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-sr-RS.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-sr-RS.xml
index 9b152e7d2..1f8e9c075 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-sr-RS.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-sr-RS.xml
@@ -1,30 +1,30 @@
-
-
-
- Прегледај странице
- Откажи
- Преносим податке на Конфлуенс…
- Умножи Wikimarkup
- Назив датотеке
- Лични простор у претрази и прегледању
- Лозинка:
- Време истека:
- Адреса:
- Корисник:
- Учитавам податке Конфлуенса…
- Дошло је до грешке при пријављивању: {0}
- Унесите податке за пријављивање на Конфлуенс
- У реду
- Отвори страницу након отпремања
- Отвори странице
- Поставке Конфлуенса
- Претражи
- Претражи странице
- Претражи текст
- Отпреми
- Дошло је до грешке при отпремању на Конфлуенс:
- Формат слике:
- Отпреми на Конфлуенс
- Слика је успешно отпремљена на Конфлуенс.
-
+
+
+
+ Прегледај странице
+ Откажи
+ Преносим податке на Конфлуенс…
+ Умножи Wikimarkup
+ Назив датотеке
+ Лични простор у претрази и прегледању
+ Лозинка:
+ Време истека:
+ Адреса:
+ Корисник:
+ Учитавам податке Конфлуенса…
+ Дошло је до грешке при пријављивању: {0}
+ Унесите податке за пријављивање на Конфлуенс
+ У реду
+ Отвори страницу након отпремања
+ Отвори странице
+ Поставке Конфлуенса
+ Претражи
+ Претражи странице
+ Претражи текст
+ Отпреми
+ Дошло је до грешке при отпремању на Конфлуенс:
+ Формат слике:
+ Отпреми на Конфлуенс
+ Слика је успешно отпремљена на Конфлуенс.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-sv-SE.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-sv-SE.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-uk-UA.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-uk-UA.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-uk-UA.xml
index 217e3a096..c39d91099 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-uk-UA.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-uk-UA.xml
@@ -1,30 +1,30 @@
-
-
-
- Параметри Confluence
- Відбулась помилка під час авторизації: {0}
- Посилання
- Затримка
- Користувач
- Пароль
- Будь ласка, введіть дані облікового запису Confluence
- Гаразд
- Скасувати
- Вивантажити на Confluence
- Зображення вдало вивантажено на Confluence!
- Відбулась помилка при вивантаженні зображення на Confluence:
- Відкрити сторінку після вивантаження
- Вивантажити у форматі
- Копіювати Вікі-розмітку в буфер обміну
- Назва файла
- Вивантажити
- Відкрити сторінки
- Пошук сторінок
- Огляд сторінок
- Шукати текст
- Пошук
- Завантаження даних Confluence, будь ласка, зачекайте...
- Включити особистий простір у пошук та перегляд
- Передача даних на Confluence, будь ласка, зачекайте...
-
-
+
+
+
+ Параметри Confluence
+ Відбулась помилка під час авторизації: {0}
+ Посилання
+ Затримка
+ Користувач
+ Пароль
+ Будь ласка, введіть дані облікового запису Confluence
+ Гаразд
+ Скасувати
+ Вивантажити на Confluence
+ Зображення вдало вивантажено на Confluence!
+ Відбулась помилка при вивантаженні зображення на Confluence:
+ Відкрити сторінку після вивантаження
+ Вивантажити у форматі
+ Копіювати Вікі-розмітку в буфер обміну
+ Назва файла
+ Вивантажити
+ Відкрити сторінки
+ Пошук сторінок
+ Огляд сторінок
+ Шукати текст
+ Пошук
+ Завантаження даних Confluence, будь ласка, зачекайте...
+ Включити особистий простір у пошук та перегляд
+ Передача даних на Confluence, будь ласка, зачекайте...
+
+
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-CN.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-CN.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-CN.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-CN.xml
index aa7745f32..fc7946f15 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-CN.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-CN.xml
@@ -1,30 +1,30 @@
-
-
-
- 浏览器页面
- 取消
- 正在传送数据到Confluence,请稍后...
- 把Wikimarkup复制到剪贴板
- 文件名
- 在搜索和浏览时包含个人空间
- 密码
- 超时
- 网址
- 用户名
- 正在载入Confluence数据,请稍后...
- 登录时发生错误:{0}
- 请输入您的Confluence登录信息
- 确认
- 上传之后打开页面
- 打开页面
- Confluence设置
- 搜索
- 搜索页面
- 搜索文字
- 上传
- 上传到Confluence时发生错误
- 上传格式
- 上传到Confluence
- 图片已成功上传到Confluence!
-
+
+
+
+ 浏览器页面
+ 取消
+ 正在传送数据到Confluence,请稍后...
+ 把Wikimarkup复制到剪贴板
+ 文件名
+ 在搜索和浏览时包含个人空间
+ 密码
+ 超时
+ 网址
+ 用户名
+ 正在载入Confluence数据,请稍后...
+ 登录时发生错误:{0}
+ 请输入您的Confluence登录信息
+ 确认
+ 上传之后打开页面
+ 打开页面
+ Confluence设置
+ 搜索
+ 搜索页面
+ 搜索文字
+ 上传
+ 上传到Confluence时发生错误
+ 上传格式
+ 上传到Confluence
+ 图片已成功上传到Confluence!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-TW.xml b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-TW.xml
rename to GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-TW.xml
index 916e39245..26d018dee 100644
--- a/src/Greenshot.Plugin.Confluence/Languages/language_confluence-zh-TW.xml
+++ b/GreenshotConfluencePlugin/Languages/language_confluenceplugin-zh-TW.xml
@@ -1,30 +1,30 @@
-
-
-
- 瀏覽頁面
- 取消
- 正在與 Confluence 通訊,請稍候...
- 複製 Wikimarkup 到剪貼簿
- 檔案名稱
- 搜尋和瀏覽包含無效的空格
- 密碼
- 逾時
- URL
- 使用者
- 正在載入 Confluence 資料,請稍候...
- 登入期間發生問題: {0}
- 請輸入您的 Confluence 登入資料
- 確定
- 上傳後開啟頁面
- 開啟頁面
- Confluence 設定
- 搜尋
- 搜尋頁面
- 搜尋文字
- 上傳
- 上傳到 Confluence 時發生錯誤:
- 上傳格式
- 上傳到 Confluence
- 上傳圖片到 Confluence 成功!
-
+
+
+
+ 瀏覽頁面
+ 取消
+ 正在與 Confluence 通訊,請稍候...
+ 複製 Wikimarkup 到剪貼簿
+ 檔案名稱
+ 搜尋和瀏覽包含無效的空格
+ 密碼
+ 逾時
+ URL
+ 使用者
+ 正在載入 Confluence 資料,請稍候...
+ 登入期間發生問題: {0}
+ 請輸入您的 Confluence 登入資料
+ 確定
+ 上傳後開啟頁面
+ 開啟頁面
+ Confluence 設定
+ 搜尋
+ 搜尋頁面
+ 搜尋文字
+ 上傳
+ 上傳到 Confluence 時發生錯誤:
+ 上傳格式
+ 上傳到 Confluence
+ 上傳圖片到 Confluence 成功!
+
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs b/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..17d53dec2
--- /dev/null
+++ b/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,51 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GreenshotConfluencePlugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Confluence Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotConfluencePlugin.ConfluencePlugin", true)]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// Solve Link-Demand issues
+[assembly: SecurityTransparent]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Confluence/Support/ITranslationProvider.cs b/GreenshotConfluencePlugin/Support/ITranslationProvider.cs
similarity index 65%
rename from src/Greenshot.Plugin.Confluence/Support/ITranslationProvider.cs
rename to GreenshotConfluencePlugin/Support/ITranslationProvider.cs
index d189db670..79efd538c 100644
--- a/src/Greenshot.Plugin.Confluence/Support/ITranslationProvider.cs
+++ b/GreenshotConfluencePlugin/Support/ITranslationProvider.cs
@@ -1,7 +1,5 @@
-namespace Greenshot.Plugin.Confluence.Support
-{
- public interface ITranslationProvider
- {
+namespace TranslationByMarkupExtension {
+ public interface ITranslationProvider {
///
/// Translates the specified key.
///
@@ -9,4 +7,4 @@
///
object Translate(string key);
}
-}
\ No newline at end of file
+}
diff --git a/src/Greenshot.Plugin.Confluence/Support/LanguageChangedEventManager.cs b/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
similarity index 81%
rename from src/Greenshot.Plugin.Confluence/Support/LanguageChangedEventManager.cs
rename to GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
index 6ca4ec384..8fe9289d3 100644
--- a/src/Greenshot.Plugin.Confluence/Support/LanguageChangedEventManager.cs
+++ b/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
@@ -1,7 +1,7 @@
using System;
using System.Windows;
-namespace Greenshot.Plugin.Confluence.Support
+namespace TranslationByMarkupExtension
{
public class LanguageChangedEventManager : WeakEventManager
{
@@ -22,13 +22,13 @@ namespace Greenshot.Plugin.Confluence.Support
protected override void StartListening(object source)
{
- var manager = (TranslationManager) source;
+ var manager = (TranslationManager)source;
manager.LanguageChanged += OnLanguageChanged;
}
protected override void StopListening(object source)
{
- var manager = (TranslationManager) source;
+ var manager = (TranslationManager)source;
manager.LanguageChanged -= OnLanguageChanged;
}
@@ -37,15 +37,15 @@ namespace Greenshot.Plugin.Confluence.Support
get
{
Type managerType = typeof(LanguageChangedEventManager);
- var manager = (LanguageChangedEventManager) GetCurrentManager(managerType);
+ var manager = (LanguageChangedEventManager)GetCurrentManager(managerType);
if (manager == null)
{
manager = new LanguageChangedEventManager();
SetCurrentManager(managerType, manager);
}
-
return manager;
}
- }
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs b/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs
new file mode 100644
index 000000000..e5cf3bfe8
--- /dev/null
+++ b/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs
@@ -0,0 +1,30 @@
+using GreenshotPlugin.Core;
+
+namespace TranslationByMarkupExtension {
+ ///
+ ///
+ ///
+ public class LanguageXMLTranslationProvider : ITranslationProvider {
+ #region Private Members
+
+ #endregion
+
+ #region Construction
+
+ #endregion
+
+ #region ITranslationProvider Members
+
+ ///
+ /// See
+ ///
+ public object Translate(string key) {
+ if (Language.HasKey("confluence", key)) {
+ return Language.GetString("confluence", key);
+ }
+ return key;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Greenshot.Plugin.Confluence/Support/TranslateExtension.cs b/GreenshotConfluencePlugin/Support/TranslateExtension.cs
similarity index 76%
rename from src/Greenshot.Plugin.Confluence/Support/TranslateExtension.cs
rename to GreenshotConfluencePlugin/Support/TranslateExtension.cs
index 012f0c552..4ae20584a 100644
--- a/src/Greenshot.Plugin.Confluence/Support/TranslateExtension.cs
+++ b/GreenshotConfluencePlugin/Support/TranslateExtension.cs
@@ -2,7 +2,7 @@
using System.Windows.Data;
using System.Windows.Markup;
-namespace Greenshot.Plugin.Confluence.Support
+namespace TranslationByMarkupExtension
{
///
/// The Translate Markup extension returns a binding to a TranslationData
@@ -10,8 +10,14 @@ namespace Greenshot.Plugin.Confluence.Support
///
public class TranslateExtension : MarkupExtension
{
+ #region Private Members
+
private string _key;
+ #endregion
+
+ #region Construction
+
///
/// Initializes a new instance of the class.
///
@@ -21,11 +27,13 @@ namespace Greenshot.Plugin.Confluence.Support
_key = key;
}
+ #endregion
+
[ConstructorArgument("key")]
public string Key
{
get { return _key; }
- set { _key = value; }
+ set { _key = value;}
}
///
@@ -34,10 +42,10 @@ namespace Greenshot.Plugin.Confluence.Support
public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = new Binding("Value")
- {
- Source = new TranslationData(_key)
- };
+ {
+ Source = new TranslationData(_key)
+ };
return binding.ProvideValue(serviceProvider);
}
}
-}
\ No newline at end of file
+}
diff --git a/GreenshotConfluencePlugin/Support/TranslationData.cs b/GreenshotConfluencePlugin/Support/TranslationData.cs
new file mode 100644
index 000000000..287cca4c0
--- /dev/null
+++ b/GreenshotConfluencePlugin/Support/TranslationData.cs
@@ -0,0 +1,57 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+
+namespace TranslationByMarkupExtension {
+ public class TranslationData : IWeakEventListener, INotifyPropertyChanged {
+ #region Private Members
+
+ private readonly string _key;
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ public TranslationData( string key) {
+ _key = key;
+ LanguageChangedEventManager.AddListener(TranslationManager.Instance, this);
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~TranslationData() {
+ LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this);
+ }
+
+ public object Value => TranslationManager.Instance.Translate(_key);
+
+ #region IWeakEventListener Members
+
+ public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ if (managerType == typeof(LanguageChangedEventManager))
+ {
+ OnLanguageChanged(sender, e);
+ return true;
+ }
+ return false;
+ }
+
+ private void OnLanguageChanged(object sender, EventArgs e)
+ {
+ PropertyChanged?.Invoke( this, new PropertyChangedEventArgs("Value"));
+ }
+
+ #endregion
+
+ #region INotifyPropertyChanged Members
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+}
diff --git a/GreenshotConfluencePlugin/Support/TranslationManager.cs b/GreenshotConfluencePlugin/Support/TranslationManager.cs
new file mode 100644
index 000000000..bf315a5d5
--- /dev/null
+++ b/GreenshotConfluencePlugin/Support/TranslationManager.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace TranslationByMarkupExtension {
+ public class TranslationManager {
+ private static TranslationManager _translationManager;
+
+ public event EventHandler LanguageChanged;
+
+ /*public CultureInfo CurrentLanguage {
+ get { return Thread.CurrentThread.CurrentUICulture; }
+ set {
+ if( value != Thread.CurrentThread.CurrentUICulture) {
+ Thread.CurrentThread.CurrentUICulture = value;
+ OnLanguageChanged();
+ }
+ }
+ }
+
+ public IEnumerable Languages {
+ get {
+ if( TranslationProvider != null) {
+ return TranslationProvider.Languages;
+ }
+ return Enumerable.Empty();
+ }
+ }*/
+
+ public static TranslationManager Instance => _translationManager ?? (_translationManager = new TranslationManager());
+
+ public ITranslationProvider TranslationProvider { get; set; }
+
+ private void OnLanguageChanged()
+ {
+ LanguageChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public object Translate(string key) {
+ object translatedValue = TranslationProvider?.Translate(key);
+ if( translatedValue != null) {
+ return translatedValue;
+ }
+ return $"!{key}!";
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Confluence/Web References/confluence/Reference.cs b/GreenshotConfluencePlugin/Web References/confluence/Reference.cs
similarity index 93%
rename from src/Greenshot.Plugin.Confluence/Web References/confluence/Reference.cs
rename to GreenshotConfluencePlugin/Web References/confluence/Reference.cs
index aba156d27..c432337f4 100644
--- a/src/Greenshot.Plugin.Confluence/Web References/confluence/Reference.cs
+++ b/GreenshotConfluencePlugin/Web References/confluence/Reference.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
+// Runtime Version:4.0.30319.34209
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,7 +9,7 @@
//------------------------------------------------------------------------------
//
-// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.42000.
+// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.34209.
//
#pragma warning disable 1591
@@ -23,10 +23,10 @@ namespace GreenshotConfluencePlugin.confluence {
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
- [System.Web.Services.WebServiceBindingAttribute(Name="confluenceservice-v1SoapBinding", Namespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.WebServiceBindingAttribute(Name="confluenceservice-v1SoapBinding", Namespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(AbstractRemotePageSummary))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemoteSpaceSummary))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemoteSearchResult))]
@@ -58,7 +58,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
public ConfluenceSoapServiceService() {
- this.Url = "https://confluence/rpc/soap-axis/confluenceservice-v1";
+ this.Url = "http://confluence/rpc/soap-axis/confluenceservice-v1";
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
@@ -126,7 +126,7 @@ namespace GreenshotConfluencePlugin.confluence {
public event getPagesCompletedEventHandler getPagesCompleted;
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("searchReturn")]
public RemoteSearchResult[] search(string in0, string in1, int in2) {
object[] results = this.Invoke("search", new object[] {
@@ -160,7 +160,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getSpaceReturn")]
public RemoteSpace getSpace(string in0, string in1) {
object[] results = this.Invoke("getSpace", new object[] {
@@ -192,7 +192,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getChildrenReturn")]
public RemotePageSummary[] getChildren(string in0, long in1) {
object[] results = this.Invoke("getChildren", new object[] {
@@ -224,7 +224,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("loginReturn")]
public string login(string in0, string in1) {
object[] results = this.Invoke("login", new object[] {
@@ -256,7 +256,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getPageReturn")]
public RemotePage getPage(string in0, string in1, string in2) {
object[] results = this.Invoke("getPage", new object[] {
@@ -291,7 +291,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
[System.Web.Services.WebMethodAttribute(MessageName="getPage1")]
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getPageReturn")]
public RemotePage getPage(string in0, long in1) {
object[] results = this.Invoke("getPage1", new object[] {
@@ -323,7 +323,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("logoutReturn")]
public bool logout(string in0) {
object[] results = this.Invoke("logout", new object[] {
@@ -353,7 +353,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("addAttachmentReturn")]
public RemoteAttachment addAttachment(string in0, long in1, RemoteAttachment in2, [System.Xml.Serialization.SoapElementAttribute(DataType="base64Binary")] byte[] in3) {
object[] results = this.Invoke("addAttachment", new object[] {
@@ -390,7 +390,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
[System.Web.Services.WebMethodAttribute(MessageName="addAttachment1")]
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("addAttachmentReturn")]
public RemoteAttachment addAttachment(string in0, RemoteAttachment in1, [System.Xml.Serialization.SoapElementAttribute(DataType="base64Binary")] byte[] in2) {
object[] results = this.Invoke("addAttachment1", new object[] {
@@ -424,7 +424,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getSpacesReturn")]
public RemoteSpaceSummary[] getSpaces(string in0) {
object[] results = this.Invoke("getSpaces", new object[] {
@@ -454,7 +454,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="https://confluence/rpc/soap-axis/confluenceservice-v1")]
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://soap.rpc.confluence.atlassian.com", ResponseNamespace="http://confluence/rpc/soap-axis/confluenceservice-v1")]
[return: System.Xml.Serialization.SoapElementAttribute("getPagesReturn")]
public RemotePageSummary[] getPages(string in0, string in1) {
object[] results = this.Invoke("getPages", new object[] {
@@ -505,7 +505,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -578,7 +578,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -716,7 +716,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemotePageSummary))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemotePage))]
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -789,7 +789,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemotePage))]
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -810,7 +810,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -934,7 +934,7 @@ namespace GreenshotConfluencePlugin.confluence {
///
[System.Xml.Serialization.SoapIncludeAttribute(typeof(RemoteSpace))]
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -995,7 +995,7 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
@@ -1042,11 +1042,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void searchCompletedEventHandler(object sender, searchCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class searchCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1068,11 +1068,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getSpaceCompletedEventHandler(object sender, getSpaceCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getSpaceCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1094,11 +1094,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getChildrenCompletedEventHandler(object sender, getChildrenCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getChildrenCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1120,11 +1120,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void loginCompletedEventHandler(object sender, loginCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class loginCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1146,11 +1146,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getPageCompletedEventHandler(object sender, getPageCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getPageCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1172,11 +1172,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getPage1CompletedEventHandler(object sender, getPage1CompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getPage1CompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1198,11 +1198,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void logoutCompletedEventHandler(object sender, logoutCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class logoutCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1224,11 +1224,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void addAttachmentCompletedEventHandler(object sender, addAttachmentCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class addAttachmentCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1250,11 +1250,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void addAttachment1CompletedEventHandler(object sender, addAttachment1CompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class addAttachment1CompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1276,11 +1276,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getSpacesCompletedEventHandler(object sender, getSpacesCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getSpacesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -1302,11 +1302,11 @@ namespace GreenshotConfluencePlugin.confluence {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void getPagesCompletedEventHandler(object sender, getPagesCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.8.4084.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getPagesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
diff --git a/src/Greenshot.Plugin.Confluence/Web References/confluence/Reference.map b/GreenshotConfluencePlugin/Web References/confluence/Reference.map
similarity index 100%
rename from src/Greenshot.Plugin.Confluence/Web References/confluence/Reference.map
rename to GreenshotConfluencePlugin/Web References/confluence/Reference.map
diff --git a/src/Greenshot.Plugin.Confluence/Web References/confluence/confluenceservice-v1.wsdl b/GreenshotConfluencePlugin/Web References/confluence/confluenceservice-v1.wsdl
similarity index 89%
rename from src/Greenshot.Plugin.Confluence/Web References/confluence/confluenceservice-v1.wsdl
rename to GreenshotConfluencePlugin/Web References/confluence/confluenceservice-v1.wsdl
index 2237ddb2e..74c6f748c 100644
--- a/src/Greenshot.Plugin.Confluence/Web References/confluence/confluenceservice-v1.wsdl
+++ b/GreenshotConfluencePlugin/Web References/confluence/confluenceservice-v1.wsdl
@@ -1,14 +1,14 @@
-
-
@@ -145,7 +145,7 @@
xmlns="http://www.w3.org/2001/XMLSchema">
-
+
@@ -190,7 +190,7 @@
xmlns="http://www.w3.org/2001/XMLSchema">
-
+
@@ -291,7 +291,7 @@
-
+
@@ -500,17 +500,17 @@
@@ -522,12 +522,12 @@
@@ -539,17 +539,17 @@
@@ -561,17 +561,17 @@
@@ -583,17 +583,17 @@
@@ -605,17 +605,17 @@
@@ -627,17 +627,17 @@
@@ -649,12 +649,12 @@
@@ -666,12 +666,12 @@
@@ -683,12 +683,12 @@
@@ -700,17 +700,17 @@
@@ -722,17 +722,17 @@
@@ -741,7 +741,7 @@
+ location="http://confluence/rpc/soap-axis/confluenceservice-v1" />
diff --git a/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.Credentials.template b/GreenshotDropboxPlugin/DropBoxCredentials.cs
similarity index 79%
rename from src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.Credentials.template
rename to GreenshotDropboxPlugin/DropBoxCredentials.cs
index 56cde680f..c02e848ca 100644
--- a/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.Credentials.template
+++ b/GreenshotDropboxPlugin/DropBoxCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.Dropbox {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
- /// You can set your own values here
- ///
- public static class DropBoxCredentials {
- public static string CONSUMER_KEY = "${DropBox13_ClientId}";
- public static string CONSUMER_SECRET = "${DropBox13_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotDropboxPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
+ /// You can set your own values here
+ ///
+ public static class DropBoxCredentials {
+ public static string CONSUMER_KEY = "@credentials_dropbox_consumer_key@";
+ public static string CONSUMER_SECRET = "@credentials_dropbox_consumer_secret@";
+ }
+}
diff --git a/src/Greenshot.Plugin.Dropbox/Dropbox.gif b/GreenshotDropboxPlugin/Dropbox.gif
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Dropbox.gif
rename to GreenshotDropboxPlugin/Dropbox.gif
diff --git a/GreenshotDropboxPlugin/DropboxDestination.cs b/GreenshotDropboxPlugin/DropboxDestination.cs
new file mode 100644
index 000000000..1e378a7a1
--- /dev/null
+++ b/GreenshotDropboxPlugin/DropboxDestination.cs
@@ -0,0 +1,62 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotDropboxPlugin {
+ internal class DropboxDestination : AbstractDestination {
+ private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection();
+
+ private readonly DropboxPlugin _plugin;
+ public DropboxDestination(DropboxPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override string Designation => "Dropbox";
+
+ public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item);
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(DropboxPlugin));
+ return (Image)resources.GetObject("Dropbox");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manually, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, out uploadUrl);
+ if (uploaded) {
+ exportInformation.Uri = uploadUrl;
+ exportInformation.ExportMade = true;
+ if (DropboxConfig.AfterUploadLinkToClipBoard) {
+ ClipboardHelper.SetClipboardData(uploadUrl);
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotDropboxPlugin/DropboxPlugin.cs b/GreenshotDropboxPlugin/DropboxPlugin.cs
new file mode 100644
index 000000000..9bd6115c5
--- /dev/null
+++ b/GreenshotDropboxPlugin/DropboxPlugin.cs
@@ -0,0 +1,141 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotDropboxPlugin {
+ ///
+ /// This is the Dropbox base code
+ ///
+ public class DropboxPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
+ private static DropboxPluginConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new DropboxDestination(this);
+ }
+
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ _host = pluginHost;
+ Attributes = myAttributes;
+
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(DropboxPlugin));
+
+ _itemPlugInConfig = new ToolStripMenuItem
+ {
+ Text = Language.GetString("dropbox", LangKey.Configure),
+ Tag = _host,
+ Image = (Image)_resources.GetObject("Dropbox")
+ };
+ _itemPlugInConfig.Click += ConfigMenuClick;
+
+ PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Dropbox Plugin shutdown.");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ public void ConfigMenuClick(object sender, EventArgs eventArgs) {
+ _config.ShowConfigDialog();
+ }
+
+ ///
+ /// This will be called when the menu item in the Editor is clicked
+ ///
+ public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
+ uploadUrl = null;
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
+ try {
+ string dropboxUrl = null;
+ new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("dropbox", LangKey.communication_wait),
+ delegate
+ {
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
+ dropboxUrl = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, filename);
+ }
+ );
+ if (dropboxUrl == null) {
+ return false;
+ }
+ uploadUrl = dropboxUrl;
+ return true;
+ } catch (Exception e) {
+ Log.Error(e);
+ MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message);
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Dropbox/DropboxPlugin.resx b/GreenshotDropboxPlugin/DropboxPlugin.resx
similarity index 95%
rename from src/Greenshot.Plugin.Dropbox/DropboxPlugin.resx
rename to GreenshotDropboxPlugin/DropboxPlugin.resx
index fdc63087a..571fbeac0 100644
--- a/src/Greenshot.Plugin.Dropbox/DropboxPlugin.resx
+++ b/GreenshotDropboxPlugin/DropboxPlugin.resx
@@ -112,12 +112,12 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
diff --git a/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs
new file mode 100644
index 000000000..a484deb7b
--- /dev/null
+++ b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs
@@ -0,0 +1,58 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+
+namespace GreenshotDropboxPlugin {
+ ///
+ /// Description of ImgurConfiguration.
+ ///
+ [IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")]
+ public class DropboxPluginConfiguration : IniSection {
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Dropbox link to clipboard.", DefaultValue = "true")]
+ public bool AfterUploadLinkToClipBoard { get; set; }
+
+ [IniProperty("DropboxToken", Description = "The Dropbox token", Encrypted = true, ExcludeIfNull = true)]
+ public string DropboxToken { get; set; }
+ [IniProperty("DropboxTokenSecret", Description = "The Dropbox token secret", Encrypted = true, ExcludeIfNull = true)]
+ public string DropboxTokenSecret { get; set; }
+
+ ///
+ /// A form for token
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ DialogResult result = new SettingsForm().ShowDialog();
+ if (result == DialogResult.OK) {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/GreenshotDropboxPlugin/DropboxUtils.cs b/GreenshotDropboxPlugin/DropboxUtils.cs
new file mode 100644
index 000000000..f8a180f4c
--- /dev/null
+++ b/GreenshotDropboxPlugin/DropboxUtils.cs
@@ -0,0 +1,84 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotDropboxPlugin {
+ ///
+ /// Description of DropboxUtils.
+ ///
+ public class DropboxUtils {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
+ private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection();
+
+ private DropboxUtils() {
+ }
+
+ public static string UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string filename) {
+ var oAuth = new OAuthSession(DropBoxCredentials.CONSUMER_KEY, DropBoxCredentials.CONSUMER_SECRET)
+ {
+ BrowserSize = new Size(1080, 650),
+ CheckVerifier = false,
+ AccessTokenUrl = "https://api.dropbox.com/1/oauth/access_token",
+ AuthorizeUrl = "https://api.dropbox.com/1/oauth/authorize",
+ RequestTokenUrl = "https://api.dropbox.com/1/oauth/request_token",
+ LoginTitle = "Dropbox authorization",
+ Token = DropboxConfig.DropboxToken,
+ TokenSecret = DropboxConfig.DropboxTokenSecret
+ };
+
+ try {
+ SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+ string uploadResponse = oAuth.MakeOAuthRequest(HTTPMethod.POST, "https://api-content.dropbox.com/1/files_put/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, imageToUpload);
+ Log.DebugFormat("Upload response: {0}", uploadResponse);
+ } catch (Exception ex) {
+ Log.Error("Upload error: ", ex);
+ throw;
+ } finally {
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ DropboxConfig.DropboxToken = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ DropboxConfig.DropboxTokenSecret = oAuth.TokenSecret;
+ }
+ }
+
+ // Try to get a URL to the uploaded image
+ try {
+ string responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, "https://api.dropbox.com/1/shares/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, null);
+ if (responseString != null) {
+ Log.DebugFormat("Parsing output: {0}", responseString);
+ IDictionary returnValues = JSONHelper.JsonDecode(responseString);
+ if (returnValues.ContainsKey("url")) {
+ return returnValues["url"] as string;
+ }
+ }
+ } catch (Exception ex) {
+ Log.Error("Can't parse response.", ex);
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Box/Forms/BoxForm.cs b/GreenshotDropboxPlugin/Forms/DropboxForm.cs
similarity index 68%
rename from src/Greenshot.Plugin.Box/Forms/BoxForm.cs
rename to GreenshotDropboxPlugin/Forms/DropboxForm.cs
index 29c2c7a0d..c526d67d1 100644
--- a/src/Greenshot.Plugin.Box/Forms/BoxForm.cs
+++ b/GreenshotDropboxPlugin/Forms/DropboxForm.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,14 +16,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-using Greenshot.Base.Controls;
+using GreenshotPlugin.Controls;
-namespace Greenshot.Plugin.Box.Forms
-{
- public class BoxForm : GreenshotForm
- {
- }
-}
\ No newline at end of file
+namespace GreenshotDropboxPlugin.Forms {
+ public class DropboxForm : GreenshotForm {
+ }
+}
diff --git a/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs b/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
similarity index 79%
rename from src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs
rename to GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
index e65cba1ec..3e8226dc9 100644
--- a/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs
+++ b/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
@@ -2,7 +2,7 @@
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2011 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Dropbox.Forms {
+namespace GreenshotDropboxPlugin {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -48,12 +45,12 @@ namespace Greenshot.Plugin.Dropbox.Forms {
/// not be able to load this method if it was changed manually.
///
private void InitializeComponent() {
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.label_AfterUpload = new GreenshotLabel();
- this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.SuspendLayout();
//
// buttonOK
@@ -86,7 +83,7 @@ namespace Greenshot.Plugin.Dropbox.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(116, 9);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(DropboxConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Dropbox";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(309, 21);
this.combobox_uploadimageformat.TabIndex = 1;
@@ -109,10 +106,11 @@ namespace Greenshot.Plugin.Dropbox.Forms {
//
// checkboxAfterUploadLinkToClipBoard
//
+ this.checkboxAfterUploadLinkToClipBoard.AutoSize = true;
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "dropbox.label_AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(116, 37);
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
- this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(DropboxConfiguration.AfterUploadLinkToClipBoard);
+ this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Dropbox";
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
@@ -138,11 +136,11 @@ namespace Greenshot.Plugin.Dropbox.Forms {
this.PerformLayout();
}
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotLabel label_AfterUpload;
- private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
}
}
diff --git a/GreenshotDropboxPlugin/Forms/SettingsForm.cs b/GreenshotDropboxPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..d057b10dc
--- /dev/null
+++ b/GreenshotDropboxPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,39 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotDropboxPlugin.Forms;
+
+namespace GreenshotDropboxPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : DropboxForm {
+ public SettingsForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = buttonOK;
+ CancelButton = buttonCancel;
+ }
+
+ }
+}
diff --git a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj
new file mode 100644
index 000000000..7721478a4
--- /dev/null
+++ b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj
@@ -0,0 +1,82 @@
+
+
+
+
+ {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}
+ Library
+ GreenshotDropboxPlugin
+ GreenshotDropboxPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+
+
+
+
+
+ 3.5
+
+
+
+
+ False
+ ..\Greenshot\lib\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+ DropboxPlugin.cs
+
+
+
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+ if exist "$(ProjectDir)DropBoxCredentials.orig.cs" (
+ rename "$(ProjectDir)DropBoxCredentials.cs" "DropBoxCredentials.private.cs"
+ rename "$(ProjectDir)DropBoxCredentials.orig.cs" "DropBoxCredentials.cs"
+)
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+if exist "$(ProjectDir)DropBoxCredentials.private.cs" (
+ rename "$(ProjectDir)DropBoxCredentials.cs" "DropBoxCredentials.orig.cs"
+ rename "$(ProjectDir)DropBoxCredentials.private.cs" "DropBoxCredentials.cs"
+)
+
+
\ No newline at end of file
diff --git a/GreenshotDropboxPlugin/LanguageKeys.cs b/GreenshotDropboxPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..0cc9c5204
--- /dev/null
+++ b/GreenshotDropboxPlugin/LanguageKeys.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotDropboxPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ settings_title,
+ label_upload_format,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ Configure,
+ label_AfterUpload,
+ label_AfterUploadLinkToClipBoard
+ }
+}
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-cs-CZ.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-cs-CZ.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-cs-CZ.xml
index 5f0dcd81e..00a5acef0 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-cs-CZ.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-cs-CZ.xml
@@ -1,25 +1,25 @@
-
-
-
- Použijte prosím webové stránky dropbox k přihlášení a poskytněte programu Greenshot přístup k službě dropbox, dokončete stisknutím OK.
- Ověřit
- Zrušit
- Probíhá komunikace s Dropbox. Počkejte prosím...
- Konfigurovat
- Jste si jistý, že chcete odstranit obrázek {0} z Dropbox?
- Odstranit Dropbox {0}
- Historie
- Po odeslání
- Odkaz do schránky
- Otevřít historii
- Ověření Token
- Formát obrázku
- OK
- Nastavení Dropbox
- Prosím ověřit dostupnost aplikace Dropbox. Otevřít obrazovku pro nastavení snímku.
- Odeslat
- Při odesílání do Dropbox došlo k chybě:
- Odeslat do Dropbox
- Obrázek úspěšně odslán do Dropbox!
-
+
+
+
+ Použijte prosím webové stránky dropbox k přihlášení a poskytněte programu Greenshot přístup k službě dropbox, dokončete stisknutím OK.
+ Ověřit
+ Zrušit
+ Probíhá komunikace s Dropbox. Počkejte prosím...
+ Konfigurovat
+ Jste si jistý, že chcete odstranit obrázek {0} z Dropbox?
+ Odstranit Dropbox {0}
+ Historie
+ Po odeslání
+ Odkaz do schránky
+ Otevřít historii
+ Ověření Token
+ Formát obrázku
+ OK
+ Nastavení Dropbox
+ Prosím ověřit dostupnost aplikace Dropbox. Otevřít obrazovku pro nastavení snímku.
+ Odeslat
+ Při odesílání do Dropbox došlo k chybě:
+ Odeslat do Dropbox
+ Obrázek úspěšně odslán do Dropbox!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-de-DE.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-de-DE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-de-DE.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-de-DE.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-en-US.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-en-US.xml
similarity index 94%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-en-US.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-en-US.xml
index d4fe2ec95..682135288 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-en-US.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-en-US.xml
@@ -23,7 +23,7 @@
Successfully uploaded image to Dropbox!
- An error occurred while uploading to Dropbox:
+ An error occured while uploading to Dropbox:
Image format
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-fr-FR.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-fr-FR.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-fr-FR.xml
index ef2f440ec..9f50c56d7 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-fr-FR.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-fr-FR.xml
@@ -1,14 +1,14 @@
-
-
-
- Communication en cours avec Dropbox. Veuillez patientez...
- Configurer Dropbox
- Après téléversement
- Copier le lien dans le presse-papier
- Format image
- Paramètres Dropbox
- Une erreur s'est produite lors du téléversement vers Dropbox :
- Téléverser vers Dropbox
- Image téléversée aves succès vers Dropbox !
-
+
+
+
+ Communication en cours avec Dropbox. Veuillez patientez...
+ Configurer Dropbox
+ Après téléversement
+ Copier le lien dans le presse-papier
+ Format image
+ Paramètres Dropbox
+ Une erreur s'est produite lors du téléversement vers Dropbox :
+ Téléverser vers Dropbox
+ Image téléversée aves succès vers Dropbox !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-id-ID.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-id-ID.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-id-ID.xml
index 2bdfdbba7..9485440b5 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-id-ID.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-id-ID.xml
@@ -1,15 +1,15 @@
-
-
-
- Menyambungkan ke Dropbox. Tunggu sebentar...
- Konfigurasi Dropbox
- Setelah mengunggah
- Sambung ke papanklip
- Buka riwayat
- Format gambar
- Setelan Dropbox
- Kesalahan terjadi ketik mengunggah ke Dropbox:
- Unggah ke Dropbox
- Sukses mengunggah gambar ke Dropbox!
-
+
+
+
+ Menyambungkan ke Dropbox. Tunggu sebentar...
+ Konfigurasi Dropbox
+ Setelah mengunggah
+ Sambung ke papanklip
+ Buka riwayat
+ Format gambar
+ Setelan Dropbox
+ Kesalahan terjadi ketik mengunggah ke Dropbox:
+ Unggah ke Dropbox
+ Sukses mengunggah gambar ke Dropbox!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-it-IT.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-it-IT.xml
similarity index 76%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-it-IT.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-it-IT.xml
index e295eebab..ec618c12e 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-it-IT.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-it-IT.xml
@@ -1,17 +1,17 @@
-
+
- Collegamento agli Appunti
+ Collegamento agli appunti
Apri cronologia
- Dopo il caricamento
+ Dopo il carico
- Impostazioni di Dropbox
+ Configurazione di Dropbox
Carica su Dropbox
@@ -20,7 +20,7 @@
Impostazioni di Dropbox
- Caricamento immagine su Dropbox completato!
+ Immagine caricata correttamente su Dropbox!
Si è verificato un errore durante il caricamento su Dropbox:
@@ -29,7 +29,7 @@
Formato immagine
- Comunicazione con Dropbox...
+ Comunicazione con Dropbox. Attendere prego...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-kab-DZ.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-kab-DZ.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-ko-KR.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-ko-KR.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-lv-LV.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-lv-LV.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-pl-PL.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-pl-PL.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-pl-PL.xml
index cc021f461..493cccd49 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-pl-PL.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-pl-PL.xml
@@ -1,15 +1,15 @@
-
-
-
- Trwa komunikacja z Dropbox. Proszę czekać...
- Konfiguruj Dropbox
- Po wysłaniu
- Link do schowka
- Otwórz historię
- Format obrazu
- Ustawienia Dropbox
- Wystąpił błąd przy wysyłaniu do Dropbox:
- Wyślij do Dropbox
- Wysyłanie obrazu do Dropbox powiodło się!
-
+
+
+
+ Trwa komunikacja z Dropbox. Proszę czekać...
+ Konfiguruj Dropbox
+ Po wysłaniu
+ Link do schowka
+ Otwórz historię
+ Format obrazu
+ Ustawienia Dropbox
+ Wystąpił błąd przy wysyłaniu do Dropbox:
+ Wyślij do Dropbox
+ Wysyłanie obrazu do Dropbox powiodło się!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-pt-PT.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-pt-PT.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-ru-RU.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-ru-RU.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-ru-RU.xml
index bb96769a5..863e0446d 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-ru-RU.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-ru-RU.xml
@@ -1,15 +1,15 @@
-
-
-
- Обмен информацией с Dropbox. Подождите...
- Настройка Dropbox
- После загрузки
- Ссылку в буфер обмена
- Открыть историию
- Формат изображения
- Настройки Dropbox
- Произошла ошибка при загрузке на Dropbox:
- Добавить в Dropbox
- Изображение успешно загружено на Dropbox!
-
+
+
+
+ Обмен информацией с Dropbox. Подождите...
+ Настройка Dropbox
+ После загрузки
+ Ссылку в буфер обмена
+ Открыть историию
+ Формат изображения
+ Настройки Dropbox
+ Произошла ошибка при загрузке на Dropbox:
+ Добавить в Dropbox
+ Изображение успешно загружено на Dropbox!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-sr-RS.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-sr-RS.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-sr-RS.xml
index 55c054c38..01e8743c5 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-sr-RS.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-sr-RS.xml
@@ -1,15 +1,15 @@
-
-
-
- Комуницирам с Дропбоксом. Сачекајте…
- Поставке Дропбокса
- Након отпремања:
- Веза ка остави
- Отвори историју
- Формат слике:
- Поставке Дропбокса
- Дошло је до грешке при отпремању на Дропбокс:
- Отпреми на Дропбокс
- Слика је успешно отпремљена на Дропбокс.
-
+
+
+
+ Комуницирам с Дропбоксом. Сачекајте…
+ Поставке Дропбокса
+ Након отпремања:
+ Веза ка остави
+ Отвори историју
+ Формат слике:
+ Поставке Дропбокса
+ Дошло је до грешке при отпремању на Дропбокс:
+ Отпреми на Дропбокс
+ Слика је успешно отпремљена на Дропбокс.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-sv-SE.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-sv-SE.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-uk-UA.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-uk-UA.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-uk-UA.xml
index 980f13bad..023913e83 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-uk-UA.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-uk-UA.xml
@@ -1,15 +1,15 @@
-
-
-
- Посилання в буфер обміну
- Відкрити історію
- Після вивантаження
- Налаштувати Dropbox
- Вивантажити на Dropbox
- Параметри Dropbox
- Зображення вдало вивантажено на Dropbox!
- Відбулась помилка при вивантаженні зображення на Dropbox:
- Формат зображення
- З’єднання з Dropbox. Будь ласка, зачекайте...
-
-
+
+
+
+ Посилання в буфер обміну
+ Відкрити історію
+ Після вивантаження
+ Налаштувати Dropbox
+ Вивантажити на Dropbox
+ Параметри Dropbox
+ Зображення вдало вивантажено на Dropbox!
+ Відбулась помилка при вивантаженні зображення на Dropbox:
+ Формат зображення
+ З’єднання з Dropbox. Будь ласка, зачекайте...
+
+
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-CN.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-CN.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-CN.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-CN.xml
index 34903f726..e5305d89e 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-CN.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-CN.xml
@@ -1,15 +1,15 @@
-
-
-
- 正在连接Dropbox。请稍后...
- 配置Dropbox
- 上传之后
- 复制链接到剪贴板
- 打开历史记录
- 图片格式
- Dropbox设置
- 在上传到Dropbox时发生错误:
- 上传到Dropbox
- 图片已成功上传到了Dropbox!
-
+
+
+
+ 正在连接Dropbox。请稍后...
+ 配置Dropbox
+ 上传之后
+ 复制链接到剪贴板
+ 打开历史记录
+ 图片格式
+ Dropbox设置
+ 在上传到Dropbox时发生错误:
+ 上传到Dropbox
+ 图片已成功上传到了Dropbox!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-TW.xml b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-TW.xml
rename to GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-TW.xml
index b3767b223..a62a84cf1 100644
--- a/src/Greenshot.Plugin.Dropbox/Languages/language_dropbox-zh-TW.xml
+++ b/GreenshotDropboxPlugin/Languages/language_dropboxplugin-zh-TW.xml
@@ -1,15 +1,15 @@
-
-
-
- 正在與 Dropbox 通訊,請稍候...
- 組態 Dropbox
- 上傳後
- 連結到剪貼簿
- 開啟歷程記錄
- 圖片格式
- Dropbox 設定
- 上傳到 Dropbox 時發生錯誤:
- 上傳到 Dropbox
- 上傳圖片到 Dropbox 成功!
-
+
+
+
+ 正在與 Dropbox 通訊,請稍候...
+ 組態 Dropbox
+ 上傳後
+ 連結到剪貼簿
+ 開啟歷程記錄
+ 圖片格式
+ Dropbox 設定
+ 上傳到 Dropbox 時發生錯誤:
+ 上傳到 Dropbox
+ 上傳圖片到 Dropbox 成功!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Properties/AssemblyInfo.cs b/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
similarity index 57%
rename from src/Greenshot.Plugin.Dropbox/Properties/AssemblyInfo.cs
rename to GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
index b95b9af6d..44f4a108a 100644
--- a/src/Greenshot.Plugin.Dropbox/Properties/AssemblyInfo.cs
+++ b/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
+[assembly: AssemblyTitle("Greenshot-Dropbox-Plugin")]
[assembly: AssemblyDescription("A plugin to upload images to Dropbox")]
-[assembly: AssemblyPluginIdentifier("Dropbox Plugin")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot & F. Noel")]
+[assembly: AssemblyProduct("Dropbox Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotDropboxPlugin.DropboxPlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs b/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs
new file mode 100644
index 000000000..d6aae0d1f
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs
@@ -0,0 +1,158 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace ExternalCommand {
+ ///
+ /// Description of FlickrConfiguration.
+ ///
+ [IniSection("ExternalCommand", Description="Greenshot ExternalCommand Plugin configuration")]
+ public class ExternalCommandConfiguration : IniSection {
+ [IniProperty("Commands", Description="The commands that are available.")]
+ public List Commands { get; set; }
+
+ [IniProperty("RedirectStandardError", Description = "Redirect the standard error of all external commands, used to output as warning to the greenshot.log.", DefaultValue = "true")]
+ public bool RedirectStandardError { get; set; }
+
+ [IniProperty("RedirectStandardOutput", Description = "Redirect the standard output of all external commands, used for different other functions (more below).", DefaultValue = "true")]
+ public bool RedirectStandardOutput { get; set; }
+
+ [IniProperty("ShowStandardOutputInLog", Description = "Depends on 'RedirectStandardOutput': Show standard output of all external commands to the Greenshot log, this can be usefull for debugging.", DefaultValue = "false")]
+ public bool ShowStandardOutputInLog { get; set; }
+
+ [IniProperty("ParseForUri", Description = "Depends on 'RedirectStandardOutput': Parse the output and take the first found URI, if a URI is found than clicking on the notify bubble goes there.", DefaultValue = "true")]
+ public bool ParseOutputForUri { get; set; }
+
+ [IniProperty("OutputToClipboard", Description = "Depends on 'RedirectStandardOutput': Place the standard output on the clipboard.", DefaultValue = "false")]
+ public bool OutputToClipboard { get; set; }
+
+ [IniProperty("UriToClipboard", Description = "Depends on 'RedirectStandardOutput' & 'ParseForUri': If an URI is found in the standard input, place it on the clipboard. (This overwrites the output from OutputToClipboard setting.)", DefaultValue = "true")]
+ public bool UriToClipboard { get; set; }
+
+ [IniProperty("Commandline", Description="The commandline for the output command.")]
+ public Dictionary Commandline { get; set; }
+
+ [IniProperty("Argument", Description="The arguments for the output command.")]
+ public Dictionary Argument { get; set; }
+
+ [IniProperty("RunInbackground", Description = "Should the command be started in the background.")]
+ public Dictionary RunInbackground { get; set; }
+
+ [IniProperty("DeletedBuildInCommands", Description = "If a build in command was deleted manually, it should not be recreated.")]
+ public List DeletedBuildInCommands { get; set; }
+
+ private const string MsPaint = "MS Paint";
+ private static readonly string PaintPath;
+ private static readonly bool HasPaint;
+
+ private const string PaintDotNet = "Paint.NET";
+ private static readonly string PaintDotNetPath;
+ private static readonly bool HasPaintDotNet;
+ static ExternalCommandConfiguration() {
+ try {
+ PaintPath = PluginUtils.GetExePath("pbrush.exe");
+ HasPaint = !string.IsNullOrEmpty(PaintPath) && File.Exists(PaintPath);
+ } catch {
+ // Ignore
+ }
+ try
+ {
+ PaintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe");
+ HasPaintDotNet = !string.IsNullOrEmpty(PaintDotNetPath) && File.Exists(PaintDotNetPath);
+ }
+ catch
+ {
+ // Ignore
+ }
+ }
+
+ ///
+ /// Delete the configuration for the specified command
+ ///
+ /// string with command
+ public void Delete(string command)
+ {
+ if (string.IsNullOrEmpty(command))
+ {
+ return;
+ }
+ Commands.Remove(command);
+ Commandline.Remove(command);
+ Argument.Remove(command);
+ RunInbackground.Remove(command);
+ if (MsPaint.Equals(command) || PaintDotNet.Equals(command))
+ {
+ if (!DeletedBuildInCommands.Contains(command))
+ {
+ DeletedBuildInCommands.Add(command);
+ }
+ }
+ }
+
+ public override void AfterLoad()
+ {
+ base.AfterLoad();
+
+ // Check if we need to add MsPaint
+ if (HasPaint && !Commands.Contains(MsPaint) && !DeletedBuildInCommands.Contains(MsPaint))
+ {
+ Commands.Add(MsPaint);
+ Commandline.Add(MsPaint, PaintPath);
+ Argument.Add(MsPaint, "\"{0}\"");
+ RunInbackground.Add(MsPaint, true);
+ }
+
+ // Check if we need to add Paint.NET
+ if (HasPaintDotNet && !Commands.Contains(PaintDotNet) && !DeletedBuildInCommands.Contains(PaintDotNet))
+ {
+ Commands.Add(PaintDotNet);
+ Commandline.Add(PaintDotNet, PaintDotNetPath);
+ Argument.Add(PaintDotNet, "\"{0}\"");
+ RunInbackground.Add(PaintDotNet, true);
+ }
+ }
+
+ ///
+ /// Supply values we can't put as defaults
+ ///
+ /// The property to return a default for
+ /// object with the default value for the supplied property
+ public override object GetDefault(string property) {
+ switch(property) {
+ case nameof(DeletedBuildInCommands):
+ return new List();
+ case nameof(Commands):
+ return new List();
+ case nameof(Commandline):
+ return new Dictionary();
+ case nameof(Argument):
+ return new Dictionary();
+ case nameof(RunInbackground):
+ return new Dictionary();
+ }
+ return null;
+ }
+ }
+}
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs b/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs
new file mode 100644
index 000000000..93c0e8096
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs
@@ -0,0 +1,223 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Threading;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System.ComponentModel;
+using System.Text.RegularExpressions;
+
+namespace ExternalCommand {
+ ///
+ /// Description of OCRDestination.
+ ///
+ public class ExternalCommandDestination : AbstractDestination {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandDestination));
+ private static readonly Regex URI_REGEXP = new Regex(@"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)");
+ private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private readonly string _presetCommand;
+
+ public ExternalCommandDestination(string commando) {
+ _presetCommand = commando;
+ }
+
+ public override string Designation => "External " + _presetCommand.Replace(',','_');
+
+ public override string Description => _presetCommand;
+
+ public override IEnumerable DynamicDestinations() {
+ yield break;
+ }
+
+ public override Image DisplayIcon => IconCache.IconForCommand(_presetCommand);
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
+ outputSettings.PreventGreenshotFormat();
+
+ if (_presetCommand != null) {
+ if (!config.RunInbackground.ContainsKey(_presetCommand)) {
+ config.RunInbackground.Add(_presetCommand, true);
+ }
+ bool runInBackground = config.RunInbackground[_presetCommand];
+ string fullPath = captureDetails.Filename;
+ if (fullPath == null) {
+ fullPath = ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
+ }
+
+ string output;
+ string error;
+ if (runInBackground) {
+ Thread commandThread = new Thread(delegate()
+ {
+ CallExternalCommand(exportInformation, fullPath, out output, out error);
+ ProcessExport(exportInformation, surface);
+ })
+ {
+ Name = "Running " + _presetCommand,
+ IsBackground = true
+ };
+ commandThread.SetApartmentState(ApartmentState.STA);
+ commandThread.Start();
+ exportInformation.ExportMade = true;
+ } else {
+ CallExternalCommand(exportInformation, fullPath, out output, out error);
+ ProcessExport(exportInformation, surface);
+ }
+ }
+ return exportInformation;
+ }
+
+ ///
+ /// Wrapper method for the background and normal call, this does all the logic:
+ /// Call the external command, parse for URI, place to clipboard and set the export information
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void CallExternalCommand(ExportInformation exportInformation, string fullPath, out string output, out string error) {
+ output = null;
+ error = null;
+ try {
+ if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0) {
+ exportInformation.ExportMade = true;
+ if (!string.IsNullOrEmpty(output)) {
+ MatchCollection uriMatches = URI_REGEXP.Matches(output);
+ // Place output on the clipboard before the URI, so if one is found this overwrites
+ if (config.OutputToClipboard) {
+ ClipboardHelper.SetClipboardData(output);
+ }
+ if (uriMatches.Count > 0) {
+ exportInformation.Uri = uriMatches[0].Groups[1].Value;
+ LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
+ if (config.UriToClipboard) {
+ ClipboardHelper.SetClipboardData(exportInformation.Uri);
+ }
+ }
+ }
+ } else {
+ LOG.WarnFormat("Error calling external command: {0} ", output);
+ exportInformation.ExportMade = false;
+ exportInformation.ErrorMessage = error;
+ }
+ } catch (Exception ex) {
+ exportInformation.ExportMade = false;
+ exportInformation.ErrorMessage = ex.Message;
+ LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
+ }
+ }
+
+ ///
+ /// Wrapper to retry with a runas
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private int CallExternalCommand(string commando, string fullPath, out string output, out string error) {
+ try {
+ return CallExternalCommand(commando, fullPath, null, out output, out error);
+ } catch (Win32Exception w32Ex) {
+ try {
+ return CallExternalCommand(commando, fullPath, "runas", out output, out error);
+ } catch {
+ w32Ex.Data.Add("commandline", config.Commandline[_presetCommand]);
+ w32Ex.Data.Add("arguments", config.Argument[_presetCommand]);
+ throw;
+ }
+ } catch (Exception ex) {
+ ex.Data.Add("commandline", config.Commandline[_presetCommand]);
+ ex.Data.Add("arguments", config.Argument[_presetCommand]);
+ throw;
+ }
+ }
+
+ ///
+ /// The actual executing code for the external command
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private int CallExternalCommand(string commando, string fullPath, string verb, out string output, out string error) {
+ string commandline = config.Commandline[commando];
+ string arguments = config.Argument[commando];
+ output = null;
+ error = null;
+ if (!string.IsNullOrEmpty(commandline)) {
+ using (Process process = new Process())
+ {
+ // Fix variables
+ commandline = FilenameHelper.FillVariables(commandline, true);
+ commandline = FilenameHelper.FillCmdVariables(commandline, true);
+
+ arguments = FilenameHelper.FillVariables(arguments, false);
+ arguments = FilenameHelper.FillCmdVariables(arguments, false);
+
+ process.StartInfo.FileName = FilenameHelper.FillCmdVariables(commandline, true);
+ process.StartInfo.Arguments = FormatArguments(arguments, fullPath);
+ process.StartInfo.UseShellExecute = false;
+ if (config.RedirectStandardOutput) {
+ process.StartInfo.RedirectStandardOutput = true;
+ }
+ if (config.RedirectStandardError) {
+ process.StartInfo.RedirectStandardError = true;
+ }
+ if (verb != null) {
+ process.StartInfo.Verb = verb;
+ }
+ LOG.InfoFormat("Starting : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
+ process.Start();
+ process.WaitForExit();
+ if (config.RedirectStandardOutput) {
+ output = process.StandardOutput.ReadToEnd();
+ if (config.ShowStandardOutputInLog && output.Trim().Length > 0) {
+ LOG.InfoFormat("Output:\n{0}", output);
+ }
+ }
+ if (config.RedirectStandardError) {
+ error = process.StandardError.ReadToEnd();
+ if (error.Trim().Length > 0) {
+ LOG.WarnFormat("Error:\n{0}", error);
+ }
+ }
+ LOG.InfoFormat("Finished : {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
+ return process.ExitCode;
+ }
+ }
+ return -1;
+ }
+
+ public static string FormatArguments(string arguments, string fullpath)
+ {
+ return string.Format(arguments, fullpath);
+ }
+ }
+}
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandForm.cs b/GreenshotExternalCommandPlugin/ExternalCommandForm.cs
new file mode 100644
index 000000000..b7971baaa
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/ExternalCommandForm.cs
@@ -0,0 +1,29 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using GreenshotPlugin.Controls;
+
+namespace ExternalCommand {
+ ///
+ /// This class is needed for design-time resolving of the language files
+ ///
+ public class ExternalCommandForm : GreenshotForm {
+ }
+}
\ No newline at end of file
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs
new file mode 100644
index 000000000..670b17106
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs
@@ -0,0 +1,172 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Windows.Forms;
+
+namespace ExternalCommand {
+ ///
+ /// An Plugin to run commands after an image was written
+ ///
+ public class ExternalCommandPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ExternalCommandPlugin));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
+ private IGreenshotHost _host;
+ private PluginAttribute _myAttributes;
+ private ToolStripMenuItem _itemPlugInRoot;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Dispose();
+ _itemPlugInRoot = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ foreach(string command in ExternalCommandConfig.Commands) {
+ yield return new ExternalCommandDestination(command);
+ }
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Check and eventually fix the command settings
+ ///
+ ///
+ /// false if the command is not correctly configured
+ private bool IsCommandValid(string command) {
+ if (!ExternalCommandConfig.RunInbackground.ContainsKey(command)) {
+ Log.WarnFormat("Found missing runInbackground for {0}", command);
+ // Fix it
+ ExternalCommandConfig.RunInbackground.Add(command, true);
+ }
+ if (!ExternalCommandConfig.Argument.ContainsKey(command)) {
+ Log.WarnFormat("Found missing argument for {0}", command);
+ // Fix it
+ ExternalCommandConfig.Argument.Add(command, "{0}");
+ }
+ if (!ExternalCommandConfig.Commandline.ContainsKey(command)) {
+ Log.WarnFormat("Found missing commandline for {0}", command);
+ return false;
+ }
+ string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true);
+ commandline = FilenameHelper.FillCmdVariables(commandline, true);
+
+ if (!File.Exists(commandline)) {
+ Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command);
+ return false;
+ }
+ return true;
+ }
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ Log.DebugFormat("Initialize called of {0}", myAttributes.Name);
+
+ List commandsToDelete = new List();
+ // Check configuration
+ foreach(string command in ExternalCommandConfig.Commands) {
+ if (!IsCommandValid(command)) {
+ commandsToDelete.Add(command);
+ }
+ }
+
+ // cleanup
+ foreach (string command in commandsToDelete) {
+ ExternalCommandConfig.Delete(command);
+ }
+
+ _host = pluginHost;
+ _myAttributes = myAttributes;
+
+
+ _itemPlugInRoot = new ToolStripMenuItem {Tag = _host};
+ OnIconSizeChanged(this, new PropertyChangedEventArgs("IconSize"));
+ OnLanguageChanged(this, null);
+ _itemPlugInRoot.Click += ConfigMenuClick;
+
+ PluginUtils.AddToContextMenu(_host, _itemPlugInRoot);
+ Language.LanguageChanged += OnLanguageChanged;
+ CoreConfig.PropertyChanged += OnIconSizeChanged;
+ return true;
+ }
+
+ ///
+ /// Fix icon reference
+ ///
+ ///
+ ///
+ private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) {
+ if (e.PropertyName == "IconSize") {
+ try {
+ string exePath = PluginUtils.GetExePath("cmd.exe");
+ if (exePath != null && File.Exists(exePath)) {
+ _itemPlugInRoot.Image = PluginUtils.GetCachedExeIcon(exePath, 0);
+ }
+ } catch (Exception ex) {
+ Log.Warn("Couldn't get the cmd.exe image", ex);
+ }
+ }
+ }
+
+ private void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Text = Language.GetString("externalcommand", "contextmenu_configure");
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Shutdown of " + _myAttributes.Name);
+ }
+
+ private void ConfigMenuClick(object sender, EventArgs eventArgs) {
+ Configure();
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ Log.Debug("Configure called");
+ new SettingsForm().ShowDialog();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj
new file mode 100644
index 000000000..8be1f0a81
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj
@@ -0,0 +1,100 @@
+
+
+
+
+ {47F23C86-604E-4CC3-8767-B3D4088F30BB}
+ Library
+ GreenshotExternalCommandPlugin
+ GreenshotExternalCommandPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ OnBuildSuccess
+
+
+
+
+
+ 3.5
+
+
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+
+
+
+
+ Form
+
+
+
+
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+ Form
+
+
+ SettingsFormDetail.cs
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+
+
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+ False
+ Off
+ 4194304
+ x86
+ 4096
+
+
+ False
+ Off
+ 4194304
+ AnyCPU
+ 4096
+
+
+ DEBUG;TRACE
+ False
+ True
+ Full
+ true
+
+
+ TRACE
+ True
+ False
+ None
+ false
+
+
\ No newline at end of file
diff --git a/GreenshotExternalCommandPlugin/IconCache.cs b/GreenshotExternalCommandPlugin/IconCache.cs
new file mode 100644
index 000000000..fdff5815e
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/IconCache.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using System.IO;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace ExternalCommand {
+ public static class IconCache {
+ private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IconCache));
+
+ public static Image IconForCommand(string commandName) {
+ Image icon = null;
+ if (commandName != null) {
+ if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName])) {
+ try {
+ icon = PluginUtils.GetCachedExeIcon(config.Commandline[commandName], 0);
+ } catch (Exception ex) {
+ LOG.Warn("Problem loading icon for " + config.Commandline[commandName], ex);
+ }
+ }
+ }
+ return icon;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-cs-CZ.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-cs-CZ.xml
similarity index 96%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-cs-CZ.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-cs-CZ.xml
index 7cade6479..e48f874d1 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-cs-CZ.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-cs-CZ.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Nakonfigurovat externí příkazy
-
-
- Externí příkaz Nastavení
-
-
- Konfigurace příkazu
-
-
- Nový
-
-
- Odstranit
-
-
- Úpravy
-
-
- Jméno
-
-
- Příkaz
-
-
- Argumenty
-
-
- {0} je název vašeho snímku
-
-
+
+
+
+
+ Nakonfigurovat externí příkazy
+
+
+ Externí příkaz Nastavení
+
+
+ Konfigurace příkazu
+
+
+ Nový
+
+
+ Odstranit
+
+
+ Úpravy
+
+
+ Jméno
+
+
+ Příkaz
+
+
+ Argumenty
+
+
+ {0} je název vašeho snímku
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-de-DE.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-de-DE.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-de-DE.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-de-DE.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-en-US.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-en-US.xml
similarity index 96%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-en-US.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-en-US.xml
index d1315b64c..d1d116122 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-en-US.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-en-US.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Configure external commands
-
-
- External command settings
-
-
- Configure command
-
-
- New
-
-
- Delete
-
-
- Edit
-
-
- Name
-
-
- Command
-
-
- Arguments
-
-
- {0} is the filename of your screenshot
-
-
+
+
+
+
+ Configure external commands
+
+
+ External command settings
+
+
+ Configure command
+
+
+ New
+
+
+ Delete
+
+
+ Edit
+
+
+ Name
+
+
+ Command
+
+
+ Arguments
+
+
+ {0} is the filename of your screenshot
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-fr-FR.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-fr-FR.xml
similarity index 96%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-fr-FR.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-fr-FR.xml
index 6433a93bd..ddbb7ea18 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-fr-FR.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-fr-FR.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Configuration de commandes externes
-
-
- Paramètrage de la commande externe
-
-
- Configuration de la commande
-
-
- Nouvelle
-
-
- Supprimer
-
-
- Editer
-
-
- Nom
-
-
- Commande
-
-
- Arguments
-
-
- {0} est le nom du fichier de votre capture d'écran
-
-
+
+
+
+
+ Configuration de commandes externes
+
+
+ Paramètrage de la commande externe
+
+
+ Configuration de la commande
+
+
+ Nouvelle
+
+
+ Supprimer
+
+
+ Editer
+
+
+ Nom
+
+
+ Commande
+
+
+ Arguments
+
+
+ {0} est le nom du fichier de votre capture d'écran
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-id-ID.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-id-ID.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-id-ID.xml
index 41ea2322a..cfd34aed5 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-id-ID.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-id-ID.xml
@@ -1,15 +1,15 @@
-
-
-
- Konfigurasi perintah eksternal
- Argumen
- Perintah
- {0} adalah nama berkas dari tangkapan anda
- Nama
- Hapus
- Konfigursi perintah
- Edit
- Baru
- Setelan perintah eksternal
-
+
+
+
+ Konfigurasi perintah eksternal
+ Argumen
+ Perintah
+ {0} adalah nama berkas dari tangkapan anda
+ Nama
+ Hapus
+ Konfigursi perintah
+ Edit
+ Baru
+ Setelan perintah eksternal
+
\ No newline at end of file
diff --git a/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-it-IT.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-it-IT.xml
new file mode 100644
index 000000000..3c0b77f87
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-it-IT.xml
@@ -0,0 +1,15 @@
+
+
+
+ Configurazione comandi esterni
+ Parametri
+ Comando
+ {0} è il nome file della vostra immagine
+ Nome
+ Elimina
+ Configurazione comando
+ Modifica
+ Nuovo
+ Impostazioni comandi esterni
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-kab-DZ.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-kab-DZ.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-ko-KR.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-ko-KR.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-lv-LV.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-lv-LV.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-pl-PL.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-pl-PL.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-pl-PL.xml
index 5a9a9ff40..40195d762 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-pl-PL.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-pl-PL.xml
@@ -1,15 +1,15 @@
-
-
-
- Konfiguruj zewnętrzne komendy
- Parametry
- Komenda
- {0} oznacza nazwę pliku zrzutu ekranu
- Nazwa
- Usuń
- Ustawienia komendy
- Edytuj
- Nowy
- Ustawienia zewnętrznych komend
-
+
+
+
+ Konfiguruj zewnętrzne komendy
+ Parametry
+ Komenda
+ {0} oznacza nazwę pliku zrzutu ekranu
+ Nazwa
+ Usuń
+ Ustawienia komendy
+ Edytuj
+ Nowy
+ Ustawienia zewnętrznych komend
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-pt-PT.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-pt-PT.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-ru-RU.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-ru-RU.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-ru-RU.xml
index 8655e0d86..8f3c52b10 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-ru-RU.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-ru-RU.xml
@@ -1,15 +1,15 @@
-
-
-
- Настройка внешних команд
- Аргументы
- Команда
- {0} это имя файла вашего скриншота
- Имя
- Удалить
- Настройка команды
- Изменить
- Новая
- Параметры внешней команды
-
+
+
+
+ Настройка внешних команд
+ Аргументы
+ Команда
+ {0} это имя файла вашего скриншота
+ Имя
+ Удалить
+ Настройка команды
+ Изменить
+ Новая
+ Параметры внешней команды
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sk-SK.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sk-SK.xml
similarity index 96%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sk-SK.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sk-SK.xml
index 5fb3f32fd..494232db3 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sk-SK.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sk-SK.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Konfigurácia externých príkazov
-
-
- Nastavenia externých príkazov
-
-
- Konfigurácia príkazu
-
-
- Nový
-
-
- Zmazať
-
-
- Upraviť
-
-
- Názov
-
-
- Príkaz
-
-
- Parametre
-
-
- {0} = názov súboru kde je uložená snímka
-
-
+
+
+
+
+ Konfigurácia externých príkazov
+
+
+ Nastavenia externých príkazov
+
+
+ Konfigurácia príkazu
+
+
+ Nový
+
+
+ Zmazať
+
+
+ Upraviť
+
+
+ Názov
+
+
+ Príkaz
+
+
+ Parametre
+
+
+ {0} = názov súboru kde je uložená snímka
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sr-RS.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sr-RS.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sr-RS.xml
index 8d97d36c5..6775da405 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sr-RS.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sr-RS.xml
@@ -1,15 +1,15 @@
-
-
-
- Подеси спољне наредбе
- Аргумент:
- Наредба:
- {0} је назив снимка екрана.
- Назив:
- Обриши
- Подешавање наредби
- Уреди
- Ново
- Поставке спољних наредби
-
+
+
+
+ Подеси спољне наредбе
+ Аргумент:
+ Наредба:
+ {0} је назив снимка екрана.
+ Назив:
+ Обриши
+ Подешавање наредби
+ Уреди
+ Ново
+ Поставке спољних наредби
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sv-SE.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-sv-SE.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-uk-UA.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-uk-UA.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-uk-UA.xml
index 45b65f885..9a7adf789 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-uk-UA.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-uk-UA.xml
@@ -1,15 +1,15 @@
-
-
-
- Налаштувати зовнішні команди
- Параметри зовнішньої команди
- Налаштувати команду
- Нова
- Видалити
- Змінити
- Назва
- Команда
- Аргументи
- {0} — назва файла Вашого знімку
-
-
+
+
+
+ Налаштувати зовнішні команди
+ Параметри зовнішньої команди
+ Налаштувати команду
+ Нова
+ Видалити
+ Змінити
+ Назва
+ Команда
+ Аргументи
+ {0} — назва файла Вашого знімку
+
+
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-CN.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-CN.xml
similarity index 87%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-CN.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-CN.xml
index eef53e22a..a5e48c945 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-CN.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-CN.xml
@@ -1,15 +1,15 @@
-
-
-
- 配置外部命令
- 参数
- 命令
- {0}为您的截图文件的名称
- 名称
- 删除
- 配置命令
- 编辑
- 新建
- 外部命令设置
-
+
+
+
+ 配置外部命令
+ 参数
+ 命令
+ {0}为您的截图文件的名称
+ 名称
+ 删除
+ 配置命令
+ 编辑
+ 新建
+ 外部命令设置
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-TW.xml b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-TW.xml
rename to GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-TW.xml
index 81ef0455e..380acc223 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Languages/language_externalcommand-zh-TW.xml
+++ b/GreenshotExternalCommandPlugin/Languages/language_externalcommandplugin-zh-TW.xml
@@ -1,15 +1,15 @@
-
-
-
- 組態外部命令
- 引數
- 命令
- {0} 是螢幕擷圖的檔案名稱
- 名稱
- 刪除
- 組態命令
- 編輯
- 新增
- 外部命令設定
-
+
+
+
+ 組態外部命令
+ 引數
+ 命令
+ {0} 是螢幕擷圖的檔案名稱
+ 名稱
+ 刪除
+ 組態命令
+ 編輯
+ 新增
+ 外部命令設定
+
\ No newline at end of file
diff --git a/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs b/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..61259677a
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GreenshotExternalCommandPlugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("External command Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("ExternalCommand.ExternalCommandPlugin", true)]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs b/GreenshotExternalCommandPlugin/SettingsForm.Designer.cs
similarity index 82%
rename from src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs
rename to GreenshotExternalCommandPlugin/SettingsForm.Designer.cs
index 5b266d576..7119086ff 100644
--- a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs
+++ b/GreenshotExternalCommandPlugin/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.ExternalCommand {
+namespace ExternalCommand {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -48,13 +45,13 @@ namespace Greenshot.Plugin.ExternalCommand {
/// not be able to load this method if it was changed manually.
///
private void InitializeComponent() {
- this.buttonCancel = new GreenshotButton();
- this.buttonOk = new GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonOk = new GreenshotPlugin.Controls.GreenshotButton();
this.listView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.button_new = new GreenshotButton();
- this.button_delete = new GreenshotButton();
- this.button_edit = new GreenshotButton();
+ this.button_new = new GreenshotPlugin.Controls.GreenshotButton();
+ this.button_delete = new GreenshotPlugin.Controls.GreenshotButton();
+ this.button_edit = new GreenshotPlugin.Controls.GreenshotButton();
this.SuspendLayout();
//
// buttonCancel
@@ -133,8 +130,8 @@ namespace Greenshot.Plugin.ExternalCommand {
// SettingsForm
//
this.AcceptButton = this.buttonOk;
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(365, 208);
this.Controls.Add(this.button_edit);
@@ -149,13 +146,13 @@ namespace Greenshot.Plugin.ExternalCommand {
this.ResumeLayout(false);
}
- private GreenshotButton button_edit;
- private GreenshotButton button_delete;
- private GreenshotButton button_new;
+ private GreenshotPlugin.Controls.GreenshotButton button_edit;
+ private GreenshotPlugin.Controls.GreenshotButton button_delete;
+ private GreenshotPlugin.Controls.GreenshotButton button_new;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ListView listView1;
- private GreenshotButton buttonOk;
- private GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOk;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
}
}
diff --git a/GreenshotExternalCommandPlugin/SettingsForm.cs b/GreenshotExternalCommandPlugin/SettingsForm.cs
new file mode 100644
index 000000000..e5721749b
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/SettingsForm.cs
@@ -0,0 +1,126 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace ExternalCommand {
+ ///
+ /// Description of SettingsForm.
+ ///
+ public partial class SettingsForm : ExternalCommandForm {
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
+
+ public SettingsForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = buttonOk;
+ CancelButton = buttonCancel;
+ UpdateView();
+ }
+
+ private void ButtonOkClick(object sender, EventArgs e) {
+ IniConfig.Save();
+ }
+
+ private void ButtonAddClick(object sender, EventArgs e) {
+ var form = new SettingsFormDetail(null);
+ form.ShowDialog();
+
+ UpdateView();
+ }
+
+ private void ButtonDeleteClick(object sender, EventArgs e) {
+ foreach(ListViewItem item in listView1.SelectedItems) {
+ string commando = item.Tag as string;
+
+ ExternalCommandConfig.Delete(commando);
+ }
+ UpdateView();
+ }
+
+ private void UpdateView() {
+ listView1.Items.Clear();
+ if(ExternalCommandConfig.Commands != null) {
+ listView1.ListViewItemSorter = new ListviewComparer();
+ ImageList imageList = new ImageList();
+ listView1.SmallImageList = imageList;
+ int imageNr = 0;
+ foreach(string commando in ExternalCommandConfig.Commands) {
+ ListViewItem item;
+ Image iconForExe = IconCache.IconForCommand(commando);
+ if(iconForExe != null) {
+ imageList.Images.Add(iconForExe);
+ item = new ListViewItem(commando, imageNr++);
+ } else {
+ item = new ListViewItem(commando);
+ }
+ item.Tag = commando;
+ listView1.Items.Add(item);
+ }
+ }
+ // Fix for bug #1484, getting an ArgumentOutOfRangeException as there is nothing selected but the edit button was still active.
+ button_edit.Enabled = listView1.SelectedItems.Count > 0;
+ }
+
+ private void ListView1ItemSelectionChanged(object sender, EventArgs e) {
+ button_edit.Enabled = listView1.SelectedItems.Count > 0;
+ }
+
+ private void ButtonEditClick(object sender, EventArgs e) {
+ ListView1DoubleClick(sender, e);
+ }
+
+ private void ListView1DoubleClick(object sender, EventArgs e) {
+ // Safety check for bug #1484
+ bool selectionActive = listView1.SelectedItems.Count > 0;
+ if(!selectionActive) {
+ button_edit.Enabled = false;
+ return;
+ }
+ string commando = listView1.SelectedItems[0].Tag as string;
+
+ var form = new SettingsFormDetail(commando);
+ form.ShowDialog();
+
+ UpdateView();
+ }
+ }
+
+ public class ListviewComparer : System.Collections.IComparer {
+ public int Compare(object x, object y) {
+ if(!(x is ListViewItem)) {
+ return (0);
+ }
+ if(!(y is ListViewItem)) {
+ return (0);
+ }
+
+ var l1 = (ListViewItem)x;
+ var l2 = (ListViewItem)y;
+ return string.Compare(l1.Text, l2.Text, StringComparison.Ordinal);
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs b/GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs
similarity index 82%
rename from src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs
rename to GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs
index 5cbe41b49..2a34a4cf0 100644
--- a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs
+++ b/GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.ExternalCommand {
+namespace ExternalCommand {
partial class SettingsFormDetail {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,16 +46,16 @@ namespace Greenshot.Plugin.ExternalCommand {
///
private void InitializeComponent()
{
- this.buttonOk = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.groupBox1 = new GreenshotGroupBox();
- this.label4 = new GreenshotLabel();
+ this.buttonOk = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.groupBox1 = new GreenshotPlugin.Controls.GreenshotGroupBox();
+ this.label4 = new GreenshotPlugin.Controls.GreenshotLabel();
this.buttonPathSelect = new System.Windows.Forms.Button();
- this.label3 = new GreenshotLabel();
+ this.label3 = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBox_name = new System.Windows.Forms.TextBox();
- this.label2 = new GreenshotLabel();
+ this.label2 = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBox_arguments = new System.Windows.Forms.TextBox();
- this.label1 = new GreenshotLabel();
+ this.label1 = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBox_commandline = new System.Windows.Forms.TextBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
@@ -171,8 +168,8 @@ namespace Greenshot.Plugin.ExternalCommand {
// SettingsFormDetail
//
this.AcceptButton = this.buttonOk;
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(360, 172);
@@ -187,13 +184,13 @@ namespace Greenshot.Plugin.ExternalCommand {
this.ResumeLayout(false);
}
- private GreenshotLabel label1;
- private GreenshotLabel label2;
- private GreenshotLabel label3;
- private GreenshotLabel label4;
- private GreenshotGroupBox groupBox1;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOk;
+ private GreenshotPlugin.Controls.GreenshotLabel label1;
+ private GreenshotPlugin.Controls.GreenshotLabel label2;
+ private GreenshotPlugin.Controls.GreenshotLabel label3;
+ private GreenshotPlugin.Controls.GreenshotLabel label4;
+ private GreenshotPlugin.Controls.GreenshotGroupBox groupBox1;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOk;
private System.Windows.Forms.TextBox textBox_commandline;
private System.Windows.Forms.TextBox textBox_arguments;
private System.Windows.Forms.TextBox textBox_name;
diff --git a/GreenshotExternalCommandPlugin/SettingsFormDetail.cs b/GreenshotExternalCommandPlugin/SettingsFormDetail.cs
new file mode 100644
index 000000000..00a306a6d
--- /dev/null
+++ b/GreenshotExternalCommandPlugin/SettingsFormDetail.cs
@@ -0,0 +1,166 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+
+namespace ExternalCommand {
+ ///
+ /// Description of SettingsFormDetail.
+ ///
+ public partial class SettingsFormDetail : ExternalCommandForm {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SettingsFormDetail));
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
+
+ private readonly string _commando;
+ private readonly int _commandIndex;
+
+ public SettingsFormDetail(string commando) {
+ InitializeComponent();
+ AcceptButton = buttonOk;
+ CancelButton = buttonCancel;
+ _commando = commando;
+
+ if(commando != null) {
+ textBox_name.Text = commando;
+ textBox_commandline.Text = ExternalCommandConfig.Commandline[commando];
+ textBox_arguments.Text = ExternalCommandConfig.Argument[commando];
+ _commandIndex = ExternalCommandConfig.Commands.FindIndex(s => s == commando);
+ } else {
+ textBox_arguments.Text = "\"{0}\"";
+ }
+ OkButtonState();
+ }
+
+ private void ButtonOkClick(object sender, EventArgs e) {
+ string commandName = textBox_name.Text;
+ string commandLine = textBox_commandline.Text;
+ string arguments = textBox_arguments.Text;
+ if(_commando != null) {
+ ExternalCommandConfig.Commands[_commandIndex] = commandName;
+ ExternalCommandConfig.Commandline.Remove(_commando);
+ ExternalCommandConfig.Commandline.Add(commandName, commandLine);
+ ExternalCommandConfig.Argument.Remove(_commando);
+ ExternalCommandConfig.Argument.Add(commandName, arguments);
+ } else {
+ ExternalCommandConfig.Commands.Add(commandName);
+ ExternalCommandConfig.Commandline.Add(commandName, commandLine);
+ ExternalCommandConfig.Argument.Add(commandName, arguments);
+ }
+ }
+
+ private void Button3Click(object sender, EventArgs e) {
+ var openFileDialog = new OpenFileDialog
+ {
+ Filter = "Executables (*.exe, *.bat, *.com)|*.exe; *.bat; *.com|All files (*)|*",
+ FilterIndex = 1,
+ CheckFileExists = true,
+ Multiselect = false
+ };
+ string initialPath = null;
+ try
+ {
+ initialPath = Path.GetDirectoryName(textBox_commandline.Text);
+ }
+ catch (Exception ex)
+ {
+ Log.WarnFormat("Can't get the initial path via {0}", textBox_commandline.Text);
+ Log.Warn("Exception: ", ex);
+ }
+ if(initialPath != null && Directory.Exists(initialPath)) {
+ openFileDialog.InitialDirectory = initialPath;
+ } else {
+ initialPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
+ openFileDialog.InitialDirectory = initialPath;
+ }
+ Log.DebugFormat("Starting OpenFileDialog at {0}", initialPath);
+ if(openFileDialog.ShowDialog() == DialogResult.OK) {
+ textBox_commandline.Text = openFileDialog.FileName;
+ }
+ }
+
+ private void OkButtonState() {
+ // Assume OK
+ buttonOk.Enabled = true;
+ textBox_name.BackColor = Color.White;
+ textBox_commandline.BackColor = Color.White;
+ textBox_arguments.BackColor = Color.White;
+ // Is there a text in the name field
+ if(string.IsNullOrEmpty(textBox_name.Text)) {
+ buttonOk.Enabled = false;
+ }
+ // Check if commandname is unique
+ if(_commando == null && !string.IsNullOrEmpty(textBox_name.Text) && ExternalCommandConfig.Commands.Contains(textBox_name.Text)) {
+ buttonOk.Enabled = false;
+ textBox_name.BackColor = Color.Red;
+ }
+ // Is there a text in the commandline field
+ if(string.IsNullOrEmpty(textBox_commandline.Text)) {
+ buttonOk.Enabled = false;
+ }
+
+ if (!string.IsNullOrEmpty(textBox_commandline.Text))
+ {
+ // Added this to be more flexible, using the Greenshot var format
+ string cmdPath = FilenameHelper.FillVariables(textBox_commandline.Text, true);
+ // And also replace the "DOS" Variables
+ cmdPath = FilenameHelper.FillCmdVariables(cmdPath, true);
+ // Is the command available?
+ if (!File.Exists(cmdPath))
+ {
+ buttonOk.Enabled = false;
+ textBox_commandline.BackColor = Color.Red;
+ }
+ }
+ // Are the arguments in a valid format?
+ try
+ {
+ string arguments = FilenameHelper.FillVariables(textBox_arguments.Text, false);
+ arguments = FilenameHelper.FillCmdVariables(arguments, false);
+
+ ExternalCommandDestination.FormatArguments(arguments, string.Empty);
+ }
+ catch
+ {
+ buttonOk.Enabled = false;
+ textBox_arguments.BackColor = Color.Red;
+ }
+ }
+
+ private void textBox_name_TextChanged(object sender, EventArgs e) {
+ OkButtonState();
+ }
+
+ private void textBox_commandline_TextChanged(object sender, EventArgs e) {
+ OkButtonState();
+ }
+
+ private void textBox_arguments_TextChanged(object sender, EventArgs e)
+ {
+ OkButtonState();
+ }
+
+ }
+}
diff --git a/GreenshotFlickrPlugin/FlickrConfiguration.cs b/GreenshotFlickrPlugin/FlickrConfiguration.cs
new file mode 100644
index 000000000..0d6ad0574
--- /dev/null
+++ b/GreenshotFlickrPlugin/FlickrConfiguration.cs
@@ -0,0 +1,80 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotFlickrPlugin {
+ public enum SafetyLevel {
+ Safe = 1,
+ Moderate = 2,
+ Restricted = 3
+ }
+ ///
+ /// Description of FlickrConfiguration.
+ ///
+ [IniSection("Flickr", Description = "Greenshot Flickr Plugin configuration")]
+ public class FlickrConfiguration : IniSection {
+ [IniProperty("flickrIsPublic", Description = "IsPublic.", DefaultValue = "true")]
+ public bool IsPublic { get; set; }
+
+ [IniProperty("flickrIsFamily", Description = "IsFamily.", DefaultValue = "true")]
+ public bool IsFamily { get; set; }
+
+ [IniProperty("flickrIsFriend", Description = "IsFriend.", DefaultValue = "true")]
+ public bool IsFriend { get; set; }
+
+ [IniProperty("SafetyLevel", Description = "Safety level", DefaultValue = "Safe")]
+ public SafetyLevel SafetyLevel { get; set; }
+
+ [IniProperty("HiddenFromSearch", Description = "Hidden from search", DefaultValue = "false")]
+ public bool HiddenFromSearch { get; set; }
+
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send flickr link to clipboard.", DefaultValue = "true")]
+ public bool AfterUploadLinkToClipBoard { get; set; }
+
+ [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
+ public bool UsePageLink { get; set; }
+
+ [IniProperty("FlickrToken", Description = "The Flickr token", Encrypted = true, ExcludeIfNull = true)]
+ public string FlickrToken { get; set; }
+ [IniProperty("FlickrTokenSecret", Description = "The Flickr token secret", Encrypted = true, ExcludeIfNull = true)]
+ public string FlickrTokenSecret { get; set; }
+
+ ///
+ /// A form for token
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ DialogResult result = new SettingsForm().ShowDialog();
+ if (result == DialogResult.OK) {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.Credentials.template b/GreenshotFlickrPlugin/FlickrCredentials.cs
similarity index 78%
rename from src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.Credentials.template
rename to GreenshotFlickrPlugin/FlickrCredentials.cs
index 0d7c50529..2eb6aea2a 100644
--- a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.Credentials.template
+++ b/GreenshotFlickrPlugin/FlickrCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.Flickr {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
- /// You can set your own values here
- ///
- public static class FlickrCredentials {
- public static string ConsumerKey = "${Flickr_ClientId}";
- public static string ConsumerSecret = "${Flickr_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotFlickrPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
+ /// You can set your own values here
+ ///
+ public static class FlickrCredentials {
+ public static string ConsumerKey = "@credentials_flickr_consumer_key@";
+ public static string ConsumerSecret = "@credentials_flickr_consumer_secret@";
+ }
+}
diff --git a/GreenshotFlickrPlugin/FlickrDestination.cs b/GreenshotFlickrPlugin/FlickrDestination.cs
new file mode 100644
index 000000000..70778e1f7
--- /dev/null
+++ b/GreenshotFlickrPlugin/FlickrDestination.cs
@@ -0,0 +1,56 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotFlickrPlugin {
+ public class FlickrDestination : AbstractDestination {
+ private readonly FlickrPlugin _plugin;
+ public FlickrDestination(FlickrPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override string Designation => "Flickr";
+
+ public override string Description => Language.GetString("flickr", LangKey.upload_menu_item);
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(FlickrPlugin));
+ return (Image)resources.GetObject("flickr");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, out uploadUrl);
+ if (uploaded) {
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = uploadUrl;
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotFlickrPlugin/FlickrPlugin.cs b/GreenshotFlickrPlugin/FlickrPlugin.cs
new file mode 100644
index 000000000..5533ba643
--- /dev/null
+++ b/GreenshotFlickrPlugin/FlickrPlugin.cs
@@ -0,0 +1,148 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace GreenshotFlickrPlugin
+{
+ ///
+ /// This is the Flickr base code
+ ///
+ public class FlickrPlugin : IGreenshotPlugin {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(FlickrPlugin));
+ private static FlickrConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (!disposing) {
+ return;
+ }
+ if (_itemPlugInConfig == null) {
+ return;
+ }
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+
+ public IEnumerable Destinations() {
+ yield return new FlickrDestination(this);
+ }
+
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute pluginAttribute) {
+ _host = pluginHost;
+ Attributes = pluginAttribute;
+
+
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(FlickrPlugin));
+
+ _itemPlugInConfig = new ToolStripMenuItem
+ {
+ Text = Language.GetString("flickr", LangKey.Configure),
+ Tag = _host,
+ Image = (Image) _resources.GetObject("flickr")
+ };
+ _itemPlugInConfig.Click += ConfigMenuClick;
+
+ PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("flickr", LangKey.Configure);
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Flickr Plugin shutdown.");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ public void ConfigMenuClick(object sender, EventArgs eventArgs) {
+ _config.ShowConfigDialog();
+ }
+
+ public bool Upload(ICaptureDetails captureDetails, ISurface surface, out string uploadUrl) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
+ uploadUrl = null;
+ try {
+ string flickrUrl = null;
+ new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("flickr", LangKey.communication_wait),
+ delegate {
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
+ flickrUrl = FlickrUtils.UploadToFlickr(surface, outputSettings, captureDetails.Title, filename);
+ }
+ );
+
+ if (flickrUrl == null) {
+ return false;
+ }
+ uploadUrl = flickrUrl;
+
+ if (_config.AfterUploadLinkToClipBoard) {
+ ClipboardHelper.SetClipboardData(flickrUrl);
+ }
+ return true;
+ } catch (Exception e) {
+ Log.Error("Error uploading.", e);
+ MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message);
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Flickr/FlickrPlugin.resx b/GreenshotFlickrPlugin/FlickrPlugin.resx
similarity index 95%
rename from src/Greenshot.Plugin.Flickr/FlickrPlugin.resx
rename to GreenshotFlickrPlugin/FlickrPlugin.resx
index 154c66500..d4a65b3e2 100644
--- a/src/Greenshot.Plugin.Flickr/FlickrPlugin.resx
+++ b/GreenshotFlickrPlugin/FlickrPlugin.resx
@@ -112,13 +112,13 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
- flickr.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+ flickr.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
\ No newline at end of file
diff --git a/GreenshotFlickrPlugin/FlickrUtils.cs b/GreenshotFlickrPlugin/FlickrUtils.cs
new file mode 100644
index 000000000..39c423cdf
--- /dev/null
+++ b/GreenshotFlickrPlugin/FlickrUtils.cs
@@ -0,0 +1,163 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Xml;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace GreenshotFlickrPlugin {
+ ///
+ /// Description of FlickrUtils.
+ ///
+ public class FlickrUtils {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrUtils));
+ private static readonly FlickrConfiguration config = IniConfig.GetIniSection();
+ private const string FLICKR_API_BASE_URL = "https://api.flickr.com/services/";
+ private const string FLICKR_UPLOAD_URL = FLICKR_API_BASE_URL + "upload/";
+ // OAUTH
+ private const string FLICKR_OAUTH_BASE_URL = FLICKR_API_BASE_URL + "oauth/";
+ private const string FLICKR_ACCESS_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "access_token";
+ private const string FLICKR_AUTHORIZE_URL = FLICKR_OAUTH_BASE_URL + "authorize";
+ private const string FLICKR_REQUEST_TOKEN_URL = FLICKR_OAUTH_BASE_URL + "request_token";
+ private const string FLICKR_FARM_URL = "https://farm{0}.staticflickr.com/{1}/{2}_{3}_o.{4}";
+ // REST
+ private const string FLICKR_REST_URL = FLICKR_API_BASE_URL + "rest/";
+ private const string FLICKR_GET_INFO_URL = FLICKR_REST_URL + "?method=flickr.photos.getInfo";
+
+ ///
+ /// Do the actual upload to Flickr
+ /// For more details on the available parameters, see: http://flickrnet.codeplex.com
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// url to image
+ public static string UploadToFlickr(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
+ var oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret)
+ {
+ BrowserSize = new Size(520, 800),
+ CheckVerifier = false,
+ AccessTokenUrl = FLICKR_ACCESS_TOKEN_URL,
+ AuthorizeUrl = FLICKR_AUTHORIZE_URL,
+ RequestTokenUrl = FLICKR_REQUEST_TOKEN_URL,
+ LoginTitle = "Flickr authorization",
+ Token = config.FlickrToken,
+ TokenSecret = config.FlickrTokenSecret
+ };
+ if (string.IsNullOrEmpty(oAuth.Token)) {
+ if (!oAuth.Authorize()) {
+ return null;
+ }
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ config.FlickrToken = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ config.FlickrTokenSecret = oAuth.TokenSecret;
+ }
+ IniConfig.Save();
+ }
+ try {
+ IDictionary signedParameters = new Dictionary();
+ signedParameters.Add("content_type", "2"); // Screenshot
+ signedParameters.Add("tags", "Greenshot");
+ signedParameters.Add("is_public", config.IsPublic ? "1" : "0");
+ signedParameters.Add("is_friend", config.IsFriend ? "1" : "0");
+ signedParameters.Add("is_family", config.IsFamily ? "1" : "0");
+ signedParameters.Add("safety_level", $"{(int) config.SafetyLevel}");
+ signedParameters.Add("hidden", config.HiddenFromSearch ? "1" : "2");
+ IDictionary otherParameters = new Dictionary();
+ otherParameters.Add("photo", new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ string response = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_UPLOAD_URL, signedParameters, otherParameters, null);
+ string photoId = GetPhotoId(response);
+
+ // Get Photo Info
+ signedParameters = new Dictionary { { "photo_id", photoId } };
+ string photoInfo = oAuth.MakeOAuthRequest(HTTPMethod.POST, FLICKR_GET_INFO_URL, signedParameters, null, null);
+ return GetUrl(photoInfo);
+ } catch (Exception ex) {
+ LOG.Error("Upload error: ", ex);
+ throw;
+ } finally {
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ config.FlickrToken = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ config.FlickrTokenSecret = oAuth.TokenSecret;
+ }
+ }
+ }
+
+ private static string GetUrl(string response) {
+ try {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(response);
+ if (config.UsePageLink) {
+ XmlNodeList nodes = doc.GetElementsByTagName("url");
+ if (nodes.Count > 0) {
+ var xmlNode = nodes.Item(0);
+ if (xmlNode != null) {
+ return xmlNode.InnerText;
+ }
+ }
+ } else {
+ XmlNodeList nodes = doc.GetElementsByTagName("photo");
+ if (nodes.Count > 0) {
+ var item = nodes.Item(0);
+ if (item?.Attributes != null) {
+ string farmId = item.Attributes["farm"].Value;
+ string serverId = item.Attributes["server"].Value;
+ string photoId = item.Attributes["id"].Value;
+ string originalsecret = item.Attributes["originalsecret"].Value;
+ string originalFormat = item.Attributes["originalformat"].Value;
+ return string.Format(FLICKR_FARM_URL, farmId, serverId, photoId, originalsecret, originalFormat);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ LOG.Error("Error parsing Flickr Response.", ex);
+ }
+ return null;
+ }
+
+ private static string GetPhotoId(string response) {
+ try {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(response);
+ XmlNodeList nodes = doc.GetElementsByTagName("photoid");
+ if (nodes.Count > 0) {
+ var xmlNode = nodes.Item(0);
+ if (xmlNode != null) {
+ return xmlNode.InnerText;
+ }
+ }
+ } catch (Exception ex) {
+ LOG.Error("Error parsing Flickr Response.", ex);
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs b/GreenshotFlickrPlugin/Forms/FlickrForm.cs
similarity index 68%
rename from src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs
rename to GreenshotFlickrPlugin/Forms/FlickrForm.cs
index 3f1ed03ff..be50a03ca 100644
--- a/src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs
+++ b/GreenshotFlickrPlugin/Forms/FlickrForm.cs
@@ -1,28 +1,27 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Editor.Helpers
-{
- public interface IHaveScaleOptions
- {
- ScaleOptions GetScaleOptions();
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace GreenshotFlickrPlugin.Forms {
+ public class FlickrForm : GreenshotForm {
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs b/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
similarity index 74%
rename from src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs
rename to GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
index 5eed52b57..f87792173 100644
--- a/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs
+++ b/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Flickr.Forms {
+namespace GreenshotFlickrPlugin {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,18 +46,18 @@ namespace Greenshot.Plugin.Flickr.Forms {
///
private void InitializeComponent()
{
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.checkBoxPublic = new GreenshotCheckBox();
- this.checkBoxFamily = new GreenshotCheckBox();
- this.checkBoxFriend = new GreenshotCheckBox();
- this.label_SafetyLevel = new GreenshotLabel();
- this.combobox_safetyLevel = new GreenshotComboBox();
- this.label_AfterUpload = new GreenshotLabel();
- this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox();
- this.checkBox_hiddenfromsearch = new GreenshotCheckBox();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkBoxPublic = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkBoxFamily = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkBoxFriend = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_SafetyLevel = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.combobox_safetyLevel = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkBox_hiddenfromsearch = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.SuspendLayout();
//
// buttonOK
@@ -93,7 +90,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(174, 6);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(FlickrConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Flickr";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(251, 21);
this.combobox_uploadimageformat.TabIndex = 1;
@@ -108,10 +105,11 @@ namespace Greenshot.Plugin.Flickr.Forms {
//
// checkBoxPublic
//
+ this.checkBoxPublic.AutoSize = true;
this.checkBoxPublic.LanguageKey = "flickr.public";
this.checkBoxPublic.Location = new System.Drawing.Point(174, 88);
this.checkBoxPublic.Name = "checkBoxPublic";
- this.checkBoxPublic.PropertyName = nameof(FlickrConfiguration.IsPublic);
+ this.checkBoxPublic.PropertyName = "flickrIsPublic";
this.checkBoxPublic.SectionName = "Flickr";
this.checkBoxPublic.Size = new System.Drawing.Size(55, 17);
this.checkBoxPublic.TabIndex = 4;
@@ -119,10 +117,11 @@ namespace Greenshot.Plugin.Flickr.Forms {
//
// checkBoxFamily
//
+ this.checkBoxFamily.AutoSize = true;
this.checkBoxFamily.LanguageKey = "flickr.family";
this.checkBoxFamily.Location = new System.Drawing.Point(265, 88);
this.checkBoxFamily.Name = "checkBoxFamily";
- this.checkBoxFamily.PropertyName = nameof(FlickrConfiguration.IsFamily);
+ this.checkBoxFamily.PropertyName = "flickrIsFamily";
this.checkBoxFamily.SectionName = "Flickr";
this.checkBoxFamily.Size = new System.Drawing.Size(55, 17);
this.checkBoxFamily.TabIndex = 5;
@@ -130,10 +129,11 @@ namespace Greenshot.Plugin.Flickr.Forms {
//
// checkBoxFriend
//
+ this.checkBoxFriend.AutoSize = true;
this.checkBoxFriend.LanguageKey = "flickr.friend";
this.checkBoxFriend.Location = new System.Drawing.Point(350, 88);
this.checkBoxFriend.Name = "checkBoxFriend";
- this.checkBoxFriend.PropertyName = nameof(FlickrConfiguration.IsFriend);
+ this.checkBoxFriend.PropertyName = "flickrIsFriend";
this.checkBoxFriend.SectionName = "Flickr";
this.checkBoxFriend.Size = new System.Drawing.Size(55, 17);
this.checkBoxFriend.TabIndex = 6;
@@ -155,7 +155,7 @@ namespace Greenshot.Plugin.Flickr.Forms {
this.combobox_safetyLevel.FormattingEnabled = true;
this.combobox_safetyLevel.Location = new System.Drawing.Point(174, 33);
this.combobox_safetyLevel.Name = "combobox_safetyLevel";
- this.combobox_safetyLevel.PropertyName = nameof(FlickrConfiguration.SafetyLevel);
+ this.combobox_safetyLevel.PropertyName = "SafetyLevel";
this.combobox_safetyLevel.SectionName = "Flickr";
this.combobox_safetyLevel.Size = new System.Drawing.Size(251, 21);
this.combobox_safetyLevel.TabIndex = 2;
@@ -170,10 +170,11 @@ namespace Greenshot.Plugin.Flickr.Forms {
//
// checkboxAfterUploadLinkToClipBoard
//
+ this.checkboxAfterUploadLinkToClipBoard.AutoSize = true;
this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "flickr.label_AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(173, 116);
this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
- this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(FlickrConfiguration.AfterUploadLinkToClipBoard);
+ this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
this.checkboxAfterUploadLinkToClipBoard.SectionName = "Flickr";
this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
this.checkboxAfterUploadLinkToClipBoard.TabIndex = 7;
@@ -181,10 +182,11 @@ namespace Greenshot.Plugin.Flickr.Forms {
//
// checkBox_hiddenfromsearch
//
+ this.checkBox_hiddenfromsearch.AutoSize = true;
this.checkBox_hiddenfromsearch.LanguageKey = "flickr.label_HiddenFromSearch";
this.checkBox_hiddenfromsearch.Location = new System.Drawing.Point(174, 60);
this.checkBox_hiddenfromsearch.Name = "checkBox_hiddenfromsearch";
- this.checkBox_hiddenfromsearch.PropertyName = nameof(FlickrConfiguration.HiddenFromSearch);
+ this.checkBox_hiddenfromsearch.PropertyName = "HiddenFromSearch";
this.checkBox_hiddenfromsearch.SectionName = "Flickr";
this.checkBox_hiddenfromsearch.Size = new System.Drawing.Size(118, 17);
this.checkBox_hiddenfromsearch.TabIndex = 3;
@@ -216,17 +218,17 @@ namespace Greenshot.Plugin.Flickr.Forms {
this.PerformLayout();
}
- private GreenshotCheckBox checkBox_hiddenfromsearch;
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotCheckBox checkBoxPublic;
- private GreenshotCheckBox checkBoxFamily;
- private GreenshotCheckBox checkBoxFriend;
- private GreenshotLabel label_SafetyLevel;
- private GreenshotComboBox combobox_safetyLevel;
- private GreenshotLabel label_AfterUpload;
- private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_hiddenfromsearch;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxPublic;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxFamily;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxFriend;
+ private GreenshotPlugin.Controls.GreenshotLabel label_SafetyLevel;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_safetyLevel;
+ private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
}
}
diff --git a/GreenshotFlickrPlugin/Forms/SettingsForm.cs b/GreenshotFlickrPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..5c1e24551
--- /dev/null
+++ b/GreenshotFlickrPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,39 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotFlickrPlugin.Forms;
+
+namespace GreenshotFlickrPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : FlickrForm {
+ public SettingsForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ CancelButton = buttonCancel;
+ AcceptButton = buttonOK;
+ }
+
+ }
+}
diff --git a/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj
new file mode 100644
index 000000000..69d67f146
--- /dev/null
+++ b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+ {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}
+ Library
+ GreenshotFlickrPlugin
+ GreenshotFlickrPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+ 3.5
+
+
+
+
+
+
+
+
+
+ False
+ ..\Greenshot\lib\log4net.dll
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+
+
+
+ Always
+ Designer
+
+
+ FlickrPlugin.cs
+
+
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+ if exist "$(ProjectDir)FlickrCredentials.orig.cs" (
+ rename "$(ProjectDir)FlickrCredentials.cs" "FlickrCredentials.private.cs"
+ rename "$(ProjectDir)FlickrCredentials.orig.cs" "FlickrCredentials.cs"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+if exist "$(ProjectDir)FlickrCredentials.private.cs" (
+ rename "$(ProjectDir)FlickrCredentials.cs" "FlickrCredentials.orig.cs"
+ rename "$(ProjectDir)FlickrCredentials.private.cs" "FlickrCredentials.cs"
+)
+
+
\ No newline at end of file
diff --git a/GreenshotFlickrPlugin/LanguageKeys.cs b/GreenshotFlickrPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..77590dc7c
--- /dev/null
+++ b/GreenshotFlickrPlugin/LanguageKeys.cs
@@ -0,0 +1,35 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotFlickrPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ settings_title,
+ label_upload_format,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ Configure,
+ label_HiddenFromSearch,
+ label_SafetyLevel,
+ label_AfterUpload,
+ label_AfterUploadLinkToClipBoard
+ }
+}
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-cs-CZ.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-cs-CZ.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-cs-CZ.xml
index fefe146ee..edf244e5f 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-cs-CZ.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-cs-CZ.xml
@@ -1,31 +1,31 @@
-
-
-
- Ověřit
- Zrušit
- Komunikace s Flickr. Počkejte prosím...
- Konfigurovat
- Jste si jistý, že chcete odstranit obrázek {0} z Flickr?
- Odstranit Flickr {0}
- Rodina
- Flickr historie
- Přátelé
- Historie
- Po odeslání
- Odkaz do schránky
- Otevřít historii
- Ověření Token
- Výchozí velikost
- Skrýt formulář hledání
- Úroveň bezpečnosti
- Formát obrázku
- OK
- Veřejné
- Nastavení Flickr
- Prosím ověřit aplikaci Flickr. Otevřít nastavení obrazovky. ???
- Odeslat
- Při odesílání do Flicker došlo k chybě:
- Odeslat do Flickr
- Úspěšně odeslaný obrázek do Flickr!
-
+
+
+
+ Ověřit
+ Zrušit
+ Komunikace s Flickr. Počkejte prosím...
+ Konfigurovat
+ Jste si jistý, že chcete odstranit obrázek {0} z Flickr?
+ Odstranit Flickr {0}
+ Rodina
+ Flickr historie
+ Přátelé
+ Historie
+ Po odeslání
+ Odkaz do schránky
+ Otevřít historii
+ Ověření Token
+ Výchozí velikost
+ Skrýt formulář hledání
+ Úroveň bezpečnosti
+ Formát obrázku
+ OK
+ Veřejné
+ Nastavení Flickr
+ Prosím ověřit aplikaci Flickr. Otevřít nastavení obrazovky. ???
+ Odeslat
+ Při odesílání do Flicker došlo k chybě:
+ Odeslat do Flickr
+ Úspěšně odeslaný obrázek do Flickr!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-de-DE.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-de-DE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-de-DE.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-de-DE.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-en-US.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-en-US.xml
similarity index 95%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-en-US.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-en-US.xml
index 1127f625b..ec8408d4e 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-en-US.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-en-US.xml
@@ -26,7 +26,7 @@
Successfully uploaded image to Flickr!
- An error occurred while uploading to Flickr:
+ An error occured while uploading to Flickr:
Image format
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-fr-FR.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-fr-FR.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-fr-FR.xml
index a9b8b61df..c464fc191 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-fr-FR.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-fr-FR.xml
@@ -1,19 +1,19 @@
-
-
-
- Communication en cours avec Flickr. Veuillez patientez...
- Configurer Flickr
- Famille
- Ami
- Après téléversement
- Copier le lien dans le presse-papier
- Caché dans les recherches
- Niveau de sécurité
- Format image
- Publique
- Paramètres Flickr
- Une erreur s'est produite lors du téléversement vers Flickr :
- Téléverser vers Flickr
- Image téléversée aves succès vers Flickr !
-
+
+
+
+ Communication en cours avec Flickr. Veuillez patientez...
+ Configurer Flickr
+ Famille
+ Ami
+ Après téléversement
+ Copier le lien dans le presse-papier
+ Caché dans les recherches
+ Niveau de sécurité
+ Format image
+ Publique
+ Paramètres Flickr
+ Une erreur s'est produite lors du téléversement vers Flickr :
+ Téléverser vers Flickr
+ Image téléversée aves succès vers Flickr !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-id-ID.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-id-ID.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-id-ID.xml
index 961412c99..28f29e51f 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-id-ID.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-id-ID.xml
@@ -1,19 +1,19 @@
-
-
-
- Menyambung ke Flickr. Tunggu sebentar...
- Konfigurasi Flickr
- Keluarga
- Teman
- Sesudah mengunggah
- Sambung ke papanklip
- Pencarian form tersembunyi
- Tingkat keamanan
- Format gambar
- Umum
- Setelan Flickr
- Kesalahan terjadi ketika mengunggah ke Flickr:
- Unggah ke Flickr
- Berhasil mengunggah gambar ke Flickr!
-
+
+
+
+ Menyambung ke Flickr. Tunggu sebentar...
+ Konfigurasi Flickr
+ Keluarga
+ Teman
+ Sesudah mengunggah
+ Sambung ke papanklip
+ Pencarian form tersembunyi
+ Tingkat keamanan
+ Format gambar
+ Umum
+ Setelan Flickr
+ Kesalahan terjadi ketika mengunggah ke Flickr:
+ Unggah ke Flickr
+ Berhasil mengunggah gambar ke Flickr!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-it-IT.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-it-IT.xml
similarity index 81%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-it-IT.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-it-IT.xml
index 0630da364..88347e287 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-it-IT.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-it-IT.xml
@@ -1,5 +1,5 @@
-
+
Visibilità
@@ -8,13 +8,13 @@
Liv. sicurezza
- Collegamento agli Appunti
+ Collegamento agli appunti
- Dopo il caricamento
+ Dopo il carico
- Impostazioni Flickr
+ Configurazione Flickr
Carica su Flickr
@@ -23,7 +23,7 @@
Impostazioni di Flickr
- Caricamento immagine su Flickr completato!
+ Immagine caricata correttamente su Flickr!
Si è verificato un errore durante il caricamento su Flickr:
@@ -32,7 +32,7 @@
Formato immagine
- Comunicazione con Flickr...
+ Comunicazione con Flickr. Attendere prego...
Pubblica
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-kab-DZ.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-kab-DZ.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-ko-KR.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-ko-KR.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-lv-LV.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-lv-LV.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-pl-PL.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-pl-PL.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-pl-PL.xml
index 316ca3264..e97537658 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-pl-PL.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-pl-PL.xml
@@ -1,19 +1,19 @@
-
-
-
- Trwa komunikacja z Flickr. Proszę czekać...
- Konfiguruj Flickr
- Rodzina
- Przyjaciele
- Po wysłaniu
- Link do schowka
- Ukrywaj z wyszukiwarki
- Poziom bezpieczeństwa
- Format obrazów
- Publiczny
- Ustawienia Flickr
- Wystąpił błąd przy wysyłaniu doFlickr:
- Wyślij do Flickr
- Wysyłanie obrazu do Flickr powiodło się!
-
+
+
+
+ Trwa komunikacja z Flickr. Proszę czekać...
+ Konfiguruj Flickr
+ Rodzina
+ Przyjaciele
+ Po wysłaniu
+ Link do schowka
+ Ukrywaj z wyszukiwarki
+ Poziom bezpieczeństwa
+ Format obrazów
+ Publiczny
+ Ustawienia Flickr
+ Wystąpił błąd przy wysyłaniu doFlickr:
+ Wyślij do Flickr
+ Wysyłanie obrazu do Flickr powiodło się!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-pt-PT.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-pt-PT.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-ru-RU.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-ru-RU.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-ru-RU.xml
index b279d0fb4..149bae07d 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-ru-RU.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-ru-RU.xml
@@ -1,19 +1,19 @@
-
-
-
- Общение с Flickr. Подождите...
- Настройка Flickr
- Семья
- Друг
- После загрузки
- Ссылка в буфер обмена
- Поиск скрытых форм
- Уровень безопасности
- Формат изображения
- Общество
- Параметры Flickr
- Произошла ошибка при загрузке на Flickr:
- Загрузить на Flickr
- Изображение успешно загружено на Flickr!
-
+
+
+
+ Общение с Flickr. Подождите...
+ Настройка Flickr
+ Семья
+ Друг
+ После загрузки
+ Ссылка в буфер обмена
+ Поиск скрытых форм
+ Уровень безопасности
+ Формат изображения
+ Общество
+ Параметры Flickr
+ Произошла ошибка при загрузке на Flickr:
+ Загрузить на Flickr
+ Изображение успешно загружено на Flickr!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-sr-RS.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-sr-RS.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-sr-RS.xml
index efc98c2a4..5a0faef07 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-sr-RS.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-sr-RS.xml
@@ -1,19 +1,19 @@
-
-
-
- Комуницирам с Фликром. Сачекајте…
- Поставке Фликра
- Породица
- Пријатељи
- Након отпремања:
- Веза ка остави
- Претражи скривене обрасце
- Ниво безбедности:
- Формат слике:
- Јавно
- Поставке Фликра
- Дошло је до грешке при отпремању на Фликр:
- Отпреми на Фликр
- Слика је успешно отпремљена на Фликр.
-
+
+
+
+ Комуницирам с Фликром. Сачекајте…
+ Поставке Фликра
+ Породица
+ Пријатељи
+ Након отпремања:
+ Веза ка остави
+ Претражи скривене обрасце
+ Ниво безбедности:
+ Формат слике:
+ Јавно
+ Поставке Фликра
+ Дошло је до грешке при отпремању на Фликр:
+ Отпреми на Фликр
+ Слика је успешно отпремљена на Фликр.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-sv-SE.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-sv-SE.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-uk-UA.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-uk-UA.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-uk-UA.xml
index 070b641e9..a85e0d722 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-uk-UA.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-uk-UA.xml
@@ -1,19 +1,19 @@
-
-
-
- Приховати з пошуку
- Рівень безпеки
- Посилання в буфер обміну
- Після вивантаження
- Налаштувати Flickr
- Вивантажити на Flickr
- Параметри Flickr
- Зображення вдало вивантажено на Flickr!
- Відбулась помилка при вивантаженні зображення на Flickr:
- Формат зображення
- З’єднання з Flickr. Будь ласка, зачекайте...
- Загальне
- Родина
- Друзі
-
-
+
+
+
+ Приховати з пошуку
+ Рівень безпеки
+ Посилання в буфер обміну
+ Після вивантаження
+ Налаштувати Flickr
+ Вивантажити на Flickr
+ Параметри Flickr
+ Зображення вдало вивантажено на Flickr!
+ Відбулась помилка при вивантаженні зображення на Flickr:
+ Формат зображення
+ З’єднання з Flickr. Будь ласка, зачекайте...
+ Загальне
+ Родина
+ Друзі
+
+
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-CN.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-CN.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-CN.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-CN.xml
index 781b54d97..6c3e41a0c 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-CN.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-CN.xml
@@ -1,19 +1,19 @@
-
-
-
- 正在连接到Flickr。请稍后...
- 配置Flickr
- 家庭
- 朋友
- 上传之后
- 复制链接到剪贴板
- 从搜索结果中隐藏
- 安全级别
- 图片格式
- 公开
- Flickr设置
- 上除到Flickr时发生错误!
- 上传到Flickr
- 图片已成功上传到了Flickr!
-
+
+
+
+ 正在连接到Flickr。请稍后...
+ 配置Flickr
+ 家庭
+ 朋友
+ 上传之后
+ 复制链接到剪贴板
+ 从搜索结果中隐藏
+ 安全级别
+ 图片格式
+ 公开
+ Flickr设置
+ 上除到Flickr时发生错误!
+ 上传到Flickr
+ 图片已成功上传到了Flickr!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-TW.xml b/GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-TW.xml
rename to GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-TW.xml
index b14932e4b..9386c7063 100644
--- a/src/Greenshot.Plugin.Flickr/Languages/language_flickr-zh-TW.xml
+++ b/GreenshotFlickrPlugin/Languages/language_flickrplugin-zh-TW.xml
@@ -1,19 +1,19 @@
-
-
-
- 正在與 Flickr 通訊,請稍候...
- 組態 Flickr
- 家庭
- 尋找
- 上傳後
- 連結到剪貼簿
- 從搜尋隱藏
- 安全性等級
- 圖片格式
- 公開
- Flickr 設定
- 上傳到 Flickr 時發生錯誤:
- 上傳到 Flickr
- 上傳圖片到 Flickr 成功!
-
+
+
+
+ 正在與 Flickr 通訊,請稍候...
+ 組態 Flickr
+ 家庭
+ 尋找
+ 上傳後
+ 連結到剪貼簿
+ 從搜尋隱藏
+ 安全性等級
+ 圖片格式
+ 公開
+ Flickr 設定
+ 上傳到 Flickr 時發生錯誤:
+ 上傳到 Flickr
+ 上傳圖片到 Flickr 成功!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/Properties/AssemblyInfo.cs b/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
similarity index 57%
rename from src/Greenshot.Plugin.Flickr/Properties/AssemblyInfo.cs
rename to GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
index 9701ef654..e507ea606 100644
--- a/src/Greenshot.Plugin.Flickr/Properties/AssemblyInfo.cs
+++ b/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
+[assembly: AssemblyTitle("Greenshot-Flickr-Plugin")]
[assembly: AssemblyDescription("A plugin to upload images to Flickr")]
-[assembly: AssemblyPluginIdentifier("Flickr Plugin")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot & F. Noel")]
+[assembly: AssemblyProduct("Flickr Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotFlickrPlugin.FlickrPlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Flickr/flickr.png b/GreenshotFlickrPlugin/flickr.png
similarity index 100%
rename from src/Greenshot.Plugin.Flickr/flickr.png
rename to GreenshotFlickrPlugin/flickr.png
diff --git a/GreenshotImgurPlugin/Forms/ImgurForm.cs b/GreenshotImgurPlugin/Forms/ImgurForm.cs
new file mode 100644
index 000000000..00d3c01fd
--- /dev/null
+++ b/GreenshotImgurPlugin/Forms/ImgurForm.cs
@@ -0,0 +1,30 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// This class is needed for design-time resolving of the language files
+ ///
+ public class ImgurForm : GreenshotForm {
+ }
+}
diff --git a/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.Designer.cs b/GreenshotImgurPlugin/Forms/ImgurHistory.Designer.cs
similarity index 92%
rename from src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.Designer.cs
rename to GreenshotImgurPlugin/Forms/ImgurHistory.Designer.cs
index a55f2710a..b9945c0a3 100644
--- a/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.Designer.cs
+++ b/GreenshotImgurPlugin/Forms/ImgurHistory.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,9 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-namespace Greenshot.Plugin.Imgur.Forms
+namespace GreenshotImgurPlugin
{
partial class ImgurHistory
{
@@ -87,6 +87,7 @@ namespace Greenshot.Plugin.Imgur.Forms
// deleteButton
//
this.deleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.deleteButton.AutoSize = true;
this.deleteButton.Location = new System.Drawing.Point(109, 272);
this.deleteButton.Name = "deleteButton";
this.deleteButton.Size = new System.Drawing.Size(75, 23);
@@ -98,6 +99,7 @@ namespace Greenshot.Plugin.Imgur.Forms
// openButton
//
this.openButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.openButton.AutoSize = true;
this.openButton.Location = new System.Drawing.Point(109, 305);
this.openButton.Name = "openButton";
this.openButton.Size = new System.Drawing.Size(75, 23);
@@ -120,6 +122,7 @@ namespace Greenshot.Plugin.Imgur.Forms
// clipboardButton
//
this.clipboardButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.clipboardButton.AutoSize = true;
this.clipboardButton.Location = new System.Drawing.Point(109, 338);
this.clipboardButton.Name = "clipboardButton";
this.clipboardButton.Size = new System.Drawing.Size(129, 23);
@@ -141,8 +144,8 @@ namespace Greenshot.Plugin.Imgur.Forms
//
// ImgurHistory
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(534, 372);
this.Controls.Add(this.clearHistoryButton);
this.Controls.Add(this.clipboardButton);
diff --git a/GreenshotImgurPlugin/Forms/ImgurHistory.cs b/GreenshotImgurPlugin/Forms/ImgurHistory.cs
new file mode 100644
index 000000000..517bb165f
--- /dev/null
+++ b/GreenshotImgurPlugin/Forms/ImgurHistory.cs
@@ -0,0 +1,221 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Globalization;
+using System.Text;
+using System.Windows.Forms;
+
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// Imgur history form
+ ///
+ public sealed partial class ImgurHistory : ImgurForm {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurHistory));
+ private readonly GreenshotColumnSorter _columnSorter;
+ private static readonly object Lock = new object();
+ private static readonly ImgurConfiguration Config = IniConfig.GetIniSection();
+ private static ImgurHistory _instance;
+
+ public static void ShowHistory() {
+ lock (Lock)
+ {
+ if (ImgurUtils.IsHistoryLoadingNeeded())
+ {
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait("Imgur " + Language.GetString("imgur", LangKey.history), Language.GetString("imgur", LangKey.communication_wait),
+ ImgurUtils.LoadHistory
+ );
+ }
+
+ // Make sure the history is loaded, will be done only once
+ if (_instance == null)
+ {
+ _instance = new ImgurHistory();
+ }
+ if (!_instance.Visible)
+ {
+ _instance.Show();
+ }
+ _instance.Redraw();
+ }
+ }
+
+ private ImgurHistory() {
+ ManualLanguageApply = true;
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = finishedButton;
+ CancelButton = finishedButton;
+ // Init sorting
+ _columnSorter = new GreenshotColumnSorter();
+ listview_imgur_uploads.ListViewItemSorter = _columnSorter;
+ _columnSorter.SortColumn = 3;
+ _columnSorter.Order = SortOrder.Descending;
+ Redraw();
+ if (listview_imgur_uploads.Items.Count > 0) {
+ listview_imgur_uploads.Items[0].Selected = true;
+ }
+ ApplyLanguage();
+ if (Config.Credits > 0) {
+ Text = Text + " (" + Config.Credits + " credits)";
+ }
+ }
+
+ private void Redraw() {
+ // Should fix Bug #3378699
+ pictureBox1.Image = pictureBox1.ErrorImage;
+ listview_imgur_uploads.BeginUpdate();
+ listview_imgur_uploads.Items.Clear();
+ listview_imgur_uploads.Columns.Clear();
+ string[] columns = { "hash", "title", "deleteHash", "Date"};
+ foreach (string column in columns) {
+ listview_imgur_uploads.Columns.Add(column);
+ }
+ foreach (ImgurInfo imgurInfo in Config.runtimeImgurHistory.Values) {
+ var item = new ListViewItem(imgurInfo.Hash)
+ {
+ Tag = imgurInfo
+ };
+ item.SubItems.Add(imgurInfo.Title);
+ item.SubItems.Add(imgurInfo.DeleteHash);
+ item.SubItems.Add(imgurInfo.Timestamp.ToString("yyyy-MM-dd HH:mm:ss", DateTimeFormatInfo.InvariantInfo));
+ listview_imgur_uploads.Items.Add(item);
+ }
+ for (int i = 0; i < columns.Length; i++) {
+ listview_imgur_uploads.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
+ }
+
+ listview_imgur_uploads.EndUpdate();
+ listview_imgur_uploads.Refresh();
+ deleteButton.Enabled = false;
+ openButton.Enabled = false;
+ clipboardButton.Enabled = false;
+ }
+
+ private void Listview_imgur_uploadsSelectedIndexChanged(object sender, EventArgs e) {
+ pictureBox1.Image = pictureBox1.ErrorImage;
+ if (listview_imgur_uploads.SelectedItems.Count > 0) {
+ deleteButton.Enabled = true;
+ openButton.Enabled = true;
+ clipboardButton.Enabled = true;
+ if (listview_imgur_uploads.SelectedItems.Count == 1) {
+ ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[0].Tag;
+ pictureBox1.Image = imgurInfo.Image;
+ }
+ } else {
+ pictureBox1.Image = pictureBox1.ErrorImage;
+ deleteButton.Enabled = false;
+ openButton.Enabled = false;
+ clipboardButton.Enabled = false;
+ }
+ }
+
+ private void DeleteButtonClick(object sender, EventArgs e) {
+ if (listview_imgur_uploads.SelectedItems.Count > 0) {
+ for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) {
+ ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag;
+ DialogResult result = MessageBox.Show(Language.GetFormattedString("imgur", LangKey.delete_question, imgurInfo.Title), Language.GetFormattedString("imgur", LangKey.delete_title, imgurInfo.Hash), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result != DialogResult.Yes)
+ {
+ continue;
+ }
+ // Should fix Bug #3378699
+ pictureBox1.Image = pictureBox1.ErrorImage;
+ try {
+ new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait),
+ delegate {
+ ImgurUtils.DeleteImgurImage(imgurInfo);
+ }
+ );
+ } catch (Exception ex) {
+ Log.Warn("Problem communicating with Imgur: ", ex);
+ }
+
+ imgurInfo.Dispose();
+ }
+ }
+ Redraw();
+ }
+
+ private void ClipboardButtonClick(object sender, EventArgs e) {
+ StringBuilder links = new StringBuilder();
+ if (listview_imgur_uploads.SelectedItems.Count > 0) {
+ for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++)
+ {
+ ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag;
+ links.AppendLine(Config.UsePageLink ? imgurInfo.Page : imgurInfo.Original);
+ }
+ }
+ ClipboardHelper.SetClipboardData(links.ToString());
+ }
+
+ private void ClearHistoryButtonClick(object sender, EventArgs e) {
+ DialogResult result = MessageBox.Show(Language.GetString("imgur", LangKey.clear_question), "Imgur", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ if (result == DialogResult.Yes) {
+ Config.runtimeImgurHistory.Clear();
+ Config.ImgurUploadHistory.Clear();
+ IniConfig.Save();
+ Redraw();
+ }
+ }
+
+ private void FinishedButtonClick(object sender, EventArgs e)
+ {
+ Hide();
+ }
+
+ private void OpenButtonClick(object sender, EventArgs e) {
+ if (listview_imgur_uploads.SelectedItems.Count > 0) {
+ for (int i = 0; i < listview_imgur_uploads.SelectedItems.Count; i++) {
+ ImgurInfo imgurInfo = (ImgurInfo)listview_imgur_uploads.SelectedItems[i].Tag;
+ System.Diagnostics.Process.Start(imgurInfo.Page);
+ }
+ }
+ }
+
+ private void listview_imgur_uploads_ColumnClick(object sender, ColumnClickEventArgs e) {
+ // Determine if clicked column is already the column that is being sorted.
+ if (e.Column == _columnSorter.SortColumn) {
+ // Reverse the current sort direction for this column.
+ _columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
+ } else {
+ // Set the column number that is to be sorted; default to ascending.
+ _columnSorter.SortColumn = e.Column;
+ _columnSorter.Order = SortOrder.Ascending;
+ }
+
+ // Perform the sort with these new sort options.
+ listview_imgur_uploads.Sort();
+ }
+
+
+ private void ImgurHistoryFormClosing(object sender, FormClosingEventArgs e)
+ {
+ _instance = null;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs b/GreenshotImgurPlugin/Forms/SettingsForm.Designer.cs
similarity index 77%
rename from src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs
rename to GreenshotImgurPlugin/Forms/SettingsForm.Designer.cs
index 1b9b52c42..6f867efc8 100644
--- a/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs
+++ b/GreenshotImgurPlugin/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Imgur.Forms {
+namespace GreenshotImgurPlugin {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,13 +46,13 @@ namespace Greenshot.Plugin.Imgur.Forms {
///
private void InitializeComponent()
{
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.historyButton = new GreenshotButton();
- this.checkbox_anonymous_access = new GreenshotCheckBox();
- this.checkbox_usepagelink = new GreenshotCheckBox();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.historyButton = new GreenshotPlugin.Controls.GreenshotButton();
+ this.checkbox_anonymous_access = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkbox_usepagelink = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.SuspendLayout();
//
// buttonOK
@@ -86,7 +83,7 @@ namespace Greenshot.Plugin.Imgur.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(168, 7);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(ImgurConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Imgur";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(210, 21);
this.combobox_uploadimageformat.TabIndex = 1;
@@ -112,10 +109,11 @@ namespace Greenshot.Plugin.Imgur.Forms {
//
// checkbox_anonymous_access
//
+ this.checkbox_anonymous_access.AutoSize = true;
this.checkbox_anonymous_access.LanguageKey = "imgur.anonymous_access";
this.checkbox_anonymous_access.Location = new System.Drawing.Point(15, 38);
this.checkbox_anonymous_access.Name = "checkbox_anonymous_access";
- this.checkbox_anonymous_access.PropertyName = nameof(ImgurConfiguration.AnonymousAccess);
+ this.checkbox_anonymous_access.PropertyName = "AnonymousAccess";
this.checkbox_anonymous_access.SectionName = "Imgur";
this.checkbox_anonymous_access.Size = new System.Drawing.Size(139, 17);
this.checkbox_anonymous_access.TabIndex = 2;
@@ -123,10 +121,11 @@ namespace Greenshot.Plugin.Imgur.Forms {
//
// checkbox_usepagelink
//
+ this.checkbox_usepagelink.AutoSize = true;
this.checkbox_usepagelink.LanguageKey = "imgur.use_page_link";
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 57);
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
- this.checkbox_usepagelink.PropertyName = nameof(ImgurConfiguration.UsePageLink);
+ this.checkbox_usepagelink.PropertyName = "UsePageLink";
this.checkbox_usepagelink.SectionName = "Imgur";
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
this.checkbox_usepagelink.TabIndex = 3;
@@ -153,12 +152,12 @@ namespace Greenshot.Plugin.Imgur.Forms {
this.PerformLayout();
}
- private GreenshotButton historyButton;
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotCheckBox checkbox_anonymous_access;
- private GreenshotCheckBox checkbox_usepagelink;
+ private GreenshotPlugin.Controls.GreenshotButton historyButton;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_anonymous_access;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usepagelink;
}
}
diff --git a/GreenshotImgurPlugin/Forms/SettingsForm.cs b/GreenshotImgurPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..f68a50794
--- /dev/null
+++ b/GreenshotImgurPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,44 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : ImgurForm {
+ public SettingsForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ CancelButton = buttonCancel;
+ AcceptButton = buttonOK;
+
+ historyButton.Enabled = ImgurUtils.IsHistoryLoadingNeeded();
+ }
+
+ private void ButtonHistoryClick(object sender, EventArgs e) {
+ ImgurHistory.ShowHistory();
+ }
+ }
+}
diff --git a/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj
new file mode 100644
index 000000000..6e4f81932
--- /dev/null
+++ b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj
@@ -0,0 +1,102 @@
+
+
+
+
+ {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}
+ Library
+ GreenshotImgurPlugin
+ GreenshotImgurPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+
+
+
+ 3.5
+
+
+
+
+
+
+ ..\packages\LinqBridge.1.3.0\lib\net20\LinqBridge.dll
+ True
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ ImgurHistory.cs
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+
+
+
+
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+
+ ImgurPlugin.cs
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+if exist "$(ProjectDir)ImgurCredentials.private.cs" (
+ rename "$(ProjectDir)ImgurCredentials.cs" "ImgurCredentials.orig.cs"
+ rename "$(ProjectDir)ImgurCredentials.private.cs" "ImgurCredentials.cs"
+)
+ if exist "$(ProjectDir)ImgurCredentials.orig.cs" (
+ rename "$(ProjectDir)ImgurCredentials.cs" "ImgurCredentials.private.cs"
+ rename "$(ProjectDir)ImgurCredentials.orig.cs" "ImgurCredentials.cs"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
\ No newline at end of file
diff --git a/GreenshotImgurPlugin/ImgurConfiguration.cs b/GreenshotImgurPlugin/ImgurConfiguration.cs
new file mode 100644
index 000000000..a65c3e7b2
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurConfiguration.cs
@@ -0,0 +1,102 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// Description of ImgurConfiguration.
+ ///
+ [IniSection("Imgur", Description="Greenshot Imgur Plugin configuration")]
+ public class ImgurConfiguration : IniSection {
+ [IniProperty("ImgurApi3Url", Description = "Url to Imgur system.", DefaultValue = "https://api.imgur.com/3")]
+ public string ImgurApi3Url { get; set; }
+
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+ [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
+ public bool UploadReduceColors { get; set; }
+ [IniProperty("CopyLinkToClipboard", Description = "Copy the link, which one is controlled by the UsePageLink, on the clipboard", DefaultValue = "True")]
+ public bool CopyLinkToClipboard { get; set; }
+ [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
+ public bool UsePageLink { get; set; }
+ [IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue="true")]
+ public bool AnonymousAccess { get; set; }
+
+ [IniProperty("RefreshToken", Description = "Imgur refresh Token", Encrypted = true, ExcludeIfNull = true)]
+ public string RefreshToken { get; set; }
+
+ ///
+ /// AccessToken, not stored
+ ///
+ public string AccessToken { get; set; }
+
+ ///
+ /// AccessTokenExpires, not stored
+ ///
+ public DateTimeOffset AccessTokenExpires { get; set; }
+
+ [IniProperty("AddTitle", Description = "Is the title passed on to Imgur", DefaultValue = "False")]
+ public bool AddTitle { get; set; }
+ [IniProperty("AddFilename", Description = "Is the filename passed on to Imgur", DefaultValue = "False")]
+ public bool AddFilename { get; set; }
+ [IniProperty("FilenamePattern", Description = "Filename for the Imgur upload", DefaultValue = "${capturetime:d\"yyyyMMdd-HHmm\"}")]
+ public string FilenamePattern { get; set; }
+
+ [IniProperty("ImgurUploadHistory", Description="Imgur upload history (ImgurUploadHistory.hash=deleteHash)")]
+ public Dictionary ImgurUploadHistory { get; set; }
+
+ // Not stored, only run-time!
+ public Dictionary runtimeImgurHistory = new Dictionary();
+ public int Credits {
+ get;
+ set;
+ }
+
+ ///
+ /// Supply values we can't put as defaults
+ ///
+ /// The property to return a default for
+ /// object with the default value for the supplied property
+ public override object GetDefault(string property) {
+ switch(property) {
+ case "ImgurUploadHistory":
+ return new Dictionary();
+ }
+ return null;
+ }
+ ///
+ /// A form for username/password
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ SettingsForm settingsForm = new SettingsForm();
+ DialogResult result = settingsForm.ShowDialog();
+ return result == DialogResult.OK;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.Credentials.template b/GreenshotImgurPlugin/ImgurCredentials.cs
similarity index 78%
rename from src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.Credentials.template
rename to GreenshotImgurPlugin/ImgurCredentials.cs
index eaf70d311..159a4e08a 100644
--- a/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.Credentials.template
+++ b/GreenshotImgurPlugin/ImgurCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.Imgur {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for imgur integration.
- /// You can set your own values here
- ///
- public static class ImgurCredentials {
- public static string CONSUMER_KEY = "${Imgur13_ClientId}";
- public static string CONSUMER_SECRET = "${Imgur13_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for imgur integration.
+ /// You can set your own values here
+ ///
+ public static class ImgurCredentials {
+ public static string CONSUMER_KEY = "@credentials_imgur_consumer_key@";
+ public static string CONSUMER_SECRET = "@credentials_imgur_consumer_secret@";
+ }
+}
diff --git a/GreenshotImgurPlugin/ImgurDestination.cs b/GreenshotImgurPlugin/ImgurDestination.cs
new file mode 100644
index 000000000..030a6e81a
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurDestination.cs
@@ -0,0 +1,57 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// Description of ImgurDestination.
+ ///
+ public class ImgurDestination : AbstractDestination {
+ private readonly ImgurPlugin _plugin;
+
+ public ImgurDestination(ImgurPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override string Designation => "Imgur";
+
+ public override string Description => Language.GetString("imgur", LangKey.upload_menu_item);
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(ImgurPlugin));
+ return (Image)resources.GetObject("Imgur");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ exportInformation.ExportMade = _plugin.Upload(captureDetails, surface, out uploadUrl);
+ exportInformation.Uri = uploadUrl;
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotImgurPlugin/ImgurInfo.cs b/GreenshotImgurPlugin/ImgurInfo.cs
new file mode 100644
index 000000000..61f16a17e
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurInfo.cs
@@ -0,0 +1,218 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Xml;
+
+namespace GreenshotImgurPlugin
+{
+ ///
+ /// Description of ImgurInfo.
+ ///
+ public class ImgurInfo : IDisposable
+ {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurInfo));
+
+ public string Hash
+ {
+ get;
+ set;
+ }
+
+ private string _deleteHash;
+ public string DeleteHash
+ {
+ get { return _deleteHash; }
+ set
+ {
+ _deleteHash = value;
+ DeletePage = "https://imgur.com/delete/" + value;
+ }
+ }
+
+ public string Title
+ {
+ get;
+ set;
+ }
+
+ public string ImageType
+ {
+ get;
+ set;
+ }
+
+ public DateTime Timestamp
+ {
+ get;
+ set;
+ }
+
+ public string Original
+ {
+ get;
+ set;
+ }
+
+ public string Page
+ {
+ get;
+ set;
+ }
+
+ public string SmallSquare
+ {
+ get;
+ set;
+ }
+
+ public string LargeThumbnail
+ {
+ get;
+ set;
+ }
+
+ public string DeletePage
+ {
+ get;
+ set;
+ }
+
+ private Image _image;
+ public Image Image
+ {
+ get { return _image; }
+ set
+ {
+ _image?.Dispose();
+ _image = value;
+ }
+ }
+
+ ///
+ /// The public accessible Dispose
+ /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ /// When disposing==true all non-managed resources should be freed too!
+ ///
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _image?.Dispose();
+ }
+ _image = null;
+ }
+ public static ImgurInfo ParseResponse(string response)
+ {
+ Log.Debug(response);
+ // This is actually a hack for BUG-1695
+ // The problem is the (C) sign, we send it HTML encoded "®" to Imgur and get it HTML encoded in the XML back
+ // Added all the encodings I found quickly, I guess these are not all... but it should fix the issue for now.
+ response = response.Replace("¢", "¢");
+ response = response.Replace("£", "£");
+ response = response.Replace("¥", "¥");
+ response = response.Replace("€", "€");
+ response = response.Replace("©", "©");
+ response = response.Replace("®", "®");
+
+ ImgurInfo imgurInfo = new ImgurInfo();
+ try
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(response);
+ XmlNodeList nodes = doc.GetElementsByTagName("id");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Hash = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("hash");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Hash = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("deletehash");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.DeleteHash = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("type");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.ImageType = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("title");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Title = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("datetime");
+ if (nodes.Count > 0)
+ {
+ // Version 3 has seconds since Epoch
+ double secondsSince;
+ if (double.TryParse(nodes.Item(0)?.InnerText, out secondsSince))
+ {
+ var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
+ imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime;
+ }
+ }
+ nodes = doc.GetElementsByTagName("original");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
+ }
+ // Version 3 API only has Link
+ nodes = doc.GetElementsByTagName("link");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Original = nodes.Item(0)?.InnerText.Replace("http:", "https:");
+ }
+ nodes = doc.GetElementsByTagName("imgur_page");
+ if (nodes.Count > 0)
+ {
+ imgurInfo.Page = nodes.Item(0)?.InnerText.Replace("http:", "https:");
+ }
+ else
+ {
+ // Version 3 doesn't have a page link in the response
+ imgurInfo.Page = $"https://imgur.com/{imgurInfo.Hash}";
+ }
+ nodes = doc.GetElementsByTagName("small_square");
+ imgurInfo.SmallSquare = nodes.Count > 0 ? nodes.Item(0)?.InnerText : $"http://i.imgur.com/{imgurInfo.Hash}s.png";
+ }
+ catch (Exception e)
+ {
+ Log.ErrorFormat("Could not parse Imgur response due to error {0}, response was: {1}", e.Message, response);
+ }
+ return imgurInfo;
+ }
+ }
+}
diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs
new file mode 100644
index 000000000..00af89c19
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurPlugin.cs
@@ -0,0 +1,221 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// This is the ImgurPlugin code
+ ///
+ public class ImgurPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurPlugin));
+ private static ImgurConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _historyMenuItem;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_historyMenuItem != null) {
+ _historyMenuItem.Dispose();
+ _historyMenuItem = null;
+ }
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new ImgurDestination(this);
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ _host = pluginHost;
+ Attributes = myAttributes;
+
+ // Get configuration
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(ImgurPlugin));
+
+ ToolStripMenuItem itemPlugInRoot = new ToolStripMenuItem("Imgur")
+ {
+ Image = (Image) _resources.GetObject("Imgur")
+ };
+
+ _historyMenuItem = new ToolStripMenuItem(Language.GetString("imgur", LangKey.history))
+ {
+ Tag = _host
+ };
+ _historyMenuItem.Click += delegate {
+ ImgurHistory.ShowHistory();
+ };
+ itemPlugInRoot.DropDownItems.Add(_historyMenuItem);
+
+ _itemPlugInConfig = new ToolStripMenuItem(Language.GetString("imgur", LangKey.configure))
+ {
+ Tag = _host
+ };
+ _itemPlugInConfig.Click += delegate {
+ _config.ShowConfigDialog();
+ };
+ itemPlugInRoot.DropDownItems.Add(_itemPlugInConfig);
+
+ PluginUtils.AddToContextMenu(_host, itemPlugInRoot);
+ Language.LanguageChanged += OnLanguageChanged;
+
+ // Enable history if there are items available
+ UpdateHistoryMenuItem();
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("imgur", LangKey.configure);
+ }
+ if (_historyMenuItem != null) {
+ _historyMenuItem.Text = Language.GetString("imgur", LangKey.history);
+ }
+ }
+
+ private void UpdateHistoryMenuItem() {
+ if (_historyMenuItem == null)
+ {
+ return;
+ }
+ try
+ {
+ _host.GreenshotForm.BeginInvoke((MethodInvoker)delegate {
+ if (_config.ImgurUploadHistory != null && _config.ImgurUploadHistory.Count > 0) {
+ _historyMenuItem.Enabled = true;
+ } else {
+ _historyMenuItem.Enabled = false;
+ }
+ });
+ } catch (Exception ex) {
+ Log.Error("Error loading history", ex);
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Imgur Plugin shutdown.");
+ Language.LanguageChanged -= OnLanguageChanged;
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ ///
+ /// Upload the capture to imgur
+ ///
+ /// ICaptureDetails
+ /// ISurface
+ /// out string for the url
+ /// true if the upload succeeded
+ public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, _config.UploadReduceColors);
+ try {
+ string filename = Path.GetFileName(FilenameHelper.GetFilenameFromPattern(_config.FilenamePattern, _config.UploadFormat, captureDetails));
+ ImgurInfo imgurInfo = null;
+
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait("Imgur plug-in", Language.GetString("imgur", LangKey.communication_wait),
+ delegate
+ {
+ imgurInfo = ImgurUtils.UploadToImgur(surfaceToUpload, outputSettings, captureDetails.Title, filename);
+ if (imgurInfo != null && _config.AnonymousAccess) {
+ Log.InfoFormat("Storing imgur upload for hash {0} and delete hash {1}", imgurInfo.Hash, imgurInfo.DeleteHash);
+ _config.ImgurUploadHistory.Add(imgurInfo.Hash, imgurInfo.DeleteHash);
+ _config.runtimeImgurHistory.Add(imgurInfo.Hash, imgurInfo);
+ UpdateHistoryMenuItem();
+ }
+ }
+ );
+
+ if (imgurInfo != null) {
+ // TODO: Optimize a second call for export
+ using (Image tmpImage = surfaceToUpload.GetImageForExport()) {
+ imgurInfo.Image = ImageHelper.CreateThumbnail(tmpImage, 90, 90);
+ }
+ IniConfig.Save();
+
+ if (_config.UsePageLink)
+ {
+ uploadUrl = imgurInfo.Page;
+ }
+ else
+ {
+ uploadUrl = imgurInfo.Original;
+ }
+ if (!string.IsNullOrEmpty(uploadUrl) && _config.CopyLinkToClipboard)
+ {
+ try
+ {
+ ClipboardHelper.SetClipboardData(uploadUrl);
+
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Can't write to clipboard: ", ex);
+ uploadUrl = null;
+ }
+ }
+ return true;
+ }
+ } catch (Exception e) {
+ Log.Error("Error uploading.", e);
+ MessageBox.Show(Language.GetString("imgur", LangKey.upload_failure) + " " + e.Message);
+ }
+ uploadUrl = null;
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Imgur/ImgurPlugin.resx b/GreenshotImgurPlugin/ImgurPlugin.resx
similarity index 95%
rename from src/Greenshot.Plugin.Imgur/ImgurPlugin.resx
rename to GreenshotImgurPlugin/ImgurPlugin.resx
index ce27fddee..133a58122 100644
--- a/src/Greenshot.Plugin.Imgur/ImgurPlugin.resx
+++ b/GreenshotImgurPlugin/ImgurPlugin.resx
@@ -112,12 +112,12 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs
new file mode 100644
index 000000000..c2f002ccc
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurUtils.cs
@@ -0,0 +1,359 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Net;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotImgurPlugin {
+ ///
+ /// A collection of Imgur helper methods
+ ///
+ public static class ImgurUtils {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils));
+ private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg";
+ private static readonly ImgurConfiguration Config = IniConfig.GetIniSection();
+ private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}";
+ private const string TokenUrl = "https://api.imgur.com/oauth2/token";
+
+ ///
+ /// Check if we need to load the history
+ ///
+ ///
+ public static bool IsHistoryLoadingNeeded()
+ {
+ Log.InfoFormat("Checking if imgur cache loading needed, configuration has {0} imgur hashes, loaded are {1} hashes.", Config.ImgurUploadHistory.Count, Config.runtimeImgurHistory.Count);
+ return Config.runtimeImgurHistory.Count != Config.ImgurUploadHistory.Count;
+ }
+
+ ///
+ /// Load the complete history of the imgur uploads, with the corresponding information
+ ///
+ public static void LoadHistory() {
+ if (!IsHistoryLoadingNeeded())
+ {
+ return;
+ }
+
+ bool saveNeeded = false;
+
+ // Load the ImUr history
+ foreach (string hash in Config.ImgurUploadHistory.Keys.ToList()) {
+ if (Config.runtimeImgurHistory.ContainsKey(hash)) {
+ // Already loaded
+ continue;
+ }
+
+ try
+ {
+ var deleteHash = Config.ImgurUploadHistory[hash];
+ ImgurInfo imgurInfo = RetrieveImgurInfo(hash, deleteHash);
+ if (imgurInfo != null) {
+ RetrieveImgurThumbnail(imgurInfo);
+ Config.runtimeImgurHistory[hash] = imgurInfo;
+ } else {
+ Log.InfoFormat("Deleting unknown ImgUr {0} from config, delete hash was {1}.", hash, deleteHash);
+ Config.ImgurUploadHistory.Remove(hash);
+ Config.runtimeImgurHistory.Remove(hash);
+ saveNeeded = true;
+ }
+ } catch (WebException wE) {
+ bool redirected = false;
+ if (wE.Status == WebExceptionStatus.ProtocolError) {
+ HttpWebResponse response = (HttpWebResponse)wE.Response;
+
+ if (response.StatusCode == HttpStatusCode.Forbidden)
+ {
+ Log.Error("Imgur loading forbidden", wE);
+ break;
+ }
+ // Image no longer available?
+ if (response.StatusCode == HttpStatusCode.Redirect) {
+ Log.InfoFormat("ImgUr image for hash {0} is no longer available, removing it from the history", hash);
+ Config.ImgurUploadHistory.Remove(hash);
+ Config.runtimeImgurHistory.Remove(hash);
+ redirected = true;
+ }
+ }
+ if (!redirected) {
+ Log.Error("Problem loading ImgUr history for hash " + hash, wE);
+ }
+ } catch (Exception e) {
+ Log.Error("Problem loading ImgUr history for hash " + hash, e);
+ }
+ }
+ if (saveNeeded) {
+ // Save needed changes
+ IniConfig.Save();
+ }
+ }
+
+ ///
+ /// Use this to make sure Imgur knows from where the upload comes.
+ ///
+ ///
+ private static void SetClientId(HttpWebRequest webRequest) {
+ webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY);
+ }
+
+ ///
+ /// Do the actual upload to Imgur
+ /// For more details on the available parameters, see: http://api.imgur.com/resources_anon
+ ///
+ /// ISurface to upload
+ /// OutputSettings for the image file format
+ /// Title
+ /// Filename
+ /// ImgurInfo with details
+ public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
+ IDictionary otherParameters = new Dictionary();
+ // add title
+ if (title != null && Config.AddTitle) {
+ otherParameters["title"]= title;
+ }
+ // add filename
+ if (filename != null && Config.AddFilename) {
+ otherParameters["name"] = filename;
+ }
+ string responseString = null;
+ if (Config.AnonymousAccess) {
+ // add key, we only use the other parameters for the AnonymousAccess
+ //otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
+ HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(Config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST);
+ webRequest.ContentType = "image/" + outputSettings.Format;
+ webRequest.ServicePoint.Expect100Continue = false;
+
+ SetClientId(webRequest);
+ try {
+ using (var requestStream = webRequest.GetRequestStream()) {
+ ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings);
+ }
+
+ using (WebResponse response = webRequest.GetResponse())
+ {
+ LogRateLimitInfo(response);
+ var responseStream = response.GetResponseStream();
+ if (responseStream != null)
+ {
+ using (StreamReader reader = new StreamReader(responseStream, true))
+ {
+ responseString = reader.ReadToEnd();
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Log.Error("Upload to imgur gave an exeption: ", ex);
+ throw;
+ }
+ } else {
+
+ var oauth2Settings = new OAuth2Settings
+ {
+ AuthUrlPattern = AuthUrlPattern,
+ TokenUrl = TokenUrl,
+ RedirectUrl = "https://imgur.com",
+ CloudServiceName = "Imgur",
+ ClientId = ImgurCredentials.CONSUMER_KEY,
+ ClientSecret = ImgurCredentials.CONSUMER_SECRET,
+ AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser,
+ BrowserSize = new Size(680, 880),
+ RefreshToken = Config.RefreshToken,
+ AccessToken = Config.AccessToken,
+ AccessTokenExpires = Config.AccessTokenExpires
+ };
+
+ // Copy the settings from the config, which is kept in memory and on the disk
+
+ try
+ {
+ var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "/upload.xml", oauth2Settings);
+ otherParameters["image"] = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+
+ NetworkHelper.WriteMultipartFormData(webRequest, otherParameters);
+
+ responseString = NetworkHelper.GetResponseAsString(webRequest);
+ }
+ finally
+ {
+ // Copy the settings back to the config, so they are stored.
+ Config.RefreshToken = oauth2Settings.RefreshToken;
+ Config.AccessToken = oauth2Settings.AccessToken;
+ Config.AccessTokenExpires = oauth2Settings.AccessTokenExpires;
+ Config.IsDirty = true;
+ IniConfig.Save();
+ }
+ }
+ if (string.IsNullOrEmpty(responseString))
+ {
+ return null;
+ }
+ return ImgurInfo.ParseResponse(responseString);
+ }
+
+ ///
+ /// Retrieve the thumbnail of an imgur image
+ ///
+ ///
+ public static void RetrieveImgurThumbnail(ImgurInfo imgurInfo) {
+ if (imgurInfo.SmallSquare == null) {
+ Log.Warn("Imgur URL was null, not retrieving thumbnail.");
+ return;
+ }
+ Log.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare);
+ HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET);
+ webRequest.ServicePoint.Expect100Continue = false;
+ // Not for getting the thumbnail, in anonymous modus
+ //SetClientId(webRequest);
+ using (WebResponse response = webRequest.GetResponse()) {
+ LogRateLimitInfo(response);
+ Stream responseStream = response.GetResponseStream();
+ if (responseStream != null)
+ {
+ imgurInfo.Image = ImageHelper.FromStream(responseStream);
+ }
+ }
+ }
+
+ ///
+ /// Retrieve information on an imgur image
+ ///
+ ///
+ ///
+ /// ImgurInfo
+ public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash) {
+ string url = Config.ImgurApi3Url + "/image/" + hash + ".xml";
+ Log.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url);
+ HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET);
+ webRequest.ServicePoint.Expect100Continue = false;
+ SetClientId(webRequest);
+ string responseString = null;
+ try {
+ using (WebResponse response = webRequest.GetResponse()) {
+ LogRateLimitInfo(response);
+ var responseStream = response.GetResponseStream();
+ if (responseStream != null)
+ {
+ using (StreamReader reader = new StreamReader(responseStream, true))
+ {
+ responseString = reader.ReadToEnd();
+ }
+ }
+ }
+ } catch (WebException wE) {
+ if (wE.Status == WebExceptionStatus.ProtocolError) {
+ if (((HttpWebResponse)wE.Response).StatusCode == HttpStatusCode.NotFound) {
+ return null;
+ }
+ }
+ throw;
+ }
+ ImgurInfo imgurInfo = null;
+ if (responseString != null)
+ {
+ Log.Debug(responseString);
+ imgurInfo = ImgurInfo.ParseResponse(responseString);
+ imgurInfo.DeleteHash = deleteHash;
+ }
+ return imgurInfo;
+ }
+
+ ///
+ /// Delete an imgur image, this is done by specifying the delete hash
+ ///
+ ///
+ public static void DeleteImgurImage(ImgurInfo imgurInfo) {
+ Log.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash);
+
+ try {
+ string url = Config.ImgurApi3Url + "/image/" + imgurInfo.DeleteHash + ".xml";
+ HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.DELETE);
+ webRequest.ServicePoint.Expect100Continue = false;
+ SetClientId(webRequest);
+ string responseString = null;
+ using (WebResponse response = webRequest.GetResponse()) {
+ LogRateLimitInfo(response);
+ var responseStream = response.GetResponseStream();
+ if (responseStream != null)
+ {
+ using (StreamReader reader = new StreamReader(responseStream, true))
+ {
+ responseString = reader.ReadToEnd();
+ }
+ }
+ }
+ Log.InfoFormat("Delete result: {0}", responseString);
+ } catch (WebException wE) {
+ // Allow "Bad request" this means we already deleted it
+ if (wE.Status == WebExceptionStatus.ProtocolError) {
+ if (((HttpWebResponse)wE.Response).StatusCode != HttpStatusCode.BadRequest) {
+ throw ;
+ }
+ }
+ }
+ // Make sure we remove it from the history, if no error occured
+ Config.runtimeImgurHistory.Remove(imgurInfo.Hash);
+ Config.ImgurUploadHistory.Remove(imgurInfo.Hash);
+ imgurInfo.Image = null;
+ }
+
+ ///
+ /// Helper for logging
+ ///
+ ///
+ ///
+ private static void LogHeader(IDictionary nameValues, string key) {
+ if (nameValues.ContainsKey(key)) {
+ Log.InfoFormat("{0}={1}", key, nameValues[key]);
+ }
+ }
+
+ ///
+ /// Log the current rate-limit information
+ ///
+ ///
+ private static void LogRateLimitInfo(WebResponse response) {
+ IDictionary nameValues = new Dictionary();
+ foreach (string key in response.Headers.AllKeys) {
+ if (!nameValues.ContainsKey(key)) {
+ nameValues.Add(key, response.Headers[key]);
+ }
+ }
+ LogHeader(nameValues, "X-RateLimit-Limit");
+ LogHeader(nameValues, "X-RateLimit-Remaining");
+ LogHeader(nameValues, "X-RateLimit-UserLimit");
+ LogHeader(nameValues, "X-RateLimit-UserRemaining");
+ LogHeader(nameValues, "X-RateLimit-UserReset");
+ LogHeader(nameValues, "X-RateLimit-ClientLimit");
+ LogHeader(nameValues, "X-RateLimit-ClientRemaining");
+
+ // Update the credits in the config, this is shown in a form
+ int credits;
+ if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out credits)) {
+ Config.Credits = credits;
+ }
+ }
+ }
+}
diff --git a/GreenshotImgurPlugin/LanguageKeys.cs b/GreenshotImgurPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..fbee74ad7
--- /dev/null
+++ b/GreenshotImgurPlugin/LanguageKeys.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotImgurPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ settings_title,
+ label_url,
+ label_upload_format,
+ label_clear,
+ OK,
+ CANCEL,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ delete_question,
+ clear_question,
+ delete_title,
+ use_page_link,
+ history,
+ configure
+ }
+}
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-cs-CZ.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-cs-CZ.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-cs-CZ.xml
index 07020ce21..2b7a62e83 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-cs-CZ.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-cs-CZ.xml
@@ -1,21 +1,21 @@
-
-
-
- Použít anonymní přístup
- Zrušit
- Jste si jisti, že chcete smazat místní historii Imgur?
- Komunikace s Imgur. Prosím čekejte ...
- Nastavení
- Jste si jisti, že chcete smazat obrázek {0} z Imgur?
- Odstranit Imgur {0}
- Historie
- Formát obrázku
- Url
- OK
- Nastavení Imgur
- Došlo k chybě při nahrávání na Imgur:
- Nahrát na Imgur
- Obrázek byl úspěšně odeslán na Imgur!
- Použijte odkaz na stránku namísto odkaz na obrázek do schránky
-
+
+
+
+ Použít anonymní přístup
+ Zrušit
+ Jste si jisti, že chcete smazat místní historii Imgur?
+ Komunikace s Imgur. Prosím čekejte ...
+ Nastavení
+ Jste si jisti, že chcete smazat obrázek {0} z Imgur?
+ Odstranit Imgur {0}
+ Historie
+ Formát obrázku
+ Url
+ OK
+ Nastavení Imgur
+ Došlo k chybě při nahrávání na Imgur:
+ Nahrát na Imgur
+ Obrázek byl úspěšně odeslán na Imgur!
+ Použijte odkaz na stránku namísto odkaz na obrázek do schránky
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-de-DE.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-de-DE.xml
similarity index 96%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-de-DE.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-de-DE.xml
index 2fc7ffd06..a4c50d955 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-de-DE.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-de-DE.xml
@@ -1,50 +1,50 @@
-
-
-
-
- Zu Imgur hochladen
-
-
- Imgur Einstellungen
-
-
- Url
-
-
- OK
-
-
- Cancel
-
-
- Das Hochladen zu Imgur war erfolgreich.
-
-
- Es gab einen Fehler beim Hochladen zu Imgur:
-
-
- Bildformat
-
-
- Übermittle Daten zu Imgur. Bitte warten...
-
-
- Sind Sie sicher das sie das Bild {0} von Imgur löschen möchte?
-
-
- Sind Sie sicher das sie den lokalen Imgur Verlauf löschen möchte?
-
-
- Imgur {0} löschen
-
-
- Benutze der Seite-URL statt Bild-URL im Zwischenablage
-
-
- Verlauf
-
-
- Einstellungen
-
-
+
+
+
+
+ Zu Imgur hochladen
+
+
+ Imgur Einstellungen
+
+
+ Url
+
+
+ OK
+
+
+ Cancel
+
+
+ Das Hochladen zu Imgur war erfolgreich.
+
+
+ Es gab einen Fehler beim Hochladen zu Imgur:
+
+
+ Bildformat
+
+
+ Übermittle Daten zu Imgur. Bitte warten...
+
+
+ Sind Sie sicher das sie das Bild {0} von Imgur löschen möchte?
+
+
+ Sind Sie sicher das sie den lokalen Imgur Verlauf löschen möchte?
+
+
+ Imgur {0} löschen
+
+
+ Benutze der Seite-URL statt Bild-URL im Zwischenablage
+
+
+ Verlauf
+
+
+ Einstellungen
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-en-US.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-en-US.xml
similarity index 92%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-en-US.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-en-US.xml
index aa9883ef9..22eb3840e 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-en-US.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-en-US.xml
@@ -1,53 +1,53 @@
-
-
-
-
- Upload to Imgur
-
-
- Imgur settings
-
-
- Url
-
-
- OK
-
-
- Cancel
-
-
- Successfully uploaded image to Imgur!
-
-
- An error occurred while uploading to Imgur:
-
-
- Image format
-
-
- Communicating with Imgur. Please wait...
-
-
- Are you sure you want to delete the image {0} from Imgur?
-
-
- Are you sure you want to delete the local Imgur history?
-
-
- Delete Imgur {0}
-
-
- Use anonymous access
-
-
- Use page link instead of image link on clipboard
-
-
- History
-
-
- Configure
-
-
+
+
+
+
+ Upload to Imgur
+
+
+ Imgur settings
+
+
+ Url
+
+
+ OK
+
+
+ Cancel
+
+
+ Successfully uploaded image to Imgur!
+
+
+ An error occured while uploading to Imgur:
+
+
+ Image format
+
+
+ Communicating with Imgur. Please wait...
+
+
+ Are you sure you want to delete the image {0} from Imgur?
+
+
+ Are you sure you want to delete the local Imgur history?
+
+
+ Delete Imgur {0}
+
+
+ Use anonymous access
+
+
+ Use page link instead of image link on clipboard
+
+
+ History
+
+
+ Configure
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-fr-FR.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-fr-FR.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-fr-FR.xml
index 578c10215..29f191e67 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-fr-FR.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-fr-FR.xml
@@ -1,20 +1,20 @@
-
-
-
- Annuler
- Êtes-vous sûr(e) de vouloir supprimer l'historique local de Imgur ?
- Communication en cours avec Imgur. Veuillez patienter...
- Configurer
- Êtes-vous sûr(e) de vouloir supprimer l'image {0} de Imgur ?
- Supprimer Imgur {0}
- Historique
- Format image
- Url
- OK
- Paramètres Imgur
- Une erreur est survenue lors du téléversement vers Imgur :
- Téléverser vers Imgur
- Image téléversée vers Imgur avec succès !
- Utiliser le lien de la page au lieu du lien de l'image dans le presse-papier
-
+
+
+
+ Annuler
+ Êtes-vous sûr(e) de vouloir supprimer l'historique local de Imgur ?
+ Communication en cours avec Imgur. Veuillez patienter...
+ Configurer
+ Êtes-vous sûr(e) de vouloir supprimer l'image {0} de Imgur ?
+ Supprimer Imgur {0}
+ Historique
+ Format image
+ Url
+ OK
+ Paramètres Imgur
+ Une erreur est survenue lors du téléversement vers Imgur :
+ Téléverser vers Imgur
+ Image téléversée vers Imgur avec succès !
+ Utiliser le lien de la page au lieu du lien de l'image dans le presse-papier
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-id-ID.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-id-ID.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-id-ID.xml
index 43823cf71..c73051357 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-id-ID.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-id-ID.xml
@@ -1,21 +1,21 @@
-
-
-
- Gunakan akses anonim
- Batal
- Apakah anda benar-benar ingin menghapus riwayat lokal Imgur?
- Menyambungkan ke Imgur. Tunggu sebentar...
- Pengaturan
- Apakah anda benar-benar ingin menghapus gambar {0} dari Imgur?
- Hapus Imgur {0}
- Riwayat
- Format gambar
- Url
- Oke
- Setelan Imgur
- Kesalahan terjadi ketika mengunggah ke Imgur:
- Unggah ke Imgur
- Gambar berhasil diunggah ke Imgur!
- Gunakan link laman daripada link gambar di papanklip
-
+
+
+
+ Gunakan akses anonim
+ Batal
+ Apakah anda benar-benar ingin menghapus riwayat lokal Imgur?
+ Menyambungkan ke Imgur. Tunggu sebentar...
+ Pengaturan
+ Apakah anda benar-benar ingin menghapus gambar {0} dari Imgur?
+ Hapus Imgur {0}
+ Riwayat
+ Format gambar
+ Url
+ Oke
+ Setelan Imgur
+ Kesalahan terjadi ketika mengunggah ke Imgur:
+ Unggah ke Imgur
+ Gambar berhasil diunggah ke Imgur!
+ Gunakan link laman daripada link gambar di papanklip
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-it-IT.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-it-IT.xml
similarity index 64%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-it-IT.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-it-IT.xml
index b0d86a5d0..f3bb72df1 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-it-IT.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-it-IT.xml
@@ -1,53 +1,50 @@
-
-
-
-
- Carica su Imgur
-
-
- Impostazioni Imgur
-
-
- URL
-
-
- OK
-
-
- Annulla
-
-
- caricamento immagine su Imgur completato!
-
-
- Si è verificato un problema durante il caricamento:
-
-
- Formato immagine
-
-
- Comunicazione con Imgur...
-
-
- Sei sicuro di voler eliminare l'immagine {0} da Imgur?
-
-
- Sei sicuro di voler eliminare la cronologia locale di Imgur?
-
-
- Elimina Imgur {0}
-
-
- Usa accesso anonimo
-
-
- Negli Appunti usa collegamento pagina invece di quello all'immagine
-
-
- Cronologia
-
-
- Impostazioni
-
-
+
+
+
+
+ Carica su Imgur
+
+
+ Impostazioni Imgur
+
+
+ Url
+
+
+ OK
+
+
+ Annulla
+
+
+ Immagine caricata correttamente su Imgur!
+
+
+ Si è verificato un problema durante il collegamento:
+
+
+ Formato immagine
+
+
+ Comunicazione con Imgur. Attendere prego...
+
+
+ Sei sicuro si voler eliminare l'immagine {0} da Imgur?
+
+
+ Sei sicuro si voler eliminare la cronologia locale di Imgur?
+
+
+ Elimina Imgur {0}
+
+
+ Usa il collegamento alla pagina invece di quello all'immagine su appunti
+
+
+ Cronologia
+
+
+ Configurazione
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-kab-DZ.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-kab-DZ.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-ko-KR.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-ko-KR.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-lv-LV.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-lv-LV.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-nl-NL.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-nl-NL.xml
similarity index 96%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-nl-NL.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-nl-NL.xml
index 9550bd2b5..a3692776e 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-nl-NL.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-nl-NL.xml
@@ -1,50 +1,50 @@
-
-
-
-
- Naar Imgur uploaden
-
-
- Imgur instellingen
-
-
- Url
-
-
- OK
-
-
- Afbreken
-
-
- Het uploaden naar Imgur is geslaagt!
-
-
- Tijdens het uploaden naar Imgur is een fout opgetreden:
-
-
- Beeld formaat
-
-
- Data overdraging naar Imgur, wachten AUB...
-
-
- Weet U zeker dat U het beeld {0} van Imgur verwijderen wilt?
-
-
- Weet U zeker dat U de locale Imgur historie verwijderen wilt?
-
-
- Imgur {0} verwijderen
-
-
- Kopieer de pagina link in plaats van de beeld link in het klembord
-
-
- Verloop
-
-
- Instellingen
-
-
+
+
+
+
+ Naar Imgur uploaden
+
+
+ Imgur instellingen
+
+
+ Url
+
+
+ OK
+
+
+ Afbreken
+
+
+ Het uploaden naar Imgur is geslaagt!
+
+
+ Tijdens het uploaden naar Imgur is een fout opgetreden:
+
+
+ Beeld formaat
+
+
+ Data overdraging naar Imgur, wachten AUB...
+
+
+ Weet U zeker dat U het beeld {0} van Imgur verwijderen wilt?
+
+
+ Weet U zeker dat U de locale Imgur historie verwijderen wilt?
+
+
+ Imgur {0} verwijderen
+
+
+ Kopieer de pagina link in plaats van de beeld link in het klembord
+
+
+ Verloop
+
+
+ Instellingen
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-pl-PL.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-pl-PL.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-pl-PL.xml
index e2b6caa39..7db3a2118 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-pl-PL.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-pl-PL.xml
@@ -1,21 +1,21 @@
-
-
-
- Używaj jako niezalogowany
- Anuluj
- Na pewno chcesz usunąć historię lokalną Imgur?
- Trwa komunikacja z Imgur. Proszę czekać...
- Konfiguruj
- Na pewno chcesz usunąć obraz {0} z Imgur?
- Usuń z Imgur {0}
- Historia
- Format obrazów
- URL
- OK
- Ustawienia Imgur
- Wystąpił błąd przy wysyłaniu do Imgur:
- Wyślij do Imgur
- Wysyłanie obrazu do Imgur powiodło się!
- Kopiuj do schowka link do strony zamiast link do obrazu
-
+
+
+
+ Używaj jako niezalogowany
+ Anuluj
+ Na pewno chcesz usunąć historię lokalną Imgur?
+ Trwa komunikacja z Imgur. Proszę czekać...
+ Konfiguruj
+ Na pewno chcesz usunąć obraz {0} z Imgur?
+ Usuń z Imgur {0}
+ Historia
+ Format obrazów
+ URL
+ OK
+ Ustawienia Imgur
+ Wystąpił błąd przy wysyłaniu do Imgur:
+ Wyślij do Imgur
+ Wysyłanie obrazu do Imgur powiodło się!
+ Kopiuj do schowka link do strony zamiast link do obrazu
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-pt-PT.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-pt-PT.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-ru-RU.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-ru-RU.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-ru-RU.xml
index 2279b6c4f..719c49b3f 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-ru-RU.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-ru-RU.xml
@@ -1,21 +1,21 @@
-
-
-
- Использовать анонимный доступ
- Отмена
- Вы действительно хотите удалить местную историю Imgur?
- Взаимодействие с Imgur. Подождите...
- Настройка
- Вы действительно хотите удалить изображение {0} из Imgur?
- Удалить Imgur {0}
- История
- Формат изображения
- Url
- OK
- Imgur параметры
- Произошла ошибка при загрузке на Imgur:
- Загрузить на Imgur
- Изображение успешно загружено на Imgur!
- Использовать ссылку страницы, вместо ссылки изображения в буфере обмена
-
+
+
+
+ Использовать анонимный доступ
+ Отмена
+ Вы действительно хотите удалить местную историю Imgur?
+ Взаимодействие с Imgur. Подождите...
+ Настройка
+ Вы действительно хотите удалить изображение {0} из Imgur?
+ Удалить Imgur {0}
+ История
+ Формат изображения
+ Url
+ OK
+ Imgur параметры
+ Произошла ошибка при загрузке на Imgur:
+ Загрузить на Imgur
+ Изображение успешно загружено на Imgur!
+ Использовать ссылку страницы, вместо ссылки изображения в буфере обмена
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-sk-SK.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-sk-SK.xml
similarity index 96%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-sk-SK.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-sk-SK.xml
index bb08ee691..bc4bcfb82 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-sk-SK.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-sk-SK.xml
@@ -1,53 +1,53 @@
-
-
-
-
- Nahrať na Imgur
-
-
- Imgur nastavenia
-
-
- Url
-
-
- OK
-
-
- Zrušiť
-
-
- Obrázok bol úspešne nahraný na Imgur!
-
-
- Chyba pri nahrávaní na Imgur:
-
-
- Formát obrázku
-
-
- Prebieha komunikácia s Imgur. Čakajte prosím ...
-
-
- Chcete naozaj zmazať obrázok {0} z Imgur?
-
-
- Chcete naozaj zmazať lokálnu históriu Imgur?
-
-
- Zmazať Imgur {0}
-
-
- Použiť anonymný prístup
-
-
- Použiť odkaz stránky namiesto odkazu obrázku v schránke
-
-
- História
-
-
- Konfigurácia
-
-
+
+
+
+
+ Nahrať na Imgur
+
+
+ Imgur nastavenia
+
+
+ Url
+
+
+ OK
+
+
+ Zrušiť
+
+
+ Obrázok bol úspešne nahraný na Imgur!
+
+
+ Chyba pri nahrávaní na Imgur:
+
+
+ Formát obrázku
+
+
+ Prebieha komunikácia s Imgur. Čakajte prosím ...
+
+
+ Chcete naozaj zmazať obrázok {0} z Imgur?
+
+
+ Chcete naozaj zmazať lokálnu históriu Imgur?
+
+
+ Zmazať Imgur {0}
+
+
+ Použiť anonymný prístup
+
+
+ Použiť odkaz stránky namiesto odkazu obrázku v schránke
+
+
+ História
+
+
+ Konfigurácia
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-sr-RS.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-sr-RS.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-sr-RS.xml
index 521257ead..f1db2a0ba 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-sr-RS.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-sr-RS.xml
@@ -1,21 +1,21 @@
-
-
-
- Анонимни приступ
- Откажи
- Желите ли да обришете локалну историју Имиџера?
- Комуницирам с Имиџером. Сачекајте…
- Поставке
- Желите ли да обришете слику {0} са Имиџера?
- Обриши Имиџер {0}
- Историја
- Формат слике:
- Адреса
- У реду
- Поставке Имиџера
- Дошло је до грешке при отпремању на Имиџер:
- Отпреми на Имиџер
- Слика је успешно отпремљена на Имиџер.
- Веза ка страници уместо везе ка слици у остави
-
+
+
+
+ Анонимни приступ
+ Откажи
+ Желите ли да обришете локалну историју Имиџера?
+ Комуницирам с Имиџером. Сачекајте…
+ Поставке
+ Желите ли да обришете слику {0} са Имиџера?
+ Обриши Имиџер {0}
+ Историја
+ Формат слике:
+ Адреса
+ У реду
+ Поставке Имиџера
+ Дошло је до грешке при отпремању на Имиџер:
+ Отпреми на Имиџер
+ Слика је успешно отпремљена на Имиџер.
+ Веза ка страници уместо везе ка слици у остави
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-sv-SE.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-sv-SE.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-uk-UA.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-uk-UA.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-uk-UA.xml
index df5ff014a..8152b94fe 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-uk-UA.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-uk-UA.xml
@@ -1,21 +1,21 @@
-
-
-
- Вивантажити на Imgur
- Параметри Imgur
- Посилання
- Гаразд
- Скасувати
- Зображення вдало вивантажено на Imgur!
- Відбулась помилка при вивантаженні зображення на Imgur:
- Формат зображення
- З’єднання з Imgur. Будь ласка, зачекайте...
- Чи дійсно Ви хочете видалити зображення {0} з Imgur?
- Чи дійсно Ви хочете видалити локальну історію Imgur?
- Видалити Imgur {0}
- Використовувати анонімний доступ
- Використовувати посилання на сторінку замість посилання на зображення
- Історія
- Налаштувати
-
-
+
+
+
+ Вивантажити на Imgur
+ Параметри Imgur
+ Посилання
+ Гаразд
+ Скасувати
+ Зображення вдало вивантажено на Imgur!
+ Відбулась помилка при вивантаженні зображення на Imgur:
+ Формат зображення
+ З’єднання з Imgur. Будь ласка, зачекайте...
+ Чи дійсно Ви хочете видалити зображення {0} з Imgur?
+ Чи дійсно Ви хочете видалити локальну історію Imgur?
+ Видалити Imgur {0}
+ Використовувати анонімний доступ
+ Використовувати посилання на сторінку замість посилання на зображення
+ Історія
+ Налаштувати
+
+
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-CN.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-zh-CN.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-CN.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-zh-CN.xml
index acb0b6426..ce0541241 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-CN.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-zh-CN.xml
@@ -1,21 +1,21 @@
-
-
-
- 使用匿名连接
- 取消
- 是否真的要删除本地的Imgur历史记录?
- 正在连接到Imgur。请稍后...
- 配置
- 是否真的要从Imgur上删除图片{0}?
- 删除 Imgur {0}
- 历史记录
- 图片格式
- 网址
- 确认
- Imgur设置
- 上传图片到Imgur时发生错误:
- 上传到Imgur
- 图片已成功上传到了Imgur!
- 当复制链接到剪贴板时,使用页面的网址而不是图片的网址
-
+
+
+
+ 使用匿名连接
+ 取消
+ 是否真的要删除本地的Imgur历史记录?
+ 正在连接到Imgur。请稍后...
+ 配置
+ 是否真的要从Imgur上删除图片{0}?
+ 删除 Imgur {0}
+ 历史记录
+ 图片格式
+ 网址
+ 确认
+ Imgur设置
+ 上传图片到Imgur时发生错误:
+ 上传到Imgur
+ 图片已成功上传到了Imgur!
+ 当复制链接到剪贴板时,使用页面的网址而不是图片的网址
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-TW.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-TW.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-zh-TW.xml
index 5a743870a..1fe08f257 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-zh-TW.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-zh-TW.xml
@@ -1,21 +1,21 @@
-
-
-
- 使用匿名存取
- 取消
- 您確定要刪除本機 Imgur 歷程記錄嗎?
- 正在與 Imgur 通訊,請稍候...
- 組態
- 您確定要從 Imgur 刪除圖片 {0} 嗎?
- 刪除 Imgur {0}
- 歷程記錄
- 圖片格式
- URL
- 確定
- Imgur 設定
- 上傳到 Imgur 時發生錯誤:
- 上傳到 Imgur
- 上傳圖片到 Imgur 成功!
- 在剪貼簿使用頁面連結而不是圖片連結
-
+
+
+
+ 使用匿名存取
+ 取消
+ 您確定要刪除本機 Imgur 歷程記錄嗎?
+ 正在與 Imgur 通訊,請稍候...
+ 組態
+ 您確定要從 Imgur 刪除圖片 {0} 嗎?
+ 刪除 Imgur {0}
+ 歷程記錄
+ 圖片格式
+ URL
+ 確定
+ Imgur 設定
+ 上傳到 Imgur 時發生錯誤:
+ 上傳到 Imgur
+ 上傳圖片到 Imgur 成功!
+ 在剪貼簿使用頁面連結而不是圖片連結
+
\ No newline at end of file
diff --git a/GreenshotImgurPlugin/Properties/AssemblyInfo.cs b/GreenshotImgurPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..f0234c49c
--- /dev/null
+++ b/GreenshotImgurPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GreenshotImgurPlugin")]
+[assembly: AssemblyDescription("A plugin to upload images to Imgur")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Imgur Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotImgurPlugin.ImgurPlugin", true)]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
\ No newline at end of file
diff --git a/GreenshotImgurPlugin/packages.config b/GreenshotImgurPlugin/packages.config
new file mode 100644
index 000000000..6003a80e6
--- /dev/null
+++ b/GreenshotImgurPlugin/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/AsyncMemoryCache.cs b/GreenshotJiraPlugin/AsyncMemoryCache.cs
new file mode 100644
index 000000000..479bbbd20
--- /dev/null
+++ b/GreenshotJiraPlugin/AsyncMemoryCache.cs
@@ -0,0 +1,246 @@
+#region Dapplo 2016 - GNU Lesser General Public License
+
+// Dapplo - building blocks for .NET applications
+// Copyright (C) 2016 Dapplo
+//
+// For more information see: http://dapplo.net/
+// Dapplo repositories are hosted on GitHub: https://github.com/dapplo
+//
+// This file is part of Dapplo.Utils
+//
+// Dapplo.Utils is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Dapplo.Utils is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have a copy of the GNU Lesser General Public License
+// along with Dapplo.Utils. If not, see .
+
+#endregion
+
+#region Usings
+
+using System;
+using System.Runtime.Caching;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Log;
+
+#endregion
+
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// This abstract class builds a base for a simple async memory cache.
+ ///
+ /// Type for the key
+ /// Type for the stored value
+ public abstract class AsyncMemoryCache where TResult : class
+ {
+ private static readonly Task EmptyValueTask = Task.FromResult(null);
+ private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
+ private readonly MemoryCache _cache = new MemoryCache(Guid.NewGuid().ToString());
+ private readonly LogSource _log = new LogSource();
+
+ ///
+ /// Set the timespan for items to expire.
+ ///
+ public TimeSpan? ExpireTimeSpan { get; set; }
+
+ ///
+ /// Set the timespan for items to slide.
+ ///
+ public TimeSpan? SlidingTimeSpan { get; set; }
+
+ ///
+ /// Specifies if the RemovedCallback needs to be called
+ /// If this is active, ActivateUpdateCallback should be false
+ ///
+ protected bool ActivateRemovedCallback { get; set; } = true;
+
+ ///
+ /// Specifies if the UpdateCallback needs to be called.
+ /// If this is active, ActivateRemovedCallback should be false
+ ///
+ protected bool ActivateUpdateCallback { get; set; } = false;
+
+ ///
+ /// Implement this method, it should create an instance of TResult via the supplied TKey.
+ ///
+ /// TKey
+ /// CancellationToken
+ /// TResult
+ protected abstract Task CreateAsync(TKey key, CancellationToken cancellationToken = default(CancellationToken));
+
+ ///
+ /// Creates a key under which the object is stored or retrieved, default is a toString on the object.
+ ///
+ /// TKey
+ /// string
+ protected virtual string CreateKey(TKey keyObject)
+ {
+ return keyObject.ToString();
+ }
+
+ ///
+ /// Get an element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CancellationToken
+ /// TResult
+ public async Task DeleteAsync(TKey keyObject, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ await _semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false);
+ try
+ {
+ _cache.Remove(key);
+ }
+ finally
+ {
+ _semaphoreSlim.Release();
+ }
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available return null.
+ /// You probably want to call GetOrCreateAsync
+ ///
+ /// object for the key
+ /// Task with TResult, null if no value
+ public Task GetAsync(TKey keyObject)
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? EmptyValueTask;
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CancellationToken
+ /// Task with TResult
+ public Task GetOrCreateAsync(TKey keyObject, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, null, cancellationToken);
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CacheItemPolicy for when you want more control over the item
+ /// CancellationToken
+ /// Task with TResult
+ public Task GetOrCreateAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, cacheItemPolicy, cancellationToken);
+ }
+
+ ///
+ /// This takes care of the real async part of the code.
+ ///
+ ///
+ /// CacheItemPolicy for when you want more control over the item
+ /// CancellationToken
+ /// TResult
+ private async Task GetOrCreateInternalAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ var completionSource = new TaskCompletionSource();
+
+ if (cacheItemPolicy == null)
+ {
+ cacheItemPolicy = new CacheItemPolicy
+ {
+ AbsoluteExpiration = ExpireTimeSpan.HasValue ? DateTimeOffset.Now.Add(ExpireTimeSpan.Value) : ObjectCache.InfiniteAbsoluteExpiration,
+ SlidingExpiration = SlidingTimeSpan ?? ObjectCache.NoSlidingExpiration
+ };
+ if (ActivateUpdateCallback)
+ {
+ cacheItemPolicy.UpdateCallback = UpdateCallback;
+ }
+ if (ActivateRemovedCallback)
+ {
+ cacheItemPolicy.RemovedCallback = RemovedCallback;
+ }
+ }
+
+ var result = _cache.AddOrGetExisting(key, completionSource.Task, cacheItemPolicy) as Task;
+ // Test if we got an existing object or our own
+ if (result != null && !completionSource.Task.Equals(result))
+ {
+ return await result.ConfigureAwait(false);
+ }
+
+ await _semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false);
+ try
+ {
+ result = _cache.AddOrGetExisting(key, completionSource.Task, cacheItemPolicy) as Task;
+ if (result != null && !completionSource.Task.Equals(result))
+ {
+ return await result.ConfigureAwait(false);
+ }
+
+ // Now, start the background task, which will set the completionSource with the correct response
+ // ReSharper disable once MethodSupportsCancellation
+ // ReSharper disable once UnusedVariable
+ var ignoreBackgroundTask = Task.Run(async () =>
+ {
+ try
+ {
+ var backgroundResult = await CreateAsync(keyObject, cancellationToken).ConfigureAwait(false);
+ completionSource.TrySetResult(backgroundResult);
+ }
+ catch (TaskCanceledException)
+ {
+ completionSource.TrySetCanceled();
+ }
+ catch (Exception ex)
+ {
+ completionSource.TrySetException(ex);
+ }
+ });
+ }
+ finally
+ {
+ _semaphoreSlim.Release();
+ }
+
+ return await completionSource.Task.ConfigureAwait(false);
+ }
+
+ ///
+ /// Override to know when an item is removed, make sure to configure ActivateUpdateCallback / ActivateRemovedCallback
+ ///
+ /// CacheEntryRemovedArguments
+ protected virtual void RemovedCallback(CacheEntryRemovedArguments cacheEntryRemovedArguments)
+ {
+ _log.Verbose().WriteLine("Item {0} removed due to {1}.", cacheEntryRemovedArguments.CacheItem.Key, cacheEntryRemovedArguments.RemovedReason);
+ var disposable = cacheEntryRemovedArguments.CacheItem.Value as IDisposable;
+ if (disposable != null)
+ {
+ _log.Debug().WriteLine("Disposed cached item.");
+ disposable.Dispose();
+ }
+ }
+
+ ///
+ /// Override to modify the cache behaviour when an item is about to be removed, make sure to configure
+ /// ActivateUpdateCallback / ActivateRemovedCallback
+ ///
+ /// CacheEntryUpdateArguments
+ protected virtual void UpdateCallback(CacheEntryUpdateArguments cacheEntryUpdateArguments)
+ {
+ _log.Verbose().WriteLine("Update request for {0} due to {1}.", cacheEntryUpdateArguments.Key, cacheEntryUpdateArguments.RemovedReason);
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/Forms/JiraForm.Designer.cs b/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
similarity index 93%
rename from src/Greenshot.Plugin.Jira/Forms/JiraForm.Designer.cs
rename to GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
index c233ab6f1..c19bf181d 100644
--- a/src/Greenshot.Plugin.Jira/Forms/JiraForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,9 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-namespace Greenshot.Plugin.Jira.Forms {
+namespace GreenshotJiraPlugin.Forms {
partial class JiraForm {
///
/// Required designer variable.
@@ -71,6 +71,7 @@ namespace Greenshot.Plugin.Jira.Forms {
//
// label_jirafilter
//
+ this.label_jirafilter.AutoSize = true;
this.label_jirafilter.Location = new System.Drawing.Point(14, 14);
this.label_jirafilter.Name = "label_jirafilter";
this.label_jirafilter.Size = new System.Drawing.Size(52, 13);
@@ -79,6 +80,7 @@ namespace Greenshot.Plugin.Jira.Forms {
//
// label_jira
//
+ this.label_jira.AutoSize = true;
this.label_jira.Location = new System.Drawing.Point(14, 41);
this.label_jira.Name = "label_jira";
this.label_jira.Size = new System.Drawing.Size(30, 13);
@@ -125,6 +127,7 @@ namespace Greenshot.Plugin.Jira.Forms {
// label_filename
//
this.label_filename.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.label_filename.AutoSize = true;
this.label_filename.Location = new System.Drawing.Point(14, 222);
this.label_filename.Name = "label_filename";
this.label_filename.Size = new System.Drawing.Size(49, 13);
@@ -134,6 +137,7 @@ namespace Greenshot.Plugin.Jira.Forms {
// label_comment
//
this.label_comment.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.label_comment.AutoSize = true;
this.label_comment.Location = new System.Drawing.Point(14, 248);
this.label_comment.Name = "label_comment";
this.label_comment.Size = new System.Drawing.Size(51, 13);
@@ -163,6 +167,7 @@ namespace Greenshot.Plugin.Jira.Forms {
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(14, 274);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(23, 13);
diff --git a/GreenshotJiraPlugin/Forms/JiraForm.cs b/GreenshotJiraPlugin/Forms/JiraForm.cs
new file mode 100644
index 000000000..f4a47a347
--- /dev/null
+++ b/GreenshotJiraPlugin/Forms/JiraForm.cs
@@ -0,0 +1,234 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Globalization;
+using System.Windows.Forms;
+using Dapplo.Jira.Entities;
+using Greenshot.IniFile;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace GreenshotJiraPlugin.Forms {
+ public partial class JiraForm : Form {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraForm));
+ private readonly JiraConnector _jiraConnector;
+ private Issue _selectedIssue;
+ private readonly GreenshotColumnSorter _columnSorter;
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ public JiraForm(JiraConnector jiraConnector) {
+ InitializeComponent();
+ Icon = GreenshotResources.getGreenshotIcon();
+ AcceptButton = uploadButton;
+ CancelButton = cancelButton;
+
+ InitializeComponentText();
+
+ _columnSorter = new GreenshotColumnSorter();
+ jiraListView.ListViewItemSorter = _columnSorter;
+
+ _jiraConnector = jiraConnector;
+
+ ChangeModus(false);
+
+ uploadButton.Enabled = false;
+ Load += OnLoad;
+ }
+
+ private async void OnLoad(object sender, EventArgs eventArgs)
+ {
+ try
+ {
+ if (!_jiraConnector.IsLoggedIn)
+ {
+ await _jiraConnector.LoginAsync();
+ }
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show(Language.GetFormattedString("jira", LangKey.login_error, e.Message));
+ }
+ if (_jiraConnector.IsLoggedIn)
+ {
+ var filters = await _jiraConnector.GetFavoriteFiltersAsync();
+ if (filters.Count > 0)
+ {
+ foreach (var filter in filters)
+ {
+ jiraFilterBox.Items.Add(filter);
+ }
+ jiraFilterBox.SelectedIndex = 0;
+ }
+ ChangeModus(true);
+ if (_jiraConnector.Monitor.RecentJiras.Any())
+ {
+ _selectedIssue = _jiraConnector.Monitor.RecentJiras.First().JiraIssue;
+ jiraKey.Text = _selectedIssue.Key;
+ uploadButton.Enabled = true;
+ }
+ }
+ }
+
+ private void InitializeComponentText() {
+ label_jirafilter.Text = Language.GetString("jira", LangKey.label_jirafilter);
+ label_comment.Text = Language.GetString("jira", LangKey.label_comment);
+ label_filename.Text = Language.GetString("jira", LangKey.label_filename);
+ }
+
+ private void ChangeModus(bool enabled) {
+ jiraFilterBox.Enabled = enabled;
+ jiraListView.Enabled = enabled;
+ jiraFilenameBox.Enabled = enabled;
+ jiraCommentBox.Enabled = enabled;
+ }
+
+ public void SetFilename(string filename) {
+ jiraFilenameBox.Text = filename;
+ }
+
+ public Issue GetJiraIssue() {
+ return _selectedIssue;
+ }
+
+ public async Task UploadAsync(IBinaryContainer attachment) {
+ attachment.Filename = jiraFilenameBox.Text;
+ await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment);
+
+ if (!string.IsNullOrEmpty(jiraCommentBox.Text)) {
+ await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text);
+ }
+ }
+
+ private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (_jiraConnector.IsLoggedIn) {
+
+ uploadButton.Enabled = false;
+ var filter = (Filter)jiraFilterBox.SelectedItem;
+ if (filter == null) {
+ return;
+ }
+ IList issues = null;
+ try
+ {
+ issues = await _jiraConnector.SearchAsync(filter);
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex);
+ MessageBox.Show(this, ex.Message, "Error in filter", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ jiraListView.Items.Clear();
+ if (issues?.Count > 0) {
+ jiraListView.Columns.Clear();
+ LangKey[] columns = { LangKey.column_issueType, LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary };
+ foreach (LangKey column in columns)
+ {
+ string translation;
+ if (!Language.TryGetString("jira", column, out translation))
+ {
+ translation = "";
+ }
+ jiraListView.Columns.Add(translation);
+ }
+ var imageList = new ImageList {
+ ImageSize = CoreConfig.IconSize
+ };
+ jiraListView.SmallImageList = imageList;
+ jiraListView.LargeImageList = imageList;
+
+ foreach (var issue in issues) {
+ var item = new ListViewItem
+ {
+ Tag = issue
+ };
+ try
+ {
+ var issueIcon = await _jiraConnector.GetIssueTypeBitmapAsync(issue);
+ imageList.Images.Add(issueIcon);
+ item.ImageIndex = imageList.Images.Count - 1;
+ }
+ catch (Exception ex)
+ {
+ Log.Warn("Problem loading issue type, ignoring", ex);
+ }
+
+ item.SubItems.Add(issue.Key);
+ item.SubItems.Add(issue.Fields.Created.ToString("d", DateTimeFormatInfo.InvariantInfo));
+ item.SubItems.Add(issue.Fields.Assignee?.DisplayName);
+ item.SubItems.Add(issue.Fields.Reporter?.DisplayName);
+ item.SubItems.Add(issue.Fields.Summary);
+ jiraListView.Items.Add(item);
+ for (int i = 0; i < columns.Length; i++)
+ {
+ jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
+ }
+ jiraListView.Invalidate();
+ jiraListView.Update();
+ }
+
+ jiraListView.Refresh();
+ }
+ }
+ }
+
+ private void JiraListView_SelectedIndexChanged(object sender, EventArgs e) {
+ if (jiraListView.SelectedItems.Count > 0) {
+ _selectedIssue = (Issue)jiraListView.SelectedItems[0].Tag;
+ jiraKey.Text = _selectedIssue.Key;
+ uploadButton.Enabled = true;
+ } else {
+ uploadButton.Enabled = false;
+ }
+ }
+
+ private void JiraListView_ColumnClick(object sender, ColumnClickEventArgs e) {
+ // Determine if clicked column is already the column that is being sorted.
+ if (e.Column == _columnSorter.SortColumn) {
+ // Reverse the current sort direction for this column.
+ _columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
+ } else {
+ // Set the column number that is to be sorted; default to ascending.
+ _columnSorter.SortColumn = e.Column;
+ _columnSorter.Order = SortOrder.Ascending;
+ }
+
+ // Perform the sort with these new sort options.
+ jiraListView.Sort();
+ }
+
+ private async void JiraKeyTextChanged(object sender, EventArgs e) {
+ string jiranumber = jiraKey.Text;
+ uploadButton.Enabled = false;
+ int dashIndex = jiranumber.IndexOf('-');
+ if (dashIndex > 0 && jiranumber.Length > dashIndex+1) {
+ _selectedIssue = await _jiraConnector.GetIssueAsync(jiraKey.Text);
+ if (_selectedIssue != null) {
+ uploadButton.Enabled = true;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Greenshot.Editor/Helpers/IDoubleProcessor.cs b/GreenshotJiraPlugin/Forms/JiraFormBase.cs
similarity index 69%
rename from src/Greenshot.Editor/Helpers/IDoubleProcessor.cs
rename to GreenshotJiraPlugin/Forms/JiraFormBase.cs
index beb426c68..503304e66 100644
--- a/src/Greenshot.Editor/Helpers/IDoubleProcessor.cs
+++ b/GreenshotJiraPlugin/Forms/JiraFormBase.cs
@@ -1,8 +1,8 @@
-/*
+/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,13 +16,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-namespace Greenshot.Editor.Helpers
-{
- public interface IDoubleProcessor
- {
- double Process(double d);
- }
-}
\ No newline at end of file
+using GreenshotPlugin.Controls;
+
+namespace GreenshotJiraPlugin.Forms {
+ public class JiraFormBase : GreenshotForm {
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs b/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
similarity index 79%
rename from src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs
rename to GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
index 6903f74fd..10e184dc4 100644
--- a/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Jira.Forms {
+namespace GreenshotJiraPlugin.Forms {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,12 +46,12 @@ namespace Greenshot.Plugin.Jira.Forms {
///
private void InitializeComponent()
{
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.label_url = new GreenshotLabel();
- this.textBoxUrl = new GreenshotTextBox();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.label_url = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textBoxUrl = new GreenshotPlugin.Controls.GreenshotTextBox();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
this.SuspendLayout();
//
// buttonOK
@@ -94,7 +91,7 @@ namespace Greenshot.Plugin.Jira.Forms {
this.textBoxUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.textBoxUrl.Location = new System.Drawing.Point(164, 21);
this.textBoxUrl.Name = "textBoxUrl";
- this.textBoxUrl.PropertyName = nameof(JiraConfiguration.Url);
+ this.textBoxUrl.PropertyName = "Url";
this.textBoxUrl.SectionName = "Jira";
this.textBoxUrl.Size = new System.Drawing.Size(214, 20);
this.textBoxUrl.TabIndex = 6;
@@ -105,7 +102,7 @@ namespace Greenshot.Plugin.Jira.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(164, 47);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(JiraConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Jira";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(214, 21);
this.combobox_uploadimageformat.TabIndex = 8;
@@ -139,11 +136,11 @@ namespace Greenshot.Plugin.Jira.Forms {
this.PerformLayout();
}
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotTextBox textBoxUrl;
- private GreenshotLabel label_url;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotTextBox textBoxUrl;
+ private GreenshotPlugin.Controls.GreenshotLabel label_url;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
}
}
diff --git a/GreenshotJiraPlugin/Forms/SettingsForm.cs b/GreenshotJiraPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..7d128ea8a
--- /dev/null
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,37 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotJiraPlugin.Forms {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : JiraFormBase {
+ public SettingsForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = buttonOK;
+ CancelButton = buttonCancel;
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
new file mode 100644
index 000000000..b29d53140
--- /dev/null
+++ b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
@@ -0,0 +1,183 @@
+
+
+
+
+ {19FEEF09-313F-43C7-819D-F1BCA782B08B}
+ Library
+ GreenshotJiraPlugin
+ GreenshotJiraPlugin
+ v4.5
+ Properties
+ False
+ False
+ 4
+ false
+ OnBuildSuccess
+
+
+
+ 3.5
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+
+ ..\packages\Dapplo.HttpExtensions.0.6.17\lib\net45\Dapplo.HttpExtensions.dll
+ True
+
+
+ ..\packages\Dapplo.Jira.0.5.12\lib\net45\Dapplo.Jira.dll
+ True
+
+
+ ..\packages\Dapplo.Log.1.0.23\lib\net45\Dapplo.Log.dll
+ True
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+ ..\packages\Svg.2.3.0\lib\net35\Svg.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ JiraForm.cs
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
+ JiraPlugin.cs
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}
+ Greenshot
+
+
+
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+"$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+del /q /s "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"\*
+
+if "$(ConfigurationName)" == "Release" (
+ ..\..\..\packages\LibZ.Tool.1.2.0.0\tools\libz.exe inject-dll --assembly $(ProjectDir)bin\$(Configuration)\$(TargetFileName) --include $(ProjectDir)bin\$(Configuration)\dapplo*.dll --include $(ProjectDir)bin\$(Configuration)\svg.dll --move
+)
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+
+if "$(ConfigurationName)" == "Debug" (
+ copy "$(ProjectDir)bin\$(Configuration)\Dapplo.*" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+ copy "$(ProjectDir)bin\$(Configuration)\Svg.dll" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+ copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+ False
+ Off
+ 4194304
+ x86
+ 4096
+
+
+ False
+ Off
+ 4194304
+ AnyCPU
+ 4096
+
+
+ DEBUG;TRACE
+ False
+ True
+ Full
+ true
+
+
+ TRACE
+ True
+ False
+ None
+ false
+
+
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs b/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs
new file mode 100644
index 000000000..6ec8878fd
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs
@@ -0,0 +1,50 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// Event arguments for the TitleChangeEvent
+ ///
+ public class TitleChangeEventArgs : EventArgs
+ {
+ ///
+ /// HWnd of the window which has a changed title
+ ///
+ public IntPtr HWnd
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Title which is changed
+ ///
+ public string Title
+ {
+ get;
+ set;
+ }
+ }
+
+}
diff --git a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs b/GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs
similarity index 52%
rename from src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs
rename to GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs
index 4cb0e6141..29847a1e5 100644
--- a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs
+++ b/GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs
@@ -1,9 +1,9 @@
/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
*
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,14 +16,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Dropbox.Forms
+namespace GreenshotJiraPlugin.Hooking
{
- public class DropboxForm : GreenshotForm
- {
- }
+ ///
+ /// Delegate for the title change event
+ ///
+ ///
+ public delegate void TitleChangeEventDelegate(TitleChangeEventArgs eventArgs);
}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs b/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs
new file mode 100644
index 000000000..e2be9d0b0
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs
@@ -0,0 +1,152 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// The WinEventHook can register handlers to become important windows events
+ /// This makes it possible to know a.o. when a window is created, moved, updated and closed.
+ ///
+ public class WindowsEventHook : IDisposable
+ {
+ private readonly WinEventDelegate _winEventHandler;
+ private GCHandle _gcHandle;
+
+ ///
+ /// Used with Register hook
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public delegate void WinEventHandler(WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+
+ ///
+ /// Create a WindowsEventHook object
+ ///
+ public WindowsEventHook()
+ {
+ _winEventHandler = WinEventDelegateHandler;
+ _gcHandle = GCHandle.Alloc(_winEventHandler);
+ }
+
+ #region native code
+ [DllImport("user32", SetLastError = true)]
+ private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
+ [DllImport("user32", SetLastError = true)]
+ private static extern IntPtr SetWinEventHook(WinEvent eventMin, WinEvent eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, int idProcess, int idThread, WinEventHookFlags dwFlags);
+
+ ///
+ /// Used with SetWinEventHook
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+ #endregion
+
+ private readonly IDictionary _winEventHandlers = new Dictionary();
+
+ ///
+ /// Are hooks active?
+ ///
+ public bool IsHooked => _winEventHandlers.Count > 0;
+
+ ///
+ /// Hook a WinEvent
+ ///
+ ///
+ ///
+ /// true if success
+ public void Hook(WinEvent winEvent, WinEventHandler winEventHandler)
+ {
+ Hook(winEvent, winEvent, winEventHandler);
+ }
+
+ ///
+ /// Hook a WinEvent
+ ///
+ ///
+ ///
+ ///
+ public void Hook(WinEvent winEventStart, WinEvent winEventEnd, WinEventHandler winEventHandler)
+ {
+ var hookPtr = SetWinEventHook(winEventStart, winEventEnd, IntPtr.Zero, _winEventHandler, 0, 0, WinEventHookFlags.WINEVENT_SKIPOWNPROCESS | WinEventHookFlags.WINEVENT_OUTOFCONTEXT);
+ _winEventHandlers.Add(hookPtr, winEventHandler);
+ }
+
+ ///
+ /// Remove all hooks
+ ///
+ private void Unhook()
+ {
+ foreach (var hookPtr in _winEventHandlers.Keys)
+ {
+ if (hookPtr != IntPtr.Zero)
+ {
+ UnhookWinEvent(hookPtr);
+ }
+ }
+ _winEventHandlers.Clear();
+ _gcHandle.Free();
+ }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Unhook();
+ }
+
+ ///
+ /// Call the WinEventHandler for this event
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void WinEventDelegateHandler(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ {
+ WinEventHandler handler;
+ if (_winEventHandlers.TryGetValue(hWinEventHook, out handler))
+ {
+ handler(eventType, hWnd, idObject, idChild, dwEventThread, dwmsEventTime);
+ }
+ }
+
+ }
+
+}
diff --git a/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs b/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs
new file mode 100644
index 000000000..5e0a05cf7
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs
@@ -0,0 +1,139 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// Monitor all title changes
+ ///
+ public sealed class WindowsTitleMonitor : IDisposable
+ {
+ private WindowsEventHook _hook;
+ private readonly object _lockObject = new object();
+ // ReSharper disable once InconsistentNaming
+ private event TitleChangeEventDelegate _titleChangeEvent;
+
+ ///
+ /// Add / remove event handler to the title monitor
+ ///
+ public event TitleChangeEventDelegate TitleChangeEvent
+ {
+ add
+ {
+ lock (_lockObject)
+ {
+ if (_hook == null)
+ {
+ _hook = new WindowsEventHook();
+ _hook.Hook(WinEvent.EVENT_OBJECT_NAMECHANGE, WinEventHandler);
+ }
+ _titleChangeEvent += value;
+ }
+ }
+ remove
+ {
+ lock (_lockObject)
+ {
+ _titleChangeEvent -= value;
+ if (_titleChangeEvent == null || _titleChangeEvent.GetInvocationList().Length == 0)
+ {
+ if (_hook != null)
+ {
+ _hook.Dispose();
+ _hook = null;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// WinEventDelegate for the creation & destruction
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void WinEventHandler(WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ {
+ if (hWnd == IntPtr.Zero || idObject != EventObjects.OBJID_WINDOW)
+ {
+ return;
+ }
+ if (eventType == WinEvent.EVENT_OBJECT_NAMECHANGE)
+ {
+ if (_titleChangeEvent != null)
+ {
+ string newTitle = new WindowDetails(hWnd).Text;
+ _titleChangeEvent(new TitleChangeEventArgs { HWnd = hWnd, Title = newTitle });
+ }
+ }
+ }
+
+ #region IDisposable Support
+
+ private bool _disposedValue; // To detect redundant calls
+
+ ///
+ /// Dispose the underlying hook
+ ///
+ public void Dispose(bool disposing)
+ {
+ if (_disposedValue)
+ {
+ return;
+ }
+ lock (_lockObject)
+ {
+ _hook?.Dispose();
+ }
+ _disposedValue = true;
+ }
+
+ ///
+ /// Make sure the finalizer disposes the underlying hook
+ ///
+ ~WindowsTitleMonitor()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(false);
+ }
+
+ ///
+ /// Dispose the underlying hook
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+}
diff --git a/GreenshotJiraPlugin/IssueTypeBitmapCache.cs b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
new file mode 100644
index 000000000..782d2e9ed
--- /dev/null
+++ b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
@@ -0,0 +1,55 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Jira;
+using Dapplo.Jira.Entities;
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// This is the bach for the IssueType bitmaps
+ ///
+ public class IssueTypeBitmapCache : AsyncMemoryCache
+ {
+ private readonly IJiraClient _jiraClient;
+
+ public IssueTypeBitmapCache(IJiraClient jiraClient)
+ {
+ _jiraClient = jiraClient;
+ // Set the expire timeout to an hour
+ ExpireTimeSpan = TimeSpan.FromHours(4);
+ }
+
+ protected override string CreateKey(IssueType keyObject)
+ {
+ return keyObject.Name;
+ }
+
+ protected override async Task CreateAsync(IssueType issueType, CancellationToken cancellationToken = new CancellationToken())
+ {
+ return await _jiraClient.Server.GetUriContentAsync(issueType.IconUri, cancellationToken).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/JiraConfiguration.cs b/GreenshotJiraPlugin/JiraConfiguration.cs
new file mode 100644
index 000000000..8674aeaa4
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraConfiguration.cs
@@ -0,0 +1,49 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// Description of JiraConfiguration.
+ ///
+ [IniSection("Jira", Description="Greenshot Jira Plugin configuration")]
+ public class JiraConfiguration : IniSection {
+ public const string DefaultPrefix = "http://";
+ private const string DefaultUrl = DefaultPrefix + "jira";
+
+ [IniProperty("Url", Description="Base url to Jira system, without anything else", DefaultValue=DefaultUrl)]
+ public string Url { get; set; }
+
+ [IniProperty("Timeout", Description="Session timeout in minutes", DefaultValue="30")]
+ public int Timeout { get; set; }
+
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
+ public bool UploadReduceColors { get; set; }
+ }
+}
diff --git a/GreenshotJiraPlugin/JiraConnector.cs b/GreenshotJiraPlugin/JiraConnector.cs
new file mode 100644
index 000000000..c786f4b46
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraConnector.cs
@@ -0,0 +1,297 @@
+
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Dapplo.HttpExtensions;
+using Dapplo.HttpExtensions.Extensions;
+using Dapplo.Jira;
+using Dapplo.Jira.Converters;
+using Dapplo.Jira.Entities;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed
+ ///
+ public class JiraConnector : IDisposable {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraConnector));
+ private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ // Used to remove the wsdl information from the old SOAP Uri
+ public const string DefaultPostfix = "/rpc/soap/jirasoapservice-v2?wsdl";
+ private DateTimeOffset _loggedInTime = DateTimeOffset.MinValue;
+ private bool _loggedIn;
+ private readonly int _timeout;
+ private IJiraClient _jiraClient;
+ private IssueTypeBitmapCache _issueTypeBitmapCache;
+
+ ///
+ /// Initialize some basic stuff, in the case the SVG to bitmap converter
+ ///
+ static JiraConnector()
+ {
+ CoreConfig.PropertyChanged += (sender, args) =>
+ {
+ if (args.PropertyName == nameof(CoreConfig.IconSize))
+ {
+ JiraPlugin.Instance.JiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height });
+ }
+ };
+
+ }
+
+ ///
+ /// Dispose, logout the users
+ ///
+ public void Dispose() {
+ if (_jiraClient != null)
+ {
+ Task.Run(async () => await LogoutAsync()).Wait();
+ }
+ FavIcon?.Dispose();
+ }
+
+ ///
+ /// Constructor
+ ///
+ public JiraConnector()
+ {
+ JiraConfig.Url = JiraConfig.Url.Replace(DefaultPostfix, "");
+ _timeout = JiraConfig.Timeout;
+ }
+
+ ///
+ /// Access the jira monitor
+ ///
+ public JiraMonitor Monitor { get; private set; }
+
+ public Bitmap FavIcon { get; private set; }
+
+ ///
+ /// Internal login which catches the exceptions
+ ///
+ /// true if login was done sucessfully
+ private async Task DoLoginAsync(string user, string password, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
+ {
+ return false;
+ }
+ _jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
+ _jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height });
+
+ _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
+ try
+ {
+ await _jiraClient.Session.StartAsync(user, password, cancellationToken);
+ Monitor = new JiraMonitor();
+ await Monitor.AddJiraInstanceAsync(_jiraClient, cancellationToken);
+
+ var favIconUri = _jiraClient.JiraBaseUri.AppendSegments("favicon.ico");
+ try
+ {
+ FavIcon = await _jiraClient.Server.GetUriContentAsync(favIconUri, cancellationToken);
+ }
+ catch (Exception ex)
+ {
+ Log.WarnFormat("Couldn't load favicon from {0}", favIconUri);
+ Log.Warn("Exception details: ", ex);
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Use the credentials dialog, this will show if there are not correct credentials.
+ /// If there are credentials, call the real login.
+ ///
+ /// Task
+ public async Task LoginAsync(CancellationToken cancellationToken = default(CancellationToken)) {
+ await LogoutAsync(cancellationToken);
+ try {
+ // Get the system name, so the user knows where to login to
+ var credentialsDialog = new CredentialsDialog(JiraConfig.Url)
+ {
+ Name = null
+ };
+ while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK) {
+ if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password, cancellationToken)) {
+ if (credentialsDialog.SaveChecked) {
+ credentialsDialog.Confirm(true);
+ }
+ _loggedIn = true;
+ _loggedInTime = DateTime.Now;
+ return;
+ }
+ // Login failed, confirm this
+ try {
+ credentialsDialog.Confirm(false);
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+ // For every windows version after XP show an incorrect password baloon
+ credentialsDialog.IncorrectPassword = true;
+ // Make sure the dialog is display, the password was false!
+ credentialsDialog.AlwaysDisplay = true;
+ }
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+
+ }
+
+ ///
+ /// End the session, if there was one
+ ///
+ public async Task LogoutAsync(CancellationToken cancellationToken = default(CancellationToken)) {
+ if (_jiraClient != null && _loggedIn)
+ {
+ Monitor.Dispose();
+ await _jiraClient.Session.EndAsync(cancellationToken);
+ _loggedIn = false;
+ }
+ }
+
+ ///
+ /// check the login credentials, to prevent timeouts of the session, or makes a login
+ /// Do not use ConfigureAwait to call this, as it will move await from the UI thread.
+ ///
+ ///
+ private async Task CheckCredentialsAsync(CancellationToken cancellationToken = default(CancellationToken)) {
+ if (_loggedIn) {
+ if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
+ await LogoutAsync(cancellationToken);
+ await LoginAsync(cancellationToken);
+ }
+ } else {
+ await LoginAsync(cancellationToken);
+ }
+ }
+
+ ///
+ /// Get the favourite filters
+ ///
+ /// List with filters
+ public async Task> GetFavoriteFiltersAsync(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ return await _jiraClient.Filter.GetFavoritesAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the issue for a key
+ ///
+ /// Jira issue key
+ /// CancellationToken
+ /// Issue
+ public async Task GetIssueAsync(string issueKey, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ try
+ {
+ return await _jiraClient.Issue.GetAsync(issueKey, cancellationToken).ConfigureAwait(false);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Attach the content to the jira
+ ///
+ ///
+ /// IBinaryContainer
+ ///
+ ///
+ public async Task AttachAsync(string issueKey, IBinaryContainer content, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ using (var memoryStream = new MemoryStream())
+ {
+ content.WriteToStream(memoryStream);
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ await _jiraClient.Attachment.AttachAsync(issueKey, memoryStream, content.Filename, content.ContentType, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Add a comment to the supplied issue
+ ///
+ /// Jira issue key
+ /// text
+ /// the visibility role
+ /// CancellationToken
+ public async Task AddCommentAsync(string issueKey, string body, string visibility = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ await _jiraClient.Issue.AddCommentAsync(issueKey, body, visibility, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the search results for the specified filter
+ ///
+ /// Filter
+ ///
+ ///
+ public async Task> SearchAsync(Filter filter, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ var searchResult = await _jiraClient.Issue.SearchAsync(filter.Jql, 20, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, cancellationToken).ConfigureAwait(false);
+ return searchResult.Issues;
+ }
+
+ ///
+ /// Get the bitmap representing the issue type of an issue, from cache.
+ ///
+ /// Issue
+ /// CancellationToken
+ /// Bitmap
+ public async Task GetIssueTypeBitmapAsync(Issue issue, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return await _issueTypeBitmapCache.GetOrCreateAsync(issue.Fields.IssueType, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the base uri
+ ///
+ public Uri JiraBaseUri => _jiraClient.JiraBaseUri;
+
+ ///
+ /// Is the user "logged in?
+ ///
+ public bool IsLoggedIn => _loggedIn;
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraDestination.cs b/GreenshotJiraPlugin/JiraDestination.cs
new file mode 100644
index 000000000..e6f60cd46
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraDestination.cs
@@ -0,0 +1,164 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Dapplo.HttpExtensions;
+using Dapplo.Jira.Entities;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotJiraPlugin.Forms;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// Description of JiraDestination.
+ ///
+ public class JiraDestination : AbstractDestination {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraDestination));
+ private static readonly JiraConfiguration Config = IniConfig.GetIniSection();
+ private readonly JiraPlugin _jiraPlugin;
+ private readonly Issue _jiraIssue;
+
+ public JiraDestination(JiraPlugin jiraPlugin) {
+ _jiraPlugin = jiraPlugin;
+ }
+
+ public JiraDestination(JiraPlugin jiraPlugin, Issue jiraIssue) {
+ _jiraPlugin = jiraPlugin;
+ _jiraIssue = jiraIssue;
+ }
+
+ public override string Designation => "Jira";
+
+ public override string Description {
+ get
+ {
+ if (_jiraIssue?.Fields?.Summary == null) {
+ return Language.GetString("jira", LangKey.upload_menu_item);
+ }
+ // Format the title of this destination
+ return _jiraIssue.Key + ": " + _jiraIssue.Fields.Summary.Substring(0, Math.Min(20, _jiraIssue.Fields.Summary.Length));
+ }
+ }
+
+ public override bool IsActive => base.IsActive && !string.IsNullOrEmpty(Config.Url);
+
+ public override bool IsDynamic => true;
+
+ public override Image DisplayIcon {
+ get
+ {
+ Image displayIcon = null;
+ var jiraConnector = JiraPlugin.Instance.CurrentJiraConnector;
+ if (jiraConnector != null)
+ {
+ if (_jiraIssue != null)
+ {
+ // Try to get the issue type as icon
+ try
+ {
+ displayIcon = jiraConnector.GetIssueTypeBitmapAsync(_jiraIssue).Result;
+ }
+ catch (Exception ex)
+ {
+ Log.Warn($"Problem loading issue type for {_jiraIssue.Key}, ignoring", ex);
+ }
+ }
+ if (displayIcon == null)
+ {
+ displayIcon = jiraConnector.FavIcon;
+ }
+ }
+ if (displayIcon == null)
+ {
+ var resources = new ComponentResourceManager(typeof(JiraPlugin));
+ displayIcon = (Image)resources.GetObject("Jira");
+ }
+ return displayIcon;
+ }
+ }
+
+ public override IEnumerable DynamicDestinations()
+ {
+ var jiraConnector = JiraPlugin.Instance.CurrentJiraConnector;
+ if (jiraConnector == null || !jiraConnector.IsLoggedIn) {
+ yield break;
+ }
+ foreach(var jiraDetails in jiraConnector.Monitor.RecentJiras)
+ {
+ yield return new JiraDestination(_jiraPlugin,jiraDetails.JiraIssue);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surfaceToUpload, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(Config.UploadFormat, captureDetails));
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(Config.UploadFormat, Config.UploadJpegQuality, Config.UploadReduceColors);
+ if (_jiraIssue != null) {
+ try {
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
+ async () =>
+ {
+ var surfaceContainer = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+ await _jiraPlugin.JiraConnector.AttachAsync(_jiraIssue.Key, surfaceContainer);
+ surfaceToUpload.UploadUrl = _jiraPlugin.JiraConnector.JiraBaseUri.AppendSegments("browse", _jiraIssue.Key).AbsoluteUri;
+ }
+ );
+ Log.DebugFormat("Uploaded to Jira {0}", _jiraIssue.Key);
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = surfaceToUpload.UploadUrl;
+ } catch (Exception e) {
+ MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
+ }
+ } else {
+ var jiraForm = new JiraForm(_jiraPlugin.JiraConnector);
+ jiraForm.SetFilename(filename);
+ var dialogResult = jiraForm.ShowDialog();
+ if (dialogResult == DialogResult.OK) {
+ try {
+ surfaceToUpload.UploadUrl = _jiraPlugin.JiraConnector.JiraBaseUri.AppendSegments("browse", jiraForm.GetJiraIssue().Key).AbsoluteUri;
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
+ async () =>
+ {
+ await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ }
+ );
+ Log.DebugFormat("Uploaded to Jira {0}", jiraForm.GetJiraIssue().Key);
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = surfaceToUpload.UploadUrl;
+ } catch(Exception e) {
+ MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
+ }
+ }
+ }
+ ProcessExport(exportInformation, surfaceToUpload);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/JiraDetails.cs b/GreenshotJiraPlugin/JiraDetails.cs
new file mode 100644
index 000000000..e03172873
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraDetails.cs
@@ -0,0 +1,71 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub: https://github.com/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using Dapplo.Jira.Entities;
+
+namespace GreenshotJiraPlugin
+{
+ public class JiraDetails : IComparable
+ {
+ public JiraDetails()
+ {
+ FirstSeenAt = SeenAt = DateTimeOffset.Now;
+ }
+
+ public string ProjectKey
+ {
+ get;
+ set;
+ }
+
+ public string Id
+ {
+ get;
+ set;
+ }
+
+ public string JiraKey => ProjectKey + "-" + Id;
+
+ public Issue JiraIssue
+ {
+ get;
+ set;
+ }
+
+ public DateTimeOffset FirstSeenAt
+ {
+ get;
+ private set;
+ }
+
+ public DateTimeOffset SeenAt
+ {
+ get;
+ set;
+ }
+
+ public int CompareTo(JiraDetails other)
+ {
+ return SeenAt.CompareTo(other.SeenAt);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/JiraEventArgs.cs b/GreenshotJiraPlugin/JiraEventArgs.cs
similarity index 63%
rename from src/Greenshot.Plugin.Jira/JiraEventArgs.cs
rename to GreenshotJiraPlugin/JiraEventArgs.cs
index d847c9392..cbe7caa0d 100644
--- a/src/Greenshot.Plugin.Jira/JiraEventArgs.cs
+++ b/GreenshotJiraPlugin/JiraEventArgs.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub: https://github.com/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,17 +16,25 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
using System;
-namespace Greenshot.Plugin.Jira
+namespace GreenshotJiraPlugin
{
- public class JiraEventArgs : EventArgs
- {
- public JiraEventTypes EventType { get; set; }
+ public class JiraEventArgs : EventArgs
+ {
+ public JiraEventTypes EventType
+ {
+ get;
+ set;
+ }
- public JiraDetails Details { get; set; }
- }
-}
\ No newline at end of file
+ public JiraDetails Details
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/JiraEventTypes.cs b/GreenshotJiraPlugin/JiraEventTypes.cs
similarity index 67%
rename from src/Greenshot.Plugin.Jira/JiraEventTypes.cs
rename to GreenshotJiraPlugin/JiraEventTypes.cs
index cc433c85e..06b95db22 100644
--- a/src/Greenshot.Plugin.Jira/JiraEventTypes.cs
+++ b/GreenshotJiraPlugin/JiraEventTypes.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub: https://github.com/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,14 +16,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-namespace Greenshot.Plugin.Jira
+namespace GreenshotJiraPlugin
{
- public enum JiraEventTypes
- {
- OrderChanged,
- DetectedNewJiraIssue
- }
+ public enum JiraEventTypes
+ {
+ OrderChanged,
+ DetectedNewJiraIssue
+ }
}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraMonitor.cs b/GreenshotJiraPlugin/JiraMonitor.cs
new file mode 100644
index 000000000..562bf6c4c
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraMonitor.cs
@@ -0,0 +1,225 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub: https://github.com/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Jira;
+using Dapplo.Log;
+using GreenshotJiraPlugin.Hooking;
+
+namespace GreenshotJiraPlugin
+{
+
+ ///
+ /// This class will monitor all _jira activity by registering for title changes
+ /// It keeps a list of the last "accessed" jiras, and makes it easy to upload to one.
+ /// Make sure this is instanciated on the UI thread!
+ ///
+ public class JiraMonitor : IDisposable
+ {
+ private static readonly LogSource Log = new LogSource();
+ private readonly Regex _jiraKeyPattern = new Regex(@"[A-Z][A-Z0-9]+\-[0-9]+");
+ private readonly WindowsTitleMonitor _monitor;
+ private readonly IList _jiraInstances = new List();
+ private readonly IDictionary _projectJiraClientMap = new Dictionary();
+ private readonly int _maxEntries;
+ // TODO: Add issues from issueHistory (JQL -> Where.IssueKey.InIssueHistory())
+ private IDictionary _recentJiras = new Dictionary();
+
+ ///
+ /// Register to this event to get events when new jira issues are detected
+ ///
+ public event EventHandler JiraEvent;
+
+ public JiraMonitor(int maxEntries = 40)
+ {
+ _maxEntries = maxEntries;
+ _monitor = new WindowsTitleMonitor();
+ _monitor.TitleChangeEvent += MonitorTitleChangeEvent;
+ }
+
+ #region Dispose
+
+ ///
+ /// Dispose
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Dispose all managed resources
+ ///
+ /// when true is passed all managed resources are disposed.
+ protected void Dispose(bool disposing)
+ {
+ if (!disposing)
+ {
+ return;
+ }
+ // free managed resources
+ _monitor.TitleChangeEvent -= MonitorTitleChangeEvent;
+ _monitor.Dispose();
+ // free native resources if there are any.
+ }
+
+ #endregion
+
+ ///
+ /// Retrieve the API belonging to a JiraDetails
+ ///
+ ///
+ /// IJiraClient
+ public IJiraClient GetJiraClientForKey(JiraDetails jiraDetails)
+ {
+ return _projectJiraClientMap[jiraDetails.ProjectKey];
+ }
+
+ ///
+ /// Get the "list" of recently seen Jiras
+ ///
+ public IEnumerable RecentJiras =>
+ (from jiraDetails in _recentJiras.Values
+ orderby jiraDetails.SeenAt descending
+ select jiraDetails);
+
+ ///
+ /// Check if this monitor has active instances
+ ///
+ public bool HasJiraInstances => _jiraInstances.Count > 0;
+
+ ///
+ /// Add an instance of a JIRA system
+ ///
+ ///
+ ///
+ public async Task AddJiraInstanceAsync(IJiraClient jiraInstance, CancellationToken token = default(CancellationToken))
+ {
+ _jiraInstances.Add(jiraInstance);
+ var projects = await jiraInstance.Project.GetAllAsync(cancellationToken: token).ConfigureAwait(false);
+ if (projects != null)
+ {
+ foreach (var project in projects)
+ {
+ if (!_projectJiraClientMap.ContainsKey(project.Key))
+ {
+ _projectJiraClientMap.Add(project.Key, jiraInstance);
+ }
+ }
+ }
+ }
+
+ ///
+ /// This method will update details, like the title, and send an event to registed listeners of the JiraEvent
+ ///
+ /// Contains the jira key to retrieve the title (XYZ-1234)
+ /// Task
+ private async Task DetectedNewJiraIssueAsync(JiraDetails jiraDetails)
+ {
+ try
+ {
+ IJiraClient jiraClient;
+ if (_projectJiraClientMap.TryGetValue(jiraDetails.ProjectKey, out jiraClient))
+ {
+ var issue = await jiraClient.Issue.GetAsync(jiraDetails.JiraKey).ConfigureAwait(false);
+ jiraDetails.JiraIssue = issue;
+ }
+ // Send event
+ JiraEvent?.Invoke(this, new JiraEventArgs { Details = jiraDetails, EventType = JiraEventTypes.DetectedNewJiraIssue });
+ }
+ catch (Exception ex)
+ {
+ Log.Warn().WriteLine("Couldn't retrieve JIRA title: {0}", ex.Message);
+ }
+ }
+
+ ///
+ /// Handle title changes, check for JIRA
+ ///
+ ///
+ private void MonitorTitleChangeEvent(TitleChangeEventArgs eventArgs)
+ {
+ string windowTitle = eventArgs.Title;
+ if (string.IsNullOrEmpty(windowTitle))
+ {
+ return;
+ }
+ var jiraKeyMatch = _jiraKeyPattern.Match(windowTitle);
+ if (!jiraKeyMatch.Success)
+ {
+ return;
+ }
+ // Found a possible JIRA title
+ var jiraKey = jiraKeyMatch.Value;
+ var jiraKeyParts = jiraKey.Split('-');
+ var projectKey = jiraKeyParts[0];
+ var jiraId = jiraKeyParts[1];
+
+ IJiraClient jiraClient;
+ // Check if we have a JIRA instance with a project for this key
+ if (_projectJiraClientMap.TryGetValue(projectKey, out jiraClient))
+ {
+ // We have found a project for this _jira key, so it must be a valid & known JIRA
+ JiraDetails currentJiraDetails;
+ if (_recentJiras.TryGetValue(jiraKey, out currentJiraDetails))
+ {
+ // update
+ currentJiraDetails.SeenAt = DateTimeOffset.Now;
+
+ // Notify the order change
+ JiraEvent?.Invoke(this, new JiraEventArgs { Details = currentJiraDetails, EventType = JiraEventTypes.OrderChanged });
+ // Nothing else to do
+
+ return;
+ }
+ // We detected an unknown JIRA, so add it to our list
+ currentJiraDetails = new JiraDetails
+ {
+ Id = jiraId,
+ ProjectKey = projectKey
+ };
+ _recentJiras.Add(currentJiraDetails.JiraKey, currentJiraDetails);
+
+ // Make sure we don't collect _jira's until the memory is full
+ if (_recentJiras.Count > _maxEntries)
+ {
+ // Add it to the list of recent Jiras
+ _recentJiras = (from jiraDetails in _recentJiras.Values.ToList()
+ orderby jiraDetails.SeenAt descending
+ select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd);
+ }
+ // Now we can get the title from JIRA itself
+ // ReSharper disable once UnusedVariable
+ var updateTitleTask = DetectedNewJiraIssueAsync(currentJiraDetails);
+ }
+ else
+ {
+ Log.Info().WriteLine("Couldn't match possible JIRA key {0} to projects in a configured JIRA instance, ignoring", projectKey);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraPlugin.cs b/GreenshotJiraPlugin/JiraPlugin.cs
new file mode 100644
index 000000000..ed26d888d
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraPlugin.cs
@@ -0,0 +1,203 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Collections.Generic;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using System;
+using System.Threading.Tasks;
+using Dapplo.Log;
+using Greenshot.Forms;
+using Greenshot.Helpers;
+using GreenshotJiraPlugin.Forms;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// This is the JiraPlugin base code
+ ///
+ public class JiraPlugin : IGreenshotPlugin {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin));
+ private JiraConfiguration _config;
+ private static JiraPlugin _instance;
+ private JiraConnector _jiraConnector;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing) {
+ if (disposing) {
+ if (JiraConnector != null) {
+ JiraConnector.Dispose();
+ JiraConnector = null;
+ }
+ }
+ }
+
+ public static JiraPlugin Instance => _instance;
+
+ public JiraPlugin() {
+ _instance = this;
+ // Added to prevent Greenshot from shutting down when there was an exception in a Task
+ TaskScheduler.UnobservedTaskException += (sender, args) =>
+ {
+ try
+ {
+ Exception exceptionToLog = args.Exception;
+ string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
+ Log.Error("Exception caught in the UnobservedTaskException handler.");
+ Log.Error(exceptionText);
+ new BugReportForm(exceptionText).ShowDialog();
+ }
+ finally
+ {
+ args.SetObserved();
+ }
+ };
+ }
+
+ public IEnumerable Destinations() {
+ yield return new JiraDestination(this);
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ //Needed for a fail-fast
+ public JiraConnector CurrentJiraConnector => JiraConnector;
+
+ public JiraConnector JiraConnector
+ {
+ get
+ {
+ lock (_instance)
+ {
+ if (_jiraConnector == null)
+ {
+ JiraConnector = new JiraConnector();
+ }
+ }
+ return _jiraConnector;
+ }
+ private set { _jiraConnector = value; }
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+
+ // Make sure the loggin is enable for the corect level.
+ if (Log.IsDebugEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Verbose);
+ }
+ else if (Log.IsInfoEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Info);
+ }
+ else if (Log.IsWarnEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Warn);
+ }
+ else if (Log.IsErrorEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Error);
+ }
+ else if (Log.IsErrorEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Error);
+ }
+ else
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Fatal);
+ }
+
+ // Add a SVG converter, although it doesn't fit to the Jira plugin there is currently no other way
+ ImageHelper.StreamConverters["svg"] = (stream, s) =>
+ {
+ stream.Position = 0;
+ try
+ {
+ return SvgImage.FromStream(stream).Image;
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Can't load SVG", ex);
+ }
+ return null;
+ };
+
+ return true;
+ }
+
+ public void Shutdown() {
+ Log.Debug("Jira Plugin shutdown.");
+ if (JiraConnector != null)
+ {
+ Task.Run(async () => await JiraConnector.LogoutAsync());
+ }
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public void Configure() {
+ string url = _config.Url;
+ if (ShowConfigDialog()) {
+ // check for re-login
+ if (JiraConnector != null && JiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url)) {
+ if (!url.Equals(_config.Url)) {
+ Task.Run(async () =>
+ {
+ await JiraConnector.LogoutAsync();
+ await JiraConnector.LoginAsync();
+ });
+ }
+ }
+ }
+ }
+
+ ///
+ /// A form for username/password
+ ///
+ /// bool true if OK was pressed, false if cancel
+ private bool ShowConfigDialog()
+ {
+ var settingsForm = new SettingsForm();
+ var result = settingsForm.ShowDialog();
+ if (result == DialogResult.OK)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/JiraPlugin.resx b/GreenshotJiraPlugin/JiraPlugin.resx
similarity index 95%
rename from src/Greenshot.Plugin.Jira/JiraPlugin.resx
rename to GreenshotJiraPlugin/JiraPlugin.resx
index e21fb17c2..d6a7cedd1 100644
--- a/src/Greenshot.Plugin.Jira/JiraPlugin.resx
+++ b/GreenshotJiraPlugin/JiraPlugin.resx
@@ -112,12 +112,12 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
diff --git a/GreenshotJiraPlugin/LanguageKeys.cs b/GreenshotJiraPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..0ef41c755
--- /dev/null
+++ b/GreenshotJiraPlugin/LanguageKeys.cs
@@ -0,0 +1,46 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotJiraPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ column_assignee,
+ column_created,
+ column_issueType,
+ column_id,
+ column_reporter,
+ column_summary,
+ label_comment,
+ label_filename,
+ label_jira,
+ label_jirafilter,
+ login_error,
+ login_title,
+ settings_title,
+ label_url,
+ label_upload_format,
+ OK,
+ CANCEL,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-cs-CZ.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-cs-CZ.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-cs-CZ.xml
index 1a7133833..0c3202c3a 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-cs-CZ.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-cs-CZ.xml
@@ -1,25 +1,25 @@
-
-
-
- Zrušit
- Pověřené osoby
- Vytvořil(a)
- ID
- Reporter ???
- Shrnutí
- Přenos dat na JIRA, prosím počkejte...
- Komentář
- Jméno souboru
- JIRA
- JIRA filtr
- Formát obrázku
- Url
- Problém při přihlášení: {0}
- Prosím, zadejte přihlašovací údaje pre Jira
- OK
- Nastavení Jira
- Došlo k chybě při nahrávání na Jira:
- Nahrát na Jira
- Obrázek úspěšně nahrán na Jira!
-
+
+
+
+ Zrušit
+ Pověřené osoby
+ Vytvořil(a)
+ ID
+ Reporter ???
+ Shrnutí
+ Přenos dat na JIRA, prosím počkejte...
+ Komentář
+ Jméno souboru
+ JIRA
+ JIRA filtr
+ Formát obrázku
+ Url
+ Problém při přihlášení: {0}
+ Prosím, zadejte přihlašovací údaje pre Jira
+ OK
+ Nastavení Jira
+ Došlo k chybě při nahrávání na Jira:
+ Nahrát na Jira
+ Obrázek úspěšně nahrán na Jira!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-de-DE.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-de-DE.xml
similarity index 95%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-de-DE.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-de-DE.xml
index 2f6e7ea11..e32894a69 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-de-DE.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-de-DE.xml
@@ -1,65 +1,65 @@
-
-
-
-
- In Jira hochladen
-
-
- Bearbeiter
-
-
- Erstellt
-
-
- ID
-
-
- Author
-
-
- Kurzbeschreibung
-
-
- Kommentar
-
-
- Dateiname
-
-
- JIRA
-
-
- JIRA Filter
-
-
- Es gab ein Problem beim Login: {0}
-
-
- Bitte geben Sie ihre Jira Login-Daten ein
-
-
- Jira Einstellungen
-
-
- Url
-
-
- OK
-
-
- Cancel
-
-
- Das Hochladen zu Jira war erfolgreich.
-
-
- Es gab einen Fehler beim Hochladen zu Jira:
-
-
- Bildformat
-
-
- Übermittle Daten zu Jira. Bitte warten...
-
-
+
+
+
+
+ In Jira hochladen
+
+
+ Bearbeiter
+
+
+ Erstellt
+
+
+ ID
+
+
+ Author
+
+
+ Kurzbeschreibung
+
+
+ Kommentar
+
+
+ Dateiname
+
+
+ JIRA
+
+
+ JIRA Filter
+
+
+ Es gab ein Problem beim Login: {0}
+
+
+ Bitte geben Sie ihre Jira Login-Daten ein
+
+
+ Jira Einstellungen
+
+
+ Url
+
+
+ OK
+
+
+ Cancel
+
+
+ Das Hochladen zu Jira war erfolgreich.
+
+
+ Es gab einen Fehler beim Hochladen zu Jira:
+
+
+ Bildformat
+
+
+ Übermittle Daten zu Jira. Bitte warten...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-en-US.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-en-US.xml
similarity index 92%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-en-US.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-en-US.xml
index ca64fd7a8..b64eb75f4 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-en-US.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-en-US.xml
@@ -1,65 +1,65 @@
-
-
-
-
- Upload to Jira
-
-
- Assignee
-
-
- Created
-
-
- ID
-
-
- Reporter
-
-
- Summary
-
-
- Comment
-
-
- Filename
-
-
- JIRA
-
-
- JIRA Filter
-
-
- There was a problem during the login: {0}
-
-
- Url
-
-
- Please enter your Jira login data
-
-
- Jira settings
-
-
- OK
-
-
- Cancel
-
-
- Successfully uploaded image to Jira!
-
-
- An error occurred while uploading to Jira:
-
-
- Image format
-
-
- Transferring data to JIRA, please wait...
-
-
+
+
+
+
+ Upload to Jira
+
+
+ Assignee
+
+
+ Created
+
+
+ ID
+
+
+ Reporter
+
+
+ Summary
+
+
+ Comment
+
+
+ Filename
+
+
+ JIRA
+
+
+ JIRA Filter
+
+
+ There was a problem during the login: {0}
+
+
+ Url
+
+
+ Please enter your Jira login data
+
+
+ Jira settings
+
+
+ OK
+
+
+ Cancel
+
+
+ Successfully uploaded image to Jira!
+
+
+ An error occured while uploading to Jira:
+
+
+ Image format
+
+
+ Transferring data to JIRA, please wait...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-fr-FR.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-fr-FR.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-fr-FR.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-fr-FR.xml
index c27433023..9b5faa3b0 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-fr-FR.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-fr-FR.xml
@@ -1,25 +1,25 @@
-
-
-
- Annuler
- Bénéficiaire
- Créé
- ID
- Reporter
- Résumé
- Transfert de données vers JIRA, veuillez patienter...
- Commentaire
- Fichier
- JIRA
- Filtre JIRA
- Format image
- Url
- Un problème est survenu lors de l'authentification : {0}
- Veuillez saisir vos identifiants Jira
- OK
- Paramètres Jira
- Une erreur est survenue lors du téléversement vers Jira :
- Téléverser vers Jira
- L'image a été téléversée vers Jira avec succès !
-
+
+
+
+ Annuler
+ Bénéficiaire
+ Créé
+ ID
+ Reporter
+ Résumé
+ Transfert de données vers JIRA, veuillez patienter...
+ Commentaire
+ Fichier
+ JIRA
+ Filtre JIRA
+ Format image
+ Url
+ Un problème est survenu lors de l'authentification : {0}
+ Veuillez saisir vos identifiants Jira
+ OK
+ Paramètres Jira
+ Une erreur est survenue lors du téléversement vers Jira :
+ Téléverser vers Jira
+ L'image a été téléversée vers Jira avec succès !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-id-ID.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-id-ID.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-id-ID.xml
index 91bfd1dc5..47a72857b 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-id-ID.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-id-ID.xml
@@ -1,25 +1,25 @@
-
-
-
- Batal
- Tujuan
- Tercipta
- ID
- Pelapor
- Penjelasan
- Mentransfer data ke JIRA, tunggu sebentar...
- Komentar
- Nama berkas
- JIRA
- JIRA Filter
- Format gambar
- Url
- Masalah terjadi ketika login: {0}
- Masukkan data login Jira anda
- Oke
- Setelan Jira
- Kesalahan terjadi ketika mengunggah ke Jira:
- Unggah ke Jira
- Berhasil mengunggah gambar ke Jira!
-
+
+
+
+ Batal
+ Tujuan
+ Tercipta
+ ID
+ Pelapor
+ Penjelasan
+ Mentransfer data ke JIRA, tunggu sebentar...
+ Komentar
+ Nama berkas
+ JIRA
+ JIRA Filter
+ Format gambar
+ Url
+ Masalah terjadi ketika login: {0}
+ Masukkan data login Jira anda
+ Oke
+ Setelan Jira
+ Kesalahan terjadi ketika mengunggah ke Jira:
+ Unggah ke Jira
+ Berhasil mengunggah gambar ke Jira!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-it-IT.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-it-IT.xml
similarity index 80%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-it-IT.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-it-IT.xml
index f69d1fb37..8b9febaf8 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-it-IT.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-it-IT.xml
@@ -1,65 +1,65 @@
-
-
-
-
- Carica su Jira
-
-
- Assegnatario
-
-
- Creata
-
-
- ID
-
-
- Segnalatore
-
-
- Riepilogo
-
-
- Commento
-
-
- Nome file
-
-
- JIRA
-
-
- Filtro JIRA
-
-
- Si è verificato un problema durante il collegamento: {0}
-
-
- URL
-
-
- Inserisci le credenziali di accesso a Jira
-
-
- Impostazioni Jira
-
-
- OK
-
-
- Annulla
-
-
- caricamento immagine su Jira completato!
-
-
- Si è verificato un errore durante il caricamento su Jira:
-
-
- Formato immagine
-
-
- Trasferimento dati verso JIRA...
-
-
+
+
+
+
+ Carica su Jira
+
+
+ Assegnatario
+
+
+ Creata
+
+
+ ID
+
+
+ Reporter
+
+
+ Riepilogo
+
+
+ Commento
+
+
+ Nome File
+
+
+ JIRA
+
+
+ Filtro JIRA
+
+
+ Si è verificato un problema durante il collegamento: {0}
+
+
+ Url
+
+
+ Inserisci le tue credenziali di collegamento a Jira
+
+
+ Impostazioni Jira
+
+
+ OK
+
+
+ Annulla
+
+
+ Immagine caricata correttamente su Jira!
+
+
+ Si è verificato un errore durante il caricamento su Jira:
+
+
+ Formato immagine
+
+
+ Trasferimento dati verso JIRA, attendere prego...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-ko-KR.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-ko-KR.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-lv-LV.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-lv-LV.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-nl-NL.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-nl-NL.xml
similarity index 95%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-nl-NL.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-nl-NL.xml
index 05db8619e..47275ceae 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-nl-NL.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-nl-NL.xml
@@ -1,71 +1,71 @@
-
-
-
-
- Naar Jira uploaden
-
-
- Toegewezen aan
-
-
- Gecreërd
-
-
- ID
-
-
- Gemeld door
-
-
- Samenvatting
-
-
- Kommentaar
-
-
- Filename
-
-
- JIRA
-
-
- JIRA filter
-
-
- Tijdens de login is een fout opgetreden: {0}
-
-
- Url
-
-
- Gebruiker
-
-
- Password
-
-
- Geef uw Jira login data
-
-
- Jira instellingen
-
-
- OK
-
-
- Afbreken
-
-
- Het uploaden naar Jira is geslaagt!
-
-
- Tijdens het uploaden naar Jira is een fout opgetreden:
-
-
- Beeld formaat
-
-
- Gegevensoverdracht naar Jira, wachten A.U.B...
-
-
+
+
+
+
+ Naar Jira uploaden
+
+
+ Toegewezen aan
+
+
+ Gecreërd
+
+
+ ID
+
+
+ Gemeld door
+
+
+ Samenvatting
+
+
+ Kommentaar
+
+
+ Filename
+
+
+ JIRA
+
+
+ JIRA filter
+
+
+ Tijdens de login is een fout opgetreden: {0}
+
+
+ Url
+
+
+ Gebruiker
+
+
+ Password
+
+
+ Geef uw Jira login data
+
+
+ Jira instellingen
+
+
+ OK
+
+
+ Afbreken
+
+
+ Het uploaden naar Jira is geslaagt!
+
+
+ Tijdens het uploaden naar Jira is een fout opgetreden:
+
+
+ Beeld formaat
+
+
+ Gegevensoverdracht naar Jira, wachten A.U.B...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-pl-PL.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-pl-PL.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-pl-PL.xml
index d7d22aca2..dc1050295 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-pl-PL.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-pl-PL.xml
@@ -1,25 +1,25 @@
-
-
-
- Anuluj
- Przypisane do
- Utworzone
- ID
- Zgłaszający
- Podsumowanie
- Trwa komunikacja z JIRA. Proszę czekać...
- Komentarz
- Nazwa pliku
- JIRA
- Filtr JIRA
- Format obrazu
- URL
- Wystąpił problem podczas logowania: {0}
- Wprowadź swoje dane logowania
- OK
- Ustawienia JIRA
- Wystąpił błąd przy wysyłaniu do JIRA:
- Wyślij do JIRA
- Wysyłanie obrazu do JIRA powiodło się!
-
+
+
+
+ Anuluj
+ Przypisane do
+ Utworzone
+ ID
+ Zgłaszający
+ Podsumowanie
+ Trwa komunikacja z JIRA. Proszę czekać...
+ Komentarz
+ Nazwa pliku
+ JIRA
+ Filtr JIRA
+ Format obrazu
+ URL
+ Wystąpił problem podczas logowania: {0}
+ Wprowadź swoje dane logowania
+ OK
+ Ustawienia JIRA
+ Wystąpił błąd przy wysyłaniu do JIRA:
+ Wyślij do JIRA
+ Wysyłanie obrazu do JIRA powiodło się!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-pt-PT.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-pt-PT.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-ru-RU.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-ru-RU.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-ru-RU.xml
index 8e3ad5003..b983711a1 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-ru-RU.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-ru-RU.xml
@@ -1,25 +1,25 @@
-
-
-
- Отмена
- Представитель
- Создан
- ID
- Корреспондент
- Резюме
- Передача данных в JIRA, подождите, пожалуйста!...
- Комментарий
- Имя файла
- JIRA
- Фильтр JIRA
- Формат изображения
- Url
- Произошла ошибка во время входа: {0}
- Пожалуйста, введите ваши регистрационные данные Jira
- OK
- JIRA параметры
- Произошла ошибка при загрузке на Jira:
- Загрузить на Jira
- Изображение успешно загружено на Jira!
-
+
+
+
+ Отмена
+ Представитель
+ Создан
+ ID
+ Корреспондент
+ Резюме
+ Передача данных в JIRA, подождите, пожалуйста!...
+ Комментарий
+ Имя файла
+ JIRA
+ Фильтр JIRA
+ Формат изображения
+ Url
+ Произошла ошибка во время входа: {0}
+ Пожалуйста, введите ваши регистрационные данные Jira
+ OK
+ JIRA параметры
+ Произошла ошибка при загрузке на Jira:
+ Загрузить на Jira
+ Изображение успешно загружено на Jira!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-sr-RS.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-sr-RS.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-sr-RS.xml
index 6e1d3e2f2..bc35c25cc 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-sr-RS.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-sr-RS.xml
@@ -1,25 +1,25 @@
-
-
-
- Откажи
- Представник
- Направљено
- ИД
- Кореспондент
- Резиме
- Преносим податке на Џиру…
- Коментар
- Назив датотеке
- Џира
- Филтер Џире
- Формат слике:
- Адреса:
- Дошло је до грешке при пријављивању: {0}
- Унесите податке за пријављивање на Џиру
- У реду
- Поставке Џире
- Дошло је до грешке при отпремању на Џиру:
- Отпреми на Џиру
- Слика је успешно постављена на Џиру.
-
+
+
+
+ Откажи
+ Представник
+ Направљено
+ ИД
+ Кореспондент
+ Резиме
+ Преносим податке на Џиру…
+ Коментар
+ Назив датотеке
+ Џира
+ Филтер Џире
+ Формат слике:
+ Адреса:
+ Дошло је до грешке при пријављивању: {0}
+ Унесите податке за пријављивање на Џиру
+ У реду
+ Поставке Џире
+ Дошло је до грешке при отпремању на Џиру:
+ Отпреми на Џиру
+ Слика је успешно постављена на Џиру.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-sv-SE.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-sv-SE.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-uk-UA.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-uk-UA.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-uk-UA.xml
index d9763c9c4..59a9bcc8f 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-uk-UA.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-uk-UA.xml
@@ -1,25 +1,25 @@
-
-
-
- Вивантажити на Jira
- Представник
- Створено
- Ідентифікатор
- Кореспондент
- Зведення
- Коментар
- Назва файла
- JIRA
- Фільтр JIRA
- Відбулась помилка під час авторизації: {0}
- Посилання
- Будь ласка, введіть дані облікового запису Jira
- Параметри Jira
- Гаразд
- Скасувати
- Зображення вдало вивантажено на Jira!
- Відбулась помилка під час вивантаження на Jira:
- Формат зображення
- Передача даних на JIRA, будь ласка, зачекайте...
-
-
+
+
+
+ Вивантажити на Jira
+ Представник
+ Створено
+ Ідентифікатор
+ Кореспондент
+ Зведення
+ Коментар
+ Назва файла
+ JIRA
+ Фільтр JIRA
+ Відбулась помилка під час авторизації: {0}
+ Посилання
+ Будь ласка, введіть дані облікового запису Jira
+ Параметри Jira
+ Гаразд
+ Скасувати
+ Зображення вдало вивантажено на Jira!
+ Відбулась помилка під час вивантаження на Jira:
+ Формат зображення
+ Передача даних на JIRA, будь ласка, зачекайте...
+
+
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-zh-CN.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-zh-CN.xml
similarity index 95%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-zh-CN.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-zh-CN.xml
index e69deefc2..779eb0c0c 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-zh-CN.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-zh-CN.xml
@@ -1,65 +1,65 @@
-
-
-
-
- 上传到 Jira
-
-
- 委托人
-
-
- 已创建
-
-
- ID
-
-
- 报告人
-
-
- 摘要
-
-
- 注释
-
-
- 文件名
-
-
- JIRA
-
-
- JIRA 过滤
-
-
- 登录过程中出现问题: {0}
-
-
- Url
-
-
- 请输入你的 Jira 登录数据
-
-
- Jira 设置
-
-
- 确定
-
-
- 取消
-
-
- 已成功上传图片到 Jira !
-
-
- 上传到 Jira 时出现错误:
-
-
- 图片格式
-
-
- 正在传输数据到 JIRA ,请稍候...
-
-
+
+
+
+
+ 上传到 Jira
+
+
+ 委托人
+
+
+ 已创建
+
+
+ ID
+
+
+ 报告人
+
+
+ 摘要
+
+
+ 注释
+
+
+ 文件名
+
+
+ JIRA
+
+
+ JIRA 过滤
+
+
+ 登录过程中出现问题: {0}
+
+
+ Url
+
+
+ 请输入你的 Jira 登录数据
+
+
+ Jira 设置
+
+
+ 确定
+
+
+ 取消
+
+
+ 已成功上传图片到 Jira !
+
+
+ 上传到 Jira 时出现错误:
+
+
+ 图片格式
+
+
+ 正在传输数据到 JIRA ,请稍候...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-zh-TW.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-zh-TW.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-zh-TW.xml
index f3e51c75b..b2ea00222 100644
--- a/src/Greenshot.Plugin.Jira/Languages/language_jira-zh-TW.xml
+++ b/GreenshotJiraPlugin/Languages/language_jiraplugin-zh-TW.xml
@@ -1,25 +1,25 @@
-
-
-
- 取消
- 指派
- 建立日期
- ID
- 報導
- 摘要
- 正在傳輸資料到 JIRA,請稍候...
- 註解
- 檔案名稱
- JIRA
- JIRA 篩選
- 圖片格式
- URL
- 登入期間發生問題: {0}
- 請輸入您的 JIRA 登入資料
- 確定
- JIRA 設定
- 上傳到 JIRA 時發生錯誤:
- 上傳到
- 上傳圖片到 JIRA 成功!
-
+
+
+
+ 取消
+ 指派
+ 建立日期
+ ID
+ 報導
+ 摘要
+ 正在傳輸資料到 JIRA,請稍候...
+ 註解
+ 檔案名稱
+ JIRA
+ JIRA 篩選
+ 圖片格式
+ URL
+ 登入期間發生問題: {0}
+ 請輸入您的 JIRA 登入資料
+ 確定
+ JIRA 設定
+ 上傳到 JIRA 時發生錯誤:
+ 上傳到
+ 上傳圖片到 JIRA 成功!
+
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/Log4NetLogger.cs b/GreenshotJiraPlugin/Log4NetLogger.cs
new file mode 100644
index 000000000..3018a8823
--- /dev/null
+++ b/GreenshotJiraPlugin/Log4NetLogger.cs
@@ -0,0 +1,120 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Dapplo.Log;
+using log4net;
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// Used to make Dapplo.Log, used in Dapplo.Jira, write to Log4net
+ ///
+ public class Log4NetLogger : AbstractLogger
+ {
+ private ILog GetLogger(LogSource logSource)
+ {
+ return logSource.SourceType != null ? LogManager.GetLogger(logSource.SourceType) : LogManager.GetLogger(logSource.Source);
+ }
+
+ ///
+ /// Write the supplied information to a log4net.ILog
+ ///
+ /// LogInfo
+ /// string
+ /// params object[]
+ public override void Write(LogInfo logInfo, string messageTemplate, params object[] propertyValues)
+ {
+ var log = GetLogger(logInfo.Source);
+
+ switch (logInfo.LogLevel)
+ {
+ case LogLevels.Verbose:
+ case LogLevels.Debug:
+ if (propertyValues != null)
+ log.DebugFormat(messageTemplate, propertyValues);
+ else
+ log.Debug(messageTemplate);
+ break;
+ case LogLevels.Error:
+ if (propertyValues != null)
+ log.ErrorFormat(messageTemplate, propertyValues);
+ else
+ log.Error(messageTemplate);
+ break;
+ case LogLevels.Fatal:
+ if (propertyValues != null)
+ log.FatalFormat(messageTemplate, propertyValues);
+ else
+ log.Fatal(messageTemplate);
+ break;
+ case LogLevels.Info:
+ if (propertyValues != null)
+ log.InfoFormat(messageTemplate, propertyValues);
+ else
+ log.Info(messageTemplate);
+ break;
+ case LogLevels.Warn:
+ if (propertyValues != null)
+ log.WarnFormat(messageTemplate, propertyValues);
+ else
+ log.Warn(messageTemplate);
+ break;
+ }
+ }
+
+ ///
+ /// Make sure there are no newlines passed
+ ///
+ ///
+ ///
+ ///
+ public override void WriteLine(LogInfo logInfo, string messageTemplate, params object[] logParameters)
+ {
+ Write(logInfo, messageTemplate, logParameters);
+ }
+
+ ///
+ /// Test if a certain LogLevels enum is enabled
+ ///
+ /// LogLevels value
+ /// LogSource to check for
+ /// bool true if the LogLevels enum is enabled
+ public override bool IsLogLevelEnabled(LogLevels level, LogSource logSource = null)
+ {
+ var log = GetLogger(logSource);
+ switch (level)
+ {
+ case LogLevels.Verbose:
+ case LogLevels.Debug:
+ return log.IsDebugEnabled;
+ case LogLevels.Error:
+ return log.IsErrorEnabled;
+ case LogLevels.Fatal:
+ return log.IsFatalEnabled;
+ case LogLevels.Info:
+ return log.IsInfoEnabled;
+ case LogLevels.Warn:
+ return log.IsWarnEnabled;
+ }
+ return false;
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/Properties/AssemblyInfo.cs b/GreenshotJiraPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..5065d542c
--- /dev/null
+++ b/GreenshotJiraPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,47 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GreenshotJiraPlugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Jira Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: Plugin("GreenshotJiraPlugin.JiraPlugin", true)]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/GreenshotJiraPlugin/SvgImage.cs b/GreenshotJiraPlugin/SvgImage.cs
new file mode 100644
index 000000000..bb86e3264
--- /dev/null
+++ b/GreenshotJiraPlugin/SvgImage.cs
@@ -0,0 +1,118 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using GreenshotPlugin.Core;
+using Svg;
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// Create an image look like of the SVG
+ ///
+ public class SvgImage : IImage
+ {
+ private readonly SvgDocument _svgDocument;
+
+ private Image _imageClone;
+
+ ///
+ /// Factory to create via a stream
+ ///
+ /// Stream
+ /// IImage
+ public static IImage FromStream(Stream stream)
+ {
+ return new SvgImage(stream);
+ }
+
+ ///
+ /// Default constructor
+ ///
+ ///
+ public SvgImage(Stream stream)
+ {
+ _svgDocument = SvgDocument.Open(stream);
+ Height = (int)_svgDocument.ViewBox.Height;
+ Width = (int)_svgDocument.ViewBox.Width;
+ }
+
+ ///
+ /// Height of the image, can be set to change
+ ///
+ public int Height { get; set; }
+
+ ///
+ /// Width of the image, can be set to change.
+ ///
+ public int Width { get; set; }
+
+ ///
+ /// Size of the image
+ ///
+ public Size Size => new Size(Width, Height);
+
+ ///
+ /// Pixelformat of the underlying image
+ ///
+ public PixelFormat PixelFormat => Image.PixelFormat;
+
+ ///
+ /// Horizontal resolution of the underlying image
+ ///
+ public float HorizontalResolution => Image.HorizontalResolution;
+
+ ///
+ /// Vertical resolution of the underlying image
+ ///
+ public float VerticalResolution => Image.VerticalResolution;
+
+ ///
+ /// Unterlying image, or an on demand rendered version with different attributes as the original
+ ///
+ public Image Image
+ {
+ get
+ {
+ if (_imageClone?.Height == Height && _imageClone?.Width == Width)
+ {
+ return _imageClone;
+ }
+ // Calculate new image clone
+ _imageClone?.Dispose();
+ _imageClone = ImageHelper.CreateEmpty(Width, Height, PixelFormat.Format32bppArgb, Color.Transparent, 96, 96);
+ _svgDocument.Draw((Bitmap)_imageClone);
+ return _imageClone;
+
+ }
+ }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ _imageClone?.Dispose();
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-kab-DZ.xml b/GreenshotJiraPlugin/language_jiraplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-kab-DZ.xml
rename to GreenshotJiraPlugin/language_jiraplugin-kab-DZ.xml
diff --git a/GreenshotJiraPlugin/packages.config b/GreenshotJiraPlugin/packages.config
new file mode 100644
index 000000000..3562425cc
--- /dev/null
+++ b/GreenshotJiraPlugin/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRCommand/COMWrapper.cs b/GreenshotOCRCommand/COMWrapper.cs
new file mode 100644
index 000000000..4d9d7f11b
--- /dev/null
+++ b/GreenshotOCRCommand/COMWrapper.cs
@@ -0,0 +1,530 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Proxies;
+
+namespace Greenshot.Interop {
+ ///
+ /// Wraps a late-bound COM server.
+ ///
+ public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo {
+ private const int MK_E_UNAVAILABLE = -2147221021;
+ private const int CO_E_CLASSSTRING = -2147221005;
+
+ #region Private Data
+
+ ///
+ /// Holds reference to the actual COM object which is wrapped by this proxy
+ ///
+ private readonly object _comObject;
+
+ ///
+ /// Type of the COM object, set on constructor after getting the COM reference
+ ///
+ private readonly Type _comType;
+
+ ///
+ /// The type of which method calls are intercepted and executed on the COM object.
+ ///
+ private readonly Type _interceptType;
+
+ #endregion
+
+ #region Construction
+
+ ///
+ /// Gets a COM object and returns the transparent proxy which intercepts all calls to the object
+ ///
+ /// Interface which defines the method and properties to intercept
+ /// Transparent proxy to the real proxy for the object
+ /// T must be an interface decorated with the attribute.
+ public static T GetInstance() {
+ Type type = typeof(T);
+ if (null == type) {
+ throw new ArgumentNullException(nameof(T));
+ }
+ if (!type.IsInterface) {
+ throw new ArgumentException("The specified type must be an interface.", nameof(T));
+ }
+
+ ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type);
+ if (string.IsNullOrEmpty(progIdAttribute?.Value)) {
+ throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T));
+ }
+ string progId = progIdAttribute.Value;
+
+ object comObject = null;
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE)
+ {
+ Debug.WriteLine($"No current instance of {progId} object available.");
+ }
+ else if (comE.ErrorCode == CO_E_CLASSSTRING)
+ {
+ Debug.WriteLine($"Unknown progId {progId}");
+ }
+ } catch (Exception ex) {
+ Debug.WriteLine($"Error getting active object for {progId} {ex.Message}");
+ }
+
+ if (comObject != null) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ }
+ return default(T);
+ }
+
+ ///
+ /// Gets or creates a COM object and returns the transparent proxy which intercepts all calls to the object
+ /// The ComProgId can be a normal ComProgId or a GUID prefixed with "clsid:"
+ ///
+ /// Interface which defines the method and properties to intercept
+ /// Transparent proxy to the real proxy for the object
+ /// The type must be an interface decorated with the attribute.
+ public static T GetOrCreateInstance() {
+ Type type = typeof(T);
+ if (null == type) {
+ throw new ArgumentNullException(nameof(T));
+ }
+ if (!type.IsInterface) {
+ throw new ArgumentException("The specified type must be an interface.", nameof(T));
+ }
+
+ ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type);
+ if (string.IsNullOrEmpty(progIdAttribute?.Value)) {
+ throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T));
+ }
+
+ object comObject = null;
+ Type comType = null;
+ string progId = progIdAttribute.Value;
+
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE)
+ {
+ Debug.WriteLine($"No current instance of {progId} object available.");
+ }
+ else if (comE.ErrorCode == CO_E_CLASSSTRING)
+ {
+ Debug.WriteLine($"Unknown progId {progId}");
+ }
+ } catch (Exception ex) {
+ Debug.WriteLine($"Error getting active object for {progId} {ex.Message}");
+ }
+ // Did we get the current instance? If not, try to create a new
+ if (comObject == null) {
+ try {
+ comType = Type.GetTypeFromProgID(progId, true);
+ } catch (Exception) {
+ Debug.WriteLine($"Error getting type for {progId}");
+ }
+ if (comType != null) {
+ try {
+ comObject = Activator.CreateInstance(comType);
+ if (comObject != null) {
+ Debug.WriteLine($"Created new instance of {progId} object.");
+ }
+ } catch (Exception ex) {
+ Debug.WriteLine($"Error creating object for {progId} {ex.Message}");
+ }
+ }
+ }
+ if (comObject != null) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ }
+ return default(T);
+ }
+
+ ///
+ /// Wrap an object and return the transparent proxy which intercepts all calls to the object
+ ///
+ /// An object to intercept
+ /// Interface which defines the method and properties to intercept
+ /// Transparent proxy to the real proxy for the object
+ private static object Wrap(object comObject, Type type) {
+ if (null == comObject) {
+ throw new ArgumentNullException(nameof(comObject));
+ }
+ if (null == type) {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return wrapper.GetTransparentProxy();
+ }
+
+ ///
+ /// Constructor
+ ///
+ ///
+ /// The COM object to wrap.
+ ///
+ ///
+ /// The interface type to impersonate.
+ ///
+ private COMWrapper(object comObject, Type type)
+ : base(type) {
+ _comObject = comObject;
+ _comType = comObject.GetType();
+ _interceptType = type;
+ }
+
+ #endregion
+
+ #region Clean up
+
+ ///
+ /// If is not called, we need to make
+ /// sure that the COM object is still cleaned up.
+ ///
+ ~COMWrapper() {
+ Dispose(false);
+ }
+
+ ///
+ /// Cleans up the COM object.
+ ///
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Release the COM reference
+ ///
+ ///
+ /// if this was called from the
+ /// interface.
+ ///
+ private void Dispose(bool disposing) {
+ if (disposing && null != _comObject) {
+ if (Marshal.IsComObject(_comObject)) {
+ try {
+ while (Marshal.ReleaseComObject(_comObject) > 0)
+ {
+ }
+ } catch (Exception ex) {
+ Debug.WriteLine($"Problem releasing {_comType}");
+ Debug.WriteLine("Error: " + ex);
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region Object methods
+
+ ///
+ /// Returns a string representing the wrapped object.
+ ///
+ ///
+ /// The full name of the intercepted type.
+ ///
+ public override string ToString() {
+ return _interceptType.FullName;
+ }
+
+ ///
+ /// Returns the hash code of the wrapped object.
+ ///
+ ///
+ /// The hash code of the wrapped object.
+ ///
+ public override int GetHashCode() {
+ return _comObject.GetHashCode();
+ }
+
+ ///
+ /// Compares this object to another.
+ ///
+ ///
+ /// The value to compare to.
+ ///
+ ///
+ /// if the objects are equal.
+ ///
+ public override bool Equals(object value) {
+ if (null != value && RemotingServices.IsTransparentProxy(value)) {
+ COMWrapper wrapper = RemotingServices.GetRealProxy(value) as COMWrapper;
+ if (null != wrapper) {
+ return _comObject == wrapper._comObject;
+ }
+ }
+
+ return base.Equals(value);
+ }
+
+ ///
+ /// Returns the base type for a reference type.
+ ///
+ ///
+ /// The reference type.
+ ///
+ ///
+ /// The base value type.
+ ///
+ ///
+ /// is .
+ ///
+ private static Type GetByValType(Type byRefType) {
+ if (null == byRefType) {
+ throw new ArgumentNullException(nameof(byRefType));
+ }
+
+ if (byRefType.IsByRef) {
+ string name = byRefType.FullName;
+ name = name.Substring(0, name.Length - 1);
+ byRefType = byRefType.Assembly.GetType(name, true);
+ }
+
+ return byRefType;
+ }
+
+ #endregion
+
+ ///
+ /// Intercept method calls
+ ///
+ ///
+ /// Contains information about the method being called
+ ///
+ ///
+ /// A .
+ ///
+ public override IMessage Invoke(IMessage myMessage) {
+ IMethodCallMessage callMessage = myMessage as IMethodCallMessage;
+
+ MethodInfo method = callMessage?.MethodBase as MethodInfo;
+ if (method == null)
+ {
+ if (callMessage != null)
+ {
+ Debug.WriteLine($"Unrecognized Invoke call: {callMessage.MethodBase}");
+ }
+ return null;
+ }
+
+ object returnValue = null;
+ object[] outArgs = null;
+ int outArgsCount = 0;
+
+ string methodName = method.Name;
+ Type returnType = method.ReturnType;
+ BindingFlags flags = BindingFlags.InvokeMethod;
+ int argCount = callMessage.ArgCount;
+
+ ParameterModifier[] argModifiers = null;
+ ParameterInfo[] parameters = null;
+
+ if ("Dispose" == methodName && 0 == argCount && typeof(void) == returnType) {
+ Dispose();
+ } else if ("ToString" == methodName && 0 == argCount && typeof(string) == returnType) {
+ returnValue = ToString();
+ } else if ("GetType" == methodName && 0 == argCount && typeof(Type) == returnType) {
+ returnValue = _interceptType;
+ } else if ("GetHashCode" == methodName && 0 == argCount && typeof(int) == returnType) {
+ returnValue = GetHashCode();
+ } else if ("Equals" == methodName && 1 == argCount && typeof(bool) == returnType) {
+ returnValue = Equals(callMessage.Args[0]);
+ } else if (1 == argCount && typeof(void) == returnType && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) {
+ var handler = callMessage.InArgs[0] as Delegate;
+ if (null == handler) {
+ return new ReturnMessage(new ArgumentNullException(nameof(handler)), callMessage);
+ }
+ } else {
+ var invokeObject = _comObject;
+ var invokeType = _comType;
+
+ ParameterInfo parameter;
+ object[] args;
+ if (methodName.StartsWith("get_")) {
+ // Property Get
+ methodName = methodName.Substring(4);
+ flags = BindingFlags.GetProperty;
+ args = callMessage.InArgs;
+ } else if (methodName.StartsWith("set_")) {
+ // Property Set
+ methodName = methodName.Substring(4);
+ flags = BindingFlags.SetProperty;
+ args = callMessage.InArgs;
+ } else {
+ args = callMessage.Args;
+ if (null != args && 0 != args.Length) {
+ // Modifiers for ref / out parameters
+ argModifiers = new ParameterModifier[1];
+ argModifiers[0] = new ParameterModifier(args.Length);
+
+ parameters = method.GetParameters();
+ for (int i = 0; i < parameters.Length; i++) {
+ parameter = parameters[i];
+ if (parameter.IsOut || parameter.ParameterType.IsByRef) {
+ argModifiers[0][i] = true;
+ outArgsCount++;
+ }
+ }
+
+ if (0 == outArgsCount) {
+ argModifiers = null;
+ }
+ }
+ }
+
+ // Un-wrap wrapped COM objects before passing to the method
+ COMWrapper[] originalArgs;
+ COMWrapper wrapper;
+ Type byValType;
+ if (null == args || 0 == args.Length) {
+ originalArgs = null;
+ } else {
+ originalArgs = new COMWrapper[args.Length];
+ for (int i = 0; i < args.Length; i++) {
+ if (null != args[i] && RemotingServices.IsTransparentProxy(args[i])) {
+ wrapper = RemotingServices.GetRealProxy(args[i]) as COMWrapper;
+ if (null != wrapper) {
+ originalArgs[i] = wrapper;
+ args[i] = wrapper._comObject;
+ }
+ } else if (argModifiers != null && (0 != outArgsCount && argModifiers[0][i])) {
+ byValType = GetByValType(parameters[i].ParameterType);
+ if (byValType.IsInterface) {
+ // If we're passing a COM object by reference, and
+ // the parameter is null, we need to pass a
+ // DispatchWrapper to avoid a type mismatch exception.
+ if (null == args[i]) {
+ args[i] = new DispatchWrapper(null);
+ }
+ } else if (typeof(decimal) == byValType) {
+ // If we're passing a decimal value by reference,
+ // we need to pass a CurrencyWrapper to avoid a
+ // type mismatch exception.
+ // http://support.microsoft.com/?kbid=837378
+ args[i] = new CurrencyWrapper(args[i]);
+ }
+ }
+ }
+ }
+
+ try {
+ returnValue = invokeType.InvokeMember(methodName, flags, null, invokeObject, args, argModifiers, null, null);
+ } catch (Exception ex) {
+ return new ReturnMessage(ex, callMessage);
+ }
+
+ // Handle enum and interface return types
+ if (null != returnValue) {
+ if (returnType.IsInterface) {
+ // Wrap the returned value in an intercepting COM wrapper
+ if (Marshal.IsComObject(returnValue)) {
+ returnValue = Wrap(returnValue, returnType);
+ }
+ } else if (returnType.IsEnum) {
+ // Convert to proper Enum type
+ returnValue = Enum.Parse(returnType, returnValue.ToString());
+ }
+ }
+
+ // Handle out args
+ if (0 != outArgsCount) {
+ if (args != null && parameters != null)
+ {
+ outArgs = new object[args.Length];
+ for (int i = 0; i < parameters.Length; i++) {
+ if (argModifiers != null && !argModifiers[0][i]) {
+ continue;
+ }
+
+ var arg = args[i];
+ if (null == arg) {
+ continue;
+ }
+
+ parameter = parameters[i];
+ wrapper = null;
+
+ byValType = GetByValType(parameter.ParameterType);
+ if (typeof(decimal) == byValType) {
+ if (arg is CurrencyWrapper) {
+ arg = ((CurrencyWrapper)arg).WrappedObject;
+ }
+ } else if (byValType.IsEnum) {
+ arg = Enum.Parse(byValType, arg.ToString());
+ } else if (byValType.IsInterface) {
+ if (Marshal.IsComObject(arg)) {
+ if (originalArgs != null)
+ {
+ wrapper = originalArgs[i];
+ }
+ if (null != wrapper && wrapper._comObject != arg) {
+ wrapper.Dispose();
+ wrapper = null;
+ }
+
+ if (null == wrapper) {
+ wrapper = new COMWrapper(arg, byValType);
+ }
+ arg = wrapper.GetTransparentProxy();
+ }
+ }
+ outArgs[i] = arg;
+ }
+ }
+ }
+ }
+
+ return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage);
+ }
+
+ ///
+ /// Implementation for the interface IRemotingTypeInfo
+ /// This makes it possible to cast the COMWrapper
+ ///
+ /// Type to cast to
+ /// object to cast
+ ///
+ public bool CanCastTo(Type toType, object o) {
+ bool returnValue = _interceptType.IsAssignableFrom(toType);
+ return returnValue;
+ }
+
+ ///
+ /// Implementation for the interface IRemotingTypeInfo
+ ///
+ public string TypeName {
+ get {
+ throw new NotSupportedException();
+ }
+ set {
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
diff --git a/GreenshotOCRCommand/ComProgIdAttribute.cs b/GreenshotOCRCommand/ComProgIdAttribute.cs
new file mode 100644
index 000000000..05fd69237
--- /dev/null
+++ b/GreenshotOCRCommand/ComProgIdAttribute.cs
@@ -0,0 +1,78 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+
+namespace Greenshot.Interop {
+ ///
+ /// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner)
+ ///
+ [AttributeUsage(AttributeTargets.Interface)]
+ public sealed class ComProgIdAttribute : Attribute {
+ ///
+ /// Extracts the attribute from the specified type.
+ ///
+ ///
+ /// The interface type.
+ ///
+ ///
+ /// The .
+ ///
+ ///
+ /// is .
+ ///
+ public static ComProgIdAttribute GetAttribute(Type interfaceType) {
+ if (null == interfaceType) {
+ throw new ArgumentNullException(nameof(interfaceType));
+ }
+
+ Type attributeType = typeof(ComProgIdAttribute);
+ object[] attributes = interfaceType.GetCustomAttributes(attributeType, false);
+
+ if (0 == attributes.Length) {
+ Type[] interfaces = interfaceType.GetInterfaces();
+ for (int i = 0; i < interfaces.Length; i++) {
+ interfaceType = interfaces[i];
+ attributes = interfaceType.GetCustomAttributes(attributeType, false);
+ if (0 != attributes.Length) {
+ break;
+ }
+ }
+ }
+
+ if (0 == attributes.Length) {
+ return null;
+ }
+ return (ComProgIdAttribute)attributes[0];
+ }
+
+ /// Constructor
+ /// The COM ProgID.
+ public ComProgIdAttribute(string value) {
+ Value = value;
+ }
+
+ ///
+ /// Returns the COM ProgID
+ ///
+ public string Value { get; }
+ }
+}
diff --git a/GreenshotOCRCommand/GreenshotOCRCommand.csproj b/GreenshotOCRCommand/GreenshotOCRCommand.csproj
new file mode 100644
index 000000000..b9645113d
--- /dev/null
+++ b/GreenshotOCRCommand/GreenshotOCRCommand.csproj
@@ -0,0 +1,92 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}
+ WinExe
+ Properties
+ GreenshotOCRCommand
+ GreenshotOCRCommand
+ v2.0
+ 512
+ OnBuildSuccess
+ False
+ False
+ false
+ False
+ Off
+ 4194304
+ x86
+
+
+
+
+ 3.5
+
+
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ None
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+ GreenshotOCRCommand.Program
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\GreenshotOCRPlugin"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\GreenshotOCRPlugin"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName).config" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\GreenshotOCRPlugin"
+
+
+
+ False
+
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs b/GreenshotOCRCommand/Modi/CompressionLevel.cs
similarity index 66%
rename from src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs
rename to GreenshotOCRCommand/Modi/CompressionLevel.cs
index 10ea7556c..a8bc9e34a 100644
--- a/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs
+++ b/GreenshotOCRCommand/Modi/CompressionLevel.cs
@@ -1,29 +1,29 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Jira.Forms
-{
- public class JiraFormBase : GreenshotForm
- {
- }
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ public enum CompressionLevel {
+ miCOMP_LEVEL_LOW = 0,
+ miCOMP_LEVEL_MEDIUM = 1,
+ miCOMP_LEVEL_HIGH = 2
+ }
}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/FileFormat.cs b/GreenshotOCRCommand/Modi/FileFormat.cs
new file mode 100644
index 000000000..cbf061333
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/FileFormat.cs
@@ -0,0 +1,30 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCR
+{
+ public enum FileFormat {
+ miFILE_FORMAT_DEFAULTVALUE = -1,
+ miFILE_FORMAT_TIFF = 1,
+ miFILE_FORMAT_TIFF_LOSSLESS = 2,
+ miFILE_FORMAT_MDI = 4
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/ICommon.cs b/GreenshotOCRCommand/Modi/ICommon.cs
new file mode 100644
index 000000000..ecdf4052d
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ICommon.cs
@@ -0,0 +1,32 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Base class for the common properties of the Modi interfaces
+ ///
+ public interface ICommon : IDisposable {
+ IDocument Application { get; }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/IDispatch.cs b/GreenshotOCRCommand/Modi/IDispatch.cs
new file mode 100644
index 000000000..22235153d
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IDispatch.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.CustomMarshalers;
+
+namespace GreenshotOCRCommand.Modi {
+ [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IDispatch {
+ void Reserved();
+ [PreserveSig]
+ int GetTypeInfo(uint nInfo, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo);
+ }
+}
diff --git a/GreenshotOCRCommand/Modi/IDocument.cs b/GreenshotOCRCommand/Modi/IDocument.cs
new file mode 100644
index 000000000..7913ece5f
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IDocument.cs
@@ -0,0 +1,82 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Interop;
+using GreenshotOCR;
+
+namespace GreenshotOCRCommand.Modi {
+ ///
+ /// The MODI Document object represents an ordered collection of document images saved as a single file.
+ /// You can use the Create method to load an existing MDI or TIF file, or to create an empty document that you can populate with images from other documents.
+ /// The OCR method performs OCR on all pages in the document, and the OnOCRProgress event reports the status of the operation and allows the user to cancel it.
+ /// The Dirty property lets you know whether your document has unsaved OCR results or changes.
+ /// The SaveAs method allows you to specify an image file format and a compression level.
+ /// You can also use the PrintOut method to print the document to a printer or a file.
+ ///
+ [ComProgId("MODI.Document")]
+ public interface IDocument : ICommon {
+ ///
+ /// Closes the document.
+ ///
+ ///
+ void Close(bool saveCall);
+
+ ///
+ /// The document's collection of pages.
+ ///
+ IImages Images
+ {
+ get;
+ }
+
+ ///
+ /// Occurs periodically during an optical character recognition (OCR) operation. Returns the estimated percentage of the OCR operation that is complete, and allows the user to cancel the operation.
+ ///
+ // event OnOCRProgress { get; }
+
+ ///
+ /// Indicates whether the active document has unsaved changes.
+ ///
+ bool Dirty { get; }
+
+ ///
+ /// Creates a new document.
+ ///
+ /// Optional String. The path and filename of the optional document file that is to be loaded into the new document.
+ void Create(string file);
+
+ ///
+ /// Performs optical character recognition (OCR) on the specified document or image.
+ ///
+ /// ModiLanguage
+ /// Optional Boolean. Specifies whether the OCR engine attempts to determine the orientation of the page. Default is true.
+ /// Optional Boolean. Specifies whether the OCR engine attempts to "de-skew" the page to correct for small angles of misalignment from the vertical. Default is true.
+ void OCR(ModiLanguage language, bool orientimage, bool straightenImage);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ void SaveAs(string filename, FileFormat fileFormat, CompressionLevel compressionLevel);
+ }
+}
diff --git a/GreenshotOCRCommand/Modi/IImage.cs b/GreenshotOCRCommand/Modi/IImage.cs
new file mode 100644
index 000000000..fd7dd3c06
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IImage.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Describes the page in a scan
+ ///
+ public interface IImage : ICommon {
+ ILayout Layout {
+ get;
+ }
+
+ long BitsPerPixel { get; }
+ CompressionLevel Compression { get; }
+ //IPictureDisp Picture { get; }
+ int PixelHeight { get; }
+ int PixelWidth { get; }
+ //IPictureDisp Thumbnail { get; }
+ int XDPI { get; }
+ int YDPI { get; }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/IImages.cs b/GreenshotOCRCommand/Modi/IImages.cs
new file mode 100644
index 000000000..885dd1bba
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IImages.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections;
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Use the Images accessor property of the Document object to return an Images collection.
+ /// Use the Item property of the Images collection to return an Image object and gain access to its OCR Layout
+ /// (including recognized Text and Words), the properties that describe its dimensions and format (BitsPerPixel, Compression, PixelHeight, PixelWidth, XDPI, and YDPI),
+ /// and its Picture and Thumbnail images.
+ ///
+ public interface IImages : ICommon, IEnumerable {
+ int Count {
+ get;
+ }
+ IImage this [int index] {
+ get;
+ }
+ new IEnumerator GetEnumerator();
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/ILayout.cs b/GreenshotOCRCommand/Modi/ILayout.cs
new file mode 100644
index 000000000..ca7b43322
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ILayout.cs
@@ -0,0 +1,55 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Layout of the IImage
+ ///
+ public interface ILayout : ICommon {
+ ///
+ /// Returns the recognized text as a Unicode string.
+ ///
+ string Text {
+ get;
+ }
+
+ ///
+ /// An accessor property that returns the Words collection recognized in the text during an optical character recognition (OCR) operation.
+ ///
+ IWords Words { get; }
+
+ ///
+ /// Returns the number of characters in the recognized text.
+ ///
+ int NumChars { get; }
+
+ ///
+ /// Returns the number of words in the recognized text.
+ ///
+ int NumWords { get; }
+
+ ///
+ /// Returns the language identifier for the recognized text. Read-only Long.
+ ///
+ ModiLanguage Language { get; }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/IMiRect.cs b/GreenshotOCRCommand/Modi/IMiRect.cs
new file mode 100644
index 000000000..18ac6b0e8
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IMiRect.cs
@@ -0,0 +1,48 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Represents a bounding rectangle in the optical character recognition (OCR) layout.
+ ///
+ public interface IMiRect : ICommon {
+ ///
+ /// The Bottom property represent the distance in pixels from the top edge of the containing image.
+ ///
+ int Bottom { get; }
+
+ ///
+ /// The Left property represent the distance in pixels from the left edge of the containing image.
+ ///
+ int Left { get; }
+
+ ///
+ /// The Right property represent the distance in pixels from the left edge of the containing image.
+ ///
+ int Right { get; }
+
+ ///
+ /// The Top property represent the distance in pixels from the top edge of the containing image.
+ ///
+ int Top { get; }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/IMiRects.cs b/GreenshotOCRCommand/Modi/IMiRects.cs
new file mode 100644
index 000000000..9981bdd5f
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IMiRects.cs
@@ -0,0 +1,38 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections;
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Represents the collection of bounding rectangles in the optical character recognition (OCR) layout. A collection of MiRect objects.
+ ///
+ public interface IMiRects : ICommon, IEnumerable {
+ int Count {
+ get;
+ }
+ IMiRect this [int index] {
+ get;
+ }
+ new IEnumerator GetEnumerator();
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Modi/IWord.cs b/GreenshotOCRCommand/Modi/IWord.cs
new file mode 100644
index 000000000..8e7895f8c
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IWord.cs
@@ -0,0 +1,65 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// Represents a word recognized in the text during an optical character recognition (OCR) operation.
+ ///
+ public interface IWord : ICommon
+ {
+ ///
+ /// Returns the index of the specified word in the Words collection of the Layout or IMiSelectableItem object.
+ ///
+ long Id { get; }
+
+ ///
+ /// Returns the number of the region in the optical character recognition (OCR) layout where the word occurs.
+ ///
+ long RegionId { get; }
+
+ ///
+ /// Returns the number of the line in the optical character recognition (OCR) layout where the word occurs.
+ ///
+ long LineId { get; }
+
+ ///
+ /// Returns the recognized text as a Unicode string.
+ ///
+ string Text { get; }
+
+ ///
+ /// Returns the relative confidence factor reported by the optical character recognition (OCR) engine (on a scale of 0 to 999) after recognizing the specified word.
+ ///
+ short RecognitionConfidence { get; }
+
+ ///
+ /// Returns the index of the font used by the specified wordthis is the font that was recognized in the text during an optical character recognition (OCR) operation.
+ ///
+ long FontId { get; }
+
+ ///
+ /// Rectangles
+ ///
+ IMiRects Rects { get; }
+
+ }
+}
diff --git a/GreenshotOCRCommand/Modi/IWords.cs b/GreenshotOCRCommand/Modi/IWords.cs
new file mode 100644
index 000000000..b26b6f0c3
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IWords.cs
@@ -0,0 +1,43 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections;
+
+namespace GreenshotOCRCommand.Modi
+{
+ ///
+ /// The Words collection recognized in the text during an optical character recognition (OCR) operation.
+ ///
+ public interface IWords : ICommon, IEnumerable
+ {
+ int Count
+ {
+ get;
+ }
+
+ IWord this[int index]
+ {
+ get;
+ }
+
+ new IEnumerator GetEnumerator();
+ }
+}
diff --git a/GreenshotOCRCommand/Modi/ModiLanguage.cs b/GreenshotOCRCommand/Modi/ModiLanguage.cs
new file mode 100644
index 000000000..d062a4cb9
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ModiLanguage.cs
@@ -0,0 +1,48 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotOCRCommand.Modi
+{
+ public enum ModiLanguage {
+ CHINESE_SIMPLIFIED = 2052,
+ CHINESE_TRADITIONAL = 1028,
+ CZECH = 5,
+ DANISH = 6,
+ DUTCH = 19,
+ ENGLISH = 9,
+ FINNISH = 11,
+ FRENCH = 12,
+ GERMAN = 7,
+ GREEK = 8,
+ HUNGARIAN = 14,
+ ITALIAN = 16,
+ JAPANESE = 17,
+ KOREAN = 18,
+ NORWEGIAN = 20,
+ POLISH = 21,
+ PORTUGUESE = 22,
+ RUSSIAN = 25,
+ SPANISH = 10,
+ SWEDISH = 29,
+ TURKISH = 31,
+ SYSDEFAULT = 2048
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRCommand/Program.cs b/GreenshotOCRCommand/Program.cs
new file mode 100644
index 000000000..6f7fe33a1
--- /dev/null
+++ b/GreenshotOCRCommand/Program.cs
@@ -0,0 +1,122 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using Greenshot.Interop;
+using GreenshotOCRCommand.Modi;
+
+namespace GreenshotOCRCommand {
+ public class Program {
+ private const string Usage = "<-c> | [language] [orientimage] [straightenImage]";
+ public static int Main(string[] args) {
+ if (args.Length == 0) {
+ Console.WriteLine(Usage);
+ return -1;
+ }
+ string filename = args[0];
+ ModiLanguage language = ModiLanguage.ENGLISH;
+ if (args.Length >= 2) {
+ language = (ModiLanguage)Enum.Parse(typeof(ModiLanguage), args[1]);
+ }
+ bool orientimage = true;
+ if (args.Length >= 3) {
+ orientimage = bool.Parse(args[2]);
+ }
+ bool straightenImage = true;
+ if (args.Length >= 4) {
+ straightenImage = bool.Parse(args[3]);
+ }
+ try {
+ if (File.Exists(filename) || "-c".Equals(filename)) {
+ using (var document = COMWrapper.GetOrCreateInstance()) {
+ if (document == null) {
+ Console.WriteLine("MODI not installed");
+ return -2;
+ }
+ if ("-c".Equals(filename)) {
+ return 0;
+ }
+ document.Create(filename);
+ document.OCR(language, orientimage, straightenImage);
+ var modiImage = document.Images[0];
+ var layout = modiImage.Layout;
+ if (layout != null)
+ {
+#if DEBUG
+ if (layout.Words != null)
+ {
+ foreach (var word in ToEnumerable(layout.Words))
+ {
+ if (word.Rects != null)
+ {
+ foreach (var rect in ToEnumerable(word.Rects))
+ {
+ Debug.WriteLine($"Rect {rect.Left},{rect.Top},{rect.Right},{rect.Bottom} - Word {word.Text} : Confidence: {word.RecognitionConfidence}");
+ }
+ }
+ }
+ }
+#endif
+ if (layout.Text != null)
+ {
+ // For for BUG-1884:
+ // Although trim is done in the OCR Plugin, it does make sense in the command too.
+ Console.WriteLine(layout.Text.Trim());
+ }
+ }
+ document.Close(false);
+ return 0;
+ }
+ }
+ } catch (Exception ex) {
+ Console.WriteLine(ex.Message);
+ }
+ return -1;
+ }
+
+ ///
+ /// Helper method
+ ///
+ /// IEnumerable of IMiRect
+ private static IEnumerable ToEnumerable(IMiRects rects)
+ {
+ for (int i = 0; i < rects.Count; i++)
+ {
+ yield return rects[i];
+ }
+ }
+
+ ///
+ /// Helper method
+ ///
+ /// IEnumerable of IWord
+ private static IEnumerable ToEnumerable(IWords words)
+ {
+ for (int i = 0; i < words.Count; i++)
+ {
+ yield return words[i];
+ }
+ }
+ }
+}
diff --git a/GreenshotOCRCommand/Properties/AssemblyInfo.cs b/GreenshotOCRCommand/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..00eb68097
--- /dev/null
+++ b/GreenshotOCRCommand/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("GreenshotOCRCommand")]
+[assembly: AssemblyDescription("A small executable to OCR a bitmap")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("GreenshotOCRCommand")]
+[assembly: AssemblyCopyright("Greenshot")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("d7668e7e-3018-4d27-9aa0-21b1afade1b8")]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/GreenshotOCRCommand/app.config b/GreenshotOCRCommand/app.config
new file mode 100644
index 000000000..2dcad202f
--- /dev/null
+++ b/GreenshotOCRCommand/app.config
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj
new file mode 100644
index 000000000..22257a2c1
--- /dev/null
+++ b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj
@@ -0,0 +1,101 @@
+
+
+
+
+ {C6988EE8-2FEE-4349-9F09-F9628A0D8965}
+ Library
+ GreenshotOCR
+ GreenshotOCRPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ OnBuildSuccess
+
+
+
+ 3.5
+
+
+
+
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+
+
+
+
+ Form
+
+
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+ False
+ Off
+ 4194304
+ x86
+ 4096
+
+
+ False
+ Off
+ 4194304
+ AnyCPU
+ 4096
+
+
+ Full
+ true
+ DEBUG;TRACE
+ False
+ True
+
+
+ None
+ false
+ TRACE
+ True
+ False
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml
new file mode 100644
index 000000000..eb225ae3e
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml
@@ -0,0 +1,8 @@
+
+
+
+ Jazyk pro OCR
+ Orientaci obrázku
+ Srovnat obrázek
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml
new file mode 100644
index 000000000..a5743f569
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Sprache für OCR
+
+
+ Bild ausrichten
+
+
+ Bild glätten
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml
new file mode 100644
index 000000000..6412a02f6
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Language for OCR
+
+
+ Orient image
+
+
+ Straighten image
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml
new file mode 100644
index 000000000..9e3c8126d
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml
@@ -0,0 +1,8 @@
+
+
+
+ Langage pour l'OCR
+ Orienter l'image
+ Redresser l'image
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml
new file mode 100644
index 000000000..e828076e2
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml
@@ -0,0 +1,8 @@
+
+
+
+ Bahasa untuk OCR
+ Orientasikan gambar
+ Rapikan gambar
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml
new file mode 100644
index 000000000..670f233e2
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Lingua OCR
+
+
+ Orienta
+
+
+ Raddrizza
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml
new file mode 100644
index 000000000..3d884a724
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml
@@ -0,0 +1,8 @@
+
+
+
+ Tutlayt i OCR
+ Wehhi tugna
+ Seggwem tugna
+
+
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml
new file mode 100644
index 000000000..e35bfe3b8
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ OCR 언어
+
+
+ 가로 이미지
+
+
+ 세로 이미지
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml
new file mode 100644
index 000000000..463aa73fb
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ OCR valoda
+
+
+ Pagriezt attēlu
+
+
+ Iztaisnot attēlu
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml
new file mode 100644
index 000000000..dac711d25
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Taal voor OCR
+
+
+ Beeld richten
+
+
+ Beeld vereffenen
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml
new file mode 100644
index 000000000..37b40b65a
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml
@@ -0,0 +1,8 @@
+
+
+
+ Język dla OCR
+ Orientacja obrazu
+ Wyprostowanie obrazów
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml
new file mode 100644
index 000000000..ee55958d8
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml
@@ -0,0 +1,8 @@
+
+
+
+ Idioma para OCR
+ Orientar imagem
+ Endireitar imagem
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml
new file mode 100644
index 000000000..f2fffd34e
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml
@@ -0,0 +1,8 @@
+
+
+
+ Язык для OCR
+ Ориентация изображения
+ Выпрямление изображения
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml
new file mode 100644
index 000000000..0f61ec429
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Jazyk pre OCR
+
+
+ Orientácia obrázku
+
+
+ Narovnať obrázok
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml
new file mode 100644
index 000000000..eaf252bd6
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml
@@ -0,0 +1,8 @@
+
+
+
+ Језик за препознавање знакова
+ Усмери слику
+ Исправи слику
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml
new file mode 100644
index 000000000..e59ce5e75
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Språk för OCR
+
+
+ Orientera bild
+
+
+ Släta ut bild
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml
new file mode 100644
index 000000000..7a433eb4f
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml
@@ -0,0 +1,8 @@
+
+
+
+ Мова для ОРТ
+ Орієнтувати зображення
+ Випрямлення зображення
+
+
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml
new file mode 100644
index 000000000..ccd0e159a
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ OCR语言
+
+
+ 图像定位
+
+
+ 图像矫正
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml
new file mode 100644
index 000000000..dce00e4cf
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml
@@ -0,0 +1,8 @@
+
+
+
+ OCR 語言
+ 定向圖片
+ 拉直圖片
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/OCRConfiguration.cs b/GreenshotOCRPlugin/OCRConfiguration.cs
new file mode 100644
index 000000000..75ccf0c14
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRConfiguration.cs
@@ -0,0 +1,36 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using Greenshot.IniFile;
+
+namespace GreenshotOCR {
+ ///
+ /// Description of CoreConfiguration.
+ ///
+ [IniSection("OCR", Description="Greenshot OCR Plugin configuration")]
+ public class OCRConfiguration : IniSection {
+ [IniProperty("Language", Description="Language for OCR", DefaultValue="miLANG_ENGLISH")]
+ public string Language { get; set; }
+ [IniProperty("orientimage", Description="Orient image?", DefaultValue="true")]
+ public bool Orientimage { get; set; }
+ [IniProperty("straightenImage", Description="Straighten image?", DefaultValue="true")]
+ public bool StraightenImage { get; set; }
+ }
+}
diff --git a/GreenshotOCRPlugin/OCRDestination.cs b/GreenshotOCRPlugin/OCRDestination.cs
new file mode 100644
index 000000000..69503cc3b
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRDestination.cs
@@ -0,0 +1,59 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Drawing;
+using System.IO;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotOCR {
+ ///
+ /// Description of OCRDestination.
+ ///
+ public class OCRDestination : AbstractDestination {
+ private readonly OcrPlugin _plugin;
+
+ public override string Designation => "OCR";
+
+ public override string Description => "OCR";
+
+ public override Image DisplayIcon {
+ get {
+ string exePath = PluginUtils.GetExePath("MSPVIEW.EXE");
+ if (exePath != null && File.Exists(exePath)) {
+ return PluginUtils.GetCachedExeIcon(exePath, 0);
+ }
+ return null;
+ }
+ }
+
+ public OCRDestination(OcrPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description)
+ {
+ ExportMade = _plugin.DoOcr(surface) != null
+ };
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotOCRPlugin/OCRForm.cs b/GreenshotOCRPlugin/OCRForm.cs
new file mode 100644
index 000000000..468b31bac
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRForm.cs
@@ -0,0 +1,30 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace GreenshotOCR {
+ ///
+ /// This class is needed for design-time resolving of the language files
+ ///
+ public class OcrForm : GreenshotForm {
+ }
+}
diff --git a/GreenshotOCRPlugin/OCRPlugin.cs b/GreenshotOCRPlugin/OCRPlugin.cs
new file mode 100644
index 000000000..992e6ea96
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRPlugin.cs
@@ -0,0 +1,240 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Effects;
+
+//using Microsoft.Win32;
+
+namespace GreenshotOCR {
+ // Needed for the drop down, available languages for OCR
+ public enum ModiLanguage {
+ CHINESE_SIMPLIFIED = 2052,
+ CHINESE_TRADITIONAL = 1028,
+ CZECH = 5,
+ DANISH = 6,
+ DUTCH = 19,
+ ENGLISH = 9,
+ FINNISH = 11,
+ FRENCH = 12,
+ GERMAN = 7,
+ GREEK = 8,
+ HUNGARIAN = 14,
+ ITALIAN = 16,
+ JAPANESE = 17,
+ KOREAN = 18,
+ NORWEGIAN = 20,
+ POLISH = 21,
+ PORTUGUESE = 22,
+ RUSSIAN = 25,
+ SPANISH = 10,
+ SWEDISH = 29,
+ TURKISH = 31,
+ SYSDEFAULT = 2048
+ }
+ ///
+ /// OCR Plugin Greenshot
+ ///
+ public class OcrPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OcrPlugin));
+ private string _ocrCommand;
+ private static OCRConfiguration config;
+ private PluginAttribute _myAttributes;
+ private ToolStripMenuItem _ocrMenuItem = new ToolStripMenuItem();
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_ocrMenuItem != null) {
+ _ocrMenuItem.Dispose();
+ _ocrMenuItem = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new OCRDestination(this);
+ }
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ /// true if plugin is initialized, false if not (doesn't show)
+ public virtual bool Initialize(IGreenshotHost greenshotHost, PluginAttribute myAttributes) {
+ Log.Debug("Initialize called of " + myAttributes.Name);
+ _myAttributes = myAttributes;
+
+ var ocrDirectory = Path.GetDirectoryName(myAttributes.DllFile);
+ if (ocrDirectory == null)
+ {
+ return false;
+ }
+ _ocrCommand = Path.Combine(ocrDirectory, "greenshotocrcommand.exe");
+
+ if (!HasModi()) {
+ Log.Warn("No MODI found!");
+ return false;
+ }
+ // Load configuration
+ config = IniConfig.GetIniSection();
+
+ if (config.Language != null) {
+ config.Language = config.Language.Replace("miLANG_","").Replace("_"," ");
+ }
+ return true;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Shutdown
+ ///
+ public void Shutdown() {
+ Log.Debug("Shutdown of " + _myAttributes.Name);
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ if (!HasModi()) {
+ MessageBox.Show("Sorry, is seems that Microsoft Office Document Imaging (MODI) is not installed, therefor the OCR Plugin cannot work.");
+ return;
+ }
+ SettingsForm settingsForm = new SettingsForm(Enum.GetNames(typeof(ModiLanguage)), config);
+ DialogResult result = settingsForm.ShowDialog();
+ if (result == DialogResult.OK) {
+ // "Re"set hotkeys
+ IniConfig.Save();
+ }
+ }
+
+
+ private const int MinWidth = 130;
+ private const int MinHeight = 130;
+ ///
+ /// Handling of the CaptureTaken "event" from the ICaptureHost
+ /// We do the OCR here!
+ ///
+ /// Has the Image and the capture details
+ public string DoOcr(ISurface surface) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 0, true)
+ {
+ ReduceColors = true,
+ SaveBackgroundOnly = true
+ };
+ // We only want the background
+ // Force Grayscale output
+ outputSettings.Effects.Add(new GrayscaleEffect());
+
+ // Also we need to check the size, resize if needed to 130x130 this is the minimum
+ if (surface.Image.Width < MinWidth || surface.Image.Height < MinHeight) {
+ int addedWidth = MinWidth - surface.Image.Width;
+ if (addedWidth < 0) {
+ addedWidth = 0;
+ }
+ int addedHeight = MinHeight - surface.Image.Height;
+ if (addedHeight < 0) {
+ addedHeight = 0;
+ }
+ IEffect effect = new ResizeCanvasEffect(addedWidth / 2, addedWidth / 2, addedHeight / 2, addedHeight / 2);
+ outputSettings.Effects.Add(effect);
+ }
+ var filePath = ImageOutput.SaveToTmpFile(surface, outputSettings, null);
+
+ Log.Debug("Saved tmp file to: " + filePath);
+
+ string text = "";
+ try {
+ ProcessStartInfo processStartInfo = new ProcessStartInfo(_ocrCommand, "\"" + filePath + "\" " + config.Language + " " + config.Orientimage + " " + config.StraightenImage)
+ {
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ UseShellExecute = false
+ };
+ using (Process process = Process.Start(processStartInfo)) {
+ if (process != null)
+ {
+ process.WaitForExit(30 * 1000);
+ if (process.ExitCode == 0) {
+ text = process.StandardOutput.ReadToEnd();
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.Error("Error while calling Microsoft Office Document Imaging (MODI) to OCR: ", e);
+ } finally {
+ if (File.Exists(filePath)) {
+ Log.Debug("Cleaning up tmp file: " + filePath);
+ File.Delete(filePath);
+ }
+ }
+
+ if (string.IsNullOrEmpty(text)) {
+ Log.Info("No text returned");
+ return null;
+ }
+
+ // For for BUG-1884:
+ text = text.Trim();
+
+ try {
+ Log.DebugFormat("Pasting OCR Text to Clipboard: {0}", text);
+ // Paste to Clipboard (the Plugin currently doesn't have access to the ClipboardHelper from Greenshot
+ IDataObject ido = new DataObject();
+ ido.SetData(DataFormats.Text, true, text);
+ Clipboard.SetDataObject(ido, true);
+ } catch (Exception e) {
+ Log.Error("Problem pasting text to clipboard: ", e);
+ }
+ return text;
+ }
+
+ private bool HasModi() {
+ try {
+ using (Process process = Process.Start(_ocrCommand, "-c")) {
+ if (process != null)
+ {
+ process.WaitForExit();
+ return process.ExitCode == 0;
+ }
+ }
+ } catch(Exception e) {
+ Log.DebugFormat("Error trying to initiate MODI: {0}", e.Message);
+ }
+ Log.InfoFormat("No Microsoft Office Document Imaging (MODI) found, disabling OCR");
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Properties/AssemblyInfo.cs b/GreenshotOCRPlugin/Properties/AssemblyInfo.cs
similarity index 56%
rename from src/Greenshot.Plugin.GooglePhotos/Properties/AssemblyInfo.cs
rename to GreenshotOCRPlugin/Properties/AssemblyInfo.cs
index 3ff014500..d895fbe59 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Properties/AssemblyInfo.cs
+++ b/GreenshotOCRPlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,22 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyDescription("A plugin to upload images to GooglePhotos")]
-
-// Still using the old name 'Picasa-Web Plugin' as identifier for backwards compatibility
-// TODO: replace plugin identifier with "GooglePhotos Plugin" in the future
-[assembly: AssemblyPluginIdentifier("Picasa-Web Plugin")]
+[assembly: AssemblyTitle("GreenshotOCR")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("OCR Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotOCR.OcrPlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/GreenshotOCRPlugin/SettingsForm.Designer.cs b/GreenshotOCRPlugin/SettingsForm.Designer.cs
new file mode 100644
index 000000000..23506ad8b
--- /dev/null
+++ b/GreenshotOCRPlugin/SettingsForm.Designer.cs
@@ -0,0 +1,146 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotOCR
+{
+ partial class SettingsForm
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.comboBox_languages = new System.Windows.Forms.ComboBox();
+ this.checkBox_orientImage = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.checkBox_straightenImage = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.label_language = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.SuspendLayout();
+ //
+ // comboBox_languages
+ //
+ this.comboBox_languages.FormattingEnabled = true;
+ this.comboBox_languages.Items.AddRange(new object[] {
+ "English",
+ "Deutsch"});
+ this.comboBox_languages.Location = new System.Drawing.Point(74, 12);
+ this.comboBox_languages.Name = "comboBox_languages";
+ this.comboBox_languages.Size = new System.Drawing.Size(153, 21);
+ this.comboBox_languages.TabIndex = 1;
+ //
+ // checkBox_orientImage
+ //
+ this.checkBox_orientImage.LanguageKey = "ocr.orient_image";
+ this.checkBox_orientImage.Location = new System.Drawing.Point(13, 68);
+ this.checkBox_orientImage.Name = "checkBox_orientImage";
+ this.checkBox_orientImage.PropertyName = "orientimage";
+ this.checkBox_orientImage.SectionName = "OCR";
+ this.checkBox_orientImage.Size = new System.Drawing.Size(104, 24);
+ this.checkBox_orientImage.TabIndex = 3;
+ this.checkBox_orientImage.UseVisualStyleBackColor = true;
+ //
+ // checkBox_straightenImage
+ //
+ this.checkBox_straightenImage.LanguageKey = "ocr.straighten_image";
+ this.checkBox_straightenImage.Location = new System.Drawing.Point(13, 41);
+ this.checkBox_straightenImage.Name = "checkBox_straightenImage";
+ this.checkBox_straightenImage.PropertyName = "straightenImage";
+ this.checkBox_straightenImage.SectionName = "OCR";
+ this.checkBox_straightenImage.Size = new System.Drawing.Size(109, 24);
+ this.checkBox_straightenImage.TabIndex = 2;
+ this.checkBox_straightenImage.UseVisualStyleBackColor = true;
+ //
+ // label_language
+ //
+ this.label_language.LanguageKey = "ocr.language";
+ this.label_language.Location = new System.Drawing.Point(13, 15);
+ this.label_language.Name = "label_language";
+ this.label_language.Size = new System.Drawing.Size(55, 23);
+ this.label_language.TabIndex = 3;
+ //
+ // buttonOK
+ //
+ this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.buttonOK.LanguageKey = "OK";
+ this.buttonOK.Location = new System.Drawing.Point(12, 98);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(104, 23);
+ this.buttonOK.TabIndex = 4;
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.ButtonOKClick);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.LanguageKey = "CANCEL";
+ this.buttonCancel.Location = new System.Drawing.Point(128, 98);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(104, 23);
+ this.buttonCancel.TabIndex = 5;
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // SettingsForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.ClientSize = new System.Drawing.Size(244, 135);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.Controls.Add(this.label_language);
+ this.Controls.Add(this.checkBox_straightenImage);
+ this.Controls.Add(this.checkBox_orientImage);
+ this.Controls.Add(this.comboBox_languages);
+ this.LanguageKey = "settings_title";
+ this.Name = "SettingsForm";
+ this.ResumeLayout(false);
+
+ }
+ private GreenshotPlugin.Controls.GreenshotLabel label_language;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_orientImage;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_straightenImage;
+ private System.Windows.Forms.ComboBox comboBox_languages;
+ }
+}
diff --git a/GreenshotOCRPlugin/SettingsForm.cs b/GreenshotOCRPlugin/SettingsForm.cs
new file mode 100644
index 000000000..e63ca4eb2
--- /dev/null
+++ b/GreenshotOCRPlugin/SettingsForm.cs
@@ -0,0 +1,64 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace GreenshotOCR {
+ ///
+ /// Description of SettingsForm.
+ ///
+ public partial class SettingsForm : OcrForm {
+ private readonly OCRConfiguration config;
+
+ public SettingsForm(string [] languages, OCRConfiguration config) {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ this.config = config;
+ InitializeComponent();
+ AcceptButton = buttonOK;
+ CancelButton = buttonCancel;
+
+ comboBox_languages.Items.Clear();
+ int index=0;
+
+ // Preventing Tracker #3234560, although this should not happen...
+ string languageFromConfig = "ENGLISH";
+ if (config.Language != null) {
+ languageFromConfig = config.Language;
+ }
+ foreach(string availableLanguage in languages) {
+ string displayLanguage = availableLanguage.Substring(0, 1).ToUpper() + availableLanguage.Substring(1).ToLower();
+ comboBox_languages.Items.Add(displayLanguage);
+ if (availableLanguage.Equals(languageFromConfig, StringComparison.CurrentCultureIgnoreCase)) {
+ comboBox_languages.SelectedIndex = index;
+ }
+ index++;
+ }
+ }
+
+ private void ButtonOKClick(object sender, EventArgs e) {
+ string selectedString = (string) comboBox_languages.SelectedItem;
+ if (selectedString != null) {
+ config.Language = selectedString.ToUpper();
+ }
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/Destinations/ExcelDestination.cs b/GreenshotOfficePlugin/Destinations/ExcelDestination.cs
new file mode 100644
index 000000000..caa0bc37a
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/ExcelDestination.cs
@@ -0,0 +1,96 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.Interop.Office;
+using System.Text.RegularExpressions;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// Description of PowerpointDestination.
+ ///
+ public class ExcelDestination : AbstractDestination {
+ private const int IconApplication = 0;
+ private const int IconWorkbook = 1;
+ private static readonly string ExePath;
+ private readonly string _workbookName;
+
+ static ExcelDestination() {
+ ExePath = PluginUtils.GetExePath("EXCEL.EXE");
+ if (ExePath != null && File.Exists(ExePath)) {
+ WindowDetails.AddProcessToExcludeFromFreeze("excel");
+ } else {
+ ExePath = null;
+ }
+ }
+
+ public ExcelDestination() {
+ }
+
+ public ExcelDestination(string workbookName) {
+ _workbookName = workbookName;
+ }
+
+ public override string Designation => "Excel";
+
+ public override string Description => _workbookName ?? "Microsoft Excel";
+
+ public override int Priority => 5;
+
+ public override bool IsDynamic => true;
+
+ public override bool IsActive => base.IsActive && ExePath != null;
+
+ public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_workbookName) ? IconWorkbook : IconApplication);
+
+ public override IEnumerable DynamicDestinations() {
+ foreach (string workbookName in ExcelExporter.GetWorkbooks()) {
+ yield return new ExcelDestination(workbookName);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ bool createdFile = false;
+ string imageFile = captureDetails.Filename;
+ if (imageFile == null || surface.Modified || !Regex.IsMatch(imageFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) {
+ imageFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
+ createdFile = true;
+ }
+ if (_workbookName != null) {
+ ExcelExporter.InsertIntoExistingWorkbook(_workbookName, imageFile, surface.Image.Size);
+ } else {
+ ExcelExporter.InsertIntoNewWorkbook(imageFile, surface.Image.Size);
+ }
+ exportInformation.ExportMade = true;
+ ProcessExport(exportInformation, surface);
+ // Cleanup imageFile if we created it here, so less tmp-files are generated and left
+ if (createdFile) {
+ ImageOutput.DeleteNamedTmpFile(imageFile);
+ }
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs b/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs
new file mode 100644
index 000000000..e6b677596
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs
@@ -0,0 +1,122 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Interop.Office;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+
+namespace GreenshotOfficePlugin {
+ public class OneNoteDestination : AbstractDestination {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(WordDestination));
+ private const int ICON_APPLICATION = 0;
+ public const string DESIGNATION = "OneNote";
+ private static readonly string exePath;
+ private readonly OneNotePage page;
+
+ static OneNoteDestination() {
+ exePath = PluginUtils.GetExePath("ONENOTE.EXE");
+ if (exePath != null && File.Exists(exePath)) {
+ WindowDetails.AddProcessToExcludeFromFreeze("onenote");
+ } else {
+ exePath = null;
+ }
+ }
+
+ public OneNoteDestination() {
+
+ }
+
+ public OneNoteDestination(OneNotePage page) {
+ this.page = page;
+ }
+
+ public override string Designation {
+ get {
+ return DESIGNATION;
+ }
+ }
+
+ public override string Description {
+ get {
+ if (page == null) {
+ return "Microsoft OneNote";
+ } else {
+ return page.DisplayName;
+ }
+ }
+ }
+
+ public override int Priority {
+ get {
+ return 4;
+ }
+ }
+
+ public override bool IsDynamic {
+ get {
+ return true;
+ }
+ }
+
+ public override bool IsActive {
+ get {
+ return base.IsActive && exePath != null;
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ return PluginUtils.GetCachedExeIcon(exePath, ICON_APPLICATION);
+ }
+ }
+
+ public override IEnumerable DynamicDestinations() {
+ foreach (OneNotePage page in OneNoteExporter.GetPages()) {
+ yield return new OneNoteDestination(page);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+
+ if (page == null) {
+ try {
+ exportInformation.ExportMade = OneNoteExporter.ExportToNewPage(surface);
+ } catch(Exception ex) {
+ exportInformation.ErrorMessage = ex.Message;
+ LOG.Error(ex);
+ }
+ } else {
+ try {
+ exportInformation.ExportMade = OneNoteExporter.ExportToPage(surface, page);
+ } catch(Exception ex) {
+ exportInformation.ErrorMessage = ex.Message;
+ LOG.Error(ex);
+ }
+ }
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/Destinations/OutlookDestination.cs b/GreenshotOfficePlugin/Destinations/OutlookDestination.cs
new file mode 100644
index 000000000..6474eb844
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/OutlookDestination.cs
@@ -0,0 +1,162 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Interop.Office;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// Description of OutlookDestination.
+ ///
+ public class OutlookDestination : AbstractDestination {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OutlookDestination));
+ private const int IconApplication = 0;
+ private const int IconMeeting = 2;
+
+ private static readonly Image MailIcon = GreenshotResources.getImage("Email.Image");
+ private static readonly OfficeConfiguration OfficeConfig = IniConfig.GetIniSection();
+ private static readonly string ExePath;
+ private static readonly bool IsActiveFlag;
+ private const string MapiClient = "Microsoft Outlook";
+ private readonly string _outlookInspectorCaption;
+ private readonly OlObjectClass _outlookInspectorType;
+
+ static OutlookDestination() {
+ if (EmailConfigHelper.HasOutlook()) {
+ IsActiveFlag = true;
+ }
+ ExePath = PluginUtils.GetExePath("OUTLOOK.EXE");
+ if (ExePath != null && File.Exists(ExePath)) {
+ WindowDetails.AddProcessToExcludeFromFreeze("outlook");
+ } else {
+ ExePath = null;
+ }
+ if (ExePath == null) {
+ IsActiveFlag = false;
+ }
+ }
+
+ public OutlookDestination() {
+ }
+
+ public OutlookDestination(string outlookInspectorCaption, OlObjectClass outlookInspectorType) {
+ _outlookInspectorCaption = outlookInspectorCaption;
+ _outlookInspectorType = outlookInspectorType;
+ }
+
+ public override string Designation => "Outlook";
+
+ public override string Description => _outlookInspectorCaption ?? MapiClient;
+
+ public override int Priority => 3;
+
+ public override bool IsActive => base.IsActive && IsActiveFlag;
+
+ public override bool IsDynamic => true;
+
+ public override Keys EditorShortcutKeys => Keys.Control | Keys.E;
+
+ public override Image DisplayIcon {
+ get
+ {
+ if (_outlookInspectorCaption == null)
+ {
+ return PluginUtils.GetCachedExeIcon(ExePath, IconApplication);
+ }
+ if (OlObjectClass.olAppointment.Equals(_outlookInspectorType)) {
+ // Make sure we loaded the icon, maybe the configuration has been changed!
+ return PluginUtils.GetCachedExeIcon(ExePath, IconMeeting);
+ }
+ return MailIcon;
+ }
+ }
+
+ public override IEnumerable DynamicDestinations() {
+ IDictionary inspectorCaptions = OutlookEmailExporter.RetrievePossibleTargets();
+ if (inspectorCaptions != null) {
+ foreach (string inspectorCaption in inspectorCaptions.Keys) {
+ yield return new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]);
+ }
+ }
+ }
+
+ ///
+ /// Export the capture to outlook
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ // Outlook logic
+ string tmpFile = captureDetails.Filename;
+ if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) {
+ tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
+ } else {
+ Log.InfoFormat("Using already available file: {0}", tmpFile);
+ }
+
+ // Create a attachment name for the image
+ string attachmentName = captureDetails.Title;
+ if (!string.IsNullOrEmpty(attachmentName)) {
+ attachmentName = attachmentName.Trim();
+ }
+ // Set default if non is set
+ if (string.IsNullOrEmpty(attachmentName)) {
+ attachmentName = "Greenshot Capture";
+ }
+ // Make sure it's "clean" so it doesn't corrupt the header
+ attachmentName = Regex.Replace(attachmentName, @"[^\x20\d\w]", "");
+
+ if (_outlookInspectorCaption != null) {
+ OutlookEmailExporter.ExportToInspector(_outlookInspectorCaption, tmpFile, attachmentName);
+ exportInformation.ExportMade = true;
+ } else {
+ if (!manuallyInitiated) {
+ var inspectorCaptions = OutlookEmailExporter.RetrievePossibleTargets();
+ if (inspectorCaptions != null && inspectorCaptions.Count > 0) {
+ var destinations = new List
+ {
+ new OutlookDestination()
+ };
+ foreach (string inspectorCaption in inspectorCaptions.Keys) {
+ destinations.Add(new OutlookDestination(inspectorCaption, inspectorCaptions[inspectorCaption]));
+ }
+ // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
+ return ShowPickerMenu(false, surface, captureDetails, destinations);
+ }
+ } else {
+ exportInformation.ExportMade = OutlookEmailExporter.ExportToOutlook(OfficeConfig.OutlookEmailFormat, tmpFile, FilenameHelper.FillPattern(OfficeConfig.EmailSubjectPattern, captureDetails, false), attachmentName, OfficeConfig.EmailTo, OfficeConfig.EmailCC, OfficeConfig.EmailBCC, null);
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOfficePlugin/Destinations/PowerpointDestination.cs b/GreenshotOfficePlugin/Destinations/PowerpointDestination.cs
new file mode 100644
index 000000000..6ab1e1a54
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/PowerpointDestination.cs
@@ -0,0 +1,120 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using GreenshotPlugin.Core;
+using Greenshot.Plugin;
+using Greenshot.Interop.Office;
+using System.Text.RegularExpressions;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// Description of PowerpointDestination.
+ ///
+ public class PowerpointDestination : AbstractDestination {
+ private const int IconApplication = 0;
+ private const int IconPresentation = 1;
+
+ private static readonly string ExePath;
+ private readonly string _presentationName;
+
+ static PowerpointDestination() {
+ ExePath = PluginUtils.GetExePath("POWERPNT.EXE");
+ if (ExePath != null && File.Exists(ExePath)) {
+ WindowDetails.AddProcessToExcludeFromFreeze("powerpnt");
+ } else {
+ ExePath = null;
+ }
+ }
+
+ public PowerpointDestination() {
+ }
+
+ public PowerpointDestination(string presentationName) {
+ _presentationName = presentationName;
+ }
+
+ public override string Designation => "Powerpoint";
+
+ public override string Description {
+ get
+ {
+ if (_presentationName == null) {
+ return "Microsoft Powerpoint";
+ }
+ return _presentationName;
+ }
+ }
+
+ public override int Priority => 4;
+
+ public override bool IsDynamic => true;
+
+ public override bool IsActive => base.IsActive && ExePath != null;
+
+ public override Image DisplayIcon {
+ get {
+ if (!string.IsNullOrEmpty(_presentationName)) {
+ return PluginUtils.GetCachedExeIcon(ExePath, IconPresentation);
+ }
+
+ return PluginUtils.GetCachedExeIcon(ExePath, IconApplication);
+ }
+ }
+
+ public override IEnumerable DynamicDestinations() {
+ foreach (string presentationName in PowerpointExporter.GetPowerpointPresentations()) {
+ yield return new PowerpointDestination(presentationName);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string tmpFile = captureDetails.Filename;
+ Size imageSize = Size.Empty;
+ if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) {
+ tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
+ imageSize = surface.Image.Size;
+ }
+ if (_presentationName != null) {
+ exportInformation.ExportMade = PowerpointExporter.ExportToPresentation(_presentationName, tmpFile, imageSize, captureDetails.Title);
+ } else {
+ if (!manuallyInitiated) {
+ var presentations = PowerpointExporter.GetPowerpointPresentations();
+ if (presentations != null && presentations.Count > 0) {
+ var destinations = new List {new PowerpointDestination()};
+ foreach (string presentation in presentations) {
+ destinations.Add(new PowerpointDestination(presentation));
+ }
+ // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
+ return ShowPickerMenu(false, surface, captureDetails, destinations);
+ }
+ } else if (!exportInformation.ExportMade) {
+ exportInformation.ExportMade = PowerpointExporter.InsertIntoNewPresentation(tmpFile, imageSize, captureDetails.Title);
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/Destinations/WordDestination.cs b/GreenshotOfficePlugin/Destinations/WordDestination.cs
new file mode 100644
index 000000000..989dd0626
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/WordDestination.cs
@@ -0,0 +1,129 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Interop.Office;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// Description of EmailDestination.
+ ///
+ public class WordDestination : AbstractDestination {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(WordDestination));
+ private const int IconApplication = 0;
+ private const int IconDocument = 1;
+ private static readonly string ExePath;
+ private readonly string _documentCaption;
+
+ static WordDestination() {
+ ExePath = PluginUtils.GetExePath("WINWORD.EXE");
+ if (ExePath != null && !File.Exists(ExePath)) {
+ ExePath = null;
+ }
+ }
+
+ public WordDestination() {
+
+ }
+
+ public WordDestination(string wordCaption) {
+ _documentCaption = wordCaption;
+ }
+
+ public override string Designation => "Word";
+
+ public override string Description => _documentCaption ?? "Microsoft Word";
+
+ public override int Priority => 4;
+
+ public override bool IsDynamic => true;
+
+ public override bool IsActive => base.IsActive && ExePath != null;
+
+ public override Image DisplayIcon => PluginUtils.GetCachedExeIcon(ExePath, !string.IsNullOrEmpty(_documentCaption) ? IconDocument : IconApplication);
+
+ public override IEnumerable DynamicDestinations() {
+ foreach (string wordCaption in WordExporter.GetWordDocuments()) {
+ yield return new WordDestination(wordCaption);
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string tmpFile = captureDetails.Filename;
+ if (tmpFile == null || surface.Modified || !Regex.IsMatch(tmpFile, @".*(\.png|\.gif|\.jpg|\.jpeg|\.tiff|\.bmp)$")) {
+ tmpFile = ImageOutput.SaveNamedTmpFile(surface, captureDetails, new SurfaceOutputSettings().PreventGreenshotFormat());
+ }
+ if (_documentCaption != null) {
+ try {
+ WordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
+ exportInformation.ExportMade = true;
+ } catch (Exception) {
+ try {
+ WordExporter.InsertIntoExistingDocument(_documentCaption, tmpFile);
+ exportInformation.ExportMade = true;
+ } catch (Exception ex) {
+ Log.Error(ex);
+ // TODO: Change to general logic in ProcessExport
+ surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
+ }
+ }
+ } else {
+ if (!manuallyInitiated) {
+ var documents = WordExporter.GetWordDocuments();
+ if (documents != null && documents.Count > 0) {
+ var destinations = new List
+ {
+ new WordDestination()
+ };
+ foreach (string document in documents) {
+ destinations.Add(new WordDestination(document));
+ }
+ // Return the ExportInformation from the picker without processing, as this indirectly comes from us self
+ return ShowPickerMenu(false, surface, captureDetails, destinations);
+ }
+ }
+ try {
+ WordExporter.InsertIntoNewDocument(tmpFile, null, null);
+ exportInformation.ExportMade = true;
+ } catch(Exception) {
+ // Retry once, just in case
+ try {
+ WordExporter.InsertIntoNewDocument(tmpFile, null, null);
+ exportInformation.ExportMade = true;
+ } catch (Exception ex) {
+ Log.Error(ex);
+ // TODO: Change to general logic in ProcessExport
+ surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("destination_exportfailed", Description));
+ }
+ }
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/GlobalSuppressions.cs b/GreenshotOfficePlugin/GlobalSuppressions.cs
new file mode 100644
index 000000000..882507f6b
Binary files /dev/null and b/GreenshotOfficePlugin/GlobalSuppressions.cs differ
diff --git a/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj
new file mode 100644
index 000000000..43f976544
--- /dev/null
+++ b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj
@@ -0,0 +1,100 @@
+
+
+
+ {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}
+ Debug
+ x86
+ Library
+ GreenshotOfficePlugin
+ GreenshotOfficePlugin
+ v2.0
+ Properties
+ OnBuildSuccess
+ False
+ False
+ 4
+ false
+
+
+
+
+
+ 3.5
+
+
+ x86
+ False
+ Off
+ 4194304
+ 4096
+
+
+ bin\Debug\
+ true
+ Full
+ False
+ True
+ DEBUG;TRACE
+
+
+ bin\Release\
+ false
+ None
+ True
+ False
+ TRACE
+
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+
+
+
+ AnyCPU
+ False
+ Off
+ 4194304
+ 4096
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Office/Languages/language_office-fr-FR.ini b/GreenshotOfficePlugin/Languages/language_officeplugin-fr-FR.ini
similarity index 100%
rename from src/Greenshot.Plugin.Office/Languages/language_office-fr-FR.ini
rename to GreenshotOfficePlugin/Languages/language_officeplugin-fr-FR.ini
diff --git a/GreenshotOfficePlugin/Languages/language_officeplugin-fr-FR.xml b/GreenshotOfficePlugin/Languages/language_officeplugin-fr-FR.xml
new file mode 100644
index 000000000..d0fef9cc1
--- /dev/null
+++ b/GreenshotOfficePlugin/Languages/language_officeplugin-fr-FR.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ Paramètres Office
+
+
+ Verrouiller les proportions de l'image dans les exportations de Word
+
+
+ Autoriser les exportations à des réunions
+
+
+ Modèle pour le sujet d'Outlook
+
+
+ Format du courriel pour les courriels nouvellement créés
+
+
+ Insérer une signature par défaut pour les nouveaux courriels
+
+
+ Défaut envoyer par courriel à l'adresse
+
+
+ Défaut envoyer par courriel CC à l'adresse
+
+
+ Défaut envoyer par courriel CCI à l'adresse
+
+
+ Mise en page utilisée pour l'exportation
+
+
+ Verrouiller les proportions de l'image dans les exportations de PowerPoint
+
+
+
diff --git a/GreenshotOfficePlugin/OfficeConfiguration.cs b/GreenshotOfficePlugin/OfficeConfiguration.cs
new file mode 100644
index 000000000..4f943c7c3
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeConfiguration.cs
@@ -0,0 +1,52 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using Greenshot.IniFile;
+using Greenshot.Interop.Office;
+
+namespace GreenshotOfficePlugin {
+
+ ///
+ /// Description of CoreConfiguration.
+ ///
+ [IniSection("Office", Description="Greenshot Office configuration")]
+ public class OfficeConfiguration : IniSection {
+ [IniProperty("OutlookEmailFormat", Description = "Default type for emails. (Text, HTML)", DefaultValue = "HTML")]
+ public EmailFormat OutlookEmailFormat { get; set; }
+
+ [IniProperty("EmailSubjectPattern", Description = "Email subject pattern, works like the OutputFileFilenamePattern", DefaultValue = "${title}")]
+ public string EmailSubjectPattern { get; set; }
+ [IniProperty("EmailTo", Description = "Default value for the to in emails that are created", DefaultValue = "")]
+ public string EmailTo { get; set; }
+ [IniProperty("EmailCC", Description = "Default value for the CC in emails that are created", DefaultValue = "")]
+ public string EmailCC { get; set; }
+ [IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")]
+ public string EmailBCC { get; set; }
+ [IniProperty("OutlookAllowExportInMeetings", Description = "For Outlook: Allow export in meeting items", DefaultValue = "False")]
+ public bool OutlookAllowExportInMeetings { get; set; }
+ [IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")]
+ public bool WordLockAspectRatio { get; set; }
+ [IniProperty("PowerpointLockAspectRatio", Description = "For Powerpoint: Lock the aspect ratio of the image", DefaultValue = "True")]
+ public bool PowerpointLockAspectRatio { get; set; }
+ [IniProperty("PowerpointSlideLayout", Description = "For Powerpoint: Slide layout, changing this to a wrong value will fallback on ppLayoutBlank!!", DefaultValue = "ppLayoutPictureWithCaption")]
+ public PPSlideLayout PowerpointSlideLayout { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs b/GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs
new file mode 100644
index 000000000..f65a3e33e
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs
@@ -0,0 +1,167 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Drawing;
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Interop.Office {
+ public class ExcelExporter {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ExcelExporter));
+ private static Version _excelVersion;
+
+ ///
+ /// Get all currently opened workbooks
+ ///
+ /// List of string with names of the workbooks
+ public static List GetWorkbooks() {
+ List currentWorkbooks = new List();
+ using (IExcelApplication excelApplication = GetExcelApplication()) {
+ if (excelApplication == null) {
+ return currentWorkbooks;
+ }
+ using (IWorkbooks workbooks = excelApplication.Workbooks) {
+ for (int i = 1; i <= workbooks.Count; i++) {
+ using (IWorkbook workbook = workbooks[i]) {
+ if (workbook != null) {
+ currentWorkbooks.Add(workbook.Name);
+ }
+ }
+ }
+ }
+ }
+ currentWorkbooks.Sort();
+ return currentWorkbooks;
+ }
+
+ ///
+ /// Insert image from supplied tmp file into the give excel workbook
+ ///
+ ///
+ ///
+ ///
+ public static void InsertIntoExistingWorkbook(string workbookName, string tmpFile, Size imageSize) {
+ using (IExcelApplication excelApplication = GetExcelApplication()) {
+ if (excelApplication == null) {
+ return;
+ }
+ using (IWorkbooks workbooks = excelApplication.Workbooks) {
+ for (int i = 1; i <= workbooks.Count; i++) {
+ using (IWorkbook workbook = workbooks[i]) {
+ if (workbook != null && workbook.Name.StartsWith(workbookName)) {
+ InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
+ }
+ }
+ }
+ }
+ int hWnd = excelApplication.Hwnd;
+ if (hWnd > 0)
+ {
+ WindowDetails.ToForeground(new IntPtr(hWnd));
+ }
+ }
+ }
+
+ ///
+ /// Insert a file into an already created workbook
+ ///
+ ///
+ ///
+ ///
+ private static void InsertIntoExistingWorkbook(IWorkbook workbook, string tmpFile, Size imageSize) {
+ IWorksheet workSheet = workbook.ActiveSheet;
+ if (workSheet == null) {
+ return;
+ }
+ using (IShapes shapes = workSheet.Shapes) {
+ if (shapes != null) {
+ using (IShape shape = shapes.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, imageSize.Width, imageSize.Height)) {
+ if (shape != null) {
+ shape.Top = 40;
+ shape.Left = 40;
+ shape.LockAspectRatio = MsoTriState.msoTrue;
+ shape.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
+ shape.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Add an image-file to a newly created workbook
+ ///
+ ///
+ ///
+ public static void InsertIntoNewWorkbook(string tmpFile, Size imageSize) {
+ using (IExcelApplication excelApplication = GetOrCreateExcelApplication()) {
+ if (excelApplication != null) {
+ excelApplication.Visible = true;
+ object template = Missing.Value;
+ using (IWorkbooks workbooks = excelApplication.Workbooks) {
+ IWorkbook workbook = workbooks.Add(template);
+ InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// Call this to get the running Excel application, returns null if there isn't any.
+ ///
+ /// IExcelApplication or null
+ private static IExcelApplication GetExcelApplication() {
+ IExcelApplication excelApplication = COMWrapper.GetInstance();
+ InitializeVariables(excelApplication);
+ return excelApplication;
+ }
+
+ ///
+ /// Call this to get the running Excel application, or create a new instance
+ ///
+ /// IExcelApplication
+ private static IExcelApplication GetOrCreateExcelApplication() {
+ IExcelApplication excelApplication = COMWrapper.GetOrCreateInstance();
+ InitializeVariables(excelApplication);
+ return excelApplication;
+ }
+
+ ///
+ /// Initialize static outlook variables like version and currentuser
+ ///
+ ///
+ private static void InitializeVariables(IExcelApplication excelApplication) {
+ if (excelApplication == null || _excelVersion != null) {
+ return;
+ }
+ try {
+ _excelVersion = new Version(excelApplication.Version);
+ Log.InfoFormat("Using Excel {0}", _excelVersion);
+ } catch (Exception exVersion) {
+ Log.Error(exVersion);
+ Log.Warn("Assuming Excel version 1997.");
+ _excelVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0);
+ }
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs
new file mode 100644
index 000000000..83d7a6255
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs
@@ -0,0 +1,227 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Runtime.InteropServices;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+namespace Greenshot.Interop.Office {
+
+ public class OneNoteExporter {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OneNoteExporter));
+ private const string XmlImageContent = "{0} ";
+ private const string XmlOutline = " {0} ";
+ private const string OnenoteNamespace2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote";
+
+ ///
+ /// Create a new page in the "unfiled notes section", with the title of the capture, and export the capture there.
+ ///
+ /// ISurface
+ /// bool true if export worked
+ public static bool ExportToNewPage(ISurface surfaceToUpload) {
+ using(IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) {
+ OneNotePage newPage = new OneNotePage();
+ string unfiledNotesSectionId = GetSectionId(oneNoteApplication, SpecialLocation.slUnfiledNotesSection);
+ if(unfiledNotesSectionId != null) {
+ // ReSharper disable once RedundantAssignment
+ string pageId = "";
+ oneNoteApplication.CreateNewPage(unfiledNotesSectionId, out pageId, NewPageStyle.npsDefault);
+ newPage.ID = pageId;
+ // Set the new name, this is automatically done in the export to page
+ newPage.Name = surfaceToUpload.CaptureDetails.Title;
+ return ExportToPage(oneNoteApplication, surfaceToUpload, newPage);
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Export the capture to the specified page
+ ///
+ /// ISurface
+ /// OneNotePage
+ /// bool true if everything worked
+ public static bool ExportToPage(ISurface surfaceToUpload, OneNotePage page) {
+ using(IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) {
+ return ExportToPage(oneNoteApplication, surfaceToUpload, page);
+ }
+ }
+
+ ///
+ /// Export the capture to the specified page
+ ///
+ /// IOneNoteApplication
+ /// ISurface
+ /// OneNotePage
+ /// bool true if everything worked
+ private static bool ExportToPage(IOneNoteApplication oneNoteApplication, ISurface surfaceToUpload, OneNotePage page) {
+ if(oneNoteApplication == null) {
+ return false;
+ }
+ using (MemoryStream pngStream = new MemoryStream()) {
+ SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
+ ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
+ string base64String = Convert.ToBase64String(pngStream.GetBuffer());
+ string imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height);
+ string pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.ID, OnenoteNamespace2010, page.Name);
+ Log.InfoFormat("Sending XML: {0}", pageChangesXml);
+ oneNoteApplication.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false);
+ try {
+ oneNoteApplication.NavigateTo(page.ID, null, false);
+ } catch(Exception ex) {
+ Log.Warn("Unable to navigate to the target page", ex);
+ }
+ return true;
+ }
+ }
+
+ ///
+ /// Retrieve the Section ID for the specified special location
+ ///
+ ///
+ /// SpecialLocation
+ /// string with section ID
+ private static string GetSectionId(IOneNoteApplication oneNoteApplication, SpecialLocation specialLocation) {
+ if(oneNoteApplication == null) {
+ return null;
+ }
+ // ReSharper disable once RedundantAssignment
+ string unfiledNotesPath = "";
+ oneNoteApplication.GetSpecialLocation(specialLocation, out unfiledNotesPath);
+
+ // ReSharper disable once RedundantAssignment
+ string notebookXml = "";
+ oneNoteApplication.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
+ if(!string.IsNullOrEmpty(notebookXml)) {
+ Log.Debug(notebookXml);
+ StringReader reader = null;
+ try {
+ reader = new StringReader(notebookXml);
+ using(XmlTextReader xmlReader = new XmlTextReader(reader)) {
+ while(xmlReader.Read()) {
+ if("one:Section".Equals(xmlReader.Name)) {
+ string id = xmlReader.GetAttribute("ID");
+ string path = xmlReader.GetAttribute("path");
+ if(unfiledNotesPath.Equals(path)) {
+ return id;
+ }
+ }
+ }
+ }
+ } finally
+ {
+ reader?.Dispose();
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Get the captions of all the open word documents
+ ///
+ ///
+ public static List GetPages() {
+ List pages = new List();
+ try {
+ using (IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) {
+ if (oneNoteApplication != null) {
+ // ReSharper disable once RedundantAssignment
+ string notebookXml = "";
+ oneNoteApplication.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
+ if (!string.IsNullOrEmpty(notebookXml)) {
+ Log.Debug(notebookXml);
+ StringReader reader = null;
+ try {
+ reader = new StringReader(notebookXml);
+ using (XmlTextReader xmlReader = new XmlTextReader(reader)) {
+ reader = null;
+ OneNoteSection currentSection = null;
+ OneNoteNotebook currentNotebook = null;
+ while (xmlReader.Read()) {
+ if ("one:Notebook".Equals(xmlReader.Name)) {
+ string id = xmlReader.GetAttribute("ID");
+ if (id != null && (currentNotebook == null || !id.Equals(currentNotebook.ID))) {
+ currentNotebook = new OneNoteNotebook
+ {
+ ID = xmlReader.GetAttribute("ID"),
+ Name = xmlReader.GetAttribute("name")
+ };
+ }
+ }
+ if ("one:Section".Equals(xmlReader.Name)) {
+ string id = xmlReader.GetAttribute("ID");
+ if (id != null && (currentSection == null || !id.Equals(currentSection.ID))) {
+ currentSection = new OneNoteSection
+ {
+ ID = xmlReader.GetAttribute("ID"),
+ Name = xmlReader.GetAttribute("name"),
+ Parent = currentNotebook
+ };
+ }
+ }
+ if ("one:Page".Equals(xmlReader.Name)) {
+ // Skip deleted items
+ if ("true".Equals(xmlReader.GetAttribute("isInRecycleBin"))) {
+ continue;
+ }
+ OneNotePage page = new OneNotePage
+ {
+ Parent = currentSection,
+ Name = xmlReader.GetAttribute("name"),
+ ID = xmlReader.GetAttribute("ID")
+ };
+ if (page.ID == null || page.Name == null) {
+ continue;
+ }
+ page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
+ pages.Add(page);
+ }
+ }
+ }
+ } finally
+ {
+ reader?.Dispose();
+ }
+ }
+ }
+ }
+ } catch (COMException cEx) {
+ if (cEx.ErrorCode == unchecked((int)0x8002801D)) {
+ Log.Warn("Wrong registry keys, to solve this remove the OneNote key as described here: http://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/");
+ }
+ Log.Warn("Problem retrieving onenote destinations, ignoring: ", cEx);
+ } catch (Exception ex) {
+ Log.Warn("Problem retrieving onenote destinations, ignoring: ", ex);
+ }
+ pages.Sort(delegate(OneNotePage p1, OneNotePage p2) {
+ if(p1.IsCurrentlyViewed || p2.IsCurrentlyViewed) {
+ return p2.IsCurrentlyViewed.CompareTo(p1.IsCurrentlyViewed);
+ }
+ return string.Compare(p1.DisplayName, p2.DisplayName, StringComparison.Ordinal);
+ });
+ return pages;
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs b/GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs
new file mode 100644
index 000000000..4d0d724f2
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs
@@ -0,0 +1,571 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+using Microsoft.Win32;
+using Greenshot.Interop.IE;
+using GreenshotOfficePlugin;
+using Greenshot.IniFile;
+
+namespace Greenshot.Interop.Office {
+ ///
+ /// Outlook exporter has all the functionality to export to outlook
+ ///
+ public class OutlookEmailExporter {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OutlookEmailExporter));
+ private static readonly OfficeConfiguration OfficeConfig = IniConfig.GetIniSection();
+ private static readonly string SignaturePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Microsoft\Signatures");
+ private static Version _outlookVersion;
+ private static string _currentUser;
+
+ // The signature key can be found at:
+ // HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\\9375CFF0413111d3B88A00104B2A6676\ [New Signature]
+ private const string ProfilesKey = @"Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\";
+ private const string AccountKey = "9375CFF0413111d3B88A00104B2A6676";
+ private const string NewSignatureValue = "New Signature";
+ private const string DefaultProfileValue = "DefaultProfile";
+
+ ///
+ /// A method to retrieve all inspectors which can act as an export target
+ ///
+ /// List of strings with inspector captions (window title)
+ public static IDictionary RetrievePossibleTargets() {
+ IDictionary inspectorCaptions = new SortedDictionary();
+ try {
+ using (IOutlookApplication outlookApplication = GetOutlookApplication()) {
+ if (outlookApplication == null) {
+ return null;
+ }
+
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2013) {
+ // Check inline "panel" for Outlook 2013
+ using (var activeExplorer = outlookApplication.ActiveExplorer()) {
+ if (activeExplorer != null) {
+ using (var inlineResponse = activeExplorer.ActiveInlineResponse) {
+ if (CanExportToInspector(inlineResponse)) {
+ OlObjectClass currentItemClass = inlineResponse.Class;
+ inspectorCaptions.Add(activeExplorer.Caption, currentItemClass);
+ }
+ }
+ }
+ }
+ }
+
+ using (IInspectors inspectors = outlookApplication.Inspectors) {
+ if (inspectors != null && inspectors.Count > 0) {
+ for (int i = 1; i <= inspectors.Count; i++) {
+ using (IInspector inspector = outlookApplication.Inspectors[i]) {
+ using (IItem currentItem = inspector.CurrentItem) {
+ if (CanExportToInspector(currentItem)) {
+ OlObjectClass currentItemClass = currentItem.Class;
+ inspectorCaptions.Add(inspector.Caption, currentItemClass);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Log.Warn("Problem retrieving word destinations, ignoring: ", ex);
+ }
+ return inspectorCaptions;
+ }
+
+ ///
+ /// Return true if we can export to the supplied inspector
+ ///
+ /// the Item to check
+ ///
+ private static bool CanExportToInspector(IItem currentItem) {
+ try {
+ if (currentItem != null) {
+ OlObjectClass currentItemClass = currentItem.Class;
+ if (OlObjectClass.olMail.Equals(currentItemClass)) {
+ MailItem mailItem = (MailItem)currentItem;
+ //MailItem mailItem = COMWrapper.Cast(currentItem);
+ Log.DebugFormat("Mail sent: {0}", mailItem.Sent);
+ if (!mailItem.Sent) {
+ return true;
+ }
+ } else if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2010 && OfficeConfig.OutlookAllowExportInMeetings && OlObjectClass.olAppointment.Equals(currentItemClass)) {
+ //AppointmentItem appointmentItem = COMWrapper.Cast(currentItem);
+ AppointmentItem appointmentItem = (AppointmentItem)currentItem;
+ if (string.IsNullOrEmpty(appointmentItem.Organizer) || (_currentUser != null && _currentUser.Equals(appointmentItem.Organizer))) {
+ return true;
+ }
+ Log.DebugFormat("Not exporting, as organizer is {0} and currentuser {1}", appointmentItem.Organizer, _currentUser);
+ }
+ }
+ } catch (Exception ex) {
+ Log.WarnFormat("Couldn't process item due to: {0}", ex.Message);
+ }
+ return false;
+ }
+
+
+ ///
+ /// Export the image stored in tmpFile to the Inspector with the caption
+ ///
+ /// Caption of the inspector
+ /// Path to image file
+ /// name of the attachment (used as the tooltip of the image)
+ /// true if it worked
+ public static bool ExportToInspector(string inspectorCaption, string tmpFile, string attachmentName) {
+ using (IOutlookApplication outlookApplication = GetOrCreateOutlookApplication()) {
+ if (outlookApplication == null) {
+ return false;
+ }
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2013) {
+ // Check inline "panel" for Outlook 2013
+ using (var activeExplorer = outlookApplication.ActiveExplorer()) {
+ if (activeExplorer == null) {
+ return false;
+ }
+ var currentCaption = activeExplorer.Caption;
+ if (currentCaption.StartsWith(inspectorCaption)) {
+ using (var inlineResponse = activeExplorer.ActiveInlineResponse) {
+ using (IItem currentItem = activeExplorer.ActiveInlineResponse) {
+ if (CanExportToInspector(inlineResponse)) {
+ try {
+ return ExportToInspector(activeExplorer, currentItem, tmpFile, attachmentName);
+ } catch (Exception exExport) {
+ Log.Error("Export to " + currentCaption + " failed.", exExport);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ using (IInspectors inspectors = outlookApplication.Inspectors) {
+ if (inspectors == null || inspectors.Count == 0) {
+ return false;
+ }
+ Log.DebugFormat("Got {0} inspectors to check", inspectors.Count);
+ for (int i = 1; i <= inspectors.Count; i++) {
+ using (IInspector inspector = outlookApplication.Inspectors[i]) {
+ string currentCaption = inspector.Caption;
+ if (currentCaption.StartsWith(inspectorCaption)) {
+ using (IItem currentItem = inspector.CurrentItem) {
+ if (CanExportToInspector(currentItem)) {
+ try {
+ return ExportToInspector(inspector, currentItem, tmpFile, attachmentName);
+ } catch (Exception exExport) {
+ Log.Error("Export to " + currentCaption + " failed.", exExport);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Export the file to the supplied inspector
+ ///
+ /// ICommonExplorer
+ /// Item
+ ///
+ ///
+ ///
+ private static bool ExportToInspector(ICommonExplorer inspectorOrExplorer, IItem currentItem, string tmpFile, string attachmentName) {
+ if (currentItem == null) {
+ Log.Warn("No current item.");
+ return false;
+ }
+ OlObjectClass itemClass = currentItem.Class;
+ bool isMail = OlObjectClass.olMail.Equals(itemClass);
+ bool isAppointment = OlObjectClass.olAppointment.Equals(itemClass);
+ if (!isMail && !isAppointment) {
+ Log.Warn("Item is no mail or appointment.");
+ return false;
+ }
+ MailItem mailItem = null;
+ try {
+ if (isMail) {
+ //mailItem = COMWrapper.Cast(currentItem);
+ mailItem = (MailItem)currentItem;
+ if (mailItem.Sent) {
+ Log.WarnFormat("Item already sent, can't export to {0}", currentItem.Subject);
+ return false;
+ }
+ }
+
+ // Make sure the inspector is activated, only this way the word editor is active!
+ // This also ensures that the window is visible!
+ inspectorOrExplorer.Activate();
+ bool isTextFormat = false;
+ if (isMail) {
+ isTextFormat = OlBodyFormat.olFormatPlain.Equals(mailItem.BodyFormat);
+ }
+ if (isAppointment || !isTextFormat) {
+ // Check for wordmail, if so use the wordexporter
+ // http://msdn.microsoft.com/en-us/library/dd492012%28v=office.12%29.aspx
+ // Earlier versions of Outlook also supported an Inspector.HTMLEditor object property, but since Internet Explorer is no longer the rendering engine for HTML messages and posts, HTMLEditor is no longer supported.
+ IWordDocument wordDocument = null;
+ var explorer = inspectorOrExplorer as IExplorer;
+ if (explorer != null) {
+ wordDocument = explorer.ActiveInlineResponseWordEditor;
+ }
+ else
+ {
+ var inspector1 = inspectorOrExplorer as IInspector;
+ if (inspector1 != null) {
+ var inspector = inspector1;
+ if (inspector.IsWordMail()) {
+ wordDocument = inspector.WordEditor;
+ }
+ }
+ }
+ if (wordDocument != null) {
+ try {
+ if (WordExporter.InsertIntoExistingDocument(wordDocument.Application, wordDocument, tmpFile, null, null)) {
+ Log.Info("Inserted into Wordmail");
+ wordDocument.Dispose();
+ return true;
+ }
+ } catch (Exception exportException) {
+ Log.Error("Error exporting to the word editor, trying to do it via another method", exportException);
+ }
+ } else if (isAppointment) {
+ Log.Info("Can't export to an appointment if no word editor is used");
+ return false;
+ } else {
+ Log.Info("Trying export for outlook < 2007.");
+ }
+ }
+ // Only use mailitem as it should be filled!!
+ Log.InfoFormat("Item '{0}' has format: {1}", mailItem?.Subject, mailItem?.BodyFormat);
+
+ string contentId;
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2007) {
+ contentId = Guid.NewGuid().ToString();
+ } else {
+ Log.Info("Older Outlook (<2007) found, using filename as contentid.");
+ contentId = Path.GetFileName(tmpFile);
+ }
+
+ // Use this to change the format, it will probably lose the current selection.
+ //if (!OlBodyFormat.olFormatHTML.Equals(currentMail.BodyFormat)) {
+ // LOG.Info("Changing format to HTML.");
+ // currentMail.BodyFormat = OlBodyFormat.olFormatHTML;
+ //}
+
+ bool inlinePossible = false;
+ if (inspectorOrExplorer is IInspector && OlBodyFormat.olFormatHTML.Equals(mailItem?.BodyFormat)) {
+ // if html we can try to inline it
+ // The following might cause a security popup... can't ignore it.
+ try {
+ IHTMLDocument2 document2 = (inspectorOrExplorer as IInspector).HTMLEditor as IHTMLDocument2;
+ if (document2 != null) {
+ IHTMLSelectionObject selection = document2.selection;
+ if (selection != null) {
+ IHTMLTxtRange range = selection.createRange();
+ if (range != null) {
+ // First paste, than attach (otherwise the range is wrong!)
+ range.pasteHTML(" ");
+ inlinePossible = true;
+ } else {
+ Log.DebugFormat("No range for '{0}'", inspectorOrExplorer.Caption);
+ }
+ } else {
+ Log.DebugFormat("No selection for '{0}'", inspectorOrExplorer.Caption);
+ }
+ } else {
+ Log.DebugFormat("No HTML editor for '{0}'", inspectorOrExplorer.Caption);
+ }
+ } catch (Exception e) {
+ // Continue with non inline image
+ Log.Warn("Error pasting HTML, most likely due to an ACCESS_DENIED as the user clicked no.", e);
+ }
+ }
+
+ // Create the attachment (if inlined the attachment isn't visible as attachment!)
+ using (IAttachment attachment = mailItem.Attachments.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName)) {
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2007) {
+ // Add the content id to the attachment, this only works for Outlook >= 2007
+ try {
+ IPropertyAccessor propertyAccessor = attachment.PropertyAccessor;
+ propertyAccessor.SetProperty(PropTag.ATTACHMENT_CONTENT_ID, contentId);
+ } catch {
+ // Ignore
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Log.WarnFormat("Problem while trying to add attachment to Item '{0}' : {1}", inspectorOrExplorer.Caption, ex);
+ return false;
+ }
+ try {
+ inspectorOrExplorer.Activate();
+ } catch (Exception ex) {
+ Log.Warn("Problem activating inspector/explorer: ", ex);
+ return false;
+ }
+ Log.Debug("Finished!");
+ return true;
+ }
+
+ ///
+ /// Export image to a new email
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static void ExportToNewEmail(IOutlookApplication outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url) {
+ using (IItem newItem = outlookApplication.CreateItem(OlItemType.olMailItem)) {
+ if (newItem == null) {
+ return;
+ }
+ //MailItem newMail = COMWrapper.Cast(newItem);
+ MailItem newMail = (MailItem)newItem;
+ newMail.Subject = subject;
+ if (!string.IsNullOrEmpty(to)) {
+ newMail.To = to;
+ }
+ if (!string.IsNullOrEmpty(cc)) {
+ newMail.CC = cc;
+ }
+ if (!string.IsNullOrEmpty(bcc)) {
+ newMail.BCC = bcc;
+ }
+ newMail.BodyFormat = OlBodyFormat.olFormatHTML;
+ string bodyString = null;
+ // Read the default signature, if nothing found use empty email
+ try {
+ bodyString = GetOutlookSignature(format);
+ } catch (Exception e) {
+ Log.Error("Problem reading signature!", e);
+ }
+ switch (format) {
+ case EmailFormat.Text:
+ // Create the attachment (and dispose the COM object after using)
+ using (newMail.Attachments.Add(tmpFile, OlAttachmentType.olByValue, 1, attachmentName))
+ {
+ newMail.BodyFormat = OlBodyFormat.olFormatPlain;
+ if (bodyString == null) {
+ bodyString = "";
+ }
+ newMail.Body = bodyString;
+ }
+ break;
+ default:
+ string contentId = Path.GetFileName(tmpFile);
+ // Create the attachment (and dispose the COM object after using)
+ using (IAttachment attachment = newMail.Attachments.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName)) {
+ // add content ID to the attachment
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2007) {
+ try {
+ contentId = Guid.NewGuid().ToString();
+ IPropertyAccessor propertyAccessor = attachment.PropertyAccessor;
+ propertyAccessor.SetProperty(PropTag.ATTACHMENT_CONTENT_ID, contentId);
+ } catch {
+ Log.Info("Error working with the PropertyAccessor, using filename as contentid");
+ contentId = Path.GetFileName(tmpFile);
+ }
+ }
+ }
+
+ newMail.BodyFormat = OlBodyFormat.olFormatHTML;
+ string href = "";
+ string hrefEnd = "";
+ if (!string.IsNullOrEmpty(url)) {
+ href = $"";
+ hrefEnd = " ";
+ }
+ string htmlImgEmbedded = $" {href} {hrefEnd} ";
+ string fallbackBody = $"{htmlImgEmbedded}";
+ if (bodyString == null) {
+ bodyString = fallbackBody;
+ } else {
+ int bodyIndex = bodyString.IndexOf("= 0)
+ {
+ bodyIndex = bodyString.IndexOf(">", bodyIndex, StringComparison.Ordinal) + 1;
+ bodyString = bodyIndex >= 0 ? bodyString.Insert(bodyIndex, htmlImgEmbedded) : fallbackBody;
+ } else {
+ bodyString = fallbackBody;
+ }
+ }
+ newMail.HTMLBody = bodyString;
+ break;
+ }
+ // So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
+ newMail.Display(false);
+
+ using (IInspector inspector = newMail.GetInspector()) {
+ if (inspector != null) {
+ try {
+ inspector.Activate();
+ } catch {
+ // Ignore
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Helper method to create an outlook mail item with attachment
+ ///
+ ///
+ /// The file to send, do not delete the file right away!
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// true if it worked, false if not
+ public static bool ExportToOutlook(EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url) {
+ bool exported = false;
+ try {
+ using (IOutlookApplication outlookApplication = GetOrCreateOutlookApplication()) {
+ if (outlookApplication != null) {
+ ExportToNewEmail(outlookApplication, format, tmpFile, subject, attachmentName, to, cc, bcc, url);
+ exported = true;
+ }
+ }
+ return exported;
+ } catch (Exception e) {
+ Log.Error("Error while creating an outlook mail item: ", e);
+ }
+ return exported;
+ }
+
+ ///
+ /// Helper method to get the Outlook signature
+ ///
+ ///
+ private static string GetOutlookSignature(EmailFormat format) {
+ using (RegistryKey profilesKey = Registry.CurrentUser.OpenSubKey(ProfilesKey, false)) {
+ if (profilesKey == null) {
+ return null;
+ }
+ string defaultProfile = (string)profilesKey.GetValue(DefaultProfileValue);
+ Log.DebugFormat("defaultProfile={0}", defaultProfile);
+ using (RegistryKey profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false)) {
+ if (profileKey != null)
+ {
+ string[] numbers = profileKey.GetSubKeyNames();
+ foreach (string number in numbers) {
+ Log.DebugFormat("Found subkey {0}", number);
+ using (RegistryKey numberKey = profileKey.OpenSubKey(number, false)) {
+ if (numberKey != null)
+ {
+ byte[] val = (byte[])numberKey.GetValue(NewSignatureValue);
+ if (val == null) {
+ continue;
+ }
+ string signatureName = "";
+ foreach (byte b in val) {
+ if (b != 0) {
+ signatureName += (char)b;
+ }
+ }
+ Log.DebugFormat("Found email signature: {0}", signatureName);
+ string extension;
+ switch (format) {
+ case EmailFormat.Text:
+ extension = ".txt";
+ break;
+ default:
+ extension = ".htm";
+ break;
+ }
+ string signatureFile = Path.Combine(SignaturePath, signatureName + extension);
+ if (File.Exists(signatureFile)) {
+ Log.DebugFormat("Found email signature file: {0}", signatureFile);
+ return File.ReadAllText(signatureFile, Encoding.Default);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Initialize static outlook variables like version and currentuser
+ ///
+ ///
+ private static void InitializeVariables(IOutlookApplication outlookApplication) {
+ if (outlookApplication == null || _outlookVersion != null) {
+ return;
+ }
+ try {
+ _outlookVersion = new Version(outlookApplication.Version);
+ Log.InfoFormat("Using Outlook {0}", _outlookVersion);
+ } catch (Exception exVersion) {
+ Log.Error(exVersion);
+ Log.Warn("Assuming outlook version 1997.");
+ _outlookVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0);
+ }
+ // Preventing retrieval of currentUser if Outlook is older than 2007
+ if (_outlookVersion.Major >= (int)OfficeVersion.OFFICE_2007) {
+ try {
+ INameSpace mapiNamespace = outlookApplication.GetNameSpace("MAPI");
+ _currentUser = mapiNamespace.CurrentUser.Name;
+ Log.InfoFormat("Current user: {0}", _currentUser);
+ } catch (Exception exNs) {
+ Log.Error(exNs);
+ }
+ }
+ }
+
+ ///
+ /// Call this to get the running outlook application, returns null if there isn't any.
+ ///
+ /// IOutlookApplication or null
+ private static IOutlookApplication GetOutlookApplication() {
+ IOutlookApplication outlookApplication = COMWrapper.GetInstance();
+ InitializeVariables(outlookApplication);
+ return outlookApplication;
+ }
+
+ ///
+ /// Call this to get the running outlook application, or create a new instance
+ ///
+ /// IOutlookApplication
+ private static IOutlookApplication GetOrCreateOutlookApplication() {
+ IOutlookApplication outlookApplication = COMWrapper.GetOrCreateInstance();
+ InitializeVariables(outlookApplication);
+ return outlookApplication;
+ }
+ }
+
+}
diff --git a/GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs b/GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs
new file mode 100644
index 000000000..713a73c90
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs
@@ -0,0 +1,255 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using GreenshotOfficePlugin;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Greenshot.Interop.Office {
+ public class PowerpointExporter {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PowerpointExporter));
+ private static Version _powerpointVersion;
+ private static readonly OfficeConfiguration officeConfiguration = IniConfig.GetIniSection();
+
+ private static bool IsAfter2003() {
+ return _powerpointVersion.Major > (int)OfficeVersion.OFFICE_2003;
+ }
+
+ ///
+ /// Get the captions of all the open powerpoint presentations
+ ///
+ ///
+ public static List GetPowerpointPresentations() {
+ List foundPresentations = new List();
+ try {
+ using (IPowerpointApplication powerpointApplication = GetPowerpointApplication()) {
+ if (powerpointApplication == null) {
+ return foundPresentations;
+ }
+
+ using (IPresentations presentations = powerpointApplication.Presentations) {
+ LOG.DebugFormat("Open Presentations: {0}", presentations.Count);
+ for (int i = 1; i <= presentations.Count; i++) {
+ using (IPresentation presentation = presentations.item(i)) {
+ if (presentation == null) {
+ continue;
+ }
+ if (presentation.ReadOnly == MsoTriState.msoTrue) {
+ continue;
+ }
+ if (IsAfter2003()) {
+ if (presentation.Final) {
+ continue;
+ }
+ }
+ foundPresentations.Add(presentation.Name);
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ LOG.Warn("Problem retrieving word destinations, ignoring: ", ex);
+ }
+ foundPresentations.Sort();
+ return foundPresentations;
+ }
+
+ ///
+ /// Export the image from the tmpfile to the presentation with the supplied name
+ ///
+ /// Name of the presentation to insert to
+ /// Filename of the image file to insert
+ /// Size of the image
+ /// A string with the image title
+ ///
+ public static bool ExportToPresentation(string presentationName, string tmpFile, Size imageSize, string title) {
+ using (IPowerpointApplication powerpointApplication = GetPowerpointApplication()) {
+ if (powerpointApplication == null) {
+ return false;
+ }
+ using (IPresentations presentations = powerpointApplication.Presentations) {
+ LOG.DebugFormat("Open Presentations: {0}", presentations.Count);
+ for (int i = 1; i <= presentations.Count; i++) {
+ using (IPresentation presentation = presentations.item(i)) {
+ if (presentation == null) {
+ continue;
+ }
+ if (!presentation.Name.StartsWith(presentationName)) {
+ continue;
+ }
+ try {
+ AddPictureToPresentation(presentation, tmpFile, imageSize, title);
+ return true;
+ } catch (Exception e) {
+ LOG.Error(e);
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Internal method to add a picture to a presentation
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static void AddPictureToPresentation(IPresentation presentation, string tmpFile, Size imageSize, string title) {
+ if (presentation != null) {
+ //ISlide slide = presentation.Slides.AddSlide( presentation.Slides.Count + 1, PPSlideLayout.ppLayoutPictureWithCaption);
+ ISlide slide;
+ float left = (presentation.PageSetup.SlideWidth / 2) - (imageSize.Width / 2f);
+ float top = (presentation.PageSetup.SlideHeight / 2) - (imageSize.Height / 2f);
+ float width = imageSize.Width;
+ float height = imageSize.Height;
+ IShape shapeForCaption = null;
+ bool hasScaledWidth = false;
+ bool hasScaledHeight = false;
+ try {
+ slide = presentation.Slides.Add(presentation.Slides.Count + 1, (int)officeConfiguration.PowerpointSlideLayout);
+ // Shapes[2] is the image shape on this layout.
+ shapeForCaption = slide.Shapes.item(1);
+ IShape shapeForLocation = slide.Shapes.item(2);
+
+ if (width > shapeForLocation.Width) {
+ width = shapeForLocation.Width;
+ left = shapeForLocation.Left;
+ hasScaledWidth = true;
+ } else {
+ shapeForLocation.Left = left;
+ }
+ shapeForLocation.Width = imageSize.Width;
+
+ if (height > shapeForLocation.Height) {
+ height = shapeForLocation.Height;
+ top = shapeForLocation.Top;
+ hasScaledHeight = true;
+ } else {
+ top = (shapeForLocation.Top + (shapeForLocation.Height / 2)) - (imageSize.Height / 2f);
+ }
+ shapeForLocation.Height = imageSize.Height;
+ } catch (Exception e) {
+ LOG.Error(e);
+ slide = presentation.Slides.Add(presentation.Slides.Count + 1, (int)PPSlideLayout.ppLayoutBlank);
+ }
+ IShape shape = slide.Shapes.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height);
+ if (officeConfiguration.PowerpointLockAspectRatio) {
+ shape.LockAspectRatio = MsoTriState.msoTrue;
+ } else {
+ shape.LockAspectRatio = MsoTriState.msoFalse;
+ }
+ shape.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
+ shape.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
+ if (hasScaledWidth) {
+ shape.Width = width;
+ }
+ if (hasScaledHeight) {
+ shape.Height = height;
+ }
+ shape.Left = left;
+ shape.Top = top;
+ shape.AlternativeText = title;
+ if (shapeForCaption != null) {
+ try {
+ // Using try/catch to make sure problems with the text range don't give an exception.
+ ITextFrame textFrame = shapeForCaption.TextFrame;
+ textFrame.TextRange.Text = title;
+ } catch (Exception ex) {
+ LOG.Warn("Problem setting the title to a text-range", ex);
+ }
+ }
+ presentation.Application.ActiveWindow.View.GotoSlide(slide.SlideNumber);
+ presentation.Application.Activate();
+ }
+ }
+
+ ///
+ /// Insert a capture into a new presentation
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool InsertIntoNewPresentation(string tmpFile, Size imageSize, string title) {
+ bool isPictureAdded = false;
+ using (IPowerpointApplication powerpointApplication = GetOrCreatePowerpointApplication()) {
+ if (powerpointApplication != null) {
+ powerpointApplication.Visible = true;
+ using (IPresentations presentations = powerpointApplication.Presentations) {
+ using (IPresentation presentation = presentations.Add(MsoTriState.msoTrue)) {
+ try {
+ AddPictureToPresentation(presentation, tmpFile, imageSize, title);
+ isPictureAdded = true;
+ } catch (Exception e) {
+ LOG.Error(e);
+ }
+ }
+ }
+ }
+ }
+ return isPictureAdded;
+ }
+
+ ///
+ /// Call this to get the running powerpoint application, returns null if there isn't any.
+ ///
+ /// IPowerpointApplication or null
+ private static IPowerpointApplication GetPowerpointApplication() {
+ IPowerpointApplication powerpointApplication = COMWrapper.GetInstance();
+ InitializeVariables(powerpointApplication);
+ return powerpointApplication;
+ }
+
+ ///
+ /// Call this to get the running powerpoint application, or create a new instance
+ ///
+ /// IPowerpointApplication
+ private static IPowerpointApplication GetOrCreatePowerpointApplication() {
+ IPowerpointApplication powerpointApplication = COMWrapper.GetOrCreateInstance();
+ InitializeVariables(powerpointApplication);
+ return powerpointApplication;
+ }
+
+ ///
+ /// Initialize static outlook variables like version and currentuser
+ ///
+ /// IPowerpointApplication
+ private static void InitializeVariables(IPowerpointApplication powerpointApplication) {
+ if (powerpointApplication == null || _powerpointVersion != null) {
+ return;
+ }
+ try {
+ _powerpointVersion = new Version(powerpointApplication.Version);
+ LOG.InfoFormat("Using Powerpoint {0}", _powerpointVersion);
+ } catch (Exception exVersion) {
+ LOG.Error(exVersion);
+ LOG.Warn("Assuming Powerpoint version 1997.");
+ _powerpointVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0);
+ }
+ }
+
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeExport/WordExporter.cs b/GreenshotOfficePlugin/OfficeExport/WordExporter.cs
new file mode 100644
index 000000000..350f51fd8
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeExport/WordExporter.cs
@@ -0,0 +1,297 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using GreenshotOfficePlugin;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace Greenshot.Interop.Office {
+ public class WordExporter {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(WordExporter));
+ private static Version _wordVersion;
+ private static readonly OfficeConfiguration OfficeConfig = IniConfig.GetIniSection();
+
+ ///
+ /// Check if the used version is higher than Office 2003
+ ///
+ ///
+ private static bool IsAfter2003() {
+ return _wordVersion.Major > (int)OfficeVersion.OFFICE_2003;
+ }
+
+ ///
+ /// Insert the bitmap stored under the tempfile path into the word document with the supplied caption
+ ///
+ ///
+ ///
+ ///
+ public static bool InsertIntoExistingDocument(string wordCaption, string tmpFile) {
+ using (IWordApplication wordApplication = GetWordApplication()) {
+ if (wordApplication == null) {
+ return false;
+ }
+ using (IDocuments documents = wordApplication.Documents) {
+ for (int i = 1; i <= documents.Count; i++) {
+ using (IWordDocument wordDocument = documents.item(i)) {
+ using (IWordWindow activeWindow = wordDocument.ActiveWindow) {
+ if (activeWindow.Caption.StartsWith(wordCaption)) {
+ return InsertIntoExistingDocument(wordApplication, wordDocument, tmpFile, null, null);
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Internal method for the insert
+ ///
+ ///
+ ///
+ ///
+ /// link for the image
+ /// tooltip of the image
+ ///
+ internal static bool InsertIntoExistingDocument(IWordApplication wordApplication, IWordDocument wordDocument, string tmpFile, string address, string tooltip) {
+ // Bug #1517: image will be inserted into that document, where the focus was last. It will not inserted into the chosen one.
+ // Solution: Make sure the selected document is active, otherwise the insert will be made in a different document!
+ try {
+ wordDocument.Activate();
+ }
+ catch
+ {
+ // ignored
+ }
+ using (ISelection selection = wordApplication.Selection) {
+ if (selection == null) {
+ Log.InfoFormat("No selection to insert {0} into found.", tmpFile);
+ return false;
+ }
+ // Add Picture
+ using (IInlineShape shape = AddPictureToSelection(selection, tmpFile)) {
+ if (!string.IsNullOrEmpty(address)) {
+ object screentip = Type.Missing;
+ if (!string.IsNullOrEmpty(tooltip)) {
+ screentip = tooltip;
+ }
+ try {
+ using (IHyperlinks hyperlinks = wordDocument.Hyperlinks) {
+ hyperlinks.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing);
+ }
+ } catch (Exception e) {
+ Log.WarnFormat("Couldn't add hyperlink for image: {0}", e.Message);
+ }
+ }
+ }
+ try {
+ using (IWordWindow activeWindow = wordDocument.ActiveWindow) {
+ activeWindow.Activate();
+ using (IPane activePane = activeWindow.ActivePane) {
+ using (IWordView view = activePane.View) {
+ view.Zoom.Percentage = 100;
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.WarnFormat("Couldn't set zoom to 100, error: {0}", e.InnerException?.Message ?? e.Message);
+ }
+ try {
+ wordApplication.Activate();
+ }
+ catch
+ {
+ // ignored
+ }
+ try {
+ using (var activeWindow = wordDocument.ActiveWindow)
+ {
+ activeWindow.Activate();
+ int hWnd = activeWindow.Hwnd;
+ if (hWnd > 0)
+ {
+ WindowDetails.ToForeground(new IntPtr(hWnd));
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ return true;
+ }
+ }
+
+ ///
+ /// Helper method to add the file as image to the selection
+ ///
+ ///
+ ///
+ ///
+ private static IInlineShape AddPictureToSelection(ISelection selection, string tmpFile) {
+ using (IInlineShapes shapes = selection.InlineShapes) {
+ IInlineShape shape = shapes.AddPicture(tmpFile, false, true, Type.Missing);
+ // Lock aspect ratio
+ if (OfficeConfig.WordLockAspectRatio) {
+ shape.LockAspectRatio = MsoTriState.msoTrue;
+ }
+ selection.InsertAfter("\r\n");
+ selection.MoveDown(WdUnits.wdLine, 1, Type.Missing);
+ return shape;
+ }
+ }
+
+ public static void InsertIntoNewDocument(string tmpFile, string address, string tooltip) {
+ using (IWordApplication wordApplication = GetOrCreateWordApplication()) {
+ if (wordApplication == null) {
+ return;
+ }
+ wordApplication.Visible = true;
+ wordApplication.Activate();
+ // Create new Document
+ object template = string.Empty;
+ object newTemplate = false;
+ object documentType = 0;
+ object documentVisible = true;
+ using (IDocuments documents = wordApplication.Documents) {
+ using (IWordDocument wordDocument = documents.Add(ref template, ref newTemplate, ref documentType, ref documentVisible)) {
+ using (ISelection selection = wordApplication.Selection) {
+ // Add Picture
+ using (IInlineShape shape = AddPictureToSelection(selection, tmpFile)) {
+ if (!string.IsNullOrEmpty(address)) {
+ object screentip = Type.Missing;
+ if (!string.IsNullOrEmpty(tooltip)) {
+ screentip = tooltip;
+ }
+ try {
+ using (IHyperlinks hyperlinks = wordDocument.Hyperlinks) {
+ hyperlinks.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing);
+ }
+ } catch (Exception e) {
+ Log.WarnFormat("Couldn't add hyperlink for image: {0}", e.Message);
+ }
+ }
+ }
+ }
+ try {
+ wordDocument.Activate();
+ }
+ catch
+ {
+ // ignored
+ }
+ try {
+ using (var activeWindow = wordDocument.ActiveWindow)
+ {
+ activeWindow.Activate();
+ int hWnd = activeWindow.Hwnd;
+ if (hWnd > 0)
+ {
+ WindowDetails.ToForeground(new IntPtr(hWnd));
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Get the captions of all the open word documents
+ ///
+ ///
+ public static List GetWordDocuments() {
+ List openDocuments = new List();
+ try {
+ using (IWordApplication wordApplication = GetWordApplication()) {
+ if (wordApplication == null) {
+ return openDocuments;
+ }
+ using (IDocuments documents = wordApplication.Documents) {
+ for (int i = 1; i <= documents.Count; i++) {
+ using (IWordDocument document = documents.item(i)) {
+ if (document.ReadOnly) {
+ continue;
+ }
+ if (IsAfter2003()) {
+ if (document.Final) {
+ continue;
+ }
+ }
+ using (IWordWindow activeWindow = document.ActiveWindow) {
+ openDocuments.Add(activeWindow.Caption);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Log.Warn("Problem retrieving word destinations, ignoring: ", ex);
+ }
+ openDocuments.Sort();
+ return openDocuments;
+ }
+
+ ///
+ /// Call this to get the running outlook application, returns null if there isn't any.
+ ///
+ /// IWordApplication or null
+ private static IWordApplication GetWordApplication() {
+ IWordApplication wordApplication = COMWrapper.GetInstance();
+ InitializeVariables(wordApplication);
+ return wordApplication;
+ }
+
+ ///
+ /// Call this to get the running word application, or create a new instance
+ ///
+ /// IWordApplication
+ private static IWordApplication GetOrCreateWordApplication() {
+ IWordApplication wordApplication = COMWrapper.GetOrCreateInstance();
+ InitializeVariables(wordApplication);
+ return wordApplication;
+ }
+
+ ///
+ /// Initialize static outlook variables like version and currentuser
+ ///
+ ///
+ private static void InitializeVariables(IWordApplication wordApplication) {
+ if (wordApplication == null || _wordVersion != null) {
+ return;
+ }
+ try {
+ _wordVersion = new Version(wordApplication.Version);
+ Log.InfoFormat("Using Word {0}", _wordVersion);
+ } catch (Exception exVersion) {
+ Log.Error(exVersion);
+ Log.Warn("Assuming Word version 1997.");
+ _wordVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0);
+ }
+ }
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/ExcelInterop.cs b/GreenshotOfficePlugin/OfficeInterop/ExcelInterop.cs
new file mode 100644
index 000000000..4ff22b066
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/ExcelInterop.cs
@@ -0,0 +1,99 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Interop.Office {
+ // See http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.application.aspx
+ [ComProgId("Excel.Application")]
+ public interface IExcelApplication : ICommon {
+ IWorkbook ActiveWorkbook {
+ get;
+ }
+ //ISelection Selection {get;}
+ IWorkbooks Workbooks {
+ get;
+ }
+ bool Visible {
+ get;
+ set;
+ }
+ string Version {
+ get;
+ }
+
+ ///
+ /// Returns an Integer indicating the top-level window handle of the Microsoft Excel window.
+ ///
+ int Hwnd
+ {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.workbooks.aspx
+ public interface IWorkbooks : ICommon, ICollection {
+ IWorkbook Add(object template);
+ // Use index + 1!!
+ IWorkbook this[object index] {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.workbook.aspx
+ public interface IWorkbook : ICommon {
+ IWorksheet ActiveSheet {
+ get;
+ }
+ string Name {
+ get;
+ }
+ void Activate();
+ IWorksheets Worksheets {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel._worksheet_members.aspx
+ public interface IWorksheet : ICommon {
+ IPictures Pictures {
+ get;
+ }
+ IShapes Shapes {
+ get;
+ }
+ string Name {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.iworksheets_members.aspx
+ public interface IWorksheets : ICollection {
+ // Use index + 1!!
+ IWorksheet this[object index] {
+ get;
+ }
+ }
+
+ public interface IPictures : ICollection {
+ // Use index + 1!!
+ //IPicture this[object Index] { get; }
+ void Insert(string file);
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/OfficeCommunicator.cs b/GreenshotOfficePlugin/OfficeInterop/OfficeCommunicator.cs
new file mode 100644
index 000000000..f659d12b3
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/OfficeCommunicator.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Greenshot.Interop;
+using Greenshot.Interop.Office;
+
+namespace GreenshotInterop.OfficeInterop {
+ // See: http://msdn.microsoft.com/en-us/library/bb758788%28v=office.12%29
+ [ComProgId("Communicator.UIAutomation")]
+ public interface IMessenger : Common {
+ void AutoSignin();
+ string MyServiceId {
+ get;
+ }
+ IMessengerContact GetContact(string signinName, string serviceId);
+ IMessengerWindow InstantMessage(string contact);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/bb787250%28v=office.12%29
+ public interface IMessengerContact : Common {
+ string FriendlyName {
+ get;
+ }
+ string ServiceName {
+ get;
+ }
+ string ServiceId {
+ get;
+ }
+ string SigninName {
+ get;
+ }
+ MISTATUS Status {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/bb787207%28v=office.12%29
+ public enum MISTATUS {
+ MISTATUS_UNKNOWN = 0x0000,
+ MISTATUS_OFFLINE = 0x0001,
+ MISTATUS_ONLINE = 0x0002,
+ MISTATUS_INVISIBLE = 0x0006,
+ MISTATUS_BUSY = 0x000A,
+ MISTATUS_BE_RIGHT_BACK = 0x000E,
+ MISTATUS_IDLE = 0x0012,
+ MISTATUS_AWAY = 0x0022,
+ MISTATUS_ON_THE_PHONE = 0x0032,
+ MISTATUS_OUT_TO_LUNCH = 0x0042,
+ MISTATUS_IN_A_MEETING = 0x0052,
+ MISTATUS_OUT_OF_OFFICE = 0x0062,
+ MISTATUS_DO_NOT_DISTURB = 0x0072,
+ MISTATUS_IN_A_CONFERENCE = 0x0082,
+ MISTATUS_ALLOW_URGENT_INTERRUPTIONS = 0x0092,
+ MISTATUS_MAY_BE_AVAILABLE = 0x00A2,
+ MISTATUS_CUSTOM = 0x00B2,
+ MISTATUS_LOCAL_FINDING_SERVER = 0x0100,
+ MISTATUS_LOCAL_CONNECTING_TO_SERVER = 0x0200,
+ MISTATUS_LOCAL_SYNCHRONIZING_WITH_SERVER = 0x0300,
+ MISTATUS_LOCAL_DISCONNECTING_FROM_SERVER = 0x0400
+ } ;
+
+ // See: http://msdn.microsoft.com/en-us/library/bb758816%28v=office.12%29
+ public interface IMessengerWindow : Common {
+ bool IsClosed {
+ get;
+ }
+ void Show();
+ }
+
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/OfficeInterop.cs b/GreenshotOfficePlugin/OfficeInterop/OfficeInterop.cs
new file mode 100644
index 000000000..6887d4374
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/OfficeInterop.cs
@@ -0,0 +1,43 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Collections;
+
+namespace Greenshot.Interop.Office {
+ public enum OfficeVersion : int {
+ OFFICE_97 = 8,
+ OFFICE_2000 = 9,
+ OFFICE_2002 = 10,
+ OFFICE_2003 = 11,
+ OFFICE_2007 = 12,
+ OFFICE_2010 = 14,
+ OFFICE_2013 = 15
+ }
+
+ ///
+ /// If the "type" this[object index] { get; } is implemented, use index + 1!!! (starts at 1)
+ ///
+ public interface ICollection : ICommon, IEnumerable {
+ int Count {
+ get;
+ }
+ void Remove(int index);
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs b/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs
new file mode 100644
index 000000000..ed00cfdb5
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs
@@ -0,0 +1,103 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+
+namespace Greenshot.Interop.Office {
+ // More details about OneNote: http://msdn.microsoft.com/en-us/magazine/ff796230.aspx
+
+ // See http://msdn.microsoft.com/de-de/library/microsoft.office.interop.word.applicationclass_members%28v=Office.11%29.aspx
+ [ComProgId("OneNote.Application")]
+ public interface IOneNoteApplication : ICommon {
+ ///
+ /// Make sure that the out variables are filled with a string, e.g. "", otherwise a type error occurs.
+ /// For more info on the methods: http://msdn.microsoft.com/en-us/library/gg649853.aspx
+ ///
+ void GetHierarchy(string startNode, HierarchyScope scope, out string notebookXml, XMLSchema schema);
+ void GetSpecialLocation(SpecialLocation specialLocation, out string specialLocationPath);
+ void UpdatePageContent(string pageChangesXml, DateTime dateExpectedLastModified, XMLSchema schema, bool force);
+ void GetPageContent(string pageId, out string pageXml, PageInfo pageInfoToExport, XMLSchema schema);
+ void NavigateTo(string hierarchyObjectID, string objectId, bool newWindow);
+ void CreateNewPage(string sectionID, out string pageID, NewPageStyle newPageStyle);
+ }
+
+ public enum PageInfo {
+ piBasic = 0, // Returns only basic page content, without selection markup and binary data objects. This is the standard value to pass.
+ piBinaryData = 1, // Returns page content with no selection markup, but with all binary data.
+ piSelection = 2, // Returns page content with selection markup, but no binary data.
+ piBinaryDataSelection = 3, // Returns page content with selection markup and all binary data.
+ piAll = 3 // Returns all page content.
+ }
+
+ public enum HierarchyScope {
+ hsSelf = 0, // Gets just the start node specified and no descendants.
+ hsChildren = 1, //Gets the immediate child nodes of the start node, and no descendants in higher or lower subsection groups.
+ hsNotebooks = 2, // Gets all notebooks below the start node, or root.
+ hsSections = 3, //Gets all sections below the start node, including sections in section groups and subsection groups.
+ hsPages = 4 //Gets all pages below the start node, including all pages in section groups and subsection groups.
+ }
+
+ public enum XMLSchema {
+ xs2007 = 0,
+ xs2010 = 1,
+ xsCurrent= xs2010
+ }
+
+ public enum SpecialLocation : int {
+ slBackupFolder = 0,
+ slUnfiledNotesSection = 1,
+ slDefaultNotebookFolder = 2
+ }
+
+ public enum NewPageStyle {
+ npsDefault = 0,
+ npsBlankPageWithTitle = 1,
+ npsBlankPageNoTitle = 2
+ }
+
+ public class OneNotePage {
+ public OneNoteSection Parent { get; set; }
+ public string Name { get; set; }
+ public string ID { get; set; }
+ public bool IsCurrentlyViewed { get; set; }
+ public string DisplayName {
+ get {
+ OneNoteNotebook notebook = Parent.Parent;
+ if(string.IsNullOrEmpty(notebook.Name)) {
+ return string.Format("{0} / {1}", Parent.Name, Name);
+ } else {
+ return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name);
+ }
+ }
+ }
+ }
+
+ public class OneNoteSection {
+ public OneNoteNotebook Parent { get; set; }
+ public string Name { get; set; }
+ public string ID { get; set; }
+ }
+
+ public class OneNoteNotebook {
+ public string Name { get; set; }
+ public string ID { get; set; }
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/OutlookInterop.cs b/GreenshotOfficePlugin/OfficeInterop/OutlookInterop.cs
new file mode 100644
index 000000000..2fee5863d
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/OutlookInterop.cs
@@ -0,0 +1,660 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections;
+
+namespace Greenshot.Interop.Office {
+ ///
+ /// Wrapper for Outlook.Application, see: http://msdn.microsoft.com/en-us/library/aa210897%28v=office.11%29.aspx
+ /// This is the initial COM-Object which is created/retrieved
+ ///
+ [ComProgId("Outlook.Application")]
+ public interface IOutlookApplication : ICommon {
+ string Name {
+ get;
+ }
+ string Version {
+ get;
+ }
+ IItem CreateItem(OlItemType ItemType);
+ object CreateItemFromTemplate(string TemplatePath, object InFolder);
+ object CreateObject(string ObjectName);
+ IInspector ActiveInspector();
+ IInspectors Inspectors {
+ get;
+ }
+ INameSpace GetNameSpace(string type);
+ IExplorer ActiveExplorer();
+ IExplorers Explorers {
+ get;
+ }
+ }
+
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/bb208387%28v=office.12%29.aspx
+ ///
+ public interface IItems : ICollection, IEnumerable {
+ IItem this[object index] {
+ get;
+ }
+ IItem GetFirst();
+ IItem GetNext();
+ IItem GetLast();
+ IItem GetPrevious();
+
+ bool IncludeRecurrences {
+ get;
+ set;
+ }
+
+ IItems Restrict(string filter);
+ void Sort(string property, object descending);
+
+ // Actual definition is "object Add( object )", just making it convenient
+ object Add(OlItemType type);
+ }
+
+ // Common attributes of all the Items (MailItem, AppointmentItem)
+ // See: http://msdn.microsoft.com/en-us/library/ff861252.aspx
+ public interface IItem : ICommon {
+ IAttachments Attachments {
+ get;
+ }
+ string Body {
+ get;
+ set;
+ }
+ OlObjectClass Class {
+ get;
+ }
+ DateTime CreationTime {
+ get;
+ }
+ string EntryID {
+ get;
+ }
+ DateTime LastModificationTime {
+ get;
+ }
+ string MessageClass {
+ get;
+ set;
+ }
+ bool NoAging {
+ get;
+ set;
+ }
+ int OutlookInternalVersion {
+ get;
+ }
+ string OutlookVersion {
+ get;
+ }
+ bool Saved {
+ get;
+ }
+ OlSensitivity Sensitivity {
+ get;
+ set;
+ }
+ int Size {
+ get;
+ }
+ string Subject {
+ get;
+ set;
+ }
+ bool UnRead {
+ get;
+ set;
+ }
+ object Copy();
+ void Display(bool Modal);
+ void Save();
+ IPropertyAccessor PropertyAccessor {
+ get;
+ }
+ IInspector GetInspector();
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/ff861252.aspx
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.mailitem.aspx
+ public interface MailItem : IItem, ICommon {
+ bool Sent {
+ get;
+ }
+ object MAPIOBJECT {
+ get;
+ }
+ string HTMLBody {
+ get;
+ set;
+ }
+ DateTime ExpiryTime {
+ get;
+ set;
+ }
+ DateTime ReceivedTime {
+ get;
+ }
+ string SenderName {
+ get;
+ }
+ DateTime SentOn {
+ get;
+ }
+ OlBodyFormat BodyFormat {
+ get;
+ set;
+ }
+ string To {
+ get;
+ set;
+ }
+ string CC {
+ get;
+ set;
+ }
+ string BCC {
+ get;
+ set;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/ff869026.aspx
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.appointmentitem.aspx
+ public interface AppointmentItem : IItem, ICommon {
+ string Organizer {
+ get;
+ set;
+ }
+ string SendUsingAccount {
+ get;
+ }
+ string Categories {
+ get;
+ }
+ DateTime Start {
+ get;
+ }
+ DateTime End {
+ get;
+ }
+ OlReoccurenceState RecurrenceState {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.contactitem.aspx
+ public interface IContactItem : IItem, ICommon {
+ bool HasPicture {
+ get;
+ }
+ void SaveBusinessCardImage(string path);
+ void AddPicture(string path);
+ void RemovePicture();
+ string FirstName {
+ get;
+ set;
+ }
+ string LastName {
+ get;
+ set;
+ }
+ }
+
+ public interface IAttachments : ICollection {
+ IAttachment Add(object source, object type, object position, object displayName);
+ // Use index+1!!!!
+ IAttachment this[object index] {
+ get;
+ }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.attachment_members.aspx
+ public interface IAttachment : ICommon {
+ string DisplayName {
+ get;
+ set;
+ }
+ string FileName {
+ get;
+ }
+ OlAttachmentType Type {
+ get;
+ }
+ IPropertyAccessor PropertyAccessor {
+ get;
+ }
+ object MAPIOBJECT {
+ get;
+ }
+ void SaveAsFile(string path);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.propertyaccessor_members.aspx
+ public interface IPropertyAccessor : ICommon {
+ void SetProperty(string SchemaName, object Value);
+ object GetProperty(string SchemaName);
+ }
+
+ // Schema definitions for the MAPI properties
+ // See: http://msdn.microsoft.com/en-us/library/aa454438.aspx
+ // and see: http://msdn.microsoft.com/en-us/library/bb446117.aspx
+ public static class PropTag {
+ public const string ATTACHMENT_CONTENT_ID = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/bb176693%28v=office.12%29.aspx
+ ///
+ public interface INameSpace : ICommon {
+ IRecipient CurrentUser {
+ get;
+ }
+ IFolder GetDefaultFolder(OlDefaultFolders defaultFolder);
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/bb176362%28v=office.12%29.aspx
+ ///
+ public interface IFolder : ICommon {
+ IItems Items {
+ get;
+ }
+ }
+
+ public interface IRecipient : ICommon {
+ string Name {
+ get;
+ }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.inspector_members.aspx
+ ///
+ public interface IInspector : ICommonExplorer {
+ IItem CurrentItem {
+ get;
+ }
+ OlEditorType EditorType {
+ get;
+ }
+ object ModifiedFormPages {
+ get;
+ }
+ void Close(OlInspectorClose SaveMode);
+ void Display(object Modal);
+ void HideFormPage(string PageName);
+ bool IsWordMail();
+ void SetCurrentFormPage(string PageName);
+ void ShowFormPage(string PageName);
+ object HTMLEditor {
+ get;
+ }
+ IWordDocument WordEditor {
+ get;
+ }
+ void SetControlItemProperty(object Control, string PropertyName);
+ }
+
+ ///
+ /// Is a joined interface of the Explorer an Inspector
+ ///
+ public interface ICommonExplorer : ICommon {
+ void Activate();
+ string Caption {
+ get;
+ }
+ int Height {
+ get;
+ set;
+ }
+ int Left {
+ get;
+ set;
+ }
+ int Top {
+ get;
+ set;
+ }
+ int Width {
+ get;
+ set;
+ }
+ OlWindowState WindowState {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// Since Outlook 2010, but since 2013 one can edit inside an explorer
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.explorer_members(v=office.15).aspx
+ ///
+ ///
+ public interface IExplorer : ICommonExplorer {
+ IItem ActiveInlineResponse {
+ get;
+ }
+ IWordDocument ActiveInlineResponseWordEditor {
+ get;
+ }
+ }
+
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._application.inspectors.aspx
+ public interface IInspectors : ICommon, ICollection, IEnumerable {
+ // Use index + 1!!
+ IInspector this[object Index] {
+ get;
+ }
+ }
+
+ ///
+ /// Since Outlook 2010, but since 2013 one can edit inside an explorer
+ /// See: http://msdn.microsoft.com/en-us/library/office/ff867227(v=office.15).aspx
+ ///
+ public interface IExplorers : ICommon, ICollection, IEnumerable {
+ // Use index + 1!!
+ IExplorer this[object Index] {
+ get;
+ }
+ }
+
+ ///
+ /// Specifies which EmailFormat the email needs to use
+ ///
+ public enum EmailFormat {
+ Text,
+ HTML
+ }
+ public enum OlBodyFormat {
+ // Fields
+ olFormatHTML = 2,
+ olFormatPlain = 1,
+ olFormatRichText = 3,
+ olFormatUnspecified = 0
+ }
+
+ public enum OlAttachmentType {
+ // Fields
+ olByReference = 4,
+ olByValue = 1,
+ olEmbeddeditem = 5,
+ olOLE = 6
+ }
+
+ public enum OlSensitivity {
+ // Fields
+ olConfidential = 3,
+ olNormal = 0,
+ olPersonal = 1,
+ olPrivate = 2
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/ff863329.aspx
+ public enum OlObjectClass {
+ olAccount = 105, // Represents an Account object.
+ olAccountRuleCondition = 135, // Represents an AccountRuleCondition object.
+ olAccounts = 106, // Represents an Accounts object.
+ olAction = 32, // Represents an Action object.
+ olActions = 33, // Represents an Actions object.
+ olAddressEntries = 21, // Represents an AddressEntries object.
+ olAddressEntry = 8, // Represents an AddressEntry object.
+ olAddressList = 7, // Represents an AddressList object.
+ olAddressLists = 20, // Represents an AddressLists object.
+ olAddressRuleCondition = 170, // Represents an AddressRuleCondition object.
+ olApplication = 0, // Represents an Application object.
+ olAppointment = 26, // Represents an AppointmentItem object.
+ olAssignToCategoryRuleAction = 122, // Represents an AssignToCategoryRuleAction object.
+ olAttachment = 5, // Represents an Attachment object.
+ olAttachments = 18, // Represents an Attachments object.
+ olAttachmentSelection = 169, // Represents an AttachmentSelection object.
+ olAutoFormatRule = 147, // Represents an AutoFormatRule object.
+ olAutoFormatRules = 148, // Represents an AutoFormatRules object.
+ olCalendarModule = 159, // Represents a CalendarModule object.
+ olCalendarSharing = 151, // Represents a CalendarSharing object.
+ olCategories = 153, // Represents a Categories object.
+ olCategory = 152, // Represents a Category object.
+ olCategoryRuleCondition = 130, // Represents a CategoryRuleCondition object.
+ olClassBusinessCardView = 168, // Represents a BusinessCardView object.
+ olClassCalendarView = 139, // Represents a CalendarView object.
+ olClassCardView = 138, // Represents a CardView object.
+ olClassIconView = 137, // Represents a IconView object.
+ olClassNavigationPane = 155, // Represents a NavigationPane object.
+ olClassTableView = 136, // Represents a TableView object.
+ olClassTimeLineView = 140, // Represents a TimelineView object.
+ olClassTimeZone = 174, // Represents a TimeZone object.
+ olClassTimeZones = 175, // Represents a TimeZones object.
+ olColumn = 154, // Represents a Column object.
+ olColumnFormat = 149, // Represents a ColumnFormat object.
+ olColumns = 150, // Represents a Columns object.
+ olConflict = 102, // Represents a Conflict object.
+ olConflicts = 103, // Represents a Conflicts object.
+ olContact = 40, // Represents a ContactItem object.
+ olContactsModule = 160, // Represents a ContactsModule object.
+ olDistributionList = 69, // Represents a ExchangeDistributionList object.
+ olDocument = 41, // Represents a DocumentItem object.
+ olException = 30, // Represents an Exception object.
+ olExceptions = 29, // Represents an Exceptions object.
+ olExchangeDistributionList = 111, // Represents an ExchangeDistributionList object.
+ olExchangeUser = 110, // Represents an ExchangeUser object.
+ olExplorer = 34, // Represents an Explorer object.
+ olExplorers = 60, // Represents an Explorers object.
+ olFolder = 2, // Represents a Folder object.
+ olFolders = 15, // Represents a Folders object.
+ olFolderUserProperties = 172, // Represents a UserDefinedProperties object.
+ olFolderUserProperty = 171, // Represents a UserDefinedProperty object.
+ olFormDescription = 37, // Represents a FormDescription object.
+ olFormNameRuleCondition = 131, // Represents a FormNameRuleCondition object.
+ olFormRegion = 129, // Represents a FormRegion object.
+ olFromRssFeedRuleCondition = 173, // Represents a FromRssFeedRuleCondition object.
+ olFromRuleCondition = 132, // Represents a ToOrFromRuleCondition object.
+ olImportanceRuleCondition = 128, // Represents an ImportanceRuleCondition object.
+ olInspector = 35, // Represents an Inspector object.
+ olInspectors = 61, // Represents an Inspectors object.
+ olItemProperties = 98, // Represents an ItemProperties object.
+ olItemProperty = 99, // Represents an ItemProperty object.
+ olItems = 16, // Represents an Items object.
+ olJournal = 42, // Represents a JournalItem object.
+ olJournalModule = 162, // Represents a JournalModule object.
+ olLink = 75, // Represents a Link object.
+ olLinks = 76, // Represents a Links object.
+ olMail = 43, // Represents a MailItem object.
+ olMailModule = 158, // Represents a MailModule object.
+ olMarkAsTaskRuleAction = 124, // Represents a MarkAsTaskRuleAction object.
+ olMeetingCancellation = 54, // Represents a MeetingItem object that is a meeting cancellation notice.
+ olMeetingRequest = 53, // Represents a MeetingItem object that is a meeting request.
+ olMeetingResponseNegative = 55, // Represents a MeetingItem object that is a refusal of a meeting request.
+ olMeetingResponsePositive = 56, // Represents a MeetingItem object that is an acceptance of a meeting request.
+ olMeetingResponseTentative = 57, // Represents a MeetingItem object that is a tentative acceptance of a meeting request.
+ olMoveOrCopyRuleAction = 118, // Represents a MoveOrCopyRuleAction object.
+ olNamespace = 1, // Represents a NameSpace object.
+ olNavigationFolder = 167, // Represents a NavigationFolder object.
+ olNavigationFolders = 166, // Represents a NavigationFolders object.
+ olNavigationGroup = 165, // Represents a NavigationGroup object.
+ olNavigationGroups = 164, // Represents a NavigationGroups object.
+ olNavigationModule = 157, // Represents a NavigationModule object.
+ olNavigationModules = 156, // Represents a NavigationModules object.
+ olNewItemAlertRuleAction = 125, // Represents a NewItemAlertRuleAction object.
+ olNote = 44, // Represents a NoteItem object.
+ olNotesModule = 163, // Represents a NotesModule object.
+ olOrderField = 144, // Represents an OrderField object.
+ olOrderFields = 145, // Represents an OrderFields object.
+ olOutlookBarGroup = 66, // Represents an OutlookBarGroup object.
+ olOutlookBarGroups = 65, // Represents an OutlookBarGroups object.
+ olOutlookBarPane = 63, // Represents an OutlookBarPane object.
+ olOutlookBarShortcut = 68, // Represents an OutlookBarShortcut object.
+ olOutlookBarShortcuts = 67, // Represents an OutlookBarShortcuts object.
+ olOutlookBarStorage = 64, // Represents an OutlookBarStorage object.
+ olPages = 36, // Represents a Pages object.
+ olPanes = 62, // Represents a Panes object.
+ olPlaySoundRuleAction = 123, // Represents a PlaySoundRuleAction object.
+ olPost = 45, // Represents a PostItem object.
+ olPropertyAccessor = 112, // Represents a PropertyAccessor object.
+ olPropertyPages = 71, // Represents a PropertyPages object.
+ olPropertyPageSite = 70, // Represents a PropertyPageSite object.
+ olRecipient = 4, // Represents a Recipient object.
+ olRecipients = 17, // Represents a Recipients object.
+ olRecurrencePattern = 28, // Represents a RecurrencePattern object.
+ olReminder = 101, // Represents a Reminder object.
+ olReminders = 100, // Represents a Reminders object.
+ olRemote = 47, // Represents a RemoteItem object.
+ olReport = 46, // Represents a ReportItem object.
+ olResults = 78, // Represents a Results object.
+ olRow = 121, // Represents a Row object.
+ olRule = 115, // Represents a Rule object.
+ olRuleAction = 117, // Represents a RuleAction object.
+ olRuleActions = 116, // Represents a RuleAction object.
+ olRuleCondition = 127, // Represents a RuleCondition object.
+ olRuleConditions = 126, // Represents a RuleConditions object.
+ olRules = 114, // Represents a Rules object.
+ olSearch = 77, // Represents a Search object.
+ olSelection = 74, // Represents a Selection object.
+ olSelectNamesDialog = 109, // Represents a SelectNamesDialog object.
+ olSenderInAddressListRuleCondition = 133, // Represents a SenderInAddressListRuleCondition object.
+ olSendRuleAction = 119, // Represents a SendRuleAction object.
+ olSharing = 104, // Represents a SharingItem object.
+ olStorageItem = 113, // Represents a StorageItem object.
+ olStore = 107, // Represents a Store object.
+ olStores = 108, // Represents a Stores object.
+ olSyncObject = 72, // Represents a SyncObject object.
+ olSyncObjects = 73, // Represents a SyncObject object.
+ olTable = 120, // Represents a Table object.
+ olTask = 48, // Represents a TaskItem object.
+ olTaskRequest = 49, // Represents a TaskRequestItem object.
+ olTaskRequestAccept = 51, // Represents a TaskRequestAcceptItem object.
+ olTaskRequestDecline = 52, // Represents a TaskRequestDeclineItem object.
+ olTaskRequestUpdate = 50, // Represents a TaskRequestUpdateItem object.
+ olTasksModule = 161, // Represents a TasksModule object.
+ olTextRuleCondition = 134, // Represents a TextRuleCondition object.
+ olUserDefinedProperties = 172, // Represents a UserDefinedProperties object.
+ olUserDefinedProperty = 171, // Represents a UserDefinedProperty object.
+ olUserProperties = 38, // Represents a UserProperties object.
+ olUserProperty = 39, // Represents a UserProperty object.
+ olView = 80, // Represents a View object.
+ olViewField = 142, // Represents a ViewField object.
+ olViewFields = 141, // Represents a ViewFields object.
+ olViewFont = 146, // Represents a ViewFont object.
+ olViews = 79 // Represents a Views object.
+ }
+
+ public enum OlDefaultFolders {
+ olFolderCalendar = 9, // The Calendar folder.
+ olFolderConflicts = 19, // The Conflicts folder (subfolder of Sync Issues folder). Only available for an Exchange account.
+ olFolderContacts = 10, // The Contacts folder.
+ olFolderDeletedItems = 3, // The Deleted Items folder.
+ olFolderDrafts = 16, // The Drafts folder.
+ olFolderInbox = 6, // The Inbox folder.
+ olFolderJournal = 11, // The Journal folder.
+ olFolderJunk = 23, // The Junk E-Mail folder.
+ olFolderLocalFailures = 21, // The Local Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
+ olFolderManagedEmail = 29, // The top-level folder in the Managed Folders group. For more information on Managed Folders, see Help in Microsoft Outlook. Only available for an Exchange account.
+ olFolderNotes = 12, // The Notes folder.
+ olFolderOutbox = 4, // The Outbox folder.
+ olFolderSentMail = 5, // The Sent Mail folder.
+ olFolderServerFailures = 22, // The Server Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
+ olFolderSyncIssues = 20, // The Sync Issues folder. Only available for an Exchange account.
+ olFolderTasks = 13, // The Tasks folder.
+ olFolderToDo = 28, // The To Do folder.
+ olPublicFoldersAllPublicFolders = 18, // The All Public Folders folder in the Exchange Public Folders store. Only available for an Exchange account.
+ olFolderRssFeeds = 25 // The RSS Feeds folder.
+ }
+
+ public enum OlItemType {
+ // Fields
+ olAppointmentItem = 1,
+ olContactItem = 2,
+ olDistributionListItem = 7,
+ olJournalItem = 4,
+ olMailItem = 0,
+ olNoteItem = 5,
+ olPostItem = 6,
+ olTaskItem = 3
+ }
+
+ public enum OlEditorType {
+ // Fields
+ olEditorHTML = 2,
+ olEditorRTF = 3,
+ olEditorText = 1,
+ olEditorWord = 4
+ }
+
+ public enum OlWindowState {
+ // Fields
+ olMaximized = 0,
+ olMinimized = 1,
+ olNormalWindow = 2
+ }
+
+ public enum OlInspectorClose {
+ // Fields
+ olDiscard = 1,
+ olPromptForSave = 2,
+ olSave = 0
+ }
+
+ public enum MsoTriState {
+ msoTrue = -1,
+ msoFalse = 0,
+ msoCTrue = 1,
+ msoTriStateToggle = -3,
+ msoTriStateMixed = -2
+ }
+
+ public enum OlReoccurenceState {
+ olApptException,
+ olApptMaster,
+ olApptNotRecurring,
+ olApptOccurrence
+ }
+
+ public enum MsoScaleFrom {
+ msoScaleFromTopLeft = 0,
+ msoScaleFromMiddle = 1,
+ msoScaleFromBottomRight = 2
+ }
+
+ ///
+ /// Units: http://msdn.microsoft.com/en-us/library/office/bb214015(v=office.12).aspx
+ ///
+ public enum WdUnits {
+ wdCell = 12,
+ wdCharacter = 1,
+ wdCharacterFormatting = 13,
+ wdColumn = 9,
+ wdItem = 16,
+ wdLine = 5,
+ wdParagraph = 4,
+ wdParagraphFormatting = 14,
+ wdRow = 10,
+ wdScreen = 7,
+ wdSection = 8,
+ wdSentence = 3,
+ wdStory = 6,
+ wdTable = 15,
+ wdWindow = 11,
+ wdWord = 2
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/OutlookUtils.cs b/GreenshotOfficePlugin/OfficeInterop/OutlookUtils.cs
new file mode 100644
index 000000000..c0a85b341
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/OutlookUtils.cs
@@ -0,0 +1,798 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Runtime.InteropServices;
+
+namespace Greenshot.Interop.Office {
+ internal enum PT : uint {
+ PT_UNSPECIFIED = 0, /* (Reserved for interface use) type doesn't matter to caller */
+ PT_NULL = 1, /* NULL property value */
+ PT_I2 = 2, /* Signed 16-bit value */
+ PT_LONG = 3, /* Signed 32-bit value */
+ PT_R4 = 4, /* 4-byte floating point */
+ PT_DOUBLE = 5, /* Floating point double */
+ PT_CURRENCY = 6, /* Signed 64-bit int (decimal w/ 4 digits right of decimal pt) */
+ PT_APPTIME = 7, /* Application time */
+ PT_ERROR = 10, /* 32-bit error value */
+ PT_BOOLEAN = 11, /* 16-bit boolean (non-zero true, */
+ // Use PT_BOOLEAN_DESKTOP to be specific instead of using PT_BOOLEAN which is mapped to 2 in addrmapi.h
+ PT_BOOLEAN_DESKTOP = 11, /* 16-bit boolean (non-zero true) */
+ PT_OBJECT = 13, /* Embedded object in a property */
+ PT_I8 = 20, /* 8-byte signed integer */
+ PT_STRING8 = 30, /* Null terminated 8-bit character string */
+ PT_UNICODE = 31, /* Null terminated Unicode string */
+ PT_SYSTIME = 64, /* FILETIME 64-bit int w/ number of 100ns periods since Jan 1,1601 */
+ PT_CLSID = 72, /* OLE GUID */
+ PT_BINARY = 258, /* Uninterpreted (counted byte array) */
+
+ PT_TSTRING = PT_UNICODE
+ };
+
+ public enum PropTags : uint {
+ PR_ERROR = 10,
+
+ // Common non-transmittable
+ PR_ENTRYID = PT.PT_BINARY | 0x0FFF << 16,
+ PR_OBJECT_TYPE = PT.PT_LONG | 0x0FFE << 16,
+ PR_ICON = PT.PT_BINARY | 0x0FFD << 16,
+ PR_MINI_ICON = PT.PT_BINARY | 0x0FFC << 16,
+ PR_STORE_ENTRYID = PT.PT_BINARY | 0x0FFB << 16,
+ PR_STORE_RECORD_KEY = PT.PT_BINARY | 0x0FFA << 16,
+ PR_RECORD_KEY = PT.PT_BINARY | 0x0FF9 << 16,
+ PR_MAPPING_SIGNATURE = PT.PT_BINARY | 0x0FF8 << 16,
+ PR_ACCESS_LEVEL = PT.PT_LONG | 0x0FF7 << 16,
+ PR_INSTANCE_KEY = PT.PT_BINARY | 0x0FF6 << 16,
+ PR_ROW_TYPE = PT.PT_LONG | 0x0FF5 << 16,
+ PR_ACCESS = PT.PT_LONG | 0x0FF4 << 16,
+
+ // Common transmittable
+ PR_ROWID = PT.PT_LONG | 0x3000 << 16,
+ PR_DISPLAY_NAME = PT.PT_TSTRING | 0x3001 << 16,
+ PR_DISPLAY_NAME_W = PT.PT_UNICODE | 0x3001 << 16,
+ PR_DISPLAY_NAME_A = PT.PT_STRING8 | 0x3001 << 16,
+ PR_ADDRTYPE = PT.PT_TSTRING | 0x3002 << 16,
+ PR_ADDRTYPE_W = PT.PT_UNICODE | 0x3002 << 16,
+ PR_ADDRTYPE_A = PT.PT_STRING8 | 0x3002 << 16,
+ PR_EMAIL_ADDRESS = PT.PT_TSTRING | 0x3003 << 16,
+ PR_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x3003 << 16,
+ PR_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x3003 << 16,
+ PR_COMMENT = PT.PT_TSTRING | 0x3004 << 16,
+ PR_COMMENT_W = PT.PT_UNICODE | 0x3004 << 16,
+ PR_COMMENT_A = PT.PT_STRING8 | 0x3004 << 16,
+ PR_DEPTH = PT.PT_LONG | 0x3005 << 16,
+ PR_PROVIDER_DISPLAY = PT.PT_TSTRING | 0x3006 << 16,
+ PR_PROVIDER_DISPLAY_W = PT.PT_UNICODE | 0x3006 << 16,
+ PR_PROVIDER_DISPLAY_A = PT.PT_STRING8 | 0x3006 << 16,
+ PR_CREATION_TIME = PT.PT_SYSTIME | 0x3007 << 16,
+ PR_LAST_MODIFICATION_TIME = PT.PT_SYSTIME | 0x3008 << 16,
+ PR_RESOURCE_FLAGS = PT.PT_LONG | 0x3009 << 16,
+ PR_PROVIDER_DLL_NAME = PT.PT_TSTRING | 0x300A << 16,
+ PR_PROVIDER_DLL_NAME_W = PT.PT_UNICODE | 0x300A << 16,
+ PR_PROVIDER_DLL_NAME_A = PT.PT_STRING8 | 0x300A << 16,
+ PR_SEARCH_KEY = PT.PT_BINARY | 0x300B << 16,
+ PR_PROVIDER_UID = PT.PT_BINARY | 0x300C << 16,
+ PR_PROVIDER_ORDINAL = PT.PT_LONG | 0x300D << 16,
+
+ // Message store specific
+ PR_DEFAULT_STORE = PT.PT_BOOLEAN | 0x3400 << 16,
+ PR_STORE_SUPPORT_MASK = PT.PT_LONG | 0x340D << 16,
+ PR_STORE_STATE = PT.PT_LONG | 0x340E << 16,
+
+ PR_IPM_SUBTREE_SEARCH_KEY = PT.PT_BINARY | 0x3410 << 16,
+ PR_IPM_OUTBOX_SEARCH_KEY = PT.PT_BINARY | 0x3411 << 16,
+ PR_IPM_WASTEBASKET_SEARCH_KEY = PT.PT_BINARY | 0x3412 << 16,
+ PR_IPM_SENTMAIL_SEARCH_KEY = PT.PT_BINARY | 0x3413 << 16,
+ PR_MDB_PROVIDER = PT.PT_BINARY | 0x3414 << 16,
+ PR_RECEIVE_FOLDER_SETTINGS = PT.PT_OBJECT | 0x3415 << 16,
+
+ PR_VALID_FOLDER_MASK = PT.PT_LONG | 0x35DF << 16,
+ PR_IPM_SUBTREE_ENTRYID = PT.PT_BINARY | 0x35E0 << 16,
+
+ PR_IPM_OUTBOX_ENTRYID = PT.PT_BINARY | 0x35E2 << 16,
+ PR_IPM_WASTEBASKET_ENTRYID = PT.PT_BINARY | 0x35E3 << 16,
+ PR_IPM_SENTMAIL_ENTRYID = PT.PT_BINARY | 0x35E4 << 16,
+ PR_VIEWS_ENTRYID = PT.PT_BINARY | 0x35E5 << 16,
+ PR_COMMON_VIEWS_ENTRYID = PT.PT_BINARY | 0x35E6 << 16,
+ PR_FINDER_ENTRYID = PT.PT_BINARY | 0x35E7 << 16,
+ PR_ATTACH_CONTENT_ID = PT.PT_TSTRING | (0x3712 << 16),
+ PR_ATTACH_CONTENT_ID_A = PT.PT_STRING8 | (0x3712 << 16),
+ PR_ATTACH_CONTENT_ID_W = PT.PT_TSTRING | (0x3712 << 16),
+ PR_ATTACH_CONTENT_LOCATION = PT.PT_TSTRING | (0x3713 << 16),
+ PR_ATTACH_CONTENT_LOCATION_A = PT.PT_STRING8 | (0x3713 << 16),
+ PR_ATTACH_CONTENT_LOCATION_W = PT.PT_TSTRING | (0x3713 << 16),
+
+ // Message non-transmittable properties
+ PR_CURRENT_VERSION = PT.PT_I8 | 0x0E00 << 16,
+ PR_DELETE_AFTER_SUBMIT = PT.PT_BOOLEAN | 0x0E01 << 16,
+ PR_DISPLAY_BCC = PT.PT_TSTRING | 0x0E02 << 16,
+ PR_DISPLAY_BCC_W = PT.PT_UNICODE | 0x0E02 << 16,
+ PR_DISPLAY_BCC_A = PT.PT_STRING8 | 0x0E02 << 16,
+ PR_DISPLAY_CC = PT.PT_TSTRING | 0x0E03 << 16,
+ PR_DISPLAY_CC_W = PT.PT_UNICODE | 0x0E03 << 16,
+ PR_DISPLAY_CC_A = PT.PT_STRING8 | 0x0E03 << 16,
+ PR_DISPLAY_TO = PT.PT_TSTRING | 0x0E04 << 16,
+ PR_DISPLAY_TO_W = PT.PT_UNICODE | 0x0E04 << 16,
+ PR_DISPLAY_TO_A = PT.PT_STRING8 | 0x0E04 << 16,
+ PR_PARENT_DISPLAY = PT.PT_TSTRING | 0x0E05 << 16,
+ PR_PARENT_DISPLAY_W = PT.PT_UNICODE | 0x0E05 << 16,
+ PR_PARENT_DISPLAY_A = PT.PT_STRING8 | 0x0E05 << 16,
+ PR_MESSAGE_DELIVERY_TIME = PT.PT_SYSTIME | 0x0E06 << 16,
+ PR_MESSAGE_FLAGS = PT.PT_LONG | 0x0E07 << 16,
+ PR_MESSAGE_SIZE = PT.PT_LONG | 0x0E08 << 16,
+ PR_PARENT_ENTRYID = PT.PT_BINARY | 0x0E09 << 16,
+ PR_SENTMAIL_ENTRYID = PT.PT_BINARY | 0x0E0A << 16,
+ PR_CORRELATE = PT.PT_BOOLEAN | 0x0E0C << 16,
+ PR_CORRELATE_MTSID = PT.PT_BINARY | 0x0E0D << 16,
+ PR_DISCRETE_VALUES = PT.PT_BOOLEAN | 0x0E0E << 16,
+ PR_RESPONSIBILITY = PT.PT_BOOLEAN | 0x0E0F << 16,
+ PR_SPOOLER_STATUS = PT.PT_LONG | 0x0E10 << 16,
+ PR_TRANSPORT_STATUS = PT.PT_LONG | 0x0E11 << 16,
+ PR_MESSAGE_RECIPIENTS = PT.PT_OBJECT | 0x0E12 << 16,
+ PR_MESSAGE_ATTACHMENTS = PT.PT_OBJECT | 0x0E13 << 16,
+ PR_SUBMIT_FLAGS = PT.PT_LONG | 0x0E14 << 16,
+ PR_RECIPIENT_STATUS = PT.PT_LONG | 0x0E15 << 16,
+ PR_TRANSPORT_KEY = PT.PT_LONG | 0x0E16 << 16,
+ PR_MSG_STATUS = PT.PT_LONG | 0x0E17 << 16,
+ PR_MESSAGE_DOWNLOAD_TIME = PT.PT_LONG | 0x0E18 << 16,
+ PR_CREATION_VERSION = PT.PT_I8 | 0x0E19 << 16,
+ PR_MODIFY_VERSION = PT.PT_I8 | 0x0E1A << 16,
+ PR_HASATTACH = PT.PT_BOOLEAN | 0x0E1B << 16,
+ PR_BODY_CRC = PT.PT_LONG | 0x0E1C << 16,
+ PR_NORMALIZED_SUBJECT = PT.PT_TSTRING | 0x0E1D << 16,
+ PR_NORMALIZED_SUBJECT_W = PT.PT_UNICODE | 0x0E1D << 16,
+ PR_NORMALIZED_SUBJECT_A = PT.PT_STRING8 | 0x0E1D << 16,
+ PR_RTF_IN_SYNC = PT.PT_BOOLEAN | 0x0E1F << 16,
+ PR_ATTACH_SIZE = PT.PT_LONG | 0x0E20 << 16,
+ PR_ATTACH_NUM = PT.PT_LONG | 0x0E21 << 16,
+ PR_PREPROCESS = PT.PT_BOOLEAN | 0x0E22 << 16,
+
+ // Message recipient properties
+ PR_CONTENT_INTEGRITY_CHECK = PT.PT_BINARY | 0x0C00 << 16,
+ PR_EXPLICIT_CONVERSION = PT.PT_LONG | 0x0C01 << 16,
+ PR_IPM_RETURN_REQUESTED = PT.PT_BOOLEAN | 0x0C02 << 16,
+ PR_MESSAGE_TOKEN = PT.PT_BINARY | 0x0C03 << 16,
+ PR_NDR_REASON_CODE = PT.PT_LONG | 0x0C04 << 16,
+ PR_NDR_DIAG_CODE = PT.PT_LONG | 0x0C05 << 16,
+ PR_NON_RECEIPT_NOTIFICATION_REQUESTED = PT.PT_BOOLEAN | 0x0C06 << 16,
+ PR_DELIVERY_POINT = PT.PT_LONG | 0x0C07 << 16,
+
+ PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED = PT.PT_BOOLEAN | 0x0C08 << 16,
+ PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT = PT.PT_BINARY | 0x0C09 << 16,
+ PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY = PT.PT_BOOLEAN | 0x0C0A << 16,
+ PR_PHYSICAL_DELIVERY_MODE = PT.PT_LONG | 0x0C0B << 16,
+ PR_PHYSICAL_DELIVERY_REPORT_REQUEST = PT.PT_LONG | 0x0C0C << 16,
+ PR_PHYSICAL_FORWARDING_ADDRESS = PT.PT_BINARY | 0x0C0D << 16,
+ PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED = PT.PT_BOOLEAN | 0x0C0E << 16,
+ PR_PHYSICAL_FORWARDING_PROHIBITED = PT.PT_BOOLEAN | 0x0C0F << 16,
+ PR_PHYSICAL_RENDITION_ATTRIBUTES = PT.PT_BINARY | 0x0C10 << 16,
+ PR_PROOF_OF_DELIVERY = PT.PT_BINARY | 0x0C11 << 16,
+ PR_PROOF_OF_DELIVERY_REQUESTED = PT.PT_BOOLEAN | 0x0C12 << 16,
+ PR_RECIPIENT_CERTIFICATE = PT.PT_BINARY | 0x0C13 << 16,
+ PR_RECIPIENT_NUMBER_FOR_ADVICE = PT.PT_TSTRING | 0x0C14 << 16,
+ PR_RECIPIENT_NUMBER_FOR_ADVICE_W = PT.PT_UNICODE | 0x0C14 << 16,
+ PR_RECIPIENT_NUMBER_FOR_ADVICE_A = PT.PT_STRING8 | 0x0C14 << 16,
+ PR_RECIPIENT_TYPE = PT.PT_LONG | 0x0C15 << 16,
+ PR_REGISTERED_MAIL_TYPE = PT.PT_LONG | 0x0C16 << 16,
+ PR_REPLY_REQUESTED = PT.PT_BOOLEAN | 0x0C17 << 16,
+ //PR_REQUESTED_DELIVERY_METHOD = PT.PT_LONG | 0x0C18 << 16,
+ PR_SENDER_ENTRYID = PT.PT_BINARY | 0x0C19 << 16,
+ PR_SENDER_NAME = PT.PT_TSTRING | 0x0C1A << 16,
+ PR_SENDER_NAME_W = PT.PT_UNICODE | 0x0C1A << 16,
+ PR_SENDER_NAME_A = PT.PT_STRING8 | 0x0C1A << 16,
+ PR_SUPPLEMENTARY_INFO = PT.PT_TSTRING | 0x0C1B << 16,
+ PR_SUPPLEMENTARY_INFO_W = PT.PT_UNICODE | 0x0C1B << 16,
+ PR_SUPPLEMENTARY_INFO_A = PT.PT_STRING8 | 0x0C1B << 16,
+ PR_TYPE_OF_MTS_USER = PT.PT_LONG | 0x0C1C << 16,
+ PR_SENDER_SEARCH_KEY = PT.PT_BINARY | 0x0C1D << 16,
+ PR_SENDER_ADDRTYPE = PT.PT_TSTRING | 0x0C1E << 16,
+ PR_SENDER_ADDRTYPE_W = PT.PT_UNICODE | 0x0C1E << 16,
+ PR_SENDER_ADDRTYPE_A = PT.PT_STRING8 | 0x0C1E << 16,
+ PR_SENDER_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0C1F << 16,
+ PR_SENDER_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0C1F << 16,
+ PR_SENDER_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0C1F << 16,
+
+ // Message envelope properties
+ PR_ACKNOWLEDGEMENT_MODE = PT.PT_LONG | 0x0001 << 16,
+ PR_ALTERNATE_RECIPIENT_ALLOWED = PT.PT_BOOLEAN | 0x0002 << 16,
+ PR_AUTHORIZING_USERS = PT.PT_BINARY | 0x0003 << 16,
+ PR_AUTO_FORWARD_COMMENT = PT.PT_TSTRING | 0x0004 << 16,
+ PR_AUTO_FORWARD_COMMENT_W = PT.PT_UNICODE | 0x0004 << 16,
+ PR_AUTO_FORWARD_COMMENT_A = PT.PT_STRING8 | 0x0004 << 16,
+ PR_AUTO_FORWARDED = PT.PT_BOOLEAN | 0x0005 << 16,
+ PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID = PT.PT_BINARY | 0x0006 << 16,
+ PR_CONTENT_CORRELATOR = PT.PT_BINARY | 0x0007 << 16,
+ PR_CONTENT_IDENTIFIER = PT.PT_TSTRING | 0x0008 << 16,
+ PR_CONTENT_IDENTIFIER_W = PT.PT_UNICODE | 0x0008 << 16,
+ PR_CONTENT_IDENTIFIER_A = PT.PT_STRING8 | 0x0008 << 16,
+ PR_CONTENT_LENGTH = PT.PT_LONG | 0x0009 << 16,
+ PR_CONTENT_RETURN_REQUESTED = PT.PT_BOOLEAN | 0x000A << 16,
+
+ // Message envelope properties
+ PR_CONVERSATION_KEY = PT.PT_BINARY | 0x000B << 16,
+
+ PR_CONVERSION_EITS = PT.PT_BINARY | 0x000C << 16,
+ PR_CONVERSION_WITH_LOSS_PROHIBITED = PT.PT_BOOLEAN | 0x000D << 16,
+ PR_CONVERTED_EITS = PT.PT_BINARY | 0x000E << 16,
+ PR_DEFERRED_DELIVERY_TIME = PT.PT_SYSTIME | 0x000F << 16,
+ PR_DELIVER_TIME = PT.PT_SYSTIME | 0x0010 << 16,
+ PR_DISCARD_REASON = PT.PT_LONG | 0x0011 << 16,
+ PR_DISCLOSURE_OF_RECIPIENTS = PT.PT_BOOLEAN | 0x0012 << 16,
+ PR_DL_EXPANSION_HISTORY = PT.PT_BINARY | 0x0013 << 16,
+ PR_DL_EXPANSION_PROHIBITED = PT.PT_BOOLEAN | 0x0014 << 16,
+ PR_EXPIRY_TIME = PT.PT_SYSTIME | 0x0015 << 16,
+ PR_IMPLICIT_CONVERSION_PROHIBITED = PT.PT_BOOLEAN | 0x0016 << 16,
+ PR_IMPORTANCE = PT.PT_LONG | 0x0017 << 16,
+ PR_IPM_ID = PT.PT_BINARY | 0x0018 << 16,
+ PR_LATEST_DELIVERY_TIME = PT.PT_SYSTIME | 0x0019 << 16,
+ PR_MESSAGE_CLASS = PT.PT_TSTRING | 0x001A << 16,
+ PR_MESSAGE_CLASS_W = PT.PT_UNICODE | 0x001A << 16,
+ PR_MESSAGE_CLASS_A = PT.PT_STRING8 | 0x001A << 16,
+ PR_MESSAGE_DELIVERY_ID = PT.PT_BINARY | 0x001B << 16,
+
+ PR_MESSAGE_SECURITY_LABEL = PT.PT_BINARY | 0x001E << 16,
+ PR_OBSOLETED_IPMS = PT.PT_BINARY | 0x001F << 16,
+ PR_ORIGINALLY_INTENDED_RECIPIENT_NAME = PT.PT_BINARY | 0x0020 << 16,
+ PR_ORIGINAL_EITS = PT.PT_BINARY | 0x0021 << 16,
+ PR_ORIGINATOR_CERTIFICATE = PT.PT_BINARY | 0x0022 << 16,
+ PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED = PT.PT_BOOLEAN | 0x0023 << 16,
+ PR_ORIGINATOR_RETURN_ADDRESS = PT.PT_BINARY | 0x0024 << 16,
+
+ PR_PARENT_KEY = PT.PT_BINARY | 0x0025 << 16,
+ PR_PRIORITY = PT.PT_LONG | 0x0026 << 16,
+
+ PR_ORIGIN_CHECK = PT.PT_BINARY | 0x0027 << 16,
+ PR_PROOF_OF_SUBMISSION_REQUESTED = PT.PT_BOOLEAN | 0x0028 << 16,
+ PR_READ_RECEIPT_REQUESTED = PT.PT_BOOLEAN | 0x0029 << 16,
+ PR_RECEIPT_TIME = PT.PT_SYSTIME | 0x002A << 16,
+ PR_RECIPIENT_REASSIGNMENT_PROHIBITED = PT.PT_BOOLEAN | 0x002B << 16,
+ PR_REDIRECTION_HISTORY = PT.PT_BINARY | 0x002C << 16,
+ PR_RELATED_IPMS = PT.PT_BINARY | 0x002D << 16,
+ PR_ORIGINAL_SENSITIVITY = PT.PT_LONG | 0x002E << 16,
+ PR_LANGUAGES = PT.PT_TSTRING | 0x002F << 16,
+ PR_LANGUAGES_W = PT.PT_UNICODE | 0x002F << 16,
+ PR_LANGUAGES_A = PT.PT_STRING8 | 0x002F << 16,
+ PR_REPLY_TIME = PT.PT_SYSTIME | 0x0030 << 16,
+ PR_REPORT_TAG = PT.PT_BINARY | 0x0031 << 16,
+ PR_REPORT_TIME = PT.PT_SYSTIME | 0x0032 << 16,
+ PR_RETURNED_IPM = PT.PT_BOOLEAN | 0x0033 << 16,
+ PR_SECURITY = PT.PT_LONG | 0x0034 << 16,
+ PR_INCOMPLETE_COPY = PT.PT_BOOLEAN | 0x0035 << 16,
+ PR_SENSITIVITY = PT.PT_LONG | 0x0036 << 16,
+ PR_SUBJECT = PT.PT_TSTRING | 0x0037 << 16,
+ PR_SUBJECT_W = PT.PT_UNICODE | 0x0037 << 16,
+ PR_SUBJECT_A = PT.PT_STRING8 | 0x0037 << 16,
+ PR_SUBJECT_IPM = PT.PT_BINARY | 0x0038 << 16,
+ PR_CLIENT_SUBMIT_TIME = PT.PT_SYSTIME | 0x0039 << 16,
+ PR_REPORT_NAME = PT.PT_TSTRING | 0x003A << 16,
+ PR_REPORT_NAME_W = PT.PT_UNICODE | 0x003A << 16,
+ PR_REPORT_NAME_A = PT.PT_STRING8 | 0x003A << 16,
+ PR_SENT_REPRESENTING_SEARCH_KEY = PT.PT_BINARY | 0x003B << 16,
+ PR_X400_CONTENT_TYPE = PT.PT_BINARY | 0x003C << 16,
+ PR_SUBJECT_PREFIX = PT.PT_TSTRING | 0x003D << 16,
+ PR_SUBJECT_PREFIX_W = PT.PT_UNICODE | 0x003D << 16,
+ PR_SUBJECT_PREFIX_A = PT.PT_STRING8 | 0x003D << 16,
+ PR_NON_RECEIPT_REASON = PT.PT_LONG | 0x003E << 16,
+ PR_RECEIVED_BY_ENTRYID = PT.PT_BINARY | 0x003F << 16,
+ PR_RECEIVED_BY_NAME = PT.PT_TSTRING | 0x0040 << 16,
+ PR_RECEIVED_BY_NAME_W = PT.PT_UNICODE | 0x0040 << 16,
+ PR_RECEIVED_BY_NAME_A = PT.PT_STRING8 | 0x0040 << 16,
+ PR_SENT_REPRESENTING_ENTRYID = PT.PT_BINARY | 0x0041 << 16,
+ PR_SENT_REPRESENTING_NAME = PT.PT_TSTRING | 0x0042 << 16,
+ PR_SENT_REPRESENTING_NAME_W = PT.PT_UNICODE | 0x0042 << 16,
+ PR_SENT_REPRESENTING_NAME_A = PT.PT_STRING8 | 0x0042 << 16,
+ PR_RCVD_REPRESENTING_ENTRYID = PT.PT_BINARY | 0x0043 << 16,
+ PR_RCVD_REPRESENTING_NAME = PT.PT_TSTRING | 0x0044 << 16,
+ PR_RCVD_REPRESENTING_NAME_W = PT.PT_UNICODE | 0x0044 << 16,
+ PR_RCVD_REPRESENTING_NAME_A = PT.PT_STRING8 | 0x0044 << 16,
+ PR_REPORT_ENTRYID = PT.PT_BINARY | 0x0045 << 16,
+ PR_READ_RECEIPT_ENTRYID = PT.PT_BINARY | 0x0046 << 16,
+ PR_MESSAGE_SUBMISSION_ID = PT.PT_BINARY | 0x0047 << 16,
+ PR_PROVIDER_SUBMIT_TIME = PT.PT_SYSTIME | 0x0048 << 16,
+ PR_ORIGINAL_SUBJECT = PT.PT_TSTRING | 0x0049 << 16,
+ PR_ORIGINAL_SUBJECT_W = PT.PT_UNICODE | 0x0049 << 16,
+ PR_ORIGINAL_SUBJECT_A = PT.PT_STRING8 | 0x0049 << 16,
+ PR_DISC_VAL = PT.PT_BOOLEAN | 0x004A << 16,
+ PR_ORIG_MESSAGE_CLASS = PT.PT_TSTRING | 0x004B << 16,
+ PR_ORIG_MESSAGE_CLASS_W = PT.PT_UNICODE | 0x004B << 16,
+ PR_ORIG_MESSAGE_CLASS_A = PT.PT_STRING8 | 0x004B << 16,
+ PR_ORIGINAL_AUTHOR_ENTRYID = PT.PT_BINARY | 0x004C << 16,
+ PR_ORIGINAL_AUTHOR_NAME = PT.PT_TSTRING | 0x004D << 16,
+ PR_ORIGINAL_AUTHOR_NAME_W = PT.PT_UNICODE | 0x004D << 16,
+ PR_ORIGINAL_AUTHOR_NAME_A = PT.PT_STRING8 | 0x004D << 16,
+ PR_ORIGINAL_SUBMIT_TIME = PT.PT_SYSTIME | 0x004E << 16,
+ PR_REPLY_RECIPIENT_ENTRIES = PT.PT_BINARY | 0x004F << 16,
+ PR_REPLY_RECIPIENT_NAMES = PT.PT_TSTRING | 0x0050 << 16,
+ PR_REPLY_RECIPIENT_NAMES_W = PT.PT_UNICODE | 0x0050 << 16,
+ PR_REPLY_RECIPIENT_NAMES_A = PT.PT_STRING8 | 0x0050 << 16,
+
+ PR_RECEIVED_BY_SEARCH_KEY = PT.PT_BINARY | 0x0051 << 16,
+ PR_RCVD_REPRESENTING_SEARCH_KEY = PT.PT_BINARY | 0x0052 << 16,
+ PR_READ_RECEIPT_SEARCH_KEY = PT.PT_BINARY | 0x0053 << 16,
+ PR_REPORT_SEARCH_KEY = PT.PT_BINARY | 0x0054 << 16,
+ PR_ORIGINAL_DELIVERY_TIME = PT.PT_SYSTIME | 0x0055 << 16,
+ PR_ORIGINAL_AUTHOR_SEARCH_KEY = PT.PT_BINARY | 0x0056 << 16,
+
+ PR_MESSAGE_TO_ME = PT.PT_BOOLEAN | 0x0057 << 16,
+ PR_MESSAGE_CC_ME = PT.PT_BOOLEAN | 0x0058 << 16,
+ PR_MESSAGE_RECIP_ME = PT.PT_BOOLEAN | 0x0059 << 16,
+
+ PR_ORIGINAL_SENDER_NAME = PT.PT_TSTRING | 0x005A << 16,
+ PR_ORIGINAL_SENDER_NAME_W = PT.PT_UNICODE | 0x005A << 16,
+ PR_ORIGINAL_SENDER_NAME_A = PT.PT_STRING8 | 0x005A << 16,
+ PR_ORIGINAL_SENDER_ENTRYID = PT.PT_BINARY | 0x005B << 16,
+ PR_ORIGINAL_SENDER_SEARCH_KEY = PT.PT_BINARY | 0x005C << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_NAME = PT.PT_TSTRING | 0x005D << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_NAME_W = PT.PT_UNICODE | 0x005D << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_NAME_A = PT.PT_STRING8 | 0x005D << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_ENTRYID = PT.PT_BINARY | 0x005E << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY = PT.PT_BINARY | 0x005F << 16,
+
+ PR_START_DATE = PT.PT_SYSTIME | 0x0060 << 16,
+ PR_END_DATE = PT.PT_SYSTIME | 0x0061 << 16,
+ PR_OWNER_APPT_ID = PT.PT_LONG | 0x0062 << 16,
+ //PR_RESPONSE_REQUESTED = PT.PT_BOOLEAN | 0x0063 << 16,
+
+ PR_SENT_REPRESENTING_ADDRTYPE = PT.PT_TSTRING | 0x0064 << 16,
+ PR_SENT_REPRESENTING_ADDRTYPE_W = PT.PT_UNICODE | 0x0064 << 16,
+ PR_SENT_REPRESENTING_ADDRTYPE_A = PT.PT_STRING8 | 0x0064 << 16,
+ PR_SENT_REPRESENTING_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0065 << 16,
+ PR_SENT_REPRESENTING_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0065 << 16,
+ PR_SENT_REPRESENTING_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0065 << 16,
+
+ PR_ORIGINAL_SENDER_ADDRTYPE = PT.PT_TSTRING | 0x0066 << 16,
+ PR_ORIGINAL_SENDER_ADDRTYPE_W = PT.PT_UNICODE | 0x0066 << 16,
+ PR_ORIGINAL_SENDER_ADDRTYPE_A = PT.PT_STRING8 | 0x0066 << 16,
+ PR_ORIGINAL_SENDER_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0067 << 16,
+ PR_ORIGINAL_SENDER_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0067 << 16,
+ PR_ORIGINAL_SENDER_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0067 << 16,
+
+ PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE = PT.PT_TSTRING | 0x0068 << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE_W = PT.PT_UNICODE | 0x0068 << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE_A = PT.PT_STRING8 | 0x0068 << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0069 << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0069 << 16,
+ PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0069 << 16,
+
+ PR_CONVERSATION_TOPIC = PT.PT_TSTRING | 0x0070 << 16,
+ PR_CONVERSATION_TOPIC_W = PT.PT_UNICODE | 0x0070 << 16,
+ PR_CONVERSATION_TOPIC_A = PT.PT_STRING8 | 0x0070 << 16,
+ PR_CONVERSATION_INDEX = PT.PT_BINARY | 0x0071 << 16,
+
+ PR_ORIGINAL_DISPLAY_BCC = PT.PT_TSTRING | 0x0072 << 16,
+ PR_ORIGINAL_DISPLAY_BCC_W = PT.PT_UNICODE | 0x0072 << 16,
+ PR_ORIGINAL_DISPLAY_BCC_A = PT.PT_STRING8 | 0x0072 << 16,
+ PR_ORIGINAL_DISPLAY_CC = PT.PT_TSTRING | 0x0073 << 16,
+ PR_ORIGINAL_DISPLAY_CC_W = PT.PT_UNICODE | 0x0073 << 16,
+ PR_ORIGINAL_DISPLAY_CC_A = PT.PT_STRING8 | 0x0073 << 16,
+ PR_ORIGINAL_DISPLAY_TO = PT.PT_TSTRING | 0x0074 << 16,
+ PR_ORIGINAL_DISPLAY_TO_W = PT.PT_UNICODE | 0x0074 << 16,
+ PR_ORIGINAL_DISPLAY_TO_A = PT.PT_STRING8 | 0x0074 << 16,
+
+ PR_RECEIVED_BY_ADDRTYPE = PT.PT_TSTRING | 0x0075 << 16,
+ PR_RECEIVED_BY_ADDRTYPE_W = PT.PT_UNICODE | 0x0075 << 16,
+ PR_RECEIVED_BY_ADDRTYPE_A = PT.PT_STRING8 | 0x0075 << 16,
+ PR_RECEIVED_BY_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0076 << 16,
+ PR_RECEIVED_BY_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0076 << 16,
+ PR_RECEIVED_BY_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0076 << 16,
+
+ PR_RCVD_REPRESENTING_ADDRTYPE = PT.PT_TSTRING | 0x0077 << 16,
+ PR_RCVD_REPRESENTING_ADDRTYPE_W = PT.PT_UNICODE | 0x0077 << 16,
+ PR_RCVD_REPRESENTING_ADDRTYPE_A = PT.PT_STRING8 | 0x0077 << 16,
+ PR_RCVD_REPRESENTING_EMAIL_ADDRESS = PT.PT_TSTRING | 0x0078 << 16,
+ PR_RCVD_REPRESENTING_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x0078 << 16,
+ PR_RCVD_REPRESENTING_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x0078 << 16,
+
+ PR_ORIGINAL_AUTHOR_ADDRTYPE = PT.PT_TSTRING | 0x0079 << 16,
+ PR_ORIGINAL_AUTHOR_ADDRTYPE_W = PT.PT_UNICODE | 0x0079 << 16,
+ PR_ORIGINAL_AUTHOR_ADDRTYPE_A = PT.PT_STRING8 | 0x0079 << 16,
+ PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS = PT.PT_TSTRING | 0x007A << 16,
+ PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x007A << 16,
+ PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x007A << 16,
+
+ PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE = PT.PT_TSTRING | 0x007B << 16,
+ PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE_W = PT.PT_UNICODE | 0x007B << 16,
+ PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE_A = PT.PT_STRING8 | 0x007B << 16,
+ PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS = PT.PT_TSTRING | 0x007C << 16,
+ PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS_W = PT.PT_UNICODE | 0x007C << 16,
+ PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS_A = PT.PT_STRING8 | 0x007C << 16,
+
+ PR_TRANSPORT_MESSAGE_HEADERS = PT.PT_TSTRING | 0x007D << 16,
+ PR_TRANSPORT_MESSAGE_HEADERS_W = PT.PT_UNICODE | 0x007D << 16,
+ PR_TRANSPORT_MESSAGE_HEADERS_A = PT.PT_STRING8 | 0x007D << 16,
+
+ PR_DELEGATION = PT.PT_BINARY | 0x007E << 16,
+
+ PR_TNEF_CORRELATION_KEY = PT.PT_BINARY | 0x007F << 16,
+
+ // Message content properties
+ PR_BODY = PT.PT_TSTRING | 0x1000 << 16,
+ PR_BODY_W = PT.PT_UNICODE | 0x1000 << 16,
+ PR_BODY_A = PT.PT_STRING8 | 0x1000 << 16,
+ PR_REPORT_TEXT = PT.PT_TSTRING | 0x1001 << 16,
+ PR_REPORT_TEXT_W = PT.PT_UNICODE | 0x1001 << 16,
+ PR_REPORT_TEXT_A = PT.PT_STRING8 | 0x1001 << 16,
+ PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY = PT.PT_BINARY | 0x1002 << 16,
+ PR_REPORTING_DL_NAME = PT.PT_BINARY | 0x1003 << 16,
+ PR_REPORTING_MTA_CERTIFICATE = PT.PT_BINARY | 0x1004 << 16,
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+ public class OutlookUtils {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OutlookUtils));
+ private const uint KEEP_OPEN_READONLY = 0x00000001;
+ private const uint KEEP_OPEN_READWRITE = 0x00000002;
+ private const uint FORCE_SAVE = 0x00000004;
+
+ #region MAPI Interface ID'S
+ // The Interface ID's are used to retrieve the specific MAPI Interfaces from the IUnknown Object
+ public const string IID_IMAPISession = "00020300-0000-0000-C000-000000000046";
+ public const string IID_IMAPIProp = "00020303-0000-0000-C000-000000000046";
+ public const string IID_IMAPITable = "00020301-0000-0000-C000-000000000046";
+ public const string IID_IMAPIMsgStore = "00020306-0000-0000-C000-000000000046";
+ public const string IID_IMAPIFolder = "0002030C-0000-0000-C000-000000000046";
+ public const string IID_IMAPISpoolerService = "0002031E-0000-0000-C000-000000000046";
+ public const string IID_IMAPIStatus = "0002031E-0000-0000-C000-000000000046";
+ public const string IID_IMessage = "00020307-0000-0000-C000-000000000046";
+ public const string IID_IAddrBook = "00020309-0000-0000-C000-000000000046";
+ public const string IID_IProfSect = "00020304-0000-0000-C000-000000000046";
+ public const string IID_IMAPIContainer = "0002030B-0000-0000-C000-000000000046";
+ public const string IID_IABContainer = "0002030D-0000-0000-C000-000000000046";
+ public const string IID_IMsgServiceAdmin = "0002031D-0000-0000-C000-000000000046";
+ public const string IID_IProfAdmin = "0002031C-0000-0000-C000-000000000046";
+ public const string IID_IMailUser = "0002030A-0000-0000-C000-000000000046";
+ public const string IID_IDistList = "0002030E-0000-0000-C000-000000000046";
+ public const string IID_IAttachment = "00020308-0000-0000-C000-000000000046";
+ public const string IID_IMAPIControl = "0002031B-0000-0000-C000-000000000046";
+ public const string IID_IMAPILogonRemote = "00020346-0000-0000-C000-000000000046";
+ public const string IID_IMAPIForm = "00020327-0000-0000-C000-000000000046";
+ #endregion
+
+ [ComVisible(false)]
+ [ComImport()]
+ [Guid(IID_IMAPIProp)]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface IMessage : IMAPIProp {
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetAttachmentTable();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int OpenAttach();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int CreateAttach();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int DeleteAttach();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetRecipientTable();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int ModifyRecipients();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int SubmitMessage();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int SetReadFlag();
+ }
+ // [ComVisible(false)]
+ // [ComImport()]
+ // [Guid(IID_IMAPIFolder)]
+ // [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ // interface IMAPIFolder : IMAPIContainer {
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int CreateMessage(IntPtr interf, uint uFlags, [MarshalAs(UnmanagedType.Interface)] ref IMessage pMsg);
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int CopyMessages();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int CreateFolder();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int CopyFolder();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int DeleteFolder();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int SetReadFlags();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int GetMessageStatus();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int SetMessageStatus();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int SaveContentsSort();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int EmptyFolder();
+ // }
+ // [ComVisible(false)]
+ // [ComImport()]
+ // [Guid(IID_IMAPIContainer)]
+ // [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ // interface IMAPIContainer : IMAPIProp {
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int GetContentsTable(uint uFlags, [MarshalAs(UnmanagedType.Interface), Out] out outlook.Table tbl);
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int GetHierarchyTable();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int OpenEntry();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int SetSearchCriteria();
+ // [return: MarshalAs(UnmanagedType.I4)]
+ // [PreserveSig]
+ // int GetSearchCriteria();
+ // }
+
+ [ComVisible(false)]
+ [ComImport()]
+ [Guid(IID_IMAPIProp)]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface IMAPIProp {
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetLastError();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int SaveChanges(
+ uint uFlags
+ );
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetProps();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetPropList();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int OpenProperty();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int SetProps(uint values, IntPtr propArray, IntPtr problems);
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int DeleteProps();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int CopyTo();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int CopyProps();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetNamesFromIDs();
+ [return: MarshalAs(UnmanagedType.I4)]
+ [PreserveSig]
+ int GetIDsFromNames();
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct SPropValue {
+ [FieldOffset(0)]
+ public uint propTag;
+ [FieldOffset(4)]
+ public readonly uint alignPad;
+ [FieldOffset(8)]
+ public IntPtr Value;
+ [FieldOffset(8)]
+ public readonly long filler;
+ }
+
+ ///
+ /// Tries to save the changes we just made
+ ///
+ ///
+ ///
+ public static bool SaveChanges(MailItem mailItem) {
+ // Pointer to IUnknown Interface
+ IntPtr IUnknown = IntPtr.Zero;
+ // Pointer to IMAPIProp Interface
+ IntPtr IMAPIProp = IntPtr.Zero;
+ // if we have no MAPIObject everything is senseless...
+ if (mailItem == null) {
+ return false;
+ }
+
+ try {
+ // We can pass NULL here as parameter, so we do it.
+ MAPIInitialize(IntPtr.Zero);
+ // retrive the IUnknon Interface from our MAPIObject comming from Outlook.
+ IUnknown = Marshal.GetIUnknownForObject(mailItem.MAPIOBJECT);
+
+ // create a Guid that we pass to retreive the IMAPIProp Interface.
+ Guid guidIMAPIProp = new Guid(IID_IMAPIProp);
+
+ // try to retrieve the IMAPIProp interface from IMessage Interface, everything else is sensless.
+ if (Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProp) != 0) {
+ return false;
+ }
+ IMAPIProp mapiProp = (IMAPIProp)Marshal.GetTypedObjectForIUnknown(IUnknown, typeof(IMAPIProp));
+ return (mapiProp.SaveChanges(KEEP_OPEN_READWRITE) == 0);
+ } catch (Exception ex) {
+ LOG.Error(ex);
+ return false;
+ } finally {
+ // cleanup all references to COM Objects
+ if (IMAPIProp != IntPtr.Zero) Marshal.Release(IMAPIProp);
+ //if (IMessage != IntPtr.Zero) Marshal.Release(IMessage);
+ if (IUnknown != IntPtr.Zero) Marshal.Release(IUnknown);
+ }
+ }
+
+ ///
+ /// Uses the IMAPIPROP.SetProps to set the content ID
+ ///
+ ///
+ ///
+ public static void SetContentID(IAttachment attachment, string contentId) {
+ // Pointer to IUnknown Interface
+ IntPtr IUnknown = IntPtr.Zero;
+ // Pointer to IMAPIProp Interface
+ IntPtr IMAPIProp = IntPtr.Zero;
+ // A pointer that points to the SPropValue structure
+ IntPtr ptrPropValue = IntPtr.Zero;
+ // Structure that will hold the Property Value
+ SPropValue propValue;
+ // if we have no MAPIObject everything is senseless...
+ if (attachment == null) {
+ return;
+ }
+
+ try {
+ // We can pass NULL here as parameter, so we do it.
+ MAPIInitialize(IntPtr.Zero);
+
+ // retrive the IUnknon Interface from our MAPIObject comming from Outlook.
+ IUnknown = Marshal.GetIUnknownForObject(attachment.MAPIOBJECT);
+ IMAPIProp mapiProp = (IMAPIProp)Marshal.GetTypedObjectForIUnknown(IUnknown, typeof(IMAPIProp));
+
+ // Create structure
+ propValue = new SPropValue();
+ propValue.propTag = (uint)PropTags.PR_ATTACH_CONTENT_ID;
+ //propValue.propTag = 0x3712001E;
+ // Create Ansi string
+ propValue.Value = Marshal.StringToHGlobalUni(contentId);
+
+ // Create unmanaged memory for structure
+ ptrPropValue = Marshal.AllocHGlobal(Marshal.SizeOf(propValue));
+ // Copy structure to unmanged memory
+ Marshal.StructureToPtr(propValue, ptrPropValue, false);
+ mapiProp.SetProps(1, ptrPropValue, IntPtr.Zero);
+
+ propValue.propTag = (uint)PropTags.PR_ATTACH_CONTENT_LOCATION;
+ // Copy structure to unmanged memory
+ Marshal.StructureToPtr(propValue, ptrPropValue, false);
+ mapiProp.SetProps(1, ptrPropValue, IntPtr.Zero);
+
+
+ // Free string
+ Marshal.FreeHGlobal(propValue.Value);
+ mapiProp.SaveChanges(KEEP_OPEN_READWRITE);
+ } catch (Exception ex) {
+ LOG.Error(ex);
+ } finally {
+ // Free used Memory structures
+ if (ptrPropValue != IntPtr.Zero) Marshal.FreeHGlobal(ptrPropValue);
+ // cleanup all references to COM Objects
+ if (IMAPIProp != IntPtr.Zero) Marshal.Release(IMAPIProp);
+ //if (IMessage != IntPtr.Zero) Marshal.Release(IMessage);
+ if (IUnknown != IntPtr.Zero) Marshal.Release(IUnknown);
+ }
+ }
+
+ ///
+ /// Use MAPI32.DLL "HrSetOneProp" from managed code
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool SetMAPIProperty(IAttachment attachment, PropTags proptag, string propertyValue) {
+ // Pointer to IUnknown Interface
+ IntPtr IUnknown = IntPtr.Zero;
+ // Pointer to IMAPIProp Interface
+ IntPtr IMAPIProp = IntPtr.Zero;
+ // Structure that will hold the Property Value
+ SPropValue propValue;
+ // A pointer that points to the SPropValue structure
+ IntPtr ptrPropValue = IntPtr.Zero;
+ object mapiObject = attachment.MAPIOBJECT;
+ // if we have no MAPIObject everything is senseless...
+ if (mapiObject == null) {
+ return false;
+ }
+
+ try {
+ // We can pass NULL here as parameter, so we do it.
+ MAPIInitialize(IntPtr.Zero);
+
+ // retrive the IUnknon Interface from our MAPIObject comming from Outlook.
+ IUnknown = Marshal.GetIUnknownForObject(mapiObject);
+
+ // create a Guid that we pass to retreive the IMAPIProp Interface.
+ Guid guidIMAPIProp = new Guid(IID_IMAPIProp);
+
+ // try to retrieve the IMAPIProp interface from IMessage Interface, everything else is sensless.
+ if (Marshal.QueryInterface(IUnknown, ref guidIMAPIProp, out IMAPIProp) != 0) {
+ return false;
+ }
+
+ // double check, if we wave no pointer, exit...
+ if (IMAPIProp == IntPtr.Zero) {
+ return false;
+ }
+
+ // Create structure
+ propValue = new SPropValue();
+ propValue.propTag = (uint)proptag;
+ // Create Ansi string
+ propValue.Value = Marshal.StringToHGlobalUni(propertyValue);
+
+ // Create unmanaged memory for structure
+ ptrPropValue = Marshal.AllocHGlobal(Marshal.SizeOf(propValue));
+ // Copy structure to unmanged memory
+ Marshal.StructureToPtr(propValue, ptrPropValue, false);
+
+ // Set the property
+ HrSetOneProp(IMAPIProp, ptrPropValue);
+
+ // Free string
+ Marshal.FreeHGlobal(propValue.Value);
+ IMAPIProp mapiProp = (IMAPIProp)Marshal.GetTypedObjectForIUnknown(IUnknown, typeof(IMAPIProp));
+ return mapiProp.SaveChanges(4) == 0;
+ } catch (Exception ex) {
+ LOG.Error(ex);
+ return false;
+ } finally {
+ // Free used Memory structures
+ if (ptrPropValue != IntPtr.Zero) Marshal.FreeHGlobal(ptrPropValue);
+ // cleanup all references to COM Objects
+ if (IMAPIProp != IntPtr.Zero) Marshal.Release(IMAPIProp);
+ //if (IMessage != IntPtr.Zero) Marshal.Release(IMessage);
+ if (IUnknown != IntPtr.Zero) Marshal.Release(IUnknown);
+ MAPIUninitialize();
+ }
+ }
+
+ #region MAPI DLL Imports
+ [DllImport("MAPI32.DLL", EntryPoint = "HrSetOneProp@8")]
+ private static extern void HrSetOneProp(IntPtr pmp, IntPtr pprop);
+
+ [DllImport("MAPI32.DLL")]
+ private static extern int MAPIInitialize(IntPtr lpMapiInit);
+
+ [DllImport("MAPI32.DLL")]
+ private static extern void MAPIUninitialize();
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOfficePlugin/OfficeInterop/PowerpointInterop.cs b/GreenshotOfficePlugin/OfficeInterop/PowerpointInterop.cs
new file mode 100644
index 000000000..be2aaa86a
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/PowerpointInterop.cs
@@ -0,0 +1,149 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Collections;
+
+namespace Greenshot.Interop.Office {
+ // See http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.application_members.aspx
+ [ComProgId("Powerpoint.Application")]
+ public interface IPowerpointApplication : ICommon {
+ IPresentation ActivePresentation { get; }
+ IPresentations Presentations { get; }
+ bool Visible { get; set; }
+ void Activate();
+ IPowerpointWindow ActiveWindow { get; }
+ string Version { get; }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.slides_members.aspx
+ public interface ISlides : ICommon {
+ int Count { get; }
+ ISlide Add(int Index, int layout);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.documentwindow.view.aspx
+ public interface IPowerpointWindow : ICommon {
+ void Activate();
+ IPowerpointView View { get; }
+ }
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.view_members.aspx
+ public interface IPowerpointView : ICommon {
+ IZoom Zoom { get; }
+ void GotoSlide(int index);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.presentation_members.aspx
+ public interface IPresentation : ICommon {
+ string Name { get; }
+ ISlides Slides { get; }
+ IPowerpointApplication Application { get; }
+ MsoTriState ReadOnly { get; }
+ bool Final { get; set; }
+ IPageSetup PageSetup { get; }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.presentations_members.aspx
+ public interface IPresentations : ICommon, ICollection {
+ IPresentation Add(MsoTriState WithWindow);
+ IPresentation item(int index);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.pagesetup_members.aspx
+ public interface IPageSetup : ICommon, ICollection {
+ float SlideWidth { get; set; }
+ float SlideHeight { get; set; }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.slide_members.aspx
+ public interface ISlide : ICommon {
+ IShapes Shapes { get; }
+ void Select();
+ int SlideNumber { get; }
+
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.shapes_members.aspx
+ public interface IShapes : ICommon, IEnumerable {
+ int Count { get; }
+ IShape item(int index);
+ IShape AddPicture(string FileName, MsoTriState LinkToFile, MsoTriState SaveWithDocument, float Left, float Top, float Width, float Height);
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint.shape_members.aspx
+ public interface IShape : ICommon {
+ float Left { get; set; }
+ float Top { get; set; }
+ float Width { get; set; }
+ float Height { get; set; }
+ ITextFrame TextFrame { get; }
+ void ScaleWidth(float Factor, MsoTriState RelativeToOriginalSize, MsoScaleFrom fScale);
+ void ScaleHeight(float Factor, MsoTriState RelativeToOriginalSize, MsoScaleFrom fScale);
+ string AlternativeText { get; set; }
+ MsoTriState LockAspectRatio { get; set; }
+ }
+
+ public interface ITextFrame : ICommon {
+ ITextRange TextRange { get; }
+ MsoTriState HasText { get; }
+ }
+ public interface ITextRange : ICommon {
+ string Text { get; set; }
+ }
+
+ public enum PPSlideLayout : int {
+ ppLayoutMixed = -2,
+ ppLayoutTitle = 1,
+ ppLayoutText = 2,
+ ppLayoutTwoColumnText = 3,
+ ppLayoutTable = 4,
+ ppLayoutTextAndChart = 5,
+ ppLayoutChartAndText = 6,
+ ppLayoutOrgchart = 7,
+ ppLayoutChart = 8,
+ ppLayoutTextAndClipart = 9,
+ ppLayoutClipartAndText = 10,
+ ppLayoutTitleOnly = 11,
+ ppLayoutBlank = 12,
+ ppLayoutTextAndObject = 13,
+ ppLayoutObjectAndText = 14,
+ ppLayoutLargeObject = 15,
+ ppLayoutObject = 16,
+ ppLayoutTextAndMediaClip = 17,
+ ppLayoutMediaClipAndText = 18,
+ ppLayoutObjectOverText = 19,
+ ppLayoutTextOverObject = 20,
+ ppLayoutTextAndTwoObjects = 21,
+ ppLayoutTwoObjectsAndText = 22,
+ ppLayoutTwoObjectsOverText = 23,
+ ppLayoutFourObjects = 24,
+ ppLayoutVerticalText = 25,
+ ppLayoutClipArtAndVerticalText = 26,
+ ppLayoutVerticalTitleAndText = 27,
+ ppLayoutVerticalTitleAndTextOverChart = 28,
+ ppLayoutTwoObjects = 29,
+ ppLayoutObjectAndTwoObjects = 30,
+ ppLayoutTwoObjectsAndObject = 31,
+ ppLayoutCustom = 32,
+ ppLayoutSectionHeader = 33,
+ ppLayoutComparison = 34,
+ ppLayoutContentWithCaption = 35,
+ ppLayoutPictureWithCaption = 36
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficeInterop/WordInterop.cs b/GreenshotOfficePlugin/OfficeInterop/WordInterop.cs
new file mode 100644
index 000000000..2a2f63420
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeInterop/WordInterop.cs
@@ -0,0 +1,132 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Greenshot.Interop.Office {
+ // See http://msdn.microsoft.com/de-de/library/microsoft.office.interop.word.applicationclass_members%28v=Office.11%29.aspx
+ [ComProgId("Word.Application")]
+ public interface IWordApplication : ICommon {
+ IWordDocument ActiveDocument { get; }
+ ISelection Selection { get; }
+ IDocuments Documents { get; }
+ bool Visible { get; set; }
+ void Activate();
+ string Version { get; }
+ }
+
+ // See: http://msdn.microsoft.com/de-de/library/microsoft.office.interop.word.documents_members(v=office.11).aspx
+ public interface IDocuments : ICommon, ICollection {
+ IWordDocument Add(ref object Template, ref object NewTemplate, ref object DocumentType, ref object Visible);
+ IWordDocument item(int index);
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.document%28v=office.14%29.aspx
+ ///
+ public interface IWordDocument : ICommon {
+ void Activate();
+ IWordApplication Application { get; }
+ IWordWindow ActiveWindow { get; }
+ bool ReadOnly { get; }
+ IHyperlinks Hyperlinks { get; }
+
+ // Only 2007 and later!
+ bool Final { get; set; }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.window_members.aspx
+ ///
+ public interface IWordWindow : ICommon {
+ IPane ActivePane { get; }
+ void Activate();
+ string Caption {
+ get;
+ }
+
+ ///
+ /// Returns an Integer (int in C#) that indicates the window handle of the specified window
+ ///
+ int Hwnd { get; }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.pane_members.aspx
+ ///
+ public interface IPane : ICommon {
+ IWordView View { get; }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.view_members.aspx
+ ///
+ public interface IWordView : ICommon {
+ IZoom Zoom { get; }
+ }
+
+ // See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.zoom_members.aspx
+ public interface IZoom : ICommon {
+ int Percentage { get; set; }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/de-de/library/microsoft.office.interop.word.selection_members(v=office.11).aspx
+ ///
+ public interface ISelection : ICommon {
+ IInlineShapes InlineShapes { get; }
+ void InsertAfter(string text);
+ int MoveDown(object Unit, object Count, object Extend);
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/ms263866%28v=office.14%29.aspx
+ ///
+ public interface IInlineShapes : ICommon {
+ IInlineShape AddPicture(string FileName, object LinkToFile, object SaveWithDocument, object Range);
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.inlineshape_members%28v=office.14%29.aspx
+ ///
+ public interface IInlineShape : ICommon {
+ IHyperlink Hyperlink { get; }
+ MsoTriState LockAspectRatio {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.hyperlink_members%28v=office.14%29.aspx
+ ///
+ public interface IHyperlink : ICommon {
+ string Address {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.hyperlinks%28v=office.14%29.aspx
+ ///
+ public interface IHyperlinks : ICommon, ICollection {
+ IHyperlink Add(object Anchor, object Address, object SubAddress, object ScreenTip, object TextToDisplay, object Target);
+ }
+}
diff --git a/GreenshotOfficePlugin/OfficePlugin.cs b/GreenshotOfficePlugin/OfficePlugin.cs
new file mode 100644
index 000000000..76f661367
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficePlugin.cs
@@ -0,0 +1,113 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using Greenshot.Plugin;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// This is the OfficePlugin base code
+ ///
+ public class OfficePlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OfficePlugin));
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing) {
+ // Do nothing
+ }
+
+ public IEnumerable Destinations() {
+ IDestination destination;
+ try {
+ destination = new ExcelDestination();
+ } catch {
+ destination = null;
+ }
+ if (destination != null) {
+ yield return destination;
+ }
+
+ try {
+ destination = new PowerpointDestination();
+ } catch {
+ destination = null;
+ }
+ if (destination != null) {
+ yield return destination;
+ }
+
+ try {
+ destination = new WordDestination();
+ } catch {
+ destination = null;
+ }
+ if (destination != null) {
+ yield return destination;
+ }
+
+ try {
+ destination = new OutlookDestination();
+ } catch {
+ destination = null;
+ }
+ if (destination != null) {
+ yield return destination;
+ }
+
+ try {
+ destination = new OneNoteDestination();
+ } catch {
+ destination = null;
+ }
+ if (destination != null) {
+ yield return destination;
+ }
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ /// true if plugin is initialized, false if not (doesn't show)
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ return true;
+ }
+
+ public virtual void Shutdown() {
+ LOG.Debug("Office Plugin shutdown.");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs b/GreenshotOfficePlugin/Properties/AssemblyInfo.cs
similarity index 58%
rename from src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs
rename to GreenshotOfficePlugin/Properties/AssemblyInfo.cs
index 6b14a40f5..034162b0e 100644
--- a/src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs
+++ b/GreenshotOfficePlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
+[assembly: AssemblyTitle("GreenshotOfficePlugin")]
[assembly: AssemblyDescription("A plugin to export images to Office applications")]
-[assembly: AssemblyPluginIdentifier("Office Plugin")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Office Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotOfficePlugin.OfficePlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
\ No newline at end of file
diff --git a/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs b/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs
new file mode 100644
index 000000000..49b237289
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs
@@ -0,0 +1,28 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// This class is needed for design-time resolving of the language files
+ ///
+ public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm {
+ }
+}
diff --git a/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs b/GreenshotPhotobucketPlugin/Forms/SettingsForm.Designer.cs
similarity index 79%
rename from src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs
rename to GreenshotPhotobucketPlugin/Forms/SettingsForm.Designer.cs
index 1fff9f5c3..93cab0688 100644
--- a/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs
+++ b/GreenshotPhotobucketPlugin/Forms/SettingsForm.Designer.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,12 +16,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.Photobucket.Forms {
+namespace GreenshotPhotobucketPlugin {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
@@ -49,11 +46,11 @@ namespace Greenshot.Plugin.Photobucket.Forms {
///
private void InitializeComponent()
{
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.checkbox_usepagelink = new GreenshotCheckBox();
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkbox_usepagelink = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.SuspendLayout();
//
// buttonOK
@@ -84,7 +81,7 @@ namespace Greenshot.Plugin.Photobucket.Forms {
this.combobox_uploadimageformat.FormattingEnabled = true;
this.combobox_uploadimageformat.Location = new System.Drawing.Point(102, 11);
this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(PhotobucketConfiguration.UploadFormat);
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
this.combobox_uploadimageformat.SectionName = "Photobucket";
this.combobox_uploadimageformat.Size = new System.Drawing.Size(276, 21);
this.combobox_uploadimageformat.TabIndex = 1;
@@ -99,10 +96,11 @@ namespace Greenshot.Plugin.Photobucket.Forms {
//
// checkbox_usepagelink
//
+ this.checkbox_usepagelink.AutoSize = true;
this.checkbox_usepagelink.LanguageKey = "photobucket.use_page_link";
this.checkbox_usepagelink.Location = new System.Drawing.Point(15, 43);
this.checkbox_usepagelink.Name = "checkbox_usepagelink";
- this.checkbox_usepagelink.PropertyName = nameof(PhotobucketConfiguration.UsePageLink);
+ this.checkbox_usepagelink.PropertyName = "UsePageLink";
this.checkbox_usepagelink.SectionName = "Photobucket";
this.checkbox_usepagelink.Size = new System.Drawing.Size(251, 17);
this.checkbox_usepagelink.TabIndex = 2;
@@ -127,10 +125,10 @@ namespace Greenshot.Plugin.Photobucket.Forms {
this.PerformLayout();
}
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotCheckBox checkbox_usepagelink;
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usepagelink;
}
}
diff --git a/GreenshotPhotobucketPlugin/Forms/SettingsForm.cs b/GreenshotPhotobucketPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..4fc578463
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,37 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : PhotobucketForm {
+ public SettingsForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ AcceptButton = buttonOK;
+ CancelButton = buttonCancel;
+ }
+ }
+}
diff --git a/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj
new file mode 100644
index 000000000..140a7d927
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj
@@ -0,0 +1,94 @@
+
+
+
+
+ {9C0ECC4C-7807-4111-916A-4F57BB29788A}
+ Library
+ GreenshotPhotobucketPlugin
+ GreenshotPhotobucketPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ OnBuildSuccess
+
+
+
+
+
+ 3.5
+
+
+
+
+ ..\Greenshot\Lib\log4net.dll
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+
+
+
+
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+
+ PhotobucketPlugin.cs
+ Designer
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+if exist "$(ProjectDir)PhotobucketCredentials.private.cs" (
+ rename "$(ProjectDir)PhotobucketCredentials.cs" "PhotobucketCredentials.orig.cs"
+ rename "$(ProjectDir)PhotobucketCredentials.private.cs" "PhotobucketCredentials.cs"
+)
+
+
+if exist "$(ProjectDir)PhotobucketCredentials.orig.cs" (
+ rename "$(ProjectDir)PhotobucketCredentials.cs" "PhotobucketCredentials.private.cs"
+ rename "$(ProjectDir)PhotobucketCredentials.orig.cs" "PhotobucketCredentials.cs"
+)
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+
\ No newline at end of file
diff --git a/GreenshotPhotobucketPlugin/LanguageKeys.cs b/GreenshotPhotobucketPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..d8c6e1a3d
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/LanguageKeys.cs
@@ -0,0 +1,34 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPhotobucketPlugin {
+ public enum LangKey {
+ upload_menu_item,
+ settings_title,
+ label_upload_format,
+ label_clear,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ use_page_link,
+ configure
+ }
+}
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-cs-CZ.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-cs-CZ.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-cs-CZ.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-cs-CZ.xml
index 09f5b572e..437fe1072 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-cs-CZ.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-cs-CZ.xml
@@ -1,15 +1,15 @@
-
-
-
- Zrušit
- Komunikace s Photobucket. Prosím čekejte ...
- Nastavení Photobucket
- Formát obrázku
- OK
- Nastavení Photobucket
- Při nahrávání na Photobucket došlo k chybě:
- Nahrát na Photobucket
- Odeslání obrázku na bylo Photobucket úspěšné!
- Použijte odkaz na stránku namísto odkaz na obrázek do schránky
-
+
+
+
+ Zrušit
+ Komunikace s Photobucket. Prosím čekejte ...
+ Nastavení Photobucket
+ Formát obrázku
+ OK
+ Nastavení Photobucket
+ Při nahrávání na Photobucket došlo k chybě:
+ Nahrát na Photobucket
+ Odeslání obrázku na bylo Photobucket úspěšné!
+ Použijte odkaz na stránku namísto odkaz na obrázek do schránky
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-de-DE.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-de-DE.xml
similarity index 96%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-de-DE.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-de-DE.xml
index f498058b1..74f7f17f9 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-de-DE.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-de-DE.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Zu Photobucket hochladen
-
-
- Photobucket Einstellungen
-
-
- OK
-
-
- Cancel
-
-
- Das Hochladen zu Photobucket war erfolgreich.
-
-
- Es gab einen Fehler beim Hochladen zu Photobucket:
-
-
- Bildformat
-
-
- Übermittle Daten zu Photobucket. Bitte warten...
-
-
- Benutze der Seite-URL statt Bild-URL im Zwischenablage
-
-
- Photobucket Einstellungen
-
-
+
+
+
+
+ Zu Photobucket hochladen
+
+
+ Photobucket Einstellungen
+
+
+ OK
+
+
+ Cancel
+
+
+ Das Hochladen zu Photobucket war erfolgreich.
+
+
+ Es gab einen Fehler beim Hochladen zu Photobucket:
+
+
+ Bildformat
+
+
+ Übermittle Daten zu Photobucket. Bitte warten...
+
+
+ Benutze der Seite-URL statt Bild-URL im Zwischenablage
+
+
+ Photobucket Einstellungen
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-en-US.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-en-US.xml
similarity index 90%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-en-US.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-en-US.xml
index 2cb07985c..cc2d3d241 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-en-US.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-en-US.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Upload to Photobucket
-
-
- Photobucket settings
-
-
- OK
-
-
- Cancel
-
-
- Successfully uploaded image to Photobucket!
-
-
- An error occurred while uploading to Photobucket:
-
-
- Image format
-
-
- Communicating with Photobucket. Please wait...
-
-
- Use page link instead of image link on clipboard
-
-
- Configure Photobucket
-
-
+
+
+
+
+ Upload to Photobucket
+
+
+ Photobucket settings
+
+
+ OK
+
+
+ Cancel
+
+
+ Successfully uploaded image to Photobucket!
+
+
+ An error occured while uploading to Photobucket:
+
+
+ Image format
+
+
+ Communicating with Photobucket. Please wait...
+
+
+ Use page link instead of image link on clipboard
+
+
+ Configure Photobucket
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-fr_FR.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-fr_FR.xml
similarity index 96%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-fr_FR.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-fr_FR.xml
index 6d98bcd48..f2aa66b63 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-fr_FR.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-fr_FR.xml
@@ -1,29 +1,29 @@
-
-
-
-
- Téléverser vers Photobucket
-
-
- Paramètres Photobucket
-
-
- Utiliser proxy
-
-
- L'image a été téléversée vers Photobucket avec succès !
-
-
- Une erreur est survenue lors du téléversement vers Photobucket:
-
-
- Format d'image
-
-
- Téléversement vers Photobucket, veuillez patienter...
-
-
- Configurer Photobucket
-
-
+
+
+
+
+ Téléverser vers Photobucket
+
+
+ Paramètres Photobucket
+
+
+ Utiliser proxy
+
+
+ L'image a été téléversée vers Photobucket avec succès !
+
+
+ Une erreur est survenue lors du téléversement vers Photobucket:
+
+
+ Format d'image
+
+
+ Téléversement vers Photobucket, veuillez patienter...
+
+
+ Configurer Photobucket
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-id-ID.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-id-ID.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-id-ID.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-id-ID.xml
index 33541137d..b702ee68d 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-id-ID.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-id-ID.xml
@@ -1,15 +1,15 @@
-
-
-
- Batal
- Menyambungkan ke Photobucket. Tunggu sebentar...
- Konfigurasi Photobucket
- Format gambar
- Oke
- Pengaturan Photobucket
- Kesalahan terjadi ketika mengunggah ke Photobucket:
- Unggah ke Photobucket
- Berhasil mengunggah gambar ke Photobucket!
- Gunakan link laman daripada link gambar di papanklip
-
+
+
+
+ Batal
+ Menyambungkan ke Photobucket. Tunggu sebentar...
+ Konfigurasi Photobucket
+ Format gambar
+ Oke
+ Pengaturan Photobucket
+ Kesalahan terjadi ketika mengunggah ke Photobucket:
+ Unggah ke Photobucket
+ Berhasil mengunggah gambar ke Photobucket!
+ Gunakan link laman daripada link gambar di papanklip
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-it-IT.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-it-IT.xml
similarity index 69%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-it-IT.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-it-IT.xml
index 233153065..f0c1e80d2 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-it-IT.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-it-IT.xml
@@ -1,35 +1,35 @@
-
-
-
-
- Carica su Photobucket
-
-
- Impostazioni Photobucket
-
-
- OK
-
-
- Annulla
-
-
- Caricamento immagine su Photobucket completato!
-
-
- Si è verificato un errore durante il caricamento su Photobucket:
-
-
- Formato immagine
-
-
- Comunicazione con Photobucket...
-
-
- Negli Appunti usa il collegamento pagina invece di quello all'immagine
-
-
- Impostazioni Photobucket
-
-
-
+
+
+
+
+ Carica su Photobucket
+
+
+ Impostazioni Photobucket
+
+
+ OK
+
+
+ Annulla
+
+
+ Immagine caricata correttamente su Photobucket!
+
+
+ Si è verificato un errore durante il caricamento su Photobucket:
+
+
+ Formato immagine
+
+
+ Comunicazione con Photobucket. Attendere prego...
+
+
+ Usa il collegamento alla pagina invece di quello all'immagine su appunti
+
+
+ Configurazione Photobucket
+
+
+
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-kab-DZ.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-kab-DZ.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-kab-DZ.xml
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ko-KR.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ko-KR.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ko-KR.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ko-KR.xml
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-lv-LV.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-lv-LV.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-lv-LV.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-lv-LV.xml
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-nl-NL.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-nl-NL.xml
similarity index 96%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-nl-NL.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-nl-NL.xml
index 8756d62f5..dd63f662f 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-nl-NL.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-nl-NL.xml
@@ -1,29 +1,29 @@
-
-
-
-
- Naar Photobucket uploaden
-
-
- Photobucket instellingen
-
-
- Het uploaden naar Photobucket is geslaagt!
-
-
- Tijdens het uploaden naar Photobucket is een fout opgetreden:
-
-
- Beeld formaat
-
-
- Data overdraging naar Photobucket, wachten AUB...
-
-
- Kopieer de pagina link in plaats van de beeld link in het klembord
-
-
- Photobucket Instellingen
-
-
+
+
+
+
+ Naar Photobucket uploaden
+
+
+ Photobucket instellingen
+
+
+ Het uploaden naar Photobucket is geslaagt!
+
+
+ Tijdens het uploaden naar Photobucket is een fout opgetreden:
+
+
+ Beeld formaat
+
+
+ Data overdraging naar Photobucket, wachten AUB...
+
+
+ Kopieer de pagina link in plaats van de beeld link in het klembord
+
+
+ Photobucket Instellingen
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-pl-PL.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-pl-PL.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-pl-PL.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-pl-PL.xml
index 3ce17ca0e..6bd6f9c8e 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-pl-PL.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-pl-PL.xml
@@ -1,15 +1,15 @@
-
-
-
- Anuluj
- Trwa komunikacja z Photobucket. Proszę czekać...
- Konfiguruj Photobucket
- Format obrazów
- OK
- Ustawienia Photobucket
- Wystąpił błąd przy wysyłaniu do Photobucket:
- Wyślij do Photobucket
- Wysyłanie obrazu do Photobucket powiodło się!
- Kopiuj do schowka link do strony zamiast link do obrazu
-
+
+
+
+ Anuluj
+ Trwa komunikacja z Photobucket. Proszę czekać...
+ Konfiguruj Photobucket
+ Format obrazów
+ OK
+ Ustawienia Photobucket
+ Wystąpił błąd przy wysyłaniu do Photobucket:
+ Wyślij do Photobucket
+ Wysyłanie obrazu do Photobucket powiodło się!
+ Kopiuj do schowka link do strony zamiast link do obrazu
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-pt-PT.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-pt-PT.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-pt-PT.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-pt-PT.xml
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ru-RU.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ru-RU.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ru-RU.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ru-RU.xml
index 10532027e..756faf0a9 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ru-RU.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ru-RU.xml
@@ -1,15 +1,15 @@
-
-
-
- Отмена
- Обмен данными с Photobucket. Подождите...
- Настройка Photobucket
- Формат изображения
- OK
- Параметры Photobucket
- Произошла ошибка при загрузке на Photobucket:
- Загрузить на Photobucket
- Изображение успешно загружено на Photobucket!
- Использовать ссылку страницы, вместо ссылки изображения в буфере обмена
-
+
+
+
+ Отмена
+ Обмен данными с Photobucket. Подождите...
+ Настройка Photobucket
+ Формат изображения
+ OK
+ Параметры Photobucket
+ Произошла ошибка при загрузке на Photobucket:
+ Загрузить на Photobucket
+ Изображение успешно загружено на Photobucket!
+ Использовать ссылку страницы, вместо ссылки изображения в буфере обмена
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-sv-SE.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-sv-SE.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-sv-SE.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-sv-SE.xml
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-uk-UA.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-uk-UA.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-uk-UA.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-uk-UA.xml
index f85869978..c1f4e1732 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-uk-UA.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-uk-UA.xml
@@ -1,15 +1,15 @@
-
-
-
- Вивантажити на Photobucket
- Параметри Photobucket
- Гаразд
- Скасувати
- Зображення вдало вивантажено на Photobucket!
- Відбулась помилка при вивантаженні зображення на Photobucket:
- Формат зображення
- З’єднання з Photobucket. Будь ласка, зачекайте...
- Використовувати посилання на сторінку замість посилання на зображення
- Налаштувати Photobucket
-
-
+
+
+
+ Вивантажити на Photobucket
+ Параметри Photobucket
+ Гаразд
+ Скасувати
+ Зображення вдало вивантажено на Photobucket!
+ Відбулась помилка при вивантаженні зображення на Photobucket:
+ Формат зображення
+ З’єднання з Photobucket. Будь ласка, зачекайте...
+ Використовувати посилання на сторінку замість посилання на зображення
+ Налаштувати Photobucket
+
+
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-CN.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-CN.xml
similarity index 96%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-CN.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-CN.xml
index 5c0aae261..522424a35 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-CN.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-CN.xml
@@ -1,23 +1,23 @@
-
-
-
-
- 上传到 Photobucket
-
-
- Photobucket 设置
-
-
- 已成功上传图片到 Photobucket !
-
-
- 上传到 Photobucket 时出现错误:
-
-
- 图片格式
-
-
- 连接到 Photobucket,请稍候...
-
-
+
+
+
+
+ 上传到 Photobucket
+
+
+ Photobucket 设置
+
+
+ 已成功上传图片到 Photobucket !
+
+
+ 上传到 Photobucket 时出现错误:
+
+
+ 图片格式
+
+
+ 连接到 Photobucket,请稍候...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-TW.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-TW.xml
similarity index 98%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-TW.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-TW.xml
index caf649a89..c35408262 100644
--- a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-zh-TW.xml
+++ b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-zh-TW.xml
@@ -1,15 +1,15 @@
-
-
-
- 取消
- 正在與 Photobucket 通訊,請稍候...
- 組態 Photobucket
- 圖片格式
- 確定
- Photobucket 設定
- 上傳到 Photobucket 時發生錯誤:
- 上傳到 Photobucket
- 上傳圖片到 Photobucket 成功!
- 在剪貼簿使用空白連結而不是圖片連結
-
+
+
+
+ 取消
+ 正在與 Photobucket 通訊,請稍候...
+ 組態 Photobucket
+ 圖片格式
+ 確定
+ Photobucket 設定
+ 上傳到 Photobucket 時發生錯誤:
+ 上傳到 Photobucket
+ 上傳圖片到 Photobucket 成功!
+ 在剪貼簿使用空白連結而不是圖片連結
+
\ No newline at end of file
diff --git a/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs
new file mode 100644
index 000000000..4eed1bcdd
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs
@@ -0,0 +1,73 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// Description of PhotobucketConfiguration.
+ ///
+ [IniSection("Photobucket", Description="Greenshot Photobucket Plugin configuration")]
+ public class PhotobucketConfiguration : IniSection {
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+ [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
+ public bool UploadReduceColors { get; set; }
+ [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
+ public bool UsePageLink { get; set; }
+ [IniProperty("Token", Description = "The Photobucket token", Encrypted=true, ExcludeIfNull=true)]
+ public string Token { get; set; }
+ [IniProperty("TokenSecret", Description = "The Photobucket token secret", Encrypted=true, ExcludeIfNull=true)]
+ public string TokenSecret { get; set; }
+ [IniProperty("SubDomain", Description = "The Photobucket api subdomain", Encrypted = true, ExcludeIfNull = true)]
+ public string SubDomain { get; set; }
+ [IniProperty("Username", Description = "The Photobucket api username", ExcludeIfNull = true)]
+ public string Username { get; set; }
+
+ public int Credits {
+ get;
+ set;
+ }
+
+ ///
+ /// A form for username/password
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ SettingsForm settingsForm = null;
+
+ new PleaseWaitForm().ShowAndWait(PhotobucketPlugin.Attributes.Name, Language.GetString("photobucket", LangKey.communication_wait),
+ delegate {
+ settingsForm = new SettingsForm();
+ }
+ );
+ DialogResult result = settingsForm.ShowDialog();
+ if (result == DialogResult.OK) {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template b/GreenshotPhotobucketPlugin/PhotobucketCredentials.cs
similarity index 77%
rename from src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template
rename to GreenshotPhotobucketPlugin/PhotobucketCredentials.cs
index 8895f5a73..2b4cee804 100644
--- a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template
+++ b/GreenshotPhotobucketPlugin/PhotobucketCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.Photobucket {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for photobucket integration.
- /// You can set your own values here
- ///
- public static class PhotobucketCredentials {
- public static string ConsumerKey = "${Photobucket_ClientId}";
- public static string ConsumerSecret = "${Photobucket_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for photobucket integration.
+ /// You can set your own values here
+ ///
+ public static class PhotobucketCredentials {
+ public static string ConsumerKey = "@credentials_photobucket_consumer_key@";
+ public static string ConsumerSecret = "@credentials_photobucket_consumer_secret@";
+ }
+}
diff --git a/GreenshotPhotobucketPlugin/PhotobucketDestination.cs b/GreenshotPhotobucketPlugin/PhotobucketDestination.cs
new file mode 100644
index 000000000..d2b484342
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketDestination.cs
@@ -0,0 +1,102 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Drawing;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// Description of PhotobucketDestination.
+ ///
+ public class PhotobucketDestination : AbstractDestination {
+ private readonly PhotobucketPlugin _plugin;
+ private readonly string _albumPath;
+
+ ///
+ /// Create a Photobucket destination, which also has the path to the album in it
+ ///
+ ///
+ /// path to the album, null for default
+ public PhotobucketDestination(PhotobucketPlugin plugin, string albumPath) {
+ _plugin = plugin;
+ _albumPath = albumPath;
+ }
+
+ public override string Designation => "Photobucket";
+
+ public override string Description {
+ get {
+ if (_albumPath != null) {
+ return _albumPath;
+ }
+ return Language.GetString("photobucket", LangKey.upload_menu_item);
+ }
+ }
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(PhotobucketPlugin));
+ return (Image)resources.GetObject("Photobucket");
+ }
+ }
+
+ public override bool IsDynamic => true;
+
+ public override IEnumerable DynamicDestinations() {
+ IList albums = null;
+ try {
+ albums = PhotobucketUtils.RetrievePhotobucketAlbums();
+ }
+ catch
+ {
+ // ignored
+ }
+
+ if (albums == null || albums.Count == 0) {
+ yield break;
+ }
+ foreach (string album in albums) {
+ yield return new PhotobucketDestination(_plugin, album);
+ }
+ }
+
+ ///
+ /// Export the capture to Photobucket
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, _albumPath, out uploadUrl);
+ if (uploaded) {
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = uploadUrl;
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotPhotobucketPlugin/PhotobucketInfo.cs b/GreenshotPhotobucketPlugin/PhotobucketInfo.cs
new file mode 100644
index 000000000..cd66992fb
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketInfo.cs
@@ -0,0 +1,67 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Xml;
+
+namespace GreenshotPhotobucketPlugin
+{
+ ///
+ /// Description of PhotobucketInfo.
+ ///
+ public class PhotobucketInfo {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PhotobucketInfo));
+
+ public string Original { get; set; }
+
+ public string Page { get; set; }
+
+ public string Thumbnail { get; set; }
+
+ ///
+ /// Parse the upload response
+ ///
+ /// XML
+ /// PhotobucketInfo object
+ public static PhotobucketInfo FromUploadResponse(string response) {
+ Log.Debug(response);
+ PhotobucketInfo photobucketInfo = new PhotobucketInfo();
+ try {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(response);
+ var nodes = doc.GetElementsByTagName("url");
+ if(nodes.Count > 0) {
+ photobucketInfo.Original = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("browseurl");
+ if(nodes.Count > 0) {
+ photobucketInfo.Page = nodes.Item(0)?.InnerText;
+ }
+ nodes = doc.GetElementsByTagName("thumb");
+ if(nodes.Count > 0) {
+ photobucketInfo.Thumbnail = nodes.Item(0)?.InnerText;
+ }
+ } catch(Exception e) {
+ Log.ErrorFormat("Could not parse Photobucket response due to error {0}, response was: {1}", e.Message, response);
+ }
+ return photobucketInfo;
+ }
+ }
+}
diff --git a/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs b/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs
new file mode 100644
index 000000000..6d7402319
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs
@@ -0,0 +1,155 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// This is the GreenshotPhotobucketPlugin base code
+ ///
+ public class PhotobucketPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PhotobucketPlugin));
+ private static PhotobucketConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new PhotobucketDestination(this, null);
+ }
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ /// true if plugin is initialized, false if not (doesn't show)
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ _host = pluginHost;
+ Attributes = myAttributes;
+
+ // Get configuration
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(PhotobucketPlugin));
+
+ _itemPlugInConfig = new ToolStripMenuItem(Language.GetString("photobucket", LangKey.configure))
+ {
+ Tag = _host,
+ Image = (Image)_resources.GetObject("Photobucket")
+ };
+ _itemPlugInConfig.Click += delegate {
+ _config.ShowConfigDialog();
+ };
+
+ PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("photobucket", LangKey.configure);
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Photobucket Plugin shutdown.");
+ Language.LanguageChanged -= OnLanguageChanged;
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ ///
+ /// Upload the capture to Photobucket
+ ///
+ ///
+ /// ISurface
+ /// Path to the album
+ /// out string for the url
+ /// true if the upload succeeded
+ public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, string albumPath, out string uploadUrl) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, _config.UploadReduceColors);
+ try {
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
+ PhotobucketInfo photobucketInfo = null;
+
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("photobucket", LangKey.communication_wait),
+ delegate {
+ photobucketInfo = PhotobucketUtils.UploadToPhotobucket(surfaceToUpload, outputSettings, albumPath, captureDetails.Title, filename);
+ }
+ );
+ // This causes an exeption if the upload failed :)
+ Log.DebugFormat("Uploaded to Photobucket page: " + photobucketInfo.Page);
+ uploadUrl = null;
+ try {
+ if (_config.UsePageLink) {
+ uploadUrl = photobucketInfo.Page;
+ Clipboard.SetText(photobucketInfo.Page);
+ } else {
+ uploadUrl = photobucketInfo.Original;
+ Clipboard.SetText(photobucketInfo.Original);
+ }
+ } catch (Exception ex) {
+ Log.Error("Can't write to clipboard: ", ex);
+ }
+ return true;
+ } catch (Exception e) {
+ Log.Error(e);
+ MessageBox.Show(Language.GetString("photobucket", LangKey.upload_failure) + " " + e.Message);
+ }
+ uploadUrl = null;
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.resx b/GreenshotPhotobucketPlugin/PhotobucketPlugin.resx
similarity index 95%
rename from src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.resx
rename to GreenshotPhotobucketPlugin/PhotobucketPlugin.resx
index 19cb5cfbd..1727301b6 100644
--- a/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.resx
+++ b/GreenshotPhotobucketPlugin/PhotobucketPlugin.resx
@@ -112,12 +112,12 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
diff --git a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs
new file mode 100644
index 000000000..6738c0086
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs
@@ -0,0 +1,221 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Xml;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// Description of PhotobucketUtils.
+ ///
+ public static class PhotobucketUtils {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PhotobucketUtils));
+ private static readonly PhotobucketConfiguration PhotobucketConfig = IniConfig.GetIniSection();
+ private static List _albumsCache;
+
+ ///
+ /// Do the actual upload to Photobucket
+ /// For more details on the available parameters, see: http://api.Photobucket.com/resources_anon
+ ///
+ /// PhotobucketResponse
+ public static PhotobucketInfo UploadToPhotobucket(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string albumPath, string title, string filename) {
+ string responseString;
+
+ var oAuth = CreateSession(true);
+ if (oAuth == null) {
+ return null;
+ }
+ IDictionary signedParameters = new Dictionary();
+ // add album
+ if (string.IsNullOrEmpty(albumPath))
+ {
+ signedParameters.Add("id", string.IsNullOrEmpty(PhotobucketConfig.Username) ? "!" : PhotobucketConfig.Username);
+ } else {
+ signedParameters.Add("id", albumPath);
+ }
+ // add type
+ signedParameters.Add("type", "image");
+ // add title
+ if (title != null) {
+ signedParameters.Add("title", title);
+ }
+ // add filename
+ if (filename != null) {
+ signedParameters.Add("filename", filename);
+ }
+ IDictionary unsignedParameters = new Dictionary();
+ // Add image
+ unsignedParameters.Add("uploadfile", new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ try {
+ string apiUrl = "http://api.photobucket.com/album/!/upload";
+ responseString = oAuth.MakeOAuthRequest(HTTPMethod.POST, apiUrl, apiUrl.Replace("api.photobucket.com", PhotobucketConfig.SubDomain), signedParameters, unsignedParameters, null);
+ } catch (Exception ex) {
+ Log.Error("Error uploading to Photobucket.", ex);
+ throw;
+ } finally {
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ PhotobucketConfig.Token = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ PhotobucketConfig.TokenSecret = oAuth.TokenSecret;
+ }
+ }
+ if (responseString == null) {
+ return null;
+ }
+ Log.Info(responseString);
+ var photobucketInfo = PhotobucketInfo.FromUploadResponse(responseString);
+ Log.Debug("Upload to Photobucket was finished");
+ return photobucketInfo;
+ }
+
+ ///
+ /// Helper method to create an OAuth session object for contacting the Photobucket API
+ ///
+ /// OAuthSession
+ private static OAuthSession CreateSession(bool autoLogin) {
+ var oAuth = new OAuthSession(PhotobucketCredentials.ConsumerKey, PhotobucketCredentials.ConsumerSecret)
+ {
+ AutoLogin = autoLogin,
+ CheckVerifier = false,
+ CallbackUrl = "http://getgreenshot.org",
+ AccessTokenUrl = "http://api.photobucket.com/login/access",
+ AuthorizeUrl = "http://photobucket.com/apilogin/login",
+ RequestTokenUrl = "http://api.photobucket.com/login/request",
+ BrowserSize = new Size(1010, 400),
+ RequestTokenMethod = HTTPMethod.POST,
+ AccessTokenMethod = HTTPMethod.POST,
+ LoginTitle = "Photobucket authorization"
+ };
+ // This url is configured in the Photobucket API settings in the Photobucket site!!
+ // Photobucket is very particular about the used methods!
+
+ if (string.IsNullOrEmpty(PhotobucketConfig.SubDomain) || string.IsNullOrEmpty(PhotobucketConfig.Token) || string.IsNullOrEmpty(PhotobucketConfig.Username)) {
+ if (!autoLogin) {
+ return null;
+ }
+ if (!oAuth.Authorize()) {
+ return null;
+ }
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ PhotobucketConfig.Token = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ PhotobucketConfig.TokenSecret = oAuth.TokenSecret;
+ }
+ if (oAuth.AccessTokenResponseParameters?["subdomain"] != null) {
+ PhotobucketConfig.SubDomain = oAuth.AccessTokenResponseParameters["subdomain"];
+ }
+ if (oAuth.AccessTokenResponseParameters?["username"] != null) {
+ PhotobucketConfig.Username = oAuth.AccessTokenResponseParameters["username"];
+ }
+ IniConfig.Save();
+ }
+ oAuth.Token = PhotobucketConfig.Token;
+ oAuth.TokenSecret = PhotobucketConfig.TokenSecret;
+ return oAuth;
+ }
+
+ ///
+ /// Get list of photobucket albums
+ ///
+ /// List of string
+ public static IList RetrievePhotobucketAlbums() {
+ if (_albumsCache != null) {
+ return _albumsCache;
+ }
+ string responseString;
+
+ OAuthSession oAuth = CreateSession(false);
+ if (oAuth == null) {
+ return null;
+ }
+ IDictionary signedParameters = new Dictionary();
+ try {
+ string apiUrl = $"http://api.photobucket.com/album/{PhotobucketConfig.Username}";
+ responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, apiUrl, apiUrl.Replace("api.photobucket.com", PhotobucketConfig.SubDomain), signedParameters, null, null);
+ } catch (Exception ex) {
+ Log.Error("Error uploading to Photobucket.", ex);
+ throw;
+ } finally {
+ if (!string.IsNullOrEmpty(oAuth.Token)) {
+ PhotobucketConfig.Token = oAuth.Token;
+ }
+ if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
+ PhotobucketConfig.TokenSecret = oAuth.TokenSecret;
+ }
+ }
+ if (responseString == null) {
+ return null;
+ }
+ try {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(responseString);
+ List albums = new List();
+ var xmlNode = doc.GetElementsByTagName("content").Item(0);
+ if (xmlNode != null)
+ {
+ RecurseAlbums(albums, null, xmlNode.ChildNodes);
+ }
+ Log.DebugFormat("Albums: {0}", string.Join(",", albums.ToArray()));
+ _albumsCache = albums;
+ return albums;
+ } catch(Exception e) {
+ Log.Error("Error while Reading albums: ", e);
+ }
+
+ Log.Debug("Upload to Photobucket was finished");
+ return null;
+ }
+
+ ///
+ /// Parse the album nodes recursively
+ ///
+ ///
+ ///
+ ///
+ private static void RecurseAlbums(ICollection albums, string path, IEnumerable nodes) {
+ foreach(XmlNode node in nodes) {
+ if (node.Name != "album") {
+ continue;
+ }
+ if (node.Attributes != null)
+ {
+ string currentAlbum = node.Attributes["name"].Value;
+ string currentPath = currentAlbum;
+ if (!string.IsNullOrEmpty(path)) {
+ currentPath = $"{path}/{currentAlbum}";
+ }
+
+ albums.Add(currentPath);
+ if (node.Attributes["subalbum_count"] != null && node.Attributes["subalbum_count"].Value != "0") {
+ RecurseAlbums(albums, currentPath, node.ChildNodes);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs b/GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..6bfbb5a0d
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,48 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.Plugin;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Greenshot-Photobucket-Plugin")]
+[assembly: AssemblyDescription("A plugin to upload images to Photobucket")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("Photobucket Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotPhotobucketPlugin.PhotobucketPlugin", true)]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs b/GreenshotPicasaPlugin/Forms/PicasaForm.cs
similarity index 66%
rename from src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs
rename to GreenshotPicasaPlugin/Forms/PicasaForm.cs
index 84471d011..a1d093e30 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs
+++ b/GreenshotPicasaPlugin/Forms/PicasaForm.cs
@@ -1,8 +1,8 @@
/*
- * A GooglePhotos Plugin for Greenshot
+ * A Picasa Plugin for Greenshot
* Copyright (C) 2011 Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,14 +15,11 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.GooglePhotos.Forms
-{
- public class GooglePhotosForm : GreenshotForm
- {
- }
-}
\ No newline at end of file
+ * along with this program. If not, see .
+ */
+using GreenshotPlugin.Controls;
+
+namespace GreenshotPicasaPlugin {
+ public class PicasaForm : GreenshotForm {
+ }
+}
diff --git a/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs b/GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs
similarity index 74%
rename from src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs
rename to GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs
index 23e68012f..41cb346f9 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs
+++ b/GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs
@@ -1,150 +1,148 @@
-/*
- * A GooglePhotos Plugin for Greenshot
- * Copyright (C) 2011 Francis Noel
- *
- * For more information see: https://getgreenshot.org/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using Greenshot.Base.Controls;
-
-namespace Greenshot.Plugin.GooglePhotos.Forms {
- partial class SettingsForm {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent()
- {
- this.buttonOK = new GreenshotButton();
- this.buttonCancel = new GreenshotButton();
- this.combobox_uploadimageformat = new GreenshotComboBox();
- this.label_upload_format = new GreenshotLabel();
- this.label_AfterUpload = new GreenshotLabel();
- this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox();
- this.SuspendLayout();
- //
- // buttonOK
- //
- this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.buttonOK.LanguageKey = "OK";
- this.buttonOK.Location = new System.Drawing.Point(267, 78);
- this.buttonOK.Name = "buttonOK";
- this.buttonOK.Size = new System.Drawing.Size(75, 23);
- this.buttonOK.TabIndex = 10;
- this.buttonOK.UseVisualStyleBackColor = true;
- //
- // buttonCancel
- //
- this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.buttonCancel.LanguageKey = "CANCEL";
- this.buttonCancel.Location = new System.Drawing.Point(348, 78);
- this.buttonCancel.Name = "buttonCancel";
- this.buttonCancel.Size = new System.Drawing.Size(75, 23);
- this.buttonCancel.TabIndex = 11;
- this.buttonCancel.UseVisualStyleBackColor = true;
- //
- // combobox_uploadimageformat
- //
- this.combobox_uploadimageformat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.combobox_uploadimageformat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.combobox_uploadimageformat.FormattingEnabled = true;
- this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12);
- this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
- this.combobox_uploadimageformat.PropertyName = nameof(GooglePhotosConfiguration.UploadFormat);
- this.combobox_uploadimageformat.SectionName = "GooglePhotos";
- this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21);
- this.combobox_uploadimageformat.TabIndex = 1;
- //
- // label_upload_format
- //
- this.label_upload_format.LanguageKey = "googlephotos.label_upload_format";
- this.label_upload_format.Location = new System.Drawing.Point(10, 18);
- this.label_upload_format.Name = "label_upload_format";
- this.label_upload_format.Size = new System.Drawing.Size(181, 33);
- this.label_upload_format.TabIndex = 4;
- //
- // label_AfterUpload
- //
- this.label_AfterUpload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.label_AfterUpload.LanguageKey = "googlephotos.label_AfterUpload";
- this.label_AfterUpload.Location = new System.Drawing.Point(10, 51);
- this.label_AfterUpload.Name = "label_AfterUpload";
- this.label_AfterUpload.Size = new System.Drawing.Size(181, 29);
- this.label_AfterUpload.TabIndex = 8;
- //
- // checkboxAfterUploadLinkToClipBoard
- //
- this.checkboxAfterUploadLinkToClipBoard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "googlephotos.label_AfterUploadLinkToClipBoard";
- this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50);
- this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
- this.checkboxAfterUploadLinkToClipBoard.PropertyName = nameof(GooglePhotosConfiguration.AfterUploadLinkToClipBoard);
- this.checkboxAfterUploadLinkToClipBoard.SectionName = "GooglePhotos";
- this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
- this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
- this.checkboxAfterUploadLinkToClipBoard.UseVisualStyleBackColor = true;
- //
- // SettingsForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(432, 110);
- this.Controls.Add(this.checkboxAfterUploadLinkToClipBoard);
- this.Controls.Add(this.label_AfterUpload);
- this.Controls.Add(this.label_upload_format);
- this.Controls.Add(this.combobox_uploadimageformat);
- this.Controls.Add(this.buttonCancel);
- this.Controls.Add(this.buttonOK);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.LanguageKey = "googlephotos.settings_title";
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "SettingsForm";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
- private GreenshotComboBox combobox_uploadimageformat;
- private GreenshotLabel label_upload_format;
- private GreenshotButton buttonCancel;
- private GreenshotButton buttonOK;
- private GreenshotLabel label_AfterUpload;
- private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
- }
-}
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotPicasaPlugin {
+ partial class SettingsForm {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton();
+ this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton();
+ this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox();
+ this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.SuspendLayout();
+ //
+ // buttonOK
+ //
+ this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.buttonOK.LanguageKey = "OK";
+ this.buttonOK.Location = new System.Drawing.Point(267, 78);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 23);
+ this.buttonOK.TabIndex = 10;
+ this.buttonOK.UseVisualStyleBackColor = true;
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.buttonCancel.LanguageKey = "CANCEL";
+ this.buttonCancel.Location = new System.Drawing.Point(348, 78);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 11;
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ //
+ // combobox_uploadimageformat
+ //
+ this.combobox_uploadimageformat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.combobox_uploadimageformat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.combobox_uploadimageformat.FormattingEnabled = true;
+ this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12);
+ this.combobox_uploadimageformat.Name = "combobox_uploadimageformat";
+ this.combobox_uploadimageformat.PropertyName = "UploadFormat";
+ this.combobox_uploadimageformat.SectionName = "Picasa";
+ this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21);
+ this.combobox_uploadimageformat.TabIndex = 1;
+ //
+ // label_upload_format
+ //
+ this.label_upload_format.LanguageKey = "picasa.label_upload_format";
+ this.label_upload_format.Location = new System.Drawing.Point(10, 18);
+ this.label_upload_format.Name = "label_upload_format";
+ this.label_upload_format.Size = new System.Drawing.Size(181, 33);
+ this.label_upload_format.TabIndex = 4;
+ //
+ // label_AfterUpload
+ //
+ this.label_AfterUpload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.label_AfterUpload.LanguageKey = "picasa.label_AfterUpload";
+ this.label_AfterUpload.Location = new System.Drawing.Point(10, 51);
+ this.label_AfterUpload.Name = "label_AfterUpload";
+ this.label_AfterUpload.Size = new System.Drawing.Size(181, 29);
+ this.label_AfterUpload.TabIndex = 8;
+ //
+ // checkboxAfterUploadLinkToClipBoard
+ //
+ this.checkboxAfterUploadLinkToClipBoard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.checkboxAfterUploadLinkToClipBoard.AutoSize = true;
+ this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "picasa.label_AfterUploadLinkToClipBoard";
+ this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50);
+ this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard";
+ this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard";
+ this.checkboxAfterUploadLinkToClipBoard.SectionName = "Picasa";
+ this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17);
+ this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2;
+ this.checkboxAfterUploadLinkToClipBoard.UseVisualStyleBackColor = true;
+ //
+ // SettingsForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.ClientSize = new System.Drawing.Size(432, 110);
+ this.Controls.Add(this.checkboxAfterUploadLinkToClipBoard);
+ this.Controls.Add(this.label_AfterUpload);
+ this.Controls.Add(this.label_upload_format);
+ this.Controls.Add(this.combobox_uploadimageformat);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonOK);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.LanguageKey = "picasa.settings_title";
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "SettingsForm";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+ private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat;
+ private GreenshotPlugin.Controls.GreenshotLabel label_upload_format;
+ private GreenshotPlugin.Controls.GreenshotButton buttonCancel;
+ private GreenshotPlugin.Controls.GreenshotButton buttonOK;
+ private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard;
+ }
+}
diff --git a/GreenshotPicasaPlugin/Forms/SettingsForm.cs b/GreenshotPicasaPlugin/Forms/SettingsForm.cs
new file mode 100644
index 000000000..734559762
--- /dev/null
+++ b/GreenshotPicasaPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,38 @@
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// Description of PasswordRequestForm.
+ ///
+ public partial class SettingsForm : PicasaForm {
+
+ public SettingsForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ CancelButton = buttonCancel;
+ AcceptButton = buttonOK;
+ }
+
+ }
+}
diff --git a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj
new file mode 100644
index 000000000..5a7327910
--- /dev/null
+++ b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj
@@ -0,0 +1,91 @@
+
+
+
+
+ {1893A2E4-A78A-4713-A8E7-E70058DABEE0}
+ Library
+ GreenshotPicasaPlugin
+ GreenshotPicasaPlugin
+ v2.0
+ Properties
+ False
+ False
+ 4
+ false
+ Always
+
+
+ 3.5
+
+
+
+
+
+
+
+ False
+ ..\Greenshot\lib\log4net.dll
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+
+
+
+
+
+ PicasaPlugin.cs
+ Designer
+
+
+
+
+
+
+
+
+ {5B924697-4DCD-4F98-85F1-105CB84B7341}
+ GreenshotPlugin
+
+
+
+
+
+
+
+
+
+
+ if exist "$(ProjectDir)PicasaCredentials.orig.cs" (
+ rename "$(ProjectDir)PicasaCredentials.cs" "PicasaCredentials.private.cs"
+ rename "$(ProjectDir)PicasaCredentials.orig.cs" "PicasaCredentials.cs"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+
+
+if exist "$(ProjectDir)PicasaCredentials.private.cs" (
+ rename "$(ProjectDir)PicasaCredentials.cs" "PicasaCredentials.orig.cs"
+ rename "$(ProjectDir)PicasaCredentials.private.cs" "PicasaCredentials.cs"
+)
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/LanguageKeys.cs b/GreenshotPicasaPlugin/LanguageKeys.cs
similarity index 60%
rename from src/Greenshot.Plugin.GooglePhotos/LanguageKeys.cs
rename to GreenshotPicasaPlugin/LanguageKeys.cs
index 5255daac3..58a488db5 100644
--- a/src/Greenshot.Plugin.GooglePhotos/LanguageKeys.cs
+++ b/GreenshotPicasaPlugin/LanguageKeys.cs
@@ -1,8 +1,8 @@
/*
- * A GooglePhotos Plugin for Greenshot
+ * A Picasa Plugin for Greenshot
* Copyright (C) 2011 Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,16 +15,20 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.GooglePhotos
-{
- public enum LangKey
- {
- upload_menu_item,
- upload_failure,
- communication_wait,
- Configure
- }
-}
\ No newline at end of file
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPicasaPlugin {
+ public enum LangKey
+ {
+ upload_menu_item,
+ settings_title,
+ label_upload_format,
+ upload_success,
+ upload_failure,
+ communication_wait,
+ Configure,
+ label_AfterUpload,
+ label_AfterUploadLinkToClipBoard
+ }
+}
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-cs-CZ.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml
similarity index 74%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-cs-CZ.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml
index 7168b569c..4fe14494b 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-cs-CZ.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml
@@ -1,29 +1,29 @@
-
-
-
- Zrušit
- Probíhá komunikace s Picasem. Prosím počkejte ...
- Konfigurace
- Opravdu chcete odstranit obrázek {0} z GooglePhotos?
- Odstranit GooglePhotos {0}
- Historie
- Neplatná oprávnění. Otevřít nastavení pro provedené změn.
- Po odeslání
- Kopírovat odkaz do schránky
- Zobrazit historii
- Výchozí velikost
- Heslo
- Formát obrázku
- Jméno
- OK
- Originál URL
- Čtvercové náhledy URL ???
- Webová adresa URL
- Nastavení GooglePhotos
- Nahrát
- Nahrání obrázku do GooglePhotos se nezdařilo:
- Nahrát do GooglePhotos
- Úspěšně odeslaný obrázek do GooglePhotos!
- Prosím ověřit aplikaci GooglePhotos. Otevřít nastavení obrazovky. ???
-
+
+
+
+ Zrušit
+ Probíhá komunikace s Picasem. Prosím počkejte ...
+ Konfigurace
+ Opravdu chcete odstranit obrázek {0} z Picasa?
+ Odstranit Picasa {0}
+ Historie
+ Neplatná oprávnění. Otevřít nastavení pro provedené změn.
+ Po odeslání
+ Kopírovat odkaz do schránky
+ Zobrazit historii
+ Výchozí velikost
+ Heslo
+ Formát obrázku
+ Jméno
+ OK
+ Originál URL
+ Čtvercové náhledy URL ???
+ Webová adresa URL
+ Nastavení Picasa
+ Nahrát
+ Nahrání obrázku do Picasa se nezdařilo:
+ Nahrát do Picasa
+ Úspěšně odeslaný obrázek do Picasa!
+ Prosím ověřit aplikaci Picasa. Otevřít nastavení obrazovky. ???
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-de-DE.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml
similarity index 74%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-de-DE.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml
index 0a437a443..6b30f0214 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-de-DE.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml
@@ -8,25 +8,25 @@
Anschliessend
- GooglePhotos konfigurieren
+ Picasa konfigurieren
- Hochladen zu GooglePhotos
+ Hochladen zu Picasa
- GooglePhotos Einstellungen
+ Picasa Einstellungen
- Hochladen zu GooglePhotos war erfolgreich !
+ Hochladen zu Picasa war erfolgreich !
- Fehler beim Hochladen zu GooglePhotos:
+ Fehler beim Hochladen zu Picasa:
Grafikformat
- Übermittle Daten zu GooglePhotos. Bitte warten...
+ Übermittle Daten zu Picasa. Bitte warten...
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-en-US.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml
similarity index 73%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-en-US.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml
index 76c477d50..e99c84ed7 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-en-US.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml
@@ -8,25 +8,25 @@
After upload
- Configure GooglePhotos
+ Configure Picasa
- Upload to GooglePhotos
+ Upload to Picasa
- GooglePhotos settings
+ Picasa settings
- Successfully uploaded image to GooglePhotos!
+ Successfully uploaded image to Picasa!
- An error occurred while uploading to GooglePhotos:
+ An error occured while uploading to Picasa:
Image format
- Communicating with GooglePhotos. Please wait...
+ Communicating with Picasa. Please wait...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-fr-FR.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml
similarity index 62%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-fr-FR.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml
index 553d5725e..589d55613 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-fr-FR.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml
@@ -1,14 +1,14 @@
-
-
-
- Communication en cours avec GooglePhotos. Veuillez patientez...
- Configurer GooglePhotos
- Après téléversement
- Copier le lien dans le presse-papier
- Format image
- Paramètres GooglePhotos
- Une erreur s'est produite lors du téléversement vers GooglePhotos :
- Téléverser vers GooglePhotos
- Image téléversée avec succès vers GooglePhotos !
-
+
+
+
+ Communication en cours avec Picasa. Veuillez patientez...
+ Configurer Picasa
+ Après téléversement
+ Copier le lien dans le presse-papier
+ Format image
+ Paramètres Picasa
+ Une erreur s'est produite lors du téléversement vers Picasa :
+ Téléverser vers Picasa
+ Image téléversée avec succès vers Picasa !
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-id-ID.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml
similarity index 58%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-id-ID.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml
index c906bb08e..5632a3daa 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-id-ID.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml
@@ -1,14 +1,14 @@
-
-
-
- Menyambungkan ke GooglePhotos. Tunggu sebentar...
- Konfigurasi GooglePhotos
- Sesudah mengunggah
- Sambung ke papanklip
- Format gambar
- Pengaturan GooglePhotos
- Kesalahan terjadi ketika mengunggah ke GooglePhotos:
- Unggah ke GooglePhotos
- Berhasil mengunggah gambar ke GooglePhotos!
-
+
+
+
+ Menyambungkan ke Picasa. Tunggu sebentar...
+ Konfigurasi Picasa
+ Sesudah mengunggah
+ Sambung ke papanklip
+ Format gambar
+ Pengaturan Picasa
+ Kesalahan terjadi ketika mengunggah ke Picasa:
+ Unggah ke Picasa
+ Berhasil mengunggah gambar ke Picasa!
+
\ No newline at end of file
diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml
new file mode 100644
index 000000000..a72279d00
--- /dev/null
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml
@@ -0,0 +1,14 @@
+
+
+
+ Comunicazione con Picasa. Attendere prego...
+ Configurazione Picasa
+ Dopo il carico
+ Collegamento agli appunti
+ Formato immagine
+ Impostazioni di Picasa
+ Si è verificato un errore durante il caricamento su Picasa:
+ Carica su Picasa
+ Immagine caricata correttamente su Picasa!
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-kab-DZ.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml
similarity index 59%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-kab-DZ.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml
index dd5c784d4..367287108 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-kab-DZ.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml
@@ -1,14 +1,14 @@
- S tidett tebɣiḍ ad tekkseḍ amazray adigan n GooglePhotos ?...
- Swel GooglePhotos
+ S tidett tebɣiḍ ad tekkseḍ amazray adigan n Picasa ?...
+ Swel Picasa
Ticki yemmed usali
Nɣel aseɣwen ɣef afus
Amsal n tugna
- Iɣewwaṛen GooglePhotos
- Teḍra-d tuccḍa deg usali ɣer GooglePhotos :
- Sali ɣer GooglePhotos
- Tugna tuli ɣer GooglePhotos !
+ Iɣewwaṛen Picasa
+ Teḍra-d tuccḍa deg usali ɣer Picasa :
+ Sali ɣer Picasa
+ Tugna tuli ɣer Picasa !
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ko-KR.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml
similarity index 74%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ko-KR.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml
index d095f9f72..f452a9618 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ko-KR.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml
@@ -8,25 +8,25 @@
얼로드 후
- GooglePhotos 설정
+ Picasa 설정
- GooglePhotos로 업로드
+ Picasa로 업로드
- GooglePhotos 설정
+ Picasa 설정
- GooglePhotos로 이미지 업로드 성공!
+ Picasa로 이미지 업로드 성공!
- GooglePhotos로 업로드시 오류 발생:
+ Picasa로 업로드시 오류 발생:
이미지 형식
- GooglePhotos와 연결 중 잠시 기다리세요...
+ Picasa와 연결 중 잠시 기다리세요...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-lv-LV.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml
similarity index 75%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-lv-LV.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml
index 7e0e0b8ca..c33bdc519 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-lv-LV.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml
@@ -9,25 +9,25 @@
Pēc augšupielādes
- GooglePhotos iestatījumi
+ Picasa iestatījumi
- Augšupieladēt uz GooglePhotos
+ Augšupieladēt uz Picasa
- GooglePhotos iestatījumi
+ Picasa iestatījumi
- Attēls veiksmīgi augšupielādēts uz GooglePhotos!
+ Attēls veiksmīgi augšupielādēts uz Picasa!
- Kļūda augšuplādējot uz GooglePhotos:
+ Kļūda augšuplādējot uz Picasa:
Attēla formāts
- Savienojos ar GooglePhotos. Lūdzu uzgaidiet...
+ Savienojos ar Picasa. Lūdzu uzgaidiet...
diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml
new file mode 100644
index 000000000..c4be12b84
--- /dev/null
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml
@@ -0,0 +1,14 @@
+
+
+
+ Trwa komunikacja z Picasa. Proszę czekać...
+ Konfiguruj Picasa
+ Po wysłaniu
+ Link do schowka
+ Format obrazów
+ Ustawienia Picasa
+ Wystąpił błąd przy wysyłaniu do Picasa:
+ Wyślij do Picasa
+ Wysyłanie obrazu do Picasa powiodło się!
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-pt-PT.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml
similarity index 73%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-pt-PT.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml
index c3194dad0..4649e8005 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-pt-PT.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml
@@ -8,25 +8,25 @@
Após enviar
- Configurar o GooglePhotos
+ Configurar o Picasa
- enviar para o GooglePhotos
+ enviar para o Picasa
- Definições GooglePhotos
+ Definições Picasa
- Imagem enviada com êxito para o GooglePhotos!
+ Imagem enviada com êxito para o Picasa!
- Ocorreu um erro ao enviar para o GooglePhotos:
+ Ocorreu um erro ao enviar para o Picasa:
Formato da imagem
- A comunicar com o GooglePhotos. Por favor aguarde...
+ A comunicar com o Picasa. Por favor aguarde...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ru-RU.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml
similarity index 61%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ru-RU.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml
index c7aa0317d..7a273bce7 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-ru-RU.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml
@@ -1,14 +1,14 @@
-
-
-
- Обмен данными с GooglePhotos. Подождите...
- Настройка GooglePhotos
- После загрузки
- Ссылки в буфер обмена
- Формат изображения
- Настройки GooglePhotos
- Произошла ошибка при загрузке на GooglePhotos:
- Загрузить на GooglePhotos
- Изображение успешно загружено на GooglePhotos!
-
+
+
+
+ Обмен данными с Picasa. Подождите...
+ Настройка Picasa
+ После загрузки
+ Ссылки в буфер обмена
+ Формат изображения
+ Настройки Picasa
+ Произошла ошибка при загрузке на Picasa:
+ Загрузить на Picasa
+ Изображение успешно загружено на Picasa!
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sr-RS.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml
similarity index 98%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sr-RS.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml
index 88c045edd..f43494f01 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sr-RS.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml
@@ -1,14 +1,14 @@
-
-
-
- Комуницирам с Пикасом. Сачекајте…
- Поставке Пикасе
- Након отпремања:
- Веза ка остави
- Формат слике:
- Поставке Пикасе
- Дошло је до грешке при отпремању на Пикасу:
- Отпреми на Пикасу
- Слика је успешно отпремљена на Пикасу.
-
+
+
+
+ Комуницирам с Пикасом. Сачекајте…
+ Поставке Пикасе
+ Након отпремања:
+ Веза ка остави
+ Формат слике:
+ Поставке Пикасе
+ Дошло је до грешке при отпремању на Пикасу:
+ Отпреми на Пикасу
+ Слика је успешно отпремљена на Пикасу.
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sv-SE.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml
similarity index 73%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sv-SE.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml
index 86a0aec4c..d3469d802 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-sv-SE.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml
@@ -8,25 +8,25 @@
Vid uppladdning
- Konfigurera GooglePhotos
+ Konfigurera Picasa
- Ladda upp till GooglePhotos
+ Ladda upp till Picasa
- GooglePhotos-inställningar
+ Picasa-inställningar
- Skärmdumpen laddades upp till GooglePhotos!
+ Skärmdumpen laddades upp till Picasa!
- Ett fel uppstod vid uppladdning till GooglePhotos:
+ Ett fel uppstod vid uppladdning till Picasa:
Bildformat
- Kommunicerar med GooglePhotos. Vänta...
+ Kommunicerar med Picasa. Vänta...
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-uk-UA.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml
similarity index 53%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-uk-UA.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml
index 9be4ab5b6..c1ecd0a4c 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-uk-UA.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml
@@ -1,14 +1,14 @@
-
-
-
- Посилання в буфер обміну
- Після вивантаження
- Налаштувати GooglePhotos
- Вивантажити на GooglePhotos
- Параметри GooglePhotos
- Зображення вдало вивантажено на GooglePhotos!
- Відбулась помилка під час вивантаження на GooglePhotos:
- Формат зображення
- З’єднання з GooglePhotos. Будь ласка, зачекайте...
-
-
+
+
+
+ Посилання в буфер обміну
+ Після вивантаження
+ Налаштувати Picasa
+ Вивантажити на Picasa
+ Параметри Picasa
+ Зображення вдало вивантажено на Picasa!
+ Відбулась помилка під час вивантаження на Picasa:
+ Формат зображення
+ З’єднання з Picasa. Будь ласка, зачекайте...
+
+
diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml
new file mode 100644
index 000000000..38601fc93
--- /dev/null
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml
@@ -0,0 +1,14 @@
+
+
+
+ 正在连接到Picasa。请稍后...
+ 配置 Picasa
+ 上传之后
+ 复制链接到剪贴板
+ 图片格式
+ Picasa设置
+ 上传到Picasa时发生错误:
+ 上传到Picasa
+ 图片已成功上传到了Picasa!
+
+
\ No newline at end of file
diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml
new file mode 100644
index 000000000..a818bc748
--- /dev/null
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml
@@ -0,0 +1,14 @@
+
+
+
+ 正在與 Picasa 通訊,請稍候...
+ 組態 Picasa
+ 上傳後
+ 連結到剪貼簿
+ 圖片格式
+ Picasa 設定
+ 上傳到 Picasa 時發生錯誤:
+ 上傳到 Picasa
+ 上傳圖片到 Picasa 成功!
+
+
\ No newline at end of file
diff --git a/GreenshotPicasaPlugin/Picasa.png b/GreenshotPicasaPlugin/Picasa.png
new file mode 100644
index 000000000..97b70cf86
Binary files /dev/null and b/GreenshotPicasaPlugin/Picasa.png differ
diff --git a/GreenshotPicasaPlugin/PicasaConfiguration.cs b/GreenshotPicasaPlugin/PicasaConfiguration.cs
new file mode 100644
index 000000000..17e44efee
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaConfiguration.cs
@@ -0,0 +1,92 @@
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+using System;
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// Description of PicasaConfiguration.
+ ///
+ [IniSection("Picasa", Description = "Greenshot Picasa Plugin configuration")]
+ public class PicasaConfiguration : IniSection {
+ [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
+ public OutputFormat UploadFormat { get; set; }
+
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Picasa link to clipboard.", DefaultValue = "true")]
+ public bool AfterUploadLinkToClipBoard { get; set; }
+ [IniProperty("AddFilename", Description = "Is the filename passed on to Picasa", DefaultValue = "False")]
+ public bool AddFilename {
+ get;
+ set;
+ }
+
+ [IniProperty("UploadUser", Description = "The picasa user to upload to", DefaultValue = "default")]
+ public string UploadUser {
+ get;
+ set;
+ }
+
+ [IniProperty("UploadAlbum", Description = "The picasa album to upload to", DefaultValue = "default")]
+ public string UploadAlbum {
+ get;
+ set;
+ }
+
+ [IniProperty("RefreshToken", Description = "Picasa authorization refresh Token", Encrypted = true)]
+ public string RefreshToken {
+ get;
+ set;
+ }
+
+ ///
+ /// Not stored
+ ///
+ public string AccessToken {
+ get;
+ set;
+ }
+
+ ///
+ /// Not stored
+ ///
+ public DateTimeOffset AccessTokenExpires {
+ get;
+ set;
+ }
+
+ ///
+ /// A form for token
+ ///
+ /// bool true if OK was pressed, false if cancel
+ public bool ShowConfigDialog() {
+ DialogResult result = new SettingsForm().ShowDialog();
+ if (result == DialogResult.OK) {
+ return true;
+ }
+ return false;
+ }
+
+ }
+}
diff --git a/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template b/GreenshotPicasaPlugin/PicasaCredentials.cs
similarity index 75%
rename from src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template
rename to GreenshotPicasaPlugin/PicasaCredentials.cs
index c4ff6bfc6..4389bed86 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template
+++ b/GreenshotPicasaPlugin/PicasaCredentials.cs
@@ -1,31 +1,31 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-namespace Greenshot.Plugin.GooglePhotos {
- ///
- /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
- /// You can set your own values here
- ///
- public static class GooglePhotosCredentials {
- public static string ClientId = "${GooglePhotos_ClientId}";
- public static string ClientSecret = "${GooglePhotos_ClientSecret}";
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration.
+ /// You can set your own values here
+ ///
+ public static class PicasaCredentials {
+ public static string ClientId = "@credentials_picasa_consumer_key@";
+ public static string ClientSecret = "@credentials_picasa_consumer_secret@";
+ }
+}
diff --git a/GreenshotPicasaPlugin/PicasaDestination.cs b/GreenshotPicasaPlugin/PicasaDestination.cs
new file mode 100644
index 000000000..cb2206f13
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaDestination.cs
@@ -0,0 +1,55 @@
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPicasaPlugin {
+ public class PicasaDestination : AbstractDestination {
+ private readonly PicasaPlugin _plugin;
+ public PicasaDestination(PicasaPlugin plugin) {
+ _plugin = plugin;
+ }
+
+ public override string Designation => "Picasa";
+
+ public override string Description => Language.GetString("picasa", LangKey.upload_menu_item);
+
+ public override Image DisplayIcon {
+ get {
+ ComponentResourceManager resources = new ComponentResourceManager(typeof(PicasaPlugin));
+ return (Image)resources.GetObject("Picasa");
+ }
+ }
+
+ public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, out uploadUrl);
+ if (uploaded) {
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = uploadUrl;
+ }
+ ProcessExport(exportInformation, surface);
+ return exportInformation;
+ }
+ }
+}
diff --git a/GreenshotPicasaPlugin/PicasaPlugin.cs b/GreenshotPicasaPlugin/PicasaPlugin.cs
new file mode 100644
index 000000000..76bd80250
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaPlugin.cs
@@ -0,0 +1,139 @@
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// This is the Picasa base code
+ ///
+ public class PicasaPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PicasaPlugin));
+ private static PicasaConfiguration _config;
+ public static PluginAttribute Attributes;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInRoot;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Dispose();
+ _itemPlugInRoot = null;
+ }
+ }
+ }
+
+ public IEnumerable Destinations() {
+ yield return new PicasaDestination(this);
+ }
+
+
+ public IEnumerable Processors() {
+ yield break;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
+ public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ _host = pluginHost;
+ Attributes = myAttributes;
+
+ // Get configuration
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(PicasaPlugin));
+
+ _itemPlugInRoot = new ToolStripMenuItem
+ {
+ Text = Language.GetString("picasa", LangKey.Configure),
+ Tag = _host,
+ Image = (Image) _resources.GetObject("Picasa")
+ };
+ _itemPlugInRoot.Click += ConfigMenuClick;
+ PluginUtils.AddToContextMenu(_host, _itemPlugInRoot);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Text = Language.GetString("picasa", LangKey.Configure);
+ }
+ }
+
+ public virtual void Shutdown() {
+ Log.Debug("Picasa Plugin shutdown.");
+ Language.LanguageChanged -= OnLanguageChanged;
+ //host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened);
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public virtual void Configure() {
+ _config.ShowConfigDialog();
+ }
+
+ public void ConfigMenuClick(object sender, EventArgs eventArgs) {
+ Configure();
+ }
+
+ public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality);
+ try {
+ string url = null;
+ new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("picasa", LangKey.communication_wait),
+ delegate
+ {
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
+ url = PicasaUtils.UploadToPicasa(surfaceToUpload, outputSettings, captureDetails.Title, filename);
+ }
+ );
+ uploadUrl = url;
+
+ if (uploadUrl != null && _config.AfterUploadLinkToClipBoard) {
+ ClipboardHelper.SetClipboardData(uploadUrl);
+ }
+ return true;
+ } catch (Exception e) {
+ Log.Error("Error uploading.", e);
+ MessageBox.Show(Language.GetString("picasa", LangKey.upload_failure) + " " + e.Message);
+ }
+ uploadUrl = null;
+ return false;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.resx b/GreenshotPicasaPlugin/PicasaPlugin.resx
similarity index 93%
rename from src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.resx
rename to GreenshotPicasaPlugin/PicasaPlugin.resx
index 240e4a53e..6fa560f9e 100644
--- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.resx
+++ b/GreenshotPicasaPlugin/PicasaPlugin.resx
@@ -112,13 +112,13 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- GooglePhotos.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ picasa.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
\ No newline at end of file
diff --git a/GreenshotPicasaPlugin/PicasaUtils.cs b/GreenshotPicasaPlugin/PicasaUtils.cs
new file mode 100644
index 000000000..39519915c
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaUtils.cs
@@ -0,0 +1,118 @@
+/*
+ * A Picasa Plugin for Greenshot
+ * Copyright (C) 2011 Francis Noel
+ *
+ * For more information see: http://getgreenshot.org/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using System;
+using System.Xml;
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// Description of PicasaUtils.
+ ///
+ public static class PicasaUtils {
+ private const string PicasaScope = "https://picasaweb.google.com/data/";
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PicasaUtils));
+ private static readonly PicasaConfiguration Config = IniConfig.GetIniSection();
+ private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" + PicasaScope;
+ private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token";
+ private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}";
+
+ ///
+ /// Do the actual upload to Picasa
+ ///
+ /// Image to upload
+ ///
+ ///
+ ///
+ /// PicasaResponse
+ public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
+ // Fill the OAuth2Settings
+ var settings = new OAuth2Settings
+ {
+ AuthUrlPattern = AuthUrl,
+ TokenUrl = TokenUrl,
+ CloudServiceName = "Picasa",
+ ClientId = PicasaCredentials.ClientId,
+ ClientSecret = PicasaCredentials.ClientSecret,
+ AuthorizeMode = OAuth2AuthorizeMode.LocalServer,
+ RefreshToken = Config.RefreshToken,
+ AccessToken = Config.AccessToken,
+ AccessTokenExpires = Config.AccessTokenExpires
+ };
+
+ // Copy the settings from the config, which is kept in memory and on the disk
+
+ try {
+ var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings);
+ if (Config.AddFilename) {
+ webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename));
+ }
+ SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+ container.Upload(webRequest);
+
+ string response = NetworkHelper.GetResponseAsString(webRequest);
+
+ return ParseResponse(response);
+ } finally {
+ // Copy the settings back to the config, so they are stored.
+ Config.RefreshToken = settings.RefreshToken;
+ Config.AccessToken = settings.AccessToken;
+ Config.AccessTokenExpires = settings.AccessTokenExpires;
+ Config.IsDirty = true;
+ IniConfig.Save();
+ }
+ }
+
+ ///
+ /// Parse the upload URL from the response
+ ///
+ ///
+ ///
+ public static string ParseResponse(string response) {
+ if (response == null) {
+ return null;
+ }
+ try {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(response);
+ XmlNodeList nodes = doc.GetElementsByTagName("link", "*");
+ if(nodes.Count > 0) {
+ string url = null;
+ foreach(XmlNode node in nodes) {
+ if (node.Attributes != null) {
+ url = node.Attributes["href"].Value;
+ string rel = node.Attributes["rel"].Value;
+ // Pictures with rel="http://schemas.google.com/photos/2007#canonical" are the direct link
+ if (rel != null && rel.EndsWith("canonical")) {
+ break;
+ }
+ }
+ }
+ return url;
+ }
+ } catch(Exception e) {
+ Log.ErrorFormat("Could not parse Picasa response due to error {0}, response was: {1}", e.Message, response);
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Confluence/Properties/AssemblyInfo.cs b/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs
similarity index 54%
rename from src/Greenshot.Plugin.Confluence/Properties/AssemblyInfo.cs
rename to GreenshotPicasaPlugin/Properties/AssemblyInfo.cs
index 8d2833e17..350c36fe0 100644
--- a/src/Greenshot.Plugin.Confluence/Properties/AssemblyInfo.cs
+++ b/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs
@@ -1,8 +1,8 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
- * For more information see: https://getgreenshot.org/
+ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,32 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * along with this program. If not, see .
*/
+using Greenshot.Plugin;
using System.Reflection;
using System.Runtime.InteropServices;
-using Greenshot.Base.Interfaces.Plugin;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyDescription("A plugin to upload images to Confluence")]
-[assembly: AssemblyPluginIdentifier("Confluence Plugin")]
+[assembly: AssemblyTitle("Greenshot-Picasa-Plugin")]
+[assembly: AssemblyDescription("A plugin to upload images to Picasa")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot & F. Noel")]
+[assembly: AssemblyProduct("Picasa-Web Plugin")]
+[assembly: AssemblyCopyright("Copyright (C) 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The PluginAttribute describes the "entryType" and if the plugin is configurable
+[assembly: PluginAttribute("GreenshotPicasaPlugin.PicasaPlugin", true)]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
\ No newline at end of file
+[assembly: ComVisible(false)]
+
+// The assembly version, replaced by build scripts
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyInformationalVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/src/Greenshot.Plugin.GooglePhotos/README b/GreenshotPicasaPlugin/README
similarity index 100%
rename from src/Greenshot.Plugin.GooglePhotos/README
rename to GreenshotPicasaPlugin/README
diff --git a/GreenshotPlugin/Controls/AnimatingForm.cs b/GreenshotPlugin/Controls/AnimatingForm.cs
new file mode 100644
index 000000000..db6fc8c59
--- /dev/null
+++ b/GreenshotPlugin/Controls/AnimatingForm.cs
@@ -0,0 +1,127 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Windows.Forms;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Extend this Form to have the possibility for animations on your form
+ ///
+ public class AnimatingForm : GreenshotForm {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(AnimatingForm));
+ private const int DEFAULT_VREFRESH = 60;
+ private int _vRefresh;
+ private Timer _timer;
+
+ ///
+ /// This flag specifies if any animation is used
+ ///
+ protected bool EnableAnimation {
+ get;
+ set;
+ }
+
+ ///
+ /// Vertical Refresh Rate
+ ///
+ protected int VRefresh {
+ get {
+ if (_vRefresh == 0) {
+ // get te hDC of the desktop to get the VREFRESH
+ using (SafeWindowDcHandle desktopHandle = SafeWindowDcHandle.FromDesktop()) {
+ _vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
+ }
+ }
+ // A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
+ // As there is currently no know way to get the default, we guess it.
+ if (_vRefresh <= 1) {
+ _vRefresh = DEFAULT_VREFRESH;
+ }
+ return _vRefresh;
+ }
+ }
+
+ ///
+ /// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections
+ ///
+ protected bool IsTerminalServerSession => !coreConfiguration.DisableRDPOptimizing && (coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession);
+
+ ///
+ /// Calculate the amount of frames that an animation takes
+ ///
+ ///
+ /// Number of frames, 1 if in Terminal Server Session
+ protected int FramesForMillis(int milliseconds) {
+ // If we are in a Terminal Server Session we return 1
+ if (IsTerminalServerSession) {
+ return 1;
+ }
+ return milliseconds / VRefresh;
+ }
+
+ ///
+ /// Initialize the animation
+ ///
+ protected AnimatingForm() {
+ Load += delegate {
+ if (!EnableAnimation)
+ {
+ return;
+ }
+ _timer = new Timer
+ {
+ Interval = 1000/VRefresh
+ };
+ _timer.Tick += timer_Tick;
+ _timer.Start();
+ };
+
+ // Unregister at close
+ FormClosing += delegate
+ {
+ _timer?.Stop();
+ };
+ }
+
+ ///
+ /// The tick handler initiates the animation.
+ ///
+ ///
+ ///
+ private void timer_Tick(object sender, EventArgs e) {
+ try {
+ Animate();
+ } catch (Exception ex) {
+ Log.Warn("An exception occured while animating:", ex);
+ }
+ }
+
+ ///
+ /// This method will be called every frame, so implement your animation/redraw logic here.
+ ///
+ protected virtual void Animate() {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Greenshot.Base/Controls/BackgroundForm.Designer.cs b/GreenshotPlugin/Controls/BackgroundForm.Designer.cs
similarity index 86%
rename from src/Greenshot.Base/Controls/BackgroundForm.Designer.cs
rename to GreenshotPlugin/Controls/BackgroundForm.Designer.cs
index 331dedd48..382b469ac 100644
--- a/src/Greenshot.Base/Controls/BackgroundForm.Designer.cs
+++ b/GreenshotPlugin/Controls/BackgroundForm.Designer.cs
@@ -1,96 +1,98 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-namespace Greenshot.Base.Controls
-{
- partial class BackgroundForm
- {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent()
- {
- this.components = new System.ComponentModel.Container();
- this.label_pleasewait = new System.Windows.Forms.Label();
- this.timer_checkforclose = new System.Windows.Forms.Timer(this.components);
- this.SuspendLayout();
- //
- // label_pleasewait
- //
- this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
- this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
- this.label_pleasewait.Name = "label_pleasewait";
- this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
- this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
- this.label_pleasewait.TabIndex = 0;
- this.label_pleasewait.Text = "Please wait...";
- this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
- this.label_pleasewait.UseWaitCursor = true;
- //
- // timer_checkforclose
- //
- this.timer_checkforclose.Interval = 200;
- this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick);
- //
- // BackgroundForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(169, 52);
- this.ControlBox = true;
- this.Controls.Add(this.label_pleasewait);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "BackgroundForm";
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Greenshot";
- this.TopMost = true;
- this.UseWaitCursor = true;
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing);
- this.ResumeLayout(false);
- this.PerformLayout();
- }
- private System.Windows.Forms.Timer timer_checkforclose;
- private System.Windows.Forms.Label label_pleasewait;
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotPlugin.Controls
+{
+ partial class BackgroundForm
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.label_pleasewait = new System.Windows.Forms.Label();
+ this.timer_checkforclose = new System.Windows.Forms.Timer(this.components);
+ this.SuspendLayout();
+ //
+ // label_pleasewait
+ //
+ this.label_pleasewait.AutoSize = true;
+ this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
+ this.label_pleasewait.Name = "label_pleasewait";
+ this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
+ this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
+ this.label_pleasewait.TabIndex = 0;
+ this.label_pleasewait.Text = "Please wait...";
+ this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.label_pleasewait.UseWaitCursor = true;
+ //
+ // timer_checkforclose
+ //
+ this.timer_checkforclose.Interval = 200;
+ this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick);
+ //
+ // BackgroundForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoSize = true;
+ this.ClientSize = new System.Drawing.Size(169, 52);
+ this.ControlBox = true;
+ this.Controls.Add(this.label_pleasewait);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "BackgroundForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Greenshot";
+ this.TopMost = true;
+ this.UseWaitCursor = true;
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+ }
+ private System.Windows.Forms.Timer timer_checkforclose;
+ private System.Windows.Forms.Label label_pleasewait;
+ }
+}
diff --git a/GreenshotPlugin/Controls/BackgroundForm.cs b/GreenshotPlugin/Controls/BackgroundForm.cs
new file mode 100644
index 000000000..59fe024e3
--- /dev/null
+++ b/GreenshotPlugin/Controls/BackgroundForm.cs
@@ -0,0 +1,100 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Threading;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Description of PleaseWaitForm.
+ ///
+ public sealed partial class BackgroundForm : Form {
+ private volatile bool _shouldClose;
+
+ private void BackgroundShowDialog() {
+ ShowDialog();
+ }
+
+ public static BackgroundForm ShowAndWait(string title, string text) {
+ BackgroundForm backgroundForm = new BackgroundForm(title, text);
+ // Show form in background thread
+ Thread backgroundTask = new Thread (backgroundForm.BackgroundShowDialog);
+ backgroundForm.Name = "Background form";
+ backgroundTask.IsBackground = true;
+ backgroundTask.SetApartmentState(ApartmentState.STA);
+ backgroundTask.Start();
+ return backgroundForm;
+ }
+
+ public BackgroundForm(string title, string text){
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ Icon = GreenshotResources.getGreenshotIcon();
+ _shouldClose = false;
+ Text = title;
+ label_pleasewait.Text = text;
+ FormClosing += PreventFormClose;
+ timer_checkforclose.Start();
+ }
+
+ // Can be used instead of ShowDialog
+ public new void Show() {
+ base.Show();
+ bool positioned = false;
+ foreach(Screen screen in Screen.AllScreens) {
+ if (screen.Bounds.Contains(Cursor.Position)) {
+ positioned = true;
+ Location = new Point(screen.Bounds.X + (screen.Bounds.Width / 2) - (Width / 2), screen.Bounds.Y + (screen.Bounds.Height / 2) - (Height / 2));
+ break;
+ }
+ }
+ if (!positioned) {
+ Location = new Point(Cursor.Position.X - Width / 2, Cursor.Position.Y - Height / 2);
+ }
+ }
+
+ private void PreventFormClose(object sender, FormClosingEventArgs e) {
+ if(!_shouldClose) {
+ e.Cancel = true;
+ }
+ }
+
+ private void Timer_checkforcloseTick(object sender, EventArgs e) {
+ if (_shouldClose) {
+ timer_checkforclose.Stop();
+ BeginInvoke(new EventHandler( delegate {Close();}));
+ }
+ }
+
+ public void CloseDialog() {
+ _shouldClose = true;
+ Application.DoEvents();
+ }
+
+ private void BackgroundFormFormClosing(object sender, FormClosingEventArgs e) {
+ timer_checkforclose.Stop();
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/ExtendedWebBrowser.cs b/GreenshotPlugin/Controls/ExtendedWebBrowser.cs
new file mode 100644
index 000000000..6a0d52418
--- /dev/null
+++ b/GreenshotPlugin/Controls/ExtendedWebBrowser.cs
@@ -0,0 +1,63 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using GreenshotInterop.Interop;
+
+namespace GreenshotPlugin.Controls {
+ public class ExtendedWebBrowser : WebBrowser {
+ protected class ExtendedWebBrowserSite : WebBrowserSite, IOleCommandTarget {
+ private const int OLECMDID_SHOWSCRIPTERROR = 40;
+ private const int OLECMDID_SHOWMESSAGE = 41;
+
+ private static readonly Guid CGID_DocHostCommandHandler = new Guid("F38BC242-B950-11D1-8918-00C04FC2C836");
+
+ private const int S_OK = 0;
+ private const int OLECMDERR_E_NOTSUPPORTED = (-2147221248);
+ private const int OLECMDERR_E_UNKNOWNGROUP = (-2147221244);
+
+ public ExtendedWebBrowserSite(WebBrowser wb) : base(wb) {
+ }
+
+ #region IOleCommandTarget Members
+ public int QueryStatus(Guid pguidCmdGroup, int cCmds, IntPtr prgCmds, IntPtr pCmdText) {
+ return OLECMDERR_E_NOTSUPPORTED;
+ }
+
+ public int Exec(Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
+ if (pguidCmdGroup == CGID_DocHostCommandHandler) {
+ if (nCmdID == OLECMDID_SHOWSCRIPTERROR) {
+ // do not need to alter pvaOut as the docs says, enough to return S_OK here
+ return S_OK;
+ }
+ }
+
+ return OLECMDERR_E_NOTSUPPORTED;
+ }
+
+ #endregion
+ }
+
+ protected override WebBrowserSiteBase CreateWebBrowserSiteBase() {
+ return new ExtendedWebBrowserSite(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Greenshot.Base/Controls/FormWithoutActivation.cs b/GreenshotPlugin/Controls/FormWithoutActivation.cs
similarity index 72%
rename from src/Greenshot.Base/Controls/FormWithoutActivation.cs
rename to GreenshotPlugin/Controls/FormWithoutActivation.cs
index 0a69bc043..86e1eac91 100644
--- a/src/Greenshot.Base/Controls/FormWithoutActivation.cs
+++ b/GreenshotPlugin/Controls/FormWithoutActivation.cs
@@ -1,36 +1,33 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using System.Windows.Forms;
-
-namespace Greenshot.Base.Controls
-{
- ///
- /// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
- ///
- public class FormWithoutActivation : Form
- {
- protected override bool ShowWithoutActivation
- {
- get { return true; }
- }
- }
-}
\ No newline at end of file
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
+ ///
+ public class FormWithoutActivation : Form {
+ protected override bool ShowWithoutActivation {
+ get { return true; }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotButton.cs b/GreenshotPlugin/Controls/GreenshotButton.cs
new file mode 100644
index 000000000..223bd68c4
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotButton.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotButton : Button, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotCheckBox.cs b/GreenshotPlugin/Controls/GreenshotCheckBox.cs
new file mode 100644
index 000000000..58f61787c
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotCheckBox.cs
@@ -0,0 +1,45 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Description of GreenshotCheckbox.
+ ///
+ public class GreenshotCheckBox : CheckBox, IGreenshotLanguageBindable, IGreenshotConfigBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
+ public string SectionName { get; set; } = "Core";
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
+ public string PropertyName {
+ get;
+ set;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Controls/GreenshotColumnSorter.cs b/GreenshotPlugin/Controls/GreenshotColumnSorter.cs
new file mode 100644
index 000000000..4ebf2f521
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotColumnSorter.cs
@@ -0,0 +1,118 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.Collections;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// This class is an implementation of the 'IComparer' interface.
+ ///
+ public class GreenshotColumnSorter : IComparer {
+ ///
+ /// Specifies the column to be sorted
+ ///
+ private int _columnToSort;
+ ///
+ /// Specifies the order in which to sort (i.e. 'Ascending').
+ ///
+ private SortOrder _orderOfSort;
+ ///
+ /// Case insensitive comparer object
+ ///
+ private readonly CaseInsensitiveComparer _objectCompare;
+
+ ///
+ /// Class constructor. Initializes various elements
+ ///
+ public GreenshotColumnSorter() {
+ // Initialize the column to '0'
+ _columnToSort = 0;
+
+ // Initialize the sort order to 'none'
+ _orderOfSort = SortOrder.None;
+
+ // Initialize the CaseInsensitiveComparer object
+ _objectCompare = new CaseInsensitiveComparer();
+ }
+
+ ///
+ /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
+ ///
+ /// First object to be compared
+ /// Second object to be compared
+ /// The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'
+ public int Compare(object x, object y) {
+ if (x == null && y == null) {
+ return 0;
+ }
+ if (x == null) {
+ return -1;
+ }
+ if (y == null) {
+ return 1;
+ }
+ // Cast the objects to be compared to ListViewItem objects
+ var listviewX = (ListViewItem)x;
+ var listviewY = (ListViewItem)y;
+
+ // Compare the two items
+ var compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, listviewY.SubItems[_columnToSort].Text);
+
+ // Calculate correct return value based on object comparison
+ if (_orderOfSort == SortOrder.Ascending) {
+ // Ascending sort is selected, return normal result of compare operation
+ return compareResult;
+ }
+ if (_orderOfSort == SortOrder.Descending) {
+ // Descending sort is selected, return negative result of compare operation
+ return -compareResult;
+ }
+ // Return '0' to indicate they are equal
+ return 0;
+ }
+
+ ///
+ /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
+ ///
+ public int SortColumn {
+ set {
+ _columnToSort = value;
+ }
+ get {
+ return _columnToSort;
+ }
+ }
+
+ ///
+ /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
+ ///
+ public SortOrder Order {
+ set {
+ _orderOfSort = value;
+ }
+ get {
+ return _orderOfSort;
+ }
+ }
+ }
+}
+
+
diff --git a/GreenshotPlugin/Controls/GreenshotComboBox.cs b/GreenshotPlugin/Controls/GreenshotComboBox.cs
new file mode 100644
index 000000000..262309410
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotComboBox.cs
@@ -0,0 +1,104 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotComboBox : ComboBox, IGreenshotConfigBindable {
+ private Type _enumType;
+ private Enum _selectedEnum;
+
+ [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
+ public string SectionName { get; set; } = "Core";
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
+ public string PropertyName {
+ get;
+ set;
+ }
+
+ public GreenshotComboBox() {
+ SelectedIndexChanged += delegate {
+ StoreSelectedEnum();
+ };
+ }
+
+ public void SetValue(Enum currentValue) {
+ if (currentValue != null) {
+ _selectedEnum = currentValue;
+ SelectedItem = Language.Translate(currentValue);
+ }
+ }
+
+ ///
+ /// This is a method to popululate the ComboBox
+ /// with the items from the enumeration
+ ///
+ /// TEnum to populate with
+ public void Populate(Type enumType) {
+ // Store the enum-type, so we can work with it
+ _enumType = enumType;
+
+ var availableValues = Enum.GetValues(enumType);
+ Items.Clear();
+ foreach (var enumValue in availableValues) {
+ Items.Add(Language.Translate((Enum)enumValue));
+ }
+ }
+
+ ///
+ /// Store the selected value internally
+ ///
+ private void StoreSelectedEnum() {
+ string enumTypeName = _enumType.Name;
+ string selectedValue = SelectedItem as string;
+ var availableValues = Enum.GetValues(_enumType);
+ object returnValue = null;
+
+ try {
+ returnValue = Enum.Parse(_enumType, selectedValue);
+ } catch (Exception) {
+ // Ignore
+ }
+
+ foreach (Enum enumValue in availableValues) {
+ string enumKey = enumTypeName + "." + enumValue;
+ if (Language.HasKey(enumKey)) {
+ string translation = Language.GetString(enumTypeName + "." + enumValue);
+ if (translation.Equals(selectedValue)) {
+ returnValue = enumValue;
+ }
+ }
+ }
+ _selectedEnum = (Enum)returnValue;
+ }
+
+ ///
+ /// Get the selected enum value from the combobox, uses generics
+ ///
+ /// The enum value of the combobox
+ public Enum GetSelectedEnum() {
+ return _selectedEnum;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotForm.cs b/GreenshotPlugin/Controls/GreenshotForm.cs
new file mode 100644
index 000000000..e30f7e674
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotForm.cs
@@ -0,0 +1,547 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using System.Reflection;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.IO;
+using log4net;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// This form is used for automatically binding the elements of the form to the language
+ ///
+ public class GreenshotForm : Form, IGreenshotLanguageBindable {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(GreenshotForm));
+ protected static CoreConfiguration coreConfiguration;
+ private static readonly IDictionary reflectionCache = new Dictionary();
+ private IComponentChangeService m_changeService;
+ private bool _isDesignModeLanguageSet;
+ private bool _applyLanguageManually;
+ private bool _storeFieldsManually;
+ private IDictionary _designTimeControls;
+ private IDictionary _designTimeToolStripItems;
+
+ static GreenshotForm() {
+ if (!IsInDesignMode) {
+ coreConfiguration = IniConfig.GetIniSection();
+ }
+ }
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ ///
+ /// Used to check the designmode during a constructor
+ ///
+ ///
+ protected static bool IsInDesignMode {
+ get {
+ return (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1) || (Application.ExecutablePath.IndexOf("sharpdevelop.exe", StringComparison.OrdinalIgnoreCase) > -1 || (Application.ExecutablePath.IndexOf("wdexpress.exe", StringComparison.OrdinalIgnoreCase) > -1));
+ }
+ }
+
+ protected bool ManualLanguageApply {
+ get {
+ return _applyLanguageManually;
+ }
+ set {
+ _applyLanguageManually = value;
+ }
+ }
+
+ protected bool ManualStoreFields {
+ get {
+ return _storeFieldsManually;
+ }
+ set {
+ _storeFieldsManually = value;
+ }
+ }
+
+ ///
+ /// When this is set, the form will be brought to the foreground as soon as it is shown.
+ ///
+ protected bool ToFront {
+ get;
+ set;
+ }
+
+ ///
+ /// Code to initialize the language etc during design time
+ ///
+ protected void InitializeForDesigner() {
+ if (DesignMode) {
+ _designTimeControls = new Dictionary();
+ _designTimeToolStripItems = new Dictionary();
+ try {
+ ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
+
+ // Add a hard-path if you are using SharpDevelop
+ // Language.AddLanguageFilePath(@"C:\Greenshot\Greenshot\Languages");
+
+ // this "type"
+ Assembly currentAssembly = GetType().Assembly;
+ if (typeResService != null)
+ {
+ string assemblyPath = typeResService.GetPathOfAssembly(currentAssembly.GetName());
+ string assemblyDirectory = Path.GetDirectoryName(assemblyPath);
+ if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Greenshot\Languages\"))) {
+ Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Greenshot\Languages\"));
+ }
+ if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Languages\"))) {
+ Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Languages\"));
+ }
+ }
+ } catch (Exception ex) {
+ MessageBox.Show(ex.Message);
+ }
+ }
+ }
+
+ ///
+ /// This override is only for the design-time of the form
+ ///
+ ///
+ protected override void OnPaint(PaintEventArgs e) {
+ if (DesignMode) {
+ if (!_isDesignModeLanguageSet) {
+ _isDesignModeLanguageSet = true;
+ try {
+ ApplyLanguage();
+ }
+ catch (Exception)
+ {
+ // ignored
+ }
+ }
+ }
+ base.OnPaint(e);
+ }
+
+ protected override void OnLoad(EventArgs e) {
+ // Every GreenshotForm should have it's default icon
+ // And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important
+ Icon = GreenshotResources.getGreenshotIcon();
+ if (!DesignMode) {
+ if (!_applyLanguageManually) {
+ ApplyLanguage();
+ }
+ FillFields();
+ base.OnLoad(e);
+ } else {
+ LOG.Info("OnLoad called from designer.");
+ InitializeForDesigner();
+ base.OnLoad(e);
+ ApplyLanguage();
+ }
+ }
+
+ ///
+ /// Make sure the form is visible, if this is wanted
+ ///
+ /// EventArgs
+ protected override void OnShown(EventArgs e) {
+ base.OnShown(e);
+ if (ToFront) {
+ WindowDetails.ToForeground(Handle);
+ }
+ }
+
+ ///
+ /// check if the form was closed with an OK, if so store the values in the GreenshotControls
+ ///
+ ///
+ protected override void OnClosed(EventArgs e) {
+ if (!DesignMode && !_storeFieldsManually) {
+ if (DialogResult == DialogResult.OK) {
+ LOG.Info("Form was closed with OK: storing field values.");
+ StoreFields();
+ }
+ }
+ base.OnClosed(e);
+ }
+
+ ///
+ /// This override allows the control to register event handlers for IComponentChangeService events
+ /// at the time the control is sited, which happens only in design mode.
+ ///
+ public override ISite Site {
+ get {
+ return base.Site;
+ }
+ set {
+ // Clear any component change event handlers.
+ ClearChangeNotifications();
+
+ // Set the new Site value.
+ base.Site = value;
+
+ m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
+
+ // Register event handlers for component change events.
+ RegisterChangeNotifications();
+ }
+ }
+
+ private void ClearChangeNotifications() {
+ // The m_changeService value is null when not in design mode,
+ // as the IComponentChangeService is only available at design time.
+ m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
+
+ // Clear our the component change events to prepare for re-siting.
+ if (m_changeService != null) {
+ m_changeService.ComponentChanged -= OnComponentChanged;
+ m_changeService.ComponentAdded -= OnComponentAdded;
+ }
+ }
+
+ private void RegisterChangeNotifications() {
+ // Register the event handlers for the IComponentChangeService events
+ if (m_changeService != null) {
+ m_changeService.ComponentChanged += OnComponentChanged;
+ m_changeService.ComponentAdded += OnComponentAdded;
+ }
+ }
+
+ ///
+ /// This method handles the OnComponentChanged event to display a notification.
+ ///
+ ///
+ ///
+ private void OnComponentChanged(object sender, ComponentChangedEventArgs ce) {
+ if (((IComponent) ce.Component)?.Site != null && ce.Member != null) {
+ if ("LanguageKey".Equals(ce.Member.Name)) {
+ Control control = ce.Component as Control;
+ if (control != null) {
+ LOG.InfoFormat("Changing LanguageKey for {0} to {1}", control.Name, ce.NewValue);
+ ApplyLanguage(control, (string)ce.NewValue);
+ } else {
+ ToolStripItem item = ce.Component as ToolStripItem;
+ if (item != null) {
+ LOG.InfoFormat("Changing LanguageKey for {0} to {1}", item.Name, ce.NewValue);
+ ApplyLanguage(item, (string)ce.NewValue);
+ } else {
+ LOG.InfoFormat("Not possible to changing LanguageKey for {0} to {1}", ce.Component.GetType(), ce.NewValue);
+ }
+ }
+ }
+ }
+ }
+
+ private void OnComponentAdded(object sender, ComponentEventArgs ce) {
+ if (ce.Component?.Site != null) {
+ Control control = ce.Component as Control;
+ if (control != null) {
+ if (!_designTimeControls.ContainsKey(control.Name)) {
+ _designTimeControls.Add(control.Name, control);
+ } else {
+ _designTimeControls[control.Name] = control;
+ }
+ }
+ else
+ {
+ var stripItem = ce.Component as ToolStripItem;
+ if (stripItem != null) {
+ ToolStripItem item = stripItem;
+ if (!_designTimeControls.ContainsKey(item.Name)) {
+ _designTimeToolStripItems.Add(item.Name, item);
+ } else {
+ _designTimeToolStripItems[item.Name] = item;
+ }
+ }
+ }
+ }
+ }
+
+ // Clean up any resources being used.
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ ClearChangeNotifications();
+ }
+ base.Dispose(disposing);
+ }
+
+ protected void ApplyLanguage(ToolStripItem applyTo, string languageKey) {
+ string langString;
+ if (!string.IsNullOrEmpty(languageKey)) {
+ if (!Language.TryGetString(languageKey, out langString)) {
+ LOG.WarnFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name);
+ return;
+ }
+ applyTo.Text = langString;
+ } else {
+ // Fallback to control name!
+ if (Language.TryGetString(applyTo.Name, out langString)) {
+ applyTo.Text = langString;
+ return;
+ }
+ if (!DesignMode) {
+ LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name);
+ }
+ }
+ }
+
+ protected void ApplyLanguage(ToolStripItem applyTo) {
+ IGreenshotLanguageBindable languageBindable = applyTo as IGreenshotLanguageBindable;
+ if (languageBindable != null) {
+ ApplyLanguage(applyTo, languageBindable.LanguageKey);
+ }
+ }
+
+ protected void ApplyLanguage(Control applyTo) {
+ IGreenshotLanguageBindable languageBindable = applyTo as IGreenshotLanguageBindable;
+ if (languageBindable == null) {
+ // check if it's a menu!
+ ToolStrip toolStrip = applyTo as ToolStrip;
+ if (toolStrip == null)
+ {
+ return;
+ }
+ foreach (ToolStripItem item in toolStrip.Items) {
+ ApplyLanguage(item);
+ }
+ return;
+ }
+
+ // Apply language text to the control
+ ApplyLanguage(applyTo, languageBindable.LanguageKey);
+
+ // Repopulate the combox boxes
+ IGreenshotConfigBindable configBindable = applyTo as IGreenshotConfigBindable;
+ GreenshotComboBox comboxBox = applyTo as GreenshotComboBox;
+ if (configBindable != null && comboxBox != null) {
+ if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) {
+ IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
+ if (section != null) {
+ // Only update the language, so get the actual value and than repopulate
+ Enum currentValue = comboxBox.GetSelectedEnum();
+ comboxBox.Populate(section.Values[configBindable.PropertyName].ValueType);
+ comboxBox.SetValue(currentValue);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Helper method to cache the fieldinfo values, so we don't need to reflect all the time!
+ ///
+ ///
+ ///
+ private static FieldInfo[] GetCachedFields(Type typeToGetFieldsFor) {
+ FieldInfo[] fields;
+ if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out fields)) {
+ fields = typeToGetFieldsFor.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ reflectionCache.Add(typeToGetFieldsFor, fields);
+ }
+ return fields;
+ }
+
+ ///
+ /// Apply all the language settings to the "Greenshot" Controls on this form
+ ///
+ protected void ApplyLanguage() {
+ SuspendLayout();
+ try {
+ // Set title of the form
+ string langString;
+ if (!string.IsNullOrEmpty(LanguageKey) && Language.TryGetString(LanguageKey, out langString)) {
+ Text = langString;
+ }
+
+ // Reset the text values for all GreenshotControls
+ foreach (FieldInfo field in GetCachedFields(GetType())) {
+ object controlObject = field.GetValue(this);
+ if (controlObject == null) {
+ LOG.DebugFormat("No value: {0}", field.Name);
+ continue;
+ }
+ Control applyToControl = controlObject as Control;
+ if (applyToControl == null) {
+ ToolStripItem applyToItem = controlObject as ToolStripItem;
+ if (applyToItem == null) {
+ LOG.DebugFormat("No Control or ToolStripItem: {0}", field.Name);
+ continue;
+ }
+ ApplyLanguage(applyToItem);
+ } else {
+ ApplyLanguage(applyToControl);
+ }
+ }
+
+ if (DesignMode) {
+ foreach (Control designControl in _designTimeControls.Values) {
+ ApplyLanguage(designControl);
+ }
+ foreach (ToolStripItem designToolStripItem in _designTimeToolStripItems.Values) {
+ ApplyLanguage(designToolStripItem);
+ }
+ }
+ } finally {
+ ResumeLayout();
+ }
+ }
+
+ ///
+ /// Apply the language text to supplied control
+ ///
+ protected void ApplyLanguage(Control applyTo, string languageKey) {
+ string langString;
+ if (!string.IsNullOrEmpty(languageKey)) {
+ if (!Language.TryGetString(languageKey, out langString)) {
+ LOG.WarnFormat("Wrong language key '{0}' configured for control '{1}'", languageKey, applyTo.Name);
+ return;
+ }
+ applyTo.Text = langString;
+ } else {
+ // Fallback to control name!
+ if (Language.TryGetString(applyTo.Name, out langString)) {
+ applyTo.Text = langString;
+ return;
+ }
+ if (!DesignMode) {
+ LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name);
+ }
+ }
+ }
+
+ ///
+ /// Fill all GreenshotControls with the values from the configuration
+ ///
+ protected void FillFields() {
+ foreach (FieldInfo field in GetCachedFields(GetType())) {
+ var controlObject = field.GetValue(this);
+ IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable;
+ if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) {
+ IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
+ if (section != null) {
+ IniValue iniValue;
+ if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) {
+ LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'",configBindable.PropertyName,field.Name);
+ continue;
+ }
+
+ CheckBox checkBox = controlObject as CheckBox;
+ if (checkBox != null) {
+ checkBox.Checked = (bool)iniValue.Value;
+ checkBox.Enabled = !iniValue.IsFixed;
+ continue;
+ }
+ RadioButton radíoButton = controlObject as RadioButton;
+ if (radíoButton != null) {
+ radíoButton.Checked = (bool)iniValue.Value;
+ radíoButton.Enabled = !iniValue.IsFixed;
+ continue;
+ }
+
+ TextBox textBox = controlObject as TextBox;
+ if (textBox != null) {
+ HotkeyControl hotkeyControl = controlObject as HotkeyControl;
+ if (hotkeyControl != null) {
+ string hotkeyValue = (string)iniValue.Value;
+ if (!string.IsNullOrEmpty(hotkeyValue)) {
+ hotkeyControl.SetHotkey(hotkeyValue);
+ hotkeyControl.Enabled = !iniValue.IsFixed;
+ }
+ continue;
+ }
+ textBox.Text = iniValue.ToString();
+ textBox.Enabled = !iniValue.IsFixed;
+ continue;
+ }
+
+ GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
+ if (comboxBox != null) {
+ comboxBox.Populate(iniValue.ValueType);
+ comboxBox.SetValue((Enum)iniValue.Value);
+ comboxBox.Enabled = !iniValue.IsFixed;
+ }
+ }
+ }
+ }
+ OnFieldsFilled();
+ }
+
+ protected virtual void OnFieldsFilled() {
+ }
+
+ ///
+ /// Store all GreenshotControl values to the configuration
+ ///
+ protected void StoreFields() {
+ bool iniDirty = false;
+ foreach (FieldInfo field in GetCachedFields(GetType())) {
+ var controlObject = field.GetValue(this);
+ IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable;
+
+ if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) {
+ IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
+ if (section != null) {
+ IniValue iniValue;
+ if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue)) {
+ continue;
+ }
+ CheckBox checkBox = controlObject as CheckBox;
+ if (checkBox != null) {
+ iniValue.Value = checkBox.Checked;
+ iniDirty = true;
+ continue;
+ }
+ RadioButton radioButton = controlObject as RadioButton;
+ if (radioButton != null) {
+ iniValue.Value = radioButton.Checked;
+ iniDirty = true;
+ continue;
+ }
+ TextBox textBox = controlObject as TextBox;
+ if (textBox != null) {
+ HotkeyControl hotkeyControl = controlObject as HotkeyControl;
+ if (hotkeyControl != null) {
+ iniValue.Value = hotkeyControl.ToString();
+ iniDirty = true;
+ continue;
+ }
+ iniValue.UseValueOrDefault(textBox.Text);
+ iniDirty = true;
+ continue;
+ }
+ GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
+ if (comboxBox != null) {
+ iniValue.Value = comboxBox.GetSelectedEnum();
+ iniDirty = true;
+ }
+
+ }
+ }
+ }
+ if (iniDirty) {
+ IniConfig.Save();
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotGroupBox.cs b/GreenshotPlugin/Controls/GreenshotGroupBox.cs
new file mode 100644
index 000000000..33bb86073
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotGroupBox.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotGroupBox : GroupBox , IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotLabel.cs b/GreenshotPlugin/Controls/GreenshotLabel.cs
new file mode 100644
index 000000000..94620faf3
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotLabel.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotLabel : Label, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotRadioButton.cs b/GreenshotPlugin/Controls/GreenshotRadioButton.cs
new file mode 100644
index 000000000..010378da2
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotRadioButton.cs
@@ -0,0 +1,45 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Description of GreenshotCheckbox.
+ ///
+ public class GreenshotRadioButton : RadioButton, IGreenshotLanguageBindable, IGreenshotConfigBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+
+ [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
+ public string SectionName { get; set; } = "Core";
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
+ public string PropertyName {
+ get;
+ set;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Controls/GreenshotTabPage.cs b/GreenshotPlugin/Controls/GreenshotTabPage.cs
new file mode 100644
index 000000000..09081cc0c
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotTabPage.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotTabPage : TabPage, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotTextBox.cs b/GreenshotPlugin/Controls/GreenshotTextBox.cs
new file mode 100644
index 000000000..85e52492d
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotTextBox.cs
@@ -0,0 +1,36 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotTextBox : TextBox, IGreenshotConfigBindable {
+ [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
+ public string SectionName { get; set; } = "Core";
+
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
+ public string PropertyName {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs b/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs
new file mode 100644
index 000000000..d333e2a65
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotToolStripDropDownButton : ToolStripDropDownButton, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotToolStripButton.cs b/GreenshotPlugin/Controls/GreenshotToolStripButton.cs
new file mode 100644
index 000000000..696f7eb4e
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripButton.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotToolStripButton : ToolStripButton, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs b/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs
new file mode 100644
index 000000000..32c0e6238
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotToolStripLabel : ToolStripLabel, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs b/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs
new file mode 100644
index 000000000..c780a4ef3
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs
@@ -0,0 +1,33 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Controls {
+ public class GreenshotToolStripMenuItem : ToolStripMenuItem, IGreenshotLanguageBindable {
+ [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
+ public string LanguageKey {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/HotkeyControl.cs b/GreenshotPlugin/Controls/HotkeyControl.cs
new file mode 100644
index 000000000..590f6090a
--- /dev/null
+++ b/GreenshotPlugin/Controls/HotkeyControl.cs
@@ -0,0 +1,582 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+
+using Greenshot.Plugin;
+using log4net;
+using GreenshotPlugin.Core;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// A simple control that allows the user to select pretty much any valid hotkey combination
+ /// See: http://www.codeproject.com/KB/buttons/hotkeycontrol.aspx
+ /// But is modified to fit in Greenshot, and have localized support
+ ///
+ public sealed class HotkeyControl : GreenshotTextBox {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(HotkeyControl));
+
+ private static readonly EventDelay EventDelay = new EventDelay(TimeSpan.FromMilliseconds(600).Ticks);
+ private static readonly bool IsWindows7OrOlder = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1;
+
+ // Holds the list of hotkeys
+ private static readonly IDictionary KeyHandlers = new Dictionary();
+ private static int _hotKeyCounter = 1;
+ private const uint WM_HOTKEY = 0x312;
+ private static IntPtr _hotkeyHwnd;
+
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ public enum Modifiers : uint {
+ NONE = 0,
+ ALT = 1,
+ CTRL = 2,
+ SHIFT = 4,
+ WIN = 8,
+ NO_REPEAT = 0x4000
+ }
+
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ private enum MapType : uint {
+ MAPVK_VK_TO_VSC = 0, //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0.
+ MAPVK_VSC_TO_VK = 1, //The uCode parameter is a scan code and is translated into a virtual-key code that does not distinguish between left- and right-hand keys. If there is no translation, the function returns 0.
+ MAPVK_VK_TO_CHAR = 2, //The uCode parameter is a virtual-key code and is translated into an unshifted character value in the low order word of the return value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, the function returns 0.
+ MAPVK_VSC_TO_VK_EX = 3, //The uCode parameter is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand keys. If there is no translation, the function returns 0.
+ MAPVK_VK_TO_VSC_EX = 4 //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If the scan code is an extended scan code, the high byte of the uCode value can contain either 0xe0 or 0xe1 to specify the extended scan code. If there is no translation, the function returns 0.
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern uint MapVirtualKey(uint uCode, uint uMapType);
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
+
+ // These variables store the current hotkey and modifier(s)
+ private Keys _hotkey = Keys.None;
+ private Keys _modifiers = Keys.None;
+
+ // ArrayLists used to enforce the use of proper modifiers.
+ // Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing.
+ private readonly IList _needNonShiftModifier = new List();
+ private readonly IList _needNonAltGrModifier = new List();
+
+ private readonly ContextMenu _dummy = new ContextMenu();
+
+ ///
+ /// Used to make sure that there is no right-click menu available
+ ///
+ public override ContextMenu ContextMenu {
+ get {
+ return _dummy;
+ }
+ set {
+ base.ContextMenu = _dummy;
+ }
+ }
+
+ ///
+ /// Forces the control to be non-multiline
+ ///
+ public override bool Multiline {
+ get {
+ return base.Multiline;
+ }
+ set {
+ // Ignore what the user wants; force Multiline to false
+ base.Multiline = false;
+ }
+ }
+
+ ///
+ /// Creates a new HotkeyControl
+ ///
+ public HotkeyControl() {
+ ContextMenu = _dummy; // Disable right-clicking
+ Text = "None";
+
+ // Handle events that occurs when keys are pressed
+ KeyPress += HotkeyControl_KeyPress;
+ KeyUp += HotkeyControl_KeyUp;
+ KeyDown += HotkeyControl_KeyDown;
+
+ PopulateModifierLists();
+ }
+
+ ///
+ /// Populates the ArrayLists specifying disallowed hotkeys
+ /// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc
+ ///
+ private void PopulateModifierLists() {
+ // Shift + 0 - 9, A - Z
+ for (Keys k = Keys.D0; k <= Keys.Z; k++) {
+ _needNonShiftModifier.Add((int)k);
+ }
+
+ // Shift + Numpad keys
+ for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++) {
+ _needNonShiftModifier.Add((int)k);
+ }
+
+ // Shift + Misc (,;<./ etc)
+ for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++) {
+ _needNonShiftModifier.Add((int)k);
+ }
+
+ // Shift + Space, PgUp, PgDn, End, Home
+ for (Keys k = Keys.Space; k <= Keys.Home; k++) {
+ _needNonShiftModifier.Add((int)k);
+ }
+
+ // Misc keys that we can't loop through
+ _needNonShiftModifier.Add((int)Keys.Insert);
+ _needNonShiftModifier.Add((int)Keys.Help);
+ _needNonShiftModifier.Add((int)Keys.Multiply);
+ _needNonShiftModifier.Add((int)Keys.Add);
+ _needNonShiftModifier.Add((int)Keys.Subtract);
+ _needNonShiftModifier.Add((int)Keys.Divide);
+ _needNonShiftModifier.Add((int)Keys.Decimal);
+ _needNonShiftModifier.Add((int)Keys.Return);
+ _needNonShiftModifier.Add((int)Keys.Escape);
+ _needNonShiftModifier.Add((int)Keys.NumLock);
+
+ // Ctrl+Alt + 0 - 9
+ for (Keys k = Keys.D0; k <= Keys.D9; k++) {
+ _needNonAltGrModifier.Add((int)k);
+ }
+ }
+
+ ///
+ /// Resets this hotkey control to None
+ ///
+ public new void Clear() {
+ Hotkey = Keys.None;
+ HotkeyModifiers = Keys.None;
+ }
+
+ ///
+ /// Fires when a key is pushed down. Here, we'll want to update the text in the box
+ /// to notify the user what combination is currently pressed.
+ ///
+ private void HotkeyControl_KeyDown(object sender, KeyEventArgs e) {
+ // Clear the current hotkey
+ if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) {
+ ResetHotkey();
+ } else {
+ _modifiers = e.Modifiers;
+ _hotkey = e.KeyCode;
+ Redraw();
+ }
+ }
+
+ ///
+ /// Fires when all keys are released. If the current hotkey isn't valid, reset it.
+ /// Otherwise, do nothing and keep the text and hotkey as it was.
+ ///
+ private void HotkeyControl_KeyUp(object sender, KeyEventArgs e) {
+ // Somehow the PrintScreen only comes as a keyup, therefore we handle it here.
+ if (e.KeyCode == Keys.PrintScreen) {
+ _modifiers = e.Modifiers;
+ _hotkey = e.KeyCode;
+ Redraw();
+ }
+
+ if (_hotkey == Keys.None && ModifierKeys == Keys.None) {
+ ResetHotkey();
+ }
+ }
+
+ ///
+ /// Prevents the letter/whatever entered to show up in the TextBox
+ /// Without this, a "A" key press would appear as "aControl, Alt + A"
+ ///
+ private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e) {
+ e.Handled = true;
+ }
+
+ ///
+ /// Handles some misc keys, such as Ctrl+Delete and Shift+Insert
+ ///
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
+ if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete)) {
+ ResetHotkey();
+ return true;
+ }
+
+ // Paste
+ if (keyData == (Keys.Shift | Keys.Insert)) {
+ return true; // Don't allow
+ }
+
+ // Allow the rest
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+
+ ///
+ /// Clears the current hotkey and resets the TextBox
+ ///
+ public void ResetHotkey() {
+ _hotkey = Keys.None;
+ _modifiers = Keys.None;
+ Redraw();
+ }
+
+ ///
+ /// Used to get/set the hotkey (e.g. Keys.A)
+ ///
+ public Keys Hotkey {
+ get {
+ return _hotkey;
+ }
+ set {
+ _hotkey = value;
+ Redraw(true);
+ }
+ }
+
+ ///
+ /// Used to get/set the hotkey (e.g. Keys.A)
+ ///
+ public void SetHotkey(string hotkey) {
+ _hotkey = HotkeyFromString(hotkey);
+ _modifiers = HotkeyModifiersFromString(hotkey);
+ Redraw(true);
+ }
+
+ ///
+ /// Used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control)
+ ///
+ public Keys HotkeyModifiers {
+ get {
+ return _modifiers;
+ }
+ set {
+ _modifiers = value;
+ Redraw(true);
+ }
+ }
+
+ ///
+ /// Redraws the TextBox when necessary.
+ ///
+ /// Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.
+ private void Redraw(bool bCalledProgramatically = false) {
+ // No hotkey set
+ if (_hotkey == Keys.None) {
+ Text = "";
+ return;
+ }
+
+ // LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0)
+ if (_hotkey == Keys.LWin || _hotkey == Keys.RWin) {
+ Text = "";
+ return;
+ }
+
+ // Only validate input if it comes from the user
+ if (bCalledProgramatically == false) {
+ // No modifier or shift only, AND a hotkey that needs another modifier
+ if ((_modifiers == Keys.Shift || _modifiers == Keys.None) && _needNonShiftModifier.Contains((int)_hotkey)) {
+ if (_modifiers == Keys.None) {
+ // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work...
+ if (_needNonAltGrModifier.Contains((int)_hotkey) == false) {
+ _modifiers = Keys.Alt | Keys.Control;
+ } else {
+ // ... in that case, use Shift+Alt instead.
+ _modifiers = Keys.Alt | Keys.Shift;
+ }
+ } else {
+ // User pressed Shift and an invalid key (e.g. a letter or a number),
+ // that needs another set of modifier keys
+ _hotkey = Keys.None;
+ Text = "";
+ return;
+ }
+ }
+ // Check all Ctrl+Alt keys
+ if ((_modifiers == (Keys.Alt | Keys.Control)) && _needNonAltGrModifier.Contains((int)_hotkey)) {
+ // Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
+ _hotkey = Keys.None;
+ Text = "";
+ return;
+ }
+ }
+
+ // I have no idea why this is needed, but it is. Without this code, pressing only Ctrl
+ // will show up as "Control + ControlKey", etc.
+ if (_hotkey == Keys.Menu /* Alt */ || _hotkey == Keys.ShiftKey || _hotkey == Keys.ControlKey) {
+ _hotkey = Keys.None;
+ }
+ Text = HotkeyToLocalizedString(_modifiers, _hotkey);
+ }
+
+ public override string ToString() {
+ return HotkeyToString(HotkeyModifiers, Hotkey);
+ }
+
+ public static string GetLocalizedHotkeyStringFromString(string hotkeyString) {
+ Keys virtualKeyCode = HotkeyFromString(hotkeyString);
+ Keys modifiers = HotkeyModifiersFromString(hotkeyString);
+ return HotkeyToLocalizedString(modifiers, virtualKeyCode);
+ }
+
+ public static string HotkeyToString(Keys modifierKeyCode, Keys virtualKeyCode) {
+ return HotkeyModifiersToString(modifierKeyCode) + virtualKeyCode;
+ }
+
+ public static string HotkeyModifiersToString(Keys modifierKeyCode) {
+ StringBuilder hotkeyString = new StringBuilder();
+ if ((modifierKeyCode & Keys.Alt) > 0) {
+ hotkeyString.Append("Alt").Append(" + ");
+ }
+ if ((modifierKeyCode & Keys.Control) > 0) {
+ hotkeyString.Append("Ctrl").Append(" + ");
+ }
+ if ((modifierKeyCode & Keys.Shift) > 0) {
+ hotkeyString.Append("Shift").Append(" + ");
+ }
+ if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) {
+ hotkeyString.Append("Win").Append(" + ");
+ }
+ return hotkeyString.ToString();
+ }
+
+
+ public static string HotkeyToLocalizedString(Keys modifierKeyCode, Keys virtualKeyCode) {
+ return HotkeyModifiersToLocalizedString(modifierKeyCode) + GetKeyName(virtualKeyCode);
+ }
+
+ public static string HotkeyModifiersToLocalizedString(Keys modifierKeyCode) {
+ StringBuilder hotkeyString = new StringBuilder();
+ if ((modifierKeyCode & Keys.Alt) > 0) {
+ hotkeyString.Append(GetKeyName(Keys.Alt)).Append(" + ");
+ }
+ if ((modifierKeyCode & Keys.Control) > 0) {
+ hotkeyString.Append(GetKeyName(Keys.Control)).Append(" + ");
+ }
+ if ((modifierKeyCode & Keys.Shift) > 0) {
+ hotkeyString.Append(GetKeyName(Keys.Shift)).Append(" + ");
+ }
+ if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) {
+ hotkeyString.Append("Win").Append(" + ");
+ }
+ return hotkeyString.ToString();
+ }
+
+
+ public static Keys HotkeyModifiersFromString(string modifiersString) {
+ Keys modifiers = Keys.None;
+ if (!string.IsNullOrEmpty(modifiersString)) {
+ if (modifiersString.ToLower().Contains("alt")) {
+ modifiers |= Keys.Alt;
+ }
+ if (modifiersString.ToLower().Contains("ctrl")) {
+ modifiers |= Keys.Control;
+ }
+ if (modifiersString.ToLower().Contains("shift")) {
+ modifiers |= Keys.Shift;
+ }
+ if (modifiersString.ToLower().Contains("win")) {
+ modifiers |= Keys.LWin;
+ }
+ }
+ return modifiers;
+ }
+
+ public static Keys HotkeyFromString(string hotkey) {
+ Keys key = Keys.None;
+ if (!string.IsNullOrEmpty(hotkey)) {
+ if (hotkey.LastIndexOf('+') > 0) {
+ hotkey = hotkey.Remove(0,hotkey.LastIndexOf('+')+1).Trim();
+ }
+ key = (Keys)Enum.Parse(typeof(Keys), hotkey);
+ }
+ return key;
+ }
+
+ public static void RegisterHotkeyHwnd(IntPtr hWnd) {
+ _hotkeyHwnd = hWnd;
+ }
+
+ public static int RegisterHotKey(string hotkey, HotKeyHandler handler) {
+ return RegisterHotKey(HotkeyModifiersFromString(hotkey), HotkeyFromString(hotkey),handler);
+ }
+
+ ///
+ /// Register a hotkey
+ ///
+ /// The modifier, e.g.: Modifiers.CTRL, Modifiers.NONE or Modifiers.ALT
+ /// The virtual key code
+ /// A HotKeyHandler, this will be called to handle the hotkey press
+ /// the hotkey number, -1 if failed
+ public static int RegisterHotKey(Keys modifierKeyCode, Keys virtualKeyCode, HotKeyHandler handler) {
+ if (virtualKeyCode == Keys.None) {
+ Log.Warn("Trying to register a Keys.none hotkey, ignoring");
+ return 0;
+ }
+ // Convert Modifiers to fit HKM_SETHOTKEY
+ uint modifiers = 0;
+ if ((modifierKeyCode & Keys.Alt) > 0) {
+ modifiers |= (uint)Modifiers.ALT;
+ }
+ if ((modifierKeyCode & Keys.Control) > 0) {
+ modifiers |= (uint)Modifiers.CTRL;
+ }
+ if ((modifierKeyCode & Keys.Shift) > 0) {
+ modifiers |= (uint)Modifiers.SHIFT;
+ }
+ if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) {
+ modifiers |= (uint)Modifiers.WIN;
+ }
+ // Disable repeating hotkey for Windows 7 and beyond, as described in #1559
+ if (IsWindows7OrOlder) {
+ modifiers |= (uint)Modifiers.NO_REPEAT;
+ }
+ if (RegisterHotKey(_hotkeyHwnd, _hotKeyCounter, modifiers, (uint)virtualKeyCode)) {
+ KeyHandlers.Add(_hotKeyCounter, handler);
+ return _hotKeyCounter++;
+ } else {
+ Log.Warn($"Couldn't register hotkey modifier {modifierKeyCode} virtualKeyCode {virtualKeyCode}");
+ return -1;
+ }
+ }
+
+ public static void UnregisterHotkeys() {
+ foreach(int hotkey in KeyHandlers.Keys) {
+ UnregisterHotKey(_hotkeyHwnd, hotkey);
+ }
+ // Remove all key handlers
+ KeyHandlers.Clear();
+ }
+
+ public static void UnregisterHotkey(int hotkey) {
+ bool removeHotkey = false;
+ foreach(int availableHotkey in KeyHandlers.Keys) {
+ if (availableHotkey == hotkey) {
+ UnregisterHotKey(_hotkeyHwnd, hotkey);
+ removeHotkey = true;
+ }
+ }
+ if (removeHotkey) {
+ // Remove key handler
+ KeyHandlers.Remove(hotkey);
+ }
+ }
+
+ ///
+ /// Handle WndProc messages for the hotkey
+ ///
+ ///
+ /// true if the message was handled
+ public static bool HandleMessages(ref Message m) {
+ if (m.Msg != WM_HOTKEY)
+ {
+ return false;
+ }
+ // Call handler
+ if (!IsWindows7OrOlder && !EventDelay.Check())
+ {
+ return true;
+ }
+ HotKeyHandler handler;
+ if (KeyHandlers.TryGetValue((int)m.WParam, out handler))
+ {
+ handler();
+ }
+ return true;
+ }
+
+ public static string GetKeyName(Keys givenKey) {
+ StringBuilder keyName = new StringBuilder();
+ const uint numpad = 55;
+
+ Keys virtualKey = givenKey;
+ string keyString;
+ // Make VC's to real keys
+ switch(virtualKey) {
+ case Keys.Alt:
+ virtualKey = Keys.LMenu;
+ break;
+ case Keys.Control:
+ virtualKey = Keys.ControlKey;
+ break;
+ case Keys.Shift:
+ virtualKey = Keys.LShiftKey;
+ break;
+ case Keys.Multiply:
+ GetKeyNameText(numpad << 16, keyName, 100);
+ keyString = keyName.ToString().Replace("*","").Trim().ToLower();
+ if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) {
+ return "* " + keyString;
+ }
+ keyString = keyString.Substring(0,1).ToUpper() + keyString.Substring(1).ToLower();
+ return keyString + " *";
+ case Keys.Divide:
+ GetKeyNameText(numpad << 16, keyName, 100);
+ keyString = keyName.ToString().Replace("*","").Trim().ToLower();
+ if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) {
+ return "/ " + keyString;
+ }
+ keyString = keyString.Substring(0,1).ToUpper() + keyString.Substring(1).ToLower();
+ return keyString + " /";
+ }
+ uint scanCode = MapVirtualKey((uint)virtualKey, (uint)MapType.MAPVK_VK_TO_VSC);
+
+ // because MapVirtualKey strips the extended bit for some keys
+ switch (virtualKey) {
+ case Keys.Left: case Keys.Up: case Keys.Right: case Keys.Down: // arrow keys
+ case Keys.Prior: case Keys.Next: // page up and page down
+ case Keys.End: case Keys.Home:
+ case Keys.Insert: case Keys.Delete:
+ case Keys.NumLock:
+ Log.Debug("Modifying Extended bit");
+ scanCode |= 0x100; // set extended bit
+ break;
+ case Keys.PrintScreen: // PrintScreen
+ scanCode = 311;
+ break;
+ case Keys.Pause: // PrintScreen
+ scanCode = 69;
+ break;
+ }
+ scanCode |= 0x200;
+ if (GetKeyNameText(scanCode << 16, keyName, 100) != 0) {
+ string visibleName = keyName.ToString();
+ if (visibleName.Length > 1) {
+ visibleName = visibleName.Substring(0,1) + visibleName.Substring(1).ToLower();
+ }
+ return visibleName;
+ } else {
+ return givenKey.ToString();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs b/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs
new file mode 100644
index 000000000..237ebd8d9
--- /dev/null
+++ b/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs
@@ -0,0 +1,40 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPlugin.Controls {
+ public interface IGreenshotConfigBindable {
+ ///
+ /// The class where the property-value is stored
+ ///
+ string SectionName {
+ get;
+ set;
+ }
+
+ ///
+ /// Path to the property value which will be mapped with this control
+ ///
+ string PropertyName {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs b/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs
new file mode 100644
index 000000000..134d381a7
--- /dev/null
+++ b/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs
@@ -0,0 +1,36 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// This interface describes the designer fields that need to be implemented for Greenshot controls
+ ///
+ public interface IGreenshotLanguageBindable {
+ ///
+ /// Language key to use to fill the Text value with
+ ///
+ string LanguageKey {
+ get;
+ set;
+ }
+
+ }
+}
diff --git a/src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs b/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
similarity index 86%
rename from src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs
rename to GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
index cac4d8528..9e5596e37 100644
--- a/src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs
+++ b/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
@@ -1,92 +1,92 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-namespace Greenshot.Base.Controls {
- partial class OAuthLoginForm {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this._addressTextBox = new System.Windows.Forms.TextBox();
- this._browser = new ExtendedWebBrowser();
- this.SuspendLayout();
- //
- // _addressTextBox
- //
- this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
- this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
- this._addressTextBox.Enabled = false;
- this._addressTextBox.Location = new System.Drawing.Point(0, 0);
- this._addressTextBox.Name = "addressTextBox";
- this._addressTextBox.Size = new System.Drawing.Size(595, 20);
- this._addressTextBox.TabIndex = 3;
- this._addressTextBox.TabStop = false;
- //
- // _browser
- //
- this._browser.Dock = System.Windows.Forms.DockStyle.Fill;
- this._browser.Location = new System.Drawing.Point(0, 20);
- this._browser.MinimumSize = new System.Drawing.Size(100, 100);
- this._browser.Name = "browser";
- this._browser.Size = new System.Drawing.Size(595, 295);
- this._browser.TabIndex = 4;
- //
- // OAuthLoginForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(595, 315);
- this.Controls.Add(this._browser);
- this.Controls.Add(this._addressTextBox);
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "OAuthLoginForm";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.TextBox _addressTextBox;
- private ExtendedWebBrowser _browser;
-
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotPlugin.Controls {
+ partial class OAuthLoginForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this._addressTextBox = new System.Windows.Forms.TextBox();
+ this._browser = new ExtendedWebBrowser();
+ this.SuspendLayout();
+ //
+ // _addressTextBox
+ //
+ this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow;
+ this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top;
+ this._addressTextBox.Enabled = false;
+ this._addressTextBox.Location = new System.Drawing.Point(0, 0);
+ this._addressTextBox.Name = "addressTextBox";
+ this._addressTextBox.Size = new System.Drawing.Size(595, 20);
+ this._addressTextBox.TabIndex = 3;
+ this._addressTextBox.TabStop = false;
+ //
+ // _browser
+ //
+ this._browser.Dock = System.Windows.Forms.DockStyle.Fill;
+ this._browser.Location = new System.Drawing.Point(0, 20);
+ this._browser.MinimumSize = new System.Drawing.Size(100, 100);
+ this._browser.Name = "browser";
+ this._browser.Size = new System.Drawing.Size(595, 295);
+ this._browser.TabIndex = 4;
+ //
+ // OAuthLoginForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(595, 315);
+ this.Controls.Add(this._browser);
+ this.Controls.Add(this._addressTextBox);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "OAuthLoginForm";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox _addressTextBox;
+ private ExtendedWebBrowser _browser;
+
+ }
+}
diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.cs b/GreenshotPlugin/Controls/OAuthLoginForm.cs
new file mode 100644
index 000000000..a3c5ffea2
--- /dev/null
+++ b/GreenshotPlugin/Controls/OAuthLoginForm.cs
@@ -0,0 +1,108 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application
+ ///
+ public sealed partial class OAuthLoginForm : Form {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
+ private readonly string _callbackUrl;
+ private IDictionary _callbackParameters;
+
+ public IDictionary CallbackParameters => _callbackParameters;
+
+ public bool IsOk => DialogResult == DialogResult.OK;
+
+ public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) {
+ // Make sure Greenshot uses the correct browser version
+ IEHelper.FixBrowserVersion(false);
+
+ _callbackUrl = callbackUrl;
+ // Fix for BUG-2071
+ if (callbackUrl.EndsWith("/"))
+ {
+ _callbackUrl = callbackUrl.Substring(0, callbackUrl.Length - 1);
+ }
+ InitializeComponent();
+ ClientSize = size;
+ Icon = GreenshotResources.getGreenshotIcon();
+ Text = browserTitle;
+ _addressTextBox.Text = authorizationLink;
+
+ // The script errors are suppressed by using the ExtendedWebBrowser
+ _browser.ScriptErrorsSuppressed = false;
+ _browser.DocumentCompleted += Browser_DocumentCompleted;
+ _browser.Navigated += Browser_Navigated;
+ _browser.Navigating += Browser_Navigating;
+ _browser.Navigate(new Uri(authorizationLink));
+ }
+
+ ///
+ /// Make sure the form is visible
+ ///
+ /// EventArgs
+ protected override void OnShown(EventArgs e) {
+ base.OnShown(e);
+ WindowDetails.ToForeground(Handle);
+ }
+
+ private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
+ LOG.DebugFormat("document completed with url: {0}", _browser.Url);
+ CheckUrl();
+ }
+
+ private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
+ LOG.DebugFormat("Navigating to url: {0}", _browser.Url);
+ _addressTextBox.Text = e.Url.ToString();
+ }
+
+ private void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
+ LOG.DebugFormat("Navigated to url: {0}", _browser.Url);
+ CheckUrl();
+ }
+
+ private void CheckUrl() {
+ if (_browser.Url.ToString().StartsWith(_callbackUrl)) {
+ var correctedUri = new Uri(_browser.Url.AbsoluteUri.Replace("#", "&"));
+
+ string queryParams = correctedUri.Query;
+ if (queryParams.Length > 0) {
+ queryParams = NetworkHelper.UrlDecode(queryParams);
+ //Store the Token and Token Secret
+ _callbackParameters = NetworkHelper.ParseQueryString(queryParams);
+ }
+ DialogResult = DialogResult.OK;
+ }
+ }
+
+ private void AddressTextBox_KeyPress(object sender, KeyPressEventArgs e) {
+ //Cancel the key press so the user can't enter a new url
+ e.Handled = true;
+ }
+ }
+}
diff --git a/src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs b/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs
similarity index 87%
rename from src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs
rename to GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs
index 26fc19d38..cb8a3a705 100644
--- a/src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs
+++ b/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs
@@ -1,99 +1,101 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-namespace Greenshot.Base.Controls {
- partial class PleaseWaitForm {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent() {
- this.label_pleasewait = new System.Windows.Forms.Label();
- this.cancelButton = new System.Windows.Forms.Button();
- this.SuspendLayout();
- //
- // label_pleasewait
- //
- this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
- this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
- this.label_pleasewait.Name = "label_pleasewait";
- this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
- this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
- this.label_pleasewait.TabIndex = 0;
- this.label_pleasewait.Text = "Please wait...";
- this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
- this.label_pleasewait.UseWaitCursor = true;
- //
- // cancelButton
- //
- this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.cancelButton.Location = new System.Drawing.Point(38, 41);
- this.cancelButton.Name = "cancelButton";
- this.cancelButton.Size = new System.Drawing.Size(94, 23);
- this.cancelButton.TabIndex = 1;
- this.cancelButton.Text = "Cancel";
- this.cancelButton.UseVisualStyleBackColor = true;
- this.cancelButton.UseWaitCursor = true;
- this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
- //
- // PleaseWaitForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.CancelButton = this.cancelButton;
- this.ClientSize = new System.Drawing.Size(169, 76);
- this.Controls.Add(this.cancelButton);
- this.Controls.Add(this.label_pleasewait);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "PleaseWaitForm";
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Greenshot";
- this.UseWaitCursor = true;
- this.ResumeLayout(false);
- this.PerformLayout();
- }
- private System.Windows.Forms.Button cancelButton;
- private System.Windows.Forms.Label label_pleasewait;
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotPlugin.Controls {
+ partial class PleaseWaitForm {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent() {
+ this.label_pleasewait = new System.Windows.Forms.Label();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // label_pleasewait
+ //
+ this.label_pleasewait.AutoSize = true;
+ this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
+ this.label_pleasewait.Name = "label_pleasewait";
+ this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
+ this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
+ this.label_pleasewait.TabIndex = 0;
+ this.label_pleasewait.Text = "Please wait...";
+ this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.label_pleasewait.UseWaitCursor = true;
+ //
+ // cancelButton
+ //
+ this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.cancelButton.Location = new System.Drawing.Point(38, 41);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(94, 23);
+ this.cancelButton.TabIndex = 1;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ this.cancelButton.UseWaitCursor = true;
+ this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
+ //
+ // PleaseWaitForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoSize = true;
+ this.CancelButton = this.cancelButton;
+ this.ClientSize = new System.Drawing.Size(169, 76);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.label_pleasewait);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "PleaseWaitForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Greenshot";
+ this.UseWaitCursor = true;
+ this.ResumeLayout(false);
+ this.PerformLayout();
+ }
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.Label label_pleasewait;
+ }
+}
diff --git a/GreenshotPlugin/Controls/PleaseWaitForm.cs b/GreenshotPlugin/Controls/PleaseWaitForm.cs
new file mode 100644
index 000000000..3556af50b
--- /dev/null
+++ b/GreenshotPlugin/Controls/PleaseWaitForm.cs
@@ -0,0 +1,124 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using System.Threading;
+using GreenshotPlugin.Core;
+using log4net;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Description of PleaseWaitForm.
+ ///
+ public partial class PleaseWaitForm : Form {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(PleaseWaitForm));
+ private Thread _waitFor;
+ private string _title;
+ public PleaseWaitForm() {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ Icon = GreenshotResources.getGreenshotIcon();
+ }
+
+ ///
+ /// Prevent the close-window button showing
+ ///
+ private const int CP_NOCLOSE_BUTTON = 0x200;
+ protected override CreateParams CreateParams {
+ get {
+ CreateParams createParams = base.CreateParams;
+ createParams.ClassStyle = createParams.ClassStyle | CP_NOCLOSE_BUTTON ;
+ return createParams;
+ }
+ }
+
+ ///
+ /// Show the "please wait" form, execute the code from the delegate and wait until execution finishes.
+ /// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown.
+ ///
+ /// The title of the form (and Thread)
+ /// The text in the form
+ /// delegate { with your code }
+ public void ShowAndWait(string title, string text, ThreadStart waitDelegate) {
+ _title = title;
+ Text = title;
+ label_pleasewait.Text = text;
+ cancelButton.Text = Language.GetString("CANCEL");
+
+ // Make sure the form is shown.
+ Show();
+
+ // Variable to store the exception, if one is generated, from inside the thread.
+ Exception threadException = null;
+ try {
+ // Wrap the passed delegate in a try/catch which makes it possible to save the exception
+ _waitFor = new Thread(new ThreadStart(
+ delegate
+ {
+ try
+ {
+ waitDelegate.Invoke();
+ }
+ catch (Exception ex)
+ {
+ LOG.Error("invoke error:", ex);
+ threadException = ex;
+ }
+ })
+ )
+ {
+ Name = title,
+ IsBackground = true
+ };
+ _waitFor.SetApartmentState(ApartmentState.STA);
+ _waitFor.Start();
+
+ // Wait until finished
+ while (!_waitFor.Join(TimeSpan.FromMilliseconds(100))) {
+ Application.DoEvents();
+ }
+ LOG.DebugFormat("Finished {0}", title);
+ } catch (Exception ex) {
+ LOG.Error(ex);
+ throw;
+ } finally {
+ Close();
+ }
+ // Check if an exception occured, if so throw it
+ if (threadException != null) {
+ throw threadException;
+ }
+ }
+
+ ///
+ /// Called if the cancel button is clicked, will use Thread.Abort()
+ ///
+ ///
+ ///
+ private void CancelButtonClick(object sender, EventArgs e) {
+ LOG.DebugFormat("Cancel clicked on {0}", _title);
+ cancelButton.Enabled = false;
+ _waitFor.Abort();
+ }
+ }
+}
diff --git a/src/Greenshot.Base/Controls/QualityDialog.Designer.cs b/GreenshotPlugin/Controls/QualityDialog.Designer.cs
similarity index 86%
rename from src/Greenshot.Base/Controls/QualityDialog.Designer.cs
rename to GreenshotPlugin/Controls/QualityDialog.Designer.cs
index 725b17328..f754b9508 100644
--- a/src/Greenshot.Base/Controls/QualityDialog.Designer.cs
+++ b/GreenshotPlugin/Controls/QualityDialog.Designer.cs
@@ -1,147 +1,148 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: https://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-namespace Greenshot.Base.Controls {
- partial class QualityDialog {
- ///
- /// Designer variable used to keep track of non-visual components.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Disposes resources used by the form.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing) {
- if (components != null) {
- components.Dispose();
- }
- }
- base.Dispose(disposing);
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- private void InitializeComponent()
- {
- this.label_choosejpegquality = new GreenshotLabel();
- this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
- this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
- this.checkbox_dontaskagain = new GreenshotCheckBox();
- this.button_ok = new GreenshotButton();
- this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
- ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
- this.SuspendLayout();
- //
- // label_choosejpegquality
- //
- this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47);
- this.label_choosejpegquality.Name = "label_choosejpegquality";
- this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19);
- this.label_choosejpegquality.TabIndex = 15;
- this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality";
- //
- // textBoxJpegQuality
- //
- this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69);
- this.textBoxJpegQuality.Name = "textBoxJpegQuality";
- this.textBoxJpegQuality.ReadOnly = true;
- this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20);
- this.textBoxJpegQuality.TabIndex = 4;
- this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
- //
- // trackBarJpegQuality
- //
- this.trackBarJpegQuality.LargeChange = 10;
- this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69);
- this.trackBarJpegQuality.Maximum = 100;
- this.trackBarJpegQuality.Name = "trackBarJpegQuality";
- this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45);
- this.trackBarJpegQuality.TabIndex = 3;
- this.trackBarJpegQuality.TickFrequency = 10;
- this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll);
- //
- // checkbox_dontaskagain
- //
- this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
- this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
- this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106);
- this.checkbox_dontaskagain.Name = "checkbox_dontaskagain";
- this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain";
- this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37);
- this.checkbox_dontaskagain.TabIndex = 5;
- this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft;
- this.checkbox_dontaskagain.UseVisualStyleBackColor = true;
- //
- // button_ok
- //
- this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.button_ok.Location = new System.Drawing.Point(205, 149);
- this.button_ok.Name = "button_ok";
- this.button_ok.Size = new System.Drawing.Size(75, 23);
- this.button_ok.TabIndex = 1;
- this.button_ok.LanguageKey = "OK";
- this.button_ok.UseVisualStyleBackColor = true;
- this.button_ok.Click += new System.EventHandler(this.Button_okClick);
- //
- // checkBox_reduceColors
- //
- this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11);
- this.checkBox_reduceColors.Name = "checkBox_reduceColors";
- this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17);
- this.checkBox_reduceColors.TabIndex = 2;
- this.checkBox_reduceColors.Text = "settings_reducecolors";
- this.checkBox_reduceColors.UseVisualStyleBackColor = true;
- //
- // QualityDialog
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
- this.ClientSize = new System.Drawing.Size(299, 184);
- this.ControlBox = false;
- this.Controls.Add(this.checkBox_reduceColors);
- this.Controls.Add(this.button_ok);
- this.Controls.Add(this.checkbox_dontaskagain);
- this.Controls.Add(this.label_choosejpegquality);
- this.Controls.Add(this.textBoxJpegQuality);
- this.Controls.Add(this.trackBarJpegQuality);
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "QualityDialog";
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.LanguageKey = "qualitydialog_title";
- ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
- private GreenshotButton button_ok;
- private GreenshotCheckBox checkbox_dontaskagain;
- private System.Windows.Forms.TrackBar trackBarJpegQuality;
- private System.Windows.Forms.TextBox textBoxJpegQuality;
- private GreenshotLabel label_choosejpegquality;
- private System.Windows.Forms.CheckBox checkBox_reduceColors;
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+namespace GreenshotPlugin.Controls {
+ partial class QualityDialog {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
+ this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
+ this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
+ this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
+ this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
+ this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
+ ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
+ this.SuspendLayout();
+ //
+ // label_choosejpegquality
+ //
+ this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47);
+ this.label_choosejpegquality.Name = "label_choosejpegquality";
+ this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19);
+ this.label_choosejpegquality.TabIndex = 15;
+ this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality";
+ //
+ // textBoxJpegQuality
+ //
+ this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69);
+ this.textBoxJpegQuality.Name = "textBoxJpegQuality";
+ this.textBoxJpegQuality.ReadOnly = true;
+ this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20);
+ this.textBoxJpegQuality.TabIndex = 4;
+ this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ //
+ // trackBarJpegQuality
+ //
+ this.trackBarJpegQuality.LargeChange = 10;
+ this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69);
+ this.trackBarJpegQuality.Maximum = 100;
+ this.trackBarJpegQuality.Name = "trackBarJpegQuality";
+ this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45);
+ this.trackBarJpegQuality.TabIndex = 3;
+ this.trackBarJpegQuality.TickFrequency = 10;
+ this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll);
+ //
+ // checkbox_dontaskagain
+ //
+ this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
+ this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
+ this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106);
+ this.checkbox_dontaskagain.Name = "checkbox_dontaskagain";
+ this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain";
+ this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37);
+ this.checkbox_dontaskagain.TabIndex = 5;
+ this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft;
+ this.checkbox_dontaskagain.UseVisualStyleBackColor = true;
+ //
+ // button_ok
+ //
+ this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.button_ok.Location = new System.Drawing.Point(205, 149);
+ this.button_ok.Name = "button_ok";
+ this.button_ok.Size = new System.Drawing.Size(75, 23);
+ this.button_ok.TabIndex = 1;
+ this.button_ok.LanguageKey = "OK";
+ this.button_ok.UseVisualStyleBackColor = true;
+ this.button_ok.Click += new System.EventHandler(this.Button_okClick);
+ //
+ // checkBox_reduceColors
+ //
+ this.checkBox_reduceColors.AutoSize = true;
+ this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11);
+ this.checkBox_reduceColors.Name = "checkBox_reduceColors";
+ this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17);
+ this.checkBox_reduceColors.TabIndex = 2;
+ this.checkBox_reduceColors.Text = "settings_reducecolors";
+ this.checkBox_reduceColors.UseVisualStyleBackColor = true;
+ //
+ // QualityDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.ClientSize = new System.Drawing.Size(299, 184);
+ this.ControlBox = false;
+ this.Controls.Add(this.checkBox_reduceColors);
+ this.Controls.Add(this.button_ok);
+ this.Controls.Add(this.checkbox_dontaskagain);
+ this.Controls.Add(this.label_choosejpegquality);
+ this.Controls.Add(this.textBoxJpegQuality);
+ this.Controls.Add(this.trackBarJpegQuality);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "QualityDialog";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.LanguageKey = "qualitydialog_title";
+ ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+ private GreenshotPlugin.Controls.GreenshotButton button_ok;
+ private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain;
+ private System.Windows.Forms.TrackBar trackBarJpegQuality;
+ private System.Windows.Forms.TextBox textBoxJpegQuality;
+ private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality;
+ private System.Windows.Forms.CheckBox checkBox_reduceColors;
+ }
+}
diff --git a/GreenshotPlugin/Controls/QualityDialog.cs b/GreenshotPlugin/Controls/QualityDialog.cs
new file mode 100644
index 000000000..43029ed62
--- /dev/null
+++ b/GreenshotPlugin/Controls/QualityDialog.cs
@@ -0,0 +1,67 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Description of JpegQualityDialog.
+ ///
+ public partial class QualityDialog : GreenshotForm {
+ private static readonly CoreConfiguration conf = IniConfig.GetIniSection();
+ public SurfaceOutputSettings Settings {
+ get;
+ set;
+ }
+
+ public QualityDialog(SurfaceOutputSettings outputSettings) {
+ Settings = outputSettings;
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+
+ checkBox_reduceColors.Checked = Settings.ReduceColors;
+ trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
+ trackBarJpegQuality.Value = Settings.JPGQuality;
+ textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
+ textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
+ ToFront = true;
+ }
+
+ private void Button_okClick(object sender, EventArgs e) {
+ Settings.JPGQuality = trackBarJpegQuality.Value;
+ Settings.ReduceColors = checkBox_reduceColors.Checked;
+ if (checkbox_dontaskagain.Checked) {
+ conf.OutputFileJpegQuality = Settings.JPGQuality;
+ conf.OutputFilePromptQuality = false;
+ conf.OutputFileReduceColors = Settings.ReduceColors;
+ IniConfig.Save();
+ }
+ }
+
+ private void TrackBarJpegQualityScroll(object sender, EventArgs e) {
+ textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString();
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/SaveImageFileDialog.cs b/GreenshotPlugin/Controls/SaveImageFileDialog.cs
new file mode 100644
index 000000000..c077b4093
--- /dev/null
+++ b/GreenshotPlugin/Controls/SaveImageFileDialog.cs
@@ -0,0 +1,204 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.IO;
+using System.Windows.Forms;
+
+using Greenshot.Plugin;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using log4net;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// Custom dialog for saving images, wraps SaveFileDialog.
+ /// For some reason SFD is sealed :(
+ ///
+ public class SaveImageFileDialog : IDisposable {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(SaveImageFileDialog));
+ private static readonly CoreConfiguration conf = IniConfig.GetIniSection();
+ protected SaveFileDialog SaveFileDialog;
+ private FilterOption[] _filterOptions;
+ private DirectoryInfo _eagerlyCreatedDirectory;
+ private readonly ICaptureDetails _captureDetails;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (SaveFileDialog != null) {
+ SaveFileDialog.Dispose();
+ SaveFileDialog = null;
+ }
+ }
+ }
+
+ public SaveImageFileDialog() {
+ Init();
+ }
+
+ public SaveImageFileDialog(ICaptureDetails captureDetails) {
+ _captureDetails = captureDetails;
+ Init();
+ }
+
+ private void Init() {
+ SaveFileDialog = new SaveFileDialog();
+ ApplyFilterOptions();
+ string initialDirectory = null;
+ try {
+ conf.ValidateAndCorrectOutputFileAsFullpath();
+ initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath);
+ } catch {
+ LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath);
+ }
+
+ if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory)) {
+ SaveFileDialog.InitialDirectory = initialDirectory;
+ } else if (Directory.Exists(conf.OutputFilePath)) {
+ SaveFileDialog.InitialDirectory = conf.OutputFilePath;
+ }
+ // The following property fixes a problem that the directory where we save is locked (bug #2899790)
+ SaveFileDialog.RestoreDirectory = true;
+ SaveFileDialog.OverwritePrompt = true;
+ SaveFileDialog.CheckPathExists = false;
+ SaveFileDialog.AddExtension = true;
+ ApplySuggestedValues();
+ }
+
+ private void ApplyFilterOptions() {
+ PrepareFilterOptions();
+ string fdf = "";
+ int preselect = 0;
+ var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat);
+ for(int i=0; i<_filterOptions.Length; i++){
+ FilterOption fo = _filterOptions[i];
+ fdf += fo.Label + "|*." + fo.Extension + "|";
+ if(outputFileFormatAsString == fo.Extension)
+ preselect = i;
+ }
+ fdf = fdf.Substring(0, fdf.Length-1);
+ SaveFileDialog.Filter = fdf;
+ SaveFileDialog.FilterIndex = preselect + 1;
+ }
+
+ private void PrepareFilterOptions() {
+ OutputFormat[] supportedImageFormats = (OutputFormat[])Enum.GetValues(typeof(OutputFormat));
+ _filterOptions = new FilterOption[supportedImageFormats.Length];
+ for(int i=0; i<_filterOptions.Length; i++){
+ string ifo = supportedImageFormats[i].ToString();
+ if (ifo.ToLower().Equals("jpeg")) ifo = "Jpg"; // we dont want no jpeg files, so let the dialog check for jpg
+ FilterOption fo = new FilterOption
+ {
+ Label = ifo.ToUpper(),
+ Extension = ifo.ToLower()
+ };
+ _filterOptions.SetValue(fo, i);
+ }
+ }
+
+ ///
+ /// filename exactly as typed in the filename field
+ ///
+ public string FileName {
+ get {return SaveFileDialog.FileName;}
+ set {SaveFileDialog.FileName = value;}
+ }
+
+ ///
+ /// initial directory of the dialog
+ ///
+ public string InitialDirectory {
+ get {return SaveFileDialog.InitialDirectory;}
+ set {SaveFileDialog.InitialDirectory = value;}
+ }
+
+ ///
+ /// returns filename as typed in the filename field with extension.
+ /// if filename field value ends with selected extension, the value is just returned.
+ /// otherwise, the selected extension is appended to the filename.
+ ///
+ public string FileNameWithExtension {
+ get {
+ string fn = SaveFileDialog.FileName;
+ // if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay
+ if(fn.EndsWith(Extension,StringComparison.CurrentCultureIgnoreCase)) return fn;
+ // otherwise we just add the selected filter item's extension
+ else return fn + "." + Extension;
+ }
+ set {
+ FileName = Path.GetFileNameWithoutExtension(value);
+ Extension = Path.GetExtension(value);
+ }
+ }
+
+ ///
+ /// gets or sets selected extension
+ ///
+ public string Extension {
+ get {
+ return _filterOptions[SaveFileDialog.FilterIndex-1].Extension;
+ }
+ set {
+ for(int i=0; i<_filterOptions.Length; i++) {
+ if(value.Equals(_filterOptions[i].Extension, StringComparison.CurrentCultureIgnoreCase)) {
+ SaveFileDialog.FilterIndex = i + 1;
+ }
+ }
+ }
+ }
+
+ public DialogResult ShowDialog() {
+ DialogResult ret = SaveFileDialog.ShowDialog();
+ CleanUp();
+ return ret;
+ }
+
+ ///
+ /// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path
+ ///
+ private void ApplySuggestedValues() {
+ // build the full path and set dialog properties
+ FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, _captureDetails);
+ }
+
+ private class FilterOption {
+ public string Label;
+ public string Extension;
+ }
+
+ private void CleanUp() {
+ // fix for bug #3379053
+ try {
+ if(_eagerlyCreatedDirectory != null && _eagerlyCreatedDirectory.GetFiles().Length == 0 && _eagerlyCreatedDirectory.GetDirectories().Length == 0) {
+ _eagerlyCreatedDirectory.Delete();
+ _eagerlyCreatedDirectory = null;
+ }
+ } catch (Exception e) {
+ LOG.WarnFormat("Couldn't cleanup directory due to: {0}", e.Message);
+ _eagerlyCreatedDirectory = null;
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Controls/ThumbnailForm.cs b/GreenshotPlugin/Controls/ThumbnailForm.cs
new file mode 100644
index 000000000..c0ca8435b
--- /dev/null
+++ b/GreenshotPlugin/Controls/ThumbnailForm.cs
@@ -0,0 +1,119 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using Greenshot.IniFile;
+using System.Drawing;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace GreenshotPlugin.Controls {
+ ///
+ /// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture.
+ /// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform.
+ ///
+ public class ThumbnailForm : FormWithoutActivation {
+ private static readonly CoreConfiguration conf = IniConfig.GetIniSection();
+
+ private IntPtr _thumbnailHandle = IntPtr.Zero;
+
+ public ThumbnailForm() {
+ ShowInTaskbar = false;
+ FormBorderStyle = FormBorderStyle.None;
+ TopMost = false;
+ Enabled = false;
+ if (conf.WindowCaptureMode == WindowCaptureMode.Auto || conf.WindowCaptureMode == WindowCaptureMode.Aero) {
+ BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B);
+ } else {
+ BackColor = Color.White;
+ }
+
+ // cleanup at close
+ FormClosing += delegate {
+ UnregisterThumbnail();
+ };
+ }
+
+ public new void Hide() {
+ UnregisterThumbnail();
+ base.Hide();
+ }
+
+ private void UnregisterThumbnail() {
+ if (_thumbnailHandle != IntPtr.Zero) {
+ DWM.DwmUnregisterThumbnail(_thumbnailHandle);
+ _thumbnailHandle = IntPtr.Zero;
+ }
+ }
+
+ ///
+ /// Show the thumbnail of the supplied window above (or under) the parent Control
+ ///
+ /// WindowDetails
+ /// Control
+ public void ShowThumbnail(WindowDetails window, Control parentControl) {
+ UnregisterThumbnail();
+
+ DWM.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle);
+ if (_thumbnailHandle != IntPtr.Zero) {
+ SIZE sourceSize;
+ DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out sourceSize);
+ int thumbnailHeight = 200;
+ int thumbnailWidth = (int)(thumbnailHeight * (sourceSize.Width / (float)sourceSize.Height));
+ if (parentControl != null && thumbnailWidth > parentControl.Width) {
+ thumbnailWidth = parentControl.Width;
+ thumbnailHeight = (int)(thumbnailWidth * (sourceSize.Height / (float)sourceSize.Width));
+ }
+ Width = thumbnailWidth;
+ Height = thumbnailHeight;
+ // Prepare the displaying of the Thumbnail
+ DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES
+ {
+ Opacity = 255,
+ Visible = true,
+ SourceClientAreaOnly = false,
+ Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight)
+ };
+ DWM.DwmUpdateThumbnailProperties(_thumbnailHandle, ref props);
+ if (parentControl != null) {
+ AlignToControl(parentControl);
+ }
+
+ if (!Visible) {
+ Show();
+ }
+ // Make sure it's on "top"!
+ if (parentControl != null) {
+ User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE);
+ }
+ }
+ }
+
+ public void AlignToControl(Control alignTo) {
+ Rectangle screenBounds = WindowCapture.GetScreenBounds();
+ if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) {
+ Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height);
+ } else {
+ Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Bottom);
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/AbstractDestination.cs b/GreenshotPlugin/Core/AbstractDestination.cs
new file mode 100644
index 000000000..8b7ea5c19
--- /dev/null
+++ b/GreenshotPlugin/Core/AbstractDestination.cs
@@ -0,0 +1,336 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Threading;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of AbstractDestination.
+ ///
+ public abstract class AbstractDestination : IDestination {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+
+ public virtual int CompareTo(object obj) {
+ IDestination other = obj as IDestination;
+ if (other == null) {
+ return 1;
+ }
+ if (Priority == other.Priority) {
+ return String.Compare(Description, other.Description, StringComparison.Ordinal);
+ }
+ return Priority - other.Priority;
+ }
+
+ public abstract string Designation {
+ get;
+ }
+
+ public abstract string Description {
+ get;
+ }
+
+ public virtual int Priority => 10;
+
+ public virtual Image DisplayIcon => null;
+
+ public virtual Keys EditorShortcutKeys => Keys.None;
+
+ public virtual IEnumerable DynamicDestinations() {
+ yield break;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ //if (disposing) {}
+ }
+
+ public virtual bool IsDynamic => false;
+
+ public virtual bool UseDynamicsOnly => false;
+
+ public virtual bool IsLinkable => false;
+
+ public virtual bool IsActive {
+ get {
+ if (CoreConfig.ExcludeDestinations != null && CoreConfig.ExcludeDestinations.Contains(Designation)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public abstract ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails);
+
+ ///
+ /// A small helper method to perform some default destination actions, like inform the surface of the export
+ ///
+ ///
+ ///
+ public void ProcessExport(ExportInformation exportInformation, ISurface surface) {
+ if (exportInformation != null && exportInformation.ExportMade) {
+ if (!string.IsNullOrEmpty(exportInformation.Uri)) {
+ surface.UploadUrl = exportInformation.Uri;
+ surface.SendMessageEvent(this, SurfaceMessageTyp.UploadedUri, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription));
+ } else if (!string.IsNullOrEmpty(exportInformation.Filepath)) {
+ surface.LastSaveFullPath = exportInformation.Filepath;
+ surface.SendMessageEvent(this, SurfaceMessageTyp.FileSaved, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription));
+ } else {
+ surface.SendMessageEvent(this, SurfaceMessageTyp.Info, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription));
+ }
+ surface.Modified = false;
+ } else if (!string.IsNullOrEmpty(exportInformation?.ErrorMessage)) {
+ surface.SendMessageEvent(this, SurfaceMessageTyp.Error, Language.GetFormattedString("exported_to_error", exportInformation.DestinationDescription) + " " + exportInformation.ErrorMessage);
+ }
+ }
+
+ public override string ToString() {
+ return Description;
+ }
+
+ ///
+ /// Helper method to add events which set the tag, this way we can see why there might be a close.
+ ///
+ /// Item to add the events to
+ /// Menu to set the tag
+ /// Value for the tag
+ private void AddTagEvents(ToolStripMenuItem menuItem, ContextMenuStrip menu, string tagValue) {
+ if (menuItem != null && menu != null) {
+ menuItem.MouseDown += delegate
+ {
+ Log.DebugFormat("Setting tag to '{0}'", tagValue);
+ menu.Tag = tagValue;
+ };
+ menuItem.MouseUp += delegate
+ {
+ Log.Debug("Deleting tag");
+ menu.Tag = null;
+ };
+ }
+ }
+
+ ///
+ /// This method will create and show the destination picker menu
+ ///
+ /// Boolean if the dynamic values also need to be added
+ /// The surface which can be exported
+ /// Details for the surface
+ /// The list of destinations to show
+ ///
+ public ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable destinations) {
+ // Generate an empty ExportInformation object, for when nothing was selected.
+ ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker"));
+ var menu = new ContextMenuStrip
+ {
+ ImageScalingSize = CoreConfig.IconSize,
+ Tag = null,
+ TopLevel = true
+ };
+
+ menu.Closing += delegate(object source, ToolStripDropDownClosingEventArgs eventArgs) {
+ Log.DebugFormat("Close reason: {0}", eventArgs.CloseReason);
+ switch (eventArgs.CloseReason) {
+ case ToolStripDropDownCloseReason.AppFocusChange:
+ if (menu.Tag == null) {
+ // Do not allow the close if the tag is not set, this means the user clicked somewhere else.
+ eventArgs.Cancel = true;
+ } else {
+ Log.DebugFormat("Letting the menu 'close' as the tag is set to '{0}'", menu.Tag);
+ }
+ break;
+ case ToolStripDropDownCloseReason.ItemClicked:
+ case ToolStripDropDownCloseReason.CloseCalled:
+ // The ContextMenuStrip can be "closed" for these reasons.
+ break;
+ case ToolStripDropDownCloseReason.Keyboard:
+ // Dispose as the close is clicked
+ if (!captureDetails.HasDestination("Editor")) {
+ surface.Dispose();
+ surface = null;
+ }
+ break;
+ default:
+ eventArgs.Cancel = true;
+ break;
+ }
+ };
+ menu.MouseEnter += delegate
+ {
+ // in case the menu has been unfocused, focus again so that dropdown menus will still open on mouseenter
+ if(!menu.ContainsFocus) menu.Focus();
+ };
+ foreach (IDestination destination in destinations) {
+ // Fix foreach loop variable for the delegate
+ ToolStripMenuItem item = destination.GetMenuItem(addDynamics, menu,
+ delegate(object sender, EventArgs e) {
+ ToolStripMenuItem toolStripMenuItem = sender as ToolStripMenuItem;
+ IDestination clickedDestination = (IDestination) toolStripMenuItem?.Tag;
+ if (clickedDestination == null) {
+ return;
+ }
+ menu.Tag = clickedDestination.Designation;
+ // Export
+ exportInformation = clickedDestination.ExportCapture(true, surface, captureDetails);
+ if (exportInformation != null && exportInformation.ExportMade) {
+ Log.InfoFormat("Export to {0} success, closing menu", exportInformation.DestinationDescription);
+ // close menu if the destination wasn't the editor
+ menu.Close();
+
+ // Cleanup surface, only if there is no editor in the destinations and we didn't export to the editor
+ if (!captureDetails.HasDestination("Editor") && !"Editor".Equals(clickedDestination.Designation)) {
+ surface.Dispose();
+ surface = null;
+ }
+ } else {
+ Log.Info("Export cancelled or failed, showing menu again");
+
+ // Make sure a click besides the menu don't close it.
+ menu.Tag = null;
+
+ // This prevents the problem that the context menu shows in the task-bar
+ ShowMenuAtCursor(menu);
+ }
+ }
+ );
+ if (item != null) {
+ menu.Items.Add(item);
+ }
+ }
+ // Close
+ menu.Items.Add(new ToolStripSeparator());
+ ToolStripMenuItem closeItem = new ToolStripMenuItem(Language.GetString("editor_close"))
+ {
+ Image = GreenshotResources.getImage("Close.Image")
+ };
+ closeItem.Click += delegate {
+ // This menu entry is the close itself, we can dispose the surface
+ menu.Close();
+ if (!captureDetails.HasDestination("Editor")) {
+ surface.Dispose();
+ surface = null;
+ }
+ };
+ menu.Items.Add(closeItem);
+
+ ShowMenuAtCursor(menu);
+ return exportInformation;
+ }
+
+ ///
+ /// This method will show the supplied context menu at the mouse cursor, also makes sure it has focus and it's not visible in the taskbar.
+ ///
+ ///
+ private static void ShowMenuAtCursor(ContextMenuStrip menu) {
+ // find a suitable location
+ Point location = Cursor.Position;
+ Rectangle menuRectangle = new Rectangle(location, menu.Size);
+
+ menuRectangle.Intersect(WindowCapture.GetScreenBounds());
+ if (menuRectangle.Height < menu.Height) {
+ location.Offset(-40, -(menuRectangle.Height - menu.Height));
+ } else {
+ location.Offset(-40, -10);
+ }
+ // This prevents the problem that the context menu shows in the task-bar
+ User32.SetForegroundWindow(PluginUtils.Host.NotifyIcon.ContextMenuStrip.Handle);
+ menu.Show(location);
+ menu.Focus();
+
+ // Wait for the menu to close, so we can dispose it.
+ while (true) {
+ if (menu.Visible) {
+ Application.DoEvents();
+ Thread.Sleep(100);
+ } else {
+ menu.Dispose();
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Return a menu item
+ ///
+ ///
+ ///
+ ///
+ /// ToolStripMenuItem
+ public virtual ToolStripMenuItem GetMenuItem(bool addDynamics, ContextMenuStrip menu, EventHandler destinationClickHandler) {
+ var basisMenuItem = new ToolStripMenuItem(Description)
+ {
+ Image = DisplayIcon,
+ Tag = this,
+ Text = Description
+ };
+ AddTagEvents(basisMenuItem, menu, Description);
+ basisMenuItem.Click -= destinationClickHandler;
+ basisMenuItem.Click += destinationClickHandler;
+
+ if (IsDynamic && addDynamics) {
+ basisMenuItem.DropDownOpening += delegate
+ {
+ if (basisMenuItem.DropDownItems.Count == 0) {
+ List subDestinations = new List();
+ // Fixing Bug #3536968 by catching the COMException (every exception) and not displaying the "subDestinations"
+ try {
+ subDestinations.AddRange(DynamicDestinations());
+ } catch (Exception ex) {
+ Log.ErrorFormat("Skipping {0}, due to the following error: {1}", Description, ex.Message);
+ }
+ if (subDestinations.Count > 0) {
+ if (UseDynamicsOnly && subDestinations.Count == 1) {
+ basisMenuItem.Tag = subDestinations[0];
+ basisMenuItem.Text = subDestinations[0].Description;
+ basisMenuItem.Click -= destinationClickHandler;
+ basisMenuItem.Click += destinationClickHandler;
+ } else {
+ foreach (IDestination subDestination in subDestinations) {
+ var destinationMenuItem = new ToolStripMenuItem(subDestination.Description)
+ {
+ Tag = subDestination,
+ Image = subDestination.DisplayIcon
+ };
+ destinationMenuItem.Click += destinationClickHandler;
+ AddTagEvents(destinationMenuItem, menu, subDestination.Description);
+ basisMenuItem.DropDownItems.Add(destinationMenuItem);
+ }
+ }
+ }
+ }
+ };
+ }
+
+ return basisMenuItem;
+ }
+
+ }
+}
diff --git a/GreenshotPlugin/Core/AbstractProcessor.cs b/GreenshotPlugin/Core/AbstractProcessor.cs
new file mode 100644
index 000000000..69b9a9298
--- /dev/null
+++ b/GreenshotPlugin/Core/AbstractProcessor.cs
@@ -0,0 +1,73 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+using Greenshot.Plugin;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of AbstractProcessor.
+ ///
+ public abstract class AbstractProcessor : IProcessor {
+
+ public virtual int CompareTo(object obj) {
+ IProcessor other = obj as IProcessor;
+ if (other == null) {
+ return 1;
+ }
+ if (Priority == other.Priority) {
+ return Description.CompareTo(other.Description);
+ }
+ return Priority - other.Priority;
+ }
+
+ public abstract string Designation {
+ get;
+ }
+
+ public abstract string Description {
+ get;
+ }
+
+ public virtual int Priority {
+ get {
+ return 10;
+ }
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ //if (disposing) {}
+ }
+
+ public virtual bool isActive {
+ get {
+ return true;
+ }
+ }
+
+ public abstract bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails);
+ }
+}
diff --git a/GreenshotPlugin/Core/AccessibleHelper.cs b/GreenshotPlugin/Core/AccessibleHelper.cs
new file mode 100644
index 000000000..9b6064f30
--- /dev/null
+++ b/GreenshotPlugin/Core/AccessibleHelper.cs
@@ -0,0 +1,286 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using Accessibility;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+
+ ///
+ /// See: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/03a8c835-e9e4-405b-8345-6c3d36bc8941
+ /// This should really be cleaned up, there is little OO behind this class!
+ /// Maybe move the basic Accessible functions to WindowDetails!?
+ ///
+ public class Accessible {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Accessible));
+
+ #region Interop
+ private static int AccessibleObjectFromWindow(IntPtr hWnd, OBJID idObject, ref IAccessible acc) {
+ var guid = new Guid("{618736e0-3c3d-11cf-810c-00aa00389b71}"); // IAccessible
+ object obj = null;
+ int num = AccessibleObjectFromWindow(hWnd, (uint)idObject, ref guid, ref obj);
+ acc = (IAccessible)obj;
+ return num;
+ }
+ [DllImport("oleacc.dll")]
+ private static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint id, ref Guid iid, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);
+ [DllImport("oleacc.dll")]
+ private static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] object[] rgvarChildren, out int pcObtained);
+
+ [DllImport("oleacc.dll", PreserveSig=false)]
+ [return: MarshalAs(UnmanagedType.Interface)]
+ public static extern object ObjectFromLresult(UIntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam);
+ #endregion
+
+ private enum OBJID : uint {
+ OBJID_WINDOW = 0x00000000,
+ }
+
+ private const int IE_ACTIVE_TAB = 2097154;
+ private const int CHILDID_SELF = 0;
+ private readonly IAccessible accessible;
+ private Accessible[] Children {
+ get {
+ int num;
+ object[] res = GetAccessibleChildren(accessible, out num);
+ if (res == null) {
+ return new Accessible[0];
+ }
+
+ List list = new List(res.Length);
+ foreach (object obj in res) {
+ IAccessible acc = obj as IAccessible;
+ if (acc != null) {
+ list.Add(new Accessible(acc));
+ }
+ }
+ return list.ToArray();
+ }
+ }
+
+ private string Name {
+ get {
+ return accessible.get_accName(CHILDID_SELF);
+ }
+ }
+
+ private int ChildCount {
+ get {
+ return accessible.accChildCount;
+ }
+ }
+
+ public Accessible(IntPtr hWnd) {
+ AccessibleObjectFromWindow(hWnd, OBJID.OBJID_WINDOW, ref accessible);
+ if (accessible == null) {
+ throw new Exception();
+ }
+ }
+
+ public void ActivateIETab(string tabCaptionToActivate) {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ if (tab.Name == tabCaptionToActivate) {
+ tab.Activate();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public void CloseIETab(string tabCaptionToClose) {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ if (tab.Name == tabCaptionToClose) {
+ foreach (var CloseTab in tab.Children) {
+ CloseTab.Activate();
+ }
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public void ActivateIETab(int tabIndexToActivate) {
+ var index = 0;
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ if (tabIndexToActivate >= child.ChildCount -1) {
+ return;
+ }
+
+ if (index == tabIndexToActivate) {
+ tab.Activate();
+ return;
+ }
+ index++;
+ }
+ }
+ }
+ }
+
+ public string IEActiveTabUrl {
+ get {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ object tabIndex = tab.accessible.get_accState(CHILDID_SELF);
+
+ if ((int)tabIndex == IE_ACTIVE_TAB) {
+ var description = tab.accessible.get_accDescription(CHILDID_SELF);
+
+ if (!string.IsNullOrEmpty(description)) {
+ if (description.Contains(Environment.NewLine)) {
+ var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim();
+ return url;
+ }
+ }
+ }
+ }
+ }
+ }
+ return string.Empty;
+ }
+ }
+
+ public int IEActiveTabIndex {
+ get {
+ var index = 0;
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ object tabIndex = tab.accessible.get_accState(0);
+
+ if ((int)tabIndex == IE_ACTIVE_TAB) {
+ return index;
+ }
+ index++;
+ }
+ }
+ }
+ return -1;
+ }
+ }
+
+ public string IEActiveTabCaption {
+ get {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ object tabIndex = tab.accessible.get_accState(0);
+
+ if ((int)tabIndex == IE_ACTIVE_TAB) {
+ return tab.Name;
+ }
+ }
+ }
+ }
+ return string.Empty;
+ }
+ }
+
+ public List IETabCaptions {
+ get {
+ var captionList = new List();
+
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ captionList.Add(tab.Name);
+ }
+ }
+ }
+
+ // TODO: Why again?
+ if (captionList.Count > 0) {
+ captionList.RemoveAt(captionList.Count - 1);
+ }
+
+ return captionList;
+ }
+ }
+
+
+ public IEnumerable IETabUrls {
+ get {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ object tabIndex = tab.accessible.get_accState(CHILDID_SELF);
+ var description = tab.accessible.get_accDescription(CHILDID_SELF);
+ if (!string.IsNullOrEmpty(description)) {
+ if (description.Contains(Environment.NewLine)) {
+ var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim();
+ yield return url;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public int IETabCount {
+ get {
+ foreach (Accessible accessor in Children) {
+ foreach (var child in accessor.Children) {
+ foreach (var tab in child.Children) {
+ return child.ChildCount - 1;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+
+ private Accessible(IAccessible acc) {
+ if (acc == null) {
+ throw new Exception();
+ }
+ accessible = acc;
+ }
+
+ private void Activate() {
+ accessible.accDoDefaultAction(CHILDID_SELF);
+ }
+
+ private static object[] GetAccessibleChildren(IAccessible ao, out int childs) {
+ childs = 0;
+ object[] ret = null;
+ int count = ao.accChildCount;
+
+ if (count > 0) {
+ ret = new object[count];
+ AccessibleChildren(ao, 0, count, ret, out childs);
+ }
+ return ret;
+ }
+ }
+}
+
diff --git a/GreenshotPlugin/Core/AnimationHelpers.cs b/GreenshotPlugin/Core/AnimationHelpers.cs
new file mode 100644
index 000000000..f34fb04ab
--- /dev/null
+++ b/GreenshotPlugin/Core/AnimationHelpers.cs
@@ -0,0 +1,571 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+
+namespace GreenshotPlugin.Core {
+
+ ///
+ /// Helper interface for passing base type
+ ///
+ public interface IAnimator {
+ ///
+ /// Is there a next frame?
+ ///
+ bool HasNext {
+ get;
+ }
+ ///
+ /// The amount of frames
+ ///
+ int Frames {
+ get;
+ }
+
+ ///
+ /// Current frame number
+ ///
+ int CurrentFrameNr {
+ get;
+ }
+ }
+
+ ///
+ /// This class is used to store a animation leg
+ ///
+ internal class AnimationLeg {
+ public T Destination {
+ get;
+ set;
+ }
+
+ public int Frames {
+ get;
+ set;
+ }
+
+ public EasingType EasingType {
+ get;
+ set;
+ }
+
+ public EasingMode EasingMode {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// Base class for the animation logic, this only implements Properties and a constructor
+ ///
+ /// Type for the animation, like Point/Rectangle/Size
+ public abstract class AnimatorBase : IAnimator {
+ private readonly Queue> _queue = new Queue>();
+
+ ///
+ /// Constructor
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public AnimatorBase(T first, T last, int frames, EasingType easingType, EasingMode easingMode) {
+ First = first;
+ Last = last;
+ Frames = frames;
+ Current = first;
+ EasingType = easingType;
+ EasingMode = easingMode;
+ }
+
+ ///
+ /// The amount of frames
+ ///
+ public int Frames {
+ get;
+ private set;
+ }
+
+ ///
+ /// Current frame number
+ ///
+ public int CurrentFrameNr { get; private set; }
+
+ ///
+ /// First animation value
+ ///
+ public T First { get; private set; }
+
+ ///
+ /// Last animation value, of this "leg"
+ ///
+ public T Last { get; private set; }
+
+ ///
+ /// Final animation value, this is including the legs
+ ///
+ public T Final {
+ get {
+ if (_queue.Count == 0) {
+ return Last;
+ }
+ return _queue.ToArray()[_queue.Count - 1].Destination;
+ }
+ }
+
+ ///
+ /// This restarts the current animation and changes the last frame
+ ///
+ ///
+ public void ChangeDestination(T newDestination) {
+ ChangeDestination(newDestination, Frames);
+ }
+
+ ///
+ /// This restarts the current animation and changes the last frame
+ ///
+ ///
+ ///
+ public void ChangeDestination(T newDestination, int frames) {
+ _queue.Clear();
+ First = Current;
+ CurrentFrameNr = 0;
+ Frames = frames;
+ Last = newDestination;
+ }
+
+ ///
+ /// Queue the destination, it will be used to continue at the last frame
+ /// All values will stay the same
+ ///
+ ///
+ public void QueueDestinationLeg(T queuedDestination) {
+ QueueDestinationLeg(queuedDestination, Frames, EasingType, EasingMode);
+ }
+
+ ///
+ /// Queue the destination, it will be used to continue at the last frame
+ ///
+ ///
+ ///
+ public void QueueDestinationLeg(T queuedDestination, int frames) {
+ QueueDestinationLeg(queuedDestination, frames, EasingType, EasingMode);
+ }
+
+ ///
+ /// Queue the destination, it will be used to continue at the last frame
+ ///
+ ///
+ ///
+ /// EasingType
+ public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType) {
+ QueueDestinationLeg(queuedDestination, frames, easingType, EasingMode);
+ }
+
+ ///
+ /// Queue the destination, it will be used to continue at the last frame
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType, EasingMode easingMode) {
+ AnimationLeg leg = new AnimationLeg
+ {
+ Destination = queuedDestination,
+ Frames = frames,
+ EasingType = easingType,
+ EasingMode = easingMode
+ };
+ _queue.Enqueue(leg);
+ }
+
+ ///
+ /// The EasingType to use for the animation
+ ///
+ public EasingType EasingType {
+ get;
+ set;
+ }
+
+ ///
+ /// The EasingMode to use for the animation
+ ///
+ public EasingMode EasingMode {
+ get;
+ set;
+ }
+
+ ///
+ /// Get the easing value, which is from 0-1 and depends on the frame
+ ///
+ protected double EasingValue {
+ get {
+ switch (EasingMode) {
+ case EasingMode.EaseOut:
+ return Easing.EaseOut(CurrentFrameNr / (double)Frames, EasingType);
+ case EasingMode.EaseInOut:
+ return Easing.EaseInOut(CurrentFrameNr / (double)Frames, EasingType);
+ case EasingMode.EaseIn:
+ default:
+ return Easing.EaseIn(CurrentFrameNr / (double)Frames, EasingType);
+ }
+ }
+ }
+
+ ///
+ /// Get the current (previous) frame object
+ ///
+ public virtual T Current { get; set; }
+
+ ///
+ /// Returns if there are any frame left, and if this is the case than the frame is increased.
+ ///
+ public virtual bool NextFrame {
+ get {
+ if (CurrentFrameNr < Frames) {
+ CurrentFrameNr++;
+ return true;
+ }
+ if (_queue.Count > 0) {
+ First = Current;
+ CurrentFrameNr = 0;
+ AnimationLeg nextLeg = _queue.Dequeue();
+ Last = nextLeg.Destination;
+ Frames = nextLeg.Frames;
+ EasingType = nextLeg.EasingType;
+ EasingMode = nextLeg.EasingMode;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ ///
+ /// Are there more frames to animate?
+ ///
+ public virtual bool HasNext {
+ get {
+ if (CurrentFrameNr < Frames) {
+ return true;
+ }
+ return _queue.Count > 0;
+ }
+ }
+
+ ///
+ /// Get the next animation frame value object
+ ///
+ ///
+ public abstract T Next();
+ }
+
+ ///
+ /// Implementation of the RectangleAnimator
+ ///
+ public class RectangleAnimator : AnimatorBase {
+ public RectangleAnimator(Rectangle first, Rectangle last, int frames)
+ : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) {
+ }
+ public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType)
+ : base(first, last, frames, easingType, EasingMode.EaseIn) {
+ }
+
+ public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType, EasingMode easingMode)
+ : base(first, last, frames, easingType, easingMode) {
+ }
+
+ ///
+ /// Calculate the next frame object
+ ///
+ /// Rectangle
+ public override Rectangle Next() {
+ if (NextFrame) {
+ double easingValue = EasingValue;
+ double dx = Last.X - First.X;
+ double dy = Last.Y - First.Y;
+
+ int x = First.X + (int)(easingValue * dx);
+ int y = First.Y + (int)(easingValue * dy);
+ double dw = Last.Width - First.Width;
+ double dh = Last.Height - First.Height;
+ int width = First.Width + (int)(easingValue * dw);
+ int height = First.Height + (int)(easingValue * dh);
+ Current = new Rectangle(x, y, width, height);
+ }
+ return Current;
+ }
+ }
+
+ ///
+ /// Implementation of the PointAnimator
+ ///
+ public class PointAnimator : AnimatorBase {
+ public PointAnimator(Point first, Point last, int frames)
+ : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) {
+ }
+ public PointAnimator(Point first, Point last, int frames, EasingType easingType)
+ : base(first, last, frames, easingType, EasingMode.EaseIn) {
+ }
+ public PointAnimator(Point first, Point last, int frames, EasingType easingType, EasingMode easingMode)
+ : base(first, last, frames, easingType, easingMode) {
+ }
+
+ ///
+ /// Calculate the next frame value
+ ///
+ /// Point
+ public override Point Next() {
+ if (NextFrame) {
+ double easingValue = EasingValue;
+ double dx = Last.X - First.X;
+ double dy = Last.Y - First.Y;
+
+ int x = First.X + (int)(easingValue * dx);
+ int y = First.Y + (int)(easingValue * dy);
+ Current = new Point(x, y);
+ }
+ return Current;
+ }
+ }
+
+ ///
+ /// Implementation of the SizeAnimator
+ ///
+ public class SizeAnimator : AnimatorBase {
+ public SizeAnimator(Size first, Size last, int frames)
+ : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) {
+ }
+ public SizeAnimator(Size first, Size last, int frames, EasingType easingType)
+ : base(first, last, frames, easingType, EasingMode.EaseIn) {
+ }
+ public SizeAnimator(Size first, Size last, int frames, EasingType easingType, EasingMode easingMode)
+ : base(first, last, frames, easingType, easingMode) {
+ }
+
+ ///
+ /// Calculate the next frame values
+ ///
+ /// Size
+ public override Size Next() {
+ if (NextFrame) {
+ double easingValue = EasingValue;
+ double dw = Last.Width - First.Width;
+ double dh = Last.Height - First.Height;
+ int width = First.Width + (int)(easingValue * dw);
+ int height = First.Height + (int)(easingValue * dh);
+ Current = new Size(width, height);
+ }
+ return Current;
+ }
+ }
+
+ ///
+ /// Implementation of the ColorAnimator
+ ///
+ public class ColorAnimator : AnimatorBase {
+ public ColorAnimator(Color first, Color last, int frames)
+ : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) {
+ }
+ public ColorAnimator(Color first, Color last, int frames, EasingType easingType)
+ : base(first, last, frames, easingType, EasingMode.EaseIn) {
+ }
+ public ColorAnimator(Color first, Color last, int frames, EasingType easingType, EasingMode easingMode)
+ : base(first, last, frames, easingType, easingMode) {
+ }
+
+ ///
+ /// Calculate the next frame values
+ ///
+ /// Color
+ public override Color Next() {
+ if (NextFrame) {
+ double easingValue = EasingValue;
+ double da = Last.A - First.A;
+ double dr = Last.R - First.R;
+ double dg = Last.G - First.G;
+ double db = Last.B - First.B;
+ int a = First.A + (int)(easingValue * da);
+ int r = First.R + (int)(easingValue * dr);
+ int g = First.G + (int)(easingValue * dg);
+ int b = First.B + (int)(easingValue * db);
+ Current = Color.FromArgb(a,r,g,b);
+ }
+ return Current;
+ }
+ }
+
+ ///
+ /// Implementation of the IntAnimator
+ ///
+ public class IntAnimator : AnimatorBase {
+ public IntAnimator(int first, int last, int frames)
+ : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) {
+ }
+ public IntAnimator(int first, int last, int frames, EasingType easingType)
+ : base(first, last, frames, easingType, EasingMode.EaseIn) {
+ }
+ public IntAnimator(int first, int last, int frames, EasingType easingType, EasingMode easingMode)
+ : base(first, last, frames, easingType, easingMode) {
+ }
+
+ ///
+ /// Calculate the next frame values
+ ///
+ /// int
+ public override int Next() {
+ if (NextFrame) {
+ double easingValue = EasingValue;
+ double delta = Last - First;
+ Current = First + (int)(easingValue * delta);
+ }
+ return Current;
+ }
+ }
+
+ ///
+ /// Easing logic, to make the animations more "fluent"
+ ///
+ public static class Easing {
+ // Adapted from http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf
+
+ public static double Ease(double linearStep, double acceleration, EasingType type) {
+ double easedStep = acceleration > 0 ? EaseIn(linearStep, type) : acceleration < 0 ? EaseOut(linearStep, type) : linearStep;
+ // Lerp:
+ return ((easedStep - linearStep) * Math.Abs(acceleration) + linearStep);
+ }
+
+ public static double EaseIn(double linearStep, EasingType type) {
+ switch (type) {
+ case EasingType.Step:
+ return linearStep < 0.5 ? 0 : 1;
+ case EasingType.Linear:
+ return linearStep;
+ case EasingType.Sine:
+ return Sine.EaseIn(linearStep);
+ case EasingType.Quadratic:
+ return Power.EaseIn(linearStep, 2);
+ case EasingType.Cubic:
+ return Power.EaseIn(linearStep, 3);
+ case EasingType.Quartic:
+ return Power.EaseIn(linearStep, 4);
+ case EasingType.Quintic:
+ return Power.EaseIn(linearStep, 5);
+ }
+ throw new NotImplementedException();
+ }
+
+ public static double EaseOut(double linearStep, EasingType type) {
+ switch (type) {
+ case EasingType.Step:
+ return linearStep < 0.5 ? 0 : 1;
+ case EasingType.Linear:
+ return linearStep;
+ case EasingType.Sine:
+ return Sine.EaseOut(linearStep);
+ case EasingType.Quadratic:
+ return Power.EaseOut(linearStep, 2);
+ case EasingType.Cubic:
+ return Power.EaseOut(linearStep, 3);
+ case EasingType.Quartic:
+ return Power.EaseOut(linearStep, 4);
+ case EasingType.Quintic:
+ return Power.EaseOut(linearStep, 5);
+ }
+ throw new NotImplementedException();
+ }
+
+ public static double EaseInOut(double linearStep, EasingType easeInType, EasingType easeOutType) {
+ return linearStep < 0.5 ? EaseInOut(linearStep, easeInType) : EaseInOut(linearStep, easeOutType);
+ }
+
+ public static double EaseInOut(double linearStep, EasingType type) {
+ switch (type) {
+ case EasingType.Step:
+ return linearStep < 0.5 ? 0 : 1;
+ case EasingType.Linear:
+ return linearStep;
+ case EasingType.Sine:
+ return Sine.EaseInOut(linearStep);
+ case EasingType.Quadratic:
+ return Power.EaseInOut(linearStep, 2);
+ case EasingType.Cubic:
+ return Power.EaseInOut(linearStep, 3);
+ case EasingType.Quartic:
+ return Power.EaseInOut(linearStep, 4);
+ case EasingType.Quintic:
+ return Power.EaseInOut(linearStep, 5);
+ }
+ throw new NotImplementedException();
+ }
+
+ private static class Sine {
+ public static double EaseIn(double s) {
+ return Math.Sin(s * (Math.PI / 2) - (Math.PI / 2)) + 1;
+ }
+ public static double EaseOut(double s) {
+ return Math.Sin(s * (Math.PI / 2));
+ }
+ public static double EaseInOut(double s) {
+ return Math.Sin(s * Math.PI - (Math.PI / 2) + 1) / 2;
+ }
+ }
+
+ private static class Power {
+ public static double EaseIn(double s, int power) {
+ return Math.Pow(s, power);
+ }
+ public static double EaseOut(double s, int power) {
+ var sign = power % 2 == 0 ? -1 : 1;
+ return sign * (Math.Pow(s - 1, power) + sign);
+ }
+ public static double EaseInOut(double s, int power) {
+ s *= 2;
+ if (s < 1) {
+ return EaseIn(s, power) / 2;
+ }
+ var sign = power % 2 == 0 ? -1 : 1;
+ return (sign / 2.0 * (Math.Pow(s - 2, power) + sign * 2));
+ }
+ }
+ }
+
+ ///
+ /// This defines the way the animation works
+ ///
+ public enum EasingType {
+ Step,
+ Linear,
+ Sine,
+ Quadratic,
+ Cubic,
+ Quartic,
+ Quintic
+ }
+
+ public enum EasingMode {
+ EaseIn,
+ EaseOut,
+ EaseInOut
+ }
+}
diff --git a/GreenshotPlugin/Core/BinaryStructHelper.cs b/GreenshotPlugin/Core/BinaryStructHelper.cs
new file mode 100644
index 000000000..390d029e0
--- /dev/null
+++ b/GreenshotPlugin/Core/BinaryStructHelper.cs
@@ -0,0 +1,93 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Runtime.InteropServices;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// A helper class which does the mashalling for structs
+ ///
+ public static class BinaryStructHelper {
+ ///
+ /// Get a struct from a byte array
+ ///
+ /// typeof struct
+ /// byte[]
+ /// struct
+ public static T FromByteArray(byte[] bytes) where T : struct {
+ IntPtr ptr = IntPtr.Zero;
+ try {
+ int size = Marshal.SizeOf(typeof(T));
+ ptr = Marshal.AllocHGlobal(size);
+ Marshal.Copy(bytes, 0, ptr, size);
+ return FromIntPtr(ptr);
+ } finally {
+ if (ptr != IntPtr.Zero) {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+ }
+
+ ///
+ /// Get a struct from a byte array
+ ///
+ /// typeof struct
+ /// Pointer to the structor to return
+ /// struct
+ public static T FromIntPtr(IntPtr intPtr) where T : struct {
+ object obj = Marshal.PtrToStructure(intPtr, typeof(T));
+ return (T)obj;
+ }
+
+ ///
+ /// copy a struct to a byte array
+ ///
+ /// typeof struct
+ /// struct
+ /// byte[]
+ public static byte[] ToByteArray(T obj) where T : struct {
+ IntPtr ptr = IntPtr.Zero;
+ try {
+ int size = Marshal.SizeOf(typeof(T));
+ ptr = Marshal.AllocHGlobal(size);
+ Marshal.StructureToPtr(obj, ptr, true);
+ return FromPtrToByteArray(ptr);
+ } finally {
+ if (ptr != IntPtr.Zero) {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+ }
+
+ ///
+ /// copy a struct from a pointer to a byte array
+ ///
+ /// typeof struct
+ /// IntPtr to struct
+ /// byte[]
+ public static byte[] FromPtrToByteArray(IntPtr ptr) where T : struct {
+ int size = Marshal.SizeOf(typeof(T));
+ byte[] bytes = new byte[size];
+ Marshal.Copy(ptr, bytes, 0, size);
+ return bytes;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/Cache.cs b/GreenshotPlugin/Core/Cache.cs
new file mode 100644
index 000000000..61604c23b
--- /dev/null
+++ b/GreenshotPlugin/Core/Cache.cs
@@ -0,0 +1,214 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Timers;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Cache class
+ ///
+ /// Type of key
+ /// Type of value
+ public class Cache {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Cache));
+ private readonly IDictionary _internalCache = new Dictionary();
+ private readonly object _lockObject = new object();
+ private readonly int _secondsToExpire = 10;
+ private readonly CacheObjectExpired _expiredCallback;
+ public delegate void CacheObjectExpired(TK key, TV cacheValue);
+
+ ///
+ /// Initialize the cache
+ ///
+ public Cache() {
+ }
+ ///
+ /// Initialize the cache
+ ///
+ ///
+ public Cache(CacheObjectExpired expiredCallback) : this() {
+ _expiredCallback = expiredCallback;
+ }
+
+ ///
+ /// Initialize the cache with a expire setting
+ ///
+ ///
+ public Cache(int secondsToExpire) : this() {
+ _secondsToExpire = secondsToExpire;
+ }
+
+ ///
+ /// Initialize the cache with a expire setting
+ ///
+ ///
+ ///
+ public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback) {
+ _secondsToExpire = secondsToExpire;
+ }
+
+ ///
+ /// Enumerable for the values in the cache
+ ///
+ public IEnumerable Elements {
+ get {
+ List elements = new List();
+
+ lock (_lockObject)
+ {
+ foreach (TV element in _internalCache.Values) {
+ elements.Add(element);
+ }
+ }
+ foreach (TV element in elements) {
+ yield return element;
+ }
+ }
+ }
+
+ ///
+ /// Get the value by key from the cache
+ ///
+ ///
+ ///
+ public TV this[TK key] {
+ get {
+ TV result = default(TV);
+ lock (_lockObject) {
+ if (_internalCache.ContainsKey(key)) {
+ result = _internalCache[key];
+ }
+ }
+ return result;
+ }
+ }
+
+ ///
+ /// Contains
+ ///
+ ///
+ /// true if the cache contains the key
+ public bool Contains(TK key)
+ {
+ lock (_lockObject)
+ {
+ return _internalCache.ContainsKey(key);
+ }
+ }
+
+ ///
+ /// Add a value to the cache
+ ///
+ ///
+ ///
+ public void Add(TK key, TV value) {
+ Add(key, value, null);
+ }
+
+ ///
+ /// Add a value to the cache
+ ///
+ ///
+ ///
+ /// optional value for the seconds to expire
+ public void Add(TK key, TV value, int? secondsToExpire) {
+ lock (_lockObject) {
+ var cachedItem = new CachedItem(key, value, secondsToExpire ?? _secondsToExpire);
+ cachedItem.Expired += delegate(TK cacheKey, TV cacheValue) {
+ if (_internalCache.ContainsKey(cacheKey)) {
+ Log.DebugFormat("Expiring object with Key: {0}", cacheKey);
+ _expiredCallback?.Invoke(cacheKey, cacheValue);
+ Remove(cacheKey);
+ } else {
+ Log.DebugFormat("Expired old object with Key: {0}", cacheKey);
+ }
+ };
+
+ if (_internalCache.ContainsKey(key)) {
+ _internalCache[key] = value;
+ Log.DebugFormat("Updated item with Key: {0}", key);
+ } else {
+ _internalCache.Add(key, cachedItem);
+ Log.DebugFormat("Added item with Key: {0}", key);
+ }
+ }
+ }
+
+ ///
+ /// Remove item from cache
+ ///
+ ///
+ public void Remove(TK key) {
+ lock (_lockObject) {
+ if (!_internalCache.ContainsKey(key)) {
+ throw new ApplicationException($"An object with key ‘{key}’ does not exists in cache");
+ }
+ _internalCache.Remove(key);
+ Log.DebugFormat("Removed item with Key: {0}", key);
+ }
+ }
+
+ ///
+ /// A cache item
+ ///
+ private class CachedItem {
+ public event CacheObjectExpired Expired;
+ private readonly int _secondsToExpire;
+ private readonly Timer _timerEvent;
+
+ public CachedItem(TK key, TV item, int secondsToExpire) {
+ if (key == null) {
+ throw new ArgumentNullException(nameof(key));
+ }
+ Key = key;
+ Item = item;
+ _secondsToExpire = secondsToExpire;
+ if (secondsToExpire <= 0)
+ {
+ return;
+ }
+ _timerEvent = new Timer(secondsToExpire * 1000) { AutoReset = false };
+ _timerEvent.Elapsed += timerEvent_Elapsed;
+ _timerEvent.Start();
+ }
+
+ private void ExpireNow() {
+ _timerEvent.Stop();
+ if (_secondsToExpire > 0) {
+ Expired?.Invoke(Key, Item);
+ }
+ }
+
+ private void timerEvent_Elapsed(object sender, ElapsedEventArgs e) {
+ ExpireNow();
+ }
+
+ public TK Key { get; private set; }
+ public TV Item { get; private set; }
+
+ public static implicit operator TV(CachedItem a) {
+ return a.Item;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/CaptureHandler.cs b/GreenshotPlugin/Core/CaptureHandler.cs
new file mode 100644
index 000000000..0f52bfe38
--- /dev/null
+++ b/GreenshotPlugin/Core/CaptureHandler.cs
@@ -0,0 +1,44 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.Drawing;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// This is the method signature which is used to capture a rectangle from the screen.
+ ///
+ ///
+ /// Captured Bitmap
+ public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
+
+ ///
+ /// This is a hack to experiment with different screen capture routines
+ ///
+ public static class CaptureHandler {
+ ///
+ /// By changing this value, null is default
+ ///
+ public static CaptureScreenRectangleHandler CaptureScreenRectangle {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/ClipboardHelper.cs b/GreenshotPlugin/Core/ClipboardHelper.cs
new file mode 100644
index 000000000..e46821b22
--- /dev/null
+++ b/GreenshotPlugin/Core/ClipboardHelper.cs
@@ -0,0 +1,850 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.UnmanagedHelpers;
+using System.Runtime.InteropServices;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of ClipboardHelper.
+ ///
+ public static class ClipboardHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ClipboardHelper));
+ private static readonly object ClipboardLockObject = new object();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly string FORMAT_FILECONTENTS = "FileContents";
+ private static readonly string FORMAT_PNG = "PNG";
+ private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art";
+ private static readonly string FORMAT_17 = "Format17";
+ private static readonly string FORMAT_JPG = "JPG";
+ private static readonly string FORMAT_JFIF = "JFIF";
+ private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art";
+ private static readonly string FORMAT_GIF = "GIF";
+ private static readonly string FORMAT_BITMAP = "System.Drawing.Bitmap";
+ //private static readonly string FORMAT_HTML = "HTML Format";
+
+ // Template for the HTML Text on the clipboard
+ // see: http://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx
+ // or: http://msdn.microsoft.com/en-us/library/Aa767917.aspx
+ private const string HtmlClipboardString = @"Version:0.9
+StartHTML:<<<<<<<1
+EndHTML:<<<<<<<2
+StartFragment:<<<<<<<3
+EndFragment:<<<<<<<4
+StartSelection:<<<<<<<3
+EndSelection:<<<<<<<4
+
+
+
+Greenshot capture
+
+
+
+
+
+
+";
+ private const string HtmlClipboardBase64String = @"Version:0.9
+StartHTML:<<<<<<<1
+EndHTML:<<<<<<<2
+StartFragment:<<<<<<<3
+EndFragment:<<<<<<<4
+StartSelection:<<<<<<<3
+EndSelection:<<<<<<<4
+
+
+
+Greenshot capture
+
+
+
+
+
+
+";
+
+ ///
+ /// Get the current "ClipboardOwner" but only if it isn't us!
+ ///
+ /// current clipboard owner
+ private static string GetClipboardOwner() {
+ string owner = null;
+ try {
+ IntPtr hWnd = User32.GetClipboardOwner();
+ if (hWnd != IntPtr.Zero) {
+ try
+ {
+ int pid;
+ User32.GetWindowThreadProcessId(hWnd, out pid);
+ using (Process me = Process.GetCurrentProcess())
+ using (Process ownerProcess = Process.GetProcessById(pid))
+ {
+ // Exclude myself
+ if (me.Id != ownerProcess.Id)
+ {
+ // Get Process Name
+ owner = ownerProcess.ProcessName;
+ // Try to get the starting Process Filename, this might fail.
+ try
+ {
+ owner = ownerProcess.Modules[0].FileName;
+ }
+ catch (Exception)
+ {
+ // Ignore
+ }
+ }
+ }
+ }
+ catch(Exception e)
+ {
+ Log.Warn("Non critical error: Couldn't get clipboard process, trying to use the title.", e);
+ var title = new StringBuilder(260, 260);
+ User32.GetWindowText(hWnd, title, title.Capacity);
+ owner = title.ToString();
+ }
+ }
+ } catch (Exception e) {
+ Log.Warn("Non critical error: Couldn't get clipboard owner.", e);
+ }
+ return owner;
+ }
+
+ ///
+ /// The SetDataObject will lock/try/catch clipboard operations making it save and not show exceptions.
+ /// The bool "copy" is used to decided if the information stays on the clipboard after exit.
+ ///
+ ///
+ ///
+ private static void SetDataObject(IDataObject ido, bool copy) {
+ lock (ClipboardLockObject) {
+ // Clear first, this seems to solve some issues
+ try
+ {
+ Clipboard.Clear();
+ }
+ catch (Exception clearException)
+ {
+ Log.Warn(clearException.Message);
+ }
+ try
+ {
+ // For BUG-1935 this was changed from looping ourselfs, or letting MS retry...
+ Clipboard.SetDataObject(ido, copy, 15, 200);
+ }
+ catch (Exception clipboardSetException)
+ {
+ string messageText;
+ string clipboardOwner = GetClipboardOwner();
+ if (clipboardOwner != null)
+ {
+ messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner);
+ }
+ else {
+ messageText = Language.GetString("clipboard_error");
+ }
+ Log.Error(messageText, clipboardSetException);
+ }
+ }
+ }
+
+ ///
+ /// The GetDataObject will lock/try/catch clipboard operations making it save and not show exceptions.
+ ///
+ public static IDataObject GetDataObject() {
+ lock (ClipboardLockObject) {
+ int retryCount = 2;
+ while (retryCount >= 0) {
+ try {
+ return Clipboard.GetDataObject();
+ } catch (Exception ee) {
+ if (retryCount == 0) {
+ string messageText;
+ string clipboardOwner = GetClipboardOwner();
+ if (clipboardOwner != null) {
+ messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner);
+ } else {
+ messageText = Language.GetString("clipboard_error");
+ }
+ Log.Error(messageText, ee);
+ } else {
+ Thread.Sleep(100);
+ }
+ } finally {
+ --retryCount;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Wrapper for Clipboard.ContainsText, Created for Bug #3432313
+ ///
+ /// boolean if there is text on the clipboard
+ public static bool ContainsText() {
+ IDataObject clipboardData = GetDataObject();
+ return ContainsText(clipboardData);
+ }
+
+ ///
+ /// Test if the IDataObject contains Text
+ ///
+ ///
+ ///
+ public static bool ContainsText(IDataObject dataObject) {
+ if (dataObject != null) {
+ if (dataObject.GetDataPresent(DataFormats.Text) || dataObject.GetDataPresent(DataFormats.UnicodeText)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Wrapper for Clipboard.ContainsImage, specialized for Greenshot, Created for Bug #3432313
+ ///
+ /// boolean if there is an image on the clipboard
+ public static bool ContainsImage() {
+ IDataObject clipboardData = GetDataObject();
+ return ContainsImage(clipboardData);
+ }
+
+ ///
+ /// Check if the IDataObject has an image
+ ///
+ ///
+ /// true if an image is there
+ public static bool ContainsImage(IDataObject dataObject) {
+ if (dataObject != null) {
+ if (dataObject.GetDataPresent(DataFormats.Bitmap)
+ || dataObject.GetDataPresent(DataFormats.Dib)
+ || dataObject.GetDataPresent(DataFormats.Tiff)
+ || dataObject.GetDataPresent(DataFormats.EnhancedMetafile)
+ || dataObject.GetDataPresent(FORMAT_PNG)
+ || dataObject.GetDataPresent(FORMAT_17)
+ || dataObject.GetDataPresent(FORMAT_JPG)
+ || dataObject.GetDataPresent(FORMAT_GIF)) {
+ return true;
+ }
+ var imageFiles = GetImageFilenames(dataObject);
+ if (imageFiles.Any()) {
+ return true;
+ }
+ if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) {
+ try {
+ MemoryStream imageStream = dataObject.GetData(FORMAT_FILECONTENTS) as MemoryStream;
+ if (IsValidStream(imageStream)) {
+ using (ImageHelper.FromStream(imageStream))
+ {
+ // If we get here, there is an image
+ return true;
+ }
+ }
+ } catch (Exception) {
+ // Ignore
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Simple helper to check the stream
+ ///
+ ///
+ ///
+ private static bool IsValidStream(MemoryStream memoryStream) {
+ return memoryStream != null && memoryStream.Length > 0;
+ }
+
+ ///
+ /// Wrapper for Clipboard.GetImage, Created for Bug #3432313
+ ///
+ /// Image if there is an image on the clipboard
+ public static Image GetImage() {
+ IDataObject clipboardData = GetDataObject();
+ // Return the first image
+ foreach (Image clipboardImage in GetImages(clipboardData)) {
+ return clipboardImage;
+ }
+ return null;
+ }
+
+ ///
+ /// Get all images (multiple if filenames are available) from the dataObject
+ /// Returned images must be disposed by the calling code!
+ ///
+ ///
+ /// IEnumerable of Image
+ public static IEnumerable GetImages(IDataObject dataObject) {
+ // Get single image, this takes the "best" match
+ Image singleImage = GetImage(dataObject);
+ if (singleImage != null) {
+ Log.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat);
+ yield return singleImage;
+ } else {
+ // check if files are supplied
+ foreach (string imageFile in GetImageFilenames(dataObject)) {
+ Image returnImage = null;
+ try {
+ returnImage = ImageHelper.LoadImage(imageFile);
+ } catch (Exception streamImageEx) {
+ Log.Error("Problem retrieving Image from clipboard.", streamImageEx);
+ }
+ if (returnImage != null) {
+ Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat);
+ yield return returnImage;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Get an Image from the IDataObject, don't check for FileDrop
+ ///
+ ///
+ /// Image or null
+ private static Image GetImage(IDataObject dataObject) {
+ Image returnImage = null;
+ if (dataObject != null) {
+ IList formats = GetFormats(dataObject);
+ string[] retrieveFormats;
+
+ // Found a weird bug, where PNG's from Outlook 2010 are clipped
+ // So I build some special logik to get the best format:
+ if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib)) {
+ // Outlook ??
+ Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
+ retrieveFormats = new[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
+ } else {
+ retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF };
+ }
+ foreach (string currentFormat in retrieveFormats) {
+ if (formats != null && formats.Contains(currentFormat)) {
+ Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
+ returnImage = GetImageForFormat(currentFormat, dataObject);
+ } else {
+ Log.DebugFormat("Couldn't find format {0}.", currentFormat);
+ }
+ if (returnImage != null) {
+ return returnImage;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Helper method to try to get an image in the specified format from the dataObject
+ /// the DIB reader should solve some issues
+ /// It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591
+ ///
+ /// string with the format
+ /// IDataObject
+ /// Image or null
+ private static Image GetImageForFormat(string format, IDataObject dataObject) {
+ object clipboardObject = GetFromDataObject(dataObject, format);
+ MemoryStream imageStream = clipboardObject as MemoryStream;
+ if (!IsValidStream(imageStream)) {
+ // TODO: add "HTML Format" support here...
+ return clipboardObject as Image;
+ }
+ if (CoreConfig.EnableSpecialDIBClipboardReader) {
+ if (format == FORMAT_17 || format == DataFormats.Dib) {
+ Log.Info("Found DIB stream, trying to process it.");
+ try {
+ if (imageStream != null)
+ {
+ byte[] dibBuffer = new byte[imageStream.Length];
+ imageStream.Read(dibBuffer, 0, dibBuffer.Length);
+ BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray(dibBuffer);
+ if (!infoHeader.IsDibV5) {
+ Log.InfoFormat("Using special DIB
+ /// Wrapper for Clipboard.GetText created for Bug #3432313
+ ///
+ /// string if there is text on the clipboard
+ public static string GetText() {
+ return GetText(GetDataObject());
+ }
+
+ ///
+ /// Get Text from the DataObject
+ ///
+ /// string if there is text on the clipboard
+ public static string GetText(IDataObject dataObject) {
+ if (ContainsText(dataObject)) {
+ return (string)dataObject.GetData(DataFormats.Text);
+ }
+ return null;
+ }
+
+ ///
+ /// Set text to the clipboard
+ ///
+ ///
+ public static void SetClipboardData(string text) {
+ IDataObject ido = new DataObject();
+ ido.SetData(DataFormats.Text, true, text);
+ SetDataObject(ido, true);
+ }
+
+ private static string GetHtmlString(ISurface surface, string filename) {
+ string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardString));
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString());
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString());
+ utf8EncodedHtmlString= utf8EncodedHtmlString.Replace("${file}", filename.Replace("\\","/"));
+ StringBuilder sb=new StringBuilder();
+ sb.Append(utf8EncodedHtmlString);
+ sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8"));
+ sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8"));
+ sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)+"".Length).ToString("D8"));
+ sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8"));
+ return sb.ToString();
+ }
+
+ private static string GetHtmlDataUrlString(ISurface surface, MemoryStream pngStream) {
+ string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardBase64String));
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString());
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString());
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${format}", "png");
+ utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${data}", Convert.ToBase64String(pngStream.GetBuffer(),0, (int)pngStream.Length));
+ StringBuilder sb=new StringBuilder();
+ sb.Append(utf8EncodedHtmlString);
+ sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8"));
+ sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8"));
+ sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)+"".Length).ToString("D8"));
+ sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8"));
+ return sb.ToString();
+ }
+
+ private const int BITMAPFILEHEADER_LENGTH = 14;
+ ///
+ /// Set an Image to the clipboard
+ /// This method will place images to the clipboard depending on the ClipboardFormats setting.
+ /// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice
+ /// because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661
+ /// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003!
+ /// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left!
+ /// For this problem the user should not use the direct paste (=Dib), but select Bitmap
+ ///
+ public static void SetClipboardData(ISurface surface) {
+ DataObject dataObject = new DataObject();
+
+ // This will work for Office and most other applications
+ //ido.SetData(DataFormats.Bitmap, true, image);
+
+ MemoryStream dibStream = null;
+ MemoryStream dibV5Stream = null;
+ MemoryStream pngStream = null;
+ Image imageToSave = null;
+ bool disposeImage = false;
+ try {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
+ // Create the image which is going to be saved so we don't create it multiple times
+ disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave);
+ try {
+ // Create PNG stream
+ if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.PNG)) {
+ pngStream = new MemoryStream();
+ // PNG works for e.g. Powerpoint
+ SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
+ ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings);
+ pngStream.Seek(0, SeekOrigin.Begin);
+ // Set the PNG stream
+ dataObject.SetData(FORMAT_PNG, false, pngStream);
+ }
+ } catch (Exception pngEx) {
+ Log.Error("Error creating PNG for the Clipboard.", pngEx);
+ }
+
+ try {
+ if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIB)) {
+ using (MemoryStream tmpBmpStream = new MemoryStream()) {
+ // Save image as BMP
+ SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false);
+ ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings);
+
+ dibStream = new MemoryStream();
+ // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14
+ dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int)tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH);
+ }
+
+ // Set the DIB to the clipboard DataObject
+ dataObject.SetData(DataFormats.Dib, true, dibStream);
+ }
+ } catch (Exception dibEx) {
+ Log.Error("Error creating DIB for the Clipboard.", dibEx);
+ }
+
+ // CF_DibV5
+ try {
+ if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIBV5)) {
+ // Create the stream for the clipboard
+ dibV5Stream = new MemoryStream();
+
+ // Create the BITMAPINFOHEADER
+ BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32)
+ {
+ // Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
+ biCompression = BI_COMPRESSION.BI_BITFIELDS
+ };
+ // Create a byte[] to write
+ byte[] headerBytes = BinaryStructHelper.ToByteArray(header);
+ // Write the BITMAPINFOHEADER to the stream
+ dibV5Stream.Write(headerBytes, 0, headerBytes.Length);
+
+ // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added
+ BitfieldColorMask colorMask = new BitfieldColorMask();
+ // Make sure the values are set
+ colorMask.InitValues();
+ // Create the byte[] from the struct
+ byte[] colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask);
+ Array.Reverse(colorMaskBytes);
+ // Write to the stream
+ dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length);
+
+ // Create the raw bytes for the pixels only
+ byte[] bitmapBytes = BitmapToByteArray((Bitmap)imageToSave);
+ // Write to the stream
+ dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length);
+
+ // Set the DIBv5 to the clipboard DataObject
+ dataObject.SetData(FORMAT_17, true, dibV5Stream);
+ }
+ } catch (Exception dibEx) {
+ Log.Error("Error creating DIB for the Clipboard.", dibEx);
+ }
+
+ // Set the HTML
+ if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTML)) {
+ string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null);
+ string html = GetHtmlString(surface, tmpFile);
+ dataObject.SetText(html, TextDataFormat.Html);
+ } else if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL)) {
+ string html;
+ using (MemoryStream tmpPngStream = new MemoryStream()) {
+ SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false)
+ {
+ // Do not allow to reduce the colors, some applications dislike 256 color images
+ // reported with bug #3594681
+ DisableReduceColors = true
+ };
+ // Check if we can use the previously used image
+ if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed) {
+ ImageOutput.SaveToStream(imageToSave, surface, tmpPngStream, pngOutputSettings);
+ } else {
+ ImageOutput.SaveToStream(surface, tmpPngStream, pngOutputSettings);
+ }
+ html = GetHtmlDataUrlString(surface, tmpPngStream);
+ }
+ dataObject.SetText(html, TextDataFormat.Html);
+ }
+ } finally {
+ // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone!
+ // Check if Bitmap is wanted
+ if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.BITMAP)) {
+ dataObject.SetImage(imageToSave);
+ // Place the DataObject to the clipboard
+ SetDataObject(dataObject, true);
+ } else {
+ // Place the DataObject to the clipboard
+ SetDataObject(dataObject, true);
+ }
+
+ pngStream?.Dispose();
+ dibStream?.Dispose();
+ dibV5Stream?.Dispose();
+ // cleanup if needed
+ if (disposeImage) {
+ imageToSave?.Dispose();
+ }
+ }
+ }
+
+ ///
+ /// Helper method so get the bitmap bytes
+ /// See: http://stackoverflow.com/a/6570155
+ ///
+ /// Bitmap
+ /// byte[]
+ private static byte[] BitmapToByteArray(Bitmap bitmap) {
+ // Lock the bitmap's bits.
+ Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
+ BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
+
+ int absStride = Math.Abs(bmpData.Stride);
+ int bytes = absStride * bitmap.Height;
+ long ptr = bmpData.Scan0.ToInt32();
+ // Declare an array to hold the bytes of the bitmap.
+ byte[] rgbValues = new byte[bytes];
+
+ for (int i = 0; i < bitmap.Height; i++) {
+ IntPtr pointer = new IntPtr(ptr + (bmpData.Stride * i));
+ Marshal.Copy(pointer, rgbValues, absStride * (bitmap.Height - i - 1), absStride);
+ }
+
+ // Unlock the bits.
+ bitmap.UnlockBits(bmpData);
+
+ return rgbValues;
+ }
+
+ ///
+ /// Set Object with type Type to the clipboard
+ ///
+ /// Type
+ /// object
+ public static void SetClipboardData(Type type, object obj) {
+ DataFormats.Format format = DataFormats.GetFormat(type.FullName);
+
+ //now copy to clipboard
+ IDataObject dataObj = new DataObject();
+ dataObj.SetData(format.Name, false, obj);
+ // Use false to make the object dissapear when the application stops.
+ SetDataObject(dataObj, true);
+ }
+
+ ///
+ /// Retrieve a list of all formats currently on the clipboard
+ ///
+ /// List of strings with the current formats
+ public static List GetFormats() {
+ return GetFormats(GetDataObject());
+ }
+
+ ///
+ /// Retrieve a list of all formats currently in the IDataObject
+ ///
+ /// List of string with the current formats
+ public static List GetFormats(IDataObject dataObj) {
+ string[] formats = null;
+
+ if (dataObj != null) {
+ formats = dataObj.GetFormats();
+ }
+ if (formats != null) {
+ Log.DebugFormat("Got clipboard formats: {0}", string.Join(",", formats));
+ return new List(formats);
+ }
+ return new List();
+ }
+
+ ///
+ /// Check if there is currently something in the dataObject which has the supplied format
+ ///
+ /// string with format
+ /// true if one the format is found
+ public static bool ContainsFormat(string format) {
+ return ContainsFormat(GetDataObject(), new[]{format});
+ }
+
+ ///
+ /// Check if there is currently something on the clipboard which has the supplied format
+ ///
+ /// IDataObject
+ /// string with format
+ /// true if one the format is found
+ public static bool ContainsFormat(IDataObject dataObject, string format) {
+ return ContainsFormat(dataObject, new[] { format });
+ }
+
+ ///
+ /// Check if there is currently something on the clipboard which has one of the supplied formats
+ ///
+ /// string[] with formats
+ /// true if one of the formats was found
+ public static bool ContainsFormat(string[] formats) {
+ return ContainsFormat(GetDataObject(), formats);
+ }
+
+ ///
+ /// Check if there is currently something on the clipboard which has one of the supplied formats
+ ///
+ /// IDataObject
+ /// string[] with formats
+ /// true if one of the formats was found
+ public static bool ContainsFormat(IDataObject dataObject, string[] formats) {
+ bool formatFound = false;
+ List currentFormats = GetFormats(dataObject);
+ if (currentFormats == null || currentFormats.Count == 0 || formats == null || formats.Length == 0) {
+ return false;
+ }
+ foreach (string format in formats) {
+ if (currentFormats.Contains(format)) {
+ formatFound = true;
+ break;
+ }
+ }
+ return formatFound;
+ }
+
+ ///
+ /// Get Object of type Type from the clipboard
+ ///
+ /// Type to get
+ /// object from clipboard
+ public static object GetClipboardData(Type type) {
+ string format = type.FullName;
+ return GetClipboardData(format);
+ }
+
+ ///
+ /// Get Object for format from IDataObject
+ ///
+ /// IDataObject
+ /// Type to get
+ /// object from IDataObject
+ public static object GetFromDataObject(IDataObject dataObj, Type type) {
+ if (type != null) {
+ return GetFromDataObject(dataObj, type.FullName);
+ }
+ return null;
+ }
+
+ ///
+ /// Get ImageFilenames from the IDataObject
+ ///
+ /// IDataObject
+ ///
+ public static IEnumerable GetImageFilenames(IDataObject dataObject) {
+ string[] dropFileNames = (string[]) dataObject.GetData(DataFormats.FileDrop);
+ if (dropFileNames != null && dropFileNames.Length > 0)
+ {
+ return dropFileNames
+ .Where(filename => !string.IsNullOrEmpty(filename))
+ .Where(Path.HasExtension)
+ .Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1)));
+ }
+ return Enumerable.Empty();
+ }
+
+ ///
+ /// Get Object for format from IDataObject
+ ///
+ /// IDataObject
+ /// format to get
+ /// object from IDataObject
+ public static object GetFromDataObject(IDataObject dataObj, string format) {
+ if (dataObj != null) {
+ try {
+ return dataObj.GetData(format);
+ } catch (Exception e) {
+ Log.Error("Error in GetClipboardData.", e);
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Get Object for format from the clipboard
+ ///
+ /// format to get
+ /// object from clipboard
+ public static object GetClipboardData(string format) {
+ return GetFromDataObject(GetDataObject(), format);
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/CoreConfiguration.cs b/GreenshotPlugin/Core/CoreConfiguration.cs
new file mode 100644
index 000000000..4d60bb5aa
--- /dev/null
+++ b/GreenshotPlugin/Core/CoreConfiguration.cs
@@ -0,0 +1,543 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Core {
+ public enum ClipboardFormat {
+ PNG, DIB, HTML, HTMLDATAURL, BITMAP, DIBV5
+ }
+ public enum OutputFormat {
+ bmp, gif, jpg, png, tiff, greenshot, ico
+ }
+ public enum WindowCaptureMode {
+ Screen, GDI, Aero, AeroTransparent, Auto
+ }
+
+ public enum BuildStates {
+ UNSTABLE,
+ RELEASE_CANDIDATE,
+ RELEASE
+ }
+
+ public enum ClickActions {
+ DO_NOTHING,
+ OPEN_LAST_IN_EXPLORER,
+ OPEN_LAST_IN_EDITOR,
+ OPEN_SETTINGS,
+ SHOW_CONTEXT_MENU
+ }
+
+ ///
+ /// Description of CoreConfiguration.
+ ///
+ [IniSection("Core", Description="Greenshot core configuration")]
+ public class CoreConfiguration : IniSection, INotifyPropertyChanged {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ [IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")]
+ public string Language { get; set; }
+
+ [IniProperty("RegionHotkey", Description="Hotkey for starting the region capture", DefaultValue="PrintScreen")]
+ public string RegionHotkey { get; set; }
+ [IniProperty("WindowHotkey", Description="Hotkey for starting the window capture", DefaultValue="Alt + PrintScreen")]
+ public string WindowHotkey { get; set; }
+ [IniProperty("FullscreenHotkey", Description="Hotkey for starting the fullscreen capture", DefaultValue="Ctrl + PrintScreen")]
+ public string FullscreenHotkey { get; set; }
+ [IniProperty("LastregionHotkey", Description="Hotkey for starting the last region capture", DefaultValue="Shift + PrintScreen")]
+ public string LastregionHotkey { get; set; }
+ [IniProperty("IEHotkey", Description="Hotkey for starting the IE capture", DefaultValue="Shift + Ctrl + PrintScreen")]
+ public string IEHotkey { get; set; }
+
+ [IniProperty("IsFirstLaunch", Description="Is this the first time launch?", DefaultValue="true")]
+ public bool IsFirstLaunch { get; set; }
+ [IniProperty("Destinations", Separator=",", Description="Which destinations? Possible options (more might be added by plugins) are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail, Picker", DefaultValue="Picker")]
+ public List OutputDestinations { get; set; } = new List();
+ [IniProperty("ClipboardFormats", Separator=",", Description="Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", DefaultValue="PNG,DIB")]
+ public List ClipboardFormats { get; set; } = new List();
+
+ [IniProperty("CaptureMousepointer", Description="Should the mouse be captured?", DefaultValue="true")]
+ public bool CaptureMousepointer { get; set; }
+ [IniProperty("CaptureWindowsInteractive", Description="Use interactive window selection to capture? (false=Capture active window)", DefaultValue="false")]
+ public bool CaptureWindowsInteractive { get; set; }
+ [IniProperty("CaptureDelay", Description="Capture delay in millseconds.", DefaultValue="100")]
+ public int CaptureDelay { get; set; }
+ [IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")]
+ public ScreenCaptureMode ScreenCaptureMode { get; set; }
+ [IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")]
+ public int ScreenToCapture { get; set; }
+ [IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")]
+ public WindowCaptureMode WindowCaptureMode { get; set; }
+ [IniProperty("WindowCaptureAllChildLocations", Description="Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue="False")]
+ public bool WindowCaptureAllChildLocations { get; set; }
+
+ [IniProperty("DWMBackgroundColor", Description="The background color for a DWM window capture.")]
+ public Color DWMBackgroundColor { get; set; }
+
+ [IniProperty("PlayCameraSound", LanguageKey="settings_playsound",Description="Play a camera sound after taking a capture.", DefaultValue="false")]
+ public bool PlayCameraSound { get; set; } = false;
+ [IniProperty("ShowTrayNotification", LanguageKey="settings_shownotify",Description="Show a notification from the systray when a capture is taken.", DefaultValue="true")]
+ public bool ShowTrayNotification { get; set; } = true;
+
+ [IniProperty("OutputFilePath", Description="Output file path.")]
+ public string OutputFilePath { get; set; }
+ [IniProperty("OutputFileAllowOverwrite", Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")]
+ public bool OutputFileAllowOverwrite { get; set; }
+ [IniProperty("OutputFileFilenamePattern", Description = "Filename pattern for screenshot.", DefaultValue = "${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")]
+ public string OutputFileFilenamePattern { get; set; }
+ [IniProperty("OutputFileFormat", Description="Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue="png")]
+ public OutputFormat OutputFileFormat { get; set; } = OutputFormat.png;
+ [IniProperty("OutputFileReduceColors", Description="If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue="false")]
+ public bool OutputFileReduceColors { get; set; }
+ [IniProperty("OutputFileAutoReduceColors", Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "false")]
+ public bool OutputFileAutoReduceColors { get; set; }
+ [IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")]
+ public int OutputFileReduceColorsTo { get; set; }
+
+ [IniProperty("OutputFileCopyPathToClipboard", Description="When saving a screenshot, copy the path to the clipboard?", DefaultValue="true")]
+ public bool OutputFileCopyPathToClipboard { get; set; }
+ [IniProperty("OutputFileAsFullpath", Description="SaveAs Full path?")]
+ public string OutputFileAsFullpath { get; set; }
+
+ [IniProperty("OutputFileJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int OutputFileJpegQuality { get; set; }
+ [IniProperty("OutputFilePromptQuality", Description="Ask for the quality before saving?", DefaultValue="false")]
+ public bool OutputFilePromptQuality { get; set; }
+ [IniProperty("OutputFileIncrementingNumber", Description="The number for the ${NUM} in the filename pattern, is increased automatically after each save.", DefaultValue="1")]
+ public uint OutputFileIncrementingNumber { get; set; }
+
+ [IniProperty("OutputPrintPromptOptions", LanguageKey="settings_alwaysshowprintoptionsdialog", Description="Ask for print options when printing?", DefaultValue="true")]
+ public bool OutputPrintPromptOptions { get; set; }
+ [IniProperty("OutputPrintAllowRotate", LanguageKey="printoptions_allowrotate", Description="Allow rotating the picture for fitting on paper?", DefaultValue="false")]
+ public bool OutputPrintAllowRotate { get; set; }
+ [IniProperty("OutputPrintAllowEnlarge", LanguageKey="printoptions_allowenlarge", Description="Allow growing the picture for fitting on paper?", DefaultValue="false")]
+ public bool OutputPrintAllowEnlarge { get; set; }
+ [IniProperty("OutputPrintAllowShrink", LanguageKey="printoptions_allowshrink", Description="Allow shrinking the picture for fitting on paper?", DefaultValue="true")]
+ public bool OutputPrintAllowShrink { get; set; }
+ [IniProperty("OutputPrintCenter", LanguageKey="printoptions_allowcenter", Description="Center image when printing?", DefaultValue="true")]
+ public bool OutputPrintCenter { get; set; }
+ [IniProperty("OutputPrintInverted", LanguageKey="printoptions_inverted", Description="Print image inverted (use e.g. for console captures)", DefaultValue="false")]
+ public bool OutputPrintInverted { get; set; }
+ [IniProperty("OutputPrintGrayscale", LanguageKey = "printoptions_printgrayscale", Description = "Force grayscale printing", DefaultValue = "false")]
+ public bool OutputPrintGrayscale { get; set; }
+ [IniProperty("OutputPrintMonochrome", LanguageKey = "printoptions_printmonochrome", Description = "Force monorchrome printing", DefaultValue = "false")]
+ public bool OutputPrintMonochrome { get; set; }
+ [IniProperty("OutputPrintMonochromeThreshold", Description = "Threshold for monochrome filter (0 - 255), lower value means less black", DefaultValue = "127")]
+ public byte OutputPrintMonochromeThreshold { get; set; }
+ [IniProperty("OutputPrintFooter", LanguageKey = "printoptions_timestamp", Description = "Print footer on print?", DefaultValue = "true")]
+ public bool OutputPrintFooter { get; set; }
+ [IniProperty("OutputPrintFooterPattern", Description = "Footer pattern", DefaultValue = "${capturetime:d\"D\"} ${capturetime:d\"T\"} - ${title}")]
+ public string OutputPrintFooterPattern { get; set; }
+ [IniProperty("NotificationSound", Description = "The wav-file to play when a capture is taken, loaded only once at the Greenshot startup", DefaultValue="default")]
+ public string NotificationSound { get; set; }
+ [IniProperty("UseProxy", Description="Use your global proxy?", DefaultValue="True")]
+ public bool UseProxy { get; set; }
+ [IniProperty("IECapture", Description="Enable/disable IE capture", DefaultValue="True")]
+ public bool IECapture { get; set; }
+ [IniProperty("IEFieldCapture", Description="Enable/disable IE field capture, very slow but will make it possible to annotate the fields of a capture in the editor.", DefaultValue="False")]
+ public bool IEFieldCapture { get; set; }
+ [IniProperty("WindowClassesToCheckForIE", Description = "Comma separated list of Window-Classes which need to be checked for a IE instance!", DefaultValue = "AfxFrameOrView70,IMWindowClass")]
+ public List WindowClassesToCheckForIE { get; set; }
+ [IniProperty("AutoCropDifference", Description="Sets how to compare the colors for the autocrop detection, the higher the more is 'selected'. Possible values are from 0 to 255, where everything above ~150 doesn't make much sense!", DefaultValue="10")]
+ public int AutoCropDifference { get; set; }
+
+ [IniProperty("IncludePlugins", Description="Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")]
+ public List IncludePlugins { get; set; }
+ [IniProperty("ExcludePlugins", Description="Comma separated list of Plugins which are NOT allowed.")]
+ public List ExcludePlugins { get; set; }
+ [IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")]
+ public List ExcludeDestinations { get; set; }
+
+ [IniProperty("UpdateCheckInterval", Description="How many days between every update check? (0=no checks)", DefaultValue="14")]
+ public int UpdateCheckInterval { get; set; }
+ [IniProperty("LastUpdateCheck", Description="Last update check")]
+ public DateTime LastUpdateCheck { get; set; }
+
+ [IniProperty("DisableSettings", Description = "Enable/disable the access to the settings, can only be changed manually in this .ini", DefaultValue = "False")]
+ public bool DisableSettings { get; set; }
+ [IniProperty("DisableQuickSettings", Description = "Enable/disable the access to the quick settings, can only be changed manually in this .ini", DefaultValue = "False")]
+ public bool DisableQuickSettings { get; set; }
+ [IniProperty("DisableTrayicon", Description = "Disable the trayicon, can only be changed manually in this .ini", DefaultValue = "False")]
+ public bool HideTrayicon { get; set; }
+ [IniProperty("HideExpertSettings", Description = "Hide expert tab in the settings, can only be changed manually in this .ini", DefaultValue = "False")]
+ public bool HideExpertSettings { get; set; }
+
+ [IniProperty("ThumnailPreview", Description="Enable/disable thumbnail previews", DefaultValue="True")]
+ public bool ThumnailPreview { get; set; }
+
+ [IniProperty("NoGDICaptureForProduct", Description = "List of productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")]
+ public List NoGDICaptureForProduct { get; set; }
+ [IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")]
+ public List NoDWMCaptureForProduct { get; set; }
+
+ [IniProperty("OptimizeForRDP", Description="Make some optimizations for usage with remote desktop", DefaultValue="False")]
+ public bool OptimizeForRDP { get; set; }
+ [IniProperty("DisableRDPOptimizing", Description = "Disable all optimizations for usage with remote desktop", DefaultValue = "False")]
+ public bool DisableRDPOptimizing { get; set; }
+
+ [IniProperty("MinimizeWorkingSetSize", Description="Optimize memory footprint, but with a performance penalty!", DefaultValue="False")]
+ public bool MinimizeWorkingSetSize { get; set; }
+
+ [IniProperty("WindowCaptureRemoveCorners", Description = "Remove the corners from a window capture", DefaultValue = "True")]
+ public bool WindowCaptureRemoveCorners { get; set; }
+
+ [IniProperty("CheckForUnstable", Description = "Also check for unstable version updates", DefaultValue = "False")]
+ public bool CheckForUnstable { get; set; }
+
+ [IniProperty("ActiveTitleFixes", Description="The fixes that are active.")]
+ public List ActiveTitleFixes { get; set; }
+
+ [IniProperty("TitleFixMatcher", Description="The regular expressions to match the title with.")]
+ public Dictionary TitleFixMatcher { get; set; }
+
+ [IniProperty("TitleFixReplacer", Description="The replacements for the matchers.")]
+ public Dictionary TitleFixReplacer { get; set; }
+
+ [IniProperty("ExperimentalFeatures", Description="A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull=true)]
+ public List ExperimentalFeatures { get; set; }
+
+ [IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue="True")]
+ public bool EnableSpecialDIBClipboardReader { get; set; }
+
+ [IniProperty("WindowCornerCutShape", Description = "The cutshape which is used to remove the window corners, is mirrorred for all corners", DefaultValue = "5,3,2,1,1")]
+ public List WindowCornerCutShape { get; set; }
+
+ [IniProperty("LeftClickAction", Description = "Specify what action is made if the tray icon is left clicked, if a double-click action is specified this action is initiated after a delay (configurable via the windows double-click speed)", DefaultValue = "SHOW_CONTEXT_MENU")]
+ public ClickActions LeftClickAction { get; set; }
+
+ [IniProperty("DoubleClickAction", Description = "Specify what action is made if the tray icon is double clicked", DefaultValue = "OPEN_LAST_IN_EXPLORER")]
+ public ClickActions DoubleClickAction { get; set; }
+
+ [IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")]
+ public bool ZoomerEnabled { get; set; }
+ [IniProperty("ZoomerOpacity", Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", DefaultValue = "1")]
+ public float ZoomerOpacity { get; set; }
+
+ [IniProperty("MaxMenuItemLength", Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")]
+ public int MaxMenuItemLength { get; set; }
+
+ [IniProperty("MailApiTo", Description = "The 'to' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
+ public string MailApiTo { get; set; }
+ [IniProperty("MailApiCC", Description = "The 'CC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
+ public string MailApiCC { get; set; }
+ [IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
+ public string MailApiBCC { get; set; }
+
+ [IniProperty("OptimizePNGCommand", Description = "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", DefaultValue = "")]
+ public string OptimizePNGCommand { get; set; }
+ [IniProperty("OptimizePNGCommandArguments", Description = "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", DefaultValue = "\"{0}\"")]
+ public string OptimizePNGCommandArguments { get; set; }
+
+ [IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")]
+ public string LastSaveWithVersion { get; set; }
+
+ [IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", DefaultValue = "True")]
+ public bool ProcessEXIFOrientation { get; set; }
+
+ [IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")]
+ public Rectangle LastCapturedRegion { get; set; }
+
+ [IniProperty("Win10BorderCrop", Description = "The capture is cropped with these settings, e.g. when you don't want to color around it -1,-1"), DefaultValue("0,0")]
+ public Size Win10BorderCrop { get; set; }
+
+ private Size _iconSize;
+ [IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")]
+ public Size IconSize {
+ get {
+ return _iconSize;
+ }
+ set {
+ Size newSize = value;
+ if (newSize != Size.Empty) {
+ if (newSize.Width < 16) {
+ newSize.Width = 16;
+ } else if (newSize.Width > 256) {
+ newSize.Width = 256;
+ }
+ newSize.Width = (newSize.Width / 16) * 16;
+ if (newSize.Height < 16) {
+ newSize.Height = 16;
+ } else if (IconSize.Height > 256) {
+ newSize.Height = 256;
+ }
+ newSize.Height = (newSize.Height / 16) * 16;
+ }
+ if (_iconSize != newSize) {
+ _iconSize = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IconSize"));
+ }
+ }
+ }
+
+ [IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")]
+ public int WebRequestTimeout { get; set; }
+ [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
+ public int WebRequestReadWriteTimeout { get; set; }
+
+ ///
+ /// Specifies what THIS build is
+ ///
+ public BuildStates BuildState {
+ get {
+ string informationalVersion = Application.ProductVersion;
+ if (informationalVersion != null) {
+ if (informationalVersion.ToLowerInvariant().Contains("-rc")) {
+ return BuildStates.RELEASE_CANDIDATE;
+ }
+ if (informationalVersion.ToLowerInvariant().Contains("-unstable")) {
+ return BuildStates.UNSTABLE;
+ }
+ }
+ return BuildStates.RELEASE;
+ }
+ }
+
+ public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32;
+
+ ///
+ /// A helper method which returns true if the supplied experimental feature is enabled
+ ///
+ ///
+ ///
+ public bool IsExperimentalFeatureEnabled(string experimentalFeature) {
+ return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature));
+ }
+
+ ///
+ /// Supply values we can't put as defaults
+ ///
+ /// The property to return a default for
+ /// object with the default value for the supplied property
+ public override object GetDefault(string property) {
+ switch(property) {
+ case "PluginWhitelist":
+ case "PluginBacklist":
+ return new List();
+ case "OutputFileAsFullpath":
+ if (IniConfig.IsPortable) {
+ return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png");
+ }
+ return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"dummy.png");
+ case "OutputFilePath":
+ if (IniConfig.IsPortable) {
+ string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots");
+ if (!Directory.Exists(pafOutputFilePath)) {
+ try {
+ Directory.CreateDirectory(pafOutputFilePath);
+ return pafOutputFilePath;
+ } catch (Exception ex) {
+ LOG.Warn(ex);
+ // Problem creating directory, fallback to Desktop
+ }
+ } else {
+ return pafOutputFilePath;
+ }
+ }
+ return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
+ case "DWMBackgroundColor":
+ return Color.Transparent;
+ case "ActiveTitleFixes":
+ return new List {"Firefox", "IE", "Chrome"};
+ case "TitleFixMatcher":
+ return new Dictionary {{"Firefox", " - Mozilla Firefox.*"}, {"IE", " - (Microsoft|Windows) Internet Explorer.*"}, {"Chrome", " - Google Chrome.*"}};
+ case "TitleFixReplacer":
+ return new Dictionary {{"Firefox", ""}, {"IE", ""}, {"Chrome", ""}};
+ }
+ return null;
+ }
+
+ ///
+ /// This method will be called before converting the property, making to possible to correct a certain value
+ /// Can be used when migration is needed
+ ///
+ /// The name of the property
+ /// The string value of the property
+ /// string with the propertyValue, modified or not...
+ public override string PreCheckValue(string propertyName, string propertyValue) {
+ // Changed the separator, now we need to correct this
+ if ("Destinations".Equals(propertyName)) {
+ if (propertyValue != null) {
+ return propertyValue.Replace('|',',');
+ }
+ }
+ if("OutputFilePath".Equals(propertyName)) {
+ if (string.IsNullOrEmpty(propertyValue)) {
+ return null;
+ }
+ }
+ return base.PreCheckValue(propertyName, propertyValue);
+ }
+
+ ///
+ /// This method will be called before writing the configuration
+ ///
+ public override void BeforeSave() {
+ try {
+ // Store version, this can be used later to fix settings after an update
+ LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+
+ ///
+ /// This method will be called after reading the configuration, so eventually some corrections can be made
+ ///
+ public override void AfterLoad() {
+ // Comment with releases
+ // CheckForUnstable = true;
+
+ if (string.IsNullOrEmpty(LastSaveWithVersion)) {
+ try {
+ // Store version, this can be used later to fix settings after an update
+ LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
+ }
+ catch
+ {
+ // ignored
+ }
+ // Disable the AutoReduceColors as it causes issues with Mozzila applications and some others
+ OutputFileAutoReduceColors = false;
+ }
+
+ // Fix for excessive feed checking
+ if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && LastSaveWithVersion.StartsWith("1.2"))
+ {
+ UpdateCheckInterval = 14;
+ }
+ if (UpdateCheckInterval > 365)
+ {
+ UpdateCheckInterval = 365;
+ }
+
+ // Enable OneNote if upgrading from 1.1
+ if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote")) {
+ if(LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1")) {
+ ExcludeDestinations.Remove("OneNote");
+ } else {
+ // TODO: Remove with the release
+ ExcludeDestinations.Remove("OneNote");
+ }
+ }
+
+ if (OutputDestinations == null) {
+ OutputDestinations = new List();
+ }
+
+ // Make sure there is an output!
+ if (OutputDestinations.Count == 0) {
+ OutputDestinations.Add("Editor");
+ }
+
+ // Prevent both settings at once, bug #3435056
+ if (OutputDestinations.Contains("Clipboard") && OutputFileCopyPathToClipboard) {
+ OutputFileCopyPathToClipboard = false;
+ }
+
+ // Make sure we have clipboard formats, otherwise a paste doesn't make sense!
+ if (ClipboardFormats == null || ClipboardFormats.Count == 0) {
+ ClipboardFormats = new List {ClipboardFormat.PNG, ClipboardFormat.HTML, ClipboardFormat.DIB};
+ }
+
+ // Make sure the lists are lowercase, to speedup the check
+ if (NoGDICaptureForProduct != null) {
+ // Fix error in configuration
+ if (NoGDICaptureForProduct.Count >= 2) {
+ if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1])) {
+ NoGDICaptureForProduct.RemoveRange(0, 2);
+ NoGDICaptureForProduct.Add("Intellij Idea");
+ IsDirty = true;
+ }
+ }
+ for (int i = 0; i < NoGDICaptureForProduct.Count; i++) {
+ NoGDICaptureForProduct[i] = NoGDICaptureForProduct[i].ToLower();
+ }
+ }
+ if (NoDWMCaptureForProduct != null) {
+ // Fix error in configuration
+ if (NoDWMCaptureForProduct.Count >= 3) {
+ if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2])) {
+ NoDWMCaptureForProduct.RemoveRange(0, 3);
+ NoDWMCaptureForProduct.Add("Citrix ICA Client");
+ IsDirty = true;
+ }
+ }
+ for (int i = 0; i < NoDWMCaptureForProduct.Count; i++) {
+ NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower();
+ }
+ }
+
+ if (AutoCropDifference < 0) {
+ AutoCropDifference = 0;
+ }
+ if (AutoCropDifference > 255) {
+ AutoCropDifference = 255;
+ }
+ if (OutputFileReduceColorsTo < 2) {
+ OutputFileReduceColorsTo = 2;
+ }
+ if (OutputFileReduceColorsTo > 256) {
+ OutputFileReduceColorsTo = 256;
+ }
+
+ if (WebRequestTimeout <= 10) {
+ WebRequestTimeout = 100;
+ }
+ if (WebRequestReadWriteTimeout < 1) {
+ WebRequestReadWriteTimeout = 100;
+ }
+ }
+
+ ///
+ /// Validate the OutputFilePath, and if this is not correct it will be set to the default
+ /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC)
+ ///
+ public void ValidateAndCorrectOutputFilePath()
+ {
+ if (!Directory.Exists(OutputFilePath))
+ {
+ OutputFilePath = GetDefault(nameof(OutputFilePath)) as string;
+ }
+ }
+ ///
+ /// Validate the OutputFileAsFullpath, and if this is not correct it will be set to the default
+ /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC)
+ ///
+ public void ValidateAndCorrectOutputFileAsFullpath()
+ {
+ var outputFilePath = Path.GetDirectoryName(OutputFileAsFullpath);
+ if (outputFilePath == null || (!File.Exists(OutputFileAsFullpath) && !Directory.Exists(outputFilePath)))
+ {
+ OutputFileAsFullpath = GetDefault(nameof(OutputFileAsFullpath)) as string;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/CredentialsHelper.cs b/GreenshotPlugin/Core/CredentialsHelper.cs
new file mode 100644
index 000000000..a031b5922
--- /dev/null
+++ b/GreenshotPlugin/Core/CredentialsHelper.cs
@@ -0,0 +1,543 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// The following code comes from: http://www.developerfusion.com/code/4693/using-the-credential-management-api/
+ /// and is slightly modified so it works for us.
+ /// As the "Stored usernames and passwords" which can be accessed by: Start-> Run and type "Control keymgr.dll"
+ /// doesn't show all credentials use the tool here: http://www.microsoft.com/indonesia/msdn/credmgmt.aspx
+ /// The following code is an example for a login, it will call the Authenticate with user/password
+ /// which should return true if the login worked, false if not.
+ /// private static bool Login(string system, string name) {
+ /// try {
+ /// CredentialsDialog dialog = new CredentialsDialog(system);
+ /// dialog.Name = name;
+ /// while (dialog.Show(dialog.Name) == DialogResult.OK) {
+ /// if (Authenticate(dialog.Name, dialog.Password)) {
+ /// if (dialog.SaveChecked) dialog.Confirm(true);
+ /// return true;
+ /// } else {
+ /// try {
+ /// dialog.Confirm(false);
+ /// } catch (ApplicationException) {
+ /// // exception handling ...
+ /// }
+ /// dialog.IncorrectPassword = true;
+ /// }
+ /// }
+ /// } catch (ApplicationException) {
+ /// // exception handling ...
+ /// }
+ /// return false;
+ /// }
+ ///
+ /// Encapsulates dialog functionality from the Credential Management API.
+ public sealed class CredentialsDialog {
+ [DllImport("gdi32.dll", SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool DeleteObject(IntPtr hObject);
+
+ /// The only valid bitmap height (in pixels) of a user-defined banner.
+ private const int ValidBannerHeight = 60;
+
+ /// The only valid bitmap width (in pixels) of a user-defined banner.
+ private const int ValidBannerWidth = 320;
+
+ /// Initializes a new instance of the class
+ /// with the specified target.
+ /// The name of the target for the credentials, typically a server name.
+ public CredentialsDialog(string target) : this(target, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target and caption.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ public CredentialsDialog(string target, string caption) : this(target, caption, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target, caption and message.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ /// The message of the dialog (null will cause a system default message to be used).
+ public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target, caption, message and banner.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ /// The message of the dialog (null will cause a system default message to be used).
+ /// The image to display on the dialog (null will cause a system default image to be used).
+ public CredentialsDialog(string target, string caption, string message, Image banner) {
+ Target = target;
+ Caption = caption;
+ Message = message;
+ Banner = banner;
+ }
+
+ ///
+ /// Gets or sets if the dialog will be shown even if the credentials
+ /// can be returned from an existing credential in the credential manager.
+ ///
+ public bool AlwaysDisplay { get; set; }
+
+ /// Gets or sets if the dialog is populated with name/password only.
+ public bool ExcludeCertificates { get; set; } = true;
+
+ /// Gets or sets if the credentials are to be persisted in the credential manager.
+ public bool Persist { get; set; } = true;
+
+ /// Gets or sets if the incorrect password balloontip needs to be shown. Introduced AFTER Windows XP
+ public bool IncorrectPassword { get; set; }
+
+ /// Gets or sets if the name is read-only.
+ public bool KeepName { get; set; }
+
+ private string _name = string.Empty;
+ /// Gets or sets the name for the credentials.
+ public string Name {
+ get {
+ return _name;
+ }
+ set {
+ if (value?.Length > CredUi.MAX_USERNAME_LENGTH) {
+ string message = string.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The name has a maximum length of {0} characters.",
+ CredUi.MAX_USERNAME_LENGTH);
+ throw new ArgumentException(message, nameof(Name));
+ }
+ _name = value;
+ }
+ }
+
+ private string _password = string.Empty;
+ /// Gets or sets the password for the credentials.
+ public string Password {
+ get {
+ return _password;
+ }
+ set {
+ if (value?.Length > CredUi.MAX_PASSWORD_LENGTH) {
+ string message = string.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The password has a maximum length of {0} characters.",
+ CredUi.MAX_PASSWORD_LENGTH);
+ throw new ArgumentException(message, nameof(Password));
+ }
+ _password = value;
+ }
+ }
+
+ /// Gets or sets if the save checkbox status.
+ public bool SaveChecked { get; set; }
+
+ /// Gets or sets if the save checkbox is displayed.
+ /// This value only has effect if Persist is true.
+ public bool SaveDisplayed { get; set; } = true;
+
+ private string _target = string.Empty;
+ /// Gets or sets the name of the target for the credentials, typically a server name.
+ public string Target {
+ get {
+ return _target;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentException("The target cannot be a null value.", nameof(Target));
+ }
+ if (value.Length > CredUi.MAX_GENERIC_TARGET_LENGTH) {
+ string message = string.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The target has a maximum length of {0} characters.",
+ CredUi.MAX_GENERIC_TARGET_LENGTH);
+ throw new ArgumentException(message, nameof(Target));
+ }
+ _target = value;
+ }
+ }
+
+ private string _caption = string.Empty;
+ /// Gets or sets the caption of the dialog.
+ /// A null value will cause a system default caption to be used.
+ public string Caption {
+ get {
+ return _caption;
+ }
+ set {
+ if (value?.Length > CredUi.MAX_CAPTION_LENGTH) {
+ string message = string.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The caption has a maximum length of {0} characters.",
+ CredUi.MAX_CAPTION_LENGTH);
+ throw new ArgumentException(message, nameof(Caption));
+ }
+ _caption = value;
+ }
+ }
+
+ private string _message = string.Empty;
+ /// Gets or sets the message of the dialog.
+ /// A null value will cause a system default message to be used.
+ public string Message {
+ get {
+ return _message;
+ }
+ set {
+ if (value?.Length > CredUi.MAX_MESSAGE_LENGTH) {
+ string message = string.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The message has a maximum length of {0} characters.",
+ CredUi.MAX_MESSAGE_LENGTH);
+ throw new ArgumentException(message, nameof(Message));
+ }
+ _message = value;
+ }
+ }
+
+ private Image _banner;
+ /// Gets or sets the image to display on the dialog.
+ /// A null value will cause a system default image to be used.
+ public Image Banner {
+ get {
+ return _banner;
+ }
+ set {
+ if (value != null) {
+ if (value.Width != ValidBannerWidth) {
+ throw new ArgumentException("The banner image width must be 320 pixels.", nameof(Banner));
+ }
+ if (value.Height != ValidBannerHeight) {
+ throw new ArgumentException("The banner image height must be 60 pixels.", nameof(Banner));
+ }
+ }
+ _banner = value;
+ }
+ }
+
+ /// Shows the credentials dialog.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show() {
+ return Show(null, Name, Password, SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified save checkbox status.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(bool saveChecked) {
+ return Show(null, Name, Password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name.
+ /// The name for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name) {
+ return Show(null, name, Password, SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name and password.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name, string password) {
+ return Show(null, name, password, SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name, password and save checkbox status.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name, string password, bool saveChecked) {
+ return Show(null, name, password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner) {
+ return Show(owner, Name, Password, SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner and save checkbox status.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, bool saveChecked) {
+ return Show(owner, Name, Password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner, name and password.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, string name, string password) {
+ return Show(owner, name, password, SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner, name, password and save checkbox status.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, string name, string password, bool saveChecked) {
+ if ((Environment.OSVersion.Version.Major < 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor < 1))) {
+ throw new ApplicationException("The Credential Management API requires Windows XP / Windows Server 2003 or later.");
+ }
+ Name = name;
+ Password = password;
+ SaveChecked = saveChecked;
+
+ return ShowDialog(owner);
+ }
+
+ /// Confirmation action to be applied.
+ /// True if the credentials should be persisted.
+ public void Confirm(bool value)
+ {
+ var confirmResult = CredUi.CredUIConfirmCredentials(Target, value);
+ switch (confirmResult) {
+ case CredUi.ReturnCodes.NO_ERROR:
+ break;
+ case CredUi.ReturnCodes.ERROR_INVALID_PARAMETER:
+ // for some reason, this is encountered when credentials are overwritten
+ break;
+ default:
+ throw new ApplicationException($"Credential confirmation failed: {confirmResult}");
+ }
+ }
+
+ /// Returns a DialogResult indicating the user action.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ ///
+ /// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user.
+ ///
+ private DialogResult ShowDialog(IWin32Window owner) {
+ // set the api call parameters
+ StringBuilder name = new StringBuilder(CredUi.MAX_USERNAME_LENGTH);
+ name.Append(Name);
+
+ StringBuilder password = new StringBuilder(CredUi.MAX_PASSWORD_LENGTH);
+ password.Append(Password);
+
+ int saveChecked = Convert.ToInt32(SaveChecked);
+
+ CredUi.INFO info = GetInfo(owner);
+ CredUi.CredFlags credFlags = GetFlags();
+
+ // make the api call
+ CredUi.ReturnCodes code = CredUi.CredUIPromptForCredentials(
+ ref info,
+ Target,
+ IntPtr.Zero, 0,
+ name, CredUi.MAX_USERNAME_LENGTH,
+ password, CredUi.MAX_PASSWORD_LENGTH,
+ ref saveChecked,
+ credFlags
+ );
+
+ // clean up resources
+ if (Banner != null) {
+ DeleteObject(info.hbmBanner);
+ }
+
+ // set the accessors from the api call parameters
+ Name = name.ToString();
+ Password = password.ToString();
+ SaveChecked = Convert.ToBoolean(saveChecked);
+
+ return GetDialogResult(code);
+ }
+
+ /// Returns the info structure for dialog display settings.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ private CredUi.INFO GetInfo(IWin32Window owner) {
+ CredUi.INFO info = new CredUi.INFO();
+ if (owner != null) info.hwndParent = owner.Handle;
+ info.pszCaptionText = Caption;
+ info.pszMessageText = Message;
+ if (Banner != null) {
+ info.hbmBanner = new Bitmap(Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap();
+ }
+ info.cbSize = Marshal.SizeOf(info);
+ return info;
+ }
+
+ /// Returns the flags for dialog display options.
+ private CredUi.CredFlags GetFlags() {
+ CredUi.CredFlags credFlags = CredUi.CredFlags.GENERIC_CREDENTIALS;
+
+ if (IncorrectPassword) {
+ credFlags = credFlags | CredUi.CredFlags.INCORRECT_PASSWORD;
+ }
+
+ if (AlwaysDisplay) {
+ credFlags = credFlags | CredUi.CredFlags.ALWAYS_SHOW_UI;
+ }
+
+ if (ExcludeCertificates) {
+ credFlags = credFlags | CredUi.CredFlags.EXCLUDE_CERTIFICATES;
+ }
+
+ if (Persist) {
+ credFlags = credFlags | CredUi.CredFlags.EXPECT_CONFIRMATION;
+ if (SaveDisplayed) {
+ credFlags = credFlags | CredUi.CredFlags.SHOW_SAVE_CHECK_BOX;
+ } else {
+ credFlags = credFlags | CredUi.CredFlags.PERSIST;
+ }
+ } else {
+ credFlags = credFlags | CredUi.CredFlags.DO_NOT_PERSIST;
+ }
+
+ if (KeepName) {
+ credFlags = credFlags | CredUi.CredFlags.KEEP_USERNAME;
+ }
+
+ return credFlags;
+ }
+
+ /// Returns a DialogResult from the specified code.
+ /// The credential return code.
+ private DialogResult GetDialogResult(CredUi.ReturnCodes code) {
+ DialogResult result;
+ switch (code) {
+ case CredUi.ReturnCodes.NO_ERROR:
+ result = DialogResult.OK;
+ break;
+ case CredUi.ReturnCodes.ERROR_CANCELLED:
+ result = DialogResult.Cancel;
+ break;
+ case CredUi.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION:
+ throw new ApplicationException("No such logon session.");
+ case CredUi.ReturnCodes.ERROR_NOT_FOUND:
+ throw new ApplicationException("Not found.");
+ case CredUi.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME:
+ throw new ApplicationException("Invalid account name.");
+ case CredUi.ReturnCodes.ERROR_INSUFFICIENT_BUFFER:
+ throw new ApplicationException("Insufficient buffer.");
+ case CredUi.ReturnCodes.ERROR_INVALID_PARAMETER:
+ throw new ApplicationException("Invalid parameter.");
+ case CredUi.ReturnCodes.ERROR_INVALID_FLAGS:
+ throw new ApplicationException("Invalid flags.");
+ default:
+ throw new ApplicationException("Unknown credential result encountered.");
+ }
+ return result;
+ }
+ }
+
+ internal static class CredUi {
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/authentication_constants.asp
+ public const int MAX_MESSAGE_LENGTH = 100;
+ public const int MAX_CAPTION_LENGTH = 100;
+ public const int MAX_GENERIC_TARGET_LENGTH = 100;
+ public const int MAX_DOMAIN_TARGET_LENGTH = 100;
+ public const int MAX_USERNAME_LENGTH = 100;
+ public const int MAX_PASSWORD_LENGTH = 100;
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/Enums.CREDUI_FLAGS
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
+ ///
+ [Flags]
+ public enum CredFlags {
+ INCORRECT_PASSWORD = 0x1,
+ DO_NOT_PERSIST = 0x2,
+ REQUEST_ADMINISTRATOR = 0x4,
+ EXCLUDE_CERTIFICATES = 0x8,
+ REQUIRE_CERTIFICATE = 0x10,
+ SHOW_SAVE_CHECK_BOX = 0x40,
+ ALWAYS_SHOW_UI = 0x80,
+ REQUIRE_SMARTCARD = 0x100,
+ PASSWORD_ONLY_OK = 0x200,
+ VALIDATE_USERNAME = 0x400,
+ COMPLETE_USERNAME = 0x800,
+ PERSIST = 0x1000,
+ SERVER_CREDENTIAL = 0x4000,
+ EXPECT_CONFIRMATION = 0x20000,
+ GENERIC_CREDENTIALS = 0x40000,
+ USERNAME_TARGET_CREDENTIALS = 0x80000,
+ KEEP_USERNAME = 0x100000,
+ }
+
+ /// http://www.pinvoke.net/default.aspx/Enums.CredUIReturnCodes
+ public enum ReturnCodes {
+ NO_ERROR = 0,
+ ERROR_INVALID_PARAMETER = 87,
+ ERROR_INSUFFICIENT_BUFFER = 122,
+ ERROR_INVALID_FLAGS = 1004,
+ ERROR_NOT_FOUND = 1168,
+ ERROR_CANCELLED = 1223,
+ ERROR_NO_SUCH_LOGON_SESSION = 1312,
+ ERROR_INVALID_ACCOUNT_NAME = 1315
+ }
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/Structures.CREDUI_INFO
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/credui_info.asp
+ ///
+ public struct INFO {
+ public int cbSize;
+ public IntPtr hwndParent;
+ [MarshalAs(UnmanagedType.LPWStr)] public string pszMessageText;
+ [MarshalAs(UnmanagedType.LPWStr)] public string pszCaptionText;
+ public IntPtr hbmBanner;
+ }
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
+ ///
+ [DllImport("credui", CharSet = CharSet.Unicode)]
+ public static extern ReturnCodes CredUIPromptForCredentials (
+ ref INFO creditUR,
+ string targetName,
+ IntPtr reserved1,
+ int iError,
+ StringBuilder userName,
+ int maxUserName,
+ StringBuilder password,
+ int maxPassword,
+ ref int iSave,
+ CredFlags credFlags
+ );
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/credui.CredUIConfirmCredentials
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduiconfirmcredentials.asp
+ ///
+ [DllImport("credui.dll", CharSet=CharSet.Unicode)]
+ public static extern ReturnCodes CredUIConfirmCredentials(string targetName, [MarshalAs(UnmanagedType.Bool)] bool confirm);
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/DisplayKeyAttribute.cs b/GreenshotPlugin/Core/DisplayKeyAttribute.cs
new file mode 100644
index 000000000..f8b1c4408
--- /dev/null
+++ b/GreenshotPlugin/Core/DisplayKeyAttribute.cs
@@ -0,0 +1,35 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace GreenshotPlugin.Core {
+ [AttributeUsage(AttributeTargets.Field)]
+ public sealed class DisplayKeyAttribute : Attribute {
+ public string Value { get; }
+
+ public DisplayKeyAttribute(string v) {
+ Value = v;
+ }
+
+ public DisplayKeyAttribute() {
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/EffectConverter.cs b/GreenshotPlugin/Core/EffectConverter.cs
new file mode 100644
index 000000000..1d41b8086
--- /dev/null
+++ b/GreenshotPlugin/Core/EffectConverter.cs
@@ -0,0 +1,180 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Globalization;
+using System.Text;
+using GreenshotPlugin.Effects;
+
+namespace Greenshot.Core
+{
+ public class EffectConverter : TypeConverter {
+ // Fix to prevent BUG-1753
+ private readonly NumberFormatInfo _numberFormatInfo = new NumberFormatInfo();
+
+ public EffectConverter()
+ {
+ _numberFormatInfo.NumberDecimalSeparator = ".";
+ _numberFormatInfo.NumberGroupSeparator = ",";
+ }
+
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
+ if (sourceType == typeof(string)) {
+ return true;
+ }
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
+ if (destinationType == typeof(string)) {
+ return true;
+ }
+ if (destinationType == typeof(DropShadowEffect)) {
+ return true;
+ }
+ if (destinationType == typeof(TornEdgeEffect)) {
+ return true;
+ }
+ return base.CanConvertTo(context, destinationType);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
+ // to string
+ if (destinationType == typeof(string)) {
+ StringBuilder sb = new StringBuilder();
+ if (value.GetType() == typeof(DropShadowEffect)) {
+ DropShadowEffect effect = value as DropShadowEffect;
+ RetrieveDropShadowEffectValues(effect, sb);
+ return sb.ToString();
+ }
+ if (value.GetType() == typeof(TornEdgeEffect)) {
+ TornEdgeEffect effect = value as TornEdgeEffect;
+ RetrieveDropShadowEffectValues(effect, sb);
+ sb.Append("|");
+ RetrieveTornEdgeEffectValues(effect, sb);
+ return sb.ToString();
+ }
+ }
+ // from string
+ if (value is string) {
+ string settings = value as string;
+ if (destinationType == typeof(DropShadowEffect)) {
+ DropShadowEffect effect = new DropShadowEffect();
+ ApplyDropShadowEffectValues(settings, effect);
+ return effect;
+ }
+ if (destinationType == typeof(TornEdgeEffect)) {
+ TornEdgeEffect effect = new TornEdgeEffect();
+ ApplyDropShadowEffectValues(settings, effect);
+ ApplyTornEdgeEffectValues(settings, effect);
+ return effect;
+ }
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
+ var settings = value as string;
+ if (settings != null) {
+ if (settings.Contains("ToothHeight")) {
+ return ConvertTo(context, culture, settings, typeof(TornEdgeEffect));
+ }
+ return ConvertTo(context, culture, settings, typeof(DropShadowEffect));
+ }
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect) {
+ string[] values = valuesString.Split('|');
+ foreach(string nameValuePair in values) {
+ string[] pair = nameValuePair.Split(':');
+ switch (pair[0]) {
+ case "Darkness" :
+ float darkness;
+ // Fix to prevent BUG-1753
+ if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, _numberFormatInfo, out darkness)) {
+ if (darkness <= 1.0) {
+ effect.Darkness = darkness;
+ }
+ }
+ break;
+ case "ShadowSize":
+ int shadowSize;
+ if (int.TryParse(pair[1], out shadowSize)) {
+ effect.ShadowSize = shadowSize;
+ }
+ break;
+ case "ShadowOffset":
+ Point shadowOffset = new Point();
+ int shadowOffsetX;
+ int shadowOffsetY;
+ string[] coordinates = pair[1].Split(',');
+ if (int.TryParse(coordinates[0], out shadowOffsetX)) {
+ shadowOffset.X = shadowOffsetX;
+ }
+ if (int.TryParse(coordinates[1], out shadowOffsetY)) {
+ shadowOffset.Y = shadowOffsetY;
+ }
+ effect.ShadowOffset = shadowOffset;
+ break;
+ }
+ }
+ }
+
+ private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect) {
+ string[] values = valuesString.Split('|');
+ foreach (string nameValuePair in values) {
+ string[] pair = nameValuePair.Split(':');
+ switch (pair[0]) {
+ case "GenerateShadow":
+ bool generateShadow;
+ if (bool.TryParse(pair[1], out generateShadow)) {
+ effect.GenerateShadow = generateShadow;
+ }
+ break;
+ case "ToothHeight":
+ int toothHeight;
+ if (int.TryParse(pair[1], out toothHeight)) {
+ effect.ToothHeight = toothHeight;
+ }
+ break;
+ case "HorizontalToothRange":
+ int horizontalToothRange;
+ if (int.TryParse(pair[1], out horizontalToothRange)) {
+ effect.HorizontalToothRange = horizontalToothRange;
+ }
+ break;
+ case "VerticalToothRange":
+ int verticalToothRange;
+ if (int.TryParse(pair[1], out verticalToothRange)) {
+ effect.VerticalToothRange = verticalToothRange;
+ }
+ break;
+ case "Edges":
+ string[] edges = pair[1].Split(',');
+ bool edge;
+ if (bool.TryParse(edges[0], out edge)) {
+ effect.Edges[0] = edge;
+ }
+ if (bool.TryParse(edges[1], out edge)) {
+ effect.Edges[1] = edge;
+ }
+ if (bool.TryParse(edges[2], out edge)) {
+ effect.Edges[2] = edge;
+ }
+ if (bool.TryParse(edges[3], out edge)) {
+ effect.Edges[3] = edge;
+ }
+ break;
+ }
+ }
+ }
+
+ private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb) {
+ // Fix to prevent BUG-1753 is to use the numberFormatInfo
+ sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", _numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, effect.ShadowOffset.Y);
+ }
+ private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb) {
+ sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/EmailConfigHelper.cs b/GreenshotPlugin/Core/EmailConfigHelper.cs
new file mode 100644
index 000000000..14ae354f2
--- /dev/null
+++ b/GreenshotPlugin/Core/EmailConfigHelper.cs
@@ -0,0 +1,77 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.IO;
+using Microsoft.Win32;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of EmailConfigHelper.
+ ///
+ public static class EmailConfigHelper {
+ private const string OutlookPathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\OUTLOOK.EXE";
+ private const string MapiClientKey = @"SOFTWARE\Clients\Mail";
+ private const string MapiLocationKey = @"SOFTWARE\Microsoft\Windows Messaging Subsystem";
+ private const string MapiKey = @"MAPI";
+
+ public static string GetMapiClient() {
+ using (RegistryKey key = Registry.CurrentUser.OpenSubKey(MapiClientKey, false)) {
+ if (key != null) {
+ return (string)key.GetValue("");
+ }
+ }
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(MapiClientKey, false))
+ {
+ return (string) key?.GetValue("");
+ }
+ }
+
+ public static bool HasMapi() {
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(MapiLocationKey, false))
+ {
+ return key != null && "1".Equals(key.GetValue(MapiKey, "0"));
+ }
+ }
+
+ public static string GetOutlookExePath() {
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(OutlookPathKey, false)) {
+ if (key != null) {
+ // "" is the default key, which should point to the outlook location
+ return (string)key.GetValue("");
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Check if Outlook is installed
+ ///
+ /// Returns true if outlook is installed
+ public static bool HasOutlook() {
+ string outlookPath = GetOutlookExePath();
+ if (outlookPath != null) {
+ if (File.Exists(outlookPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/EnumExtensions.cs b/GreenshotPlugin/Core/EnumExtensions.cs
new file mode 100644
index 000000000..1201f28f9
--- /dev/null
+++ b/GreenshotPlugin/Core/EnumExtensions.cs
@@ -0,0 +1,102 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+namespace GreenshotPlugin.Core {
+ public static class EnumerationExtensions {
+ public static bool Has(this Enum type, T value) {
+ Type underlyingType = Enum.GetUnderlyingType(value.GetType());
+ try {
+ if (underlyingType == typeof(int)) {
+ return (((int)(object)type & (int)(object)value) == (int)(object)value);
+ } else if (underlyingType == typeof(uint)) {
+ return (((uint)(object)type & (uint)(object)value) == (uint)(object)value);
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ return false;
+ }
+
+ public static bool Is(this Enum type, T value) {
+ Type underlyingType = Enum.GetUnderlyingType(value.GetType());
+ try
+ {
+ if (underlyingType == typeof(int)) {
+ return (int)(object)type == (int)(object)value;
+ }
+ if (underlyingType == typeof(uint)) {
+ return (uint)(object)type == (uint)(object)value;
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ return false;
+ }
+
+ ///
+ /// Add a flag to an enum
+ ///
+ ///
+ ///
+ ///
+ public static T Add(this Enum type, T value) {
+ Type underlyingType = Enum.GetUnderlyingType(value.GetType());
+ try
+ {
+ if (underlyingType == typeof(int)) {
+ return (T)(object)(((int)(object)type | (int)(object)value));
+ }
+ if (underlyingType == typeof(uint)) {
+ return (T)(object)(((uint)(object)type | (uint)(object)value));
+ }
+ } catch(Exception ex) {
+ throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'.", ex);
+ }
+ throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'.");
+ }
+
+ ///
+ /// Remove a flag from an enum type
+ ///
+ ///
+ ///
+ ///
+ public static T Remove(this Enum type, T value) {
+ Type underlyingType = Enum.GetUnderlyingType(value.GetType());
+ try
+ {
+ if (underlyingType == typeof(int)) {
+ return (T)(object)(((int)(object)type & ~(int)(object)value));
+ }
+ if (underlyingType == typeof(uint)) {
+ return (T)(object)(((uint)(object)type & ~(uint)(object)value));
+ }
+ } catch(Exception ex) {
+ throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'.", ex);
+ }
+ throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'.");
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/EventDelay.cs b/GreenshotPlugin/Core/EventDelay.cs
new file mode 100644
index 000000000..b02d4317b
--- /dev/null
+++ b/GreenshotPlugin/Core/EventDelay.cs
@@ -0,0 +1,41 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+
+namespace GreenshotPlugin.Core {
+ public class EventDelay {
+ private long lastCheck;
+ private readonly long waitTime;
+ public EventDelay(long ticks) {
+ waitTime = ticks;
+ }
+
+ public bool Check() {
+ lock (this) {
+ long now = DateTime.Now.Ticks;
+ bool isPassed = now - lastCheck > waitTime;
+ lastCheck = now;
+ return isPassed;
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/ExplorerHelper.cs b/GreenshotPlugin/Core/ExplorerHelper.cs
new file mode 100644
index 000000000..a94513f48
--- /dev/null
+++ b/GreenshotPlugin/Core/ExplorerHelper.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// Simple utility for the explorer
+ ///
+ public static class ExplorerHelper
+ {
+ ///
+ /// Open the path in the windows explorer.
+ /// If the path is a directory, it will just open the explorer with that directory.
+ /// If the path is a file, the explorer is opened with the directory and the file is selected.
+ ///
+ /// Path to file or directory
+ public static bool OpenInExplorer(string path)
+ {
+ if (path == null)
+ {
+ return false;
+ }
+ try
+ {
+ // Check if path is a directory
+ if (Directory.Exists(path))
+ {
+ using (Process.Start(path))
+ {
+ return true;
+ }
+ }
+ // Check if path is a file
+ if (File.Exists(path))
+ {
+ // Start the explorer process and select the file
+ using (var explorer = Process.Start("explorer.exe", $"/select,\"{path}\""))
+ {
+ explorer?.WaitForInputIdle(500);
+ return true;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Make sure we show what we tried to open in the exception
+ ex.Data.Add("path", path);
+ throw;
+ }
+ return false;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/ExtensionAttribute.cs b/GreenshotPlugin/Core/ExtensionAttribute.cs
new file mode 100644
index 000000000..147e9a007
--- /dev/null
+++ b/GreenshotPlugin/Core/ExtensionAttribute.cs
@@ -0,0 +1,26 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+namespace System.Runtime.CompilerServices {
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
+ public sealed class ExtensionAttribute : Attribute {}
+}
diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs
new file mode 100644
index 000000000..8bc3b3313
--- /dev/null
+++ b/GreenshotPlugin/Core/FastBitmap.cs
@@ -0,0 +1,1024 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+
+namespace GreenshotPlugin.Core {
+
+ ///
+ /// The interface for the FastBitmap
+ ///
+ public interface IFastBitmap : IDisposable {
+ ///
+ /// Get the color at x,y
+ /// The returned Color object depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// Color
+ Color GetColorAt(int x, int y);
+
+ ///
+ /// Set the color at the specified location
+ ///
+ /// int x
+ /// int y
+ /// Color
+ void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Get the color at x,y
+ /// The returned byte[] color depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// byte array
+ void GetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Set the color at the specified location
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Lock the bitmap
+ ///
+ void Lock();
+
+ ///
+ /// Unlock the bitmap
+ ///
+ void Unlock();
+
+ ///
+ /// Unlock the bitmap and get the underlying bitmap in one call
+ ///
+ ///
+ Bitmap UnlockAndReturnBitmap();
+
+ ///
+ /// Size of the underlying image
+ ///
+ Size Size {
+ get;
+ }
+
+ ///
+ /// Height of the image area that this fastbitmap covers
+ ///
+ int Height {
+ get;
+ }
+
+ ///
+ /// Width of the image area that this fastbitmap covers
+ ///
+ int Width {
+ get;
+ }
+
+ ///
+ /// Top of the image area that this fastbitmap covers
+ ///
+ int Top {
+ get;
+ }
+
+ ///
+ /// Left of the image area that this fastbitmap covers
+ ///
+ int Left {
+ get;
+ }
+
+ ///
+ /// Right of the image area that this fastbitmap covers
+ ///
+ int Right {
+ get;
+ }
+
+ ///
+ /// Bottom of the image area that this fastbitmap covers
+ ///
+ int Bottom {
+ get;
+ }
+
+ ///
+ /// Does the underlying image need to be disposed
+ ///
+ bool NeedsDispose {
+ get;
+ set;
+ }
+
+ ///
+ /// Returns if this FastBitmap has an alpha channel
+ ///
+ bool HasAlphaChannel {
+ get;
+ }
+
+ ///
+ /// Draw the stored bitmap to the destionation bitmap at the supplied point
+ ///
+ /// Graphics
+ /// Point with location
+ void DrawTo(Graphics graphics, Point destination);
+
+ ///
+ /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle
+ /// Be aware that the stored bitmap will be resized to the specified rectangle!!
+ ///
+ /// Graphics
+ /// Rectangle with destination
+ void DrawTo(Graphics graphics, Rectangle destinationRect);
+
+ ///
+ /// Return true if the coordinates are inside the FastBitmap
+ ///
+ ///
+ ///
+ ///
+ bool Contains(int x, int y);
+
+ ///
+ /// Set the bitmap resolution
+ ///
+ ///
+ ///
+ void SetResolution(float horizontal, float vertical);
+ }
+
+ ///
+ /// This interface can be used for when offsetting is needed
+ ///
+ public interface IFastBitmapWithOffset : IFastBitmap {
+ ///
+ /// Return true if the coordinates are inside the FastBitmap
+ ///
+ ///
+ ///
+ ///
+ new bool Contains(int x, int y);
+
+ ///
+ /// Set the color at the specified location, using offsetting so the original coordinates can be used
+ ///
+ /// int x
+ /// int y
+ /// Color color
+ new void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Set the color at the specified location, using offsetting so the original coordinates can be used
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ new void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Get the color at x,y
+ /// The returned Color object depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// Color
+ new Color GetColorAt(int x, int y);
+
+ ///
+ /// Get the color at x,y, using offsetting so the original coordinates can be used
+ /// The returned byte[] color depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// byte array
+ new void GetColorAt(int x, int y, byte[] color);
+
+ new int Left {
+ get;
+ set;
+ }
+
+ new int Top {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// This interface can be used for when clipping is needed
+ ///
+ public interface IFastBitmapWithClip : IFastBitmap {
+ Rectangle Clip {
+ get;
+ set;
+ }
+
+ bool InvertClip {
+ get;
+ set;
+ }
+
+ ///
+ /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping
+ ///
+ /// int x
+ /// int y
+ /// Color color
+ new void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ new void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Return true if the coordinates are inside the FastBitmap and not clipped
+ ///
+ ///
+ ///
+ ///
+ new bool Contains(int x, int y);
+ }
+
+ ///
+ /// This interface is implemented when there is a alpha-blending possibility
+ ///
+ public interface IFastBitmapWithBlend : IFastBitmap {
+ Color BackgroundBlendColor {
+ get;
+ set;
+ }
+ Color GetBlendedColorAt(int x, int y);
+ }
+
+ ///
+ /// The base class for the fast bitmap implementation
+ ///
+ public abstract unsafe class FastBitmap : IFastBitmapWithClip, IFastBitmapWithOffset {
+ protected const int PixelformatIndexA = 3;
+ protected const int PixelformatIndexR = 2;
+ protected const int PixelformatIndexG = 1;
+ protected const int PixelformatIndexB = 0;
+
+ public const int ColorIndexR = 0;
+ public const int ColorIndexG = 1;
+ public const int ColorIndexB = 2;
+ public const int ColorIndexA = 3;
+
+ protected Rectangle Area;
+ ///
+ /// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap
+ ///
+ public bool NeedsDispose {
+ get;
+ set;
+ }
+
+ public Rectangle Clip {
+ get;
+ set;
+ }
+
+ public bool InvertClip {
+ get;
+ set;
+ }
+
+ ///
+ /// The bitmap for which the FastBitmap is creating access
+ ///
+ protected Bitmap Bitmap;
+
+ protected BitmapData BmData;
+ protected int Stride; /* bytes per pixel row */
+ protected bool BitsLocked;
+ protected byte* Pointer;
+
+ public static IFastBitmap Create(Bitmap source) {
+ return Create(source, Rectangle.Empty);
+ }
+
+ public void SetResolution(float horizontal, float vertical) {
+ Bitmap.SetResolution(horizontal, vertical);
+ }
+
+ ///
+ /// Factory for creating a FastBitmap depending on the pixelformat of the source
+ /// The supplied rectangle specifies the area for which the FastBitmap does its thing
+ ///
+ /// Bitmap to access
+ /// Rectangle which specifies the area to have access to, can be Rectangle.Empty for the whole image
+ /// IFastBitmap
+ public static IFastBitmap Create(Bitmap source, Rectangle area) {
+ switch (source.PixelFormat) {
+ case PixelFormat.Format8bppIndexed:
+ return new FastChunkyBitmap(source, area);
+ case PixelFormat.Format24bppRgb:
+ return new Fast24RgbBitmap(source, area);
+ case PixelFormat.Format32bppRgb:
+ return new Fast32RgbBitmap(source, area);
+ case PixelFormat.Format32bppArgb:
+ case PixelFormat.Format32bppPArgb:
+ return new Fast32ArgbBitmap(source, area);
+ default:
+ throw new NotSupportedException($"Not supported Pixelformat {source.PixelFormat}");
+ }
+ }
+
+ ///
+ /// Factory for creating a FastBitmap as a destination for the source
+ ///
+ /// Bitmap to clone
+ /// IFastBitmap
+ public static IFastBitmap CreateCloneOf(Image source) {
+ return CreateCloneOf(source, source.PixelFormat, Rectangle.Empty);
+ }
+
+ ///
+ /// Factory for creating a FastBitmap as a destination for the source
+ ///
+ /// Bitmap to clone
+ /// new Pixelformat
+ /// IFastBitmap
+ public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) {
+ return CreateCloneOf(source, pixelFormat, Rectangle.Empty);
+ }
+ ///
+ /// Factory for creating a FastBitmap as a destination for the source
+ ///
+ /// Bitmap to clone
+ /// Area of the bitmap to access, can be Rectangle.Empty for the whole
+ /// IFastBitmap
+ public static IFastBitmap CreateCloneOf(Image source, Rectangle area) {
+ return CreateCloneOf(source, PixelFormat.DontCare, area);
+ }
+
+ ///
+ /// Factory for creating a FastBitmap as a destination for the source
+ ///
+ /// Bitmap to clone
+ /// Pixelformat of the cloned bitmap
+ /// Area of the bitmap to access, can be Rectangle.Empty for the whole
+ /// IFastBitmap
+ public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat, Rectangle area) {
+ Bitmap destination = ImageHelper.CloneArea(source, area, pixelFormat);
+ FastBitmap fastBitmap = Create(destination) as FastBitmap;
+ if (fastBitmap != null)
+ {
+ fastBitmap.NeedsDispose = true;
+ fastBitmap.Left = area.Left;
+ fastBitmap.Top = area.Top;
+ }
+ return fastBitmap;
+ }
+
+ ///
+ /// Factory for creating a FastBitmap as a destination
+ ///
+ ///
+ ///
+ ///
+ /// IFastBitmap
+ public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) {
+ Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f);
+ IFastBitmap fastBitmap = Create(destination);
+ fastBitmap.NeedsDispose = true;
+ return fastBitmap;
+ }
+
+ ///
+ /// Constructor which stores the image and locks it when called
+ ///
+ /// Bitmap
+ /// Rectangle
+ protected FastBitmap(Bitmap bitmap, Rectangle area) {
+ Bitmap = bitmap;
+ Rectangle bitmapArea = new Rectangle(Point.Empty, bitmap.Size);
+ if (area != Rectangle.Empty) {
+ area.Intersect(bitmapArea);
+ Area = area;
+ } else {
+ Area = bitmapArea;
+ }
+ // As the lock takes care that only the specified area is made available we need to calculate the offset
+ Left = area.Left;
+ Top = area.Top;
+ // Default cliping is done to the area without invert
+ Clip = Area;
+ InvertClip = false;
+ // Always lock, so we don't need to do this ourselves
+ Lock();
+ }
+
+ ///
+ /// Return the size of the image
+ ///
+ public Size Size {
+ get {
+ if (Area == Rectangle.Empty) {
+ return Bitmap.Size;
+ }
+ return Area.Size;
+ }
+ }
+
+ ///
+ /// Return the width of the image
+ ///
+ public int Width {
+ get {
+ if (Area == Rectangle.Empty) {
+ return Bitmap.Width;
+ }
+ return Area.Width;
+ }
+ }
+
+ ///
+ /// Return the height of the image
+ ///
+ public int Height {
+ get {
+ if (Area == Rectangle.Empty) {
+ return Bitmap.Height;
+ }
+ return Area.Height;
+ }
+ }
+
+ private int _left;
+ ///
+ /// Return the left of the fastbitmap, this is also used as an offset
+ ///
+ public int Left {
+ get {
+ return 0;
+ }
+ set {
+ _left = value;
+ }
+ }
+
+ ///
+ /// Return the left of the fastbitmap, this is also used as an offset
+ ///
+ int IFastBitmapWithOffset.Left {
+ get {
+ return _left;
+ }
+ set {
+ _left = value;
+ }
+ }
+
+ private int _top;
+ ///
+ /// Return the top of the fastbitmap, this is also used as an offset
+ ///
+ public int Top {
+ get {
+ return 0;
+ }
+ set {
+ _top = value;
+ }
+ }
+
+ ///
+ /// Return the top of the fastbitmap, this is also used as an offset
+ ///
+ int IFastBitmapWithOffset.Top {
+ get {
+ return _top;
+ }
+ set {
+ _top = value;
+ }
+ }
+
+ ///
+ /// Return the right of the fastbitmap
+ ///
+ public int Right => Left + Width;
+
+ ///
+ /// Return the bottom of the fastbitmap
+ ///
+ public int Bottom => Top + Height;
+
+ ///
+ /// Returns the underlying bitmap, unlocks it and prevents that it will be disposed
+ ///
+ public Bitmap UnlockAndReturnBitmap() {
+ if (BitsLocked) {
+ Unlock();
+ }
+ NeedsDispose = false;
+ return Bitmap;
+ }
+
+ public virtual bool HasAlphaChannel => false;
+
+ ///
+ /// Destructor
+ ///
+ ~FastBitmap() {
+ Dispose(false);
+ }
+
+ ///
+ /// The public accessible Dispose
+ /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
+ ///
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ // The bulk of the clean-up code is implemented in Dispose(bool)
+
+ ///
+ /// This Dispose is called from the Dispose and the Destructor.
+ /// When disposing==true all non-managed resources should be freed too!
+ ///
+ ///
+ protected virtual void Dispose(bool disposing) {
+ Unlock();
+ if (disposing) {
+ if (Bitmap != null && NeedsDispose) {
+ Bitmap.Dispose();
+ }
+ }
+ Bitmap = null;
+ BmData = null;
+ Pointer = null;
+ }
+
+ ///
+ /// Lock the bitmap so we have direct access to the memory
+ ///
+ public void Lock() {
+ if (Width <= 0 || Height <= 0 || BitsLocked)
+ {
+ return;
+ }
+ BmData = Bitmap.LockBits(Area, ImageLockMode.ReadWrite, Bitmap.PixelFormat);
+ BitsLocked = true;
+
+ IntPtr scan0 = BmData.Scan0;
+ Pointer = (byte*)(void*)scan0;
+ Stride = BmData.Stride;
+ }
+
+ ///
+ /// Unlock the System Memory
+ ///
+ public void Unlock() {
+ if (BitsLocked) {
+ Bitmap.UnlockBits(BmData);
+ BitsLocked = false;
+ }
+ }
+
+ ///
+ /// Draw the stored bitmap to the destionation bitmap at the supplied point
+ ///
+ ///
+ ///
+ public void DrawTo(Graphics graphics, Point destination) {
+ DrawTo(graphics, new Rectangle(destination, Area.Size));
+ }
+
+ ///
+ /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle
+ /// Be aware that the stored bitmap will be resized to the specified rectangle!!
+ ///
+ ///
+ ///
+ public void DrawTo(Graphics graphics, Rectangle destinationRect) {
+ // Make sure this.bitmap is unlocked, if it was locked
+ bool isLocked = BitsLocked;
+ if (isLocked) {
+ Unlock();
+ }
+
+ graphics.DrawImage(Bitmap, destinationRect, Area, GraphicsUnit.Pixel);
+ }
+
+ ///
+ /// returns true if x & y are inside the FastBitmap
+ ///
+ ///
+ ///
+ /// true if x & y are inside the FastBitmap
+ public bool Contains(int x, int y) {
+ return Area.Contains(x - Left, y - Top);
+ }
+
+ public abstract Color GetColorAt(int x, int y);
+ public abstract void SetColorAt(int x, int y, Color color);
+ public abstract void GetColorAt(int x, int y, byte[] color);
+ public abstract void SetColorAt(int x, int y, byte[] color);
+
+ #region IFastBitmapWithClip
+ bool IFastBitmapWithClip.Contains(int x, int y) {
+ bool contains = Clip.Contains(x, y);
+ if (InvertClip) {
+ return !contains;
+ } else {
+ return contains;
+ }
+ }
+
+ void IFastBitmapWithClip.SetColorAt(int x, int y, byte[] color) {
+ bool contains = Clip.Contains(x, y);
+ if ((InvertClip && contains) || (!InvertClip && !contains)) {
+ return;
+ }
+ SetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithClip.SetColorAt(int x, int y, Color color) {
+ bool contains = Clip.Contains(x, y);
+ if ((InvertClip && contains) || (!InvertClip && !contains)) {
+ return;
+ }
+ SetColorAt(x, y, color);
+ }
+ #endregion
+
+ #region IFastBitmapWithOffset
+ ///
+ /// returns true if x & y are inside the FastBitmap
+ ///
+ ///
+ ///
+ /// true if x & y are inside the FastBitmap
+ bool IFastBitmapWithOffset.Contains(int x, int y) {
+ return Area.Contains(x - Left, y - Top);
+ }
+
+ Color IFastBitmapWithOffset.GetColorAt(int x, int y) {
+ x -= _left;
+ y -= _top;
+ return GetColorAt(x, y);
+ }
+ void IFastBitmapWithOffset.GetColorAt(int x, int y, byte[] color) {
+ x -= _left;
+ y -= _top;
+ GetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithOffset.SetColorAt(int x, int y, byte[] color) {
+ x -= _left;
+ y -= _top;
+ SetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithOffset.SetColorAt(int x, int y, Color color) {
+ x -= _left;
+ y -= _top;
+ SetColorAt(x, y, color);
+ }
+ #endregion
+ }
+
+ ///
+ /// This is the implementation of the FastBitmat for the 8BPP pixelformat
+ ///
+ public unsafe class FastChunkyBitmap : FastBitmap {
+ // Used for indexed images
+ private readonly Color[] _colorEntries;
+ private readonly Dictionary _colorCache = new Dictionary();
+
+ public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area) {
+ _colorEntries = Bitmap.Palette.Entries;
+ }
+
+ ///
+ /// Get the color from the specified location
+ ///
+ ///
+ ///
+ /// Color
+ public override Color GetColorAt(int x, int y) {
+ int offset = x + (y * Stride);
+ byte colorIndex = Pointer[offset];
+ return _colorEntries[colorIndex];
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference
+ public override void GetColorAt(int x, int y, byte[] color) {
+ throw new NotImplementedException("No performance gain!");
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference
+ public override void SetColorAt(int x, int y, byte[] color) {
+ throw new NotImplementedException("No performance gain!");
+ }
+
+ ///
+ /// Get the color-index from the specified location
+ ///
+ ///
+ ///
+ /// byte with index
+ public byte GetColorIndexAt(int x, int y) {
+ int offset = x + (y * Stride);
+ return Pointer[offset];
+ }
+
+ ///
+ /// Set the color-index at the specified location
+ ///
+ ///
+ ///
+ ///
+ public void SetColorIndexAt(int x, int y, byte colorIndex) {
+ int offset = x + (y * Stride);
+ Pointer[offset] = colorIndex;
+ }
+
+ ///
+ /// Set the supplied color at the specified location.
+ /// Throws an ArgumentException if the color is not in the palette
+ ///
+ ///
+ ///
+ /// Color to set
+ public override void SetColorAt(int x, int y, Color color) {
+ int offset = x + (y * Stride);
+ byte colorIndex;
+ if (!_colorCache.TryGetValue(color, out colorIndex)) {
+ bool foundColor = false;
+ for (colorIndex = 0; colorIndex < _colorEntries.Length; colorIndex++) {
+ if (color == _colorEntries[colorIndex]) {
+ _colorCache.Add(color, colorIndex);
+ foundColor = true;
+ break;
+ }
+ }
+ if (!foundColor) {
+ throw new ArgumentException("No such color!");
+ }
+ }
+ Pointer[offset] = colorIndex;
+ }
+ }
+
+ ///
+ /// This is the implementation of the IFastBitmap for 24 bit images (no Alpha)
+ ///
+ public unsafe class Fast24RgbBitmap : FastBitmap {
+
+ public Fast24RgbBitmap(Bitmap source, Rectangle area) : base(source, area) {
+ }
+
+ ///
+ /// Retrieve the color at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ /// X coordinate
+ /// Y Coordinate
+ /// Color
+ public override Color GetColorAt(int x, int y) {
+ int offset = (x * 3) + (y * Stride);
+ return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]);
+ }
+
+ ///
+ /// Set the color at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ ///
+ ///
+ ///
+ public override void SetColorAt(int x, int y, Color color) {
+ int offset = (x * 3) + (y * Stride);
+ Pointer[PixelformatIndexR + offset] = color.R;
+ Pointer[PixelformatIndexG + offset] = color.G;
+ Pointer[PixelformatIndexB + offset] = color.B;
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (r,g,b)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 3) + (y * Stride);
+ color[PixelformatIndexR] = Pointer[PixelformatIndexR + offset];
+ color[PixelformatIndexG] = Pointer[PixelformatIndexG + offset];
+ color[PixelformatIndexB] = Pointer[PixelformatIndexB + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (r,g,b)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 3) + (y * Stride);
+ Pointer[PixelformatIndexR + offset] = color[PixelformatIndexR];
+ Pointer[PixelformatIndexG + offset] = color[PixelformatIndexG];
+ Pointer[PixelformatIndexB + offset] = color[PixelformatIndexB];
+ }
+
+ }
+
+ ///
+ /// This is the implementation of the IFastBitmap for 32 bit images (no Alpha)
+ ///
+ public unsafe class Fast32RgbBitmap : FastBitmap {
+ public Fast32RgbBitmap(Bitmap source, Rectangle area) : base(source, area) {
+
+ }
+
+ ///
+ /// Retrieve the color at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ /// X coordinate
+ /// Y Coordinate
+ /// Color
+ public override Color GetColorAt(int x, int y) {
+ int offset = (x * 4) + (y * Stride);
+ return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]);
+ }
+
+ ///
+ /// Set the color at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ ///
+ ///
+ ///
+ public override void SetColorAt(int x, int y, Color color) {
+ int offset = (x * 4) + (y * Stride);
+ Pointer[PixelformatIndexR + offset] = color.R;
+ Pointer[PixelformatIndexG + offset] = color.G;
+ Pointer[PixelformatIndexB + offset] = color.B;
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * Stride);
+ color[ColorIndexR] = Pointer[PixelformatIndexR + offset];
+ color[ColorIndexG] = Pointer[PixelformatIndexG + offset];
+ color[ColorIndexB] = Pointer[PixelformatIndexB + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (r,g,b)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * Stride);
+ Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R
+ Pointer[PixelformatIndexG + offset] = color[ColorIndexG];
+ Pointer[PixelformatIndexB + offset] = color[ColorIndexB];
+ }
+ }
+
+ ///
+ /// This is the implementation of the IFastBitmap for 32 bit images with Alpha
+ ///
+ public unsafe class Fast32ArgbBitmap : FastBitmap, IFastBitmapWithBlend {
+ public override bool HasAlphaChannel => true;
+
+ public Color BackgroundBlendColor {
+ get;
+ set;
+ }
+ public Fast32ArgbBitmap(Bitmap source, Rectangle area) : base(source, area) {
+ BackgroundBlendColor = Color.White;
+ }
+
+ ///
+ /// Retrieve the color at location x,y
+ ///
+ /// X coordinate
+ /// Y Coordinate
+ /// Color
+ public override Color GetColorAt(int x, int y) {
+ int offset = (x * 4) + (y * Stride);
+ return Color.FromArgb(Pointer[PixelformatIndexA + offset], Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]);
+ }
+
+ ///
+ /// Set the color at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ ///
+ ///
+ ///
+ public override void SetColorAt(int x, int y, Color color) {
+ int offset = (x * 4) + (y * Stride);
+ Pointer[PixelformatIndexA + offset] = color.A;
+ Pointer[PixelformatIndexR + offset] = color.R;
+ Pointer[PixelformatIndexG + offset] = color.G;
+ Pointer[PixelformatIndexB + offset] = color.B;
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (r,g,b,a)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * Stride);
+ color[ColorIndexR] = Pointer[PixelformatIndexR + offset];
+ color[ColorIndexG] = Pointer[PixelformatIndexG + offset];
+ color[ColorIndexB] = Pointer[PixelformatIndexB + offset];
+ color[ColorIndexA] = Pointer[PixelformatIndexA + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (r,g,b,a)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * Stride);
+ Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R
+ Pointer[PixelformatIndexG + offset] = color[ColorIndexG];
+ Pointer[PixelformatIndexB + offset] = color[ColorIndexB];
+ Pointer[PixelformatIndexA + offset] = color[ColorIndexA];
+ }
+
+ ///
+ /// Retrieve the color, without alpha (is blended), at location x,y
+ /// Before the first time this is called the Lock() should be called once!
+ ///
+ /// X coordinate
+ /// Y Coordinate
+ /// Color
+ public Color GetBlendedColorAt(int x, int y) {
+ int offset = (x * 4) + (y * Stride);
+ int a = Pointer[PixelformatIndexA + offset];
+ int red = Pointer[PixelformatIndexR + offset];
+ int green = Pointer[PixelformatIndexG + offset];
+ int blue = Pointer[PixelformatIndexB + offset];
+
+ if (a < 255) {
+ // As the request is to get without alpha, we blend.
+ int rem = 255 - a;
+ red = (red * a + BackgroundBlendColor.R * rem) / 255;
+ green = (green * a + BackgroundBlendColor.G * rem) / 255;
+ blue = (blue * a + BackgroundBlendColor.B * rem) / 255;
+ }
+ return Color.FromArgb(255, red, green, blue);
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/FilenameHelper.cs b/GreenshotPlugin/Core/FilenameHelper.cs
new file mode 100644
index 000000000..2016c27af
--- /dev/null
+++ b/GreenshotPlugin/Core/FilenameHelper.cs
@@ -0,0 +1,552 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using log4net;
+using System.Collections.Generic;
+
+namespace GreenshotPlugin.Core {
+ public static class FilenameHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(FilenameHelper));
+ // Specify the regular expression for the filename formatting:
+ // Starting with ${
+ // than the varname, which ends with a : or }
+ // If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters.
+ // The parameter format is a single alpha followed by the value belonging to the parameter, e.g. :
+ // ${capturetime:d"yyyy-MM-dd HH_mm_ss"}
+ private static readonly Regex VarRegexp = new Regex(@"\${(?[^:}]+)[:]?(?[^}]*)}", RegexOptions.Compiled);
+ private static readonly Regex CmdVarRegexp = new Regex(@"%(?[^%]+)%", RegexOptions.Compiled);
+
+ private static readonly Regex SplitRegexp = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled);
+ private const int MaxTitleLength = 80;
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private const string UnsafeReplacement = "_";
+
+ ///
+ /// Remove invalid characters from the fully qualified filename
+ ///
+ /// string with the full path to a file
+ /// string with the full path to a file, without invalid characters
+ public static string MakeFqFilenameSafe(string fullPath) {
+ string path = MakePathSafe(Path.GetDirectoryName(fullPath));
+ string filename = MakeFilenameSafe(Path.GetFileName(fullPath));
+ // Make the fullpath again and return
+ return Path.Combine(path, filename);
+ }
+
+ ///
+ /// Remove invalid characters from the filename
+ ///
+ /// string with the full path to a file
+ /// string with the full path to a file, without invalid characters
+ public static string MakeFilenameSafe(string filename) {
+ // Make the filename save!
+ if (filename != null) {
+ foreach (char disallowed in Path.GetInvalidFileNameChars()) {
+ filename = filename.Replace(disallowed.ToString(), UnsafeReplacement);
+ }
+ }
+ return filename;
+ }
+
+ ///
+ /// Remove invalid characters from the path
+ ///
+ /// string with the full path to a file
+ /// string with the full path to a file, without invalid characters
+ public static string MakePathSafe(string path) {
+ // Make the path save!
+ if (path != null) {
+ foreach (char disallowed in Path.GetInvalidPathChars()) {
+ path = path.Replace(disallowed.ToString(), UnsafeReplacement);
+ }
+ }
+ return path;
+ }
+
+ public static string GetFilenameWithoutExtensionFromPattern(string pattern) {
+ return GetFilenameWithoutExtensionFromPattern(pattern, null);
+ }
+
+ public static string GetFilenameWithoutExtensionFromPattern(string pattern, ICaptureDetails captureDetails) {
+ return FillPattern(pattern, captureDetails, true);
+ }
+
+ public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat) {
+ return GetFilenameFromPattern(pattern, imageFormat, null);
+ }
+
+ public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat, ICaptureDetails captureDetails) {
+ return FillPattern(pattern, captureDetails, true) + "." + imageFormat.ToString().ToLower();
+ }
+
+ ///
+ /// Return a filename for the current image format (png,jpg etc) with the default file pattern
+ /// that is specified in the configuration
+ ///
+ /// A string with the format
+ ///
+ /// The filename which should be used to save the image
+ public static string GetFilename(OutputFormat format, ICaptureDetails captureDetails) {
+ string pattern = CoreConfig.OutputFileFilenamePattern;
+ if (string.IsNullOrEmpty(pattern?.Trim())) {
+ pattern = "greenshot ${capturetime}";
+ }
+ return GetFilenameFromPattern(pattern, format, captureDetails);
+ }
+
+
+ ///
+ /// This method will be called by the regexp.replace as a MatchEvaluator delegate!
+ /// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions
+ ///
+ /// What are we matching?
+ /// The detail, can be null
+ /// Variables from the process
+ /// Variables from the user
+ /// Variables from the machine
+ ///
+ /// string with the match replacement
+ private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode) {
+ try {
+ return MatchVarEvaluatorInternal(match, captureDetails, processVars, userVars, machineVars, filenameSafeMode);
+ } catch (Exception e) {
+ Log.Error("Error in MatchVarEvaluatorInternal", e);
+ }
+ return string.Empty;
+ }
+
+ ///
+ /// This method will be called by the regexp.replace as a MatchEvaluator delegate!
+ ///
+ /// What are we matching?
+ /// The detail, can be null
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode) {
+ // some defaults
+ int padWidth = 0;
+ int startIndex = 0;
+ int endIndex = 0;
+ char padChar = ' ';
+ string dateFormat = "yyyy-MM-dd HH-mm-ss";
+ IDictionary replacements = new Dictionary();
+ string replaceValue = "";
+ string variable = match.Groups["variable"].Value;
+ string parameters = match.Groups["parameters"].Value;
+
+ if (parameters.Length > 0) {
+ string[] parms = SplitRegexp.Split(parameters);
+ foreach (string parameter in parms) {
+ switch (parameter.Substring(0, 1)) {
+ // Padding p[,pad-character]
+ case "p":
+ string[] padParams = parameter.Substring(1).Split(',');
+ try {
+ padWidth = int.Parse(padParams[0]);
+ }
+ catch
+ {
+ // ignored
+ }
+ if (padParams.Length > 1) {
+ padChar = padParams[1][0];
+ }
+ break;
+ // replace
+ // r,
+ case "r":
+ string[] replaceParameters = parameter.Substring(1).Split(',');
+ if (replaceParameters != null && replaceParameters.Length == 2) {
+ replacements.Add(replaceParameters[0], replaceParameters[1]);
+ }
+ break;
+ // Dateformat d
+ // Format can be anything that is used in C# date formatting
+ case "d":
+ dateFormat = parameter.Substring(1);
+ if (dateFormat.StartsWith("\"")) {
+ dateFormat = dateFormat.Substring(1);
+ }
+ if (dateFormat.EndsWith("\"")) {
+ dateFormat = dateFormat.Substring(0, dateFormat.Length - 1);
+ }
+ break;
+ // Substring:
+ // s[,length]
+ case "s":
+ string range = parameter.Substring(1);
+ string[] rangelist = range.Split(',');
+ if (rangelist.Length > 0) {
+ try {
+ startIndex = int.Parse(rangelist[0]);
+ } catch {
+ // Ignore
+ }
+ }
+ if (rangelist.Length > 1) {
+ try {
+ endIndex = int.Parse(rangelist[1]);
+ } catch {
+ // Ignore
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (processVars != null && processVars.Contains(variable)) {
+ replaceValue = (string)processVars[variable];
+ if (filenameSafeMode) {
+ replaceValue = MakePathSafe(replaceValue);
+ }
+ } else if (userVars != null && userVars.Contains(variable)) {
+ replaceValue = (string)userVars[variable];
+ if (filenameSafeMode) {
+ replaceValue = MakePathSafe(replaceValue);
+ }
+ } else if (machineVars != null && machineVars.Contains(variable)) {
+ replaceValue = (string)machineVars[variable];
+ if (filenameSafeMode) {
+ replaceValue = MakePathSafe(replaceValue);
+ }
+ } else if (captureDetails?.MetaData != null && captureDetails.MetaData.ContainsKey(variable)) {
+ replaceValue = captureDetails.MetaData[variable];
+ if (filenameSafeMode) {
+ replaceValue = MakePathSafe(replaceValue);
+ }
+ } else {
+ // Handle other variables
+ // Default use "now" for the capture take´n
+ DateTime capturetime = DateTime.Now;
+ // Use default application name for title
+ string title = Application.ProductName;
+
+ // Check if we have capture details
+ if (captureDetails != null) {
+ capturetime = captureDetails.DateTime;
+ if (captureDetails.Title != null) {
+ title = captureDetails.Title;
+ if (title.Length > MaxTitleLength) {
+ title = title.Substring(0, MaxTitleLength);
+ }
+ }
+ }
+ switch (variable) {
+ case "domain":
+ replaceValue = Environment.UserDomainName;
+ break;
+ case "user":
+ replaceValue = Environment.UserName;
+ break;
+ case "hostname":
+ replaceValue = Environment.MachineName;
+ break;
+ case "YYYY":
+ if (padWidth == 0) {
+ padWidth = -4;
+ padChar = '0';
+ }
+ replaceValue = capturetime.Year.ToString();
+ break;
+ case "MM":
+ replaceValue = capturetime.Month.ToString();
+ if (padWidth == 0) {
+ padWidth = -2;
+ padChar = '0';
+ }
+ break;
+ case "DD":
+ replaceValue = capturetime.Day.ToString();
+ if (padWidth == 0) {
+ padWidth = -2;
+ padChar = '0';
+ }
+ break;
+ case "hh":
+ if (padWidth == 0) {
+ padWidth = -2;
+ padChar = '0';
+ }
+ replaceValue = capturetime.Hour.ToString();
+ break;
+ case "mm":
+ if (padWidth == 0) {
+ padWidth = -2;
+ padChar = '0';
+ }
+ replaceValue = capturetime.Minute.ToString();
+ break;
+ case "ss":
+ if (padWidth == 0) {
+ padWidth = -2;
+ padChar = '0';
+ }
+ replaceValue = capturetime.Second.ToString();
+ break;
+ case "now":
+ replaceValue = DateTime.Now.ToString(dateFormat);
+ if (filenameSafeMode) {
+ replaceValue = MakeFilenameSafe(replaceValue);
+ }
+ break;
+ case "capturetime":
+ replaceValue = capturetime.ToString(dateFormat);
+ if (filenameSafeMode) {
+ replaceValue = MakeFilenameSafe(replaceValue);
+ }
+ break;
+ case "NUM":
+ CoreConfig.OutputFileIncrementingNumber++;
+ IniConfig.Save();
+ replaceValue = CoreConfig.OutputFileIncrementingNumber.ToString();
+ if (padWidth == 0) {
+ padWidth = -6;
+ padChar = '0';
+ }
+
+ break;
+ case "title":
+ replaceValue = title;
+ if (filenameSafeMode) {
+ replaceValue = MakeFilenameSafe(replaceValue);
+ }
+ break;
+ case "MyPictures":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
+ break;
+ case "MyMusic":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
+ break;
+ case "MyDocuments":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ break;
+ case "Personal":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
+ break;
+ case "Desktop":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
+ break;
+ case "ApplicationData":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ break;
+ case "LocalApplicationData":
+ replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ break;
+ }
+ }
+ // do padding
+ if (padWidth > 0) {
+ replaceValue = replaceValue.PadRight(padWidth, padChar);
+ } else if (padWidth < 0) {
+ replaceValue = replaceValue.PadLeft(-padWidth, padChar);
+ }
+
+ // do substring
+ if (startIndex != 0 || endIndex != 0) {
+ if (startIndex < 0) {
+ startIndex = replaceValue.Length + startIndex;
+ }
+ if (endIndex < 0) {
+ endIndex = replaceValue.Length + endIndex;
+ }
+ if (endIndex != 0) {
+ try {
+ replaceValue = replaceValue.Substring(startIndex, endIndex);
+ } catch {
+ // Ignore
+ }
+ } else {
+ try {
+ replaceValue = replaceValue.Substring(startIndex);
+ } catch {
+ // Ignore
+ }
+ }
+ }
+
+ // new for feature #697
+ if (replacements.Count > 0) {
+ foreach (string oldValue in replacements.Keys) {
+ replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]);
+ }
+ }
+ return replaceValue;
+ }
+
+ ///
+ /// "Simply" fill the pattern with environment variables
+ ///
+ /// String with pattern %var%
+ /// true to make sure everything is filenamesafe
+ /// Filled string
+ public static string FillCmdVariables(string pattern, bool filenameSafeMode = true)
+ {
+ IDictionary processVars = null;
+ IDictionary userVars = null;
+ IDictionary machineVars = null;
+ try
+ {
+ processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
+ }
+ catch (Exception e)
+ {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Process", e);
+ }
+
+ try
+ {
+ userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
+ }
+ catch (Exception e)
+ {
+ Log.Error("Error retrieving EnvironmentVariableTarget.User", e);
+ }
+
+ try
+ {
+ machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
+ }
+ catch (Exception e)
+ {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e);
+ }
+
+ return CmdVarRegexp.Replace(pattern,
+ m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode)
+ );
+ }
+
+ ///
+ /// "Simply" fill the pattern with environment variables
+ ///
+ /// String with pattern ${var}
+ /// true to make sure everything is filenamesafe
+ /// Filled string
+ public static string FillVariables(string pattern, bool filenameSafeMode) {
+ IDictionary processVars = null;
+ IDictionary userVars = null;
+ IDictionary machineVars = null;
+ try {
+ processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Process", e);
+ }
+
+ try {
+ userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.User", e);
+ }
+
+ try {
+ machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e);
+ }
+
+ return VarRegexp.Replace(pattern,
+ m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode)
+ );
+ }
+
+ ///
+ /// Fill the pattern wit the supplied details
+ ///
+ /// Pattern
+ /// CaptureDetails, can be null
+ /// Should the result be made "filename" safe?
+ /// Filled pattern
+ public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode) {
+ IDictionary processVars = null;
+ IDictionary userVars = null;
+ IDictionary machineVars = null;
+ try {
+ processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Process", e);
+ }
+
+ try {
+ userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.User", e);
+ }
+
+ try {
+ machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
+ } catch (Exception e) {
+ Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e);
+ }
+
+ try {
+ return VarRegexp.Replace(pattern,
+ m => MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode)
+ );
+ } catch (Exception e) {
+ // adding additional data for bug tracking
+ if (captureDetails != null) {
+ e.Data.Add("title", captureDetails.Title);
+ }
+ e.Data.Add("pattern", pattern);
+ throw;
+ }
+ }
+
+ ///
+ /// Checks whether a directory name is valid in the current file system
+ ///
+ /// directory name (not path!)
+ /// true if directory name is valid
+ public static bool IsDirectoryNameValid(string directoryName) {
+ var forbiddenChars = Path.GetInvalidPathChars();
+ foreach (var forbiddenChar in forbiddenChars) {
+ if (directoryName == null || directoryName.Contains(forbiddenChar.ToString())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Checks whether a filename is valid in the current file system
+ ///
+ /// name of the file
+ /// true if filename is valid
+ public static bool IsFilenameValid(string filename) {
+ var forbiddenChars = Path.GetInvalidFileNameChars();
+ foreach (var forbiddenChar in forbiddenChars) {
+ if (filename == null || filename.Contains(forbiddenChar.ToString())) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/Func.cs b/GreenshotPlugin/Core/Func.cs
new file mode 100644
index 000000000..9c15475ca
--- /dev/null
+++ b/GreenshotPlugin/Core/Func.cs
@@ -0,0 +1,29 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace GreenshotPlugin.Core
+{
+ public delegate TResult Func();
+ public delegate TResult Func(T arg);
+ public delegate TResult Func(T1 arg1, T2 arg2);
+ public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3);
+ public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+}
diff --git a/GreenshotPlugin/Core/GreenshotResources.cs b/GreenshotPlugin/Core/GreenshotResources.cs
new file mode 100644
index 000000000..a4e2dae85
--- /dev/null
+++ b/GreenshotPlugin/Core/GreenshotResources.cs
@@ -0,0 +1,46 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System.ComponentModel;
+using System.Drawing;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Centralized storage of the icons & bitmaps
+ ///
+ public static class GreenshotResources {
+ private static readonly ComponentResourceManager greenshotResources = new ComponentResourceManager(typeof(GreenshotResources));
+
+ public static Image getImage(string imageName) {
+ return (Image)greenshotResources.GetObject(imageName);
+ }
+ public static Icon getIcon(string imageName) {
+ return (Icon)greenshotResources.GetObject(imageName);
+ }
+
+ public static Icon getGreenshotIcon() {
+ return getIcon("Greenshot.Icon");
+ }
+
+ public static Image getGreenshotImage() {
+ return getImage("Greenshot.Image");
+ }
+ }
+}
diff --git a/src/Greenshot.Base/Core/GreenshotResources.resx b/GreenshotPlugin/Core/GreenshotResources.resx
similarity index 98%
rename from src/Greenshot.Base/Core/GreenshotResources.resx
rename to GreenshotPlugin/Core/GreenshotResources.resx
index ea1760d58..dce181b2b 100644
--- a/src/Greenshot.Base/Core/GreenshotResources.resx
+++ b/GreenshotPlugin/Core/GreenshotResources.resx
@@ -1,471 +1,471 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA
- CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA
- ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP
- 6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By
- cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB
- ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC
- QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF
- gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES
- lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97
- 7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz
- fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64
- hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2
- bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G
- m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE
- k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6
- zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E
- IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j
- vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF
- Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6
- zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t
- xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb
- REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK
- 0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt
- mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd
- I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm
- Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0
- uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH
- 6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz
- l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q
- iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr
- hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM
- BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R
- q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g
- PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp
- NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP
- 4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1
- VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF
- IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS
- Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW
- hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5
- FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/
- SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU
- wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A
- MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY
- dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D
- lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y
- ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct
- KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p
- 5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0
- JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n
- AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y
- dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx
- KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO
- IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo
- NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn
- RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY
- cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv
- TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH
- 5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb
- jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq
- WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO
- Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB
- ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg
- wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV
- /xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ
- 2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25
- rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM
- ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7
- r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT
- iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o
- zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw
- +u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw
- CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC
- 27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N
- 7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1
- zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl
- Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3
- kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO
- PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl
- AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt
- xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC
- NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E
- zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq
- ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg
- d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ
- 6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa
- w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa
- /8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t
- ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK
- QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb
- LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN
- eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF
- zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW
- 20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM
- 1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh
- NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt
- iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr
- m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01
- bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt
- CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh
- HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ
- 6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb
- mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8
- PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu
- ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk
- i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX
- smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL
- 2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx
- /50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb
- /1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK
- /zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR
- /xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw
- wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP
- WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw
- CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ
- ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw
- AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL
- AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb
- AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA
- AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/
- //8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C
- SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA
- AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA
- BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA
- AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA
- AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB
- HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA
- AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA
- AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs
- SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA
- AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke
- AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA
- AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo
- HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA
- AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK
- SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M
- SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx
- SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
- AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
- AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
- AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
- AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
- AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
- AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
- AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4
- TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq
- d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg
- lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR
- xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB
- +ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE
- UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU
- LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA
- AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/
- //8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/
- 9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/
- 0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/
- l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/
- cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/
- UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy
- Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ
- Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs
- APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA
- AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA
- AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA
- Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA
- JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA
- AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS
- REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA
- ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W
- ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw
- CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+
- FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB
- AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1
- VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk
- iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV
- uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE
- 7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA
- kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG
- cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi
- UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm
- LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA
- AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/
- //8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/
- 5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/
- trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/
- kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/
- cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0
- Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm
- Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+
- Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR
- LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn
- OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD
- AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA
- AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka
- AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO
- OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo
- DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA
- AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy
- XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg
- mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL
- 2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA
- z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA
- sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI
- kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw
- cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA
- UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv
- JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA
- AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/
- //8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/
- 1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/
- scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/
- kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2
- cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0
- Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY
- Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV
- AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA
- AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF
- JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
- Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I
- k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU
- HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw
- zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK
- 0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH
- 70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+
- ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j
- 12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM
- sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+
- 2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ
- abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ
- EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I
- U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE
- HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry
- j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF
- IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+
- Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh
- u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l
- 1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq
- 4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl
- /P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP
- MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4
- Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg==
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L
- QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv
- 5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm
- A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf
- f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/
- zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX
- CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2
- mXizAAAAAElFTkSuQmCC
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL
- AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU
- wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ
- UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw
- vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p
- ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC
- 4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son
- bfJW/NwRDyIAAAAASUVORK5CYII=
-
-
-
-
- iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
- YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
- QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
- 9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
- uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
- VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
- t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
- IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA
+ CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA
+ ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP
+ 6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By
+ cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB
+ ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC
+ QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF
+ gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES
+ lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97
+ 7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz
+ fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64
+ hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2
+ bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G
+ m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE
+ k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6
+ zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E
+ IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j
+ vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF
+ Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6
+ zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t
+ xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb
+ REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK
+ 0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt
+ mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd
+ I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm
+ Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0
+ uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH
+ 6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz
+ l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q
+ iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr
+ hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM
+ BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R
+ q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g
+ PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp
+ NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP
+ 4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1
+ VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF
+ IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS
+ Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW
+ hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5
+ FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/
+ SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU
+ wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A
+ MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY
+ dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D
+ lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y
+ ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct
+ KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p
+ 5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0
+ JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n
+ AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y
+ dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx
+ KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO
+ IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo
+ NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn
+ RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY
+ cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv
+ TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH
+ 5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb
+ jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq
+ WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO
+ Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB
+ ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg
+ wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV
+ /xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ
+ 2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25
+ rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM
+ ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7
+ r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT
+ iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o
+ zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw
+ +u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw
+ CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC
+ 27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N
+ 7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1
+ zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl
+ Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3
+ kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO
+ PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl
+ AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt
+ xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC
+ NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E
+ zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq
+ ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg
+ d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ
+ 6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa
+ w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa
+ /8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t
+ ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK
+ QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb
+ LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN
+ eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF
+ zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW
+ 20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM
+ 1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh
+ NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt
+ iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr
+ m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01
+ bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt
+ CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh
+ HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ
+ 6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb
+ mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8
+ PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu
+ ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk
+ i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX
+ smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL
+ 2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx
+ /50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb
+ /1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK
+ /zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR
+ /xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw
+ wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP
+ WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw
+ CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ
+ ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw
+ AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL
+ AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb
+ AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA
+ AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/
+ //8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C
+ SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA
+ AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA
+ BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA
+ AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB
+ HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA
+ AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA
+ AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs
+ SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA
+ AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke
+ AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA
+ AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo
+ HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA
+ AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK
+ SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M
+ SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx
+ SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
+ AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
+ AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
+ AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
+ AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
+ AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
+ AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
+ AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4
+ TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq
+ d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg
+ lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR
+ xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB
+ +ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE
+ UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU
+ LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA
+ AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/
+ //8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/
+ 9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/
+ 0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/
+ l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/
+ cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/
+ UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy
+ Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ
+ Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs
+ APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA
+ AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA
+ AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA
+ Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA
+ JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA
+ AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS
+ REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA
+ ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W
+ ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw
+ CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+
+ FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB
+ AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1
+ VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk
+ iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV
+ uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE
+ 7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA
+ kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG
+ cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi
+ UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm
+ LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA
+ AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/
+ //8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/
+ 5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/
+ trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/
+ kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/
+ cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0
+ Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm
+ Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+
+ Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR
+ LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn
+ OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD
+ AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA
+ AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka
+ AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO
+ OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo
+ DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA
+ AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy
+ XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg
+ mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL
+ 2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA
+ z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA
+ sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI
+ kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw
+ cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA
+ UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv
+ JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA
+ AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/
+ //8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/
+ 1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/
+ scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/
+ kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2
+ cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0
+ Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY
+ Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV
+ AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA
+ AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF
+ JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
+ Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I
+ k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU
+ HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw
+ zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK
+ 0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH
+ 70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+
+ ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j
+ 12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM
+ sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+
+ 2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ
+ abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ
+ EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I
+ U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE
+ HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry
+ j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF
+ IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+
+ Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh
+ u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l
+ 1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq
+ 4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl
+ /P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP
+ MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4
+ Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg==
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L
+ QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv
+ 5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm
+ A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf
+ f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/
+ zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX
+ CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2
+ mXizAAAAAElFTkSuQmCC
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL
+ AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU
+ wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ
+ UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw
+ vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p
+ ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC
+ 4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son
+ bfJW/NwRDyIAAAAASUVORK5CYII=
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
+ QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
+ 9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
+ uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
+ VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
+ t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
+ IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
+
+
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/IEHelper.cs b/GreenshotPlugin/Core/IEHelper.cs
new file mode 100644
index 000000000..92ffa2816
--- /dev/null
+++ b/GreenshotPlugin/Core/IEHelper.cs
@@ -0,0 +1,190 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using log4net;
+using Microsoft.Win32;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of IEHelper.
+ ///
+ public static class IEHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(IEHelper));
+ // Internet explorer Registry key
+ private const string IeKey = @"Software\Microsoft\Internet Explorer";
+
+ ///
+ /// Get the current browser version
+ ///
+ /// int with browser version
+ public static int IEVersion
+ {
+ get
+ {
+ var maxVer = 7;
+ using (var ieKey = Registry.LocalMachine.OpenSubKey(IeKey, false))
+ {
+ foreach (var value in new[] { "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" })
+ {
+ var objVal = ieKey.GetValue(value, "0");
+ var strVal = Convert.ToString(objVal);
+
+ var iPos = strVal.IndexOf('.');
+ if (iPos > 0)
+ {
+ strVal = strVal.Substring(0, iPos);
+ }
+
+ int res;
+ if (int.TryParse(strVal, out res))
+ {
+ maxVer = Math.Max(maxVer, res);
+ }
+ }
+ }
+
+ return maxVer;
+ }
+ }
+
+ ///
+ /// Get the highest possible version for the embedded browser
+ ///
+ /// true to ignore the doctype when loading a page
+ /// IE Feature
+ public static int GetEmbVersion(bool ignoreDoctype = true)
+ {
+ var ieVersion = IEVersion;
+
+ if (ieVersion > 9)
+ {
+ return ieVersion * 1000 + (ignoreDoctype ? 1 : 0);
+ }
+
+ if (ieVersion > 7)
+ {
+ return ieVersion * 1111;
+ }
+
+ return 7000;
+ }
+
+ ///
+ /// Fix browser version to the highest possible
+ ///
+ /// true to ignore the doctype when loading a page
+ public static void FixBrowserVersion(bool ignoreDoctype = true)
+ {
+ var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
+ FixBrowserVersion(applicationName, ignoreDoctype);
+ }
+
+ ///
+ /// Fix the browser version for the specified application
+ ///
+ /// Name of the process
+ /// true to ignore the doctype when loading a page
+ public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true)
+ {
+ FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype));
+ }
+
+ ///
+ /// Fix the browser version for the specified application
+ ///
+ /// Name of the process
+ ///
+ /// Version, see
+ /// Browser Emulation
+ ///
+ public static void FixBrowserVersion(string applicationName, int ieVersion)
+ {
+ ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".exe", ieVersion);
+#if DEBUG
+ ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".vshost.exe", ieVersion);
+#endif
+ }
+
+ ///
+ /// Make the change to the registry
+ ///
+ /// HKEY_CURRENT_USER or something
+ /// Name of the executable
+ /// Version to use
+ private static void ModifyRegistry(string root, string applicationName, int ieFeatureVersion)
+ {
+ var regKey = root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION";
+ try
+ {
+ Registry.SetValue(regKey, applicationName, ieFeatureVersion);
+ }
+ catch (Exception ex)
+ {
+ // some config will hit access rights exceptions
+ // this is why we try with both LOCAL_MACHINE and CURRENT_USER
+ Log.Error(ex);
+ Log.ErrorFormat("couldn't modify the registry key {0}", regKey);
+ }
+ }
+
+ ///
+ /// Find the DirectUI window for MSAA (Accessible)
+ ///
+ /// The browser WindowDetails
+ /// WindowDetails for the DirectUI window
+ public static WindowDetails GetDirectUI(WindowDetails browserWindowDetails) {
+ if (browserWindowDetails == null) {
+ return null;
+ }
+ WindowDetails tmpWd = browserWindowDetails;
+ // Since IE 9 the TabBandClass is less deep!
+ if (IEVersion < 9) {
+ tmpWd = tmpWd.GetChild("CommandBarClass");
+ tmpWd = tmpWd?.GetChild("ReBarWindow32");
+ }
+ tmpWd = tmpWd?.GetChild("TabBandClass");
+ tmpWd = tmpWd?.GetChild("DirectUIHWND");
+ return tmpWd;
+ }
+
+ ///
+ /// Return an IEnumerable with the currently opened IE urls
+ ///
+ ///
+ public static IEnumerable GetIEUrls() {
+ // Find the IE window
+ foreach (WindowDetails ieWindow in WindowDetails.GetAllWindows("IEFrame")) {
+ WindowDetails directUIWD = GetDirectUI(ieWindow);
+ if (directUIWD != null) {
+ Accessible ieAccessible = new Accessible(directUIWD.Handle);
+ foreach(string url in ieAccessible.IETabUrls)
+ {
+ yield return url;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/IImage.cs b/GreenshotPlugin/Core/IImage.cs
new file mode 100644
index 000000000..ee5c9f367
--- /dev/null
+++ b/GreenshotPlugin/Core/IImage.cs
@@ -0,0 +1,68 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// The image interface, this abstracts an image
+ ///
+ public interface IImage : IDisposable
+ {
+ ///
+ /// Height of the image, can be set to change
+ ///
+ int Height { get; set; }
+
+ ///
+ /// Width of the image, can be set to change.
+ ///
+ int Width { get; set; }
+
+ ///
+ /// Size of the image
+ ///
+ Size Size { get; }
+
+ ///
+ /// Pixelformat of the underlying image
+ ///
+ PixelFormat PixelFormat { get; }
+
+ ///
+ /// Vertical resolution of the underlying image
+ ///
+ float VerticalResolution { get; }
+
+ ///
+ /// Horizontal resolution of the underlying image
+ ///
+ float HorizontalResolution { get; }
+
+ ///
+ /// Unterlying image, or an on demand rendered version with different attributes as the original
+ ///
+ Image Image { get; }
+ }
+}
diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs
new file mode 100644
index 000000000..bac22c31b
--- /dev/null
+++ b/GreenshotPlugin/Core/ImageHelper.cs
@@ -0,0 +1,1755 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using Greenshot.IniFile;
+using GreenshotPlugin.UnmanagedHelpers;
+using Greenshot.Plugin;
+using GreenshotPlugin.Effects;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+ internal enum ExifOrientations : byte {
+ Unknown = 0,
+ TopLeft = 1,
+ TopRight = 2,
+ BottomRight = 3,
+ BottomLeft = 4,
+ LeftTop = 5,
+ RightTop = 6,
+ RightBottom = 7,
+ LeftBottom = 8,
+ }
+
+ ///
+ /// Description of ImageHelper.
+ ///
+ public static class ImageHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ImageHelper));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private const int ExifOrientationId = 0x0112;
+
+ ///
+ /// This is a factory method to create a surface, set from the Greenshot main project
+ ///
+ public static Func SurfaceFactory { get; set; }
+
+ static ImageHelper()
+ {
+ StreamConverters["greenshot"] = (stream, s) =>
+ {
+ var surface = SurfaceFactory();
+ return surface.GetImageForExport();
+ };
+
+ Func defaultConverter = (stream, s) =>
+ {
+ stream.Position = 0;
+ using (var tmpImage = Image.FromStream(stream, true, true))
+ {
+ Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
+ return Clone(tmpImage, PixelFormat.Format32bppArgb);
+ }
+ };
+
+ // Fallback
+ StreamConverters[""] = defaultConverter;
+ StreamConverters["gif"] = defaultConverter;
+ StreamConverters["bmp"] = defaultConverter;
+ StreamConverters["jpg"] = defaultConverter;
+ StreamConverters["jpeg"] = defaultConverter;
+ StreamConverters["png"] = defaultConverter;
+ StreamConverters["wmf"] = defaultConverter;
+
+ StreamConverters["ico"] = (stream, extension) =>
+ {
+ // Icon logic, try to get the Vista icon, else the biggest possible
+ try
+ {
+ using (Image tmpImage = ExtractVistaIcon(stream))
+ {
+ if (tmpImage != null)
+ {
+ return Clone(tmpImage, PixelFormat.Format32bppArgb);
+ }
+ }
+ }
+ catch (Exception vistaIconException)
+ {
+ Log.Warn("Can't read icon", vistaIconException);
+ }
+ try
+ {
+ // No vista icon, try normal icon
+ stream.Position = 0;
+ // We create a copy of the bitmap, so everything else can be disposed
+ using (Icon tmpIcon = new Icon(stream, new Size(1024, 1024)))
+ {
+ using (Image tmpImage = tmpIcon.ToBitmap())
+ {
+ return Clone(tmpImage, PixelFormat.Format32bppArgb);
+ }
+ }
+ }
+ catch (Exception iconException)
+ {
+ Log.Warn("Can't read icon", iconException);
+ }
+
+ stream.Position = 0;
+ return defaultConverter(stream, extension);
+ };
+ }
+
+ public static IDictionary> StreamConverters { get; } = new Dictionary>();
+
+ ///
+ /// Make sure the image is orientated correctly
+ ///
+ ///
+ public static void Orientate(Image image)
+ {
+ if (!CoreConfig.ProcessEXIFOrientation)
+ {
+ return;
+ }
+ try
+ {
+ // Get the index of the orientation property.
+ int orientationIndex = Array.IndexOf(image.PropertyIdList, ExifOrientationId);
+ // If there is no such property, return Unknown.
+ if (orientationIndex < 0)
+ {
+ return;
+ }
+ PropertyItem item = image.GetPropertyItem(ExifOrientationId);
+
+ ExifOrientations orientation = (ExifOrientations)item.Value[0];
+ // Orient the image.
+ switch (orientation)
+ {
+ case ExifOrientations.Unknown:
+ case ExifOrientations.TopLeft:
+ break;
+ case ExifOrientations.TopRight:
+ image.RotateFlip(RotateFlipType.RotateNoneFlipX);
+ break;
+ case ExifOrientations.BottomRight:
+ image.RotateFlip(RotateFlipType.Rotate180FlipNone);
+ break;
+ case ExifOrientations.BottomLeft:
+ image.RotateFlip(RotateFlipType.RotateNoneFlipY);
+ break;
+ case ExifOrientations.LeftTop:
+ image.RotateFlip(RotateFlipType.Rotate90FlipX);
+ break;
+ case ExifOrientations.RightTop:
+ image.RotateFlip(RotateFlipType.Rotate90FlipNone);
+ break;
+ case ExifOrientations.RightBottom:
+ image.RotateFlip(RotateFlipType.Rotate90FlipY);
+ break;
+ case ExifOrientations.LeftBottom:
+ image.RotateFlip(RotateFlipType.Rotate270FlipNone);
+ break;
+ }
+ // Set the orientation to be normal, as we rotated the image.
+ item.Value[0] = (byte)ExifOrientations.TopLeft;
+ image.SetPropertyItem(item);
+ }
+ catch (Exception orientEx)
+ {
+ Log.Warn("Problem orientating the image: ", orientEx);
+ }
+ }
+
+ ///
+ /// Create a Thumbnail
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Image CreateThumbnail(Image image, int thumbWidth, int thumbHeight, int maxWidth = -1, int maxHeight = -1)
+ {
+ int srcWidth = image.Width;
+ int srcHeight = image.Height;
+ if (thumbHeight < 0)
+ {
+ thumbHeight = (int)(thumbWidth * (srcHeight / (float)srcWidth));
+ }
+ if (thumbWidth < 0)
+ {
+ thumbWidth = (int)(thumbHeight * (srcWidth / (float)srcHeight));
+ }
+ if (maxWidth > 0 && thumbWidth > maxWidth)
+ {
+ thumbWidth = Math.Min(thumbWidth, maxWidth);
+ thumbHeight = (int)(thumbWidth * (srcHeight / (float)srcWidth));
+ }
+ if (maxHeight > 0 && thumbHeight > maxHeight)
+ {
+ thumbHeight = Math.Min(thumbHeight, maxHeight);
+ thumbWidth = (int)(thumbHeight * (srcWidth / (float)srcHeight));
+ }
+
+ Bitmap bmp = new Bitmap(thumbWidth, thumbHeight);
+ using (Graphics graphics = Graphics.FromImage(bmp))
+ {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ Rectangle rectDestination = new Rectangle(0, 0, thumbWidth, thumbHeight);
+ graphics.DrawImage(image, rectDestination, 0, 0, srcWidth, srcHeight, GraphicsUnit.Pixel);
+ }
+ return bmp;
+ }
+
+ ///
+ /// Crops the image to the specified rectangle
+ ///
+ /// Image to crop
+ /// Rectangle with bitmap coordinates, will be "intersected" to the bitmap
+ public static bool Crop(ref Image image, ref Rectangle cropRectangle)
+ {
+ if (image is Bitmap && (image.Width * image.Height > 0))
+ {
+ cropRectangle.Intersect(new Rectangle(0, 0, image.Width, image.Height));
+ if (cropRectangle.Width != 0 || cropRectangle.Height != 0)
+ {
+ Image returnImage = CloneArea(image, cropRectangle, PixelFormat.DontCare);
+ image.Dispose();
+ image = returnImage;
+ return true;
+ }
+ }
+ Log.Warn("Can't crop a null/zero size image!");
+ return false;
+ }
+
+ ///
+ /// Private helper method for the FindAutoCropRectangle
+ ///
+ ///
+ ///
+ ///
+ /// Rectangle
+ private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference)
+ {
+ Rectangle cropRectangle = Rectangle.Empty;
+ Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y);
+ Point min = new Point(int.MaxValue, int.MaxValue);
+ Point max = new Point(int.MinValue, int.MinValue);
+
+ if (cropDifference > 0)
+ {
+ for (int y = 0; y < fastBitmap.Height; y++)
+ {
+ for (int x = 0; x < fastBitmap.Width; x++)
+ {
+ Color currentColor = fastBitmap.GetColorAt(x, y);
+ int diffR = Math.Abs(currentColor.R - referenceColor.R);
+ int diffG = Math.Abs(currentColor.G - referenceColor.G);
+ int diffB = Math.Abs(currentColor.B - referenceColor.B);
+ if ((diffR + diffG + diffB) / 3 <= cropDifference)
+ {
+ continue;
+ }
+ if (x < min.X) min.X = x;
+ if (y < min.Y) min.Y = y;
+ if (x > max.X) max.X = x;
+ if (y > max.Y) max.Y = y;
+ }
+ }
+ }
+ else
+ {
+ for (int y = 0; y < fastBitmap.Height; y++)
+ {
+ for (int x = 0; x < fastBitmap.Width; x++)
+ {
+ Color currentColor = fastBitmap.GetColorAt(x, y);
+ if (!referenceColor.Equals(currentColor))
+ {
+ continue;
+ }
+ if (x < min.X) min.X = x;
+ if (y < min.Y) min.Y = y;
+ if (x > max.X) max.X = x;
+ if (y > max.Y) max.Y = y;
+ }
+ }
+ }
+
+ if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1))))
+ {
+ if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue))
+ {
+ cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1);
+ }
+ }
+ return cropRectangle;
+ }
+
+ ///
+ /// Get a rectangle for the image which crops the image of all colors equal to that on 0,0
+ ///
+ ///
+ ///
+ /// Rectangle
+ public static Rectangle FindAutoCropRectangle(Image image, int cropDifference)
+ {
+ Rectangle cropRectangle = Rectangle.Empty;
+ var checkPoints = new List
+ {
+ new Point(0, 0),
+ new Point(0, image.Height - 1),
+ new Point(image.Width - 1, 0),
+ new Point(image.Width - 1, image.Height - 1)
+ };
+ // Top Left
+ // Bottom Left
+ // Top Right
+ // Bottom Right
+ using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap)image))
+ {
+ // find biggest area
+ foreach (Point checkPoint in checkPoints)
+ {
+ var currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference);
+ if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height)
+ {
+ cropRectangle = currentRectangle;
+ }
+ }
+ }
+ return cropRectangle;
+ }
+
+ ///
+ /// Load an image from file
+ ///
+ ///
+ ///
+ public static Image LoadImage(string filename)
+ {
+ if (string.IsNullOrEmpty(filename))
+ {
+ return null;
+ }
+ if (!File.Exists(filename))
+ {
+ return null;
+ }
+ Image fileImage;
+ Log.InfoFormat("Loading image from file {0}", filename);
+ // Fixed lock problem Bug #3431881
+ using (Stream imageFileStream = File.OpenRead(filename))
+ {
+ fileImage = FromStream(imageFileStream, Path.GetExtension(filename));
+ }
+ if (fileImage != null)
+ {
+ Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat, fileImage.HorizontalResolution, fileImage.VerticalResolution);
+ }
+ return fileImage;
+ }
+
+ ///
+ /// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx
+ /// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx
+ ///
+ /// Stream with the icon information
+ /// Bitmap with the Vista Icon (256x256)
+ private static Bitmap ExtractVistaIcon(Stream iconStream)
+ {
+ const int sizeIconDir = 6;
+ const int sizeIconDirEntry = 16;
+ Bitmap bmpPngExtracted = null;
+ try
+ {
+ byte[] srcBuf = new byte[iconStream.Length];
+ iconStream.Read(srcBuf, 0, (int)iconStream.Length);
+ int iCount = BitConverter.ToInt16(srcBuf, 4);
+ for (int iIndex = 0; iIndex < iCount; iIndex++)
+ {
+ int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex];
+ int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1];
+ if (iWidth == 0 && iHeight == 0)
+ {
+ int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
+ int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
+ using (MemoryStream destStream = new MemoryStream())
+ {
+ destStream.Write(srcBuf, iImageOffset, iImageSize);
+ destStream.Seek(0, SeekOrigin.Begin);
+ bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
+ }
+ break;
+ }
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ return bmpPngExtracted;
+ }
+
+ ///
+ /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx
+ ///
+ /// The file (EXE or DLL) to get the icon from
+ /// Index of the icon
+ /// true if the large icon is wanted
+ /// Icon
+ public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge)
+ {
+ IntPtr large;
+ IntPtr small;
+ Shell32.ExtractIconEx(location, index, out large, out small, 1);
+ Icon returnIcon = null;
+ bool isLarge = false;
+ bool isSmall = false;
+ try
+ {
+ if (takeLarge && !IntPtr.Zero.Equals(large))
+ {
+ returnIcon = Icon.FromHandle(large);
+ isLarge = true;
+ }
+ else if (!IntPtr.Zero.Equals(small))
+ {
+ returnIcon = Icon.FromHandle(small);
+ isSmall = true;
+ }
+ else if (!IntPtr.Zero.Equals(large))
+ {
+ returnIcon = Icon.FromHandle(large);
+ isLarge = true;
+ }
+ }
+ finally
+ {
+ if (isLarge && !IntPtr.Zero.Equals(small))
+ {
+ User32.DestroyIcon(small);
+ }
+ if (isSmall && !IntPtr.Zero.Equals(large))
+ {
+ User32.DestroyIcon(large);
+ }
+ }
+ return returnIcon;
+ }
+
+ ///
+ /// Get the number of icon in the file
+ ///
+ /// Location of the EXE or DLL
+ ///
+ public static int CountAssociatedIcons(string location)
+ {
+ IntPtr large;
+ IntPtr small;
+ return Shell32.ExtractIconEx(location, -1, out large, out small, 0);
+ }
+
+ ///
+ /// Apply the effect to the bitmap
+ ///
+ /// Bitmap
+ /// IEffect
+ ///
+ /// Bitmap
+ public static Image ApplyEffect(Image sourceImage, IEffect effect, Matrix matrix)
+ {
+ var effects = new List { effect };
+ return ApplyEffects(sourceImage, effects, matrix);
+ }
+
+ ///
+ /// Apply the effects in the supplied order to the bitmap
+ ///
+ /// Bitmap
+ /// List of IEffect
+ ///
+ /// Bitmap
+ public static Image ApplyEffects(Image sourceImage, IEnumerable effects, Matrix matrix)
+ {
+ var currentImage = sourceImage;
+ bool disposeImage = false;
+ foreach (var effect in effects)
+ {
+ var tmpImage = effect.Apply(currentImage, matrix);
+ if (tmpImage != null)
+ {
+ if (disposeImage)
+ {
+ currentImage.Dispose();
+ }
+ currentImage = tmpImage;
+ // Make sure the "new" image is disposed
+ disposeImage = true;
+ }
+ }
+ return currentImage;
+ }
+
+ ///
+ /// Helper method for the tornedge
+ ///
+ /// Path to draw to
+ /// Points for the lines to draw
+ private static void DrawLines(GraphicsPath path, List points)
+ {
+ path.AddLine(points[0], points[1]);
+ for (int i = 0; i < points.Count - 1; i++)
+ {
+ path.AddLine(points[i], points[i + 1]);
+ }
+ }
+
+ ///
+ /// Make the picture look like it's torn
+ ///
+ /// Bitmap to make torn edge off
+ /// How large (height) is each tooth
+ /// How wide is a horizontal tooth
+ /// How wide is a vertical tooth
+ /// bool[] with information on if the edge needs torn or not. Order is clockwise: 0=top,1=right,2=bottom,3=left
+ /// Changed bitmap
+ public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges)
+ {
+ Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ using (var path = new GraphicsPath())
+ {
+ Random random = new Random();
+ int horizontalRegions = (int)Math.Round((float)sourceImage.Width / horizontalToothRange);
+ int verticalRegions = (int)Math.Round((float)sourceImage.Height / verticalToothRange);
+
+ Point topLeft = new Point(0, 0);
+ Point topRight = new Point(sourceImage.Width, 0);
+ Point bottomLeft = new Point(0, sourceImage.Height);
+ Point bottomRight = new Point(sourceImage.Width, sourceImage.Height);
+
+ List points = new List();
+
+ if (edges[0])
+ {
+ // calculate starting point only if the left edge is torn
+ if (!edges[3])
+ {
+ points.Add(topLeft);
+ }
+ else
+ {
+ points.Add(new Point(random.Next(1, toothHeight), random.Next(1, toothHeight)));
+ }
+ for (int i = 1; i < horizontalRegions - 1; i++)
+ {
+ points.Add(new Point(i * horizontalToothRange, random.Next(1, toothHeight)));
+ }
+ points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), random.Next(1, toothHeight)));
+ }
+ else
+ {
+ // set start & endpoint to be the default "whole-line"
+ points.Add(topLeft);
+ points.Add(topRight);
+ }
+ // Right
+ if (edges[1])
+ {
+ for (int i = 1; i < verticalRegions - 1; i++)
+ {
+ points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), i * verticalToothRange));
+ }
+ points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight)));
+ }
+ else
+ {
+ // correct previous ending point
+ points[points.Count - 1] = topRight;
+ // set endpoint to be the default "whole-line"
+ points.Add(bottomRight);
+ }
+ // Bottom
+ if (edges[2])
+ {
+ for (int i = 1; i < horizontalRegions - 1; i++)
+ {
+ points.Add(new Point(sourceImage.Width - i * horizontalToothRange, sourceImage.Height - random.Next(1, toothHeight)));
+ }
+ points.Add(new Point(random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight)));
+ }
+ else
+ {
+ // correct previous ending point
+ points[points.Count - 1] = bottomRight;
+ // set endpoint to be the default "whole-line"
+ points.Add(bottomLeft);
+ }
+ // Left
+ if (edges[3])
+ {
+ // One fewer as the end point is the starting point
+ for (int i = 1; i < verticalRegions - 1; i++)
+ {
+ points.Add(new Point(random.Next(1, toothHeight), points[points.Count - 1].Y - verticalToothRange));
+ }
+ }
+ else
+ {
+ // correct previous ending point
+ points[points.Count - 1] = bottomLeft;
+ // set endpoint to be the default "whole-line"
+ points.Add(topLeft);
+ }
+ // End point always is the starting point
+ points[points.Count - 1] = points[0];
+
+ DrawLines(path, points);
+
+ path.CloseFigure();
+
+ // Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing
+ using (Graphics graphics = Graphics.FromImage(returnImage))
+ {
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ using (Brush brush = new TextureBrush(sourceImage))
+ {
+ // Important note: If the target wouldn't be at 0,0 we need to translate-transform!!
+ graphics.FillPath(brush, path);
+ }
+ }
+ }
+ return returnImage;
+ }
+
+ ///
+ /// Apply BoxBlur to the destinationBitmap
+ ///
+ /// Bitmap to blur
+ /// Must be ODD!
+ public static void ApplyBoxBlur(Bitmap destinationBitmap, int range)
+ {
+ // We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V)
+ using (IFastBitmap fastBitmap = FastBitmap.Create(destinationBitmap))
+ {
+ ApplyBoxBlur(fastBitmap, range);
+ }
+ }
+
+ ///
+ /// Apply BoxBlur to the fastBitmap
+ ///
+ /// IFastBitmap to blur
+ /// Must be ODD!
+ public static void ApplyBoxBlur(IFastBitmap fastBitmap, int range)
+ {
+ // Range must be odd!
+ if ((range & 1) == 0)
+ {
+ range++;
+ }
+ if (range <= 1)
+ {
+ return;
+ }
+ // Box blurs are frequently used to approximate a Gaussian blur.
+ // By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel.
+ // This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur.
+ // (Might also be a mistake in our blur, but for now it looks great)
+ if (fastBitmap.HasAlphaChannel)
+ {
+ BoxBlurHorizontalAlpha(fastBitmap, range);
+ BoxBlurVerticalAlpha(fastBitmap, range);
+ BoxBlurHorizontalAlpha(fastBitmap, range);
+ BoxBlurVerticalAlpha(fastBitmap, range);
+ }
+ else
+ {
+ BoxBlurHorizontal(fastBitmap, range);
+ BoxBlurVertical(fastBitmap, range);
+ BoxBlurHorizontal(fastBitmap, range);
+ BoxBlurVertical(fastBitmap, range);
+ }
+ }
+
+ ///
+ /// BoxBlurHorizontal is a private helper method for the BoxBlur
+ ///
+ /// Target BitmapBuffer
+ /// Range must be odd!
+ private static void BoxBlurHorizontal(IFastBitmap targetFastBitmap, int range)
+ {
+ if (targetFastBitmap.HasAlphaChannel)
+ {
+ throw new NotSupportedException("BoxBlurHorizontal should NOT be called for bitmaps with alpha channel");
+ }
+ int halfRange = range / 2;
+ Color[] newColors = new Color[targetFastBitmap.Width];
+ byte[] tmpColor = new byte[3];
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++)
+ {
+ int hits = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++)
+ {
+ int oldPixel = x - halfRange - 1;
+ if (oldPixel >= targetFastBitmap.Left)
+ {
+ targetFastBitmap.GetColorAt(oldPixel, y, tmpColor);
+ r -= tmpColor[FastBitmap.ColorIndexR];
+ g -= tmpColor[FastBitmap.ColorIndexG];
+ b -= tmpColor[FastBitmap.ColorIndexB];
+ hits--;
+ }
+
+ int newPixel = x + halfRange;
+ if (newPixel < targetFastBitmap.Right)
+ {
+ targetFastBitmap.GetColorAt(newPixel, y, tmpColor);
+ r += tmpColor[FastBitmap.ColorIndexR];
+ g += tmpColor[FastBitmap.ColorIndexG];
+ b += tmpColor[FastBitmap.ColorIndexB];
+ hits++;
+ }
+
+ if (x >= targetFastBitmap.Left)
+ {
+ newColors[x - targetFastBitmap.Left] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ }
+ }
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++)
+ {
+ targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]);
+ }
+ }
+ }
+ ///
+ /// BoxBlurHorizontal is a private helper method for the BoxBlur, only for IFastBitmaps with alpha channel
+ ///
+ /// Target BitmapBuffer
+ /// Range must be odd!
+ private static void BoxBlurHorizontalAlpha(IFastBitmap targetFastBitmap, int range)
+ {
+ if (!targetFastBitmap.HasAlphaChannel)
+ {
+ throw new NotSupportedException("BoxBlurHorizontalAlpha should be called for bitmaps with alpha channel");
+ }
+ int halfRange = range / 2;
+ Color[] newColors = new Color[targetFastBitmap.Width];
+ byte[] tmpColor = new byte[4];
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++)
+ {
+ int hits = 0;
+ int a = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++)
+ {
+ int oldPixel = x - halfRange - 1;
+ if (oldPixel >= targetFastBitmap.Left)
+ {
+ targetFastBitmap.GetColorAt(oldPixel, y, tmpColor);
+ a -= tmpColor[FastBitmap.ColorIndexA];
+ r -= tmpColor[FastBitmap.ColorIndexR];
+ g -= tmpColor[FastBitmap.ColorIndexG];
+ b -= tmpColor[FastBitmap.ColorIndexB];
+ hits--;
+ }
+
+ int newPixel = x + halfRange;
+ if (newPixel < targetFastBitmap.Right)
+ {
+ targetFastBitmap.GetColorAt(newPixel, y, tmpColor);
+ a += tmpColor[FastBitmap.ColorIndexA];
+ r += tmpColor[FastBitmap.ColorIndexR];
+ g += tmpColor[FastBitmap.ColorIndexG];
+ b += tmpColor[FastBitmap.ColorIndexB];
+ hits++;
+ }
+
+ if (x >= targetFastBitmap.Left)
+ {
+ newColors[x - targetFastBitmap.Left] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ }
+ }
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++)
+ {
+ targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]);
+ }
+ }
+ }
+
+ ///
+ /// BoxBlurVertical is a private helper method for the BoxBlur
+ ///
+ /// BitmapBuffer which previously was created with BoxBlurHorizontal
+ /// Range must be odd!
+ private static void BoxBlurVertical(IFastBitmap targetFastBitmap, int range)
+ {
+ if (targetFastBitmap.HasAlphaChannel)
+ {
+ throw new NotSupportedException("BoxBlurVertical should NOT be called for bitmaps with alpha channel");
+ }
+ int halfRange = range / 2;
+ Color[] newColors = new Color[targetFastBitmap.Height];
+ byte[] tmpColor = new byte[4];
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++)
+ {
+ int hits = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++)
+ {
+ int oldPixel = y - halfRange - 1;
+ if (oldPixel >= targetFastBitmap.Top)
+ {
+ targetFastBitmap.GetColorAt(x, oldPixel, tmpColor);
+ r -= tmpColor[FastBitmap.ColorIndexR];
+ g -= tmpColor[FastBitmap.ColorIndexG];
+ b -= tmpColor[FastBitmap.ColorIndexB];
+ hits--;
+ }
+
+ int newPixel = y + halfRange;
+ if (newPixel < targetFastBitmap.Bottom)
+ {
+ targetFastBitmap.GetColorAt(x, newPixel, tmpColor);
+ r += tmpColor[FastBitmap.ColorIndexR];
+ g += tmpColor[FastBitmap.ColorIndexG];
+ b += tmpColor[FastBitmap.ColorIndexB];
+ hits++;
+ }
+
+ if (y >= targetFastBitmap.Top)
+ {
+ newColors[y - targetFastBitmap.Top] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ }
+ }
+
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++)
+ {
+ targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]);
+ }
+ }
+ }
+
+ ///
+ /// BoxBlurVertical is a private helper method for the BoxBlur
+ ///
+ /// BitmapBuffer which previously was created with BoxBlurHorizontal
+ /// Range must be odd!
+ private static void BoxBlurVerticalAlpha(IFastBitmap targetFastBitmap, int range)
+ {
+ if (!targetFastBitmap.HasAlphaChannel)
+ {
+ throw new NotSupportedException("BoxBlurVerticalAlpha should be called for bitmaps with alpha channel");
+ }
+
+ int halfRange = range / 2;
+ Color[] newColors = new Color[targetFastBitmap.Height];
+ byte[] tmpColor = new byte[4];
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++)
+ {
+ int hits = 0;
+ int a = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++)
+ {
+ int oldPixel = y - halfRange - 1;
+ if (oldPixel >= targetFastBitmap.Top)
+ {
+ targetFastBitmap.GetColorAt(x, oldPixel, tmpColor);
+ a -= tmpColor[FastBitmap.ColorIndexA];
+ r -= tmpColor[FastBitmap.ColorIndexR];
+ g -= tmpColor[FastBitmap.ColorIndexG];
+ b -= tmpColor[FastBitmap.ColorIndexB];
+ hits--;
+ }
+
+ int newPixel = y + halfRange;
+ if (newPixel < targetFastBitmap.Bottom)
+ {
+ //int colorg = pixels[index + newPixelOffset];
+ targetFastBitmap.GetColorAt(x, newPixel, tmpColor);
+ a += tmpColor[FastBitmap.ColorIndexA];
+ r += tmpColor[FastBitmap.ColorIndexR];
+ g += tmpColor[FastBitmap.ColorIndexG];
+ b += tmpColor[FastBitmap.ColorIndexB];
+ hits++;
+ }
+
+ if (y >= targetFastBitmap.Top)
+ {
+ newColors[y - targetFastBitmap.Top] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ }
+ }
+
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++)
+ {
+ targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]);
+ }
+ }
+ }
+
+ ///
+ /// This method fixes the problem that we can't apply a filter outside the target bitmap,
+ /// therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap.
+ /// It will also account for the Invert flag.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Rectangle CreateIntersectRectangle(Size applySize, Rectangle rect, bool invert)
+ {
+ Rectangle myRect;
+ if (invert)
+ {
+ myRect = new Rectangle(0, 0, applySize.Width, applySize.Height);
+ }
+ else
+ {
+ Rectangle applyRect = new Rectangle(0, 0, applySize.Width, applySize.Height);
+ myRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+ myRect.Intersect(applyRect);
+ }
+ return myRect;
+ }
+
+ ///
+ /// Create a new bitmap where the sourceBitmap has a shadow
+ ///
+ /// Bitmap to make a shadow on
+ /// How dark is the shadow
+ /// Size of the shadow
+ /// What pixel format must the returning bitmap have
+ ///
+ /// The transform matrix which describes how the elements need to be transformed to stay at the same location
+ /// Bitmap with the shadow, is bigger than the sourceBitmap!!
+ public static Bitmap CreateShadow(Image sourceBitmap, float darkness, int shadowSize, Point shadowOffset, Matrix matrix, PixelFormat targetPixelformat)
+ {
+ Point offset = shadowOffset;
+ offset.X += shadowSize - 1;
+ offset.Y += shadowSize - 1;
+ matrix.Translate(offset.X, offset.Y, MatrixOrder.Append);
+ // Create a new "clean" image
+ Bitmap returnImage = CreateEmpty(sourceBitmap.Width + shadowSize * 2, sourceBitmap.Height + shadowSize * 2, targetPixelformat, Color.Empty, sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
+ // Make sure the shadow is odd, there is no reason for an even blur!
+ if ((shadowSize & 1) == 0)
+ {
+ shadowSize++;
+ }
+ bool useGdiBlur = GDIplus.IsBlurPossible(shadowSize);
+ // Create "mask" for the shadow
+ ColorMatrix maskMatrix = new ColorMatrix
+ {
+ Matrix00 = 0,
+ Matrix11 = 0,
+ Matrix22 = 0
+ };
+ if (useGdiBlur)
+ {
+ maskMatrix.Matrix33 = darkness + 0.1f;
+ }
+ else
+ {
+ maskMatrix.Matrix33 = darkness;
+ }
+ Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size);
+ ApplyColorMatrix((Bitmap)sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix);
+
+ // blur "shadow", apply to whole new image
+ if (useGdiBlur)
+ {
+ // Use GDI Blur
+ Rectangle newImageRectangle = new Rectangle(0, 0, returnImage.Width, returnImage.Height);
+ GDIplus.ApplyBlur(returnImage, newImageRectangle, shadowSize + 1, false);
+ }
+ else
+ {
+ // try normal software blur
+ //returnImage = CreateBlur(returnImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle);
+ ApplyBoxBlur(returnImage, shadowSize);
+ }
+
+ // Draw the original image over the shadow
+ using (Graphics graphics = Graphics.FromImage(returnImage))
+ {
+ // Make sure we draw with the best quality!
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ // draw original with a TextureBrush so we have nice antialiasing!
+ using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp))
+ {
+ // We need to do a translate-transform otherwise the image is wrapped
+ graphics.TranslateTransform(offset.X, offset.Y);
+ graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
+ }
+ }
+ return returnImage;
+ }
+
+ ///
+ /// Return negative of Bitmap
+ ///
+ /// Bitmap to create a negative off
+ /// Negative bitmap
+ public static Bitmap CreateNegative(Image sourceImage)
+ {
+ Bitmap clone = (Bitmap)Clone(sourceImage);
+ ColorMatrix invertMatrix = new ColorMatrix(new[] {
+ new float[] {-1, 0, 0, 0, 0},
+ new float[] {0, -1, 0, 0, 0},
+ new float[] {0, 0, -1, 0, 0},
+ new float[] {0, 0, 0, 1, 0},
+ new float[] {1, 1, 1, 1, 1}
+ });
+ ApplyColorMatrix(clone, invertMatrix);
+ return clone;
+ }
+ ///
+ /// Apply a color matrix to the image
+ ///
+ /// Image to apply matrix to
+ /// ColorMatrix to apply
+ public static void ApplyColorMatrix(Bitmap source, ColorMatrix colorMatrix)
+ {
+ ApplyColorMatrix(source, Rectangle.Empty, source, Rectangle.Empty, colorMatrix);
+ }
+
+ ///
+ /// Apply a color matrix by copying from the source to the destination
+ ///
+ /// Image to copy from
+ /// Rectangle to copy from
+ /// Rectangle to copy to
+ /// Image to copy to
+ /// ColorMatrix to apply
+ public static void ApplyColorMatrix(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ColorMatrix colorMatrix)
+ {
+ using (ImageAttributes imageAttributes = new ImageAttributes())
+ {
+ imageAttributes.ClearColorMatrix();
+ imageAttributes.SetColorMatrix(colorMatrix);
+ ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes);
+ }
+ }
+
+ ///
+ /// Apply image attributes to the image
+ ///
+ /// Image to apply matrix to
+ /// ImageAttributes to apply
+ public static void ApplyColorMatrix(Bitmap source, ImageAttributes imageAttributes)
+ {
+ ApplyImageAttributes(source, Rectangle.Empty, source, Rectangle.Empty, imageAttributes);
+ }
+
+ ///
+ /// Apply a color matrix by copying from the source to the destination
+ ///
+ /// Image to copy from
+ /// Rectangle to copy from
+ /// Rectangle to copy to
+ /// Image to copy to
+ /// ImageAttributes to apply
+ public static void ApplyImageAttributes(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ImageAttributes imageAttributes)
+ {
+ if (sourceRect == Rectangle.Empty)
+ {
+ sourceRect = new Rectangle(0, 0, source.Width, source.Height);
+ }
+ if (dest == null)
+ {
+ dest = source;
+ }
+ if (destRect == Rectangle.Empty)
+ {
+ destRect = new Rectangle(0, 0, dest.Width, dest.Height);
+ }
+ using (Graphics graphics = Graphics.FromImage(dest))
+ {
+ // Make sure we draw with the best quality!
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.CompositingMode = CompositingMode.SourceCopy;
+
+ graphics.DrawImage(source, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes);
+ }
+ }
+
+ ///
+ /// Returns a b/w of Bitmap
+ ///
+ /// Bitmap to create a b/w of
+ /// Threshold for monochrome filter (0 - 255), lower value means less black
+ /// b/w bitmap
+ public static Bitmap CreateMonochrome(Image sourceImage, byte threshold)
+ {
+ using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat))
+ {
+ for (int y = 0; y < fastBitmap.Height; y++)
+ {
+ for (int x = 0; x < fastBitmap.Width; x++)
+ {
+ Color color = fastBitmap.GetColorAt(x, y);
+ int colorBrightness = (color.R + color.G + color.B) / 3 > threshold ? 255 : 0;
+ Color monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness);
+ fastBitmap.SetColorAt(x, y, monoColor);
+ }
+ }
+ return fastBitmap.UnlockAndReturnBitmap();
+ }
+ }
+
+ ///
+ /// Create a new bitmap where the sourceBitmap has a Simple border around it
+ ///
+ /// Bitmap to make a border on
+ /// Size of the border
+ /// Color of the border
+ /// What pixel format must the returning bitmap have
+ /// The transform matrix which describes how the elements need to be transformed to stay at the same location
+ /// Bitmap with the shadow, is bigger than the sourceBitmap!!
+ public static Image CreateBorder(Image sourceImage, int borderSize, Color borderColor, PixelFormat targetPixelformat, Matrix matrix)
+ {
+ // "return" the shifted offset, so the caller can e.g. move elements
+ Point offset = new Point(borderSize, borderSize);
+ matrix.Translate(offset.X, offset.Y, MatrixOrder.Append);
+
+ // Create a new "clean" image
+ Bitmap newImage = CreateEmpty(sourceImage.Width + borderSize * 2, sourceImage.Height + borderSize * 2, targetPixelformat, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ using (Graphics graphics = Graphics.FromImage(newImage))
+ {
+ // Make sure we draw with the best quality!
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ using (GraphicsPath path = new GraphicsPath())
+ {
+ path.AddRectangle(new Rectangle(borderSize >> 1, borderSize >> 1, newImage.Width - borderSize, newImage.Height - borderSize));
+ using (Pen pen = new Pen(borderColor, borderSize))
+ {
+ pen.LineJoin = LineJoin.Round;
+ pen.StartCap = LineCap.Round;
+ pen.EndCap = LineCap.Round;
+ graphics.DrawPath(pen, path);
+ }
+ }
+ // draw original with a TextureBrush so we have nice antialiasing!
+ using (Brush textureBrush = new TextureBrush(sourceImage, WrapMode.Clamp))
+ {
+ // We need to do a translate-tranform otherwise the image is wrapped
+ graphics.TranslateTransform(offset.X, offset.Y);
+ graphics.FillRectangle(textureBrush, 0, 0, sourceImage.Width, sourceImage.Height);
+ }
+ }
+ return newImage;
+ }
+
+ ///
+ /// Create ImageAttributes to modify
+ ///
+ ///
+ ///
+ ///
+ /// ImageAttributes
+ public static ImageAttributes CreateAdjustAttributes(float brightness, float contrast, float gamma)
+ {
+ float adjustedBrightness = brightness - 1.0f;
+ ColorMatrix applyColorMatrix = new ColorMatrix(
+ new[]
+ {
+ new[] {contrast, 0, 0, 0, 0}, // scale red
+ new[] {0, contrast, 0, 0, 0}, // scale green
+ new[] {0, 0, contrast, 0, 0}, // scale blue
+ new[] {0, 0, 0, 1.0f, 0}, // don't scale alpha
+ new[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1}
+ });
+
+ //create some image attributes
+ ImageAttributes attributes = new ImageAttributes();
+ attributes.ClearColorMatrix();
+ attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
+ attributes.SetGamma(gamma, ColorAdjustType.Bitmap);
+ return attributes;
+ }
+
+ ///
+ /// Adjust the brightness, contract or gamma of an image.
+ /// Use the value "1.0f" for no changes.
+ ///
+ /// Original bitmap
+ ///
+ ///
+ ///
+ /// Bitmap with grayscale
+ public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma)
+ {
+ //create a blank bitmap the same size as original
+ // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format.
+ Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma))
+ {
+ ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes);
+ }
+ return newBitmap;
+ }
+
+ ///
+ /// Create a new bitmap where the sourceBitmap is in grayscale
+ ///
+ /// Original bitmap
+ /// Bitmap with grayscale
+ public static Image CreateGrayscale(Image sourceImage)
+ {
+ Bitmap clone = (Bitmap)Clone(sourceImage);
+ ColorMatrix grayscaleMatrix = new ColorMatrix(new[]
+ {
+ new[] {.3f, .3f, .3f, 0, 0},
+ new[] {.59f, .59f, .59f, 0, 0},
+ new[] {.11f, .11f, .11f, 0, 0},
+ new float[] {0, 0, 0, 1, 0},
+ new float[] {0, 0, 0, 0, 1}
+ });
+ ApplyColorMatrix(clone, grayscaleMatrix);
+ return clone;
+ }
+
+ ///
+ /// Checks if the supplied Bitmap has a PixelFormat we support
+ ///
+ /// bitmap to check
+ /// bool if we support it
+ public static bool SupportsPixelFormat(Image image)
+ {
+ return SupportsPixelFormat(image.PixelFormat);
+ }
+
+ ///
+ /// Checks if we support the pixel format
+ ///
+ /// PixelFormat to check
+ /// bool if we support it
+ public static bool SupportsPixelFormat(PixelFormat pixelformat)
+ {
+ return pixelformat.Equals(PixelFormat.Format32bppArgb) ||
+ pixelformat.Equals(PixelFormat.Format32bppPArgb) ||
+ pixelformat.Equals(PixelFormat.Format32bppRgb) ||
+ pixelformat.Equals(PixelFormat.Format24bppRgb);
+ }
+
+ ///
+ /// Wrapper for just cloning which calls the CloneArea
+ ///
+ /// Image to clone
+ /// Bitmap with clone image data
+ public static Image Clone(Image sourceImage)
+ {
+ if (sourceImage is Metafile)
+ {
+ return (Image)sourceImage.Clone();
+ }
+ return CloneArea(sourceImage, Rectangle.Empty, PixelFormat.DontCare);
+ }
+
+ ///
+ /// Wrapper for just cloning & TargetFormat which calls the CloneArea
+ ///
+ /// Image to clone
+ /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported)
+ /// Bitmap with clone image data
+ public static Bitmap Clone(Image sourceBitmap, PixelFormat targetFormat)
+ {
+ return CloneArea(sourceBitmap, Rectangle.Empty, targetFormat);
+ }
+
+ ///
+ /// Clone an image, taking some rules into account:
+ /// 1) When sourceRect is the whole bitmap there is a GDI+ bug in Clone
+ /// Clone will than return the same PixelFormat as the source
+ /// a quick workaround is using new Bitmap which uses a default of Format32bppArgb
+ /// 2) When going from a transparent to a non transparent bitmap, we draw the background white!
+ ///
+ /// Source bitmap to clone
+ /// Rectangle to copy from the source, use Rectangle.Empty for all
+ /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported)
+ ///
+ public static Bitmap CloneArea(Image sourceImage, Rectangle sourceRect, PixelFormat targetFormat)
+ {
+ Bitmap newImage;
+ Rectangle bitmapRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
+
+ // Make sure the source is not Rectangle.Empty
+ if (Rectangle.Empty.Equals(sourceRect))
+ {
+ sourceRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
+ }
+ else
+ {
+ sourceRect.Intersect(bitmapRect);
+ }
+
+ // If no pixelformat is supplied
+ if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat)
+ {
+ if (SupportsPixelFormat(sourceImage.PixelFormat))
+ {
+ targetFormat = sourceImage.PixelFormat;
+ }
+ else if (Image.IsAlphaPixelFormat(sourceImage.PixelFormat))
+ {
+ targetFormat = PixelFormat.Format32bppArgb;
+ }
+ else
+ {
+ targetFormat = PixelFormat.Format24bppRgb;
+ }
+ }
+
+ // check the target format
+ if (!SupportsPixelFormat(targetFormat))
+ {
+ targetFormat = Image.IsAlphaPixelFormat(targetFormat) ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb;
+ }
+
+ bool destinationIsTransparent = Image.IsAlphaPixelFormat(targetFormat);
+ bool sourceIsTransparent = Image.IsAlphaPixelFormat(sourceImage.PixelFormat);
+ bool fromTransparentToNon = !destinationIsTransparent && sourceIsTransparent;
+ bool isBitmap = sourceImage is Bitmap;
+ bool isAreaEqual = sourceRect.Equals(bitmapRect);
+ if (isAreaEqual || fromTransparentToNon || !isBitmap)
+ {
+ // Rule 1: if the areas are equal, always copy ourselves
+ newImage = new Bitmap(bitmapRect.Width, bitmapRect.Height, targetFormat);
+ // Make sure both images have the same resolution
+ newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+
+ using (Graphics graphics = Graphics.FromImage(newImage))
+ {
+ if (fromTransparentToNon)
+ {
+ // Rule 2: Make sure the background color is white
+ graphics.Clear(Color.White);
+ }
+ // decide fastest copy method
+ if (isAreaEqual)
+ {
+ graphics.DrawImageUnscaled(sourceImage, 0, 0);
+ }
+ else
+ {
+ graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel);
+ }
+ }
+ }
+ else
+ {
+ // Let GDI+ decide how to convert, need to test what is quicker...
+ newImage = (sourceImage as Bitmap).Clone(sourceRect, targetFormat);
+ // Make sure both images have the same resolution
+ newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ }
+ // Clone property items (EXIF information etc)
+ foreach (var propertyItem in sourceImage.PropertyItems)
+ {
+ try
+ {
+ newImage.SetPropertyItem(propertyItem);
+ }
+ catch (Exception ex)
+ {
+ Log.Warn("Problem cloning a propertyItem.", ex);
+ }
+ }
+ return newImage;
+ }
+
+ ///
+ /// Rotate the bitmap
+ ///
+ ///
+ ///
+ ///
+ public static Image RotateFlip(Image sourceImage, RotateFlipType rotateFlipType)
+ {
+ Image returnImage = Clone(sourceImage);
+ returnImage.RotateFlip(rotateFlipType);
+ return returnImage;
+ }
+
+ ///
+ /// A generic way to create an empty image
+ ///
+ /// the source bitmap as the specifications for the new bitmap
+ /// The color to fill with, or Color.Empty to take the default depending on the pixel format
+ ///
+ public static Bitmap CreateEmptyLike(Image sourceImage, Color backgroundColor)
+ {
+ PixelFormat pixelFormat = sourceImage.PixelFormat;
+ if (backgroundColor.A < 255)
+ {
+ pixelFormat = PixelFormat.Format32bppArgb;
+ }
+ return CreateEmpty(sourceImage.Width, sourceImage.Height, pixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ }
+
+ ///
+ /// A generic way to create an empty image
+ ///
+ ///
+ ///
+ ///
+ /// The color to fill with, or Color.Empty to take the default depending on the pixel format
+ ///
+ ///
+ /// Bitmap
+ public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution, float verticalResolution)
+ {
+ // Create a new "clean" image
+ Bitmap newImage = new Bitmap(width, height, format);
+ newImage.SetResolution(horizontalResolution, verticalResolution);
+ if (format != PixelFormat.Format8bppIndexed)
+ {
+ using (Graphics graphics = Graphics.FromImage(newImage))
+ {
+ // Make sure the background color is what we want (transparent or white, depending on the pixel format)
+ if (!Color.Empty.Equals(backgroundColor))
+ {
+ graphics.Clear(backgroundColor);
+ }
+ else if (Image.IsAlphaPixelFormat(format))
+ {
+ graphics.Clear(Color.Transparent);
+ }
+ else
+ {
+ graphics.Clear(Color.White);
+ }
+ }
+ }
+ return newImage;
+ }
+
+ ///
+ /// Get a scaled version of the sourceBitmap
+ ///
+ ///
+ /// 1-99 to make smaller, use 101 and more to make the picture bigger
+ ///
+ public static Bitmap ScaleByPercent(Bitmap sourceBitmap, int percent)
+ {
+ float nPercent = (float)percent / 100;
+
+ int sourceWidth = sourceBitmap.Width;
+ int sourceHeight = sourceBitmap.Height;
+ int destWidth = (int)(sourceWidth * nPercent);
+ int destHeight = (int)(sourceHeight * nPercent);
+
+ Bitmap scaledBitmap = CreateEmpty(destWidth, destHeight, sourceBitmap.PixelFormat, Color.Empty, sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
+ using (Graphics graphics = Graphics.FromImage(scaledBitmap))
+ {
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, destWidth, destHeight), new Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
+ }
+ return scaledBitmap;
+ }
+
+ ///
+ /// Resize canvas with pixel to the left, right, top and bottom
+ ///
+ ///
+ /// The color to fill with, or Color.Empty to take the default depending on the pixel format
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// a new bitmap with the source copied on it
+ public static Image ResizeCanvas(Image sourceImage, Color backgroundColor, int left, int right, int top, int bottom, Matrix matrix)
+ {
+ matrix.Translate(left, top, MatrixOrder.Append);
+ Bitmap newBitmap = CreateEmpty(sourceImage.Width + left + right, sourceImage.Height + top + bottom, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ using (Graphics graphics = Graphics.FromImage(newBitmap))
+ {
+ graphics.DrawImageUnscaled(sourceImage, left, top);
+ }
+ return newBitmap;
+ }
+
+ ///
+ /// Wrapper for the more complex Resize, this resize could be used for e.g. Thumbnails
+ ///
+ ///
+ /// true to maintain the aspect ratio
+ ///
+ ///
+ ///
+ ///
+ public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, int newWidth, int newHeight, Matrix matrix)
+ {
+ return ResizeImage(sourceImage, maintainAspectRatio, false, Color.Empty, newWidth, newHeight, matrix);
+ }
+
+ ///
+ /// Count how many times the supplied color exists
+ ///
+ /// Image to count the pixels of
+ /// Color to count
+ /// true if Alpha needs to be checked
+ /// int with the number of pixels which have colorToCount
+ public static int CountColor(Image sourceImage, Color colorToCount, bool includeAlpha)
+ {
+ int colors = 0;
+ int toCount = colorToCount.ToArgb();
+ if (!includeAlpha)
+ {
+ toCount = toCount & 0xffffff;
+ }
+ using (IFastBitmap bb = FastBitmap.Create((Bitmap)sourceImage))
+ {
+ for (int y = 0; y < bb.Height; y++)
+ {
+ for (int x = 0; x < bb.Width; x++)
+ {
+ int bitmapcolor = bb.GetColorAt(x, y).ToArgb();
+ if (!includeAlpha)
+ {
+ bitmapcolor = bitmapcolor & 0xffffff;
+ }
+ if (bitmapcolor == toCount)
+ {
+ colors++;
+ }
+ }
+ }
+ return colors;
+ }
+ }
+
+ ///
+ /// Scale the bitmap, keeping aspect ratio, but the canvas will always have the specified size.
+ ///
+ /// Image to scale
+ /// true to maintain the aspect ratio
+ /// Makes the image maintain aspect ratio, but the canvas get's the specified size
+ /// The color to fill with, or Color.Empty to take the default depending on the pixel format
+ /// new width
+ /// new height
+ ///
+ /// a new bitmap with the specified size, the source-Image scaled to fit with aspect ratio locked
+ public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, bool canvasUseNewSize, Color backgroundColor, int newWidth, int newHeight, Matrix matrix)
+ {
+ int destX = 0;
+ int destY = 0;
+
+ var nPercentW = newWidth / (float)sourceImage.Width;
+ var nPercentH = newHeight / (float)sourceImage.Height;
+ if (maintainAspectRatio)
+ {
+ if ((int)nPercentW == 1)
+ {
+ nPercentW = nPercentH;
+ if (canvasUseNewSize)
+ {
+ destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2));
+ }
+ }
+ else if ((int)nPercentH == 1)
+ {
+ nPercentH = nPercentW;
+ if (canvasUseNewSize)
+ {
+ destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2));
+ }
+ }
+ else if ((int)nPercentH != 0 && nPercentH < nPercentW)
+ {
+ nPercentW = nPercentH;
+ if (canvasUseNewSize)
+ {
+ destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2));
+ }
+ }
+ else
+ {
+ nPercentH = nPercentW;
+ if (canvasUseNewSize)
+ {
+ destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2));
+ }
+ }
+ }
+
+ int destWidth = (int)(sourceImage.Width * nPercentW);
+ int destHeight = (int)(sourceImage.Height * nPercentH);
+ if (newWidth == 0)
+ {
+ newWidth = destWidth;
+ }
+ if (newHeight == 0)
+ {
+ newHeight = destHeight;
+ }
+ Image newImage;
+ if (maintainAspectRatio && canvasUseNewSize)
+ {
+ newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ matrix?.Scale((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height, MatrixOrder.Append);
+ }
+ else
+ {
+ newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ matrix?.Scale((float)destWidth / sourceImage.Width, (float)destHeight / sourceImage.Height, MatrixOrder.Append);
+ }
+
+ using (Graphics graphics = Graphics.FromImage(newImage))
+ {
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ using (ImageAttributes wrapMode = new ImageAttributes())
+ {
+ wrapMode.SetWrapMode(WrapMode.TileFlipXY);
+ graphics.DrawImage(sourceImage, new Rectangle(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode);
+ }
+ }
+ return newImage;
+ }
+
+ ///
+ /// Load a Greenshot surface from a stream
+ ///
+ /// Stream
+ ///
+ /// ISurface
+ public static ISurface LoadGreenshotSurface(Stream surfaceFileStream, ISurface returnSurface)
+ {
+ Image fileImage;
+ // Fixed problem that the bitmap stream is disposed... by Cloning the image
+ // This also ensures the bitmap is correctly created
+
+ // We create a copy of the bitmap, so everything else can be disposed
+ surfaceFileStream.Position = 0;
+ using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true))
+ {
+ Log.DebugFormat("Loaded .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
+ fileImage = Clone(tmpImage);
+ }
+ // Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
+ const int markerSize = 14;
+ surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
+ using (StreamReader streamReader = new StreamReader(surfaceFileStream))
+ {
+ var greenshotMarker = streamReader.ReadToEnd();
+ if (!greenshotMarker.StartsWith("Greenshot"))
+ {
+ throw new ArgumentException("Stream is not a Greenshot file!");
+ }
+ Log.InfoFormat("Greenshot file format: {0}", greenshotMarker);
+ const int filesizeLocation = 8 + markerSize;
+ surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
+ using (BinaryReader reader = new BinaryReader(surfaceFileStream))
+ {
+ long bytesWritten = reader.ReadInt64();
+ surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
+ returnSurface.LoadElementsFromStream(surfaceFileStream);
+ }
+ }
+ if (fileImage != null)
+ {
+ returnSurface.Image = fileImage;
+ Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", fileImage.Width, fileImage.Height, fileImage.PixelFormat, fileImage.HorizontalResolution, fileImage.VerticalResolution);
+ }
+ return returnSurface;
+ }
+
+ ///
+ /// Create an image from a stream, if an extension is supplied more formats are supported.
+ ///
+ /// Stream
+ ///
+ /// Image
+ public static Image FromStream(Stream stream, string extension = null)
+ {
+ if (stream == null)
+ {
+ return null;
+ }
+ if (!string.IsNullOrEmpty(extension))
+ {
+ extension = extension.Replace(".", "");
+ }
+
+ // Make sure we can try multiple times
+ if (!stream.CanSeek)
+ {
+ var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
+ stream = memoryStream;
+ }
+
+ Image returnImage = null;
+ Func converter;
+ if (StreamConverters.TryGetValue(extension ?? "", out converter))
+ {
+ returnImage = converter(stream, extension);
+ }
+ // Fallback
+ if (returnImage == null)
+ {
+ // We create a copy of the bitmap, so everything else can be disposed
+ stream.Position = 0;
+ using (var tmpImage = Image.FromStream(stream, true, true))
+ {
+ Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
+ returnImage = Clone(tmpImage, PixelFormat.Format32bppArgb);
+ }
+ }
+ return returnImage;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/ImageOutput.cs b/GreenshotPlugin/Core/ImageOutput.cs
new file mode 100644
index 000000000..125ec0dda
--- /dev/null
+++ b/GreenshotPlugin/Core/ImageOutput.cs
@@ -0,0 +1,684 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using GreenshotPlugin.Controls;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using Encoder = System.Drawing.Imaging.Encoder;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of ImageOutput.
+ ///
+ public static class ImageOutput {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ImageOutput));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
+ private static readonly Cache TmpFileCache = new Cache(10 * 60 * 60, RemoveExpiredTmpFile);
+
+ ///
+ /// Creates a PropertyItem (Metadata) to store with the image.
+ /// For the possible ID's see: http://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx
+ /// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that!
+ ///
+ /// ID
+ /// Text
+ ///
+ private static PropertyItem CreatePropertyItem(int id, string text) {
+ PropertyItem propertyItem = null;
+ try {
+ ConstructorInfo ci = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
+ propertyItem = (PropertyItem)ci.Invoke(null);
+ // Make sure it's of type string
+ propertyItem.Type = 2;
+ // Set the ID
+ propertyItem.Id = id;
+ // Set the text
+ byte[] byteString = Encoding.ASCII.GetBytes(text + " ");
+ // Set Zero byte for String end.
+ byteString[byteString.Length - 1] = 0;
+ propertyItem.Value = byteString;
+ propertyItem.Len = text.Length + 1;
+ } catch (Exception e) {
+ Log.WarnFormat("Error creating a PropertyItem: {0}", e.Message);
+ }
+ return propertyItem;
+ }
+ #region save
+ ///
+ /// Saves ISurface to stream with specified output settings
+ ///
+ /// ISurface to save
+ /// Stream to save to
+ /// SurfaceOutputSettings
+ public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) {
+ Image imageToSave;
+ bool disposeImage = CreateImageFromSurface(surface, outputSettings, out imageToSave);
+ SaveToStream(imageToSave, surface, stream, outputSettings);
+ // cleanup if needed
+ if (disposeImage) {
+ imageToSave?.Dispose();
+ }
+ }
+
+ ///
+ /// Saves image to stream with specified quality
+ /// To prevent problems with GDI version of before Windows 7:
+ /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used.
+ ///
+ /// image to save
+ /// surface for the elements, needed if the greenshot format is used
+ /// Stream to save to
+ /// SurfaceOutputSettings
+ public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) {
+ bool useMemoryStream = false;
+ MemoryStream memoryStream = null;
+ if (outputSettings.Format == OutputFormat.greenshot && surface == null) {
+ throw new ArgumentException("Surface needs to be set when using OutputFormat.Greenshot");
+ }
+
+ try {
+ ImageFormat imageFormat;
+ switch (outputSettings.Format) {
+ case OutputFormat.bmp:
+ imageFormat = ImageFormat.Bmp;
+ break;
+ case OutputFormat.gif:
+ imageFormat = ImageFormat.Gif;
+ break;
+ case OutputFormat.jpg:
+ imageFormat = ImageFormat.Jpeg;
+ break;
+ case OutputFormat.tiff:
+ imageFormat = ImageFormat.Tiff;
+ break;
+ case OutputFormat.ico:
+ imageFormat = ImageFormat.Icon;
+ break;
+ default:
+ imageFormat = ImageFormat.Png;
+ break;
+ }
+ Log.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat);
+
+ // Check if we want to use a memory stream, to prevent issues with non seakable streams
+ // The save is made to the targetStream, this is directed to either the MemoryStream or the original
+ Stream targetStream = stream;
+ if (!stream.CanSeek)
+ {
+ useMemoryStream = true;
+ Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream.");
+ memoryStream = new MemoryStream();
+ targetStream = memoryStream;
+ }
+
+ if (Equals(imageFormat, ImageFormat.Jpeg))
+ {
+ bool foundEncoder = false;
+ foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders())
+ {
+ if (imageCodec.FormatID == imageFormat.Guid)
+ {
+ EncoderParameters parameters = new EncoderParameters(1)
+ {
+ Param = {[0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality)}
+ };
+ // Removing transparency if it's not supported in the output
+ if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
+ {
+ Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
+ AddTag(nonAlphaImage);
+ nonAlphaImage.Save(targetStream, imageCodec, parameters);
+ nonAlphaImage.Dispose();
+ }
+ else
+ {
+ AddTag(imageToSave);
+ imageToSave.Save(targetStream, imageCodec, parameters);
+ }
+ foundEncoder = true;
+ break;
+ }
+ }
+ if (!foundEncoder)
+ {
+ throw new ApplicationException("No JPG encoder found, this should not happen.");
+ }
+ } else if (Equals(imageFormat, ImageFormat.Icon)) {
+ // FEATURE-916: Added Icon support
+ IList images = new List();
+ images.Add(imageToSave);
+ WriteIcon(stream, images);
+ } else {
+ bool needsDispose = false;
+ // Removing transparency if it's not supported in the output
+ if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) {
+ imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
+ needsDispose = true;
+ }
+ AddTag(imageToSave);
+ // Added for OptiPNG
+ bool processed = false;
+ if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) {
+ processed = ProcessPngImageExternally(imageToSave, targetStream);
+ }
+ if (!processed) {
+ imageToSave.Save(targetStream, imageFormat);
+ }
+ if (needsDispose) {
+ imageToSave.Dispose();
+ }
+ }
+
+ // If we used a memory stream, we need to stream the memory stream to the original stream.
+ if (useMemoryStream) {
+ memoryStream.WriteTo(stream);
+ }
+
+ // Output the surface elements, size and marker to the stream
+ if (outputSettings.Format != OutputFormat.greenshot)
+ {
+ return;
+ }
+ using (MemoryStream tmpStream = new MemoryStream()) {
+ long bytesWritten = surface.SaveElementsToStream(tmpStream);
+ using (BinaryWriter writer = new BinaryWriter(tmpStream)) {
+ writer.Write(bytesWritten);
+ Version v = Assembly.GetExecutingAssembly().GetName().Version;
+ byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}");
+ writer.Write(marker);
+ tmpStream.WriteTo(stream);
+ }
+ }
+ }
+ finally
+ {
+ memoryStream?.Dispose();
+ }
+ }
+
+ ///
+ /// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream
+ ///
+ /// Image to pass to the external process
+ /// stream to write the processed image to
+ ///
+ private static bool ProcessPngImageExternally(Image imageToProcess, Stream targetStream) {
+ if (string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) {
+ return false;
+ }
+ if (!File.Exists(CoreConfig.OptimizePNGCommand)) {
+ Log.WarnFormat("Can't find 'OptimizePNGCommand' {0}", CoreConfig.OptimizePNGCommand);
+ return false;
+ }
+ string tmpFileName = Path.Combine(Path.GetTempPath(),Path.GetRandomFileName() + ".png");
+ try {
+ using (FileStream tmpStream = File.Create(tmpFileName)) {
+ Log.DebugFormat("Writing png to tmp file: {0}", tmpFileName);
+ imageToProcess.Save(tmpStream, ImageFormat.Png);
+ if (Log.IsDebugEnabled) {
+ Log.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length);
+ }
+ }
+ if (Log.IsDebugEnabled) {
+ Log.DebugFormat("Starting : {0}", CoreConfig.OptimizePNGCommand);
+ }
+
+ ProcessStartInfo processStartInfo = new ProcessStartInfo(CoreConfig.OptimizePNGCommand)
+ {
+ Arguments = string.Format(CoreConfig.OptimizePNGCommandArguments, tmpFileName),
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false
+ };
+ using (Process process = Process.Start(processStartInfo)) {
+ if (process != null) {
+ process.WaitForExit();
+ if (process.ExitCode == 0) {
+ if (Log.IsDebugEnabled) {
+ Log.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length);
+ Log.DebugFormat("Reading back tmp file: {0}", tmpFileName);
+ }
+ byte[] processedImage = File.ReadAllBytes(tmpFileName);
+ targetStream.Write(processedImage, 0, processedImage.Length);
+ return true;
+ }
+ Log.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode);
+ Log.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd());
+ Log.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd());
+ }
+ }
+ } catch (Exception e) {
+ Log.Error("Error while processing PNG image: ", e);
+ } finally {
+ if (File.Exists(tmpFileName)) {
+ Log.DebugFormat("Cleaning up tmp file: {0}", tmpFileName);
+ File.Delete(tmpFileName);
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Create an image from a surface with the settings from the output settings applied
+ ///
+ ///
+ ///
+ ///
+ /// true if the image must be disposed
+ public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) {
+ bool disposeImage = false;
+
+ if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) {
+ // We save the image of the surface, this should not be disposed
+ imageToSave = surface.Image;
+ } else {
+ // We create the export image of the surface to save
+ imageToSave = surface.GetImageForExport();
+ disposeImage = true;
+ }
+
+ // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise!
+ if (outputSettings.Format == OutputFormat.greenshot) {
+ return disposeImage;
+ }
+ Image tmpImage;
+ if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) {
+ // apply effects, if there are any
+ using (Matrix matrix = new Matrix()) {
+ tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix);
+ }
+ if (tmpImage != null) {
+ if (disposeImage) {
+ imageToSave.Dispose();
+ }
+ imageToSave = tmpImage;
+ disposeImage = true;
+ }
+ }
+
+ // check for color reduction, forced or automatically, only when the DisableReduceColors is false
+ if (outputSettings.DisableReduceColors || (!CoreConfig.OutputFileAutoReduceColors && !outputSettings.ReduceColors)) {
+ return disposeImage;
+ }
+ bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat);
+ if (outputSettings.ReduceColors || (!isAlpha && CoreConfig.OutputFileAutoReduceColors)) {
+ using (var quantizer = new WuQuantizer((Bitmap)imageToSave)) {
+ int colorCount = quantizer.GetColorCount();
+ Log.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount);
+ if (!outputSettings.ReduceColors && colorCount >= 256) {
+ return disposeImage;
+ }
+ try {
+ Log.Info("Reducing colors on bitmap to 256.");
+ tmpImage = quantizer.GetQuantizedImage(CoreConfig.OutputFileReduceColorsTo);
+ if (disposeImage) {
+ imageToSave.Dispose();
+ }
+ imageToSave = tmpImage;
+ // Make sure the "new" image is disposed
+ disposeImage = true;
+ } catch (Exception e) {
+ Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e);
+ }
+ }
+ } else if (isAlpha && !outputSettings.ReduceColors) {
+ Log.Info("Skipping 'optional' color reduction as the image has alpha");
+ }
+ return disposeImage;
+ }
+
+ ///
+ /// Add the greenshot property!
+ ///
+ ///
+ private static void AddTag(Image imageToSave) {
+ // Create meta-data
+ PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot");
+ if (softwareUsedPropertyItem != null) {
+ try {
+ imageToSave.SetPropertyItem(softwareUsedPropertyItem);
+ } catch (Exception) {
+ Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id);
+ }
+ }
+ }
+
+ ///
+ /// Load a Greenshot surface
+ ///
+ ///
+ ///
+ ///
+ public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface) {
+ if (string.IsNullOrEmpty(fullPath)) {
+ return null;
+ }
+ Log.InfoFormat("Loading image from file {0}", fullPath);
+ // Fixed lock problem Bug #3431881
+ using (Stream surfaceFileStream = File.OpenRead(fullPath)) {
+ returnSurface = ImageHelper.LoadGreenshotSurface(surfaceFileStream, returnSurface);
+ }
+ if (returnSurface != null) {
+ Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, returnSurface.Image.Width, returnSurface.Image.Height, returnSurface.Image.PixelFormat, returnSurface.Image.HorizontalResolution, returnSurface.Image.VerticalResolution);
+ }
+ return returnSurface;
+ }
+
+ ///
+ /// Saves image to specific path with specified quality
+ ///
+ public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings outputSettings, bool copyPathToClipboard) {
+ fullPath = FilenameHelper.MakeFqFilenameSafe(fullPath);
+ string path = Path.GetDirectoryName(fullPath);
+
+ // check whether path exists - if not create it
+ if (path != null) {
+ DirectoryInfo di = new DirectoryInfo(path);
+ if (!di.Exists) {
+ Directory.CreateDirectory(di.FullName);
+ }
+ }
+
+ if (!allowOverwrite && File.Exists(fullPath)) {
+ ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists.");
+ throwingException.Data.Add("fullPath", fullPath);
+ throw throwingException;
+ }
+ Log.DebugFormat("Saving surface to {0}", fullPath);
+ // Create the stream and call SaveToStream
+ using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) {
+ SaveToStream(surface, stream, outputSettings);
+ }
+
+ if (copyPathToClipboard) {
+ ClipboardHelper.SetClipboardData(fullPath);
+ }
+ }
+
+ ///
+ /// Get the OutputFormat for a filename
+ ///
+ /// filename (can be a complete path)
+ /// OutputFormat
+ public static OutputFormat FormatForFilename(string fullPath) {
+ // Fix for bug 2912959
+ string extension = fullPath.Substring(fullPath.LastIndexOf(".", StringComparison.Ordinal) + 1);
+ OutputFormat format = OutputFormat.png;
+ try {
+ format = (OutputFormat)Enum.Parse(typeof(OutputFormat), extension.ToLower());
+ } catch (ArgumentException ae) {
+ Log.Warn("Couldn't parse extension: " + extension, ae);
+ }
+ return format;
+ }
+ #endregion
+
+ #region save-as
+
+ ///
+ /// Save with showing a dialog
+ ///
+ ///
+ ///
+ /// Path to filename
+ public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails) {
+ string returnValue = null;
+ using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails)) {
+ DialogResult dialogResult = saveImageFileDialog.ShowDialog();
+ if (dialogResult.Equals(DialogResult.OK)) {
+ try {
+ string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension));
+ if (CoreConfig.OutputFilePromptQuality) {
+ QualityDialog qualityDialog = new QualityDialog(outputSettings);
+ qualityDialog.ShowDialog();
+ }
+ // TODO: For now we always overwrite, should be changed
+ Save(surface, fileNameWithExtension, true, outputSettings, CoreConfig.OutputFileCopyPathToClipboard);
+ returnValue = fileNameWithExtension;
+ IniConfig.Save();
+ } catch (ExternalException) {
+ MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error"));
+ }
+ }
+ }
+ return returnValue;
+ }
+ #endregion
+
+ ///
+ /// Create a tmpfile which has the name like in the configured pattern.
+ /// Used e.g. by the email export
+ ///
+ ///
+ ///
+ ///
+ /// Path to image file
+ public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, SurfaceOutputSettings outputSettings) {
+ string pattern = CoreConfig.OutputFileFilenamePattern;
+ if (string.IsNullOrEmpty(pattern?.Trim())) {
+ pattern = "greenshot ${capturetime}";
+ }
+ string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails);
+ // Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML
+ filename = Regex.Replace(filename, @"[^\d\w\.]", "_");
+ // Remove multiple "_"
+ filename = Regex.Replace(filename, @"_+", "_");
+ string tmpFile = Path.Combine(Path.GetTempPath(), filename);
+
+ Log.Debug("Creating TMP File: " + tmpFile);
+
+ // Catching any exception to prevent that the user can't write in the directory.
+ // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218
+ try {
+ Save(surface, tmpFile, true, outputSettings, false);
+ TmpFileCache.Add(tmpFile, tmpFile);
+ } catch (Exception e) {
+ // Show the problem
+ MessageBox.Show(e.Message, "Error");
+ // when save failed we present a SaveWithDialog
+ tmpFile = SaveWithDialog(surface, captureDetails);
+ }
+ return tmpFile;
+ }
+
+ ///
+ /// Remove a tmpfile which was created by SaveNamedTmpFile
+ /// Used e.g. by the email export
+ ///
+ ///
+ /// true if it worked
+ public static bool DeleteNamedTmpFile(string tmpfile) {
+ Log.Debug("Deleting TMP File: " + tmpfile);
+ try {
+ if (File.Exists(tmpfile)) {
+ File.Delete(tmpfile);
+ TmpFileCache.Remove(tmpfile);
+ }
+ return true;
+ } catch (Exception ex) {
+ Log.Warn("Error deleting tmp file: ", ex);
+ }
+ return false;
+ }
+
+ ///
+ /// Helper method to create a temp image file
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath) {
+ string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format;
+ // Prevent problems with "other characters", which could cause problems
+ tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", "");
+ if (destinationPath == null) {
+ destinationPath = Path.GetTempPath();
+ }
+ string tmpPath = Path.Combine(destinationPath, tmpFile);
+ Log.Debug("Creating TMP File : " + tmpPath);
+
+ try {
+ Save(surface, tmpPath, true, outputSettings, false);
+ TmpFileCache.Add(tmpPath, tmpPath);
+ } catch (Exception) {
+ return null;
+ }
+ return tmpPath;
+ }
+
+ ///
+ /// Cleanup all created tmpfiles
+ ///
+ public static void RemoveTmpFiles() {
+ foreach (string tmpFile in TmpFileCache.Elements) {
+ if (File.Exists(tmpFile)) {
+ Log.DebugFormat("Removing old temp file {0}", tmpFile);
+ File.Delete(tmpFile);
+ }
+ TmpFileCache.Remove(tmpFile);
+ }
+ }
+
+ ///
+ /// Cleanup handler for expired tempfiles
+ ///
+ ///
+ ///
+ private static void RemoveExpiredTmpFile(string filekey, object filename) {
+ string path = filename as string;
+ if (path != null && File.Exists(path)) {
+ Log.DebugFormat("Removing expired file {0}", path);
+ File.Delete(path);
+ }
+ }
+
+ #region Icon
+
+ ///
+ /// Write the images to the stream as icon
+ /// Every image is resized to 256x256 (but the content maintains the aspect ratio)
+ ///
+ /// Stream to write to
+ /// List of images
+ public static void WriteIcon(Stream stream, IList images)
+ {
+ var binaryWriter = new BinaryWriter(stream);
+ //
+ // ICONDIR structure
+ //
+ binaryWriter.Write((short)0); // reserved
+ binaryWriter.Write((short)1); // image type (icon)
+ binaryWriter.Write((short)images.Count); // number of images
+
+ IList imageSizes = new List();
+ IList encodedImages = new List();
+ foreach (var image in images)
+ {
+ // Pick the best fit
+ var sizes = new[] { 16, 32, 48 };
+ int size = 256;
+ foreach (var possibleSize in sizes)
+ {
+ if (image.Width <= possibleSize && image.Height <= possibleSize)
+ {
+ size = possibleSize;
+ break;
+ }
+ }
+ var imageStream = new MemoryStream();
+ if (image.Width == size && image.Height == size)
+ {
+ using (var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb))
+ {
+ clonedImage.Save(imageStream, ImageFormat.Png);
+ imageSizes.Add(new Size(size, size));
+ }
+ }
+ else
+ {
+ // Resize to the specified size, first make sure the image is 32bpp
+ using (var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb))
+ {
+ using (var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null))
+ {
+ resizedImage.Save(imageStream, ImageFormat.Png);
+ imageSizes.Add(resizedImage.Size);
+ }
+ }
+ }
+
+ imageStream.Seek(0, SeekOrigin.Begin);
+ encodedImages.Add(imageStream);
+ }
+
+ //
+ // ICONDIRENTRY structure
+ //
+ const int iconDirSize = 6;
+ const int iconDirEntrySize = 16;
+
+ var offset = iconDirSize + (images.Count * iconDirEntrySize);
+ for (int i = 0; i < images.Count; i++)
+ {
+ var imageSize = imageSizes[i];
+ // Write the width / height, 0 means 256
+ binaryWriter.Write(imageSize.Width == 256 ? (byte)0 : (byte)imageSize.Width);
+ binaryWriter.Write(imageSize.Height == 256 ? (byte)0 : (byte)imageSize.Height);
+ binaryWriter.Write((byte)0); // no pallete
+ binaryWriter.Write((byte)0); // reserved
+ binaryWriter.Write((short)0); // no color planes
+ binaryWriter.Write((short)32); // 32 bpp
+ binaryWriter.Write((int)encodedImages[i].Length); // image data length
+ binaryWriter.Write(offset);
+ offset += (int)encodedImages[i].Length;
+ }
+
+ binaryWriter.Flush();
+ //
+ // Write image data
+ //
+ foreach (var encodedImage in encodedImages)
+ {
+ encodedImage.WriteTo(stream);
+ encodedImage.Dispose();
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/GreenshotPlugin/Core/ImageWrapper.cs b/GreenshotPlugin/Core/ImageWrapper.cs
new file mode 100644
index 000000000..f4cc03247
--- /dev/null
+++ b/GreenshotPlugin/Core/ImageWrapper.cs
@@ -0,0 +1,86 @@
+using System.Drawing;
+using System.Drawing.Imaging;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// Wrap an image, make it resizeable
+ ///
+ public class ImageWrapper : IImage
+ {
+ // Underlying image, is used to generate a resized version of it when needed
+ private readonly Image _image;
+ private Image _imageClone;
+
+ ///
+ /// Factory method
+ ///
+ /// Image
+ /// IImage
+ public static IImage FromImage(Image image)
+ {
+ return image == null ? null : new ImageWrapper(image);
+ }
+
+ public ImageWrapper(Image image)
+ {
+ // Make sure the orientation is set correctly so Greenshot can process the image correctly
+ ImageHelper.Orientate(image);
+ _image = image;
+ Width = _image.Width;
+ Height = _image.Height;
+ }
+
+ public void Dispose()
+ {
+ _image.Dispose();
+ _imageClone?.Dispose();
+ }
+
+ ///
+ /// Height of the image, can be set to change
+ ///
+ public int Height { get; set; }
+
+ ///
+ /// Width of the image, can be set to change.
+ ///
+ public int Width { get; set; }
+
+ ///
+ /// Size of the image
+ ///
+ public Size Size => new Size(Width, Height);
+
+ ///
+ /// Pixelformat of the underlying image
+ ///
+ public PixelFormat PixelFormat => Image.PixelFormat;
+
+ public float HorizontalResolution => Image.HorizontalResolution;
+ public float VerticalResolution => Image.VerticalResolution;
+
+ public Image Image
+ {
+ get
+ {
+ if (_imageClone == null)
+ {
+ if (_image.Height == Height && _image.Width == Width)
+ {
+ return _image;
+ }
+ }
+ if (_imageClone?.Height == Height && _imageClone?.Width == Width)
+ {
+ return _imageClone;
+ }
+ // Calculate new image clone
+ _imageClone?.Dispose();
+ _imageClone = ImageHelper.ResizeImage(_image, false, Width, Height, null);
+ return _imageClone;
+ }
+ }
+
+ }
+}
diff --git a/GreenshotPlugin/Core/InterfaceUtils.cs b/GreenshotPlugin/Core/InterfaceUtils.cs
new file mode 100644
index 000000000..ef5fec356
--- /dev/null
+++ b/GreenshotPlugin/Core/InterfaceUtils.cs
@@ -0,0 +1,74 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
+using Greenshot.Plugin;
+using log4net;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of InterfaceUtils.
+ ///
+ public static class InterfaceUtils {
+ private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils));
+
+ public static List GetSubclassesOf(Type type, bool excludeSystemTypes) {
+ List list = new List();
+ foreach(Assembly currentAssembly in Thread.GetDomain().GetAssemblies()) {
+ try {
+ Type[] types = currentAssembly.GetTypes();
+ if (!excludeSystemTypes || (excludeSystemTypes && !currentAssembly.FullName.StartsWith("System."))) {
+ foreach(Type currentType in types) {
+ if (type.IsInterface) {
+ if (currentType.GetInterface(type.FullName) != null) {
+ list.Add(currentType);
+ }
+ } else if (currentType.IsSubclassOf(type)) {
+ list.Add(currentType);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ LOG.WarnFormat("Problem getting subclasses of type: {0}, message: {1}", type.FullName, ex.Message);
+ }
+ }
+ return list;
+ }
+
+ public static List GetProcessors() {
+ List processors = new List();
+ foreach(Type processorType in GetSubclassesOf(typeof(IProcessor), true)) {
+ if (!processorType.IsAbstract) {
+ IProcessor processor = (IProcessor)Activator.CreateInstance(processorType);
+ if (processor.isActive) {
+ LOG.DebugFormat("Found processor {0} with designation {1}", processorType.Name, processor.Designation);
+ processors.Add(processor);
+ } else {
+ LOG.DebugFormat("Ignoring processor {0} with designation {1}", processorType.Name, processor.Designation);
+ }
+ }
+ }
+ return processors;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/JSONHelper.cs b/GreenshotPlugin/Core/JSONHelper.cs
new file mode 100644
index 000000000..57293726c
--- /dev/null
+++ b/GreenshotPlugin/Core/JSONHelper.cs
@@ -0,0 +1,361 @@
+/*
+Copyright (C) 2008 Patrick van Bergen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// This parses a JSON response, a modified version of the code found at:
+ /// See: http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
+ ///
+ /// This file is under the MIT License, which is GPL Compatible and according to: http://en.wikipedia.org/wiki/MIT_License
+ /// can be used under the GPL "umbrella".
+ ///
+ /// TODO: code should be replaced when upgrading to .NET 3.5 or higher!!
+ ///
+ public class JSONHelper {
+ public const int TOKEN_NONE = 0;
+ public const int TOKEN_CURLY_OPEN = 1;
+ public const int TOKEN_CURLY_CLOSE = 2;
+ public const int TOKEN_SQUARED_OPEN = 3;
+ public const int TOKEN_SQUARED_CLOSE = 4;
+ public const int TOKEN_COLON = 5;
+ public const int TOKEN_COMMA = 6;
+ public const int TOKEN_STRING = 7;
+ public const int TOKEN_NUMBER = 8;
+ public const int TOKEN_TRUE = 9;
+ public const int TOKEN_FALSE = 10;
+ public const int TOKEN_NULL = 11;
+
+ private const int BUILDER_CAPACITY = 2000;
+
+ ///
+ /// Parses the string json into a value
+ ///
+ /// A JSON string.
+ /// An ArrayList, a Hashtable, a double, a string, null, true, or false
+ public static IDictionary JsonDecode(string json) {
+ bool success = true;
+
+ return JsonDecode(json, ref success);
+ }
+
+ ///
+ /// Parses the string json into a value; and fills 'success' with the successfullness of the parse.
+ ///
+ /// A JSON string.
+ /// Successful parse?
+ /// An ArrayList, a Hashtable, a double, a string, null, true, or false
+ public static IDictionary JsonDecode(string json, ref bool success) {
+ success = true;
+ if (json != null) {
+ char[] charArray = json.ToCharArray();
+ int index = 0;
+ IDictionary value = ParseValue(charArray, ref index, ref success) as IDictionary;
+ return value;
+ }
+ return null;
+ }
+
+ protected static IDictionary ParseObject(char[] json, ref int index, ref bool success) {
+ IDictionary table = new Dictionary();
+ int token;
+
+ // {
+ NextToken(json, ref index);
+
+ bool done = false;
+ while (!done) {
+ token = LookAhead(json, index);
+ if (token == TOKEN_NONE) {
+ success = false;
+ return null;
+ } else if (token == TOKEN_COMMA) {
+ NextToken(json, ref index);
+ } else if (token == TOKEN_CURLY_CLOSE) {
+ NextToken(json, ref index);
+ return table;
+ } else {
+
+ // name
+ string name = ParseString(json, ref index, ref success);
+ if (!success) {
+ success = false;
+ return null;
+ }
+
+ // :
+ token = NextToken(json, ref index);
+ if (token != TOKEN_COLON) {
+ success = false;
+ return null;
+ }
+
+ // value
+ object value = ParseValue(json, ref index, ref success);
+ if (!success) {
+ success = false;
+ return null;
+ }
+
+ table.Add(name, value);
+ }
+ }
+
+ return table;
+ }
+
+ protected static IList ParseArray(char[] json, ref int index, ref bool success) {
+ IList array = new List();
+
+ // [
+ NextToken(json, ref index);
+
+ bool done = false;
+ while (!done) {
+ int token = LookAhead(json, index);
+ if (token == TOKEN_NONE) {
+ success = false;
+ return null;
+ } else if (token == TOKEN_COMMA) {
+ NextToken(json, ref index);
+ } else if (token == TOKEN_SQUARED_CLOSE) {
+ NextToken(json, ref index);
+ break;
+ } else {
+ object value = ParseValue(json, ref index, ref success);
+ if (!success) {
+ return null;
+ }
+
+ array.Add(value);
+ }
+ }
+
+ return array;
+ }
+
+ protected static object ParseValue(char[] json, ref int index, ref bool success) {
+ switch (LookAhead(json, index)) {
+ case TOKEN_STRING:
+ return ParseString(json, ref index, ref success);
+ case TOKEN_NUMBER:
+ return ParseNumber(json, ref index, ref success);
+ case TOKEN_CURLY_OPEN:
+ return ParseObject(json, ref index, ref success);
+ case TOKEN_SQUARED_OPEN:
+ return ParseArray(json, ref index, ref success);
+ case TOKEN_TRUE:
+ NextToken(json, ref index);
+ return true;
+ case TOKEN_FALSE:
+ NextToken(json, ref index);
+ return false;
+ case TOKEN_NULL:
+ NextToken(json, ref index);
+ return null;
+ case TOKEN_NONE:
+ break;
+ }
+
+ success = false;
+ return null;
+ }
+
+ protected static string ParseString(char[] json, ref int index, ref bool success) {
+ StringBuilder s = new StringBuilder(BUILDER_CAPACITY);
+
+ EatWhitespace(json, ref index);
+
+ // "
+ var c = json[index++];
+
+ bool complete = false;
+ while (!complete) {
+
+ if (index == json.Length) {
+ break;
+ }
+
+ c = json[index++];
+ if (c == '"') {
+ complete = true;
+ break;
+ } else if (c == '\\') {
+
+ if (index == json.Length) {
+ break;
+ }
+ c = json[index++];
+ if (c == '"') {
+ s.Append('"');
+ } else if (c == '\\') {
+ s.Append('\\');
+ } else if (c == '/') {
+ s.Append('/');
+ } else if (c == 'b') {
+ s.Append('\b');
+ } else if (c == 'f') {
+ s.Append('\f');
+ } else if (c == 'n') {
+ s.Append('\n');
+ } else if (c == 'r') {
+ s.Append('\r');
+ } else if (c == 't') {
+ s.Append('\t');
+ } else if (c == 'u') {
+ int remainingLength = json.Length - index;
+ if (remainingLength >= 4) {
+ // parse the 32 bit hex into an integer codepoint
+ uint codePoint;
+ if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) {
+ return "";
+ }
+ // convert the integer codepoint to a unicode char and add to string
+ s.Append(char.ConvertFromUtf32((int)codePoint));
+ // skip 4 chars
+ index += 4;
+ } else {
+ break;
+ }
+ }
+
+ } else {
+ s.Append(c);
+ }
+
+ }
+
+ if (!complete) {
+ success = false;
+ return null;
+ }
+
+ return s.ToString();
+ }
+
+ protected static double ParseNumber(char[] json, ref int index, ref bool success) {
+ EatWhitespace(json, ref index);
+
+ int lastIndex = GetLastIndexOfNumber(json, index);
+ int charLength = (lastIndex - index) + 1;
+
+ double number;
+ success = double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
+
+ index = lastIndex + 1;
+ return number;
+ }
+
+ protected static int GetLastIndexOfNumber(char[] json, int index) {
+ int lastIndex;
+
+ for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
+ if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) {
+ break;
+ }
+ }
+ return lastIndex - 1;
+ }
+
+ protected static void EatWhitespace(char[] json, ref int index) {
+ for (; index < json.Length; index++) {
+ if (" \t\n\r".IndexOf(json[index]) == -1) {
+ break;
+ }
+ }
+ }
+
+ protected static int LookAhead(char[] json, int index) {
+ int saveIndex = index;
+ return NextToken(json, ref saveIndex);
+ }
+
+ protected static int NextToken(char[] json, ref int index) {
+ EatWhitespace(json, ref index);
+
+ if (index == json.Length) {
+ return TOKEN_NONE;
+ }
+
+ char c = json[index];
+ index++;
+ switch (c) {
+ case '{':
+ return TOKEN_CURLY_OPEN;
+ case '}':
+ return TOKEN_CURLY_CLOSE;
+ case '[':
+ return TOKEN_SQUARED_OPEN;
+ case ']':
+ return TOKEN_SQUARED_CLOSE;
+ case ',':
+ return TOKEN_COMMA;
+ case '"':
+ return TOKEN_STRING;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ return TOKEN_NUMBER;
+ case ':':
+ return TOKEN_COLON;
+ }
+ index--;
+
+ int remainingLength = json.Length - index;
+
+ // false
+ if (remainingLength >= 5) {
+ if (json[index] == 'f' &&
+ json[index + 1] == 'a' &&
+ json[index + 2] == 'l' &&
+ json[index + 3] == 's' &&
+ json[index + 4] == 'e') {
+ index += 5;
+ return TOKEN_FALSE;
+ }
+ }
+
+ // true
+ if (remainingLength >= 4) {
+ if (json[index] == 't' &&
+ json[index + 1] == 'r' &&
+ json[index + 2] == 'u' &&
+ json[index + 3] == 'e') {
+ index += 4;
+ return TOKEN_TRUE;
+ }
+ }
+
+ // null
+ if (remainingLength >= 4) {
+ if (json[index] == 'n' &&
+ json[index + 1] == 'u' &&
+ json[index + 2] == 'l' &&
+ json[index + 3] == 'l') {
+ index += 4;
+ return TOKEN_NULL;
+ }
+ }
+
+ return TOKEN_NONE;
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/Language.cs b/GreenshotPlugin/Core/Language.cs
new file mode 100644
index 000000000..986623659
--- /dev/null
+++ b/GreenshotPlugin/Core/Language.cs
@@ -0,0 +1,740 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Xml;
+using Greenshot.IniFile;
+using log4net;
+using Microsoft.Win32;
+
+namespace GreenshotPlugin.Core {
+ public delegate void LanguageChangedHandler(object sender, EventArgs e);
+ ///
+ /// This class supplies the GUI with translations, based upon keys.
+ /// The language resources are loaded from the language files found on fixed or supplied paths
+ ///
+ public class Language {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Language));
+ private static readonly IList LanguagePaths = new List();
+ private static readonly IDictionary> LanguageFiles = new Dictionary>();
+ private static readonly IDictionary HelpFiles = new Dictionary();
+ private const string DefaultLanguage = "en-US";
+ private const string HelpFilenamePattern = @"help-*.html";
+ private const string LanguageFilenamePattern = @"language*.xml";
+ private static readonly Regex PrefixRegexp = new Regex(@"language_([a-zA-Z0-9]+).*");
+ private static readonly Regex IetfCleanRegexp = new Regex(@"[^a-zA-Z]+");
+ private static readonly Regex IetfRegexp = new Regex(@"^.*([a-zA-Z]{2,3}-[a-zA-Z]{1,2})\.xml$");
+ private const string LanguageGroupsKey = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups";
+ private static readonly IList UnsupportedLanguageGroups = new List();
+ private static readonly IDictionary Resources = new Dictionary();
+ private static string _currentLanguage;
+
+ public static event LanguageChangedHandler LanguageChanged;
+
+ ///
+ /// Static initializer for the language code
+ ///
+ static Language() {
+ if (!IniConfig.IsInitialized) {
+ Log.Warn("IniConfig hasn't been initialized yet! (Design mode?)");
+ IniConfig.Init("greenshot", "greenshot");
+ }
+ if (!LogHelper.IsInitialized) {
+ Log.Warn("Log4net hasn't been initialized yet! (Design mode?)");
+ LogHelper.InitializeLog4Net();
+ }
+
+ try {
+ string applicationFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+ // PAF Path
+ if (applicationFolder != null)
+ {
+ AddPath(Path.Combine(applicationFolder, @"App\Greenshot\Languages"));
+ }
+ // Application data path
+ string applicationDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ AddPath(Path.Combine(applicationDataFolder, @"Greenshot\Languages\"));
+
+ // Startup path
+ if (applicationFolder != null)
+ {
+ AddPath(Path.Combine(applicationFolder, @"Languages"));
+ }
+ }
+ catch (Exception pathException) {
+ Log.Error(pathException);
+ }
+
+ try {
+ using (RegistryKey languageGroupsKey = Registry.LocalMachine.OpenSubKey(LanguageGroupsKey, false)) {
+ if (languageGroupsKey != null) {
+ string [] groups = languageGroupsKey.GetValueNames();
+ foreach(string group in groups) {
+ string groupValue = (string)languageGroupsKey.GetValue(group);
+ bool isGroupNotInstalled = "0".Equals(groupValue);
+ if (isGroupNotInstalled) {
+ UnsupportedLanguageGroups.Add(group.ToLower());
+ }
+ }
+ }
+ }
+ } catch(Exception e) {
+ Log.Warn("Couldn't read the installed language groups.", e);
+ }
+
+ var coreConfig = IniConfig.GetIniSection();
+ ScanFiles();
+ if (!string.IsNullOrEmpty(coreConfig.Language)) {
+ CurrentLanguage = coreConfig.Language;
+ if (CurrentLanguage != null && CurrentLanguage != coreConfig.Language) {
+ coreConfig.Language = CurrentLanguage;
+ }
+ }
+
+ if (CurrentLanguage == null) {
+ Log.Warn("Couldn't set language from configuration, changing to default. Installation problem?");
+ CurrentLanguage = DefaultLanguage;
+ if (CurrentLanguage != null) {
+ coreConfig.Language = CurrentLanguage;
+ }
+ }
+
+ if (CurrentLanguage == null) {
+ Log.Error("Couldn't set language, installation problem?");
+ }
+ }
+
+ ///
+ /// Internal method to add a path to the paths that will be scanned for language files!
+ ///
+ ///
+ /// true if the path exists and is added
+ private static bool AddPath(string path) {
+ if (!LanguagePaths.Contains(path)) {
+ if (Directory.Exists(path)) {
+ Log.DebugFormat("Adding language path {0}", path);
+ LanguagePaths.Add(path);
+ return true;
+ } else {
+ Log.InfoFormat("Not adding non existing language path {0}", path);
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Add a new path to the paths that will be scanned for language files!
+ ///
+ ///
+ /// true if the path exists and is added
+ public static bool AddLanguageFilePath(string path) {
+ if (!LanguagePaths.Contains(path)) {
+ Log.DebugFormat("New language path {0}", path);
+ if (AddPath(path)) {
+ ScanFiles();
+ Reload();
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Load the files for the specified ietf
+ ///
+ ///
+ private static void LoadFiles(string ietf) {
+ ietf = ReformatIETF(ietf);
+ if (!LanguageFiles.ContainsKey(ietf)) {
+ Log.ErrorFormat("No language {0} available.", ietf);
+ return;
+ }
+ List filesToLoad = LanguageFiles[ietf];
+ foreach (LanguageFile fileToLoad in filesToLoad) {
+ LoadResources(fileToLoad);
+ }
+ }
+
+ ///
+ /// Load the language resources from the scanned files
+ ///
+ private static void Reload() {
+ Resources.Clear();
+ LoadFiles(DefaultLanguage);
+ if (_currentLanguage != null && !_currentLanguage.Equals(DefaultLanguage)) {
+ LoadFiles(_currentLanguage);
+ }
+ }
+
+ ///
+ /// Get or set the current language
+ ///
+ public static string CurrentLanguage {
+ get {
+ return _currentLanguage;
+ }
+ set {
+ string ietf = FindBestIETFMatch(value);
+ if (!LanguageFiles.ContainsKey(ietf)) {
+ Log.WarnFormat("No match for language {0} found!", ietf);
+ } else {
+ if (_currentLanguage == null || !_currentLanguage.Equals(ietf)) {
+ _currentLanguage = ietf;
+ Reload();
+ if (LanguageChanged == null)
+ {
+ return;
+ }
+ try {
+ LanguageChanged(null, null);
+ }
+ catch
+ {
+ // ignored
+ }
+ return;
+ }
+ }
+ Log.Debug("CurrentLanguage not changed!");
+ }
+ }
+
+ ///
+ /// Try to find the best match for the supplied IETF
+ ///
+ ///
+ /// IETF
+ private static string FindBestIETFMatch(string inputIETF) {
+ string returnIETF = inputIETF;
+ if (string.IsNullOrEmpty(returnIETF)) {
+ returnIETF = DefaultLanguage;
+ }
+ returnIETF = ReformatIETF(returnIETF);
+ if (!LanguageFiles.ContainsKey(returnIETF)) {
+ Log.WarnFormat("Unknown language {0}, trying best match!", returnIETF);
+ if (returnIETF.Length == 5) {
+ returnIETF = returnIETF.Substring(0, 2);
+ }
+ foreach (string availableIETF in LanguageFiles.Keys) {
+ if (availableIETF.StartsWith(returnIETF)) {
+ Log.InfoFormat("Found language {0}, best match for {1}!", availableIETF, returnIETF);
+ returnIETF = availableIETF;
+ break;
+ }
+ }
+ }
+ return returnIETF;
+ }
+
+ ///
+ /// This helper method clears all non alpha characters from the IETF, and does a reformatting.
+ /// This prevents problems with multiple formats or typos.
+ ///
+ ///
+ ///
+ private static string ReformatIETF(string inputIETF) {
+ string returnIETF = null;
+ if (!string.IsNullOrEmpty(inputIETF)) {
+ returnIETF = inputIETF.ToLower();
+ returnIETF = IetfCleanRegexp.Replace(returnIETF, "");
+ if (returnIETF.Length == 4) {
+ returnIETF = returnIETF.Substring(0, 2) + "-" + returnIETF.Substring(2, 2).ToUpper();
+ }
+ }
+ return returnIETF;
+ }
+
+ ///
+ /// Return a list of all the supported languages
+ ///
+ public static IList SupportedLanguages {
+ get {
+ IList languages = new List();
+ // Loop over all languages with all the files in there
+ foreach (List langs in LanguageFiles.Values) {
+ // Loop over all the files for a language
+ foreach (LanguageFile langFile in langs) {
+ // Only take the ones without prefix, these are the "base" language files
+ if (langFile.Prefix == null) {
+ languages.Add(langFile);
+ break;
+ }
+ }
+ }
+ return languages;
+ }
+ }
+
+ ///
+ /// Return the path to the help-file
+ ///
+ public static string HelpFilePath {
+ get {
+ if (HelpFiles.ContainsKey(_currentLanguage)) {
+ return HelpFiles[_currentLanguage];
+ }
+ return HelpFiles[DefaultLanguage];
+ }
+ }
+
+ ///
+ /// Load the resources from the language file
+ ///
+ /// File to load from
+ private static void LoadResources(LanguageFile languageFile) {
+ Log.InfoFormat("Loading language file {0}", languageFile.Filepath);
+ try {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.Load(languageFile.Filepath);
+ XmlNodeList resourceNodes = xmlDocument.GetElementsByTagName("resource");
+ foreach (XmlNode resourceNode in resourceNodes) {
+ string key = resourceNode.Attributes["name"].Value;
+ if (!string.IsNullOrEmpty(languageFile.Prefix)) {
+ key = languageFile.Prefix + "." + key;
+ }
+ string text = resourceNode.InnerText;
+ if (!string.IsNullOrEmpty(text)) {
+ text = text.Trim();
+ }
+ if (!Resources.ContainsKey(key)) {
+ Resources.Add(key, text);
+ } else {
+ Resources[key] = text;
+ }
+ }
+ } catch (Exception e) {
+ Log.Error("Could not load language file " + languageFile.Filepath, e);
+ }
+ }
+
+ ///
+ /// Load the language file information
+ ///
+ ///
+ ///
+ private static LanguageFile LoadFileInfo(string languageFilePath) {
+ try {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.Load(languageFilePath);
+ XmlNodeList nodes = xmlDocument.GetElementsByTagName("language");
+ if (nodes.Count > 0) {
+ LanguageFile languageFile = new LanguageFile
+ {
+ Filepath = languageFilePath
+ };
+ XmlNode node = nodes.Item(0);
+ if (node?.Attributes != null)
+ {
+ languageFile.Description = node.Attributes["description"].Value;
+ if (node.Attributes["ietf"] != null) {
+ languageFile.Ietf = ReformatIETF(node.Attributes["ietf"].Value);
+ }
+ if (node.Attributes["version"] != null) {
+ languageFile.Version = new Version(node.Attributes["version"].Value);
+ }
+ if (node.Attributes["prefix"] != null) {
+ languageFile.Prefix = node.Attributes["prefix"].Value.ToLower();
+ }
+ if (node.Attributes["languagegroup"] != null) {
+ string languageGroup = node.Attributes["languagegroup"].Value;
+ languageFile.LanguageGroup = languageGroup.ToLower();
+ }
+ }
+ return languageFile;
+ }
+ throw new XmlException("Root element is missing");
+ } catch (Exception e) {
+ Log.Error("Could not load language file " + languageFilePath, e);
+ }
+ return null;
+ }
+
+ ///
+ /// Scan the files in all directories
+ ///
+ private static void ScanFiles() {
+ LanguageFiles.Clear();
+ HelpFiles.Clear();
+ foreach (string languagePath in LanguagePaths) {
+ if (!Directory.Exists(languagePath)) {
+ Log.InfoFormat("Skipping non existing language path {0}", languagePath);
+ continue;
+ }
+ Log.InfoFormat("Searching language directory '{0}' for language files with pattern '{1}'", languagePath, LanguageFilenamePattern);
+ try {
+ foreach (string languageFilepath in Directory.GetFiles(languagePath, LanguageFilenamePattern, SearchOption.AllDirectories)) {
+ //LOG.DebugFormat("Found language file: {0}", languageFilepath);
+ LanguageFile languageFile = LoadFileInfo(languageFilepath);
+ if (languageFile == null) {
+ continue;
+ }
+ if (string.IsNullOrEmpty(languageFile.Ietf)) {
+ Log.WarnFormat("Fixing missing ietf in language-file {0}", languageFilepath);
+ string languageFilename = Path.GetFileName(languageFilepath);
+ if (IetfRegexp.IsMatch(languageFilename)) {
+ string replacementIETF = IetfRegexp.Replace(languageFilename, "$1");
+ languageFile.Ietf = ReformatIETF(replacementIETF);
+ Log.InfoFormat("Fixed IETF to {0}", languageFile.Ietf);
+ } else {
+ Log.ErrorFormat("Missing ietf , no recover possible... skipping language-file {0}!", languageFilepath);
+ continue;
+ }
+ }
+
+ // Check if we can display the file
+ if (!string.IsNullOrEmpty(languageFile.LanguageGroup) && UnsupportedLanguageGroups.Contains(languageFile.LanguageGroup)) {
+ Log.InfoFormat("Skipping unsuported (not able to display) language {0} from file {1}", languageFile.Description, languageFilepath);
+ continue;
+ }
+
+ // build prefix, based on the filename, but only if it's not set in the file itself.
+ if (string.IsNullOrEmpty(languageFile.Prefix)) {
+ string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath);
+ if (PrefixRegexp.IsMatch(languageFilename)) {
+ languageFile.Prefix = PrefixRegexp.Replace(languageFilename, "$1");
+ if (!string.IsNullOrEmpty(languageFile.Prefix)) {
+ languageFile.Prefix = languageFile.Prefix.Replace("plugin", "").ToLower();
+ }
+ }
+ }
+ List currentFiles = null;
+ if (LanguageFiles.ContainsKey(languageFile.Ietf)) {
+ currentFiles = LanguageFiles[languageFile.Ietf];
+ bool needToAdd = true;
+ List deleteList = new List();
+ foreach (LanguageFile compareWithLangfile in currentFiles) {
+ if ((languageFile.Prefix == null && compareWithLangfile.Prefix == null) || (languageFile.Prefix != null && languageFile.Prefix.Equals(compareWithLangfile.Prefix))) {
+ if (compareWithLangfile.Version > languageFile.Version) {
+ Log.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version);
+ needToAdd = false;
+ break;
+ } else {
+ Log.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version);
+ deleteList.Add(compareWithLangfile);
+ }
+ }
+ }
+ if (needToAdd) {
+ foreach (LanguageFile deleteFile in deleteList) {
+ currentFiles.Remove(deleteFile);
+ }
+ Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath);
+ currentFiles.Add(languageFile);
+ }
+ } else {
+ currentFiles = new List {languageFile};
+ LanguageFiles.Add(languageFile.Ietf, currentFiles);
+ Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath);
+ }
+ }
+ } catch (DirectoryNotFoundException) {
+ Log.InfoFormat("Non existing language directory: {0}", languagePath);
+ } catch (Exception e) {
+ Log.Error("Error trying for read directory " + languagePath, e);
+ }
+
+ // Now find the help files
+ Log.InfoFormat("Searching language directory '{0}' for help files with pattern '{1}'", languagePath, HelpFilenamePattern);
+ try {
+ foreach (string helpFilepath in Directory.GetFiles(languagePath, HelpFilenamePattern, SearchOption.AllDirectories)) {
+ Log.DebugFormat("Found help file: {0}", helpFilepath);
+ string helpFilename = Path.GetFileName(helpFilepath);
+ string ietf = ReformatIETF(helpFilename.Replace(".html", "").Replace("help-", ""));
+ if (!HelpFiles.ContainsKey(ietf)) {
+ HelpFiles.Add(ietf, helpFilepath);
+ } else {
+ Log.WarnFormat("skipping help file {0}, already a file with the same IETF {1} found!", helpFilepath, ietf);
+ }
+ }
+ } catch (DirectoryNotFoundException) {
+ Log.InfoFormat("Non existing language directory: {0}", languagePath);
+ } catch (Exception e) {
+ Log.Error("Error trying for read directory " + languagePath, e);
+ }
+ }
+ }
+
+ ///
+ /// Check if a resource with prefix.key exists
+ ///
+ ///
+ ///
+ /// true if available
+ public static bool HasKey(string prefix, Enum key) {
+ if (key == null) {
+ return false;
+ }
+ return HasKey(prefix + "." + key);
+ }
+
+ ///
+ /// Check if a resource with key exists
+ ///
+ ///
+ /// true if available
+ public static bool HasKey(Enum key) {
+ if (key == null) {
+ return false;
+ }
+ return HasKey(key.ToString());
+ }
+
+ ///
+ /// Check if a resource with prefix.key exists
+ ///
+ ///
+ ///
+ /// true if available
+ public static bool HasKey(string prefix, string key) {
+ return HasKey(prefix + "." + key);
+ }
+
+ ///
+ /// Check if a resource with key exists
+ ///
+ ///
+ /// true if available
+ public static bool HasKey(string key) {
+ if (key == null) {
+ return false;
+ }
+ return Resources.ContainsKey(key);
+ }
+
+ ///
+ /// TryGet method which combines HasKey & GetString
+ ///
+ ///
+ /// out string
+ ///
+ public static bool TryGetString(string key, out string languageString) {
+ return Resources.TryGetValue(key, out languageString);
+ }
+
+ ///
+ /// TryGet method which combines HasKey & GetString
+ ///
+ /// string with prefix
+ /// string with key
+ /// out string
+ ///
+ public static bool TryGetString(string prefix, string key, out string languageString) {
+ return Resources.TryGetValue(prefix + "." + key, out languageString);
+ }
+
+ ///
+ /// TryGet method which combines HasKey & GetString
+ ///
+ /// string with prefix
+ /// Enum with key
+ /// out string
+ ///
+ public static bool TryGetString(string prefix, Enum key, out string languageString)
+ {
+ return Resources.TryGetValue(prefix + "." + key, out languageString);
+ }
+
+
+ public static string Translate(object key) {
+ string typename = key.GetType().Name;
+ string enumKey = typename + "." + key;
+ if (HasKey(enumKey)) {
+ return GetString(enumKey);
+ }
+ return key.ToString();
+ }
+
+ ///
+ /// Get the resource for key
+ ///
+ ///
+ /// resource or a "string ###key### not found"
+ public static string GetString(Enum key) {
+ if (key == null) {
+ return null;
+ }
+ return GetString(key.ToString());
+ }
+
+ ///
+ /// Get the resource for prefix.key
+ ///
+ ///
+ ///
+ /// resource or a "string ###prefix.key### not found"
+ public static string GetString(string prefix, Enum key) {
+ if (key == null) {
+ return null;
+ }
+ return GetString(prefix + "." + key);
+ }
+
+ ///
+ /// Get the resource for prefix.key
+ ///
+ ///
+ ///
+ /// resource or a "string ###prefix.key### not found"
+ public static string GetString(string prefix, string key) {
+ return GetString(prefix + "." + key);
+ }
+
+ ///
+ /// Get the resource for key
+ ///
+ ///
+ /// resource or a "string ###key### not found"
+ public static string GetString(string key) {
+ if (key == null) {
+ return null;
+ }
+ string returnValue;
+ if (!Resources.TryGetValue(key, out returnValue)) {
+ return "string ###" + key + "### not found";
+ }
+ return returnValue;
+ }
+
+ ///
+ /// Get the resource for key, format with with string.format an supply the parameters
+ ///
+ ///
+ ///
+ /// formatted resource or a "string ###key### not found"
+ public static string GetFormattedString(Enum key, object param) {
+ return GetFormattedString(key.ToString(), param);
+ }
+
+ ///
+ /// Get the resource for prefix.key, format with with string.format an supply the parameters
+ ///
+ ///
+ ///
+ ///
+ /// formatted resource or a "string ###prefix.key### not found"
+ public static string GetFormattedString(string prefix, Enum key, object param) {
+ return GetFormattedString(prefix, key.ToString(), param);
+ }
+
+ ///
+ /// Get the resource for prefix.key, format with with string.format an supply the parameters
+ ///
+ ///
+ ///
+ ///
+ /// formatted resource or a "string ###prefix.key### not found"
+ public static string GetFormattedString(string prefix, string key, object param) {
+ return GetFormattedString(prefix + "." + key, param);
+ }
+
+ ///
+ /// Get the resource for key, format with with string.format an supply the parameters
+ ///
+ ///
+ ///
+ /// formatted resource or a "string ###key### not found"
+ public static string GetFormattedString(string key, object param) {
+ string returnValue;
+ if (!Resources.TryGetValue(key, out returnValue)) {
+ return "string ###" + key + "### not found";
+ }
+ return string.Format(returnValue, param);
+ }
+ }
+
+ ///
+ /// This class contains the information about a language file
+ ///
+ public class LanguageFile : IEquatable {
+ public string Description {
+ get;
+ set;
+ }
+
+ public string Ietf {
+ get;
+ set;
+ }
+
+ public Version Version {
+ get;
+ set;
+ }
+
+ public string LanguageGroup {
+ get;
+ set;
+ }
+
+ public string Filepath {
+ get;
+ set;
+ }
+
+ public string Prefix {
+ get;
+ set;
+ }
+
+ ///
+ /// Overload equals so we can delete a entry from a collection
+ ///
+ ///
+ ///
+ public bool Equals(LanguageFile other) {
+ if (Prefix != null) {
+ if (other != null && !Prefix.Equals(other.Prefix)) {
+ return false;
+ }
+ } else if (other?.Prefix != null) {
+ return false;
+ }
+ if (Ietf != null) {
+ if (other != null && !Ietf.Equals(other.Ietf)) {
+ return false;
+ }
+ } else if (other?.Ietf != null) {
+ return false;
+ }
+ if (Version != null) {
+ if (other != null && !Version.Equals(other.Version)) {
+ return false;
+ }
+ } else if (other != null && other.Version != null) {
+ return false;
+ }
+ if (Filepath != null) {
+ if (other != null && !Filepath.Equals(other.Filepath)) {
+ return false;
+ }
+ } else if (other?.Filepath != null) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+}
diff --git a/GreenshotPlugin/Core/LogHelper.cs b/GreenshotPlugin/Core/LogHelper.cs
new file mode 100644
index 000000000..8d7ab2368
--- /dev/null
+++ b/GreenshotPlugin/Core/LogHelper.cs
@@ -0,0 +1,108 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System.IO;
+using System.Reflection;
+using System.Windows.Forms;
+
+using Greenshot.IniFile;
+using log4net;
+using log4net.Appender;
+using log4net.Config;
+using log4net.Repository.Hierarchy;
+using System;
+using log4net.Util;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Initialize the logger
+ ///
+ public class LogHelper {
+ private static bool _isLog4NetConfigured;
+ private const string InitMessage = "Greenshot initialization of log system failed";
+
+ public static bool IsInitialized => _isLog4NetConfigured;
+
+ // Initialize Log4J
+ public static string InitializeLog4Net() {
+ // Setup log4j, currently the file is called log4net.xml
+ foreach (var logName in new[] { "log4net.xml" , @"App\Greenshot\log4net-portable.xml"})
+ {
+ string log4NetFilename = Path.Combine(Application.StartupPath, logName);
+ if (File.Exists(log4NetFilename))
+ {
+ try
+ {
+ XmlConfigurator.Configure(new FileInfo(log4NetFilename));
+ _isLog4NetConfigured = true;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ }
+ }
+ // Fallback
+ if (!_isLog4NetConfigured) {
+ try {
+ Assembly assembly = typeof(LogHelper).Assembly;
+ using (Stream stream = assembly.GetManifestResourceStream("GreenshotPlugin.log4net-embedded.xml")) {
+ XmlConfigurator.Configure(stream);
+ _isLog4NetConfigured = true;
+ IniConfig.ForceIniInStartupPath();
+ }
+ } catch (Exception ex){
+ MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ }
+
+ if (_isLog4NetConfigured) {
+ // Get the logfile name
+ try {
+ if (((Hierarchy)LogManager.GetRepository()).Root.Appenders.Count > 0) {
+ foreach (IAppender appender in ((Hierarchy)LogManager.GetRepository()).Root.Appenders)
+ {
+ var fileAppender = appender as FileAppender;
+ if (fileAppender != null) {
+ return fileAppender.File;
+ }
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// A simple helper class to support the logging to the AppData location
+ ///
+ public class SpecialFolderPatternConverter : PatternConverter {
+ protected override void Convert(TextWriter writer, object state) {
+ Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), Option, true);
+ writer.Write(Environment.GetFolderPath(specialFolder));
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs
new file mode 100644
index 000000000..d8874cc65
--- /dev/null
+++ b/GreenshotPlugin/Core/NetworkHelper.cs
@@ -0,0 +1,801 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using Greenshot.IniFile;
+using Greenshot.Plugin;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// HTTP Method to make sure we have the correct method
+ ///
+ public enum HTTPMethod {
+ GET,
+ POST,
+ PUT,
+ DELETE,
+ HEAD
+ };
+
+ ///
+ /// Description of NetworkHelper.
+ ///
+ public static class NetworkHelper {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper));
+ private static readonly CoreConfiguration Config = IniConfig.GetIniSection();
+
+ static NetworkHelper() {
+ try
+ {
+ // Disable certificate checking
+ ServicePointManager.ServerCertificateValidationCallback += delegate {
+ return true;
+ };
+ }
+ catch (Exception ex)
+ {
+ Log.Warn("An error has occured while allowing self-signed certificates:", ex);
+ }
+ }
+
+ ///
+ /// Download a uri response as string
+ ///
+ /// An Uri to specify the download location
+ /// string with the file content
+ public static string GetAsString(Uri uri) {
+ return GetResponseAsString(CreateWebRequest(uri));
+ }
+
+ ///
+ /// Download the FavIcon as a Bitmap
+ ///
+ ///
+ /// Bitmap with the FavIcon
+ public static Bitmap DownloadFavIcon(Uri baseUri) {
+ Uri url = new Uri(baseUri, new Uri("favicon.ico"));
+ try {
+ HttpWebRequest request = CreateWebRequest(url);
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ {
+ if (request.HaveResponse)
+ {
+ using (Stream responseStream = response.GetResponseStream())
+ {
+ if (responseStream != null)
+ {
+ using (Image image = ImageHelper.FromStream(responseStream))
+ {
+ return image.Height > 16 && image.Width > 16 ? new Bitmap(image, 16, 16) : new Bitmap(image);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.Error("Problem downloading the FavIcon from: " + baseUri, e);
+ }
+ return null;
+ }
+
+ ///
+ /// Download the uri into a memorystream, without catching exceptions
+ ///
+ /// Of an image
+ /// MemoryStream which is already seeked to 0
+ public static MemoryStream GetAsMemoryStream(string url) {
+ HttpWebRequest request = CreateWebRequest(url);
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
+ MemoryStream memoryStream = new MemoryStream();
+ using (Stream responseStream = response.GetResponseStream()) {
+ responseStream?.CopyTo(memoryStream);
+ // Make sure it can be used directly
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ }
+ return memoryStream;
+ }
+ }
+
+ ///
+ /// Download the uri to Bitmap
+ ///
+ /// Of an image
+ /// Bitmap
+ public static Image DownloadImage(string url)
+ {
+ StringBuilder extensions = new StringBuilder();
+ foreach (var extension in ImageHelper.StreamConverters.Keys)
+ {
+ if (string.IsNullOrEmpty(extension))
+ {
+ continue;
+ }
+ extensions.AppendFormat(@"\.{0}|", extension);
+ }
+ extensions.Length--;
+
+ var imageUrlRegex = new Regex($@"(http|https)://.*(?{extensions})");
+ var match = imageUrlRegex.Match(url);
+ try
+ {
+ using (var memoryStream = GetAsMemoryStream(url))
+ {
+ try
+ {
+ return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null);
+ }
+ catch (Exception)
+ {
+ // If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
+ string content;
+ using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
+ {
+ content = streamReader.ReadLine();
+ }
+ if (string.IsNullOrEmpty(content))
+ {
+ throw;
+ }
+ match = imageUrlRegex.Match(content);
+ if (!match.Success)
+ {
+ throw;
+ }
+ using (var memoryStream2 = GetAsMemoryStream(match.Value))
+ {
+ return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error("Problem downloading the image from: " + url, e);
+ }
+ return null;
+ }
+
+ ///
+ /// Helper method to create a web request with a lot of default settings
+ ///
+ /// string with uri to connect to
+ /// WebRequest
+ public static HttpWebRequest CreateWebRequest(string uri) {
+ return CreateWebRequest(new Uri(uri));
+ }
+
+ ///
+ /// Helper method to create a web request with a lot of default settings
+ ///
+ /// string with uri to connect to
+ /// /// Method to use
+ /// WebRequest
+ public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) {
+ return CreateWebRequest(new Uri(uri), method);
+ }
+
+ ///
+ /// Helper method to create a web request with a lot of default settings
+ ///
+ /// Uri with uri to connect to
+ /// Method to use
+ /// WebRequest
+ public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) {
+ HttpWebRequest webRequest = CreateWebRequest(uri);
+ webRequest.Method = method.ToString();
+ return webRequest;
+ }
+
+ ///
+ /// Helper method to create a web request, eventually with proxy
+ ///
+ /// Uri with uri to connect to
+ /// WebRequest
+ public static HttpWebRequest CreateWebRequest(Uri uri) {
+ HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
+ webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null;
+ // Make sure the default credentials are available
+ webRequest.Credentials = CredentialCache.DefaultCredentials;
+
+ // Allow redirect, this is usually needed so that we don't get a problem when a service moves
+ webRequest.AllowAutoRedirect = true;
+ // Set default timeouts
+ webRequest.Timeout = Config.WebRequestTimeout*1000;
+ webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout*1000;
+ return webRequest;
+ }
+
+ ///
+ /// Create a IWebProxy Object which can be used to access the Internet
+ /// This method will check the configuration if the proxy is allowed to be used.
+ /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins
+ ///
+ ///
+ /// IWebProxy filled with all the proxy details or null if none is set/wanted
+ public static IWebProxy CreateProxy(Uri uri) {
+ IWebProxy proxyToUse = null;
+ if (Config.UseProxy) {
+ proxyToUse = WebRequest.DefaultWebProxy;
+ if (proxyToUse != null) {
+ proxyToUse.Credentials = CredentialCache.DefaultCredentials;
+ if (Log.IsDebugEnabled) {
+ // check the proxy for the Uri
+ if (!proxyToUse.IsBypassed(uri)) {
+ Uri proxyUri = proxyToUse.GetProxy(uri);
+ if (proxyUri != null) {
+ Log.Debug("Using proxy: " + proxyUri + " for " + uri);
+ } else {
+ Log.Debug("No proxy found!");
+ }
+ } else {
+ Log.Debug("Proxy bypass for: " + uri);
+ }
+ }
+ } else {
+ Log.Debug("No proxy found!");
+ }
+ }
+ return proxyToUse;
+ }
+
+ ///
+ /// UrlEncodes a string without the requirement for System.Web
+ ///
+ ///
+ ///
+ // [Obsolete("Use System.Uri.EscapeDataString instead")]
+ public static string UrlEncode(string text) {
+ if (!string.IsNullOrEmpty(text)) {
+ // Sytem.Uri provides reliable parsing, but doesn't encode spaces.
+ return Uri.EscapeDataString(text).Replace("%20", "+");
+ }
+ return null;
+ }
+
+ ///
+ /// A wrapper around the EscapeDataString, as the limit is 32766 characters
+ /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
+ ///
+ ///
+ /// escaped data string
+ public static string EscapeDataString(string text) {
+ if (!string.IsNullOrEmpty(text)) {
+ StringBuilder result = new StringBuilder();
+ int currentLocation = 0;
+ while (currentLocation < text.Length) {
+ string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
+ result.Append(Uri.EscapeDataString(process));
+ currentLocation = currentLocation + 16384;
+ }
+ return result.ToString();
+ }
+ return null;
+ }
+
+ ///
+ /// UrlDecodes a string without requiring System.Web
+ ///
+ /// String to decode.
+ /// decoded string
+ public static string UrlDecode(string text) {
+ // pre-process for + sign space formatting since System.Uri doesn't handle it
+ // plus literals are encoded as %2b normally so this should be safe
+ text = text.Replace("+", " ");
+ return Uri.UnescapeDataString(text);
+ }
+
+ ///
+ /// ParseQueryString without the requirement for System.Web
+ ///
+ ///
+ /// IDictionary string, string
+ public static IDictionary ParseQueryString(string queryString) {
+ IDictionary parameters = new SortedDictionary();
+ // remove anything other than query string from uri
+ if (queryString.Contains("?")) {
+ queryString = queryString.Substring(queryString.IndexOf('?') + 1);
+ }
+ foreach (string vp in Regex.Split(queryString, "&")) {
+ if (string.IsNullOrEmpty(vp)) {
+ continue;
+ }
+ string[] singlePair = Regex.Split(vp, "=");
+ if (parameters.ContainsKey(singlePair[0])) {
+ parameters.Remove(singlePair[0]);
+ }
+ parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty);
+ }
+ return parameters;
+ }
+
+ ///
+ /// Generate the query paramters
+ ///
+ /// the list of query parameters
+ /// a string with the query parameters
+ public static string GenerateQueryParameters(IDictionary queryParameters) {
+ if (queryParameters == null || queryParameters.Count == 0) {
+ return string.Empty;
+ }
+
+ queryParameters = new SortedDictionary(queryParameters);
+
+ StringBuilder sb = new StringBuilder();
+ foreach(string key in queryParameters.Keys) {
+ sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}"));
+ }
+ sb.Remove(sb.Length-1,1);
+
+ return sb.ToString();
+ }
+
+ ///
+ /// Write Multipart Form Data directly to the HttpWebRequest
+ ///
+ /// HttpWebRequest to write the multipart form data to
+ /// Parameters to include in the multipart form data
+ public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) {
+ string boundary = $"----------{Guid.NewGuid():N}";
+ webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
+ using (Stream formDataStream = webRequest.GetRequestStream()) {
+ WriteMultipartFormData(formDataStream, boundary, postParameters);
+ }
+ }
+
+ ///
+ /// Write Multipart Form Data to the HttpListenerResponse
+ ///
+ /// HttpListenerResponse
+ /// Parameters to include in the multipart form data
+ public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary postParameters) {
+ string boundary = $"----------{Guid.NewGuid():N}";
+ response.ContentType = "multipart/form-data; boundary=" + boundary;
+ WriteMultipartFormData(response.OutputStream, boundary, postParameters);
+ }
+
+ ///
+ /// Write Multipart Form Data to a Stream, content-type should be set before this!
+ ///
+ /// Stream to write the multipart form data to
+ /// String boundary for the multipart/form-data
+ /// Parameters to include in the multipart form data
+ public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) {
+ bool needsClrf = false;
+ foreach (var param in postParameters) {
+ // Add a CRLF to allow multiple parameters to be added.
+ // Skip it on the first parameter, add it to subsequent parameters.
+ if (needsClrf) {
+ formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n"));
+ }
+
+ needsClrf = true;
+
+ var binaryContainer = param.Value as IBinaryContainer;
+ if (binaryContainer != null) {
+ binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream);
+ } else {
+ string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}";
+ formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
+ }
+ }
+
+ // Add the end of the request. Start with a newline
+ string footer = "\r\n--" + boundary + "--\r\n";
+ formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
+ }
+
+ ///
+ /// Post the parameters "x-www-form-urlencoded"
+ ///
+ ///
+ ///
+ public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) {
+ webRequest.ContentType = "application/x-www-form-urlencoded";
+ string urlEncoded = GenerateQueryParameters(parameters);
+
+ byte[] data = Encoding.UTF8.GetBytes(urlEncoded);
+ using (var requestStream = webRequest.GetRequestStream()) {
+ requestStream.Write(data, 0, data.Length);
+ }
+ }
+
+ ///
+ /// Log the headers of the WebResponse, if IsDebugEnabled
+ ///
+ /// WebResponse
+ private static void DebugHeaders(WebResponse response) {
+ if (!Log.IsDebugEnabled) {
+ return;
+ }
+ Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri);
+ foreach (string key in response.Headers.AllKeys) {
+ Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]);
+ }
+ }
+
+ ///
+ /// Process the web response.
+ ///
+ /// The request object.
+ /// The response data.
+ /// TODO: This method should handle the StatusCode better!
+ public static string GetResponseAsString(HttpWebRequest webRequest) {
+ return GetResponseAsString(webRequest, false);
+ }
+
+ ///
+ /// Read the response as string
+ ///
+ ///
+ /// string or null
+ private static string GetResponseAsString(HttpWebResponse response)
+ {
+ string responseData = null;
+ if (response == null)
+ {
+ return null;
+ }
+ using (response)
+ {
+ Stream responseStream = response.GetResponseStream();
+ if (responseStream != null)
+ {
+ using (StreamReader reader = new StreamReader(responseStream, true))
+ {
+ responseData = reader.ReadToEnd();
+ }
+ }
+ }
+ return responseData;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) {
+ string responseData = null;
+ HttpWebResponse response = null;
+ bool isHttpError = false;
+ try {
+ response = (HttpWebResponse)webRequest.GetResponse();
+ Log.InfoFormat("Response status: {0}", response.StatusCode);
+ isHttpError = (int)response.StatusCode >= 300;
+ if (isHttpError)
+ {
+ Log.ErrorFormat("HTTP error {0}", response.StatusCode);
+ }
+ DebugHeaders(response);
+ responseData = GetResponseAsString(response);
+ if (isHttpError)
+ {
+ Log.ErrorFormat("HTTP response {0}", responseData);
+ }
+ }
+ catch (WebException e) {
+ response = (HttpWebResponse) e.Response;
+ HttpStatusCode statusCode = HttpStatusCode.Unused;
+ if (response != null) {
+ statusCode = response.StatusCode;
+ Log.ErrorFormat("HTTP error {0}", statusCode);
+ string errorContent = GetResponseAsString(response);
+ if (alsoReturnContentOnError)
+ {
+ return errorContent;
+ }
+ Log.ErrorFormat("Content: {0}", errorContent);
+ }
+ Log.Error("WebException: ", e);
+ if (statusCode == HttpStatusCode.Unauthorized)
+ {
+ throw new UnauthorizedAccessException(e.Message);
+ }
+ throw;
+ }
+ finally
+ {
+ if (response != null)
+ {
+ if (isHttpError)
+ {
+ Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData);
+ }
+ response.Close();
+ }
+ }
+ return responseData;
+ }
+
+ ///
+ /// Get LastModified for a URI
+ ///
+ /// Uri
+ /// DateTime
+ public static DateTime GetLastModified(Uri uri) {
+ try {
+ HttpWebRequest webRequest = CreateWebRequest(uri);
+ webRequest.Method = HTTPMethod.HEAD.ToString();
+ using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
+ {
+ Log.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
+ return webResponse.LastModified;
+ }
+ } catch (Exception wE) {
+ Log.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri);
+ Log.Warn(wE.Message);
+ // Pretend it is old
+ return DateTime.MinValue;
+ }
+ }
+ }
+
+ ///
+ /// This interface can be used to pass binary information around, like byte[] or Image
+ ///
+ public interface IBinaryContainer {
+ void WriteFormDataToStream(string boundary, string name, Stream formDataStream);
+ void WriteToStream(Stream formDataStream);
+ string ToBase64String(Base64FormattingOptions formattingOptions);
+ byte[] ToByteArray();
+ void Upload(HttpWebRequest webRequest);
+
+ string ContentType { get; }
+ string Filename { get; set; }
+ }
+
+ ///
+ /// A container to supply files to a Multi-part form data upload
+ ///
+ public class ByteContainer : IBinaryContainer {
+ private readonly byte[] _file;
+ private readonly string _contentType;
+ private readonly int _fileSize;
+ public ByteContainer(byte[] file) : this(file, null) {
+ }
+ public ByteContainer(byte[] file, string filename) : this(file, filename, null) {
+ }
+ public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) {
+ }
+ public ByteContainer(byte[] file, string filename, string contenttype, int filesize) {
+ _file = file;
+ Filename = filename;
+ _contentType = contenttype;
+ _fileSize = filesize == 0 ? file.Length : filesize;
+ }
+
+ ///
+ /// Create a Base64String from the byte[]
+ ///
+ /// string
+ public string ToBase64String(Base64FormattingOptions formattingOptions) {
+ return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions);
+ }
+
+ ///
+ /// Returns the initial byte-array which was supplied when creating the FileParameter
+ ///
+ /// byte[]
+ public byte[] ToByteArray() {
+ return _file;
+ }
+
+ ///
+ /// Write Multipart Form Data directly to the HttpWebRequest response stream
+ ///
+ /// Separator
+ /// name
+ /// Stream to write to
+ public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) {
+ // Add just the first part of this param, since we will write the file data directly to the Stream
+ string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {_contentType ?? "application/octet-stream"}\r\n\r\n";
+
+ formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
+
+ // Write the file data directly to the Stream, rather than serializing it to a string.
+ formDataStream.Write(_file, 0, _fileSize);
+ }
+
+ ///
+ /// A plain "write data to stream"
+ ///
+ /// Stream to write to
+ public void WriteToStream(Stream dataStream) {
+ // Write the file data directly to the Stream, rather than serializing it to a string.
+ dataStream.Write(_file, 0, _fileSize);
+ }
+
+ ///
+ /// Upload the file to the webrequest
+ ///
+ ///
+ public void Upload(HttpWebRequest webRequest) {
+ webRequest.ContentType = _contentType;
+ webRequest.ContentLength = _fileSize;
+ using (var requestStream = webRequest.GetRequestStream()) {
+ WriteToStream(requestStream);
+ }
+ }
+
+ public string ContentType => _contentType;
+ public string Filename { get; set; }
+ }
+
+ ///
+ /// A container to supply images to a Multi-part form data upload
+ ///
+ public class BitmapContainer : IBinaryContainer {
+ private readonly Bitmap _bitmap;
+ private readonly SurfaceOutputSettings _outputSettings;
+
+ public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) {
+ _bitmap = bitmap;
+ _outputSettings = outputSettings;
+ Filename = filename;
+ }
+
+ ///
+ /// Create a Base64String from the image by saving it to a memory stream and converting it.
+ /// Should be avoided if possible, as this uses a lot of memory.
+ ///
+ /// string
+ public string ToBase64String(Base64FormattingOptions formattingOptions) {
+ using (MemoryStream stream = new MemoryStream()) {
+ ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
+ return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
+ }
+ }
+
+ ///
+ /// Create a byte[] from the image by saving it to a memory stream.
+ /// Should be avoided if possible, as this uses a lot of memory.
+ ///
+ /// byte[]
+ public byte[] ToByteArray() {
+ using (MemoryStream stream = new MemoryStream()) {
+ ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
+ return stream.ToArray();
+ }
+ }
+
+ ///
+ /// Write Multipart Form Data directly to the HttpWebRequest response stream
+ ///
+ /// Separator
+ /// Name of the thing/file
+ /// Stream to write to
+ public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) {
+ // Add just the first part of this param, since we will write the file data directly to the Stream
+ string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
+
+ formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
+ ImageOutput.SaveToStream(_bitmap, null, formDataStream, _outputSettings);
+ }
+
+ ///
+ /// A plain "write data to stream"
+ ///
+ ///
+ public void WriteToStream(Stream dataStream) {
+ // Write the file data directly to the Stream, rather than serializing it to a string.
+ ImageOutput.SaveToStream(_bitmap, null, dataStream, _outputSettings);
+ }
+
+ ///
+ /// Upload the image to the webrequest
+ ///
+ ///
+ public void Upload(HttpWebRequest webRequest) {
+ webRequest.ContentType = "image/" + _outputSettings.Format;
+ using (var requestStream = webRequest.GetRequestStream()) {
+ WriteToStream(requestStream);
+ }
+ }
+
+ public string ContentType => "image/" + _outputSettings.Format;
+
+ public string Filename { get; set; }
+ }
+
+ ///
+ /// A container to supply surfaces to a Multi-part form data upload
+ ///
+ public class SurfaceContainer : IBinaryContainer {
+ private readonly ISurface _surface;
+ private readonly SurfaceOutputSettings _outputSettings;
+
+ public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) {
+ _surface = surface;
+ _outputSettings = outputSettings;
+ Filename = filename;
+ }
+
+ ///
+ /// Create a Base64String from the Surface by saving it to a memory stream and converting it.
+ /// Should be avoided if possible, as this uses a lot of memory.
+ ///
+ /// string
+ public string ToBase64String(Base64FormattingOptions formattingOptions) {
+ using (MemoryStream stream = new MemoryStream()) {
+ ImageOutput.SaveToStream(_surface, stream, _outputSettings);
+ return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
+ }
+ }
+
+ ///
+ /// Create a byte[] from the image by saving it to a memory stream.
+ /// Should be avoided if possible, as this uses a lot of memory.
+ ///
+ /// byte[]
+ public byte[] ToByteArray() {
+ using (MemoryStream stream = new MemoryStream()) {
+ ImageOutput.SaveToStream(_surface, stream, _outputSettings);
+ return stream.ToArray();
+ }
+ }
+
+ ///
+ /// Write Multipart Form Data directly to the HttpWebRequest response stream
+ ///
+ /// Multipart separator
+ /// Name of the thing
+ /// Stream to write to
+ public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) {
+ // Add just the first part of this param, since we will write the file data directly to the Stream
+ string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
+
+ formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
+ ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings);
+ }
+
+ ///
+ /// A plain "write data to stream"
+ ///
+ ///
+ public void WriteToStream(Stream dataStream) {
+ // Write the file data directly to the Stream, rather than serializing it to a string.
+ ImageOutput.SaveToStream(_surface, dataStream, _outputSettings);
+ }
+
+ ///
+ /// Upload the Surface as image to the webrequest
+ ///
+ ///
+ public void Upload(HttpWebRequest webRequest) {
+ webRequest.ContentType = ContentType;
+ using (var requestStream = webRequest.GetRequestStream()) {
+ WriteToStream(requestStream);
+ }
+ }
+
+ public string ContentType => "image/" + _outputSettings.Format;
+ public string Filename { get; set; }
+ }
+}
diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs
new file mode 100644
index 000000000..eb0f90353
--- /dev/null
+++ b/GreenshotPlugin/Core/OAuthHelper.cs
@@ -0,0 +1,1248 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using GreenshotPlugin.Controls;
+using log4net;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Drawing;
+using System.Globalization;
+using System.Net;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol
+ ///
+ public enum OAuthSignatureTypes {
+ HMACSHA1,
+ PLAINTEXT,
+ }
+
+ ///
+ /// Specify the autorize mode that is used to get the token from the cloud service.
+ ///
+ public enum OAuth2AuthorizeMode {
+ Unknown, // Will give an exception, caller needs to specify another value
+ LocalServer, // Will specify a redirect URL to http://localhost:port/authorize, while having a HttpListener
+ MonitorTitle, // Not implemented yet: Will monitor for title changes
+ Pin, // Not implemented yet: Will ask the user to enter the shown PIN
+ EmbeddedBrowser // Will open into an embedded _browser (OAuthLoginForm), and catch the redirect
+ }
+
+ ///
+ /// Settings for the OAuth 2 protocol
+ ///
+ public class OAuth2Settings {
+ public OAuth2Settings() {
+ AdditionalAttributes = new Dictionary();
+ // Create a default state
+ State = Guid.NewGuid().ToString();
+ AuthorizeMode = OAuth2AuthorizeMode.Unknown;
+ }
+
+ public OAuth2AuthorizeMode AuthorizeMode {
+ get;
+ set;
+ }
+
+ ///
+ /// Specify the name of the cloud service, so it can be used in window titles, logs etc
+ ///
+ public string CloudServiceName {
+ get;
+ set;
+ }
+
+ ///
+ /// Specify the size of the embedded Browser, if using this
+ ///
+ public Size BrowserSize {
+ get;
+ set;
+ }
+
+ ///
+ /// The OAuth 2 client id
+ ///
+ public string ClientId {
+ get;
+ set;
+ }
+
+ ///
+ /// The OAuth 2 client secret
+ ///
+ public string ClientSecret {
+ get;
+ set;
+ }
+
+ ///
+ /// The OAuth 2 state, this is something that is passed to the server, is not processed but returned back to the client.
+ /// e.g. a correlation ID
+ /// Default this is filled with a new Guid
+ ///
+ public string State {
+ get;
+ set;
+ }
+
+ ///
+ /// The autorization URL where the values of this class can be "injected"
+ ///
+ public string AuthUrlPattern {
+ get;
+ set;
+ }
+
+ ///
+ /// Get formatted Auth url (this will call a FormatWith(this) on the AuthUrlPattern
+ ///
+ public string FormattedAuthUrl => AuthUrlPattern.FormatWith(this);
+
+ ///
+ /// The URL to get a Token
+ ///
+ public string TokenUrl {
+ get;
+ set;
+ }
+
+ ///
+ /// This is the redirect URL, in some implementations this is automatically set (LocalServerCodeReceiver)
+ /// In some implementations this could be e.g. urn:ietf:wg:oauth:2.0:oob or urn:ietf:wg:oauth:2.0:oob:auto
+ ///
+ public string RedirectUrl {
+ get;
+ set;
+ }
+
+ ///
+ /// Bearer token for accessing OAuth 2 services
+ ///
+ public string AccessToken {
+ get;
+ set;
+ }
+
+ ///
+ /// Expire time for the AccessToken, this this time (-60 seconds) is passed a new AccessToken needs to be generated with the RefreshToken
+ ///
+ public DateTimeOffset AccessTokenExpires {
+ get;
+ set;
+ }
+
+ ///
+ /// Return true if the access token is expired.
+ /// Important "side-effect": if true is returned the AccessToken will be set to null!
+ ///
+ public bool IsAccessTokenExpired {
+ get {
+ bool expired = true;
+ if (!string.IsNullOrEmpty(AccessToken)) {
+ expired = DateTimeOffset.Now.AddSeconds(60) > AccessTokenExpires;
+ }
+ // Make sure the token is not usable
+ if (expired) {
+ AccessToken = null;
+ }
+ return expired;
+ }
+ }
+
+ ///
+ /// Token used to get a new Access Token
+ ///
+ public string RefreshToken {
+ get;
+ set;
+ }
+
+ ///
+ /// Put anything in here which is needed for the OAuth 2 implementation of this specific service but isn't generic, e.g. for Google there is a "scope"
+ ///
+ public IDictionary AdditionalAttributes {
+ get;
+ set;
+ }
+
+ ///
+ /// This contains the code returned from the authorization, but only shortly after it was received.
+ /// It will be cleared as soon as it was used.
+ ///
+ public string Code {
+ get;
+ set;
+ }
+ }
+
+ ///
+ /// An OAuth 1 session object
+ ///
+ public class OAuthSession {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(OAuthSession));
+ protected const string OAUTH_VERSION = "1.0";
+ protected const string OAUTH_PARAMETER_PREFIX = "oauth_";
+
+ //
+ // List of know and used oauth parameters' names
+ //
+ protected const string OAUTH_CONSUMER_KEY_KEY = "oauth_consumer_key";
+ protected const string OAUTH_CALLBACK_KEY = "oauth_callback";
+ protected const string OAUTH_VERSION_KEY = "oauth_version";
+ protected const string OAUTH_SIGNATURE_METHOD_KEY = "oauth_signature_method";
+ protected const string OAUTH_TIMESTAMP_KEY = "oauth_timestamp";
+ protected const string OAUTH_NONCE_KEY = "oauth_nonce";
+ protected const string OAUTH_TOKEN_KEY = "oauth_token";
+ protected const string OAUTH_VERIFIER_KEY = "oauth_verifier";
+ protected const string OAUTH_TOKEN_SECRET_KEY = "oauth_token_secret";
+ protected const string OAUTH_SIGNATURE_KEY = "oauth_signature";
+
+ protected const string HMACSHA1SignatureType = "HMAC-SHA1";
+ protected const string PlainTextSignatureType = "PLAINTEXT";
+
+ protected static Random random = new Random();
+
+ protected const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
+
+ private string _userAgent = "Greenshot";
+ private IDictionary _requestTokenResponseParameters;
+
+ public IDictionary RequestTokenParameters { get; } = new Dictionary();
+
+ ///
+ /// Parameters of the last called getAccessToken
+ ///
+ public IDictionary AccessTokenResponseParameters { get; private set; }
+
+ ///
+ /// Parameters of the last called getRequestToken
+ ///
+ public IDictionary RequestTokenResponseParameters => _requestTokenResponseParameters;
+
+ private readonly string _consumerKey;
+ private readonly string _consumerSecret;
+
+ // default _browser size
+
+ #region PublicProperties
+ public HTTPMethod RequestTokenMethod {
+ get;
+ set;
+ }
+ public HTTPMethod AccessTokenMethod {
+ get;
+ set;
+ }
+ public string RequestTokenUrl {
+ get;
+ set;
+ }
+ public string AuthorizeUrl {
+ get;
+ set;
+ }
+ public string AccessTokenUrl {
+ get;
+ set;
+ }
+ public string Token {
+ get;
+ set;
+ }
+ public string TokenSecret {
+ get;
+ set;
+ }
+ public string Verifier {
+ get;
+ set;
+ }
+ public OAuthSignatureTypes SignatureType {
+ get;
+ set;
+ }
+
+ public bool UseMultipartFormData { get; set; }
+ public string UserAgent {
+ get {
+ return _userAgent;
+ }
+ set {
+ _userAgent = value;
+ }
+ }
+ public string CallbackUrl { get; set; } = "http://getgreenshot.org";
+
+ public bool CheckVerifier { get; set; } = true;
+
+ public Size BrowserSize { get; set; } = new Size(864, 587);
+
+ public string LoginTitle { get; set; } = "Authorize Greenshot access";
+
+ public bool UseHttpHeadersForAuthorization { get; set; } = true;
+
+ public bool AutoLogin {
+ get;
+ set;
+ }
+
+ #endregion
+
+ ///
+ /// Create an OAuthSession with the consumerKey / consumerSecret
+ ///
+ /// "Public" key for the encoding. When using RSASHA1 this is the path to the private key file
+ /// "Private" key for the encoding. when usin RSASHA1 this is the password for the private key file
+ public OAuthSession(string consumerKey, string consumerSecret) {
+ _consumerKey = consumerKey;
+ _consumerSecret = consumerSecret;
+ UseMultipartFormData = true;
+ RequestTokenMethod = HTTPMethod.GET;
+ AccessTokenMethod = HTTPMethod.GET;
+ SignatureType = OAuthSignatureTypes.HMACSHA1;
+ AutoLogin = true;
+ }
+
+ ///
+ /// Helper function to compute a hash value
+ ///
+ /// The hashing algorithm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function
+ /// The data to hash
+ /// a Base64 string of the hash value
+ private static string ComputeHash(HashAlgorithm hashAlgorithm, string data) {
+ if (hashAlgorithm == null) {
+ throw new ArgumentNullException(nameof(hashAlgorithm));
+ }
+
+ if (string.IsNullOrEmpty(data)) {
+ throw new ArgumentNullException(nameof(data));
+ }
+
+ byte[] dataBuffer = Encoding.UTF8.GetBytes(data);
+ byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
+
+ return Convert.ToBase64String(hashBytes);
+ }
+
+ ///
+ /// Generate the normalized paramter string
+ ///
+ /// the list of query parameters
+ /// a string with the normalized query parameters
+ private static string GenerateNormalizedParametersString(IDictionary queryParameters) {
+ if (queryParameters == null || queryParameters.Count == 0) {
+ return string.Empty;
+ }
+
+ queryParameters = new SortedDictionary(queryParameters);
+
+ StringBuilder sb = new StringBuilder();
+ foreach (string key in queryParameters.Keys) {
+ if (queryParameters[key] is string) {
+ sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode3986($"{queryParameters[key]}"));
+ }
+ }
+ sb.Remove(sb.Length - 1, 1);
+
+ return sb.ToString();
+ }
+
+ ///
+ /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
+ /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
+ /// The resulting string is for UTF-8 encoding!
+ ///
+ /// The value to Url encode
+ /// Returns a Url encoded string (unicode) with UTF-8 encoded % values
+ public static string UrlEncode3986(string value) {
+ StringBuilder result = new StringBuilder();
+
+ foreach (char symbol in value) {
+ if (UnreservedChars.IndexOf(symbol) != -1) {
+ result.Append(symbol);
+ } else {
+ byte[] utf8Bytes = Encoding.UTF8.GetBytes(symbol.ToString());
+ foreach(byte utf8Byte in utf8Bytes) {
+ result.AppendFormat("%{0:X2}", utf8Byte);
+ }
+ }
+ }
+
+ return result.ToString();
+ }
+
+ ///
+ /// Generate the timestamp for the signature
+ ///
+ ///
+ public static string GenerateTimeStamp() {
+ // Default implementation of UNIX time of the current UTC time
+ TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ return Convert.ToInt64(ts.TotalSeconds).ToString();
+ }
+
+ ///
+ /// Generate a nonce
+ ///
+ ///
+ public static string GenerateNonce() {
+ // Just a simple implementation of a random number between 123400 and 9999999
+ return random.Next(123400, 9999999).ToString();
+ }
+
+ ///
+ /// Get the request token using the consumer key and secret. Also initializes tokensecret
+ ///
+ /// response, this doesn't need to be used!!
+ private string GetRequestToken() {
+ IDictionary parameters = new Dictionary();
+ foreach(var value in RequestTokenParameters) {
+ parameters.Add(value);
+ }
+ Sign(RequestTokenMethod, RequestTokenUrl, parameters);
+ string response = MakeRequest(RequestTokenMethod, RequestTokenUrl, null, parameters, null);
+ if (!string.IsNullOrEmpty(response)) {
+ response = NetworkHelper.UrlDecode(response);
+ Log.DebugFormat("Request token response: {0}", response);
+ _requestTokenResponseParameters = NetworkHelper.ParseQueryString(response);
+ string value;
+ if (_requestTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out value)) {
+ Token = value;
+ TokenSecret = _requestTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY];
+ }
+ }
+ return response;
+ }
+
+ ///
+ /// Authorize the token by showing the dialog
+ ///
+ /// Pass the response from the server's request token, so if there is something wrong we can show it.
+ /// The request token.
+ private string GetAuthorizeToken(string requestTokenResponse) {
+ if (string.IsNullOrEmpty(Token)) {
+ Exception e = new Exception("The request token is not set, service responded with: " + requestTokenResponse);
+ throw e;
+ }
+ Log.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink);
+ OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl);
+ oAuthLoginForm.ShowDialog();
+ if (oAuthLoginForm.IsOk) {
+ if (oAuthLoginForm.CallbackParameters != null) {
+ string tokenValue;
+ if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out tokenValue)) {
+ Token = tokenValue;
+ }
+ string verifierValue;
+ if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_VERIFIER_KEY, out verifierValue)) {
+ Verifier = verifierValue;
+ }
+ }
+ }
+ if (CheckVerifier) {
+ if (!string.IsNullOrEmpty(Verifier)) {
+ return Token;
+ }
+ return null;
+ }
+ return Token;
+ }
+
+ ///
+ /// Get the access token
+ ///
+ /// The access token.
+ private string GetAccessToken() {
+ if (string.IsNullOrEmpty(Token) || (CheckVerifier && string.IsNullOrEmpty(Verifier))) {
+ Exception e = new Exception("The request token and verifier were not set");
+ throw e;
+ }
+
+ IDictionary parameters = new Dictionary();
+ Sign(AccessTokenMethod, AccessTokenUrl, parameters);
+ string response = MakeRequest(AccessTokenMethod, AccessTokenUrl, null, parameters, null);
+ if (!string.IsNullOrEmpty(response)) {
+ response = NetworkHelper.UrlDecode(response);
+ Log.DebugFormat("Access token response: {0}", response);
+ AccessTokenResponseParameters = NetworkHelper.ParseQueryString(response);
+ string tokenValue;
+ if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out tokenValue) && tokenValue != null) {
+ Token = tokenValue;
+ }
+ string secretValue;
+ if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_SECRET_KEY, out secretValue) && secretValue != null) {
+ TokenSecret = secretValue;
+ }
+ }
+
+ return Token;
+ }
+
+ ///
+ /// This method goes through the whole authorize process, including a Authorization window.
+ ///
+ /// true if the process is completed
+ public bool Authorize() {
+ Token = null;
+ TokenSecret = null;
+ Verifier = null;
+ Log.Debug("Creating Token");
+ string requestTokenResponse;
+ try {
+ requestTokenResponse = GetRequestToken();
+ } catch (Exception ex) {
+ Log.Error(ex);
+ throw new NotSupportedException("Service is not available: " + ex.Message);
+ }
+ if (string.IsNullOrEmpty(GetAuthorizeToken(requestTokenResponse))) {
+ Log.Debug("User didn't authenticate!");
+ return false;
+ }
+ try {
+ Thread.Sleep(1000);
+ return GetAccessToken() != null;
+ } catch (Exception ex) {
+ Log.Error(ex);
+ throw;
+ }
+ }
+
+ ///
+ /// Get the link to the authorization page for this application.
+ ///
+ /// The url with a valid request token, or a null string.
+ private string AuthorizationLink => AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl);
+
+ ///
+ /// Submit a web request using oAuth.
+ ///
+ /// GET or POST
+ /// The full url, including the querystring for the signing/request
+ /// Parameters for the request, which need to be signed
+ /// Parameters for the request, which do not need to be signed
+ /// Data to post (MemoryStream)
+ /// The web server response.
+ public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) {
+ return MakeOAuthRequest(method, requestUrl, requestUrl, null, parametersToSign, additionalParameters, postData);
+ }
+
+ ///
+ /// Submit a web request using oAuth.
+ ///
+ /// GET or POST
+ /// The full url, including the querystring for the signing/request
+ /// Header values
+ /// Parameters for the request, which need to be signed
+ /// Parameters for the request, which do not need to be signed
+ /// Data to post (MemoryStream)
+ /// The web server response.
+ public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) {
+ return MakeOAuthRequest(method, requestUrl, requestUrl, headers, parametersToSign, additionalParameters, postData);
+ }
+
+ ///
+ /// Submit a web request using oAuth.
+ ///
+ /// GET or POST
+ /// The full url, including the querystring for the signing
+ /// The full url, including the querystring for the request
+ /// Parameters for the request, which need to be signed
+ /// Parameters for the request, which do not need to be signed
+ /// Data to post (MemoryStream)
+ /// The web server response.
+ public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) {
+ return MakeOAuthRequest(method, signUrl, requestUrl, null, parametersToSign, additionalParameters, postData);
+ }
+
+ ///
+ /// Submit a web request using oAuth.
+ ///
+ /// GET or POST
+ /// The full url, including the querystring for the signing
+ /// The full url, including the querystring for the request
+ /// Headers for the request
+ /// Parameters for the request, which need to be signed
+ /// Parameters for the request, which do not need to be signed
+ /// Data to post (MemoryStream)
+ /// The web server response.
+ public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) {
+ if (parametersToSign == null) {
+ parametersToSign = new Dictionary();
+ }
+ int retries = 2;
+ Exception lastException = null;
+ while (retries-- > 0) {
+ // If we are not trying to get a Authorization or Accestoken, and we don't have a token, create one
+ if (string.IsNullOrEmpty(Token)) {
+ if (!AutoLogin || !Authorize()) {
+ throw new Exception("Not authorized");
+ }
+ }
+ try {
+ Sign(method, signUrl, parametersToSign);
+
+ // Join all parameters
+ IDictionary newParameters = new Dictionary();
+ foreach (var parameter in parametersToSign) {
+ newParameters.Add(parameter);
+ }
+ if (additionalParameters != null) {
+ foreach (var parameter in additionalParameters) {
+ newParameters.Add(parameter);
+ }
+ }
+ return MakeRequest(method, requestUrl, headers, newParameters, postData);
+ } catch (UnauthorizedAccessException uaEx) {
+ lastException = uaEx;
+ Token = null;
+ TokenSecret = null;
+ // Remove oauth keys, so they aren't added double
+ List keysToDelete = new List();
+ foreach (string parameterKey in parametersToSign.Keys)
+ {
+ if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX))
+ {
+ keysToDelete.Add(parameterKey);
+ }
+ }
+ foreach (string keyToDelete in keysToDelete)
+ {
+ parametersToSign.Remove(keyToDelete);
+ }
+ }
+ }
+ if (lastException != null) {
+ throw lastException;
+ }
+ throw new Exception("Not authorized");
+ }
+
+ ///
+ /// OAuth sign the parameters, meaning all oauth parameters are added to the supplied dictionary.
+ /// And additionally a signature is added.
+ ///
+ /// Method (POST,PUT,GET)
+ /// Url to call
+ /// IDictionary of string and string
+ private void Sign(HTTPMethod method, string requestUrl, IDictionary parameters) {
+ if (parameters == null) {
+ throw new ArgumentNullException(nameof(parameters));
+ }
+ // Build the signature base
+ StringBuilder signatureBase = new StringBuilder();
+
+ // Add Method to signature base
+ signatureBase.Append(method).Append("&");
+
+ // Add normalized URL
+ Uri url = new Uri(requestUrl);
+ string normalizedUrl = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", url.Scheme, url.Host);
+ if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) {
+ normalizedUrl += ":" + url.Port;
+ }
+ normalizedUrl += url.AbsolutePath;
+ signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&");
+
+ // Add normalized parameters
+ parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION);
+ parameters.Add(OAUTH_NONCE_KEY, GenerateNonce());
+ parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp());
+ switch(SignatureType) {
+ case OAuthSignatureTypes.PLAINTEXT:
+ parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, PlainTextSignatureType);
+ break;
+ default:
+ parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType);
+ break;
+ }
+ parameters.Add(OAUTH_CONSUMER_KEY_KEY, _consumerKey);
+ if (CallbackUrl != null && RequestTokenUrl != null && requestUrl.StartsWith(RequestTokenUrl)) {
+ parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl);
+ }
+ if (!string.IsNullOrEmpty(Verifier)) {
+ parameters.Add(OAUTH_VERIFIER_KEY, Verifier);
+ }
+ if (!string.IsNullOrEmpty(Token)) {
+ parameters.Add(OAUTH_TOKEN_KEY, Token);
+ }
+ signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters)));
+ Log.DebugFormat("Signature base: {0}", signatureBase);
+ string key = string.Format(CultureInfo.InvariantCulture, "{0}&{1}", UrlEncode3986(_consumerSecret), string.IsNullOrEmpty(TokenSecret) ? string.Empty : UrlEncode3986(TokenSecret));
+ switch (SignatureType) {
+ case OAuthSignatureTypes.PLAINTEXT:
+ parameters.Add(OAUTH_SIGNATURE_KEY, key);
+ break;
+ default:
+ // Generate Signature and add it to the parameters
+ HMACSHA1 hmacsha1 = new HMACSHA1 {Key = Encoding.UTF8.GetBytes(key)};
+ string signature = ComputeHash(hmacsha1, signatureBase.ToString());
+ parameters.Add(OAUTH_SIGNATURE_KEY, signature);
+ break;
+ }
+ }
+
+ ///
+ /// Make the actual OAuth request, all oauth parameters are passed as header (default) and the others are placed in the url or post data.
+ /// Any additional parameters added after the Sign call are not in the signature, this could be by design!
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// IBinaryParameter
+ /// Response from server
+ private string MakeRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parameters, IBinaryContainer postData) {
+ if (parameters == null) {
+ throw new ArgumentNullException(nameof(parameters));
+ }
+ IDictionary requestParameters;
+ // Add oAuth values as HTTP headers, if this is allowed
+ StringBuilder authHeader = null;
+ if (UseHttpHeadersForAuthorization) {
+ authHeader = new StringBuilder();
+ requestParameters = new Dictionary();
+ foreach (string parameterKey in parameters.Keys) {
+ if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) {
+ authHeader.AppendFormat(CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986($"{parameters[parameterKey]}"));
+ } else if (!requestParameters.ContainsKey(parameterKey)) {
+ requestParameters.Add(parameterKey, parameters[parameterKey]);
+ }
+ }
+ // Remove trailing comma and space and add it to the headers
+ if (authHeader.Length > 0) {
+ authHeader.Remove(authHeader.Length - 2, 2);
+ }
+ } else {
+ requestParameters = parameters;
+ }
+
+ if (HTTPMethod.GET == method || postData != null) {
+ if (requestParameters.Count > 0) {
+ // Add the parameters to the request
+ requestUrl += "?" + NetworkHelper.GenerateQueryParameters(requestParameters);
+ }
+ }
+ // Create webrequest
+ HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestUrl, method);
+ webRequest.ServicePoint.Expect100Continue = false;
+ webRequest.UserAgent = _userAgent;
+
+ if (UseHttpHeadersForAuthorization && authHeader != null) {
+ Log.DebugFormat("Authorization: OAuth {0}", authHeader);
+ webRequest.Headers.Add("Authorization: OAuth " + authHeader);
+ }
+
+ if (headers != null) {
+ foreach(string key in headers.Keys) {
+ webRequest.Headers.Add(key, headers[key]);
+ }
+ }
+
+ if ((HTTPMethod.POST == method || HTTPMethod.PUT == method) && postData == null && requestParameters.Count > 0) {
+ if (UseMultipartFormData) {
+ NetworkHelper.WriteMultipartFormData(webRequest, requestParameters);
+ } else {
+ StringBuilder form = new StringBuilder();
+ foreach (string parameterKey in requestParameters.Keys)
+ {
+ var binaryParameter = parameters[parameterKey] as IBinaryContainer;
+ form.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), binaryParameter != null ? UrlEncode3986(binaryParameter.ToBase64String(Base64FormattingOptions.None)) : UrlEncode3986($"{parameters[parameterKey]}"));
+ }
+ // Remove trailing &
+ if (form.Length > 0) {
+ form.Remove(form.Length - 1, 1);
+ }
+ webRequest.ContentType = "application/x-www-form-urlencoded";
+ byte[] data = Encoding.UTF8.GetBytes(form.ToString());
+ using (var requestStream = webRequest.GetRequestStream()) {
+ requestStream.Write(data, 0, data.Length);
+ }
+ }
+ } else if (postData != null) {
+ postData.Upload(webRequest);
+ } else {
+ webRequest.ContentLength = 0;
+ }
+
+ string responseData;
+ try {
+ responseData = NetworkHelper.GetResponseAsString(webRequest);
+ Log.DebugFormat("Response: {0}", responseData);
+ } catch (Exception ex) {
+ Log.Error("Couldn't retrieve response: ", ex);
+ throw;
+ }
+
+ return responseData;
+ }
+ }
+
+ ///
+ /// OAuth 2.0 verification code receiver that runs a local server on a free port
+ /// and waits for a call with the authorization verification code.
+ ///
+ public class LocalServerCodeReceiver {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(LocalServerCodeReceiver));
+ private readonly ManualResetEvent _ready = new ManualResetEvent(true);
+
+ ///
+ /// The call back format. Expects one port parameter.
+ /// Default: http://localhost:{0}/authorize/
+ ///
+ public string LoopbackCallbackUrl { get; set; } = "http://localhost:{0}/authorize/";
+
+ ///
+ /// HTML code to to return the _browser, default it will try to close the _browser / tab, this won't always work.
+ /// You can use CloudServiceName where you want to show the CloudServiceName from your OAuth2 settings
+ ///
+ public string ClosePageResponse { get; set; } = @"
+OAuth 2.0 Authentication CloudServiceName
+
+Greenshot received information from CloudServiceName. You can close this browser / tab if it is not closed itself...
+
+
+";
+
+ private string _redirectUri;
+ ///
+ /// The URL to redirect to
+ ///
+ protected string RedirectUri {
+ get {
+ if (!string.IsNullOrEmpty(_redirectUri)) {
+ return _redirectUri;
+ }
+
+ return _redirectUri = string.Format(LoopbackCallbackUrl, GetRandomUnusedPort());
+ }
+ }
+
+ private string _cloudServiceName;
+
+ private readonly IDictionary _returnValues = new Dictionary();
+
+
+ ///
+ /// The OAuth code receiver
+ ///
+ ///
+ /// Dictionary with values
+ public IDictionary ReceiveCode(OAuth2Settings oauth2Settings) {
+ // Set the redirect URL on the settings
+ oauth2Settings.RedirectUrl = RedirectUri;
+ _cloudServiceName = oauth2Settings.CloudServiceName;
+ using (var listener = new HttpListener()) {
+ listener.Prefixes.Add(oauth2Settings.RedirectUrl);
+ try {
+ listener.Start();
+
+ // Get the formatted FormattedAuthUrl
+ string authorizationUrl = oauth2Settings.FormattedAuthUrl;
+ Log.DebugFormat("Open a browser with: {0}", authorizationUrl);
+ Process.Start(authorizationUrl);
+
+ // Wait to get the authorization code response.
+ var context = listener.BeginGetContext(ListenerCallback, listener);
+ _ready.Reset();
+
+ while (!context.AsyncWaitHandle.WaitOne(1000, true)) {
+ Log.Debug("Waiting for response");
+ }
+ } catch (Exception) {
+ // Make sure we can clean up, also if the thead is aborted
+ _ready.Set();
+ throw;
+ } finally {
+ _ready.WaitOne();
+ listener.Close();
+ }
+ }
+ return _returnValues;
+ }
+
+ ///