@@ -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.
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 @@
+
+
+
+
+ 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
+ * 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:
+
+
+
SalvaCtrl + 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 appuntiCtrl + 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-MailCtrl + 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 프로그램이 자동을 실행됩니다.
단축키: 이미지를 생성하기 위하여 사용되는 단축키를 지정합니다.
기본 시스템 프록시 사용: 체크되었을 경우 업데이트를 위한 체크시 기본 시스템 프록시를 사용합니다.
@@ -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 97%
rename from src/Greenshot/Languages/help-nl-NL.html
rename to Greenshot/Languages/help-nl-NL.html
index 999bca3cc..553564ca5 100644
--- a/src/Greenshot/Languages/help-nl-NL.html
+++ b/Greenshot/Languages/help-nl-NL.html
@@ -332,7 +332,7 @@
Algemene instellingen
Taal: De taal waarin Greenshot wordt weergegeven.
- Aanvullende taalbestanden zijn te downloaden van de Greenshot website.
+ 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.
@@ -427,7 +427,7 @@
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/
+ http://getgreenshot.org/support/
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.
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-BR.html b/Greenshot/Languages/help-pt-BR.html
similarity index 98%
rename from src/Greenshot/Languages/help-pt-BR.html
rename to Greenshot/Languages/help-pt-BR.html
index ef817b2bb..4c1c913a1 100644
--- a/src/Greenshot/Languages/help-pt-BR.html
+++ b/Greenshot/Languages/help-pt-BR.html
@@ -333,7 +333,7 @@
Configuraes Gerais
Idioma: O idioma preferido a usar.
- Pode transferir arquivos de idiomas adicionais para o Greenshot aqui.
+ Pode transferir arquivos de idiomas adicionais para o Greenshot aqui.
Iniciar o Greenshot no inicializao: Inicia o programa no inicializao do sistema.
Teclas de Atalho: Personaliza as teclas de atalho a serem usadas para criar capturas.
Usar proxy padro do sistema: Se selecionado, o Greenshot usa proxy padro do sistema para procurar atualizaes.
@@ -428,7 +428,7 @@
muito tempo e dinheiro, ou se simplesmente gosta do Greenshot e
da ideia de software de cdigo aberto: por favor considere compensar o nosso esforo, doando.
Por favor visite a nossa pgina web para ver como pode apoiar a equipe de desenvolvimento do Greenshot:
- https://getgreenshot.org/support/
+ http://getgreenshot.org/support/
@@ -447,7 +447,7 @@
Se um usurio 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 downloads. Veja tambm no nosso monitor de tradues,
+ pgina de downloads. 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 downloads 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-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.
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 @@
diff --git a/src/Greenshot/Languages/installer/language-installer-de-DE.xml b/Greenshot/Languages/installer/language-installer-de-DE.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-de-DE.xml
rename to Greenshot/Languages/installer/language-installer-de-DE.xml
index de1fa31e3..743515c35 100644
--- a/src/Greenshot/Languages/installer/language-installer-de-DE.xml
+++ b/Greenshot/Languages/installer/language-installer-de-DE.xml
@@ -7,7 +7,7 @@
Confluence Plug-inÖffne mit ein externem Kommando Plug-inOCR Plug-in (benötigt Microsoft Office Document Imaging (MODI))
- Imgur Plug-in (Siehe: https://imgur.com)
+ Imgur Plug-in (Siehe: http://imgur.com)Zusätzliche SprachenOptimierung der Leistung, kann etwas dauern.
diff --git a/src/Greenshot/Languages/installer/language-installer-en-US.xml b/Greenshot/Languages/installer/language-installer-en-US.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-en-US.xml
rename to Greenshot/Languages/installer/language-installer-en-US.xml
index 10d3edd56..843005269 100644
--- a/src/Greenshot/Languages/installer/language-installer-en-US.xml
+++ b/Greenshot/Languages/installer/language-installer-en-US.xml
@@ -7,7 +7,7 @@
Confluence plug-inOpen with external command plug-inOCR plug-in (needs Microsoft Office Document Imaging (MODI))
- Imgur plug-in (See: https://imgur.com)
+ Imgur plug-in (See: http://imgur.com)Additional languagesOptimizing performance, this may take a while.
diff --git a/src/Greenshot/Languages/installer/language-installer-es-ES.xml b/Greenshot/Languages/installer/language-installer-es-ES.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-es-ES.xml
rename to Greenshot/Languages/installer/language-installer-es-ES.xml
index 55bf0e7fc..e11d06704 100644
--- a/src/Greenshot/Languages/installer/language-installer-es-ES.xml
+++ b/Greenshot/Languages/installer/language-installer-es-ES.xml
@@ -3,7 +3,7 @@
Extensión para ConfluenceExtensión para abrir con programas externos
- Extensión para Imgur (Ver https://imgur.com)
+ Extensión para Imgur (Ver http://imgur.com)Extensión para JiraIdiomas adicionalesExtensión para OCR (necesita Microsoft Office Document Imaging (MODI))
diff --git a/src/Greenshot/Languages/installer/language-installer-fi-FI.xml b/Greenshot/Languages/installer/language-installer-fi-FI.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-fi-FI.xml
rename to Greenshot/Languages/installer/language-installer-fi-FI.xml
index ba2133261..5182c880b 100644
--- a/src/Greenshot/Languages/installer/language-installer-fi-FI.xml
+++ b/Greenshot/Languages/installer/language-installer-fi-FI.xml
@@ -7,7 +7,7 @@
Confluence-liitännäinenAvaa Ulkoinen komento-liitännäiselläOCR-liitännäinen (Tarvitaan: Microsoft Office Document Imaging (MODI))
- Imgur-liitännäinen (Katso: https://imgur.com)
+ Imgur-liitännäinen (Katso: http://imgur.com)LisäkieletOptimoidaan suorituskykyä, tämä voi kestää hetken.
diff --git a/src/Greenshot/Languages/installer/language-installer-fr-FR.xml b/Greenshot/Languages/installer/language-installer-fr-FR.xml
similarity index 91%
rename from src/Greenshot/Languages/installer/language-installer-fr-FR.xml
rename to Greenshot/Languages/installer/language-installer-fr-FR.xml
index 3448e83d1..4f2cab573 100644
--- a/src/Greenshot/Languages/installer/language-installer-fr-FR.xml
+++ b/Greenshot/Languages/installer/language-installer-fr-FR.xml
@@ -3,7 +3,7 @@
Greffon ConfluenceOuvrir avec le greffon de commande externe
- Greffon Imgur (Voir: https://imgur.com)
+ Greffon Imgur (Voir: http://imgur.com)Greffon JiraLangues additionnellesGreffon OCR (nécessite Document Imaging de Microsoft Office [MODI])
diff --git a/src/Greenshot/Languages/installer/language-installer-it-IT.xml b/Greenshot/Languages/installer/language-installer-it-IT.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-it-IT.xml
rename to Greenshot/Languages/installer/language-installer-it-IT.xml
index f9297206f..7aa745871 100644
--- a/src/Greenshot/Languages/installer/language-installer-it-IT.xml
+++ b/Greenshot/Languages/installer/language-installer-it-IT.xml
@@ -7,7 +7,7 @@
Plugin ConfluenceApri con comando esterno pluginPlugin OCR (richiede Microsoft Office Document Imaging (MODI))
- Plugin Imgur (vedi: https://imgur.com)
+ Plugin Imgur (vedi: http://imgur.com)Lingue aggiuntiveOttimizzazione prestazioni (può richiedere tempo).
diff --git a/src/Greenshot/Languages/installer/language-installer-lv-LV.xml b/Greenshot/Languages/installer/language-installer-lv-LV.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-lv-LV.xml
rename to Greenshot/Languages/installer/language-installer-lv-LV.xml
index 7755045f4..ef7a30d6d 100644
--- a/src/Greenshot/Languages/installer/language-installer-lv-LV.xml
+++ b/Greenshot/Languages/installer/language-installer-lv-LV.xml
@@ -8,7 +8,7 @@
Confluence spraudnisPielāgotu darbību spraudnisOCR 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 valodasUzlaboju veikstpēju, tas prasīs kādu laiciņu.
diff --git a/src/Greenshot/Languages/installer/language-installer-nl-NL.xml b/Greenshot/Languages/installer/language-installer-nl-NL.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-nl-NL.xml
rename to Greenshot/Languages/installer/language-installer-nl-NL.xml
index 83764d32d..43c8454c4 100644
--- a/src/Greenshot/Languages/installer/language-installer-nl-NL.xml
+++ b/Greenshot/Languages/installer/language-installer-nl-NL.xml
@@ -3,7 +3,7 @@
Prestaties verbeteren, kan even duren.Extra talen
- Imgur plug-in (Zie: https://imgur.com)
+ Imgur plug-in (Zie: http://imgur.com)OCR plug-in (heeft Microsoft Office Document Imaging (MODI) nodig)Open met externes commando plug-inConfluence plug-in
diff --git a/src/Greenshot/Languages/installer/language-installer-nn-NO.xml b/Greenshot/Languages/installer/language-installer-nn-NO.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-nn-NO.xml
rename to Greenshot/Languages/installer/language-installer-nn-NO.xml
index 2b31da768..dbde65c2e 100644
--- a/src/Greenshot/Languages/installer/language-installer-nn-NO.xml
+++ b/Greenshot/Languages/installer/language-installer-nn-NO.xml
@@ -3,7 +3,7 @@
Confluence-tilleggTillegg for å opne med ekstern kommando
- Imgur-tillegg (sjå https://imgur.com)
+ Imgur-tillegg (sjå http://imgur.com)Jira-tilleggAndre språkOCR-tillegg (krev Microsoft Office Document Imaging (MODI))
diff --git a/src/Greenshot/Languages/installer/language-installer-sr-RS.xml b/Greenshot/Languages/installer/language-installer-sr-RS.xml
similarity index 96%
rename from src/Greenshot/Languages/installer/language-installer-sr-RS.xml
rename to Greenshot/Languages/installer/language-installer-sr-RS.xml
index 858e2a492..01e3ba5f4 100644
--- a/src/Greenshot/Languages/installer/language-installer-sr-RS.xml
+++ b/Greenshot/Languages/installer/language-installer-sr-RS.xml
@@ -3,7 +3,7 @@
Прикључак за КонфлуенсОтвори са прикључком за спољне наредбе
- Прикључак за Имиџер (https://imgur.com)
+ Прикључак за Имиџер (http://imgur.com)Прикључак за ЏируДодатни језициOCR прикључак (захтева Microsoft Office Document Imaging (MODI))
diff --git a/src/Greenshot/Languages/installer/language-installer-sv-SE.xml b/Greenshot/Languages/installer/language-installer-sv-SE.xml
similarity index 90%
rename from src/Greenshot/Languages/installer/language-installer-sv-SE.xml
rename to Greenshot/Languages/installer/language-installer-sv-SE.xml
index 6c1004ebf..92b7f27ef 100644
--- a/src/Greenshot/Languages/installer/language-installer-sv-SE.xml
+++ b/Greenshot/Languages/installer/language-installer-sv-SE.xml
@@ -7,7 +7,7 @@
Confluence-insticksprogramÖppna med externt kommando-insticksprogramOCR-insticksprogram (kräver Microsoft Office Document Imaging (MODI))
- Imgur-insticksprogram (Se: https://imgur.com)
+ Imgur-insticksprogram (Se: http://imgur.com)Ytterligare språkOptimerar prestanda, detta kan ta en stund.
diff --git a/src/Greenshot/Languages/installer/language-installer-uk-UA.xml b/Greenshot/Languages/installer/language-installer-uk-UA.xml
similarity index 91%
rename from src/Greenshot/Languages/installer/language-installer-uk-UA.xml
rename to Greenshot/Languages/installer/language-installer-uk-UA.xml
index 8de33e3ba..33698d9b2 100644
--- a/src/Greenshot/Languages/installer/language-installer-uk-UA.xml
+++ b/Greenshot/Languages/installer/language-installer-uk-UA.xml
@@ -7,7 +7,7 @@
Плагін ConfluenceПлагін запуску зовнішньої командиПлагін OCR (потребує Microsoft Office Document Imaging (MODI))
- Плагін Imgur (див.: https://imgur.com)
+ Плагін Imgur (див.: http://imgur.com)Додаткові мовиОптимізація продуктивності, це може зайняти певний час.
diff --git a/src/Greenshot/Languages/installer/language-installer-zh-CN.xml b/Greenshot/Languages/installer/language-installer-zh-CN.xml
similarity index 89%
rename from src/Greenshot/Languages/installer/language-installer-zh-CN.xml
rename to Greenshot/Languages/installer/language-installer-zh-CN.xml
index 3abce374d..ec014bb24 100644
--- a/src/Greenshot/Languages/installer/language-installer-zh-CN.xml
+++ b/Greenshot/Languages/installer/language-installer-zh-CN.xml
@@ -3,7 +3,7 @@
Confluence插件使用外部命令打开插件
- Imgur插件( (请访问: https://imgur.com))
+ Imgur插件( (请访问: http://imgur.com))Jira插件其它语言OCR插件(需要Microsoft Office Document Imaging (MODI)的支持)
diff --git a/src/Greenshot/Languages/language-ar-SY.xml b/Greenshot/Languages/language-ar-SY.xml
similarity index 98%
rename from src/Greenshot/Languages/language-ar-SY.xml
rename to Greenshot/Languages/language-ar-SY.xml
index a7363a326..c5c6edc84 100644
--- a/src/Greenshot/Languages/language-ar-SY.xml
+++ b/Greenshot/Languages/language-ar-SY.xml
@@ -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..9f92f7446 100644
--- a/src/Greenshot/Languages/language-ca-CA.xml
+++ b/Greenshot/Languages/language-ca-CA.xml
@@ -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-retallsCopiaRetalla(C)
- Retalla
- AutorretallaEina de selecció (ESC)RetallaEsborra
@@ -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 midaConfiguració del canvi de midaManté la relació d'aspecteAmplada
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..c34389ebf 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 adresePokud se vám Greenshot líbí, uvítáme Vaší podporu
- Greenshot je hostován na github.com
+ Greenshot je hostován na sourceforge.netIkony pochází ze sady Yusuke Kamiyamane's Fugue (licence Creative Commons Attribution 3.0)Copyright (C) 2007-2021 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 TomanGreenshot - revoluční utilita pro snímání obrazovkyZavřítOmlouvá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šitNeoč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)HTMLHTML s vloženými obrázky
- PNG
+ PNGAlfaPoužítModrá
@@ -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ánkyZachytit celou obrazovku
- Vše
- Spodní
- Vlevo
- Vpravo
- Nahoře
- Zachytávat aplikaci Internet Explorer
+ vše
+ spodní
+ vlevo
+ vpravo
+ horní
+ Zachytávat aplikaci Internet ExplorerZachytit 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 GreenshotKonecNápovědaOtevřít obrázek ze souboru
@@ -71,30 +70,28 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
VpravoNahořeVertikální zarovnání
- Uspořádat
+ UspořádatTvar šipkyObaKoncový bodŽádnýPočáteční bod
- Automatické oříznutí
+ Automatické oříznutíBarva výplněPoloměr rozostřeníTučné
- Okraj
+ HraniceJasZrušitChyba 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?PotvrditKopírovat obrázek do schránkyKopírovat cestu do schránkyKopírovatOříznout (C)
- Oříznout
- Automatické oříznutíVýběr objektů (ESC)VystřihnoutOdstranit
@@ -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ÚpravyEfekty
- E-mail
+ E-MailSouborVelikostBarva čáry
@@ -123,20 +120,20 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Vržený stínObrázek uložen do {0}.Vložit okno
- Invertovat
- Skloněné
+ Invertovat
+ ItalikaNačíst objekty ze souboruFaktor zvětšení
- Přizpůsobit velikosti snímku
+ Přizpůsobit velikosti snímkuZamlžit (O)RozmazatZtížení rozeznání obsahuPixelizaceObjekt
- Otevřít složku v průzkumníkovi Windows
+ Otevřít složku v prohlížeči WindowsVložitVelikost pixelu
- Kvalita náhledu
+ Náhled kvalityTiskZnovu {0}Obnovit velikost
@@ -154,7 +151,7 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Tloušťka linkyGreenshot editor obrázkůPotrhané okraje
- Zpět {0}
+ Zpět {0}Nahoru o jednu úroveňPosunout úplně nahoruMAPI klient
@@ -162,7 +159,7 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
Aplikace Outlook s prostým textemChybaProgram 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.ExpertVytvořit 8bitový obrázek, pokud má méně než 256 barev
- Kontrolovat aktualizace nestabilních verzí
+ Kontrolovat nestabilní aktualizaceFormáty schránkyČíslo pro ${NUM} ve vzoru pro název souboruVí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í editoruZobrazovat 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
+ OkNastala chyba při pokusu o tisk.Centrovat obrázek na stránceZvě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ímkuKopírovat do schránkyOtevřít v editoru obrázků
- E-mail
+ E-MailUložit přímo (pomocí nastavení níže)Uložit jako (zobrazit dialog)Vybrat cíl dynamickyOdeslat na tiskárnu
- Editor
+ EditorVzor pro název souboruObecné
- Snímek aplikace Internet Explorer
+ Snímek aplikace Internet ExplorerKvalita JPEGJazykNá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 aktualizaceVýstup
- Přehrát zvuk závěrky fotoaparátu
- Zásuvné moduly
+ Přehrát zvuk uzávěrky fotoaparátu
+ PluginyAutorCesta k DLLNázev
@@ -258,10 +252,10 @@ např. 11_58_32 (plus rozšíření uvedené v nastavení).
TiskMožnosti tiskuNastavení kvality
- Snížit počet barev na maximálně 256
+ Snížit počet barev na maximálně 256Registrovat klávesové zkratkyPoužít blesk
- Zobrazovat upozornění
+ Zobrazovat upozorněníZobrazit lupuCílNastavení
@@ -270,14 +264,14 @@ např. 11_58_32 (plus rozšíření uvedené v nastavení).
Výchozí formát obrázkuDefinuje 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 proxyEfektyPřed zachycením počkat daný počet milisekundRežim zachycování okna
- Snímek okna
+ Snímek oknaKlikně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
AutomatickyPoužít výchozí barvuJak je zobrazeno
-
+
Intenzita stínuVyrovnání stínu
@@ -304,11 +298,11 @@ Všechny funkce Greenshotu jsou stále dostupné přímo z místní nabídky bez
Horní stranaDolní stranaVytvořit stín
-
+
Přidat počítadlo (I)Přidat textovou bublinu (S)
- Změnit velikost (Z)
+ Změnit velikostNastavení změny velikostiZachovat 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 86%
rename from src/Greenshot/Languages/language-de-DE.xml
rename to Greenshot/Languages/language-de-DE.xml
index b636da112..9ece82568 100644
--- a/src/Greenshot/Languages/language-de-DE.xml
+++ b/Greenshot/Languages/language-de-DE.xml
@@ -57,8 +57,8 @@ schnell zu finden. Vielen Dank :)Greenshot unterstützenSchließenHilfe
- Datei öffnen...
- Letzten Speicherort im Explorer öffnen
+ Datei öffnen
+ Letzten Screenshot im Explorer anzeigenSchnelleinstellungenEinstellungen...Fehler beim Exportieren nach '{0}'. Bitte wiederholen Sie den Vorgang.
@@ -77,8 +77,7 @@ schnell zu finden. Vielen Dank :)KeineAnfangspunktAutomatisch zuschneiden
- Automatisches Zuschneiden nicht möglich
- Hintergrundfarbe (0-9)
+ HintergrundfarbeWeichzeichner-RadiusFettRand
@@ -93,19 +92,14 @@ schnell zu finden. Vielen Dank :)
Pfad in Zwischenablage kopierenKopierenZuschneiden (C)
- Zuschneiden - Modus
- Zuschneiden
- Vertikal ausschneiden
- Horizontal ausschneiden
- Automatisch zuschneiden
- Auswahlwerkzeug (Esc)
+ Auswahlwerkzeug (ESC)AusschneidenGewähltes Element löschenEine Ebene nach hintenIn den HintergrundPfeil 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-MailDateiGröße
- Rahmenfarbe (Num+0-9, Umschalt+0-9)
+ RahmenfarbeGraustufeBereich hervorhebenGraustufen
@@ -136,7 +130,7 @@ schnell zu finden. Vielen Dank :)
Unkenntlich machen - ModusVerpixelnObjekt
- Verzeichnis im Windows Explorer öffnen
+ Verzeichnis in Windows Explorer öffnenEinfügenPixelgrößeVorschauqualität
@@ -152,10 +146,10 @@ schnell zu finden. Vielen Dank :)
Speichern unter...Alle Objekte auswählenDruckauftrag wurde an '{0}' gesendet.
- Schatten an/aus (/)
+ Schatten An/AusBild wurde in Zwischenablage kopiert.Linienstärke
- Greenshot - Editor
+ Greenshot EditorGerissene KantenRückgängig {0}Eine Ebene nach vorne
@@ -170,12 +164,12 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
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.Experten8-Bit-Bilder bei weniger als 256 Farben erstellenAuch instabile Updates anbietenZwischenablage-Formate
- Wert für ${NUM} im Dateinamensmuster
+ Wert für ${NUM} im Dateiname-MusterIch weiß, was ich tue!Fußzeile für DruckSpeicherverbrauch reduzieren (auf Kosten der Performance - nicht empfohlen)
@@ -190,10 +184,10 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
Bitte wählen Sie die Qualität Ihres JPEG-Bildes.OKBeim 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 verkleinernFarb-EinstellungenAls Standard speichern und nicht wieder fragenFarben umkehren
@@ -201,7 +195,7 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
FarbdruckNur in Graustufen ausdruckenSchwarz-Weiß-Druck erzwingen
- Datum/Uhrzeit am Seitenende
+ Datum und Uhrzeit am Ende der Seite einfügenGreenshot - DruckeinstellungenAls Standardqualität speichern und nicht wieder fragenGreenshot - Qualität
@@ -213,7 +207,7 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
AbfotografierenMauszeiger mitfotografierenFensterteile einzeln abfotografieren
- Prüfen auf Updates alle x Tage (0 = keine Prüfung)
+ Prüfen auf Updates alle X Tage (0=keine Prüfung)Konfigurieren...Dateipfad in die Zwischenablage kopieren, wenn ein Bild gespeichert wirdZiele
@@ -225,29 +219,29 @@ Bitte überprüfen Sie die Schreibrechte oder wählen Sie einen anderen Speicher
Ziel dynamisch auswählenAn Drucker sendenEditor
- Dateinamensmuster
+ Dateiname-MusterAllgemeinInternet Explorer abfotografierenJPEG-QualitätSpracheDie 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
+Verwenden Sie den Backslash \ 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 AktualisierungenAusgabeKameraton abspielen
@@ -260,7 +254,7 @@ Beispiel: C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
BildformatDruckerDruckeinstellungen
- JPEG-Qualitätseinstellungen
+ QualitätseinstellungenMaximal 256 Farben verwendenGlobale Tastenkombinationen aktivierenBlitzlicht anzeigen
@@ -270,21 +264,21 @@ Beispiel: C:\Users\MaxMustermann\Desktop\2012-08-13\12-58-32.png
Muster, das beim Speichern von Screenshots zum Generieren von Dateinamen verwendet wirdSprache der BenutzeroberflächeStandard-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 Druck, Strg + Druck, Alt + Druck 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 verwendenEffekteMillisekunden vor dem Abfotografieren warten
- Aufnahmemodus
+ Abfotografiermodus-FensterFenster abfotografierenLupe anzeigenKlicken 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?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 Tastenkombination 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,7 +306,7 @@ Sie können aber auch alle Greenshot-Funktionen über das Kontextmenü des Green
Zähler hinzufügen (I)Sprechblase hinzufügen (S)
- Skalieren (Z)
+ SkalierenEinstellungen für SkalierungSeitenverhältnis beibehaltenBreite
diff --git a/src/Greenshot/Languages/language-de-x-franconia.xml b/Greenshot/Languages/language-de-x-franconia.xml
similarity index 97%
rename from src/Greenshot/Languages/language-de-x-franconia.xml
rename to Greenshot/Languages/language-de-x-franconia.xml
index 34da6f0b7..b989bcfe7 100644
--- a/src/Greenshot/Languages/language-de-x-franconia.xml
+++ b/Greenshot/Languages/language-de-x-franconia.xml
@@ -88,8 +88,6 @@ Dangschee, wassd scho :)Bfad in däi Zwischnblach neiKobiernZamschneidn (C)
- Zamschneidn
- Audomadisch zamschneidnAngriffln (ESC)AusschneidnWech mid dem Ding!
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..14cb68bef 100644
--- a/src/Greenshot/Languages/language-el-GR.xml
+++ b/Greenshot/Languages/language-el-GR.xml
@@ -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 94%
rename from src/Greenshot/Languages/language-en-US.xml
rename to Greenshot/Languages/language-en-US.xml
index 1403d3e9c..0537c965b 100644
--- a/src/Greenshot/Languages/language-en-US.xml
+++ b/Greenshot/Languages/language-en-US.xml
@@ -12,7 +12,7 @@ Details about the GNU General Public License:
Greenshot - the revolutionary screenshot utilityClose
- 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,7 +21,7 @@ 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 :)ErrorCancel
- 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
@@ -78,8 +78,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
NoneStart pointAuto crop
- Auto crop not possible
- Fill color (0-9)
+ Fill colorBlur radiusBoldBorder
@@ -94,11 +93,6 @@ Also, we would highly appreciate if you checked whether a tracker item already e
Copy path to clipboardCopyCrop (C)
- Crop mode
- Crop
- Crop out vertically
- Crop out horizontally
- Auto cropSelection Tool (ESC)CutDelete
@@ -117,7 +111,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
E-MailFileSize
- Line color (NumPad0-9, Shift+0-9)
+ Line colorGrayscaleHighlight areaGrayscale
@@ -153,7 +147,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
Save as...Select allPrint job was sent to '{0}'.
- Drop shadow (/)
+ Drop shadowImage stored to clipboard.Line thicknessGreenshot image editor
@@ -185,7 +179,7 @@ Please check write accessibility of the selected storage location.Suppress the save dialog when closing the editorShow 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 HelpHotkeysPlease choose the JPEG quality for your image.
@@ -312,7 +306,7 @@ All Greenshot features still work directly from the tray icon context menu witho
Add counter (I)Add speechbubble (S)
- Resize (Z)
+ ResizeResize settingsMaintain aspect ratioWidth
diff --git a/src/Greenshot/Languages/language-es-ES.xml b/Greenshot/Languages/language-es-ES.xml
similarity index 98%
rename from src/Greenshot/Languages/language-es-ES.xml
rename to Greenshot/Languages/language-es-ES.xml
index 0badf64a4..b84aee912 100644
--- a/src/Greenshot/Languages/language-es-ES.xml
+++ b/Greenshot/Languages/language-es-ES.xml
@@ -80,8 +80,6 @@ Antes de crear un nuevo informe de error, te agradeceríamos que comprobaras que
Copiar ruta al portapapelesCopiarRecortar(C)
- Recortar
- AutorrecortarHerramienta de selección (ESC)CortarBorrar
diff --git a/src/Greenshot/Languages/language-et-EE.xml b/Greenshot/Languages/language-et-EE.xml
similarity index 98%
rename from src/Greenshot/Languages/language-et-EE.xml
rename to Greenshot/Languages/language-et-EE.xml
index 7a4b0dcc3..b358977e8 100644
--- a/src/Greenshot/Languages/language-et-EE.xml
+++ b/Greenshot/Languages/language-et-EE.xml
@@ -92,8 +92,6 @@ Me oleksime väga tänulik, kui te enne kontrolliksite, ega sellest veast pole j
Kopeerige asukoht lõikelaualeKopeeriLõika (C)
- Lõika
- Automaatne lõikusValiku tööriist (ESC)LõikaKustuta
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 98%
rename from src/Greenshot/Languages/language-fi-FI.xml
rename to Greenshot/Languages/language-fi-FI.xml
index a2f211b03..f66cc5013 100644
--- a/src/Greenshot/Languages/language-fi-FI.xml
+++ b/Greenshot/Languages/language-fi-FI.xml
@@ -62,7 +62,6 @@ Olisi myös hyvä jos voisit tarkistaa onko virhe jo raportoitu aikaisemmin (voi
Kopioi tiedostopolku leikepöydälleKopioiRajaa (C)
- RajaaValintatyökalu (ESC)LeikkaaPoista
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..53f8e21f6 100644
--- a/src/Greenshot/Languages/language-fr-FR.xml
+++ b/Greenshot/Languages/language-fr-FR.xml
@@ -93,8 +93,6 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
CopierAjouter un compteurRecadrer (C)
- Recadrer
- Cadrage automatiqueOutil de sélection (ESC)CouperSupprimer
@@ -144,7 +142,7 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
ImprimerRétablir {0}Réinitialiser la taille
- Redimensionner (Z)
+ RedimensionnerMaintenir le rapport L / HHauteurPourcentage
diff --git a/src/Greenshot/Languages/language-fr-QC.xml b/Greenshot/Languages/language-fr-QC.xml
similarity index 98%
rename from src/Greenshot/Languages/language-fr-QC.xml
rename to Greenshot/Languages/language-fr-QC.xml
index cf822fa16..17c0e5537 100644
--- a/src/Greenshot/Languages/language-fr-QC.xml
+++ b/Greenshot/Languages/language-fr-QC.xml
@@ -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-papierCopierRogner (C)
- Rogner
- Rognage automatiqueOutil de sélection (ESC)CouperSupprimer
diff --git a/src/Greenshot/Languages/language-he-IL.xml b/Greenshot/Languages/language-he-IL.xml
similarity index 98%
rename from src/Greenshot/Languages/language-he-IL.xml
rename to Greenshot/Languages/language-he-IL.xml
index 537f77067..4df909d37 100644
--- a/src/Greenshot/Languages/language-he-IL.xml
+++ b/Greenshot/Languages/language-he-IL.xml
@@ -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 98%
rename from src/Greenshot/Languages/language-hu-HU.xml
rename to Greenshot/Languages/language-hu-HU.xml
index 20035f3c5..0d5a06df9 100644
--- a/src/Greenshot/Languages/language-hu-HU.xml
+++ b/Greenshot/Languages/language-hu-HU.xml
@@ -63,7 +63,6 @@ Kérjük adjon összefoglaló leírást és csatoljon minden olyan információt
Másolja a vágólapraMásolásVágás eszköz (C)
- Vágás eszközKiválasztó eszköz (ESC)KivágásTö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..e474cae59 100644
--- a/src/Greenshot/Languages/language-id-ID.xml
+++ b/Greenshot/Languages/language-id-ID.xml
@@ -93,8 +93,6 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
KopiBuat penomorPotong (C)
- Potong
- Auto potongAlat seleksi (ESC)GuntingHapus
@@ -144,7 +142,7 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
CetakUlang {0}Reset ukuran
- Ubah ukuran (Z)
+ Ubah ukuranPertahankan aspek rasioTinggiPersen
diff --git a/src/Greenshot/Languages/language-it-IT.xml b/Greenshot/Languages/language-it-IT.xml
similarity index 92%
rename from src/Greenshot/Languages/language-it-IT.xml
rename to Greenshot/Languages/language-it-IT.xml
index 89d68c988..a2b3db147 100644
--- a/src/Greenshot/Languages/language-it-IT.xml
+++ b/Greenshot/Languages/language-it-IT.xml
@@ -6,11 +6,11 @@
Greenshot è disponibile nel repository GitHubLibreria icone del set icone Fugue di Yusuke Kamiyamane (Creative Commons Attribution 3.0 license)Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
-Greenshot viene fornito SENZA ALCUNA GARANZIA.
-Questo software è gratuito", e potete ri-distribuirlo secondo certe condizioni.
+Greenshot viene fornito SENZA ALCUNA GARANZIA.
+Questo software è garuitio", e potete ri-distribuirlo secondo certe condizioni.
Dettagli della General Public License GNU:Info su Greenshot
- Traduzione italiana (v. 29.01.2021) di bovirus e tonytogna
+ Traduzione italiana (v. 16.08.2020) di bovirus e tonytognaGreenshot - Uno straordinario strumento per copiare immagini dallo schermoChiudiSi è verificato un errore inaspettato.
@@ -19,7 +19,8 @@ La buona notizia è che puoi aiutarci ad eliminarlo segnalandoci l'errore.
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 la segnalazione, controllassi se esiste già una segnalazione per questo tipo di errore (puoi usare la ricerca). Grazie :)
+Inoltre apprezzeremo molto, se prima di inserire la segnalazione, controllassi se esiste già una segnalazione per questo tipo di errore (puoi usare la ricerca)
+Grazie :)
ErroreAnnullaSi è verificato un errore inaspettato durante la scrittura negli Appunti.
@@ -81,8 +82,7 @@ Controlla i permessi di accesso per '{0}'.
Punto finaleNessunaPunto iniziale
- Ritaglia automaticamente
- Ritaglio automatico non possibile
+ Ritaglia AutomaticamenteColore di riempimentoRaggio sfumaturaGrassetto
@@ -98,10 +98,6 @@ Controlla i permessi di accesso per '{0}'.
Copia percorso negli appuntiCopiaRitaglia (C)
- Ritaglia
- Ritaglia verticalmente
- Ritaglia orizzontalmente
- Ritaglia automaticamenteStrumento di selezione (ESC)TagliaElimina
@@ -133,11 +129,11 @@ Controlla i permessi di accesso per '{0}'.
NegativoCorsivoCarica oggetti da file
- Fattore ingrandimento
- Adatta a dimensioni cattura
+ Fattore di ingrandimento
+ Adatta a dimensioni di catturaOffusca (O)Sfuma
- Modalità offuscamento
+ Modalità di offuscamentoOffusca/pixelizzaOggettiApri cartella su Windows Explorer
@@ -179,17 +175,17 @@ Verifica l'accesso in scrittura nel percorso di salvataggio.
Il nome file o cartella generato non è valido.
Correggi la maschera noem file e riprova.Utente esperto
- Crea immagine a 8bit se immagine ha meno di 256 colori
+ Crea una immagine a 8bit se i colori sono meno di 256 e l'immagine ha > 8 bitControlla disponibilità aggiornamenti versioni beta
- Formato Appunti
- Numero var. ${NUM} modello nome file
+ Formati degli Appunti
+ Numero per var. ${NUM} nel modello del nome fileSono consapevole di ciò che sto facendo!
- Modello piè pagina
+ Modello piè di paginaRiduci uso della memoria perdendo però in prestazioni (sconsigliato).Esegui ottimizzazioni per uso con desktop remotoRiutilizza se possibile la gestione immaginiEvita avviso di salvataggio in chiusura della gestione immagini
- Visualizza anteprima finestra menù contestuale (Vista/Windows 7)
+ Visualizza anteprima finestra nel menù di contesto (Vista e Windows 7)Esportato in: {0}Si è verificato un errore durante l'esportazione in {0}:Guida in linea Greenshot
@@ -211,7 +207,7 @@ Correggi la maschera noem file e riprova.
Aggiungi data/ora nel piè di paginaOpzioni di stampa di GreenshotSalva come qualità predefinita e non chiedere più
- Qualità Greenshot
+ Qualità di GreenshotSalva direttamente (usando le impostazioni preferite file destinazione)Visualizza scelta opzioni di stampa ogni volta che stampi un'immagineVisualizza scelta qualità ogni volta che si salva un'immagine
@@ -219,7 +215,7 @@ Correggi la maschera noem file e riprova.
Esegui Greenshot all'avvio del sistemaCatturaCattura puntatore mouse
- Usa modalità cattura via finestra interattiva
+ Usa la modalità di cattura via finestra interattivaIntervallo controllo aggiornamento in giorni (0=nessun controllo)ImpostaOgni volta che una immagine viene salvata copia percorso file negli Appunti
@@ -269,7 +265,7 @@ impostazioni)
StampanteOpzioni di stampaImpostazioni qualità
- Riduci i colori ad un massimo di 256
+ Riduci i colori a un massimo di 256Registra scorciatoie tastieraVisualizza torcia elettricaVisualizza notifiche
@@ -298,8 +294,8 @@ In alternativa alle scorciatoie di tastiera, tutte le funzioni di Greenshot sono
Usa colori personalizzatiMantieni trasparenza
- Automatica
- Usa colori predefiniti
+ Automaticamente
+ Usa i colori predefinitiCome visualizzata
@@ -322,12 +318,12 @@ In alternativa alle scorciatoie di tastiera, tutte le funzioni di Greenshot sono
Aggiungi conteggioAggiungi nuvoletta
- Ridimensiona (Z)
+ RidimensionaImpostazioni ridimensionamentoMantieni rapporto dimensioniLarghezzaAltezza
- Dimensione icona (pixel)
+ Dimensione icona
diff --git a/src/Greenshot/Languages/language-ja-JP.xml b/Greenshot/Languages/language-ja-JP.xml
similarity index 98%
rename from src/Greenshot/Languages/language-ja-JP.xml
rename to Greenshot/Languages/language-ja-JP.xml
index 36f5231f2..c894b9573 100644
--- a/src/Greenshot/Languages/language-ja-JP.xml
+++ b/Greenshot/Languages/language-ja-JP.xml
@@ -92,8 +92,6 @@ Greenshot には一切の保障がありません。GNU General Public License
コピーカウンターを挿入する (I)切り抜き (C)
- 切り抜き
- 自動切り抜き選択ツール (ESC)切り取り削除
@@ -143,7 +141,7 @@ Greenshot には一切の保障がありません。GNU General Public License
印刷やり直し{0}サイズをリセット
- リサイズ (Z)
+ リサイズ縦横比を維持する高さパーセント
diff --git a/src/Greenshot/Languages/language-kab-DZ.xml b/Greenshot/Languages/language-kab-DZ.xml
similarity index 99%
rename from src/Greenshot/Languages/language-kab-DZ.xml
rename to Greenshot/Languages/language-kab-DZ.xml
index 8a690952c..31930d2db 100644
--- a/src/Greenshot/Languages/language-kab-DZ.xml
+++ b/Greenshot/Languages/language-kab-DZ.xml
@@ -93,8 +93,6 @@ Rnu ɣur-s, nḥemmel aṭas ma yella tesneqdeḍ aneqqis igebren ugur-agi. (Tze
NɣelRnu AmesmiḍanSeggem (C)
- Seggem
- Aseggem awurmanAfecku n ufran (ESC)GzemKkes
@@ -144,7 +142,7 @@ Rnu ɣur-s, nḥemmel aṭas ma yella tesneqdeḍ aneqqis igebren ugur-agi. (Tze
SiggezErr-d {0}Wennez teɣzi
- Snifel tahri/teɣzi (Z)
+ Snifel tahri/teɣziEǧǧ afmiḍi Teɣ / TehAwrirAfmiḍ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..a332cea33 100644
--- a/src/Greenshot/Languages/language-ko-KR.xml
+++ b/Greenshot/Languages/language-ko-KR.xml
@@ -92,8 +92,6 @@ Also, we would highly appreciate if you checked whether a tracker item already e
경로를 클립보드로 복사복사잘라내기 (C)
- 잘라내기
- 자동 잘라내기선택도구 (ESC)잘라내기삭제
@@ -304,7 +302,7 @@ ${hostname} PC명
카운터 더하기 (I)설명선 더하기(S)
- 크기조정 (Z)
+ 크기조정크기조정 설정종횡비 유지너비
diff --git a/src/Greenshot/Languages/language-lt-LT.xml b/Greenshot/Languages/language-lt-LT.xml
similarity index 98%
rename from src/Greenshot/Languages/language-lt-LT.xml
rename to Greenshot/Languages/language-lt-LT.xml
index 9b1089811..e84388901 100644
--- a/src/Greenshot/Languages/language-lt-LT.xml
+++ b/Greenshot/Languages/language-lt-LT.xml
@@ -61,7 +61,6 @@ Dėkojame už pagalbą :)
Kopijuoti pilną failo vardąКоpijuotiIškirpti (C)
- IškirptiObjektų pasirinkimas (ESC)ApkirptiNaikinti
diff --git a/src/Greenshot/Languages/language-lv-LV.xml b/Greenshot/Languages/language-lv-LV.xml
similarity index 99%
rename from src/Greenshot/Languages/language-lv-LV.xml
rename to Greenshot/Languages/language-lv-LV.xml
index dea057944..c74e41326 100644
--- a/src/Greenshot/Languages/language-lv-LV.xml
+++ b/Greenshot/Languages/language-lv-LV.xml
@@ -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ētApcirst (C)
- Apcirst
- Automātiski apcirstAtlases rīks (ESC)IzgrieztIzdzēst
@@ -306,7 +304,7 @@ Arī bez karstiem taustiņiem visas darbības iespējams veikt izmantojot „Gre
Pievienot skaitli (I)Pievienot teksta norādi (S)
- Mainīt izmēru (Z)
+ Mainīt izmēruIzmēra maiņas iestatījumiSaglabāt izmēru attiecībasPlatums
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..507ece7dc 100644
--- a/src/Greenshot/Languages/language-nl-NL.xml
+++ b/Greenshot/Languages/language-nl-NL.xml
@@ -78,7 +78,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
GeenStartpuntAutomatisch bijsnijden
- Vulkleur (0-9)
+ VulkleurVervagingsradiusVetRand
@@ -93,8 +93,6 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
Locatie naar klembord kopiërenKopiërenBijsnijden (C)
- Bijsnijden
- Automatisch bijsnijdenSelectiegereedschap (ESC)KnippenVerwijderen
@@ -113,7 +111,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
E-mailBestandGrootte
- Lijnkleur (NumPad0-9, Shift+0-9)
+ LijnkleurGrijstintenGebied markerenGrijstinten
@@ -149,7 +147,7 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
Opslaan als…Alles selecterenAfdruktaak verzonden naar '{0}'.
- Schaduw (/)
+ SchaduwAfbeelding opgeslagen op het klembord.LijndikteGreenshot beeldbewerker
@@ -307,7 +305,7 @@ Alle Greenshot functies werken ook zonder sneltoetsen via het context menu.Teller toevoegen (I)
Tekstballon toevoegen (S)
- Grootte (Z)
+ GrootteVergrotingsinstellingenVerhouding behoudenBreedte
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..003b11b9a 100644
--- a/src/Greenshot/Languages/language-nn-NO.xml
+++ b/Greenshot/Languages/language-nn-NO.xml
@@ -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 utklyppstavlaKopierSkjer bildet [C]
- Skjer bildet
- Auto-skjerPeikarverktøy [Esc]Klypp utSlett
diff --git a/src/Greenshot/Languages/language-pl-PL.xml b/Greenshot/Languages/language-pl-PL.xml
similarity index 98%
rename from src/Greenshot/Languages/language-pl-PL.xml
rename to Greenshot/Languages/language-pl-PL.xml
index 7f908dba8..54e2fd993 100644
--- a/src/Greenshot/Languages/language-pl-PL.xml
+++ b/Greenshot/Languages/language-pl-PL.xml
@@ -93,8 +93,6 @@ Będziemy wdzięczni, jeśli najpierw sprawdzisz, czy takie zdarzenie nie zosta
Kopiuj ścieżkę do schowkaKopiujPrzytnij (C)
- Przytnij (C)
- Przytnij automatycznieNarzędzie wyboru (ESC)WytnijUsuń
diff --git a/src/Greenshot/Languages/language-pt-BR.xml b/Greenshot/Languages/language-pt-BR.xml
similarity index 98%
rename from src/Greenshot/Languages/language-pt-BR.xml
rename to Greenshot/Languages/language-pt-BR.xml
index e53603ccc..8bfd938ed 100644
--- a/src/Greenshot/Languages/language-pt-BR.xml
+++ b/Greenshot/Languages/language-pt-BR.xml
@@ -89,7 +89,6 @@
Copiar o caminho da pasta atual do arquivo para a Área de transferênciaCopiarCortar (C)
- CortarFerramenta de Seleção (ESC)CortarApagar
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..dabc42762 100644
--- a/src/Greenshot/Languages/language-pt-PT.xml
+++ b/Greenshot/Languages/language-pt-PT.xml
@@ -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ênciaCopiarRecortar (C)
- Recortar
- Recortar autoFerramenta de Selecção (ESC)CortarEliminar
@@ -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)
+ RedimensionarDefinições de RedimensionamentoManter proporçõesLargura
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 98%
rename from src/Greenshot/Languages/language-ru-RU.xml
rename to Greenshot/Languages/language-ru-RU.xml
index f9973f349..42d85df80 100644
--- a/src/Greenshot/Languages/language-ru-RU.xml
+++ b/Greenshot/Languages/language-ru-RU.xml
@@ -93,8 +93,6 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Копировать путь в буфер обменаКопироватьОбрезка (C)
- Обрезка
- АвтообрезкаИнструмент «Выделение» (ESC)ВырезатьУдалить
diff --git a/src/Greenshot/Languages/language-sk-SK.xml b/Greenshot/Languages/language-sk-SK.xml
similarity index 98%
rename from src/Greenshot/Languages/language-sk-SK.xml
rename to Greenshot/Languages/language-sk-SK.xml
index 01c68e9ed..f47c2bd5b 100644
--- a/src/Greenshot/Languages/language-sk-SK.xml
+++ b/Greenshot/Languages/language-sk-SK.xml
@@ -80,8 +80,6 @@ Tiež by sme velmi ocenili, keby ste najskôr skontrolovali, či už neexistuje
Kopírovať cestu do schránkyKopírovaťOrezať (C)
- Orezať
- Automatické orezanieNá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..fd0dc2bc4 100644
--- a/src/Greenshot/Languages/language-sl-SI.xml
+++ b/Greenshot/Languages/language-sl-SI.xml
@@ -78,8 +78,6 @@ Pred objavo preverite tudi ali je napaka že prijavlja s strani kakšnega drugeg
Kopiraj pot na odložiščeKopirajObreži (C)
- Obreži
- Samodejno obrežiOrodje za izbor (ESC)KopirajBriši
diff --git a/src/Greenshot/Languages/language-sr-RS.xml b/Greenshot/Languages/language-sr-RS.xml
similarity index 98%
rename from src/Greenshot/Languages/language-sr-RS.xml
rename to Greenshot/Languages/language-sr-RS.xml
index 9c669dba8..6b624dd9c 100644
--- a/src/Greenshot/Languages/language-sr-RS.xml
+++ b/Greenshot/Languages/language-sr-RS.xml
@@ -78,8 +78,6 @@
Умножи путањуУмножиОпсеци (C)
- Опсеци
- Аутоматско опсецањеАлатка за одабир (ESC)ИсециОбриши
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..3fe2df709 100644
--- a/src/Greenshot/Languages/language-sv-SE.xml
+++ b/Greenshot/Languages/language-sv-SE.xml
@@ -93,8 +93,6 @@ Innan du skickar uppskattar vi verkligen om du kontrollerar om felet redan blivi
Kopiera sökväg till urklippKopieraBeskär (C)
- Beskär
- AutobeskärningMarkeringsverktyg (ESC)Klipp utRadera
@@ -305,7 +303,7 @@ Alla Greenshots funktioner fungerar fortfarande från snabbmenyn i aktivitetsfä
Lägg till räknareLägg till pratbubbla
- Anpassa storlek (Z)
+ Anpassa storlekStorleksinställningarBehåll bildförhållandeBredd
diff --git a/src/Greenshot/Languages/language-tr-TR.xml b/Greenshot/Languages/language-tr-TR.xml
similarity index 98%
rename from src/Greenshot/Languages/language-tr-TR.xml
rename to Greenshot/Languages/language-tr-TR.xml
index 56011063c..b5a43f083 100644
--- a/src/Greenshot/Languages/language-tr-TR.xml
+++ b/Greenshot/Languages/language-tr-TR.xml
@@ -78,8 +78,6 @@ Ayrıca bu hata için bir izleyici kaydının açılmış olup olmadığını da
Yolu panoya kopyalaKopyalaKırp (C)
- Kırp
- Otomatik kırpmaSeçim Aracı (ESC)KesSil
diff --git a/src/Greenshot/Languages/language-uk-UA.xml b/Greenshot/Languages/language-uk-UA.xml
similarity index 98%
rename from src/Greenshot/Languages/language-uk-UA.xml
rename to Greenshot/Languages/language-uk-UA.xml
index 057927676..850a5ea7f 100644
--- a/src/Greenshot/Languages/language-uk-UA.xml
+++ b/Greenshot/Languages/language-uk-UA.xml
@@ -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 98%
rename from src/Greenshot/Languages/language-vi-VN.xml
rename to Greenshot/Languages/language-vi-VN.xml
index 6ddfc7f9d..a4b1a73c2 100644
--- a/src/Greenshot/Languages/language-vi-VN.xml
+++ b/Greenshot/Languages/language-vi-VN.xml
@@ -58,7 +58,6 @@
Chép đuờng dẫn tới clipboard.ChépCắt (C)
- CắtCông cụ chọn (ESC)CắtXóa
diff --git a/src/Greenshot/Languages/language-zh-CN.xml b/Greenshot/Languages/language-zh-CN.xml
similarity index 98%
rename from src/Greenshot/Languages/language-zh-CN.xml
rename to Greenshot/Languages/language-zh-CN.xml
index e69489c8c..7325fff33 100644
--- a/src/Greenshot/Languages/language-zh-CN.xml
+++ b/Greenshot/Languages/language-zh-CN.xml
@@ -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..590ec8f05 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 詳細資料:
+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)HTMLHTML 含內嵌圖像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/src/Greenshot/Languages/website/language-website-de-DE.xml b/Greenshot/Languages/website/language-website-de-DE.xml
similarity index 100%
rename from src/Greenshot/Languages/website/language-website-de-DE.xml
rename to Greenshot/Languages/website/language-website-de-DE.xml
diff --git a/src/Greenshot/Languages/website/language-website-en-US.xml b/Greenshot/Languages/website/language-website-en-US.xml
similarity index 88%
rename from src/Greenshot/Languages/website/language-website-en-US.xml
rename to Greenshot/Languages/website/language-website-en-US.xml
index 3920492ef..6cb85ca9f 100644
--- a/src/Greenshot/Languages/website/language-website-en-US.xml
+++ b/Greenshot/Languages/website/language-website-en-US.xml
@@ -5,15 +5,15 @@
Greenshot - a free screenshot tool optimized for productivityGreenshot is free and open sourceIf 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.
+ 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 simplifying creation of and work with screenshots every day.
+ ...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/website/language-website-es-ES.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-es-ES.xml
rename to Greenshot/Languages/website/language-website-es-ES.xml
index c4f87efb9..2c6f35720 100644
--- a/src/Greenshot/Languages/website/language-website-es-ES.xml
+++ b/Greenshot/Languages/website/language-website-es-ES.xml
@@ -5,7 +5,7 @@
Greenshot - herramienta libre de captura de pantalla, optimizada para una mayor productividadGreenshot es código libre y abiertoSi 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.
+ 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?
diff --git a/src/Greenshot/Languages/website/language-website-fr-FR.xml b/Greenshot/Languages/website/language-website-fr-FR.xml
similarity index 92%
rename from src/Greenshot/Languages/website/language-website-fr-FR.xml
rename to Greenshot/Languages/website/language-website-fr-FR.xml
index c8121ddd2..54943cced 100644
--- a/src/Greenshot/Languages/website/language-website-fr-FR.xml
+++ b/Greenshot/Languages/website/language-website-fr-FR.xml
@@ -5,7 +5,7 @@
Greenshot - Un outil de capture d’écran gratuit pour une productivité optimaleGreenshot 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.
+ 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?
diff --git a/src/Greenshot/Languages/website/language-website-it-IT.xml b/Greenshot/Languages/website/language-website-it-IT.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-it-IT.xml
rename to Greenshot/Languages/website/language-website-it-IT.xml
index 209be7f15..6e4d8c737 100644
--- a/src/Greenshot/Languages/website/language-website-it-IT.xml
+++ b/Greenshot/Languages/website/language-website-it-IT.xml
@@ -5,7 +5,7 @@
Greenshot - è uno strumento di cattura gratuito ottimizzato per la produttivitàGreenshot è gratuito ed open sourceSe scopri che Greenshot ti fa risparmiare un sacco di tempo e/o denaro, puoi <a href="/support/">sostenere lo sviluppo</a> di questa strumento di cattura.
- Greenshot è pubblicato sotto licenza <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>. Questo software può essere scaricato e usato gratuitamente, anche in un ambiente commerciale.
+ 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 usato gratuitamente, anche in un ambiente commerciale.Vuoi saperne di più?Naturalmente Greenshot pò fare molto di più per te. Guarda alcunr <a title="schermate di Greenshot in azione" href="/screenshots/">screenshots</a> of Greenshot in action or try the <a title="Scarica la versione stabile più recente di Greenshot" href="/downloads/">latest release</a>.Greenshot - Che cosa è questo?
diff --git a/src/Greenshot/Languages/website/language-website-lv-LV.xml b/Greenshot/Languages/website/language-website-lv-LV.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-lv-LV.xml
rename to Greenshot/Languages/website/language-website-lv-LV.xml
index e8e854415..c9b5739a1 100644
--- a/src/Greenshot/Languages/website/language-website-lv-LV.xml
+++ b/Greenshot/Languages/website/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ūraJa „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/website/language-website-nn-NO.xml
similarity index 100%
rename from src/Greenshot/Languages/website/language-website-nn-NO.xml
rename to Greenshot/Languages/website/language-website-nn-NO.xml
diff --git a/src/Greenshot/Languages/website/language-website-pt-BR.xml b/Greenshot/Languages/website/language-website-pt-BR.xml
similarity index 91%
rename from src/Greenshot/Languages/website/language-website-pt-BR.xml
rename to Greenshot/Languages/website/language-website-pt-BR.xml
index d9b152463..3549a06ae 100644
--- a/src/Greenshot/Languages/website/language-website-pt-BR.xml
+++ b/Greenshot/Languages/website/language-website-pt-BR.xml
@@ -5,7 +5,7 @@
Greenshot - uma ferramenta de captura de tela gratuito e otimizado para a produtividadeGreenshot é gratuito e open sourceSe você achar que Greenshot economiza um monte de tempo e dinheiro, você é muito bem-vindo ao <a href="/support/">apoiar o desenvolvimento</a> deste software de captura de tela.
- Greenshot foi publicado <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, e.x. este software pode ser baixado e usado gratuitamente, mesmo em um ambiente comercial.
+ Greenshot foi publicado <a href="http://en.wikipedia.org/wiki/GNU_General_Public_License" target="_blank">GPL</a>, e.x. este software pode ser baixado e usado gratuitamente, mesmo em um ambiente comercial.Quer ver mais?Claro que há mais que Greenshot pode fazer por você. Ter um olhar para alguns <a title="Imagens do Greenshot em ação" href="/screenshots/">screenshots</a> de Greenshot em ação ou tentar <a title="Baixe a versão mais recente estável do Greenshot" href="/downloads/">latest release</a>.O que é Greenshot????
diff --git a/src/Greenshot/Languages/website/language-website-sv-SE.xml b/Greenshot/Languages/website/language-website-sv-SE.xml
similarity index 100%
rename from src/Greenshot/Languages/website/language-website-sv-SE.xml
rename to Greenshot/Languages/website/language-website-sv-SE.xml
diff --git a/src/Greenshot/Languages/website/language-website-uk-UA.xml b/Greenshot/Languages/website/language-website-uk-UA.xml
similarity index 100%
rename from src/Greenshot/Languages/website/language-website-uk-UA.xml
rename to Greenshot/Languages/website/language-website-uk-UA.xml
diff --git a/Greenshot/Memento/AddElementMemento.cs b/Greenshot/Memento/AddElementMemento.cs
new file mode 100644
index 000000000..07b4f18d3
--- /dev/null
+++ b/Greenshot/Memento/AddElementMemento.cs
@@ -0,0 +1,67 @@
+/*
+ * 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 .
+ */
+using System;
+using Greenshot.Drawing;
+using GreenshotPlugin.Interfaces.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..1f73f2106
--- /dev/null
+++ b/Greenshot/Memento/AddElementsMemento.cs
@@ -0,0 +1,71 @@
+/*
+ * 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 .
+ */
+using Greenshot.Drawing;
+using GreenshotPlugin.Interfaces.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..225e8de20
--- /dev/null
+++ b/Greenshot/Memento/ChangeFieldHolderMemento.cs
@@ -0,0 +1,76 @@
+/*
+ * 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 .
+ */
+
+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)
+ {
+ if (otherMemento is not ChangeFieldHolderMemento other) return false;
+
+ if (!other._drawableContainer.Equals(_drawableContainer)) return false;
+
+ return other._fieldToBeChanged.Equals(_fieldToBeChanged);
+ }
+
+ 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..cf921713f
--- /dev/null
+++ b/Greenshot/Memento/DeleteElementMemento.cs
@@ -0,0 +1,73 @@
+/*
+ * 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 .
+ */
+using System;
+using Greenshot.Drawing;
+using GreenshotPlugin.Interfaces.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) {
+ _surface = surface;
+ _drawableContainer = drawableContainer;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+
+ if (_drawableContainer != null) {
+ _drawableContainer.Dispose();
+ _drawableContainer = null;
+ }
+ }
+
+ public bool Merge(IMemento otherMemento) {
+ return false;
+ }
+
+ public IMemento Restore() {
+ // Before
+ _drawableContainer.Invalidate();
+
+ var 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..33b0fe0ac
--- /dev/null
+++ b/Greenshot/Memento/DeleteElementsMemento.cs
@@ -0,0 +1,69 @@
+/*
+ * 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 .
+ */
+using Greenshot.Drawing;
+using GreenshotPlugin.Interfaces.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()
+ {
+ var 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..32870a88a
--- /dev/null
+++ b/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs
@@ -0,0 +1,108 @@
+/*
+ * 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 .
+ */
+using Greenshot.Drawing;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Drawing;
+using GreenshotPlugin.Interfaces.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();
+ private readonly List _sizes = new();
+ 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)
+ {
+ if (otherMemento is not DrawableContainerBoundsChangeMemento other) return false;
+
+ 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/SurfaceBackgroundChangeMemento.cs b/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs
new file mode 100644
index 000000000..a20823878
--- /dev/null
+++ b/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs
@@ -0,0 +1,74 @@
+/*
+ * 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 .
+ */
+
+using Greenshot.Drawing;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using GreenshotPlugin.Interfaces.Drawing;
+
+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) return;
+
+ 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..4971b8ff0
--- /dev/null
+++ b/Greenshot/Memento/TextChangeMemento.cs
@@ -0,0 +1,64 @@
+/*
+ * 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 .
+ */
+
+using Greenshot.Drawing;
+using GreenshotPlugin.Interfaces.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) {
+ _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) {
+ if (otherMemento is not TextChangeMemento other) return false;
+
+ return other._textContainer.Equals(_textContainer);
+ }
+
+ public IMemento Restore() {
+ // Before
+ _textContainer.Invalidate();
+ TextChangeMemento oldState = new TextChangeMemento(_textContainer);
+ _textContainer.ChangeText(_oldText, false);
+ // After
+ _textContainer.Invalidate();
+ return oldState;
+ }
+ }
+}
diff --git a/src/Greenshot/Processors/TitleFixProcessor.cs b/Greenshot/Processors/TitleFixProcessor.cs
similarity index 55%
rename from src/Greenshot/Processors/TitleFixProcessor.cs
rename to Greenshot/Processors/TitleFixProcessor.cs
index 4167243d3..7bcc59f01 100644
--- a/src/Greenshot/Processors/TitleFixProcessor.cs
+++ b/Greenshot/Processors/TitleFixProcessor.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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,31 +16,27 @@
* GNU General 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.Collections.Generic;
using System.Text.RegularExpressions;
-using Greenshot.Base.Core;
-using Greenshot.Base.IniFile;
-using Greenshot.Base.Interfaces;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
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();
+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)
- {
+ public TitleFixProcessor() {
+ List corruptKeys = new List();
+ foreach(string key in config.ActiveTitleFixes) {
if (config.TitleFixMatcher.ContainsKey(key)) continue;
LOG.WarnFormat("Key {0} not found, configuration is broken! Disabling this key!", key);
@@ -50,14 +46,12 @@ namespace Greenshot.Processors
// Fix configuration if needed
if (corruptKeys.Count <= 0) return;
- foreach (string corruptKey in corruptKeys)
- {
+ 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;
}
@@ -65,17 +59,14 @@ namespace Greenshot.Processors
public override string Description => 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] ?? string.Empty;
+ 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] ?? string.Empty;
if (string.IsNullOrEmpty(regexpString)) continue;
@@ -83,10 +74,9 @@ namespace Greenshot.Processors
title = regex.Replace(title, replaceString);
changed = true;
}
- }
-
- captureDetails.Title = title;
- return changed;
- }
- }
-}
\ No newline at end of file
+ }
+ captureDetails.Title = title;
+ return changed;
+ }
+ }
+}
diff --git a/src/Greenshot/Sounds.resx b/Greenshot/Sounds.resx
similarity index 100%
rename from src/Greenshot/Sounds.resx
rename to Greenshot/Sounds.resx
diff --git a/src/Greenshot/greenshot.manifest b/Greenshot/greenshot.manifest
similarity index 96%
rename from src/Greenshot/greenshot.manifest
rename to Greenshot/greenshot.manifest
index fa9d5520d..89cf7a2b6 100644
--- a/src/Greenshot/greenshot.manifest
+++ b/Greenshot/greenshot.manifest
@@ -16,7 +16,7 @@
-
+
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-zoom-actual.png b/Greenshot/icons/fugue/magnifier-zoom-actual.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier-zoom-actual.png
rename to Greenshot/icons/fugue/magnifier-zoom-actual.png
diff --git a/src/Greenshot/icons/fugue/magnifier-zoom-fit.png b/Greenshot/icons/fugue/magnifier-zoom-fit.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier-zoom-fit.png
rename to Greenshot/icons/fugue/magnifier-zoom-fit.png
diff --git a/src/Greenshot/icons/fugue/magnifier-zoom-in.png b/Greenshot/icons/fugue/magnifier-zoom-in.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier-zoom-in.png
rename to Greenshot/icons/fugue/magnifier-zoom-in.png
diff --git a/src/Greenshot/icons/fugue/magnifier-zoom-out.png b/Greenshot/icons/fugue/magnifier-zoom-out.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier-zoom-out.png
rename to Greenshot/icons/fugue/magnifier-zoom-out.png
diff --git a/src/Greenshot/icons/fugue/magnifier-zoom.png b/Greenshot/icons/fugue/magnifier-zoom.png
similarity index 100%
rename from src/Greenshot/icons/fugue/magnifier-zoom.png
rename to Greenshot/icons/fugue/magnifier-zoom.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/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
similarity index 74%
rename from installer/additional_files/readme.txt
rename to Greenshot/releases/additional_files/readme.txt
index bdb64e2c4..fc8c4c8c5 100644
--- a/installer/additional_files/readme.txt
+++ b/Greenshot/releases/additional_files/readme.txt
@@ -7,117 +7,10 @@ CHANGE LOG:
All details to our tickets can be found here: https://greenshot.atlassian.net
-# Greenshot 1.3.xxx
+Greenshot 1.3.xx RELEASE
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
+* [BUG-xxxx] - xxxx
Greenshot 1.2.10 RELEASE
@@ -668,5 +561,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/installer/innosetup/Languages/Afrikaans.isl b/Greenshot/releases/innosetup/Languages/Afrikaans.isl
similarity index 100%
rename from installer/innosetup/Languages/Afrikaans.isl
rename to Greenshot/releases/innosetup/Languages/Afrikaans.isl
diff --git a/installer/innosetup/Languages/Albanian.isl b/Greenshot/releases/innosetup/Languages/Albanian.isl
similarity index 100%
rename from installer/innosetup/Languages/Albanian.isl
rename to Greenshot/releases/innosetup/Languages/Albanian.isl
diff --git a/installer/innosetup/Languages/Arabic.isl b/Greenshot/releases/innosetup/Languages/Arabic.isl
similarity index 92%
rename from installer/innosetup/Languages/Arabic.isl
rename to Greenshot/releases/innosetup/Languages/Arabic.isl
index 03f29258d..cc25fe2cd 100644
--- a/installer/innosetup/Languages/Arabic.isl
+++ b/Greenshot/releases/innosetup/Languages/Arabic.isl
@@ -1,4 +1,4 @@
-; *** Inno Setup version 6.1.0+ arabic messages ***
+; *** Inno Setup version 6.0.3+ arabic messages ***
;
; Translated by nacer baaziz (nacerstile@gmail.com)
; http://www.jrsoftware.org/files/istrans/
@@ -14,7 +14,6 @@
LanguageName=arabic
LanguageID=$0401
LanguageCodePage=0
-RightToLeft=yes
; If the language you are translating to requires special font faces or
; sizes, uncomment any of the following entries and change them accordingly.
;DialogFontName=
@@ -71,8 +70,8 @@ PrivilegesRequiredOverrideText1=يمكن ل %1 أن يُثَبَّت على جم
PrivilegesRequiredOverrideText2=.يمكن ل %1 أن يُثَبَّت لك فقط, أو أن يُثَبَّت على جميع المستخدمين (يتطلب إمتيازات المسؤول).
PrivilegesRequiredOverrideAllUsers=التثبيت ل&كافة المستخدمين
PrivilegesRequiredOverrideAllUsersRecommended=تثبيت ل&كافة المستخدمين (مستحسن)
-PrivilegesRequiredOverrideCurrentUser=تثبيت لي &فقط
-PrivilegesRequiredOverrideCurrentUserRecommended=تثبيت بالنسبة لي &فقط (مستحسن)
+PrivilegesRequiredOverrideCurrentUser=تثبيت &لي فقط
+PrivilegesRequiredOverrideCurrentUserRecommended=تثبيت بالنسبة &لي فقط (مستحسن)
; *** Misc. errors
ErrorCreatingDir=تعذر على برنامج الإعداد إنشاء الدليل "%1"
@@ -211,18 +210,6 @@ ReadyMemoComponents=المكونات المحددة:
ReadyMemoGroup=مجلد قائمة ابدأ:
ReadyMemoTasks=مهام إضافية:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=تحميل الملفات الإضافية...
-ButtonStopDownload=إي&قاف التحميل
-StopDownload=هل أنت متأكد من أنك ترغب في إيقاف التحميل؟
-ErrorDownloadAborted=تم إلغاء التحميل
-ErrorDownloadFailed=فشل التحميل: %1 %2
-ErrorDownloadSizeFailed=خطأ في قراءة الحجم: %1 %2
-ErrorFileHash1=خطأ في قراءة الهاش الخاص بالملف: %1
-ErrorFileHash2=خطأ في هاش الملف: كان من المتوقع أن يكن : %1, بينما تم إيجاد : %2
-ErrorProgress=خطأ في الحصول على نسبة التقدم: %1 من %2
-ErrorFileSize=خطأ في حجم الملف: المتوقع هو : %1, الحجم الذي وجدناه هو : %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=التحضير للتثبيت
PreparingDesc=الإعداد يستعد لتثبيت [name] على جهازك.
@@ -305,16 +292,8 @@ ExistingFileReadOnly2=تعذر استبدال الملف الموجود لأنه
ExistingFileReadOnlyRetry=&أزل القراءة فقط عن الملفات ثم حاول مرة أخرى
ExistingFileReadOnlyKeepExisting=&إحتفظ بالملفات الموجودة
ErrorReadingExistingDest=حدث خطأ أثناء محاولة قراءة الملف الموجود:
-FileExistsSelectAction=اختر إجراء
-FileExists2=الملف موجود بالفعل.
-FileExistsOverwriteExisting=&استبدال الملف الموجود
-FileExistsKeepExisting=ا&بقاء الملف الموجود
-FileExistsOverwriteOrKeepAll=ا&فعل هذا للنزاعات القادمة
-ExistingFileNewerSelectAction=اختر إجراء
-ExistingFileNewer2=الملف الموجود أحدث من الملف الذي سيقوم معالج الإعداد بتثبيته.
-ExistingFileNewerOverwriteExisting=&&استبدال الملف الموجود
-ExistingFileNewerKeepExisting=ال&ابقاء على الملف الموجود (مستحسن)
-ExistingFileNewerOverwriteOrKeepAll=ا&فعل هذا مع النزاعات القادمة
+FileExists=الملف موجود مسبقاً.%n%nهل تريد لبرنامج الإعداد أن يكتب استبداله؟
+ExistingFileNewer=الملف الموجود أحدث من الذي يحاول الإعداد تثبيته. من المستحسن الاحتفاظ بالملف الموجود.%n%nهل تريد الاحتفاظ بالملف الموجود؟
ErrorChangingAttr=حدث خطأ أثناء محاولة تغيير سمات الملف الموجود:
ErrorCreatingTemp=حدث خطأ أثناء محاولة إنشاء ملف في الدليل الوجهة:
ErrorReadingSource=حدث خطأ أثناء محاولة قراءة ملف مصدر:
diff --git a/installer/innosetup/Languages/Asturian.isl b/Greenshot/releases/innosetup/Languages/Asturian.isl
similarity index 100%
rename from installer/innosetup/Languages/Asturian.isl
rename to Greenshot/releases/innosetup/Languages/Asturian.isl
diff --git a/installer/innosetup/Languages/Basque.isl b/Greenshot/releases/innosetup/Languages/Basque.isl
similarity index 100%
rename from installer/innosetup/Languages/Basque.isl
rename to Greenshot/releases/innosetup/Languages/Basque.isl
diff --git a/installer/innosetup/Languages/Belarusian.isl b/Greenshot/releases/innosetup/Languages/Belarusian.isl
similarity index 100%
rename from installer/innosetup/Languages/Belarusian.isl
rename to Greenshot/releases/innosetup/Languages/Belarusian.isl
diff --git a/installer/innosetup/Languages/Bengali.islu b/Greenshot/releases/innosetup/Languages/Bengali.islu
similarity index 100%
rename from installer/innosetup/Languages/Bengali.islu
rename to Greenshot/releases/innosetup/Languages/Bengali.islu
diff --git a/Greenshot/releases/innosetup/Languages/Bosnian.isl b/Greenshot/releases/innosetup/Languages/Bosnian.isl
new file mode 100644
index 000000000..93488c918
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Bosnian.isl
@@ -0,0 +1,329 @@
+; *** Inno Setup version 5.5.3+ Bosnian messages ***
+;
+; Bosnian translation by Kenan Dervisevic (kenan3008@gmail.com)
+;
+
+[LangOptions]
+LanguageName=Bosanski
+LanguageID=$141a
+LanguageCodePage=1250
+; 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=Instalacija
+SetupWindowTitle=Instalacija - %1
+UninstallAppTitle=Deinstalacija
+UninstallAppFullTitle=%1 Deinstalacija
+
+; *** Misc. common
+InformationTitle=Informacija
+ConfirmTitle=Potvrda
+ErrorTitle=Greka
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=Zapoeli ste instalaciju programa %1. elite li nastaviti?
+LdrCannotCreateTemp=Ne mogu kreirati privremenu datoteku. Instalacija prekinuta
+LdrCannotExecTemp=Ne mogu izvriti datoteku u privremenom folderu. Instalacija prekinuta
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%nGreka %2: %3
+SetupFileMissing=Datoteka %1 se ne nalazi u instalacijskom folderu. Molimo vas da rijeite problem ili nabavite novu kopiju programa.
+SetupFileCorrupt=Instalacijske datoteke sadre greku. Molimo vas da nabavite novu kopiju programa.
+SetupFileCorruptOrWrongVer=Instalacijske datoteke sadre greku, ili nisu kompatibilne sa ovom verzijom instalacije. Molimo vas rijeite problem ili nabavite novu kopiju programa.
+InvalidParameter=Neispravan parametar je proslijeen komandnoj liniji:%n%n%1
+SetupAlreadyRunning=Instalacija je ve pokrenuta.
+WindowsVersionNotSupported=Ovaj program ne podrava verziju Windowsa koja je instalirana na ovom raunaru.
+WindowsServicePackRequired=Ovaj program zahtjeva %1 Service Pack %2 ili noviji.
+NotOnThisPlatform=Ovaj program ne radi na %1.
+OnlyOnThisPlatform=Ovaj program se mora pokrenuti na %1.
+OnlyOnTheseArchitectures=Ovaj program se moe instalirati samo na verzijama Windowsa napravljenim za sljedee arhitekture procesora:%n%n%1
+MissingWOW64APIs=Verzija Windowsa koju koristite ne sadri funkcionalnosti potrebne da bi instalacijski program mogao instalirati 64-bitnu verziju. Da bi ispravili taj problem, molimo instalirajte Service Pack %1.
+WinVersionTooLowError=Ovaj program zahtjeva %1 verzije %2 ili noviju.
+WinVersionTooHighError=Ovaj program se ne moe instalirati na %1 verziji %2 ili novijoj.
+AdminPrivilegesRequired=Morate imati administratorska prava pri instaliranju ovog programa.
+PowerUserPrivilegesRequired=Morate imati administratorska prava ili biti lan grupe Power Users prilikom instaliranja ovog programa.
+SetupAppRunningError=Instalacija je detektovala da je %1 pokrenut.%n%nMolimo zatvorite program i sve njegove kopije i potom kliknite Dalje za nastavak ili Odustani za prekid.
+UninstallAppRunningError=Deinstalacija je detektovala da je %1 trenutno pokrenut.%n%nMolimo zatvorite program i sve njegove kopije i potom kliknite Dalje za nastavak ili Odustani za prekid.
+
+; *** Misc. errors
+ErrorCreatingDir=Instalacija nije mogla kreirati folder "%1"
+ErrorTooManyFilesInDir=Instalacija nije mogla kreirati datoteku u folderu "%1" zato to on sadri previe datoteka
+
+; *** Setup common messages
+ExitSetupTitle=Prekid instalacije
+ExitSetupMessage=Instalacija nije zavrena. Ako sada izaete, program nee biti instaliran.%n%nInstalaciju moete pokrenuti kasnije u sluaju da je elite zavriti.%n%nPrekid instalacije?
+AboutSetupMenuItem=&O instalaciji...
+AboutSetupTitle=O instalaciji
+AboutSetupMessage=%1 verzija %2%n%3%n%n%1 poetna stranica:%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< Na&zad
+ButtonNext=Da&lje >
+ButtonInstall=&Instaliraj
+ButtonOK=U redu
+ButtonCancel=Otkai
+ButtonYes=&Da
+ButtonYesToAll=Da za &sve
+ButtonNo=&Ne
+ButtonNoToAll=N&e za sve
+ButtonFinish=&Zavri
+ButtonBrowse=&Izaberi...
+ButtonWizardBrowse=Iza&beri...
+ButtonNewFolder=&Napravi novi folder
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=Izaberite jezik instalacije
+SelectLanguageLabel=Izaberite jezik koji elite koristiti pri instalaciji:
+
+; *** Common wizard text
+ClickNext=Kliknite na Dalje za nastavak ili Otkai za prekid instalacije.
+BeveledLabel=
+BrowseDialogTitle=Izaberite folder
+BrowseDialogLabel=Izaberite folder iz liste ispod, pa onda kliknite na U redu.
+NewFolderName=Novi folder
+
+; *** "Welcome" wizard page
+WelcomeLabel1=Dobro doli u instalaciju programa [name]
+WelcomeLabel2=Ovaj program e instalirati [name/ver] na va raunar.%n%nPreporuujemo da zatvorite sve druge programe prije nastavka i da privremeno onemoguite va antivirus i firewall.
+
+; *** "Password" wizard page
+WizardPassword=ifra
+PasswordLabel1=Instalacija je zatiena ifrom.
+PasswordLabel3=Upiite ifru i kliknite Dalje za nastavak. ifre su osjetljive na mala i velika slova.
+PasswordEditLabel=&ifra:
+IncorrectPassword=Upisali ste pogrenu ifru. Pokuajte ponovo.
+
+; *** "License Agreement" wizard page
+WizardLicense=Ugovor o koritenju
+LicenseLabel=Molimo vas da, prije nastavka, paljivo proitajte sljedee informacije.
+LicenseLabel3=Molimo vas da paljivo proitate Ugovor o koritenju. Morate prihvatiti uslove ugovora kako biste mogli nastaviti s instalacijom.
+LicenseAccepted=&Prihvatam ugovor
+LicenseNotAccepted=&Ne prihvatam ugovor
+
+; *** "Information" wizard pages
+WizardInfoBefore=Informacija
+InfoBeforeLabel=Molimo vas da, prije nastavka, proitate sljedee informacije.
+InfoBeforeClickLabel=Kada budete spremni nastaviti instalaciju, kliknite na Dalje.
+WizardInfoAfter=Informacija
+InfoAfterLabel=Molimo vas da, prije nastavka, proitate sljedee informacije.
+InfoAfterClickLabel=Kada budete spremni nastaviti instalaciju, kliknite na Dalje.
+
+; *** "User Information" wizard page
+WizardUserInfo=Informacije o korisniku
+UserInfoDesc=Upiite vae line informacije.
+UserInfoName=&Ime korisnika:
+UserInfoOrg=&Organizacija:
+UserInfoSerial=&Serijski broj:
+UserInfoNameRequired=Morate upisati ime.
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=Odaberite odredini folder
+SelectDirDesc=Gdje elite da instalirate [name]?
+SelectDirLabel3=Instalacija e instalirati [name] u sljedei folder.
+SelectDirBrowseLabel=Za nastavak, kliknite Dalje. Ako elite izabrati drugi folder, kliknite Izaberi.
+DiskSpaceMBLabel=Ovaj program zahtjeva najmanje [mb] MB slobodnog prostora na disku.
+CannotInstallToNetworkDrive=Instalacija nije mogua na mrenom disku.
+CannotInstallToUNCPath=Instalacija nije mogua za UNC putanju.
+InvalidPath=Morate unijeti punu putanju zajedno sa slovom diska; npr:%n%nC:\APP%n%nili UNC putanju u obliku:%n%n\\server\share
+InvalidDrive=Disk ili UNC share koji ste odabrali ne postoji ili je nedostupan. Odaberite neki drugi.
+DiskSpaceWarningTitle=Nedovoljno prostora na disku
+DiskSpaceWarning=Instalacija zahtjeva bar %1 KB slobodnog prostora, a odabrani disk ima samo %2 KB na raspolaganju.%n%nDa li elite nastaviti?
+DirNameTooLong=Naziv ili putanja do foldera su predugi.
+InvalidDirName=Naziv foldera nije ispravan.
+BadDirName32=Naziv foldera ne smije sadravati niti jedan od sljedeih znakova:%n%n%1
+DirExistsTitle=Folder postoji
+DirExists=Folder:%n%n%1%n%nve postoji. elite li i dalje izvriti instalaciju u njega?
+DirDoesntExistTitle=Folder ne postoji
+DirDoesntExist=Folder:%n%n%1%n%nne postoji. elite li ga napraviti?
+
+; *** "Select Components" wizard page
+WizardSelectComponents=Odaberite komponente
+SelectComponentsDesc=Koje komponente elite instalirati?
+SelectComponentsLabel2=Odaberite komponente koje elite instalirati ili uklonite kvaicu pored komponenti koje ne elite. Kliknite Dalje kad budete spremni da nastavite.
+FullInstallation=Puna instalacija
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=Kompaktna instalacija
+CustomInstallation=Instalacija prema elji
+NoUninstallWarningTitle=Komponente postoje
+NoUninstallWarning=Instalacija je detektovala da na vaem raunaru ve postoje sljedee komponente:%n%n%1%n%nAko ove komponente ne odaberete, nee doi do njihove deinstalacije.%n%nelite li ipak nastaviti?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=Trenutni izbor zahtjeva bar [mb] MB prostora na disku.
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=Izaberite dodatne radnje
+SelectTasksDesc=Koje dodatne radnje elite da se izvre?
+SelectTasksLabel2=Izaberite radnje koje e se izvriti tokom instalacije programa [name], onda kliknite Dalje.
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=Izaberite programsku grupu
+SelectStartMenuFolderDesc=Gdje instalacija treba da napravi preice?
+SelectStartMenuFolderLabel3=Izaberite folder iz Start menija u koji elite da instalacija kreira preicu, a zatim kliknite na Dalje.
+SelectStartMenuFolderBrowseLabel=Za nastavak, kliknite Dalje. Ako elite da izaberete drugi folder, kliknite Izaberi.
+MustEnterGroupName=Morate unijeti ime programske grupe.
+GroupNameTooLong=Naziv foldera ili putanje je predug.
+InvalidGroupName=Naziv foldera nije ispravan.
+BadGroupName=Naziv foldera ne smije sadravati niti jedan od sljedeih znakova:%n%n%1
+NoProgramGroupCheck2=&Ne kreiraj programsku grupu
+
+; *** "Ready to Install" wizard page
+WizardReady=Spreman za instalaciju
+ReadyLabel1=Sada smo spremni za instalaciju [name] na va raunar.
+ReadyLabel2a=Kliknite na Instaliraj ako elite instalirati program ili na Nazad ako elite pregledati ili promjeniti postavke.
+ReadyLabel2b=Kliknite na Instaliraj ako elite nastaviti sa instalacijom programa.
+ReadyMemoUserInfo=Informacije o korisniku:
+ReadyMemoDir=Odredini folder:
+ReadyMemoType=Tip instalacije:
+ReadyMemoComponents=Odabrane komponente:
+ReadyMemoGroup=Programska grupa:
+ReadyMemoTasks=Dodatne radnje:
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=Pripremam instalaciju
+PreparingDesc=Pripreme za instalaciju [name] na va raunar.
+PreviousInstallNotCompleted=Instalacija/deinstalacija prethodnog programa nije zavrena. Morate restartovati va raunar kako bi zavrili tu instalaciju.%n%nNakon toga, ponovno pokrenite ovaj program kako bi dovrili instalaciju za [name].
+CannotContinue=Instalacija ne moe nastaviti. Molimo vas da kliknete na Odustani za izlaz.
+ApplicationsFound=Sljedee aplikacije koriste datoteke koje ova instalacija treba da nadogradi. Preporuujemo vam da omoguite instalaciji da automatski zatvori ove aplikacije.
+ApplicationsFound2=Sljedee aplikacije koriste datoteke koje ova instalacija treba da nadogradi. Preporuujemo vam da omoguite instalaciji da automatski zatvori ove aplikacije. Nakon to se sve zavri, bit e izvren pokuaj ponovnog pokretanja ovih aplikacija.
+CloseApplications=&Automatski zatvori aplikacije
+DontCloseApplications=&Ne zatvaraj aplikacije
+ErrorCloseApplications=Instalacija nije mogla automatski zatvoriti sve aplikacije. Prije nego nastavite, preporuujemo vam da zatvorite sve aplikacije koje koriste datoteke koje e ova instalacija trebati da aurira.
+
+; *** "Installing" wizard page
+WizardInstalling=Instaliram
+InstallingLabel=Priekajte dok se ne zavri instalacija programa [name] na va raunar.
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel=Zavravam instalaciju [name]
+FinishedLabelNoIcons=Instalacija programa [name] je zavrena.
+FinishedLabel=Instalacija programa [name] je zavrena. Program moete pokrenuti koristei instalirane ikone.
+ClickFinish=Kliknite na Zavri da biste izali iz instalacije.
+FinishedRestartLabel=Da biste instalaciju programa [name] zavrili, potrebno je restartovati raunar. elite li to sada uiniti?
+FinishedRestartMessage=Zavretak instalacije programa [name] zahtjeva restart vaeg raunara.%n%nelite li to sada uiniti?
+ShowReadmeCheck=Da, elim proitati README datoteku.
+YesRadio=&Da, restartuj raunar sada
+NoRadio=&Ne, restartovat u raunar kasnije
+; used for example as 'Run MyProg.exe'
+RunEntryExec=Pokreni %1
+; used for example as 'View Readme.txt'
+RunEntryShellExec=Proitaj %1
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=Instalacija treba sljedei disk
+SelectDiskLabel2=Molimo ubacite Disk %1 i kliknite U redu.%n%nAko se datoteke na ovom disku nalaze u drugom folderu a ne u onom prikazanom ispod, unesite ispravnu putanju ili kliknite na Izaberi.
+PathLabel=&Putanja:
+FileNotInDir2=Datoteka "%1" ne postoji u "%2". Molimo vas ubacite odgovorajui disk ili odaberete drugi folder.
+SelectDirectoryLabel=Molimo odaberite lokaciju sljedeeg diska.
+
+; *** Installation phase messages
+SetupAborted=Instalacija nije zavrena.%n%nMolimo vas da rijeite problem i opet pokrenete instalaciju.
+EntryAbortRetryIgnore=Kliknite na Retry da pokuate opet, Ignore da nastavite, ili Abort da prekinete instalaciju.
+
+; *** Installation status messages
+StatusClosingApplications=Zatvaram aplikacije...
+StatusCreateDirs=Kreiram foldere...
+StatusExtractFiles=Raspakujem datoteke...
+StatusCreateIcons=Kreiram preice...
+StatusCreateIniEntries=Kreiram INI datoteke...
+StatusCreateRegistryEntries=Kreiram podatke za registracijsku bazu...
+StatusRegisterFiles=Registrujem datoteke...
+StatusSavingUninstall=Snimam deinstalacijske informacije...
+StatusRunProgram=Zavravam instalaciju...
+StatusRestartingApplications=Restartujem aplikaciju...
+StatusRollback=Ponitavam promjene...
+
+; *** Misc. errors
+ErrorInternal2=Interna greka: %1
+ErrorFunctionFailedNoCode=%1 nije uspjelo
+ErrorFunctionFailed=%1 nije uspjelo; kod %2
+ErrorFunctionFailedWithMessage=%1 nije uspjelo; kod %2.%n%3
+ErrorExecutingProgram=Ne mogu pokrenuti datoteku:%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=Greka pri otvaranju registracijskog kljua:%n%1\%2
+ErrorRegCreateKey=Greka pri kreiranju registracijskog kljua:%n%1\%2
+ErrorRegWriteKey=Greka pri zapisivanju registracijskog kljua:%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=Greka pri kreiranju INI podataka u datoteci "%1".
+
+; *** File copying errors
+FileAbortRetryIgnore=Kliknite Retry da pokuate ponovo, Ignore da preskoite ovu datoteku (nije preporueno), ili Abort da prekinete instalaciju.
+FileAbortRetryIgnore2=Kliknite Retry da pokuate ponovo, Ignore da preskoite ovu datoteku (nije preporueno), ili Abort da prekinete instalaciju.
+SourceIsCorrupted=Izvorna datoteka je oteena
+SourceDoesntExist=Izvorna datoteka "%1" ne postoji
+ExistingFileReadOnly=Postojea datoteka je oznaena kao samo za itanje.%n%nKliknite Retry da uklonite ovu oznaku i pokuate ponovo, Ignore da preskoite ovu datoteku, ili Abort da prekinete instalaciju.
+ErrorReadingExistingDest=Dolo je do greke prilikom pokuaja itanja postojee datoteke:
+FileExists=Datoteka ve postoji.%n%nelite li pisati preko nje?
+ExistingFileNewer=Postojea datoteka je novija od one koju pokuavate instalirati. Preporuujemo vam da zadrite postojeu datoteku.%n%nelite li zadrati postojeu datoteku?
+ErrorChangingAttr=Pojavila se greka prilikom pokuaja promjene atributa postojee datoteke:
+ErrorCreatingTemp=Pojavila se greka prilikom pokuaja kreiranja datoteke u odredinom folderu:
+ErrorReadingSource=Pojavila se greka prilikom pokuaja itanja izvorne datoteke:
+ErrorCopying=Pojavila se greka prilikom pokuaja kopiranja datoteke:
+ErrorReplacingExistingFile=Pojavila se greka prilikom pokuaja zamjene datoteke:
+ErrorRestartReplace=Ponovno pokretanje i zamjena nije uspjela:
+ErrorRenamingTemp=Pojavila se greka prilikom pokuaja preimenovanja datoteke u odredinom folderu:
+ErrorRegisterServer=Ne mogu registrovati DLL/OCX: %1
+ErrorRegSvr32Failed=RegSvr32 nije ispravno izvren, kod na kraju izvravanja %1
+ErrorRegisterTypeLib=Ne mogu registrovati tip biblioteke: %1
+
+; *** Post-installation errors
+ErrorOpeningReadme=Pojavila se greka prilikom pokuaja otvaranja README datoteke.
+ErrorRestartingComputer=Instalacija ne moe restartovati va raunar. Molimo vas da to uinite runo.
+
+; *** Uninstaller messages
+UninstallNotFound=Datoteka "%1" ne postoji. Deinstalacija prekinuta.
+UninstallOpenError=Datoteka "%1" se ne moe otvoriti. Deinstalacija nije mogua
+UninstallUnsupportedVer=Deinstalacijska log datoteka "%1" je u formatu koji nije prepoznat od ove verzije deinstalera. Nije mogua deinstalacija
+UninstallUnknownEntry=Nepoznat zapis (%1) je pronadjen u deinstalacijskoj log datoteci
+ConfirmUninstall=Da li ste sigurni da elite ukloniti %1 i sve njegove komponente?
+UninstallOnlyOnWin64=Ovaj program se moe deinstalirati samo na 64-bitnom Windowsu.
+OnlyAdminCanUninstall=Ova instalacija moe biti uklonjena samo od korisnika sa administratorskim privilegijama.
+UninstallStatusLabel=Molimo priekajte dok %1 ne bude uklonjen s vaeg raunara.
+UninstalledAll=Program %1 je uspjeno uklonjen sa vaeg raunara.
+UninstalledMost=Deinstalacija programa %1 je zavrena.%n%nNeke elemente nije bilo mogue ukloniti. Molimo vas da to uinite runo.
+UninstalledAndNeedsRestart=Da bi zavrili deinstalaciju %1, Va raunar morate restartati%n%nelite li to uiniti sada?
+UninstallDataCorrupted="%1" datoteka je oteena. Deinstalacija nije mogua.
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=Ukloni dijeljenu datoteku
+ConfirmDeleteSharedFile2=Sistem smatra da sljedee dijeljene datoteke ne koristi nijedan drugi program. elite li ukloniti te dijeljene datoteke?%n%nAko neki programi i dalje koriste ove datoteke, a one se obriu, ti programi nee raditi ispravno. Ako niste sigurni, odaberite Ne. Ostavljanje datoteka nee uzrokovati tetu vaem sistemu.
+SharedFileNameLabel=Datoteka:
+SharedFileLocationLabel=Putanja:
+WizardUninstalling=Status deinstalacije
+StatusUninstalling=Deinstaliram %1...
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=Instaliram %1.
+ShutdownBlockReasonUninstallingApp=Deinstaliram %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 verzija %2
+AdditionalIcons=Dodatne ikone:
+CreateDesktopIcon=Kreiraj &desktop ikonu
+CreateQuickLaunchIcon=Kreiraj ikonu za &brzo pokretanje
+ProgramOnTheWeb=%1 na webu
+UninstallProgram=Deinstaliraj %1
+LaunchProgram=Pokreni %1
+AssocFileExtension=&Asociraj %1 sa %2 ekstenzijom
+AssocingFileExtension=Asociram %1 sa %2 ekstenzijom...
+AutoStartProgramGroupDescription=Pokretanje:
+AutoStartProgram=Automatski pokrei %1
+AddonHostProgramNotFound=%1 nije mogao biti pronaen u folderu koji ste odabrali.%n%nDa li i dalje elite nastaviti s ovom akcijom?
diff --git a/installer/innosetup/Languages/Bulgarian.isl b/Greenshot/releases/innosetup/Languages/Bulgarian.isl
similarity index 89%
rename from installer/innosetup/Languages/Bulgarian.isl
rename to Greenshot/releases/innosetup/Languages/Bulgarian.isl
index 923aee293..65330ca41 100644
--- a/installer/innosetup/Languages/Bulgarian.isl
+++ b/Greenshot/releases/innosetup/Languages/Bulgarian.isl
@@ -1,4 +1,4 @@
-; *** Inno Setup version 6.1.0+ Bulgarian messages ***
+; *** Inno Setup version 6.0.0+ Bulgarian messages ***
; Ventsislav Dimitrov
;
; За да изтеглите преводи на този файл, предоставени от потребители, посетете:
@@ -114,7 +114,7 @@ NewFolderName=Нова папка
; *** Страница "Добре дошли" на съветника
WelcomeLabel1=Добре дошли при Съветника за инсталиране на [name]
-WelcomeLabel2=Съветникът ще инсталира [name/ver] във Вашия компютър.%n%nПрепоръчва се да затворите всички останали приложения, преди да продължите.
+WelcomeLabel2=Съветникът ще инсталира [name/ver] във вашия компютър.%n%nПрепоръчва се да затворите всички останали приложения, преди да продължите.
; *** Страница "Парола" на съветника
WizardPassword=Парола
@@ -151,7 +151,6 @@ WizardSelectDir=Избор на местоназначение
SelectDirDesc=Къде да се инсталира [name]?
SelectDirLabel3=[name] ще се инсталира в следната папка.
SelectDirBrowseLabel=Натиснете "Напред", за да продължите. За да изберете друга папка, натиснете "Преглед".
-DiskSpaceGBLabel=Изискват се поне [gb] ГБ свободно дисково пространство.
DiskSpaceMBLabel=Изискват се поне [mb] МБ свободно дисково пространство.
CannotInstallToNetworkDrive=Инсталаторът не може да инсталира на мрежово устройство.
CannotInstallToUNCPath=Инсталаторът не може да инсталира в UNC път.
@@ -172,14 +171,13 @@ WizardSelectComponents=Избор на компоненти
SelectComponentsDesc=Кои компоненти да бъдат инсталирани?
SelectComponentsLabel2=Изберете компонентите, които желаете да инсталирате, и откажете нежеланите. Натиснете "Напред", когато сте готов да продължите.
FullInstallation=Пълна инсталация
-; По възможност не превеждайте "Compact" като "Minimal" (има се предвид "Minimal" на Вашия език)
+; По възможност не превеждайте "Compact" като "Minimal" (има се предвид "Minimal" на вашия език)
CompactInstallation=Компактна инсталация
CustomInstallation=Инсталация по избор
NoUninstallWarningTitle=Компонентите съществуват
NoUninstallWarning=Инсталаторът установи, че следните компоненти са вече инсталирани в компютърa:%n%n%1%n%nОтказването на тези компоненти няма да ги деинсталира.%n%nЖелаете ли все пак да продължите?
ComponentSize1=%1 кБ
ComponentSize2=%1 МБ
-ComponentsDiskSpaceGBLabel=Направеният избор изисква поне [gb] ГБ дисково пространство.
ComponentsDiskSpaceMBLabel=Направеният избор изисква поне [mb] МБ дисково пространство.
; *** Страница "Избор на допълнителни задачи" на съветника
@@ -200,7 +198,7 @@ NoProgramGroupCheck2=И&нсталиране без папка в менюто "
; *** Страница "Готовност за инсталиране" на съветника
WizardReady=Готовност за инсталиране
-ReadyLabel1=Инсталаторът е готов да инсталира [name] във Вашия компютър.
+ReadyLabel1=Инсталаторът е готов да инсталира [name] във вашия компютър.
ReadyLabel2a=Натиснете "Инсталиране", за да продължите, или "Назад" за преглед или промяна на някои настройки.
ReadyLabel2b=Натиснете "Инсталиране", за да продължите с инсталирането.
ReadyMemoUserInfo=Данни за потребител:
@@ -210,21 +208,9 @@ ReadyMemoComponents=Избрани компоненти:
ReadyMemoGroup=Папка в менюто "Старт":
ReadyMemoTasks=Допълнителни задачи:
-; *** Страница "TDownloadWizardPage" на съветника и DownloadTemporaryFile
-DownloadingLabel=Изтегляне на допълнителни файлове...
-ButtonStopDownload=&Спри изтеглянето
-StopDownload=Сигурни ли сте, че искате да спрете изтеглянето?
-ErrorDownloadAborted=Изтеглянето беше прекъснато
-ErrorDownloadFailed=Изтеглянето беше неуспешно: %1 %2
-ErrorDownloadSizeFailed=Неуспешно получаване на размер: %1 %2
-ErrorFileHash1=Неуспешна контролна сума на файл: %1
-ErrorFileHash2=Невалидна контролна сума на файл: очаквана %1, открита %2
-ErrorProgress=Невалиден напредък: %1 of %2
-ErrorFileSize=Невалиден размер на файл: очакван %1, открит %2
-
; *** Страница "Подготовка за инсталиране" на съветника
WizardPreparing=Подготовка за инсталиране
-PreparingDesc=Инсталаторът се подготвя да инсталира [name] във Вашия компютър.
+PreparingDesc=Инсталаторът се подготвя да инсталира [name] във вашия компютър.
PreviousInstallNotCompleted=Инсталиране или премахване на предишна програма не е завършило. Рестартирайте компютъра, за да може процесът да завърши.%n%nСлед като рестартирате, стартирайте инсталатора отново, за да довършите инсталирането на [name].
CannotContinue=Инсталирането не може да продължи. Моля, натиснете "Отказ" за изход.
ApplicationsFound=Следните приложения използват файлове, които трябва да бъдат обновени от инсталатора. Препоръчва се да разрешите на инсталатора автоматично да затвори приложенията.
@@ -232,16 +218,15 @@ ApplicationsFound2=Следните приложения използват фа
CloseApplications=Приложенията да се затворят &автоматично
DontCloseApplications=Приложенията да &не се затварят
ErrorCloseApplications=Не бе възможно да се затворят автоматично всички приложения. Препоръчва се преди да продължите, да затворите всички приложения, използващи файлове, които инсталаторът трябва да обнови.
-PrepareToInstallNeedsRestart=Инсталаторът трябва да ресартира Вашия компютър. След рестартирането, стартирайте инсталатора отново, за да завършите инсталацията на [name].%n%nЖелаете ли да рестартирате сега?
; *** Страница "Инсталиране" на съветника
WizardInstalling=Инсталиране
-InstallingLabel=Моля, изчакайте докато [name] се инсталира във Вашия компютър.
+InstallingLabel=Моля, изчакайте докато [name] се инсталира във вашия компютър.
; *** Страница "Инсталирането завърши" на съветника
FinishedHeadingLabel=Съветникът за инсталиране на [name] завърши
-FinishedLabelNoIcons=Инсталирането на [name] във Вашия компютър завърши.
-FinishedLabel=Инсталирането на [name] във Вашия компютър завърши. Можете да стартирате приложението чрез инсталираните икони.
+FinishedLabelNoIcons=Инсталирането на [name] във вашия компютър завърши.
+FinishedLabel=Инсталирането на [name] във вашия компютър завърши. Можете да стартирате приложението чрез инсталираните икони.
ClickFinish=Натиснете "Готово", за да затворите инсталатора.
FinishedRestartLabel=Инсталаторът трябва да рестартира компютъра, за да завърши инсталирането на [name]. Желаете ли да рестартирате сега?
FinishedRestartMessage=Инсталаторът трябва да рестартира компютъра, за да завърши инсталирането на [name].%n%nЖелаете ли да рестартирате сега?
@@ -304,16 +289,8 @@ ExistingFileReadOnly2=Съществуващият файл не беше зам
ExistingFileReadOnlyRetry=&Премахни атрибута „само за четене“ и опитай отново
ExistingFileReadOnlyKeepExisting=&Запази съществуващия файл
ErrorReadingExistingDest=Грешка при опит за четене на съществуващ файл:
-FileExistsSelectAction=Изберете действие
-FileExists2=Файлът вече съществува.
-FileExistsOverwriteExisting=&Презапиши съществуващия файл
-FileExistsKeepExisting=&Запази съществуващия файл
-FileExistsOverwriteOrKeepAll=&Извършвай същото за останалите конфликти
-ExistingFileNewerSelectAction=Изберете действие
-ExistingFileNewer2=Съществуващият файл е по-нов от този, който инсталаторът се опитва да инсталира.
-ExistingFileNewerOverwriteExisting=&Презапиши съществуващия файл
-ExistingFileNewerKeepExisting=&Запази съществуващия файл (препоръчително)
-ExistingFileNewerOverwriteOrKeepAll=&Извършвай същото за останалите конфликти
+FileExists=Файлът вече съществува.%n%nЖелаете ли инсталаторът да го презапише?
+ExistingFileNewer=Съществуващият файл е по-нов от този, който инсталаторът се опитва да инсталира. Препоръчва се да го запазите.%n%nЖелаете ли да запазите съществуващия файл?
ErrorChangingAttr=Грешка при опит за смяна на атрибути на съществуващ файл:
ErrorCreatingTemp=Грешка при опит за създаване на файл в целевата директория:
ErrorReadingSource=Грешка при опит за четене на файл - източник:
@@ -345,10 +322,10 @@ UninstallUnknownEntry=Открит бе непознат запис (%1) в ре
ConfirmUninstall=Наистина ли желаете да премахнете напълно %1 и всички прилежащи компоненти?
UninstallOnlyOnWin64=Програмата може да бъде деинсталирана само под 64-битов Windows.
OnlyAdminCanUninstall=Програмата може да бъде премахната само от потребител с администраторски права.
-UninstallStatusLabel=Моля, изчакайте премахването на %1 от Вашия компютър да приключи.
-UninstalledAll=%1 беше премахната успешно от Вашия компютър.
+UninstallStatusLabel=Моля, изчакайте премахването на %1 от вашия компютър да приключи.
+UninstalledAll=%1 беше премахната успешно от вашия компютър.
UninstalledMost=Деинсталирането на %1 завърши.%n%nПремахването на някои елементи не бе възможно. Можете да ги отстраните ръчно.
-UninstalledAndNeedsRestart=За да приключи деинсталирането на %1, трябва да рестартирате Вашия компютър.%n%nЖелаете ли да рестартирате сега?
+UninstalledAndNeedsRestart=За да приключи деинсталирането на %1, трябва да рестартирате вашия компютър.%n%nЖелаете ли да рестартирате сега?
UninstallDataCorrupted=Файлът "%1" е повреден. Деинсталирането е невъзможно
; *** Съобщения от фаза "Деинсталиране"
diff --git a/installer/innosetup/Languages/ChineseSimplified.isl b/Greenshot/releases/innosetup/Languages/ChineseSimplified.isl
similarity index 60%
rename from installer/innosetup/Languages/ChineseSimplified.isl
rename to Greenshot/releases/innosetup/Languages/ChineseSimplified.isl
index df711d51d..1835c4f30 100644
--- a/installer/innosetup/Languages/ChineseSimplified.isl
+++ b/Greenshot/releases/innosetup/Languages/ChineseSimplified.isl
@@ -1,12 +1,4 @@
-; *** Inno Setup version 6.1.0+ Chinese Simplified messages ***
-;
-; To download user-contributed translations of this file, go to:
-; https://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).
+; *** Inno Setup version 6.0.3+ Chinese Simplified messages ***
;
; Maintained by Zhenghan Yang
; Email: 847320916@QQ.com
@@ -20,8 +12,6 @@
LanguageName=简体中文
; If Language Name display incorrect, uncomment next line
; LanguageName=<7B80><4F53><4E2D><6587>
-; About LanguageID, to reference link:
-; https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c
LanguageID=$0804
LanguageCodePage=936
; If the language you are translating to requires special font faces or
@@ -56,22 +46,22 @@ HelpTextNote=
; *** 启动错误消息
LastErrorMessage=%1.%n%n错误 %2: %3
-SetupFileMissing=安装目录中的文件 %1 丢失。请修正这个问题或者获取程序的新副本。
-SetupFileCorrupt=安装文件已损坏。请获取程序的新副本。
+SetupFileMissing=安装目录中的文件 %1 丢失。请修正这个问题或获取一个新的程序副本。
+SetupFileCorrupt=安装文件已损坏。请获取一个新的程序副本。
SetupFileCorruptOrWrongVer=安装文件已损坏,或是与这个安装程序的版本不兼容。请修正这个问题或获取新的程序副本。
-InvalidParameter=无效的命令行参数:%n%n%1
+InvalidParameter=无效的命令行参数: %n%n%1
SetupAlreadyRunning=安装程序正在运行。
-WindowsVersionNotSupported=这个程序不支持当前计算机运行的Windows版本。
-WindowsServicePackRequired=这个程序需要 %1 服务包 %2 或更高。
+WindowsVersionNotSupported=这个程序不支持该版本的计算机运行。
+WindowsServicePackRequired=这个程序要求%1服务包%1或更高。
NotOnThisPlatform=这个程序将不能运行于 %1。
OnlyOnThisPlatform=这个程序必须运行于 %1。
-OnlyOnTheseArchitectures=这个程序只能在为下列处理器结构设计的Windows版本中进行安装:%n%n%1
+OnlyOnTheseArchitectures=这个程序只能在为下列处理器结构设计的 Windows 版本中进行安装:%n%n%1
WinVersionTooLowError=这个程序需要 %1 版本 %2 或更高。
WinVersionTooHighError=这个程序不能安装于 %1 版本 %2 或更高。
AdminPrivilegesRequired=在安装这个程序时您必须以管理员身份登录。
PowerUserPrivilegesRequired=在安装这个程序时您必须以管理员身份或有权限的用户组身份登录。
-SetupAppRunningError=安装程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后点击“确定”继续,或按“取消”退出。
-UninstallAppRunningError=卸载程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后点击“确定”继续,或按“取消”退出。
+SetupAppRunningError=安装程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后单击“确定”继续,或按“取消”退出。
+UninstallAppRunningError=卸载程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后单击“确定”继续,或按“取消”退出。
; *** 启动问题
PrivilegesRequiredOverrideTitle=选择安装程序模式
@@ -79,9 +69,9 @@ PrivilegesRequiredOverrideInstruction=选择安装模式
PrivilegesRequiredOverrideText1=%1 可以为所有用户安装(需要管理员权限),或仅为您安装。
PrivilegesRequiredOverrideText2=%1 只能为您安装,或为所有用户安装(需要管理员权限)。
PrivilegesRequiredOverrideAllUsers=为所有用户安装(&A)
-PrivilegesRequiredOverrideAllUsersRecommended=为所有用户安装(&A) (建议选项)
+PrivilegesRequiredOverrideAllUsersRecommended=为所有用户安装(建议选项)(&A)
PrivilegesRequiredOverrideCurrentUser=只为我安装(&M)
-PrivilegesRequiredOverrideCurrentUserRecommended=只为我安装(&M) (建议选项)
+PrivilegesRequiredOverrideCurrentUserRecommended=只为我安装(建议选项)(&M)
; *** 其它错误
ErrorCreatingDir=安装程序不能创建目录“%1”。
@@ -89,10 +79,10 @@ ErrorTooManyFilesInDir=不能在目录“%1”中创建文件,因为里面的
; *** 安装程序公共消息
ExitSetupTitle=退出安装程序
-ExitSetupMessage=安装程序还未完成安装。如果您现在退出,程序将不能安装。%n%n您可以以后再运行安装程序完成安装。%n%n现在退出安装程序吗?
+ExitSetupMessage=安装程序未完成安装。如果您现在退出,您的程序将不能安装。%n%n您可以以后再运行安装程序完成安装。%n%n退出安装程序吗?
AboutSetupMenuItem=关于安装程序(&A)...
AboutSetupTitle=关于安装程序
-AboutSetupMessage=%1 版本 %2%n%3%n%n%1 主页:%n%4
+AboutSetupMessage=%1 版本 %2%n%3%n%n%1 主页:%n%4
AboutSetupNote=
TranslatorNote=
@@ -116,10 +106,10 @@ SelectLanguageTitle=选择安装语言
SelectLanguageLabel=选择安装时要使用的语言。
; *** 公共向导文字
-ClickNext=点击“下一步”继续,或点击“取消”退出安装程序。
+ClickNext=单击“下一步”继续,或单击“取消”退出安装程序。
BeveledLabel=
BrowseDialogTitle=浏览文件夹
-BrowseDialogLabel=在下列列表中选择一个文件夹,然后点击“确定”。
+BrowseDialogLabel=在下列列表中选择一个文件夹,然后单击“确定”。
NewFolderName=新建文件夹
; *** “欢迎”向导页
@@ -129,9 +119,9 @@ WelcomeLabel2=现在将安装 [name/ver] 到您的电脑中。%n%n推荐您在
; *** “密码”向导页
WizardPassword=密码
PasswordLabel1=这个安装程序有密码保护。
-PasswordLabel3=请输入密码,然后点击“下一步”继续。密码区分大小写。
-PasswordEditLabel=密码(&P):
-IncorrectPassword=您所输入的密码不正确,请重试。
+PasswordLabel3=请输入密码,然后单击“下一步”继续。密码区分大小写。
+PasswordEditLabel=密码(&P):
+IncorrectPassword=您输入的密码不正确,请重试。
; *** “许可协议”向导页
WizardLicense=许可协议
@@ -143,50 +133,50 @@ LicenseNotAccepted=我不同意此协议(&D)
; *** “信息”向导页
WizardInfoBefore=信息
InfoBeforeLabel=请在继续安装前阅读下列重要信息。
-InfoBeforeClickLabel=如果您想继续安装,点击“下一步”。
+InfoBeforeClickLabel=如果您想继续安装,单击“下一步”。
WizardInfoAfter=信息
InfoAfterLabel=请在继续安装前阅读下列重要信息。
-InfoAfterClickLabel=如果您想继续安装,点击“下一步”。
+InfoAfterClickLabel=如果您想继续安装,单击“下一步”。
; *** “用户信息”向导页
WizardUserInfo=用户信息
UserInfoDesc=请输入您的信息。
-UserInfoName=用户名(&U):
-UserInfoOrg=组织(&O):
-UserInfoSerial=序列号(&S):
-UserInfoNameRequired=您必须输入用户名。
+UserInfoName=用户名(&U):
+UserInfoOrg=组织(&O):
+UserInfoSerial=序列号(&S):
+UserInfoNameRequired=您必须输入名字。
-; *** “选择目标目录”向导页
+; *** “选择目标目录”向导面
WizardSelectDir=选择目标位置
-SelectDirDesc=您想将 [name] 安装在哪里?
+SelectDirDesc=您想将 [name] 安装在什么地方?
SelectDirLabel3=安装程序将安装 [name] 到下列文件夹中。
-SelectDirBrowseLabel=点击“下一步”继续。如果您想选择其它文件夹,点击“浏览”。
+SelectDirBrowseLabel=单击“下一步”继续。如果您想选择其它文件夹,单击“浏览”。
DiskSpaceGBLabel=至少需要有 [gb] GB 的可用磁盘空间。
DiskSpaceMBLabel=至少需要有 [mb] MB 的可用磁盘空间。
CannotInstallToNetworkDrive=安装程序无法安装到一个网络驱动器。
CannotInstallToUNCPath=安装程序无法安装到一个UNC路径。
-InvalidPath=您必须输入一个带驱动器卷标的完整路径,例如:%n%nC:\APP%n%n或下列形式的UNC路径:%n%n\\server\share
+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已经存在。您一定要安装到这个文件夹中吗?
+DirNameTooLong=文件夹名或路径太长。
+InvalidDirName=文件夹名是无效的。
+BadDirName32=文件夹名不能包含下列任何字符:%n%n%1
+DirExistsTitle=文件夹存在
+DirExists=文件夹:%n%n%1%n%n已经存在。您一定要安装到这个文件夹中吗?
DirDoesntExistTitle=文件夹不存在
-DirDoesntExist=文件夹:%n%n%1%n%n不存在。您想要创建此文件夹吗?
+DirDoesntExist=文件夹:%n%n%1%n%n不存在。您想要创建此目录吗?
; *** “选择组件”向导页
WizardSelectComponents=选择组件
SelectComponentsDesc=您想安装哪些程序的组件?
-SelectComponentsLabel2=选择您想要安装的组件;清除您不想安装的组件。然后点击“下一步”继续。
+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您一定要继续吗?
+NoUninstallWarningTitle=组件存在
+NoUninstallWarning=安装程序侦测到下列组件已在您的电脑中安装。:%n%n%1%n%n取消选定这些组件将不能卸载它们。%n%n您一定要继续吗?
ComponentSize1=%1 KB
ComponentSize2=%1 MB
ComponentsDiskSpaceGBLabel=当前选择的组件至少需要 [gb] GB 的磁盘空间。
@@ -195,52 +185,40 @@ ComponentsDiskSpaceMBLabel=当前选择的组件至少需要 [mb] MB 的磁盘
; *** “选择附加任务”向导页
WizardSelectTasks=选择附加任务
SelectTasksDesc=您想要安装程序执行哪些附加任务?
-SelectTasksLabel2=选择您想要安装程序在安装 [name] 时执行的附加任务,然后点击“下一步”。
+SelectTasksLabel2=选择您想要安装程序在安装 [name] 时执行的附加任务,然后单击“下一步”。
; *** “选择开始菜单文件夹”向导页
WizardSelectProgramGroup=选择开始菜单文件夹
-SelectStartMenuFolderDesc=安装程序应该在哪里放置程序的快捷方式?
+SelectStartMenuFolderDesc=您想在哪里放置程序的快捷方式?
SelectStartMenuFolderLabel3=安装程序现在将在下列开始菜单文件夹中创建程序的快捷方式。
-SelectStartMenuFolderBrowseLabel=点击“下一步”继续。如果您想选择其它文件夹,点击“浏览”。
+SelectStartMenuFolderBrowseLabel=单击“下一步”继续。如果您想选择其它文件夹,单击“浏览”。
MustEnterGroupName=您必须输入一个文件夹名。
GroupNameTooLong=文件夹名或路径太长。
InvalidGroupName=文件夹名是无效的。
-BadGroupName=文件夹名不能包含下列任何字符:%n%n%1
+BadGroupName=文件夹名不能包含下列任何字符:%n%n%1
NoProgramGroupCheck2=不创建开始菜单文件夹(&D)
; *** “准备安装”向导页
WizardReady=准备安装
ReadyLabel1=安装程序现在准备开始安装 [name] 到您的电脑中。
-ReadyLabel2a=点击“安装”继续此安装程序。如果您想要回顾或修改设置,请点击“上一步”。
-ReadyLabel2b=点击“安装”继续此安装程序?
-ReadyMemoUserInfo=用户信息:
-ReadyMemoDir=目标位置:
-ReadyMemoType=安装类型:
-ReadyMemoComponents=选定组件:
-ReadyMemoGroup=开始菜单文件夹:
-ReadyMemoTasks=附加任务:
-
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=正在下载附加文件...
-ButtonStopDownload=停止下载(&S)
-StopDownload=您确定要停止下载吗?
-ErrorDownloadAborted=下载已中止
-ErrorDownloadFailed=下载失败:%1 %2
-ErrorDownloadSizeFailed=获取下载大小失败:%1 %2
-ErrorFileHash1=校验文件哈希失败:%1
-ErrorFileHash2=无效的文件哈希:预期 %1,实际 %2
-ErrorProgress=无效的进度:%1,总共%2
-ErrorFileSize=文件大小错误:预期 %1,实际 %2
+ReadyLabel2a=单击“安装”继续此安装程序。如果您想要回顾或改变设置,请单击“上一步”。
+ReadyLabel2b=单击“安装”继续此安装程序?
+ReadyMemoUserInfo=用户信息:
+ReadyMemoDir=目标位置:
+ReadyMemoType=安装类型:
+ReadyMemoComponents=选定组件:
+ReadyMemoGroup=开始菜单文件夹:
+ReadyMemoTasks=附加任务:
; *** “正在准备安装”向导页
WizardPreparing=正在准备安装
PreparingDesc=安装程序正在准备安装 [name] 到您的电脑中。
PreviousInstallNotCompleted=先前程序的安装/卸载未完成。您需要重新启动您的电脑才能完成安装。%n%n在重新启动电脑后,再运行安装完成 [name] 的安装。
-CannotContinue=安装程序不能继续。请点击“取消”退出。
+CannotContinue=安装程序不能继续。请单击“取消”退出。
ApplicationsFound=下列应用程序正在使用的文件需要更新设置。它是建议您允许安装程序自动关闭这些应用程序。
ApplicationsFound2=下列应用程序正在使用的文件需要更新设置。它是建议您允许安装程序自动关闭这些应用程序。安装完成后,安装程序将尝试重新启动应用程序。
CloseApplications=自动关闭该应用程序(&A)
-DontCloseApplications=不要关闭该应用程序(&D)
+DontCloseApplications=不要关闭该应用程序(D)
ErrorCloseApplications=安装程序无法自动关闭所有应用程序。在继续之前,我们建议您关闭所有使用需要更新的安装程序文件。
PrepareToInstallNeedsRestart=安装程序必须重新启动计算机。重新启动计算机后,请再次运行安装程序以完成 [name] 的安装。%n%n是否立即重新启动?
@@ -252,27 +230,27 @@ InstallingLabel=安装程序正在安装 [name] 到您的电脑中,请稍等
FinishedHeadingLabel=[name] 安装完成
FinishedLabelNoIcons=安装程序已在您的电脑中安装了 [name]。
FinishedLabel=安装程序已在您的电脑中安装了 [name]。此应用程序可以通过选择安装的快捷方式运行。
-ClickFinish=点击“完成”退出安装程序。
-FinishedRestartLabel=要完成 [name] 的安装,安装程序必须重新启动您的电脑。您想要立即重新启动吗?
-FinishedRestartMessage=要完成 [name] 的安装,安装程序必须重新启动您的电脑。%n%n您想要立即重新启动吗?
-ShowReadmeCheck=是,我想查阅自述文件
+ClickFinish=单击“完成”退出安装程序。
+FinishedRestartLabel=要完成 [name] 的安装,安装程序必须重新启动您的电脑。您想现在重新启动吗?
+FinishedRestartMessage=要完成 [name] 的安装,安装程序必须重新启动您的电脑。%n%n您想现在重新启动吗?
+ShowReadmeCheck=是,您想查阅自述文件
YesRadio=是,立即重新启动电脑(&Y)
NoRadio=否,稍后重新启动电脑(&N)
-; used for example as 'Run MyProg.exe'
+; 用于象“运行 MyProg.exe”
RunEntryExec=运行 %1
-; used for example as 'View Readme.txt'
+; 用于象“查阅 Readme.txt”
RunEntryShellExec=查阅 %1
; *** “安装程序需要下一张磁盘”提示
ChangeDiskTitle=安装程序需要下一张磁盘
-SelectDiskLabel2=请插入磁盘 %1 并点击“确定”。%n%n如果这个磁盘中的文件可以在下列文件夹之外的文件夹中找到,请输入正确的路径或点击“浏览”。
-PathLabel=路径(&P):
+SelectDiskLabel2=请插入磁盘 %1 并单击“确定”。%n%n如果这个磁盘中的文件不能在不同于下列显示的文件夹中找到,输入正确的路径或单击“浏览”。
+PathLabel=路径(&P):
FileNotInDir2=文件“%1”不能在“%2”定位。请插入正确的磁盘或选择其它文件夹。
SelectDirectoryLabel=请指定下一张磁盘的位置。
; *** 安装状态消息
SetupAborted=安装程序未完成安装。%n%n请修正这个问题并重新运行安装程序。
-AbortRetryIgnoreSelectAction=选择操作
+AbortRetryIgnoreSelectAction=选项
AbortRetryIgnoreRetry=重试(&T)
AbortRetryIgnoreIgnore=忽略错误并继续(&I)
AbortRetryIgnoreCancel=关闭安装程序
@@ -291,49 +269,41 @@ StatusRestartingApplications=正在重启应用程序...
StatusRollback=正在撤销更改...
; *** 其它错误
-ErrorInternal2=内部错误:%1
+ErrorInternal2=内部错误: %1
ErrorFunctionFailedNoCode=%1 失败
ErrorFunctionFailed=%1 失败;错误代码 %2
ErrorFunctionFailedWithMessage=%1 失败;错误代码 %2.%n%3
-ErrorExecutingProgram=不能执行文件:%n%1
+ErrorExecutingProgram=不能执行文件:%n%1
; *** 注册表错误
-ErrorRegOpenKey=打开注册表项时出错:%n%1\%2
-ErrorRegCreateKey=创建注册表项时出错:%n%1\%2
-ErrorRegWriteKey=写入注册表项时出错:%n%1\%2
+ErrorRegOpenKey=打开注册表项时出错:%n%1\%2
+ErrorRegCreateKey=创建注册表项时出错:%n%1\%2
+ErrorRegWriteKey=写入注册表项时出错:%n%1\%2
; *** INI 错误
-ErrorIniEntry=在文件“%1”中创建INI条目时出错。
+ErrorIniEntry=在文件“%1”创建 INI 项目错误。
; *** 文件复制错误
-FileAbortRetryIgnoreSkipNotRecommended=跳过这个文件(&S) (不推荐)
-FileAbortRetryIgnoreIgnoreNotRecommended=忽略错误并继续(&I) (不推荐)
+FileAbortRetryIgnoreSkipNotRecommended=跳过这个文件 (不推荐)(&S)
+FileAbortRetryIgnoreIgnoreNotRecommended=忽略错误并继续 (不推荐)(&I)
SourceIsCorrupted=源文件已损坏
SourceDoesntExist=源文件“%1”不存在
ExistingFileReadOnly2=无法替换现有文件,因为它是只读的。
ExistingFileReadOnlyRetry=移除只读属性并重试(&R)
ExistingFileReadOnlyKeepExisting=保留现有文件(&K)
-ErrorReadingExistingDest=尝试读取现有文件时出错:
-FileExistsSelectAction=选择操作
-FileExists2=文件已经存在。
-FileExistsOverwriteExisting=覆盖已经存在的文件(&O)
-FileExistsKeepExisting=保留现有的文件(&K)
-FileExistsOverwriteOrKeepAll=为所有的冲突文件执行此操作(&D)
-ExistingFileNewerSelectAction=选择操作
-ExistingFileNewer2=现有的文件比安装程序将要安装的文件更新。
-ExistingFileNewerOverwriteExisting=覆盖已经存在的文件(&O)
-ExistingFileNewerKeepExisting=保留现有的文件(&K) (推荐)
-ExistingFileNewerOverwriteOrKeepAll=为所有的冲突文件执行此操作(&D)
-ErrorChangingAttr=尝试改变下列现有的文件的属性时出错:
-ErrorCreatingTemp=尝试在目标目录创建文件时出错:
-ErrorReadingSource=尝试读取下列源文件时出错:
-ErrorCopying=尝试复制下列文件时出错:
-ErrorReplacingExistingFile=尝试替换现有的文件时出错:
-ErrorRestartReplace=重新启动替换失败:
-ErrorRenamingTemp=尝试重新命名以下目标目录中的一个文件时出错:
-ErrorRegisterServer=无法注册 DLL/OCX:%1
+ErrorReadingExistingDest=尝试读取现有文件时发生一个错误:
+FileExists=文件已经存在。%n%n您想要安装程序覆盖它吗?
+ExistingFileNewer=现有的文件新与安装程序要安装的文件。推荐您保留现有文件。%n%n您想要保留现有的文件吗?
+ErrorChangingAttr=尝试改变下列现有的文件的属性时发生一个错误:
+ErrorCreatingTemp=尝试在目标目录创建文件时发生一个错误:
+ErrorReadingSource=尝试读取下列源文件时发生一个错误:
+ErrorCopying=尝试复制下列文件时发生一个错误:
+ErrorReplacingExistingFile=尝试替换现有的文件时发生错误:
+ErrorRestartReplace=重启电脑后替换文件失败:
+ErrorRenamingTemp=尝试重新命名以下目标目录中的一个文件时发生错误:
+ErrorRegisterServer=不能注册 DLL/OCX: %1
ErrorRegSvr32Failed=RegSvr32 失败;退出代码 %1
-ErrorRegisterTypeLib=无法注册类型库:%1
+ErrorRegisterTypeLib=不能注册类型库: %1
; *** 卸载显示名字标记
; used for example as 'My Program (32-bit)'
@@ -346,34 +316,34 @@ UninstallDisplayNameMarkAllUsers=所有用户
UninstallDisplayNameMarkCurrentUser=当前用户
; *** 安装后错误
-ErrorOpeningReadme=尝试打开自述文件时出错。
+ErrorOpeningReadme=当尝试打开自述文件时发生一个错误。
ErrorRestartingComputer=安装程序不能重新启动电脑,请手动重启。
; *** 卸载消息
-UninstallNotFound=文件“%1”不存在。无法卸载。
-UninstallOpenError=文件“%1”不能打开。无法卸载。
-UninstallUnsupportedVer=此版本的卸载程序无法识别卸载日志文件“%1”的格式。无法卸载
+UninstallNotFound=文件“%1”不存在。不能卸载。
+UninstallOpenError=文件“%1”不能打开。不能卸载。
+UninstallUnsupportedVer=卸载日志文件“%1”有未被这个版本的卸载器承认的格式。不能卸载
UninstallUnknownEntry=在卸载日志中遇到一个未知的条目 (%1)
ConfirmUninstall=您确认想要完全删除 %1 及它的所有组件吗?
-UninstallOnlyOnWin64=这个安装程序只能在64位Windows中进行卸载。
-OnlyAdminCanUninstall=这个安装的程序需要有管理员权限的用户才能卸载。
-UninstallStatusLabel=正在从您的电脑中删除 %1,请稍等。
+UninstallOnlyOnWin64=这个安装程序只能在 64 位 Windows 中进行卸载。
+OnlyAdminCanUninstall=这个安装的程序只能是有管理员权限的用户才能卸载。
+UninstallStatusLabel=正在从您的电脑中删除 %1,请等待。
UninstalledAll=%1 已顺利地从您的电脑中删除。
-UninstalledMost=%1 卸载完成。%n%n有一些内容无法被删除。您可以手动删除它们。
-UninstalledAndNeedsRestart=要完成 %1 的卸载,您的电脑必须重新启动。%n%n您想立即重新启动电脑吗?
-UninstallDataCorrupted=文件“%1”已损坏,无法卸载
+UninstalledMost=%1 卸载完成。%n%n有一些内容不能被删除。您可以手工删除它们。
+UninstalledAndNeedsRestart=要完成 %1 的卸载,您的电脑必须重新启动。%n%n您现在想重新启动电脑吗?
+UninstallDataCorrupted=“%1”文件被破坏,不能卸载
; *** 卸载状态消息
ConfirmDeleteSharedFileTitle=删除共享文件吗?
-ConfirmDeleteSharedFile2=系统中包含的下列共享文件已经不再被其它程序使用。您想要卸载程序删除这些共享文件吗?%n%n如果这些文件被删除,但还有程序正在使用这些文件,这些程序可能不能正确执行。如果您不能确定,选择“否”。把这些文件保留在系统中以免引起问题。
-SharedFileNameLabel=文件名:
-SharedFileLocationLabel=位置:
+ConfirmDeleteSharedFile2=系统中包含的下列共享文件已经不被其它程序使用。您想要卸载程序删除这些共享文件吗?%n%n如果这些文件被删除,但还有程序正在使用这些文件,这些程序可能不能正确执行。如果您不能确定,选择“否”。把这些文件保留在系统中以免引起问题。
+SharedFileNameLabel=文件名:
+SharedFileLocationLabel=位置:
WizardUninstalling=卸载状态
StatusUninstalling=正在卸载 %1...
; *** Shutdown block reasons
-ShutdownBlockReasonInstallingApp=正在安装 %1。
-ShutdownBlockReasonUninstallingApp=正在卸载 %1。
+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.
@@ -381,7 +351,7 @@ ShutdownBlockReasonUninstallingApp=正在卸载 %1。
[CustomMessages]
NameAndVersion=%1 版本 %2
-AdditionalIcons=附加快捷方式:
+AdditionalIcons=附加快捷方式:
CreateDesktopIcon=创建桌面快捷方式(&D)
CreateQuickLaunchIcon=创建快速运行栏快捷方式(&Q)
ProgramOnTheWeb=%1 网站
@@ -389,6 +359,7 @@ UninstallProgram=卸载 %1
LaunchProgram=运行 %1
AssocFileExtension=将 %2 文件扩展名与 %1 建立关联(&A)
AssocingFileExtension=正在将 %2 文件扩展名与 %1 建立关联...
-AutoStartProgramGroupDescription=启动组:
+AutoStartProgramGroupDescription=启动组:
AutoStartProgram=自动启动 %1
AddonHostProgramNotFound=%1无法找到您所选择的文件夹。%n%n您想要继续吗?
+
diff --git a/installer/innosetup/Languages/ChineseTraditional.isl b/Greenshot/releases/innosetup/Languages/ChineseTraditional.isl
similarity index 75%
rename from installer/innosetup/Languages/ChineseTraditional.isl
rename to Greenshot/releases/innosetup/Languages/ChineseTraditional.isl
index 1663b45c8..9c692956e 100644
--- a/installer/innosetup/Languages/ChineseTraditional.isl
+++ b/Greenshot/releases/innosetup/Languages/ChineseTraditional.isl
@@ -1,29 +1,27 @@
-; *** Inno Setup version 6.1.0+ Chinese Traditional messages ***
-; Name: Enfong Tsao, nelson22768384@gmail.com
-; Based on 5.5.3+ translations by Samuel Lee, Email: 751555749@qq.com
+; *** Inno Setup version 6.0.0+ Chinese Traditional messages ***
+;
+; Name: John Wu, mr.johnwu@gmail.com
+; Base on 5.5.3+ translations by Samuel Lee, Email: 751555749@qq.com
; Translation based on network resource
;
-; 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.
+; If Language Name display incorrect, uncomment next line
LanguageName=<7e41><9ad4><4e2d><6587>
LanguageID=$0404
LanguageCodepage=950
; 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
-;TitleFontName=Arial
-;TitleFontSize=29
-;WelcomeFontName=Verdana
-;WelcomeFontSize=12
-;CopyrightFontName=Arial
-;CopyrightFontSize=8
+DialogFontName=新細明體
+DialogFontSize=9
+TitleFontName=Arial
+TitleFontSize=28
+WelcomeFontName=新細明體
+WelcomeFontSize=12
+CopyrightFontName=新細明體
+CopyrightFontSize=9
[Messages]
@@ -39,7 +37,7 @@ ConfirmTitle=確認
ErrorTitle=錯誤
; *** SetupLdr messages
-SetupLdrStartupMessage=這將會安裝 %1。您想要繼續嗎?
+SetupLdrStartupMessage=這將會安裝 %1。您想要繼續嗎?
LdrCannotCreateTemp=無法建立暫存檔案。安裝程式將會結束。
LdrCannotExecTemp=無法執行暫存檔案。安裝程式將會結束。
HelpTextNote=
@@ -60,8 +58,8 @@ WinVersionTooLowError=這個程式必須在 %1 版本 %2 或以上的系統執
WinVersionTooHighError=這個程式無法安裝在 %1 版本 %2 或以上的系統。
AdminPrivilegesRequired=您必須登入成系統管理員以安裝這個程式。
PowerUserPrivilegesRequired=您必須登入成具有系統管理員或 Power User 權限的使用者以安裝這個程式。
-SetupAppRunningError=安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 「確定」 繼續,或按 「取消」 離開。
-UninstallAppRunningError=解除安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 「確定」 繼續,或按 「取消」 離開。
+SetupAppRunningError=安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 [確定] 繼續,或按 [取消] 離開。
+UninstallAppRunningError=解除安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 [確定] 繼續,或按 [取消] 離開。
; *** Startup questions
PrivilegesRequiredOverrideTitle=選擇安裝程式安裝模式
@@ -80,7 +78,7 @@ ErrorTooManyFilesInDir=無法在資料夾“%1”內建立檔案,因為資料
; *** Setup common messages
ExitSetupTitle=結束安裝程式
ExitSetupMessage=安裝尚未完成。如果您現在結束安裝程式,這個程式將不會被安裝。%n%n您可以稍後再執行安裝程式以完成安裝程序。您現在要結束安裝程式嗎?
-AboutSetupMenuItem=關於安裝程式 (&A)...
+AboutSetupMenuItem=關於安裝程式(&A)...
AboutSetupTitle=關於安裝程式
AboutSetupMessage=%1 版本 %2%n%3%n%n%1 網址:%n%4
AboutSetupNote=
@@ -93,23 +91,23 @@ ButtonNext=下一步(&N) >
ButtonOK=確定
ButtonCancel=取消
ButtonYes=是(&Y)
-ButtonYesToAll=全部皆是 (&A)
+ButtonYesToAll=全部皆是(&A)
ButtonNo=否(&N)
-ButtonNoToAll=全部皆否 (&O)
-ButtonFinish=完成 (&F)
-ButtonBrowse=瀏覽 (&B)...
-ButtonWizardBrowse=瀏覽 (&R)...
-ButtonNewFolder=建立新資料夾 (&M)
+ButtonNoToAll=全部皆否(&O)
+ButtonFinish=完成(&F)
+ButtonBrowse=瀏覽(&B)...
+ButtonWizardBrowse=瀏覽(&R)...
+ButtonNewFolder=建立新資料夾(&M)
; *** "Select Language" dialog messages
SelectLanguageTitle=選擇安裝語言
SelectLanguageLabel=選擇在安裝過程中使用的語言:
; *** Common wizard text
-ClickNext=按 「下一步」 繼續安裝,或按 「取消」 結束安裝程式。
+ClickNext=按 [下一步] 繼續安裝,或按 [取消] 結束安裝程式。
BeveledLabel=
BrowseDialogTitle=瀏覽資料夾
-BrowseDialogLabel=在下面的資料夾列表中選擇一個資料夾,然後按 「確定」。
+BrowseDialogLabel=在下面的資料夾列表中選擇一個資料夾,然後按 [確定]。
NewFolderName=新資料夾
; *** "Welcome" wizard page
@@ -119,24 +117,24 @@ WelcomeLabel2=這個安裝程式將會安裝 [name/ver] 到您的電腦。%n%n
; *** "Password" wizard page
WizardPassword=密碼
PasswordLabel1=這個安裝程式具有密碼保護。
-PasswordLabel3=請輸入密碼,然後按 「下一步」 繼續。密碼是區分大小寫的。
-PasswordEditLabel=密碼 (&P):
+PasswordLabel3=請輸入密碼,然後按 [下一步] 繼續。密碼是區分大小寫的。
+PasswordEditLabel=密碼(&P):
IncorrectPassword=您輸入的密碼不正確,請重新輸入。
; *** "License Agreement" wizard page
WizardLicense=授權合約
LicenseLabel=請閱讀以下授權合約。
LicenseLabel3=請閱讀以下授權合約,您必須接受合約的各項條款才能繼續安裝。
-LicenseAccepted=我同意 (&A)
-LicenseNotAccepted=我不同意 (&D)
+LicenseAccepted=我同意(&A)
+LicenseNotAccepted=我不同意(&D)
; *** "Information" wizard pages
WizardInfoBefore=訊息
InfoBeforeLabel=在繼續安裝之前請閱讀以下重要資訊。
-InfoBeforeClickLabel=當您準備好繼續安裝,請按 「下一步」。
+InfoBeforeClickLabel=當您準備好繼續安裝,請按 [下一步]。
WizardInfoAfter=訊息
InfoAfterLabel=在繼續安裝之前請閱讀以下重要資訊。
-InfoAfterClickLabel=當您準備好繼續安裝,請按 「下一步」。
+InfoAfterClickLabel=當您準備好繼續安裝,請按 [下一步]。
; *** "User Information" wizard page
WizardUserInfo=使用者資訊
@@ -150,15 +148,14 @@ UserInfoNameRequired=您必須輸入您的名稱。
WizardSelectDir=選擇目的資料夾
SelectDirDesc=選擇安裝程式安裝 [name] 的位置。
SelectDirLabel3=安裝程式將會把 [name] 安裝到下面的資料夾。
-SelectDirBrowseLabel=按 「下一步」 繼續,如果您想選擇另一個資料夾,請按 「瀏覽」。
-DiskSpaceGBLabel=最少需要 [gb] GB 磁碟空間。
+SelectDirBrowseLabel=按 [下一步] 繼續,如果您想選擇另一個資料夾,請按 [瀏覽]。
DiskSpaceMBLabel=最少需要 [mb] MB 磁碟空間。
CannotInstallToNetworkDrive=安裝程式無法安裝於網絡磁碟機。
CannotInstallToUNCPath=安裝程式無法安裝於 UNC 路徑。
InvalidPath=您必須輸入完整的路徑名稱及磁碟機代碼。%n%n例如 C:\App 或 UNC 路徑格式 \\伺服器\共用資料夾。
InvalidDrive=您選取的磁碟機或 UNC 名稱不存在或無法存取,請選擇其他的目的地。
DiskSpaceWarningTitle=磁碟空間不足
-DiskSpaceWarning=安裝程式需要至少 %1 KB 的磁碟空間,您所選取的磁碟只有 %2 KB 可用空間。%n%n您要繼續安裝嗎?
+DiskSpaceWarning=安裝程式需要至少 %1 KB 的磁碟空間,您所選取的磁碟只有 %2 KB 可用空間。%n%n您要繼續安裝嗎?
DirNameTooLong=資料夾名稱或路徑太長。
InvalidDirName=資料夾名稱不正確。
BadDirName32=資料夾名稱不得包含以下特殊字元:%n%n%1
@@ -170,39 +167,38 @@ DirDoesntExist=資料夾:%n%n%1%n%n 不存在。要建立該資料夾嗎?
; *** "Select Components" wizard page
WizardSelectComponents=選擇元件
SelectComponentsDesc=選擇將會被安裝的元件。
-SelectComponentsLabel2=選擇您想要安裝的元件;清除您不想安裝的元件。然後按 「下一步」 繼續安裝。
+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您仍然要繼續嗎?
+NoUninstallWarning=安裝程式偵測到以下元件已經安裝在您的電腦上:%n%n%1%n%n取消選擇這些元件將不會移除它們。%n%n您仍然要繼續嗎?
ComponentSize1=%1 KB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=目前的選擇需要至少 [gb] GB 磁碟空間。
ComponentsDiskSpaceMBLabel=目前的選擇需要至少 [mb] MB 磁碟空間。
; *** "Select Additional Tasks" wizard page
WizardSelectTasks=選擇附加的工作
SelectTasksDesc=選擇要執行的附加工作。
-SelectTasksLabel2=選擇安裝程式在安裝 [name] 時要執行的附加工作,然後按 「下一步」。
+SelectTasksLabel2=選擇安裝程式在安裝 [name] 時要執行的附加工作,然後按 [下一步]。
; *** "Select Start Menu Folder" wizard page
WizardSelectProgramGroup=選擇「開始」功能表的資料夾
SelectStartMenuFolderDesc=選擇安裝程式建立程式的捷徑的位置。
SelectStartMenuFolderLabel3=安裝程式將會把程式的捷徑建立在下面的「開始」功能表資料夾。
-SelectStartMenuFolderBrowseLabel=按 「下一步」 繼續,如果您想選擇另一個資料夾,請按 「瀏覽」。
+SelectStartMenuFolderBrowseLabel=按 [下一步] 繼續,如果您想選擇另一個資料夾,請按 [瀏覽]。
MustEnterGroupName=您必須輸入一個資料夾的名稱。
GroupNameTooLong=資料夾名稱或路徑太長。
InvalidGroupName=資料夾名稱不正確。
BadGroupName=資料夾名稱不得包含下列字元:%n%n%1
-NoProgramGroupCheck2=不要在「開始」功能表中建立資料夾 (&D)
+NoProgramGroupCheck2=不要在「開始」功能表中建立資料夾(&D)
; *** "Ready to Install" wizard page
WizardReady=準備安裝
ReadyLabel1=安裝程式將開始安裝 [name] 到您的電腦中。
-ReadyLabel2a=按下 「安裝」 繼續安裝,或按 「上一步」 重新檢視或設定各選項的內容。
-ReadyLabel2b=按下 「安裝」 繼續安裝。
+ReadyLabel2a=按下 [安裝] 繼續安裝,或按 [上一步] 重新檢視或設定各選項的內容。
+ReadyLabel2b=按下 [安裝] 繼續安裝。
ReadyMemoUserInfo=使用者資訊
ReadyMemoDir=目的資料夾:
ReadyMemoType=安裝型態:
@@ -210,29 +206,16 @@ ReadyMemoComponents=選擇的元件:
ReadyMemoGroup=「開始」功能表資料夾:
ReadyMemoTasks=附加工作:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=正在下載額外檔案...
-ButtonStopDownload=停止下載 (&S)
-StopDownload=您確定要停止下載嗎?
-ErrorDownloadAborted=已停止下載
-ErrorDownloadFailed=下載失敗: %1 %2
-ErrorDownloadSizeFailed=取得檔案大小失敗: %1 %2
-ErrorFileHash1=檔案雜湊失敗: %1
-ErrorFileHash2=檔案雜湊無效: 必須為 %1,收到 %2
-ErrorProgress=進度無效: %1 之 %2
-ErrorFileSize=檔案大小無效: 必須為 %1,收到 %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=準備安裝程式
PreparingDesc=安裝程式準備將 [name] 安裝到您的電腦上。
PreviousInstallNotCompleted=先前的安裝/ 解除安裝尚未完成,您必須重新啟動電腦以完成該安裝。%n%n在重新啟動電腦之後,請再執行這個程式來安裝 [name]。
-CannotContinue=安裝程式無法繼續。請按 「取消」 離開。
-ApplicationsFound=下面的應用程式正在使用安裝程式所需要更新的檔案。建議您允許安裝程式自動關閉這些應用程式。
-ApplicationsFound2=下面的應用程式正在使用安裝程式所需要更新的檔案。建議您允許安裝程式自動關閉這些應用程式。當安裝過程結束後,本安裝程式將會嘗試重新開啟該應用程式。
-CloseApplications=關閉應用程式 (&A)
+CannotContinue=安裝程式無法繼續。請按 [取消] 離開。
+ApplicationsFound=下面的應用程式正在使用安裝程式所需要更新的文檔。建議您允許安裝程式自動關閉這些應用程式。
+ApplicationsFound2=下面的應用程式正在使用安裝程式所需要更新的文檔。建議您允許安裝程式自動關閉這些應用程式。當安裝過程結束後,本安裝程式將會嘗試重新開啟該應用程式。
+CloseApplications=關閉應用程式(&A)
DontCloseApplications=不要關閉應用程式 (&D)
ErrorCloseApplications=安裝程式無法自動關閉所有應用程式。建議您在繼續前先關閉所有應用程式使用的檔案。
-PrepareToInstallNeedsRestart=安裝程式必須重新啟動您的電腦。重新啟動後,請再次執行安裝程式以完成 [name] 的安裝。%n%n您想要現在重新啟動電腦嗎?
; *** "Installing" wizard page
WizardInstalling=正在安裝
@@ -242,9 +225,9 @@ InstallingLabel=請稍候,安裝程式正在將 [name] 安裝到您的電腦
FinishedHeadingLabel=安裝完成
FinishedLabelNoIcons=安裝程式已經將 [name] 安裝在您的電腦上。
FinishedLabel=安裝程式已經將 [name] 安裝在您的電腦中,您可以選擇程式的圖示來執行該應用程式。
-ClickFinish=按 「完成」 以結束安裝程式。
-FinishedRestartLabel=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。您想要現在重新啟動電腦嗎?
-FinishedRestartMessage=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。%n%n您想要現在重新啟動電腦嗎?
+ClickFinish=按 [完成] 以結束安裝程式。
+FinishedRestartLabel=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。您想要現在重新啟動電腦嗎?
+FinishedRestartMessage=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。%n%n您想要現在重新啟動電腦嗎?
ShowReadmeCheck=是,我要閱讀讀我檔案。
YesRadio=是,立即重新啟動電腦(&Y)
NoRadio=否,我稍後重新啟動電腦(&N)
@@ -255,7 +238,7 @@ RunEntryShellExec=檢視 %1
; *** "Setup Needs the Next Disk"
ChangeDiskTitle=安裝程式需要下一張磁片
-SelectDiskLabel2=請插入磁片 %1,然後按 「確定」。%n%n如果檔案不在以下所顯示的資料夾之中,請輸入正確的資料夾名稱或按 [瀏覽] 選取。
+SelectDiskLabel2=請插入磁片 %1,然後按 [確定]。%n%n如果檔案不在以下所顯示的資料夾之中,請輸入正確的資料夾名稱或按 [瀏覽] 選取。
PathLabel=路徑(&P):
FileNotInDir2=檔案“%1”無法在“%2”找到。請插入正確的磁片或選擇其它的資料夾。
SelectDirectoryLabel=請指定下一張磁片的位置。
@@ -304,20 +287,12 @@ ExistingFileReadOnly2=無法取代現有檔案,因為檔案已標示為唯讀
ExistingFileReadOnlyRetry=移除唯讀屬性並重試 (&R)
ExistingFileReadOnlyKeepExisting=保留現有檔案 (&K)
ErrorReadingExistingDest=讀取一個已存在的檔案時發生錯誤:
-FileExistsSelectAction=選擇操作
-FileExists2=檔案已存在。
-FileExistsOverwriteExisting=覆寫現有檔案
-FileExistsKeepExisting=保留現有檔案 (&O)
-FileExistsOverwriteOrKeepAll=對下次衝突執行相同操作 (&D)
-ExistingFileNewerSelectAction=選擇操作
-ExistingFileNewer2=現有檔案比安裝程式嘗試安裝的檔案還新。
-ExistingFileNewerOverwriteExisting=覆寫現有檔案 (&O)
-ExistingFileNewerKeepExisting=保留現有檔案 (&K) (建議選項)
-ExistingFileNewerOverwriteOrKeepAll=對下次衝突執行相同操作 (&D)
+FileExists=檔案已經存在。%n%n 要讓安裝程式加以覆寫嗎?
+ExistingFileNewer=存在的檔案版本比較新,建議您保留目前已存在的檔案。%n%n您要保留目前已存在的檔案嗎?
ErrorChangingAttr=在變更檔案屬性時發生錯誤:
ErrorCreatingTemp=在目的資料夾中建立檔案時發生錯誤:
ErrorReadingSource=讀取原始檔案時發生錯誤:
-ErrorCopying=複製檔案時發生錯誤:
+ErrorCopying=復制檔案時發生錯誤:
ErrorReplacingExistingFile=取代檔案時發生錯誤:
ErrorRestartReplace=重新啟動電腦後取代檔案失敗:
ErrorRenamingTemp=在目的資料夾變更檔案名稱時發生錯誤:
@@ -330,28 +305,28 @@ ErrorRegisterTypeLib=無法注冊類型庫: %1。
UninstallDisplayNameMark=%1 (%2)
; used for example as 'My Program (32-bit, All users)'
UninstallDisplayNameMarks=%1 (%2, %3)
-UninstallDisplayNameMark32Bit=32 位元
-UninstallDisplayNameMark64Bit=64 位元
+UninstallDisplayNameMark32Bit=32-bit
+UninstallDisplayNameMark64Bit=64-bit
UninstallDisplayNameMarkAllUsers=所有使用者
UninstallDisplayNameMarkCurrentUser=目前使用者
; *** Post-installation errors
ErrorOpeningReadme=開啟讀我檔案時發生錯誤。
-ErrorRestartingComputer=安裝程式無法重新啟動電腦,請自行重新啟動。
+ErrorRestartingComputer=安裝程式無法重新啟動電腦,請以手動方式自行重新啟動電腦。
; *** Uninstaller messages
-UninstallNotFound=檔案“%1”不存在,無法解除安裝。
-UninstallOpenError=無法開啟檔案“%1”,無法解除安裝
+UninstallNotFound=檔案“%1”不存在,無法移除程式。
+UninstallOpenError=無法開啟檔案“%1”,無法移除程式。
UninstallUnsupportedVer=這個版本的解除安裝程式無法辨識記錄檔 “%1” 之格式,無法解除安裝。
UninstallUnknownEntry=解除安裝記錄檔中發現未知的記錄 (%1)。
-ConfirmUninstall=您確定要完全移除 %1 及其相關的檔案嗎?
+ConfirmUninstall=您確定要完全移除 %1 及其相關的檔案嗎?
UninstallOnlyOnWin64=這個程式只能在 64 位元的 Windows 上解除安裝。
OnlyAdminCanUninstall=這個程式要具備系統管理員權限的使用者方可解除安裝。
UninstallStatusLabel=正在從您的電腦移除 %1 中,請稍候...
UninstalledAll=%1 已經成功從您的電腦中移除。
UninstalledMost=%1 解除安裝完成。%n%n某些檔案及元件無法移除,您可以自行刪除這些檔案。
-UninstalledAndNeedsRestart=要完成 %1 的解除安裝程序,您必須重新啟動電腦。%n%n您想要現在重新啟動電腦嗎?
-UninstallDataCorrupted=檔案“%1”已經損毀,無法解除安裝
+UninstalledAndNeedsRestart=要完成 %1 的解除安裝程序,您必須重新啟動電腦。%n%n您想要現在重新啟動電腦嗎?
+UninstallDataCorrupted=檔案“%1”已經損毀,無法解除安裝。
; *** Uninstallation phase messages
ConfirmDeleteSharedFileTitle=移除共用檔案
@@ -362,8 +337,8 @@ WizardUninstalling=解除安裝狀態
StatusUninstalling=正在解除安裝 %1...
; *** Shutdown block reasons
-ShutdownBlockReasonInstallingApp=正在安裝 %1。
-ShutdownBlockReasonUninstallingApp=正在解除安裝 %1。
+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.
@@ -381,4 +356,4 @@ AssocFileExtension=將 %1 與檔案副檔名 %2 產生關聯(&A)
AssocingFileExtension=正在將 %1 與檔案副檔名 %2 產生關聯...
AutoStartProgramGroupDescription=開啟:
AutoStartProgram=自動開啟 %1
-AddonHostProgramNotFound=%1 無法在您所選的資料夾中找到。%n%n您是否還要繼續?
\ No newline at end of file
+AddonHostProgramNotFound=%1 無法在您所選的資料夾中找到。%n%n您是否還要繼續?
diff --git a/installer/innosetup/Languages/Croatian.isl b/Greenshot/releases/innosetup/Languages/Croatian.isl
similarity index 51%
rename from installer/innosetup/Languages/Croatian.isl
rename to Greenshot/releases/innosetup/Languages/Croatian.isl
index 7ebc5f41e..b8d946b5a 100644
--- a/installer/innosetup/Languages/Croatian.isl
+++ b/Greenshot/releases/innosetup/Languages/Croatian.isl
@@ -1,10 +1,10 @@
-; *** Inno Setup version 6.1.0+ Croatian messages ***
+; *** Inno Setup version 6.0.0+ Croatian messages ***
; Translated by: Milo Ivir (mail@milotype.de)
; Based on translation by Elvis Gambiraža (el.gambo@gmail.com)
; Based on translation by Krunoslav Kanjuh (krunoslav.kanjuh@zg.t-com.hr)
;
; To download user-contributed translations of this file, go to:
-; https://www.jrsoftware.org/files/istrans/
+; 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
@@ -42,7 +42,7 @@ ConfirmTitle=Potvrda
ErrorTitle=Greška
; *** SetupLdr messages
-SetupLdrStartupMessage=Ovime će se instalirati %1. Želiš li nastaviti?
+SetupLdrStartupMessage=Ovime ćeš instalirati %1. Želiš li nastaviti?
LdrCannotCreateTemp=Nije moguće stvoriti privremenu datoteku. Instalacija je prekinuta
LdrCannotExecTemp=Nije moguće pokrenuti datoteku u privremenoj mapi. Instalacija je prekinuta
HelpTextNote=
@@ -54,23 +54,23 @@ SetupFileCorrupt=Datoteke instalacije su oštećene. Nabavi novu kopiju programa
SetupFileCorruptOrWrongVer=Datoteke instalacije su oštećene ili nisu kompatibilne s ovom verzijom instalacije. Ispravi problem ili nabavi novu kopiju programa.
InvalidParameter=Neispravan parametar je prenijet u naredbenom retku:%n%n%1
SetupAlreadyRunning=Instalacija je već pokrenuta.
-WindowsVersionNotSupported=Program ne podržava Windows verziju koju koristiš.
+WindowsVersionNotSupported=Program ne podržava verziju Windowsa koju koristite.
WindowsServicePackRequired=Program zahtijeva %1 servisni paket %2 ili noviji.
-NotOnThisPlatform=Program neće raditi na %1.
-OnlyOnThisPlatform=Program se mora pokrenuti na %1.
-OnlyOnTheseArchitectures=Program se može instalirati na Windows verzijama za sljedeće procesorske arhitekture:%n%n%1
-WinVersionTooLowError=Program zahtijeva %1 verziju %2 ili noviju.
-WinVersionTooHighError=Program se ne može instalirati na %1 verziji %2 ili novijoj.
-AdminPrivilegesRequired=Za instaliranje programa moraš biti prijavljen/a kao administrator.
-PowerUserPrivilegesRequired=Za instaliranje programa moraš biti prijavljen/a kao administrator ili kao član grupe naprednih korisnika.
-SetupAppRunningError=Instalacija je otkrila da je %1 trenutačno pokrenut.%n%nZatvori program i potom pritisni "Dalje" za nastavak ili "Odustani" za prekid.
-UninstallAppRunningError=Deinstalacija je otkrila da je %1 trenutačno pokrenut.%n%nZatvori program i potom pritisni "Dalje" za nastavak ili "Odustani" za prekid.
+NotOnThisPlatform=Ovaj program neće raditi na %1.
+OnlyOnThisPlatform=Ovaj program se mora pokrenuti na %1.
+OnlyOnTheseArchitectures=Ovaj program može biti instaliran na verziji Windowsa dizajniranim za sljedeću procesorsku arhitekturu:%n%n%1
+WinVersionTooLowError=Ovaj program zahtijeva %1 verziju %2 ili noviju.
+WinVersionTooHighError=Ovaj program se ne može instalirati na %1 verziji %2 ili novijoj.
+AdminPrivilegesRequired=Morate biti prijavljeni kao administrator prilikom instaliranja ovog programa.
+PowerUserPrivilegesRequired=Morate biti prijavljeni kao administrator ili član grupe naprednih korisnika prilikom instaliranja ovog programa.
+SetupAppRunningError=Instalacija je otkrila da je %1 pokrenut.%n%nZatvorite program i potom kliknite "Dalje" za nastavak ili "Odustani" za prekid instalacije.
+UninstallAppRunningError=Deinstalacija je otkrila da je %1 pokrenut.%n%nZatvorite program i potom kliknite "Dalje" za nastavak ili "Odustani" za prekid instalacije.
; *** Startup questions
-PrivilegesRequiredOverrideTitle=Odaberi način instaliranja
-PrivilegesRequiredOverrideInstruction=Odaberi način instaliranja
-PrivilegesRequiredOverrideText1=%1 se može instalirati za sve korisnike (potrebna su administratorska prava) ili samo za tebe.
-PrivilegesRequiredOverrideText2=%1 se može instalirati samo za tebe ili za sve korisnike (potrebna su administratorska prava).
+PrivilegesRequiredOverrideTitle=Odaberite način instaliranja
+PrivilegesRequiredOverrideInstruction=Odaberite način instaliranja
+PrivilegesRequiredOverrideText1=%1 se može instalirati za sve korisnike (zahtijeva administrativna prava) ili samo za vas.
+PrivilegesRequiredOverrideText2=%1 se može instalirati samo za vas ili za sve korisnike (zahtijeva administrativna prava).
PrivilegesRequiredOverrideAllUsers=Instaliraj z&a sve korisnike
PrivilegesRequiredOverrideAllUsersRecommended=Instaliraj z&a sve korisnike (preporučeno)
PrivilegesRequiredOverrideCurrentUser=Instaliraj samo za &mene
@@ -78,14 +78,14 @@ PrivilegesRequiredOverrideCurrentUserRecommended=Instaliraj samo za &mene (prepo
; *** Misc. errors
ErrorCreatingDir=Instalacija nije mogla stvoriti mapu "%1"
-ErrorTooManyFilesInDir=Datoteku nije moguće stvoriti u mapi "%1", jer mapa sadrži previše datoteka
+ErrorTooManyFilesInDir=Nemoguće stvaranje datoteke u mapi "%1", jer ona sadrži previše datoteka
; *** Setup common messages
ExitSetupTitle=Prekini instalaciju
-ExitSetupMessage=Instalacija nije završena. Ako sad izađeš, program neće biti instaliran.%n%nInstalaciju možeš pokrenuti kasnije, ukoliko je želiš dovršiti.%n%nPrekinuti instalaciju?
+ExitSetupMessage=Instalacija nije završena. Ako sad izađete, program neće biti instaliran.%n%nInstalaciju možete pokrenuti kasnije, ukoliko ju želite završiti.%n%nPrekinuti instalaciju?
AboutSetupMenuItem=&O instalaciji …
AboutSetupTitle=O instalaciji
-AboutSetupMessage=%1 verzija %2%n%3%n%n%1 web-stranica:%n%4
+AboutSetupMessage=%1 verzija %2%n%3%n%n%1 početna stranica:%n%4
AboutSetupNote=
TranslatorNote=Prevodioci:%n%nKrunoslav Kanjuh%n%nElvis Gambiraža%n%nMilo Ivir
@@ -105,107 +105,105 @@ ButtonWizardBrowse=Odabe&ri …
ButtonNewFolder=&Stvori novu mapu
; *** "Select Language" dialog messages
-SelectLanguageTitle=Odaberi jezik za instalaciju
-SelectLanguageLabel=Odaberi jezik koji želiš koristiti tijekom instaliranja.
+SelectLanguageTitle=Odaberite jezik za instalaciju
+SelectLanguageLabel=Odberite jezik koji želite koristiti tijekom instaliranja.
; *** Common wizard text
-ClickNext=Pritisni "Dalje" za nastavak ili "Odustani" za prekid instalacije.
+ClickNext=Kliknite "Dalje" za nastavak ili "Odustani" za prekid instalacije.
BeveledLabel=
-BrowseDialogTitle=Odaberi mapu
-BrowseDialogLabel=Odaberi mapu iz popisa i pritisni "U redu".
+BrowseDialogTitle=Odaberite mapu
+BrowseDialogLabel=Odaberite mapu iz popisa te kliknite "U redu".
NewFolderName=Nova mapa
; *** "Welcome" wizard page
-WelcomeLabel1=Čarobnjak za instalaciju programa [name]
-WelcomeLabel2=Ovime ćeš instalirati [name/ver].%n%nPreporučujemo da zatvoriš sve programe prije nego što nastaviš dalje.
+WelcomeLabel1=Dobro došli u instalaciju programa [name]
+WelcomeLabel2=Ovaj program će instalirati [name/ver] na vaše računalo.%n%nPreporučamo da zatvorite sve programe prije nego što nastavite dalje.
; *** "Password" wizard page
WizardPassword=Lozinka
PasswordLabel1=Instalacija je zaštićena lozinkom.
-PasswordLabel3=Upiši lozinku i pritisni "Dalje". Lozinke su osjetljive na mala i velika slova.
+PasswordLabel3=Upišite lozinku i kliknite "Dalje". Lozinke su osjetljive na mala i velika slova.
PasswordEditLabel=&Lozinka:
-IncorrectPassword=Upisana je pogrešna lozinka. Pokušaj ponovo.
+IncorrectPassword=Upisana je pogrešna lozinka. Pokušajte ponovo.
; *** "License Agreement" wizard page
WizardLicense=Licencni ugovor
-LicenseLabel=Prije nego što nastaviš dalje, pažljivo pročitaj sljedeće važne informacije.
-LicenseLabel3=Pročitaj licencni ugovor. Moraš prihvatiti uvjete ugovora, ako želiš nastaviti instalirati.
+LicenseLabel=Prije nastavka pažljivo pročitajte sljedeće važne informacije.
+LicenseLabel3=Pročitajte licencni ugovor. Morate prihvatiti uvjete ugovora kako biste nastavili s instaliranjem.
LicenseAccepted=&Prihvaćam ugovor
LicenseNotAccepted=&Ne prihvaćam ugovor
; *** "Information" wizard pages
WizardInfoBefore=Informacije
-InfoBeforeLabel=Pročitaj sljedeće važne informacije prije nego što nastaviš dalje.
-InfoBeforeClickLabel=Kad želiš nastaviti instalirati, pritisni "Dalje".
+InfoBeforeLabel=Pročitajte sljedeće važne informacije prije nego što nastavite dalje.
+InfoBeforeClickLabel=Kada ste spremni nastaviti s instaliranjem, kliknite "Dalje".
WizardInfoAfter=Informacije
-InfoAfterLabel=Pročitaj sljedeće važne informacije prije nego što nastaviš dalje.
-InfoAfterClickLabel=Kad želiš nastaviti instalirati, pritisni "Dalje".
+InfoAfterLabel=Pročitajte sljedeće važne informacije prije nego što nastavite dalje.
+InfoAfterClickLabel=Kada ste spremni nastaviti s instaliranjem, kliknite "Dalje".
; *** "User Information" wizard page
-WizardUserInfo=Korisnički podaci
-UserInfoDesc=Upiši svoje podatke.
+WizardUserInfo=Informacije o korisniku
+UserInfoDesc=Upišite informacije o vama.
UserInfoName=&Ime korisnika:
UserInfoOrg=&Organizacija:
UserInfoSerial=&Serijski broj:
-UserInfoNameRequired=Ime je obavezno polje.
+UserInfoNameRequired=Morate upisati ime.
; *** "Select Destination Location" wizard page
-WizardSelectDir=Odaberi odredišno mjesto
-SelectDirDesc=Gdje želiš instalirati [name]?
-SelectDirLabel3=[name] će se instalirati u sljedeću mapu.
-SelectDirBrowseLabel=Za nastavak instalacije, pritisni "Dalje". Za odabir jedne druge mape, pritisni "Odaberi".
-DiskSpaceGBLabel=Potrebno je barem [gb] GB slobodnog prostora na disku.
+WizardSelectDir=Odaberite odredišno mjesto
+SelectDirDesc=Gdje treba instalirati [name]?
+SelectDirLabel3=Instalacija će instalirati [name] u sljedeću mapu.
+SelectDirBrowseLabel=Za nastavak kliknite na "Dalje". Ako želite odabrati drugu mapu, kliknite na "Odaberi".
DiskSpaceMBLabel=Potrebno je barem [mb] MB slobodnog prostora na disku.
CannotInstallToNetworkDrive=Instalacija ne može instalirati na mrežnu jedinicu.
CannotInstallToUNCPath=Instalacija ne može instalirati na UNC stazu.
-InvalidPath=Moraš upisati punu stazu zajedno sa slovom diska, npr.:%n%nC:\APP%n%nili UNC stazu u obliku:%n%n\\server\share
-InvalidDrive=Odabrani disk ne postoji. Odaberi jedan drugi.
+InvalidPath=Morate unijeti punu stazu zajedno sa slovom diska, npr.:%n%nC:\APP%n%nili UNC stazu u obliku:%n%n\\server\share
+InvalidDrive=Disk koji ste odabrali ne postoji. Odaberite neki drugi.
DiskSpaceWarningTitle=Nedovoljno prostora na disku
-DiskSpaceWarning=Instalacija treba barem %1 KB slobodnog prostora, no odabrani disk ima samo %2 KB.%n%nSvejedno nastaviti?
+DiskSpaceWarning=Instalacija zahtijeva barem %1 KB slobodnog prostora, a odabrani disk ima samo %2 KB na raspolaganju.%n%nŽelite li svejedno nastaviti?
DirNameTooLong=Naziv mape ili staze je predugačak.
InvalidDirName=Naziv mape je neispravan.
-BadDirName32=Naziv mape ne smije sadržavati sljedeće znakove:%n%n%1
+BadDirName32=Naziv mape ne smije sadržavati niti jedan od sljedećih znakova:%n%n%1
DirExistsTitle=Mapa već postoji
-DirExists=Mapa:%n%n%1%n%nveć postoji. Želiš li svejedno u nju instalirati?
+DirExists=Mapa:%n%n%1%n%nveć postoji. Želite li svejedno u nju instalirati?
DirDoesntExistTitle=Mapa ne postoji
-DirDoesntExist=Mapa:%n%n%1%n%nne postoji. Želiš li je stvoriti?
+DirDoesntExist=The folder:%n%n%1%n%nne postoji. Želite li ju stvoriti?
; *** "Select Components" wizard page
-WizardSelectComponents=Odaberi komponente
-SelectComponentsDesc=Koje komponente želiš instalirati?
-SelectComponentsLabel2=Odaberi komponente koje želiš instalirati, isključi komponente koje ne želiš instalirati. Za nastavak instalacije pritisni "Dalje".
+WizardSelectComponents=Odaberite komponente
+SelectComponentsDesc=Koje komponente želite instalirati?
+SelectComponentsLabel2=Odaberite komponente koje želite instalirati, isključite komponente koje ne želite instalirati. Za nastavak kliknite na "Dalje".
FullInstallation=Kompletna instalacija
; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
CompactInstallation=Kompaktna instalacija
CustomInstallation=Prilagođena instalacija
NoUninstallWarningTitle=Postojeće komponente
-NoUninstallWarning=Instalacija je utvrdila da na tvom računalu već postoje sljedeće komponente:%n%n%1%n%nIsključivanjem tih komponenata, one se neće deinstalirati.%n%nŽeliš li svejedno nastaviti?
+NoUninstallWarning=Instalacija je utvrdila da na vašem računalu već postoje sljedeće komponente:%n%n%1%n%nIsključivanjem tih komponenata, one neće biti deinstalirane.%n%nŽelite li ipak nastaviti?
ComponentSize1=%1 KB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=Trenutačni odabir zahtijeva barem [gb] GB na disku.
ComponentsDiskSpaceMBLabel=Trenutačni odabir zahtijeva barem [mb] MB na disku.
; *** "Select Additional Tasks" wizard page
-WizardSelectTasks=Odaberi dodatne zadatke
-SelectTasksDesc=Koje dodatne zadatke želiš izvršiti?
-SelectTasksLabel2=Odaberi zadatke koje želiš izvršiti tijekom instaliranja programa [name], zatim pritisni "Dalje".
+WizardSelectTasks=Odaberite dodatne zadatke
+SelectTasksDesc=Koje dodatne zadatke želite izvršiti?
+SelectTasksLabel2=Odaberite zadatke koje želite izvršiti tijekom instaliranja programa [name], zatim kliknite "Dalje".
; *** "Select Start Menu Folder" wizard page
-WizardSelectProgramGroup=Odaberi mapu iz "Start" izbornika
-SelectStartMenuFolderDesc=Gdje želiš da instalacija spremi programske prečace?
+WizardSelectProgramGroup=Odaberite mapu iz "Start" izbornika
+SelectStartMenuFolderDesc=Gdje želite da instalacija spremi programske prečace?
SelectStartMenuFolderLabel3=Instalacija će stvoriti programske prečace u sljedeću mapu "Start" izbornika.
-SelectStartMenuFolderBrowseLabel=Ako želiš nastaviti, pritisni "Dalje". Ako želiš odabrati jednu drugu mapu, pritisni "Odaberi".
-MustEnterGroupName=Moraš upisati naziv mape.
-GroupNameTooLong=Naziv mape ili staze je predugačak.
+SelectStartMenuFolderBrowseLabel=Kliknite "Dalje" za nastavak ili "Odaberi" za odabir jedne druge mape.
+MustEnterGroupName=Morate upisati naziv mape.
+GroupNameTooLong=Naziv mape ili staze je predug.
InvalidGroupName=Naziv mape nije ispravan.
BadGroupName=Naziv mape ne smije sadržavati sljedeće znakove:%n%n%1
NoProgramGroupCheck2=&Ne stvaraj mapu u "Start" izborniku
; *** "Ready to Install" wizard page
WizardReady=Sve je spremno za instaliranje
-ReadyLabel1=Instalacija je spremna za instaliranje programa [name].
-ReadyLabel2a=Pritisni "Instaliraj", ako želiš instalirati program. Pritisni "Natrag", ako želiš pregledati ili promijeniti postavke
-ReadyLabel2b=Pritisni "Instaliraj", ako želiš instalirati program.
+ReadyLabel1=Instalacija je spremna za instaliranje [name] na vaše računalo.
+ReadyLabel2a=Kliknite "Instaliraj" ako želite instalirati program ili "Natrag" ako želite pregledati ili promijeniti postavke
+ReadyLabel2b=Kliknite "Instaliraj" ako želite instalirati program.
ReadyMemoUserInfo=Korisnički podaci:
ReadyMemoDir=Odredišno mjesto:
ReadyMemoType=Vrsta instalacije:
@@ -213,44 +211,31 @@ ReadyMemoComponents=Odabrane komponente:
ReadyMemoGroup=Mapa u "Start" izborniku:
ReadyMemoTasks=Dodatni zadaci:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=Preuzimanje dodatnih datoteka …
-ButtonStopDownload=&Prekini preuzimanje
-StopDownload=Stvarno želiš prekinuti preuzimanje?
-ErrorDownloadAborted=Preuzimanje je prekinuto
-ErrorDownloadFailed=Neuspjelo preuzimanje: %1 %2
-ErrorDownloadSizeFailed=Neuspjelo dohvaćanje veličine: %1 %2
-ErrorFileHash1=Izračunavanje kontrolnog zbroja datoteke neuspjelo: %1
-ErrorFileHash2=Neispravan kontrolni zbroj datoteke: očekivano %1, pronađeno %2
-ErrorProgress=Neispravan napredak: %1 od %2
-ErrorFileSize=Neispravna veličina datoteke: očekivano %1, pronađeno %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=Priprema za instaliranje
-PreparingDesc=Instalacija se priprema za instaliranje programa [name].
-PreviousInstallNotCompleted=Instaliranje/uklanjanje jednog prethodnog programa nije bilo gotovo. Morat ćeš ponovo pokrenuti računalo i dovršiti to instaliranje.%n%nNakon ponovnog pokretanja računala, pokreni instalaciju ponovo, kako bi se dovršilo instaliranje programa [name].
-CannotContinue=Instalacija ne može nastaviti rad. Pritisni "Odustani" za izlaz iz instalacije.
-ApplicationsFound=Sljedeći programi koriste datoteke koje instalacija mora aktualizirati. Preporučujemo da dopustiš instalaciji zatvoriti ove programe.
-ApplicationsFound2=Sljedeći programi koriste datoteke koje instalacija mora aktualizirati. Preporučujemo da dopustiš instalaciji zatvoriti ove programe. Kad instaliranje završi, instalacija će pokušati ponovo pokrenuti programe.
+PreparingDesc=Instalacija se priprema za instaliranje [name] na vaše računalo.
+PreviousInstallNotCompleted=The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.%n%nAfter restarting your computer, run Setup again to complete the installation of [name].
+CannotContinue=Instalacija ne može nastaviti. Kliknite na "Odustani" za izlaz.
+ApplicationsFound=Sljedeći programi koriste datoteke koje instalacija mora aktualiziranti. Preporučamo da dopustite instalaciji da zatvori ove programe.
+ApplicationsFound2=Sljedeći programi koriste datoteke koje instalacija mora aktualiziranti. Preporučamo da dopustite instalaciji da zatvori ove programe. Kad instaliranje završi, instalacija će pokušati ponovo pokrenuti programe.
CloseApplications=&Zatvori programe automatski
DontCloseApplications=&Ne zatvaraj programe
-ErrorCloseApplications=Instalacija nije uspjela automatski zatvoriti programe. Preporučujemo da zatvoriš sve programe koji koriste datoteke koje se moraju aktualizirati.
-PrepareToInstallNeedsRestart=Instalacija mora ponovo pokrenuti računalo. Nakon ponovnog pokretanja računala, pokreni instalaciju ponovo, kako bi se dovršilo instaliranje programa [name].%n%nŽeliš li sada ponovo pokrenuti računalo?
+ErrorCloseApplications=Instalacija nij uspjela automatski zatvoriti programe. Preporučamo da zatvorite sve programe koji koriste datoteke, koje se moraju aktulaizirati.
; *** "Installing" wizard page
WizardInstalling=Instaliranje
-InstallingLabel=Pričekaj dok ne završi instaliranje programa [name].
+InstallingLabel=Pričekajte dok ne završi instaliranje programa [name] na vaše računalo.
; *** "Setup Completed" wizard page
FinishedHeadingLabel=Završavanje instalacijskog čarobnjaka za [name]
-FinishedLabelNoIcons=Instalacija je završila instaliranje programa [name].
-FinishedLabel=Instalacija je završila instaliranje programa [name]. Program se može pokrenuti pomoću instaliranih prečaca.
-ClickFinish=Za izlaz iz instalacije pritisni "Završi".
-FinishedRestartLabel=Za završavanje instaliranja programa [name], instalacija mora ponovo pokrenuti računalo. Želiš li sada ponovo pokrenuti računalo?
-FinishedRestartMessage=Za završavanje instaliranja programa [name], instalacija mora ponovo pokrenuti računalo.%n%nŽeliš li sada ponovo pokrenuti računalo?
+FinishedLabelNoIcons=Instalacija je završila instaliranje programa [name] na vaše računalo.
+FinishedLabel=Instalacija je završila instaliranje programa [name] na vaše računalo. Program se može pokrenuti pomoću instaliranih prečaca.
+ClickFinish=Kliknite na "Završi" kako biste izašli iz instalacije.
+FinishedRestartLabel=Kako biste završili instaliranje programa [name], potrebno je ponovo pokrenuti računalo. Želite li to sada učiniti?
+FinishedRestartMessage=Kako biste završili instaliranje programa [name], potrebno je ponovo pokrenuti računalo.%n%nŽelite li to sada učiniti?
ShowReadmeCheck=Da, želim pročitati README datoteku
-YesRadio=&Da, sada ponovo pokrenuti računalo
-NoRadio=&Ne, računalo ću kasnije ponovo pokrenuti
+YesRadio=&Da, želim sad ponovo pokrenuti računalo
+NoRadio=&Ne, kasnije ću ponovo pokrenuti računalo
; used for example as 'Run MyProg.exe'
RunEntryExec=Pokreni %1
; used for example as 'View Readme.txt'
@@ -258,14 +243,14 @@ RunEntryShellExec=Prikaži %1
; *** "Setup Needs the Next Disk" stuff
ChangeDiskTitle=Instalacija treba sljedeći disk
-SelectDiskLabel2=Umetni disk %1 i pritisni "U redu".%n%nAko se datoteke s ovog diska nalaze na nekom drugom mjestu od dolje prikazanog, upiši ispravnu stazu ili pritisni "Odaberi".
+SelectDiskLabel2=Umetnite disk %1 i kliknite na "U redu".%n%nAko se datoteke s ovog diska nalaze na nekom drugom mjestu od prikazanog ispod, upišite ispravnu stazu ili kliknite na "Odaberi".
PathLabel=&Staza:
-FileNotInDir2=Staza "%1" ne postoji u "%2". Umetni odgovarajući disk ili odaberi jednu drugu mapu.
-SelectDirectoryLabel=Odredi mjesto sljedećeg diska.
+FileNotInDir2=Staza "%1" ne postoji u "%2". Umetnite odgovarajući disk ili odaberite jednu drugu mapu.
+SelectDirectoryLabel=Odaberite mjesto sljedećeg diska.
; *** Installation phase messages
-SetupAborted=Instalacija nije završena.%n%nIspravi problem i ponovo pokreni instalaciju.
-AbortRetryIgnoreSelectAction=Odaberi radnju
+SetupAborted=Instalacija nije završena.%n%nIspravite problem i ponovo pokrenite instalaciju.
+AbortRetryIgnoreSelectAction=Odaberite radnju
AbortRetryIgnoreRetry=&Pokušaj ponovo
AbortRetryIgnoreIgnore=&Zanemari grešku i nastavi
AbortRetryIgnoreCancel=Prekini s instaliranjem
@@ -285,10 +270,10 @@ StatusRollback=Poništavanje promjena …
; *** Misc. errors
ErrorInternal2=Interna greška: %1
-ErrorFunctionFailedNoCode=%1 – neuspjelo
-ErrorFunctionFailed=%1 – neuspjelo; kod %2
-ErrorFunctionFailedWithMessage=%1 – neuspjelo; kod %2.%n%3
-ErrorExecutingProgram=Nije moguće izvršiti datoteku:%n%1
+ErrorFunctionFailedNoCode=%1 nije uspjelo
+ErrorFunctionFailed=%1 nije uspjelo; kod %2
+ErrorFunctionFailedWithMessage=%1 failed; kod %2.%n%3
+ErrorExecutingProgram=Nije moguće pokrenuti datoteku:%n%1
; *** Registry errors
ErrorRegOpenKey=Greška prilikom otvaranja ključa registra:%n%1\%2
@@ -299,25 +284,17 @@ ErrorRegWriteKey=Greška prilikom pisanja u ključ registra:%n%1\%2
ErrorIniEntry=Greška prilikom stvaranja INI unosa u datoteci "%1".
; *** File copying errors
-FileAbortRetryIgnoreSkipNotRecommended=&Preskoči ovu datoteku (ne preporučuje se)
-FileAbortRetryIgnoreIgnoreNotRecommended=&Zanemari grešku i nastavi (ne preporučuje se)
-SourceIsCorrupted=Izvorna datoteka je oštećena
-SourceDoesntExist=Izvorna datoteka "%1" ne postoji
+FileAbortRetryIgnoreSkipNotRecommended=&Preskoči ovu datoteku (ne preporuča se)
+FileAbortRetryIgnoreIgnoreNotRecommended=&Zanemari grešku i nastavi (ne preporuča se)
+SourceIsCorrupted=Izvorišna datoteka je oštećena
+SourceDoesntExist=Izvorišna datoteka "%1" ne postoji
ExistingFileReadOnly2=Postojeću datoteku nije bilo moguće zamijeniti, jer je označena sa "samo-za-čitanje".
-ExistingFileReadOnlyRetry=&Ukloni svojstvo "samo-za-čitanje" i pokušaj ponovo
+ExistingFileReadOnlyRetry=&Uklonite atribut "samo-za-čitanje" i pokušajte ponovo
ExistingFileReadOnlyKeepExisting=&Zadrži postojeću datoteku
ErrorReadingExistingDest=Pojavila se greška prilikom pokušaja čitanja postojeće datoteke:
-FileExistsSelectAction=Odaberi radnju
-FileExists2=Datoteka već postoji.
-FileExistsOverwriteExisting=&Prepiši postojeću datoteku
-FileExistsKeepExisting=&Zadrži postojeću datoteku
-FileExistsOverwriteOrKeepAll=&Uradi to i u narednim slučajevima
-ExistingFileNewerSelectAction=Odaberi radnju
-ExistingFileNewer2=Postojeća datoteka je novija od one koja se pokušava instalirati.
-ExistingFileNewerOverwriteExisting=&Prepiši postojeću datoteku
-ExistingFileNewerKeepExisting=&Zadrži postojeću datoteku (preporučeno)
-ExistingFileNewerOverwriteOrKeepAll=&Uradi to i u narednim slučajevima
-ErrorChangingAttr=Pojavila se greška prilikom pokušaja promjene svojstva postojeće datoteke:
+FileExists=The file already exists.%n%nŽelite li da ju instalacija prepiše?
+ExistingFileNewer=Postojeća datoteka je novija od one, koju pokušavate instalirati. Preporuča se da zadržite postojeću datoteku.%n%nŽelite li zadržati postojeću datoteku?
+ErrorChangingAttr=Pojavila se greška prilikom pokušaja promjene atributa postojeće datoteke:
ErrorCreatingTemp=Pojavila se greška prilikom pokušaja stvaranja datoteke u odredišnoj mapi:
ErrorReadingSource=Pojavila se greška prilikom pokušaja čitanja izvorišne datoteke:
ErrorCopying=Pojavila se greška prilikom pokušaja kopiranja datoteke:
@@ -326,7 +303,7 @@ ErrorRestartReplace=Zamijenjivanje nakon ponovnog pokretanja nije uspjelo:
ErrorRenamingTemp=Pojavila se greška prilikom pokušaja preimenovanja datoteke u odredišnoj mapi:
ErrorRegisterServer=Nije moguće registrirati DLL/OCX: %1
ErrorRegSvr32Failed=Greška u RegSvr32. Izlazni kod %1
-ErrorRegisterTypeLib=Nije moguće registrirati biblioteku vrsta: %1
+ErrorRegisterTypeLib=Nije moguće registrirati type library: %1
; *** Uninstall display name markings
; used for example as 'My Program (32-bit)'
@@ -340,25 +317,25 @@ UninstallDisplayNameMarkCurrentUser=Trenutačni korisnik
; *** Post-installation errors
ErrorOpeningReadme=Pojavila se greška prilikom pokušaja otvaranja README datoteke.
-ErrorRestartingComputer=Instalacija nije mogla ponovo pokrenuti računalo. Učini to ručno.
+ErrorRestartingComputer=Instalacija nije mogla ponovo pokrenuti računalo. Učinite to ručno.
; *** Uninstaller messages
UninstallNotFound=Datoteka "%1" ne postoji. Deinstaliranje nije moguće.
UninstallOpenError=Datoteku "%1" nije bilo moguće otvoriti. Deinstaliranje nije moguće
UninstallUnsupportedVer=Deinstalacijska datoteka "%1" je u formatu koji ova verzija deinstalacijskog programa ne prepoznaje. Deinstaliranje nije moguće
-UninstallUnknownEntry=Pronađen je nepoznat zapis (%1) u deinstalacijskoj datoteci
-ConfirmUninstall=Zaista želiš ukloniti %1 i sve pripadajuće komponente?
+UninstallUnknownEntry=Nepoznat zapis (%1) je pronađen u deinstalacijskoj datoteci
+ConfirmUninstall=Zaista želite ukloniti %1 i sve pripadajuće komponente?
UninstallOnlyOnWin64=Ovu instalaciju je moguće ukloniti samo na 64-bitnom Windows sustavu.
-OnlyAdminCanUninstall=Ovu instalaciju može ukloniti samo korisnik s administratorskim pravima.
-UninstallStatusLabel=Pričekaj dok se %1 uklanja s računala.
-UninstalledAll=%1 je uspješno uklonjen s računala.
-UninstalledMost=Deinstaliranje programa %1 je završeno.%n%nNeke elemente nije bilo moguće ukloniti. Oni se mogu ukloniti ručno.
-UninstalledAndNeedsRestart=Za završavanje deinstaliranja programa %1, potrebno je ponovo pokrenuti računalo.%n%nŽeliš li to sada učiniti?
+OnlyAdminCanUninstall=Ovu instalaciju je moguće ukloniti samo korisnik s administrativnim pravima.
+UninstallStatusLabel=Pričekajte dok se %1 uklanja s vašeg računala.
+UninstalledAll=%1 je uspješno uklonjen s vašeg računala.
+UninstalledMost=Deinstaliranje programa %1 je završeno.%n%nNeke elemente nije bilo moguće ukloniti. Mogu se ukloniti ručno.
+UninstalledAndNeedsRestart=Kako biste završili deinstalirati %1, morate ponovo pokrenuti vaše računalo%n%nŽelite li to sad učiniti?
UninstallDataCorrupted="%1" datoteka je oštećena. Deinstaliranje nije moguće
; *** Uninstallation phase messages
ConfirmDeleteSharedFileTitle=Ukloniti dijeljene datoteke?
-ConfirmDeleteSharedFile2=Sustav ukazuje na to, da sljedeću dijeljenu datoteku ne koristi niti jedan program. Želiš li ukloniti tu dijeljenu datoteku?%n%nAko neki programi i dalje koriste tu datoteku, a ona se izbriše, ti programi neće ispravno raditi. Ako ne znaš, odaberi "Ne". Datoteka neće štetiti tvom sustavu.
+ConfirmDeleteSharedFile2=Sustav ukazuje na to, da sljedeće dijeljenu datoteku ne koristi niti jedan program. Želite li ukloniti tu dijeljenu datoteku?%n%nAko neki programi i dalje koriste tu datoteku, a ona se izbriše, ti programi neće ispravno raditi. Ako niste sigurni, odaberite "Ne". Datoteka neće štetiti vašem sustavu.
SharedFileNameLabel=Datoteka:
SharedFileLocationLabel=Mjesto:
WizardUninstalling=Stanje deinstalacije
@@ -384,4 +361,4 @@ AssocFileExtension=&Poveži program %1 s datotečnim nastavkom %2
AssocingFileExtension=Povezivanje programa %1 s datotečnim nastavkom %2 …
AutoStartProgramGroupDescription=Pokretanje:
AutoStartProgram=Automatski pokreni %1
-AddonHostProgramNotFound=%1 nije nađen u odabranoj mapi.%n%nŽeliš li svejedno nastaviti?
+AddonHostProgramNotFound=%1 nije nađen u odabranoj mapi.%n%nŽelite li svejedno nastaviti?
diff --git a/installer/innosetup/Languages/EnglishBritish.isl b/Greenshot/releases/innosetup/Languages/EnglishBritish.isl
similarity index 82%
rename from installer/innosetup/Languages/EnglishBritish.isl
rename to Greenshot/releases/innosetup/Languages/EnglishBritish.isl
index 60a941064..309c560ae 100644
--- a/installer/innosetup/Languages/EnglishBritish.isl
+++ b/Greenshot/releases/innosetup/Languages/EnglishBritish.isl
@@ -1,7 +1,6 @@
-; *** Inno Setup version 6.1.0+ English (British) messages ***
+; *** Inno Setup version 5.5.3+ English (British) messages ***
;
; Translated by Boris Kotov
-; Translation updated by Andrew Truckle
[LangOptions]
; The following three entries are very important. Be sure to read and
@@ -50,6 +49,7 @@ WindowsServicePackRequired=This program requires %1 Service Pack %2 or later.
NotOnThisPlatform=This program will not run on %1.
OnlyOnThisPlatform=This program must be run on %1.
OnlyOnTheseArchitectures=This program can only be installed on versions of Windows designed for the following processor architectures:%n%n%1
+MissingWOW64APIs=The version of Windows you are running does not include functionality required by Setup to perform a 64-bit installation. To correct this problem, please install Service Pack %1.
WinVersionTooLowError=This program requires %1 version %2 or later.
WinVersionTooHighError=This program cannot be installed on %1 version %2 or later.
AdminPrivilegesRequired=You must be logged in as an administrator when installing this program.
@@ -57,16 +57,6 @@ PowerUserPrivilegesRequired=You must be logged in as an administrator or as a me
SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
-; *** Startup questions
-PrivilegesRequiredOverrideTitle=Select Setup Install Mode
-PrivilegesRequiredOverrideInstruction=Select install mode
-PrivilegesRequiredOverrideText1=%1 can be installed for all users (requires administrative privileges), or for you only.
-PrivilegesRequiredOverrideText2=%1 can be installed for you only, or for all users (requires administrative privileges).
-PrivilegesRequiredOverrideAllUsers=Install for &all users
-PrivilegesRequiredOverrideAllUsersRecommended=Install for &all users (recommended)
-PrivilegesRequiredOverrideCurrentUser=Install for &me only
-PrivilegesRequiredOverrideCurrentUserRecommended=Install for &me only (recommended)
-
; *** Misc. errors
ErrorCreatingDir=Setup was unable to create the directory "%1"
ErrorTooManyFilesInDir=Unable to create a file in the directory "%1" because it contains too many files
@@ -145,7 +135,6 @@ WizardSelectDir=Select Destination Location
SelectDirDesc=Where should [name] be installed?
SelectDirLabel3=Setup will install [name] into the following folder.
SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse.
-DiskSpaceGBLabel=At least [gb] GB of free disk space is required.
DiskSpaceMBLabel=At least [mb] MB of free disk space is required.
CannotInstallToNetworkDrive=Setup cannot install to a network drive.
CannotInstallToUNCPath=Setup cannot install to a UNC path.
@@ -173,7 +162,6 @@ NoUninstallWarningTitle=Components Exist
NoUninstallWarning=Setup has detected that the following components are already installed on your computer:%n%n%1%n%nDeselecting these components will not uninstall them.%n%nWould you like to continue anyway?
ComponentSize1=%1 KB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=Current selection requires at least [gb] GB of disk space.
ComponentsDiskSpaceMBLabel=Current selection requires at least [mb] MB of disk space.
; *** "Select Additional Tasks" wizard page
@@ -204,18 +192,6 @@ ReadyMemoComponents=Selected components:
ReadyMemoGroup=Start Menu folder:
ReadyMemoTasks=Additional tasks:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=Downloading additional files...
-ButtonStopDownload=&Stop download
-StopDownload=Are you sure you want to stop the download?
-ErrorDownloadAborted=Download aborted
-ErrorDownloadFailed=Download failed: %1 %2
-ErrorDownloadSizeFailed=Getting size failed: %1 %2
-ErrorFileHash1=File hash failed: %1
-ErrorFileHash2=Invalid file hash: expected %1, found %2
-ErrorProgress=Invalid progress: %1 of %2
-ErrorFileSize=Invalid file size: expected %1, found %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=Preparing to Install
PreparingDesc=Setup is preparing to install [name] on your computer.
@@ -226,7 +202,6 @@ ApplicationsFound2=The following applications are using files that need to be up
CloseApplications=&Automatically close the applications
DontCloseApplications=&Do not close the applications
ErrorCloseApplications=Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing.
-PrepareToInstallNeedsRestart=Setup must restart your computer. After restarting your computer, run Setup again to complete the installation of [name].%n%nWould you like to restart now?
; *** "Installing" wizard page
WizardInstalling=Installing
@@ -256,10 +231,7 @@ SelectDirectoryLabel=Please specify the location of the next disk.
; *** Installation phase messages
SetupAborted=Setup was not completed.%n%nPlease correct the problem and run Setup again.
-AbortRetryIgnoreSelectAction=Select action
-AbortRetryIgnoreRetry=&Try again
-AbortRetryIgnoreIgnore=&Ignore the error and continue
-AbortRetryIgnoreCancel=Cancel installation
+EntryAbortRetryIgnore=Click Retry to try again, Ignore to proceed anyway, or Abort to cancel installation.
; *** Installation status messages
StatusClosingApplications=Closing applications...
@@ -290,24 +262,14 @@ ErrorRegWriteKey=Error writing to registry key:%n%1\%2
ErrorIniEntry=Error creating INI entry in file "%1".
; *** File copying errors
-FileAbortRetryIgnoreSkipNotRecommended=&Skip this file (not recommended)
-FileAbortRetryIgnoreIgnoreNotRecommended=&Ignore the error and continue (not recommended)
+FileAbortRetryIgnore=Click Retry to try again, Ignore to skip this file (not recommended), or Abort to cancel installation.
+FileAbortRetryIgnore2=Click Retry to try again, Ignore to proceed anyway (not recommended), or Abort to cancel installation.
SourceIsCorrupted=The source file is corrupted
SourceDoesntExist=The source file "%1" does not exist
-ExistingFileReadOnly2=The existing file could not be replaced because it is marked read-only.
-ExistingFileReadOnlyRetry=&Remove the read-only attribute and try again
-ExistingFileReadOnlyKeepExisting=&Keep the existing file
+ExistingFileReadOnly=The existing file is marked as read-only.%n%nClick Retry to remove the read-only attribute and try again, Ignore to skip this file, or Abort to cancel installation.
ErrorReadingExistingDest=An error occurred while trying to read the existing file:
-FileExistsSelectAction=Select action
-FileExists2=The file already exists.
-FileExistsOverwriteExisting=&Overwrite the existing file
-FileExistsKeepExisting=&Keep the existing file
-FileExistsOverwriteOrKeepAll=&Do this for the next conflicts
-ExistingFileNewerSelectAction=Select action
-ExistingFileNewer2=The existing file is newer than the one Setup is trying to install.
-ExistingFileNewerOverwriteExisting=&Overwrite the existing file
-ExistingFileNewerKeepExisting=&Keep the existing file (recommended)
-ExistingFileNewerOverwriteOrKeepAll=&Do this for the next conflicts
+FileExists=The file already exists.%n%nWould you like Setup to overwrite it?
+ExistingFileNewer=The existing file is newer than the one Setup is trying to install. It is recommended that you keep the existing file.%n%nDo you want to keep the existing file?
ErrorChangingAttr=An error occurred while trying to change the attributes of the existing file:
ErrorCreatingTemp=An error occurred while trying to create a file in the destination directory:
ErrorReadingSource=An error occurred while trying to read the source file:
@@ -319,16 +281,6 @@ ErrorRegisterServer=Unable to register the DLL/OCX: %1
ErrorRegSvr32Failed=RegSvr32 failed with exit code %1
ErrorRegisterTypeLib=Unable to register the type library: %1
-; *** Uninstall display name markings
-; used for example as 'My Program (32-bit)'
-UninstallDisplayNameMark=%1 (%2)
-; used for example as 'My Program (32-bit, All users)'
-UninstallDisplayNameMarks=%1 (%2, %3)
-UninstallDisplayNameMark32Bit=32-bit
-UninstallDisplayNameMark64Bit=64-bit
-UninstallDisplayNameMarkAllUsers=All users
-UninstallDisplayNameMarkCurrentUser=Current user
-
; *** Post-installation errors
ErrorOpeningReadme=An error occurred while trying to open the README file.
ErrorRestartingComputer=Setup was unable to restart the computer. Please do this manually.
diff --git a/Greenshot/releases/innosetup/Languages/Esperanto.isl b/Greenshot/releases/innosetup/Languages/Esperanto.isl
new file mode 100644
index 000000000..5896c824c
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Esperanto.isl
@@ -0,0 +1,342 @@
+; *** Inno Setup version 5.5.3+ Esperanto messages ***
+;
+; Author: Alexander Gritchin (E-mail - alexgrimo@mail.ru)
+;
+; Au`toro: Alexander Gritc`in (E-mail - alexgrimo@mail.ru)
+; Versio del traduko - 15.06.08
+;
+;
+;
+; 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=Esperanto
+LanguageID=$0
+LanguageCodePage=0
+; 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=Instalado
+SetupWindowTitle=Instalado de - %1
+UninstallAppTitle=Forigado
+UninstallAppFullTitle=Forigado de %1
+
+; *** Misc. common
+InformationTitle=Informacio
+ConfirmTitle=Konfirmado
+ErrorTitle=Eraro
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=Nun estos instalado de %1. C`u vi volas kontinui?
+LdrCannotCreateTemp=Nepoveble estas krei tempan dosieron. La Majstro estas s`topita
+LdrCannotExecTemp=Nepoveble estas plenumi la dosieron en tempa dosierujo. La Majstro estas s`topita
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%nEraro %2: %3
+SetupFileMissing=La dosiero %1 estas preterpasita el instala dosierujo.Bonvolu korekti problemon au` ricevu novan kopion de programo.
+SetupFileCorrupt=Instalaj dosieroj estas kriplitaj. Bonvolu ricevu novan kopion de programo.
+SetupFileCorruptOrWrongVer=Instalaj dosieroj estas kriplitaj, au` ne komparablaj kun tia versio del Majstro. Bonvolu korekti problemon au` ricevu novan kopion de programo.
+InvalidParameter=Malg`usta parametro estis en komandlinio:%n%n%1
+SetupAlreadyRunning=La Majstro jam funkcias.
+WindowsVersionNotSupported=C`i tia programo ne povas subteni la version de Vindoso en via komputilo.
+WindowsServicePackRequired=Por c`i tia programo bezonas %1 Service Pack %2 au` pli olda.
+NotOnThisPlatform=C`i tia programo ne funkcios en %1.
+OnlyOnThisPlatform=C`i tia programo devas funkcii en %1.
+OnlyOnTheseArchitectures=C`i tia programo nur povas esti instalita en version de Vindoso por sekvaj procesoraj arkitekturoj:%n%n%1
+MissingWOW64APIs=La versio de Vindoso kian vi lanc`is, ne havas posedon bezonatan por ke Majstro plenumis 64-bit instaladon. Por korekti tian problemon bonvolu instali Service Pack %1.
+WinVersionTooLowError=Por c`i tia programo bezonas %1 version %2 au` pli olda.
+WinVersionTooHighError=C`i tia programo ne povas esti instalita en %1 versio %2 au` pli olda.
+AdminPrivilegesRequired=Vi devas eniri kiel administranto kiam instalas c`i tian programon.
+PowerUserPrivilegesRequired=Vi devas eniri kiel administranto au` kiel membro de grupo de Posedaj Uzantoj kiam instalas c`i tia programo.
+SetupAppRunningError=La Majstro difinis ke %1 nun funkcias.%n%nBonvolu s`topi g`in, kaj poste kliku Jes por kontinui, au` S`topi por eliri.
+UninstallAppRunningError=Forigados difinis ke %1 nun funkcias.%n%nBonvolu s`topi g`in, kaj poste kliku Jes por kontinui, au` S`topi por eliri.
+
+; *** Misc. errors
+ErrorCreatingDir=La Majstro ne povas krei dosierujon "%1"
+ErrorTooManyFilesInDir=Estas nepoveble krei dosieron en dosierujo "%1" pro tio ke g`i havas tro multe da dosierojn
+
+; *** Setup common messages
+ExitSetupTitle=S`topo Majstron
+ExitSetupMessage=La instalado ne estas plena. Se vi eliros nun, la programo ne estos instalita.%n%nPor vi bezonas s`alti Majstron denove en alia tempo por plenumi instaladon.%n%nC`u fini la Majstron?
+AboutSetupMenuItem=&Pri instalo...
+AboutSetupTitle=Pri instalo
+AboutSetupMessage=%1 version %2%n%3%n%n%1 hejma pag`o:%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< &Reen
+ButtonNext=&Antau`en >
+ButtonInstall=&Instali
+ButtonOK=Jes
+ButtonCancel=S`topi
+ButtonYes=&Jes
+ButtonYesToAll=Jes por &c`iaj
+ButtonNo=&Ne
+ButtonNoToAll=Ne por c`iaj
+ButtonFinish=&Fino
+ButtonBrowse=&Elekto...
+ButtonWizardBrowse=Elekto...
+ButtonNewFolder=&Fari la novan dosierujon
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=Elektu la lingvon
+SelectLanguageLabel=Elektu la lingvon por uzo dum instalado:
+
+; *** Common wizard text
+ClickNext=Kliku Antau`en por kontinui, au` S`topi por eliri Instaladon.
+BeveledLabel=
+BrowseDialogTitle=Elekto de dosierujo
+BrowseDialogLabel=Elektu la dosierujon en listo malalte, kaj kliku Jes.
+NewFolderName=Nova dosierujo
+
+; *** "Welcome" wizard page
+WelcomeLabel1=Bonvenon al Majstro de instalado de [name]
+WelcomeLabel2=Nun komencos instalado de [name/ver] en via komputilo.%n%nEstas rekomendite ke vi s`topu c`iajn viajn programojn antau` komenco.
+
+; *** "Password" wizard page
+WizardPassword=Pasvorto
+PasswordLabel1=C`i tia instalado postulas pasvorton.
+PasswordLabel3=Bonvolu tajpi pasvorton kaj poste kliku Antau`en por kontinui. La pasvortoj estas tajp sentemaj.
+PasswordEditLabel=&Pasvorto:
+IncorrectPassword=La pasvorto, kian vi tajpis estas malg`usta. Bonvolu provi denove.
+
+; *** "License Agreement" wizard page
+WizardLicense=Licenza konvenio
+LicenseLabel=Bonvolu legi sekvan gravan informacion antau` komenci.
+LicenseLabel3=Bonvolu legi sekvan Licenzan Konvenion. Vi devas akcepti dotaj`oj de tia konvenio antau` ke kontinui instaladon.
+LicenseAccepted=Mi akceptas konvenion
+LicenseNotAccepted=Mi ne akceptas konvenion
+
+; *** "Information" wizard pages
+WizardInfoBefore=Informacio
+InfoBeforeLabel=Bonvolu legi sekvan gravan informacion antau` komenci.
+InfoBeforeClickLabel=Kiam vi estas preta por kontinui per instalo, kliku Antau`en.
+WizardInfoAfter=Informacio
+InfoAfterLabel=Bonvolu legi sekvan gravan informacion antau` komenci.
+InfoAfterClickLabel=Kiam vi estas preta por kontinui per instalo, kliku Antau`en.
+
+; *** "User Information" wizard page
+WizardUserInfo= Informacio pri uzanto
+UserInfoDesc=Bonvolu skribi vian informacion.
+UserInfoName=Nomo de uzanto:
+UserInfoOrg=&Organizacio:
+UserInfoSerial=&Seria Numero:
+UserInfoNameRequired=Vi devas skribi nomon de uzanto.
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=Elektu Destinan Locon
+SelectDirDesc=Kie devos [name] esti instalita?
+SelectDirLabel3=La Majstro instalos [name] en sekvan dosierujon.
+SelectDirBrowseLabel=Por kontinui, kliku Antau`en. Se vi volas elekti diversan dosierujon, kliku Elekto.
+DiskSpaceMBLabel=Almenau` [mb] MB de neta diska spaco bezonas.
+CannotInstallToNetworkDrive=Majstro ne povas instali lokan diskon.
+CannotInstallToUNCPath=Majstro ne povas instali lau` UNC vojo.
+InvalidPath=Vi devas skribi plenan vojon de diska litero; por ekzamplo:%n%nC:\APP%n%sed ne UNC vojo lau` formo:%n%n\\server\share
+InvalidDrive=Disko au` UNC kian vi elektis ne ekzistas au` ne estas difinita. Bonvolu elekti denove.
+DiskSpaceWarningTitle=Mankas Diskan Spacon
+DiskSpaceWarning=Por instalo bezonas almenau` %1 KB de neta spaco por instalado, sed electita disko havas nur %2 KB.%n%nC`u vi volas kontinui per c`iokaze?
+DirNameTooLong=La nomo de dosierujo au` vojo estas tro longa.
+InvalidDirName=La nomo de dosierujo estas malg`usta.
+BadDirName32=La nomoj de dosierujoj ne povas havi de sekvaj karakteroj:%n%n%1
+DirExistsTitle=Dosierujo ekzistas
+DirExists=La dosierujo:%n%n%1%n%njam ekzistas. C`u vi volas instali en g`i c`iokaze?
+DirDoesntExistTitle=La dosierujo ne ekzistas
+DirDoesntExist=La dosierujo:%n%n%1%n%nne ekzistas. C`u vi volas por ke tia dosierujo estos farita?
+
+; *** "Select Components" wizard page
+WizardSelectComponents=Elektu komponentoj
+SelectComponentsDesc=Kiaj komponentoj devas esti instalitaj?
+SelectComponentsLabel2=Elektu komponentoj kiaj vi volas instali; forigu la komponentojn kiaj vi ne volas instali. Kliku Antau`en kiam vi estas preta por kontinui.
+FullInstallation=Tuta instalado
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=Kompakta instalado
+CustomInstallation=Kutima instalado
+NoUninstallWarningTitle=Komponentoj ekzistas
+NoUninstallWarning=La Majstro difinis ke sekvaj komponentoj jam estas instalitaj en via komputilo:%n%n%1%n%nNuligo de elekto de tiaj komponentoj ne forigos g`in.%n%nC`u vi volas kontinui c`iokaze?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=Nuna elekto bezonas almenau` [mb] MB de diska spaco.
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=Elektu aldonaj taskoj
+SelectTasksDesc=Kiaj aldonaj taskoj devos esti montrotaj?
+SelectTasksLabel2=Elektu aldonaj taskoj kiaj bezonas por ke Majstro montros dum instalado [name], kaj poste kliku Antau`en.
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=Elektu dosierujon de starta menuo
+SelectStartMenuFolderDesc=Kie Majstro devas krei tujklavon de programo?
+SelectStartMenuFolderLabel3=La Majstro kreos tujklavojn de programo en sekva dosierujo de starta menuo.
+SelectStartMenuFolderBrowseLabel=Por kontinui, kliku Antau`en. Se vi volas elekti alian dosierujon, kliku Elekto.
+MustEnterGroupName=Vi devas skribi la nomo de dosierujo.
+GroupNameTooLong=La nomo de dosierujo au` vojo estas tro longa.
+InvalidGroupName=La nomo de dosierujo estas malg`usta.
+BadGroupName=La nomoj de dosierujoj ne povas havi de sekvaj karakteroj:%n%n%1
+NoProgramGroupCheck2=Ne krei dosierujon de starta menuo
+
+; *** "Ready to Install" wizard page
+WizardReady=Preparado por Instalo
+ReadyLabel1=Nun c`io estas preparita por komenci instaladon [name] en via komputilo.
+ReadyLabel2a=Kliku Instali por kontinui instaladon, au`kliku Reen se vi volas rigardi au` s`ang`i ajnajn statojn.
+ReadyLabel2b=Kliku Instali por kontinui instaladon.
+ReadyMemoUserInfo=Informacio de uzanto:
+ReadyMemoDir=Destina loko:
+ReadyMemoType=Majstra tipo:
+ReadyMemoComponents=Elektitaj komponentoj:
+ReadyMemoGroup=La dosierujo de starta menuo:
+ReadyMemoTasks=Aldonaj taskoj:
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=Preparado por Instalo
+PreparingDesc=Majstro estas preparata por instalo [name] en via komputilo.
+PreviousInstallNotCompleted=Instalado/Forigo de antau`a programo ne estas plena. Por vi bezonas relanc`i vian komputilon por plenigi tian instaladon.%n%nPost relanc`o de via komputilo, s`altu Majstron denove por finigi instaladon de [name].
+CannotContinue=La Majstro ne povas kontinui. Bonvolu kliki Fino por eliri.
+ApplicationsFound=Sekvaj aplikaj`oj uzas dosierojn kiajn bezonas renovigi per Instalado. Estas rekomendite ke vi permesu al Majstro automate fermi tiajn aplikaj`ojn.
+ApplicationsFound2=Sekvaj aplikaj`oj uzas dosierojn kiajn bezonas renovigi per Instalado. Estas rekomendite ke vi permesu al Majstro automate fermi tiajn aplikaj`ojn. Poste de instalado Majstro provos relanc`i aplikaj`ojn.
+CloseApplications=&Automate fermi aplikaj`ojn
+DontCloseApplications=Ne fermu aplikaj`ojn
+ErrorCloseApplications=Majstro estis nepovebla au`tomate fermi c`iajn aplikaj`ojn. Estas rekomendite ke vi fermu c`iajn aplikaj`ojn, uzantaj dosierojn, kiaj estas bezonatajn por renovigo per la Majstro antau` kontinui.
+
+; *** "Installing" wizard page
+WizardInstalling=Instalado
+InstallingLabel=Bonvolu atenti dum Majstro instalas [name] en via komputilo.
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel= Fino de instalado
+FinishedLabelNoIcons=La Majstro finigis instaladon [name] en via komputilo.
+FinishedLabel=La Majstro finigis instaladon [name] en via komputilo. La aplikaj`o povos esti lanc`ita per elekto de instalaj ikonoj.
+ClickFinish= Kliku Fino por finigi instaladon.
+FinishedRestartLabel=Por plenumigi instaladon de [name], Majstro devas relanc`i vian komputilon. C`u vi volas relanc`i nun?
+FinishedRestartMessage=Por plenumigi instaladon de [name], Majstro devas relanc`i vian komputilon.%n%nC`u vi volas relanc`i nun?
+ShowReadmeCheck=Jes, mi volas rigardi dosieron README
+YesRadio=&Jes, relanc`u komputilon nun
+NoRadio=&Ne, mi volas relanc`i komputilon poste
+; used for example as 'Run MyProg.exe'
+RunEntryExec=S`altu %1
+; used for example as 'View Readme.txt'
+RunEntryShellExec=Rigardi %1
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=La Majstro postulas sekvan diskon
+SelectDiskLabel2=Bonvolu inserti Diskon %1 kaj kliku Jes.%n%nSe dosieroj en tia disko povos esti diversaj de prezentitaj malalte, enskribu korektan vojon au` kliku Elekto.
+PathLabel=&Vojo:
+FileNotInDir2=Dosieron "%1" estas nepoveble lokigi en "%2". Bonvolu inserti korectan diskon au` elektu alian dosierujon.
+SelectDirectoryLabel=Bonvolu difini lokon de alia disko.
+
+; *** Installation phase messages
+SetupAborted=Instalado ne estis plena.%n%nBonvolu korekti problemon kaj lanc`u Majstron denove.
+EntryAbortRetryIgnore=Kliku Reen por provi ankorau`, Ignori por fari c`iokaze, au` S`topi por finigi instaladon.
+
+; *** Installation status messages
+StatusClosingApplications=Fermado de aplikaj`oj...
+StatusCreateDirs=Kreado de dosierujojn...
+StatusExtractFiles=Ekstraktado de dosierojn...
+StatusCreateIcons=Kreado de tujklavojn...
+StatusCreateIniEntries=Kreado de INI dosierojn...
+StatusCreateRegistryEntries=Kreado de registraj pointoj...
+StatusRegisterFiles=Registrado de dosierojn...
+StatusSavingUninstall=Konservas informacio por forigo...
+StatusRunProgram=Finig`as instalado...
+StatusRestartingApplications=Relanc`o de aplikaj`oj...
+StatusRollback=Renovigo de s`ang`oj...
+
+; *** Misc. errors
+ErrorInternal2=Interna eraro: %1
+ErrorFunctionFailedNoCode=%1 estas kripligita
+ErrorFunctionFailed=%1 estas kripligita; kodnomo %2
+ErrorFunctionFailedWithMessage=%1 estas kripligita; kodnomo %2.%n%3
+ErrorExecutingProgram=Estas nepoveble plenumi dosieron:%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=Eraro dum malfermo de registra s`losilo:%n%1\%2
+ErrorRegCreateKey=Eraro dum kreado de registra s`losilo:%n%1\%2
+ErrorRegWriteKey=Eraro dum skribado en registra s`losilo:%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=Eraro dum kreado de INI pointo en dosiero "%1".
+
+; *** File copying errors
+FileAbortRetryIgnore=Kliku Reen por provi denove, Ignori por lasi tian dosieron (ne estas rekomendite), au` S`topi por finigi instaladon.
+FileAbortRetryIgnore2=Kliku Reen por provi denove, Ignori por plenumi c`iokaze (ne estas rekomendite), au` S`topi por finigi instaladon.
+SourceIsCorrupted=La fonta dosiero estas kripligita
+SourceDoesntExist=La fonta dosiero "%1" ne ekzistas
+ExistingFileReadOnly=Ekzista dosiero estas markita kiel nurlega.%n%nKliku Reen por forigi la nurlegan atributon kaj provu reen, Ignori por lasi tian dosieron, au` S`topi por fini instaladon.
+ErrorReadingExistingDest=Eraro aperis dum legado de ekzista dosiero:
+FileExists=La dosiero jam ekzistas.%n%nC`u vi volas ke Majstro reskribu g`in?
+ExistingFileNewer=Ekzista dosiero estas pli nova ol Majstro provas instali. Estas rekomendita ke vi konservu ekzistan dosieron.%n%nC`u vi volas konservi ekzistan dosieron?
+ErrorChangingAttr=Eraro aperis dum provo c`ang`i atributoj de ekzista dosiero:
+ErrorCreatingTemp=Eraro aperis dum kreado dosieron en destina dosierujo:
+ErrorReadingSource=Eraro aperis dum legado de dosiero:
+ErrorCopying=Eraro aperis dum kopiado de dosiero:
+ErrorReplacingExistingFile=Eraro aperis dum relokig`o de ekzistan dosieron:
+ErrorRestartReplace=Relanc`o/Relokig`o estas kripligita:
+ErrorRenamingTemp=Eraro aperis dum renomig`o del dosiero en destina dosierujo:
+ErrorRegisterServer=Estas nepoveble registri DLL/OC`: %1
+ErrorRegSvr32Failed=RegSvr32estas kripligita kun elira codo %1
+ErrorRegisterTypeLib=Estas nepoveble registri bibliotekon de tipo : %1
+
+; *** Post-installation errors
+ErrorOpeningReadme=Eraro aperis dum malfermado de README dosiero.
+ErrorRestartingComputer=Majstro ne povis relanc`i komputilo. Bonvolu fari tion permane.
+
+; *** Uninstaller messages
+UninstallNotFound=Dosiero "%1" ne ekzistas. Estas nepoveble forigi.
+UninstallOpenError=Dosieron "%1" nepoveble estas malfermi. Estas nepoveble forigi
+UninstallUnsupportedVer=\Foriga protokolo "%1" estas en nekonata formato per c`i tia versio de forigprogramo. Estas nepoveble forigi
+UninstallUnknownEntry=Ekzistas nekonata pointo (%1) en foriga protokolo
+ConfirmUninstall=C`u vi reale volas tute forigi %1 kaj c`iaj komponentoj de g`i?
+UninstallOnlyOnWin64=C`i tian instaladon povos forigi nur en 64-bit Vindoso.
+OnlyAdminCanUninstall=C`i tian instaladon povos forigi nur uzanto kun administrantaj rajtoj.
+UninstallStatusLabel=Bonvolu atendi dum %1 forig`os de via komputilo.
+UninstalledAll=%1 estis sukcese forigita de via komputilo.
+UninstalledMost=Forigo de %1 estas plena.%n%nKelkaj elementoj ne estis forigitaj. G`in poveble estas forigi permane.
+UninstalledAndNeedsRestart=Por plenumi forigadon de %1, via komputilo devas esti relanc`ita.%n%nC`u vi volas relanc`i nun?
+UninstallDataCorrupted="%1" dosiero estas kriplita. Estas nepoveble forigi
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=Forigi komune uzatan dosieron?
+ConfirmDeleteSharedFile2=La sistemo indikas ke sekva komune uzata dosiero jam ne estas uzata per neniel aplikaj`oj. C`u vi volas forigi c`i tian dosieron?%n%nSe ajna programo jam uzas tian dosieron, dum forigo g`i povos malg`uste funkcii. Se vi ne estas certa elektu Ne. Restante en via sistemo la dosiero ne damag`os g`in.
+SharedFileNameLabel=nomo de dosiero:
+SharedFileLocationLabel=Loko:
+WizardUninstalling=Stato de forigo
+StatusUninstalling=Forigado %1...
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=Instalado %1.
+ShutdownBlockReasonUninstallingApp=Forigado %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 versio %2
+AdditionalIcons=Aldonaj ikonoj:
+CreateDesktopIcon=Krei &Labortablan ikonon
+CreateQuickLaunchIcon=Krei &Rapida lanc`o ikonon
+ProgramOnTheWeb=%1 en Reto
+UninstallProgram=Rorig`ado %1
+LaunchProgram=Lanc`o %1
+AssocFileExtension=&Asociigi %1 kun %2 dosieraj finaj`oj
+AssocingFileExtension=Asociig`as %1 kun %2 dosiera finaj`o...
+AutoStartProgramGroupDescription=Lanc`o:
+AutoStartProgram=Automate s`alti %1
+AddonHostProgramNotFound=%1 nepoveble estas loki en dosierujo kian vi elektis.%n%nC`u vi volas kontinui c`iokaze?
diff --git a/installer/innosetup/Languages/Estonian.isl b/Greenshot/releases/innosetup/Languages/Estonian.isl
similarity index 100%
rename from installer/innosetup/Languages/Estonian.isl
rename to Greenshot/releases/innosetup/Languages/Estonian.isl
diff --git a/Greenshot/releases/innosetup/Languages/Farsi.isl b/Greenshot/releases/innosetup/Languages/Farsi.isl
new file mode 100644
index 000000000..232a7ce3b
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Farsi.isl
@@ -0,0 +1,337 @@
+; *** Inno Setup version 5.5.3+ Farsi messages ***
+;Translator:Hessam Mohamadi
+;Email:hessam55@hotmail.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=Farsi
+LanguageID=$0429
+LanguageCodePage=1256
+; If the language you are translating to requires special font faces or
+; sizes, uncomment any of the following entries and change them accordingly.
+DialogFontName=Tahoma
+DialogFontSize=8
+WelcomeFontName=Tahoma
+WelcomeFontSize=11
+TitleFontName=Tahoma
+TitleFontSize=28
+CopyrightFontName=Tahoma
+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= :%n%n%1
+SetupAlreadyRunning=
+WindowsVersionNotSupported= ʡ
+WindowsServicePackRequired= %1 %2
+NotOnThisPlatform= %1
+OnlyOnThisPlatform= %1
+OnlyOnTheseArchitectures= Ԑ ʡ :%n%n%1
+MissingWOW64APIs= %1 ǘ ʡ Ԙ
+WinVersionTooLowError= %1 %2
+WinVersionTooHighError= %1 %2
+AdminPrivilegesRequired=
+PowerUserPrivilegesRequired=
+SetupAppRunningError=ǘ %1 %n%n Ӂ
+UninstallAppRunningError=ǘ %1 %n%n Ӂ
+
+; *** Misc. errors
+ErrorCreatingDir= "%1"
+ErrorTooManyFilesInDir= "%1"
+
+; *** Setup common messages
+ExitSetupTitle=
+ExitSetupMessage= . ǐ ǘ ϡ %n%n . Ͽ
+AboutSetupMenuItem=... &
+AboutSetupTitle=
+AboutSetupMessage=%2 %1%n%3%n%n%1 :%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< &
+ButtonNext=& >
+ButtonInstall=&
+ButtonOK=&
+ButtonCancel=&
+ButtonYes=&
+ButtonYesToAll= &
+ButtonNo=&
+ButtonNoToAll= &
+ButtonFinish=&
+ButtonBrowse=&
+ButtonWizardBrowse=&
+ButtonNewFolder=
+
+; *** "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=:
+IncorrectPassword= .
+
+; *** "License Agreement" wizard page
+WizardLicense=
+LicenseLabel=
+LicenseLabel3= . ȁ
+LicenseAccepted= &흁
+LicenseNotAccepted= &흁
+
+; *** "Information" wizard pages
+WizardInfoBefore=
+InfoBeforeLabel=
+InfoBeforeClickLabel= ϡ
+WizardInfoAfter=
+InfoAfterLabel=
+InfoAfterClickLabel= ϡ
+
+; *** "User Information" wizard page
+WizardUserInfo=
+UserInfoDesc=
+UserInfoName= &:
+UserInfoOrg=&:
+UserInfoSerial= &:
+UserInfoNameRequired=
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=
+SelectDirDesc= Ͽ [name]
+SelectDirLabel3= [name]
+SelectDirBrowseLabel= . ʡ
+DiskSpaceMBLabel=ʝ [mb]
+CannotInstallToNetworkDrive= Ș
+CannotInstallToUNCPath=
+InvalidPath= ϡ :%n%nC:\APP%n%n :%n%n\\server\share
+InvalidDrive= ǘ ϡ .
+DiskSpaceWarningTitle=
+DiskSpaceWarning= %1 ʡ %2 .%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
+ComponentSize2=%1
+ComponentsDiskSpaceMBLabel= ʝ [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=
+
+; *** "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=& Ϙ
+DontCloseApplications=&
+ErrorCloseApplications= Ϙ .
+
+; *** "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=
+NoRadio=ѡ
+; 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=&:
+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
+
+; *** 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= / : %1
+ErrorRegSvr32Failed=%1
+ErrorRegisterTypeLib= : %1
+
+; *** Post-installation errors
+ErrorOpeningReadme=
+ErrorRestartingComputer= .
+
+; *** Uninstaller messages
+UninstallNotFound= . "%1"
+UninstallOpenError= . "%1"
+UninstallUnsupportedVer= . "%1"
+UninstallUnknownEntry= (%1)
+ConfirmUninstall= Ͽ %1
+UninstallOnlyOnWin64= ҝ 64
+OnlyAdminCanUninstall=
+UninstallStatusLabel= %1
+UninstalledAll= %1
+UninstalledMost= %1 %n%n ϡ
+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= Әǁ
+CreateQuickLaunchIcon=
+ProgramOnTheWeb=%1
+UninstallProgram=%1
+LaunchProgram=%1
+AssocFileExtension= %1 %2 &
+AssocingFileExtension= %1 %2
+AutoStartProgramGroupDescription= :
+AutoStartProgram=%1 Ϙ
+AddonHostProgramNotFound=%1 .%n%n Ͽ
diff --git a/installer/innosetup/Languages/Galician.isl b/Greenshot/releases/innosetup/Languages/Galician.isl
similarity index 91%
rename from installer/innosetup/Languages/Galician.isl
rename to Greenshot/releases/innosetup/Languages/Galician.isl
index 5d7bfeb99..fab5215e4 100644
--- a/installer/innosetup/Languages/Galician.isl
+++ b/Greenshot/releases/innosetup/Languages/Galician.isl
@@ -1,10 +1,7 @@
-; *** Inno Setup version 6.1.0+ Galician messages ***
+; *** Inno Setup version 6.0.3+ Galician messages ***
;
; Maintained by: Julio Mojon Fuentes
; (juliomf AT edu.xunta.gal)
-;
-; To download user-contributed translations of this file, go to:
-; https://jrsoftware.org/files/istrans/
[LangOptions]
LanguageName=Galego
@@ -194,18 +191,6 @@ ReadyMemoComponents=Compoñentes seleccionados:
ReadyMemoGroup=Cartafol do Menú Inicio:
ReadyMemoTasks=Tarefas adicionais:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=A descargar arquivos adicionais...
-ButtonStopDownload=&Deter descarga
-StopDownload=Está seguro de que desexa deter a descarga?
-ErrorDownloadAborted=Descarga cancelada
-ErrorDownloadFailed=A descarga fallou: %1 %2
-ErrorDownloadSizeFailed=Non se puido determinar o tamaño: %1 %2
-ErrorFileHash1=Non se puido calcular o hash do arquivo: %1
-ErrorFileHash2=Hash do arquivo inválido: esperado %1, atopado %2
-ErrorProgress=Progreso inválido: %1 de %2
-ErrorFileSize=Tamaño de arquivo inválido: esperado %1, atopado %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=A prepararse para instalar
PreparingDesc=O asistente de instalación está a prepararse para instalar [name] no seu computador.
@@ -286,16 +271,8 @@ ExistingFileReadOnly2=Non foi posible substituír o arquivo existente porque est
ExistingFileReadOnlyRetry=&Eliminar o atributo de só lectura e tentar de novo
ExistingFileReadOnlyKeepExisting=&Manter o arquivo existente
ErrorReadingExistingDest=Ocorreu un erro ao tentar ler o arquivo existente:
-FileExistsSelectAction=Seleccionar acción
-FileExists2=O arquivo xa existe.
-FileExistsOverwriteExisting=&Sobrescribir o arquivo existente
-FileExistsKeepExisting=&Manter o arquivo existente
-FileExistsOverwriteOrKeepAll=&Facer isto para os seguintes conflitos
-ExistingFileNewerSelectAction=Seleccionar acción
-ExistingFileNewer2=O arquivo existente é máis novo ca o que o asistente de instalación tenta instalar.
-ExistingFileNewerOverwriteExisting=&Sobrescribir o arquivo existente
-ExistingFileNewerKeepExisting=&Manter o arquivo existente (recomendado)
-ExistingFileNewerOverwriteOrKeepAll=&Facer isto para os seguintes conflitos
+FileExists=O arquivo xa existe.%n%nDesexa que o asistente de instalación o sobrescriba?
+ExistingFileNewer=O arquivo existente é máis novo ca o que o asistente de instalación tenta instalar. Recoméndaselle que manteña o arquivo existente.%n%nDesexa manter o arquivo existente?
ErrorChangingAttr=Ocorreu un erro ao tentar mudar os atributos do arquivo existente:
ErrorCreatingTemp=Ocorreu un erro ao tentar crear un arquivo no cartafol de destino:
ErrorReadingSource=Ocorreu un erro ao tentar ler o arquivo orixe:
diff --git a/installer/innosetup/Languages/Georgian.islu b/Greenshot/releases/innosetup/Languages/Georgian.islu
similarity index 100%
rename from installer/innosetup/Languages/Georgian.islu
rename to Greenshot/releases/innosetup/Languages/Georgian.islu
diff --git a/installer/innosetup/Languages/Greek.isl b/Greenshot/releases/innosetup/Languages/Greek.isl
similarity index 90%
rename from installer/innosetup/Languages/Greek.isl
rename to Greenshot/releases/innosetup/Languages/Greek.isl
index 8e603194f..eef0cc8dd 100644
--- a/installer/innosetup/Languages/Greek.isl
+++ b/Greenshot/releases/innosetup/Languages/Greek.isl
@@ -1,7 +1,7 @@
-; *** Inno Setup version 6.1.0+ Greek messages ***
+; *** Inno Setup version 6.0.0+ Greek messages ***
;
; To download user-contributed translations of this file, go to:
-; https://jrsoftware.org/files/istrans/
+; 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
@@ -10,7 +10,7 @@
;
; Originally translated by Anastasis Chatzioglou, baldycom@hotmail.com
; Updated by XhmikosR [XhmikosR, my_nickname at yahoo dot com]
-; Updated to version 6.1.0+ by Vasileios Karamichail, v.karamichail@outlook.com
+; Updated to version 6.0.0+ by V. Karamichail, v.karamichail@outlook.com
;
[LangOptions]
@@ -156,7 +156,6 @@ WizardSelectDir=Επιλογή Φακέλου Εγκατάστασης
SelectDirDesc=Πού θέλετε να εγκατασταθεί το [name];
SelectDirLabel3=Ο Οδηγός Εγκατάστασης θα εγκαταστήσει το [name] στον ακόλουθο φάκελο.
SelectDirBrowseLabel=Για να συνεχίσετε, πατήστε Επόμενο. Εάν θέλετε να επιλέξετε διαφορετικό φάκελο, πατήστε Αναζήτηση.
-DiskSpaceGBLabel=Απαιτούνται τουλάχιστον [gb] GB ελεύθερου χώρου στο δίσκο.
DiskSpaceMBLabel=Απαιτούνται τουλάχιστον [mb] MB ελεύθερου χώρου στο δίσκο.
CannotInstallToNetworkDrive=Η εγκατάσταση δεν μπορεί να γίνει σε δίσκο δικτύου.
CannotInstallToUNCPath=Η εγκατάσταση δεν μπορεί να γίνει σε διαδρομή UNC.
@@ -184,7 +183,6 @@ NoUninstallWarningTitle=Οι Λειτουργικές Μονάδες Υπάρχ
NoUninstallWarning=Ο Οδηγός Εγκατάστασης εντόπισε ότι τα ακόλουθα στοιχεία είναι ήδη εγκατεστημένα στον υπολογιστή σας:%n%n%1%n%nΑποεπιλέγοντας αυτά τα στοιχεία δεν θα απεγκατασταθούν.%n%nΘέλετε να συνεχίσετε παρόλα αυτά;
ComponentSize1=%1 KB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=Η τρέχουσα επιλογή απαιτεί τουλάχιστον [gb] GB χώρου στο δίσκο.
ComponentsDiskSpaceMBLabel=Η τρέχουσα επιλογή απαιτεί τουλάχιστον [mb] MB χώρου στο δίσκο.
; *** "Select Additional Tasks" wizard page
@@ -215,18 +213,6 @@ ReadyMemoComponents=Επιλεγμένες λειτουργικές μονάδε
ReadyMemoGroup=Φάκελος στο μενού Έναρξη:
ReadyMemoTasks=Επιπλέον ενέργειες:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=Λήψη πρόσθετων αρχείων...
-ButtonStopDownload=&Διακοπή λήψης
-StopDownload=Είστε βέβαιοι ότι θέλετε να διακόψετε τη λήψη;
-ErrorDownloadAborted=Η λήψη ακυρώθηκε
-ErrorDownloadFailed=Η λήψη απέτυχε: %1 %2
-ErrorDownloadSizeFailed=Η λήψη του μεγέθους απέτυχε: %1 %2
-ErrorFileHash1=Αποτυχία υπολογισμού hash: %1
-ErrorFileHash2=Μη έγκυρο hash: αναμενόμενο %1, βρέθηκε %2
-ErrorProgress=Μη έγκυρη πρόοδος: %1 από %2
-ErrorFileSize=Μη έγκυρο μέγεθος αρχείου: αναμενόμενο %1, βρέθηκε %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=Προετοιμασία Εγκατάστασης
PreparingDesc=Ο Οδηγός Εγκατάστασης προετοιμάζεται για την εγκατάσταση του [name] στον υπολογιστή σας.
@@ -236,8 +222,7 @@ ApplicationsFound=Οι ακόλουθες εφαρμογές χρησιμοπο
ApplicationsFound2=Οι ακόλουθες εφαρμογές χρησιμοποιούν αρχεία που πρέπει να ενημερωθούν από τον Οδηγό Εγκατάστασης. Συνιστάται να επιτρέψετε στον Οδηγό Εγκατάστασης να κλείσει αυτόματα αυτές τις εφαρμογές. Μετά την ολοκλήρωση της εγκατάστασης, ο Οδηγός Εγκατάστασης θα επιχειρήσει να κάνει επανεκκίνηση των εφαρμογών.
CloseApplications=&Αυτόματο κλείσιμο των εφαρμογών
DontCloseApplications=&Χωρίς κλείσιμο των εφαρμογών
-ErrorCloseApplications=Ο Οδηγός Εγκατάστασης δεν μπόρεσε να κλείσει αυτόματα όλες τις εφαρμογές. Συνιστάται να κλείσετε όλες τις εφαρμογές που χρησιμοποιούν αρχεία που πρέπει να ενημερωθούν από τον Οδηγό Εγκατάστασης προτού συνεχίσετε.
-PrepareToInstallNeedsRestart=Ο Οδηγός Εγκατάστασης πρέπει να κάνει επανεκκίνηση του υπολογιστή σας. Μετά την επανεκκίνηση του υπολογιστή σας, εκτελέστε ξανά τον Οδηγό Εγκατάστασης για να ολοκληρώσετε την εγκατάσταση του [name].%n%nΘα θέλατε να κάνετε επανεκκίνηση τώρα;
+ErrorCloseApplications=Η εγκατάσταση δεν μπόρεσε να κλείσει αυτόματα όλες τις εφαρμογές. Συνιστάται να κλείσετε όλες τις εφαρμογές που χρησιμοποιούν αρχεία που πρέπει να ενημερωθούν από τον Οδηγό Εγκατάστασης προτού συνεχίσετε.
; *** "Installing" wizard page
WizardInstalling=Εγκατάσταση
@@ -309,16 +294,8 @@ ExistingFileReadOnly2=Το υπάρχον αρχείο δεν μπόρεσε ν
ExistingFileReadOnlyRetry=&Καταργήστε το χαρακτηριστικό μόνο για ανάγνωση και δοκιμάστε ξανά
ExistingFileReadOnlyKeepExisting=&Διατηρήστε το υπάρχον αρχείο
ErrorReadingExistingDest=Παρουσιάστηκε σφάλμα κατά την προσπάθεια ανάγνωσης του υπάρχοντος αρχείου:
-FileExistsSelectAction=Επιλέξτε ενέργεια
-FileExists2=Το αρχείο υπάρχει ήδη.
-FileExistsOverwriteExisting=&Αντικατάσταση υπάρχοντος αρχείου
-FileExistsKeepExisting=&Διατήρηση υπάρχοντος αρχείου
-FileExistsOverwriteOrKeepAll=&Να γίνει το ίδιο για τις επόμενες διενέξεις
-ExistingFileNewerSelectAction=Επιλέξτε ενέργεια
-ExistingFileNewer2=Το υπάρχον αρχείο είναι νεότερο από αυτό που προσπαθεί να εγκαταστήσει ο Οδηγός Εγκατάστασης.
-ExistingFileNewerOverwriteExisting=&Αντικατάσταση υπάρχοντος αρχείου
-ExistingFileNewerKeepExisting=&Διατήρηση υπάρχοντος αρχείου (συνιστάται)
-ExistingFileNewerOverwriteOrKeepAll=&Να γίνει το ίδιο για τις επόμενες διενέξεις
+FileExists=Το αρχείο υπάρχει ήδη.%n%nΘα θέλατε ο Οδηγός Εγκατάστασης να το αντικαταστήσει;
+ExistingFileNewer=Το υπάρχον αρχείο είναι νεότερο από αυτό που ο Οδηγός Εγκατάστασης που προσπαθεί να εγκαταστήσει. Συνιστάται να διατηρείτε το υπάρχον αρχείο.%n%nΘέλετε να διατηρήσετε το υπάρχον αρχείο;
ErrorChangingAttr=Παρουσιάστηκε σφάλμα κατά την προσπάθεια αλλαγής των χαρακτηριστικών του υπάρχοντος αρχείου:
ErrorCreatingTemp=Παρουσιάστηκε σφάλμα κατά την προσπάθεια δημιουργίας ενός αρχείου στον φακέλο προορισμού:
ErrorReadingSource=Παρουσιάστηκε σφάλμα κατά την προσπάθεια ανάγνωσης του αρχείου προέλευσης:
@@ -387,4 +364,3 @@ AssocingFileExtension=Γίνεται συσχέτιση του %1 με την ε
AutoStartProgramGroupDescription=Εκκίνηση:
AutoStartProgram=Αυτόματη εκκίνηση του %1
AddonHostProgramNotFound=Το %1 δε βρέθηκε στο φάκελο που επιλέξατε.%n%nΘέλετε να συνεχίσετε παρόλα αυτά;
-
diff --git a/installer/innosetup/Languages/Hindi.islu b/Greenshot/releases/innosetup/Languages/Hindi.islu
similarity index 100%
rename from installer/innosetup/Languages/Hindi.islu
rename to Greenshot/releases/innosetup/Languages/Hindi.islu
diff --git a/Greenshot/releases/innosetup/Languages/Hungarian.isl b/Greenshot/releases/innosetup/Languages/Hungarian.isl
new file mode 100644
index 000000000..7fdee0b99
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Hungarian.isl
@@ -0,0 +1,366 @@
+;Inno Setup version 6.0.3+ Hungarian messages
+;Based on the translation of Kornl Pl, kornelpal@gmail.com
+;Istvn Szab, E-mail: istvanszabo890629@gmail.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=Magyar
+LanguageID=$040E
+LanguageCodePage=1250
+; 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 CE
+;TitleFontSize=29
+;CopyrightFontName=Arial CE
+;CopyrightFontSize=8
+
+[Messages]
+
+; *** Application titles
+SetupAppTitle=Telept
+SetupWindowTitle=%1 - Telept
+UninstallAppTitle=Eltvolt
+UninstallAppFullTitle=%1 Eltvolt
+
+; *** Misc. common
+InformationTitle=Informcik
+ConfirmTitle=Megerst
+ErrorTitle=Hiba
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=%1 teleptve lesz. Szeretn folytatni?
+LdrCannotCreateTemp=tmeneti fjl ltrehozsa nem lehetsges. A telepts megszaktva
+LdrCannotExecTemp=Fjl futattsa nem lehetsges az tmeneti knyvtrban. A telepts megszaktva
+HelpTextNote=
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%nHiba %2: %3
+SetupFileMissing=A(z) %1 fjl hinyzik a telept knyvtrbl. Krem hrtsa el a problmt, vagy szerezzen be egy msik pldnyt a programbl!
+SetupFileCorrupt=A teleptsi fjlok srltek. Krem, szerezzen be j msolatot a programbl!
+SetupFileCorruptOrWrongVer=A teleptsi fjlok srltek, vagy inkompatibilisek a telept ezen verzijval. Hrtsa el a problmt, vagy szerezzen be egy msik pldnyt a programbl!
+InvalidParameter=A parancssorba tadott paramter rvnytelen:%n%n%1
+SetupAlreadyRunning=A Telept mr fut.
+WindowsVersionNotSupported=A program nem tmogatja a Windows ezen verzijt.
+WindowsServicePackRequired=A program futtatshoz %1 Service Pack %2 vagy jabb szksges.
+NotOnThisPlatform=Ez a program nem futtathat %1 alatt.
+OnlyOnThisPlatform=Ezt a programot %1 alatt kell futtatni.
+OnlyOnTheseArchitectures=A program kizrlag a kvetkez processzor architektrkhoz tervezett Windows-on telepthet:%n%n%1
+WinVersionTooLowError=A program futtatshoz %1 %2 verzija vagy ksbbi szksges.
+WinVersionTooHighError=Ez a program nem telepthet %1 %2 vagy ksbbire.
+AdminPrivilegesRequired=Csak rendszergazdai mdban telepthet ez a program.
+PowerUserPrivilegesRequired=Csak rendszergazdaknt vagy kiemelt felhasznlknt telepthet ez a program.
+SetupAppRunningError=A telept gy szlelte %1 jelenleg fut.%n%nZrja be az sszes pldnyt, majd kattintson az 'OK'-ra a folytatshoz, vagy a 'Mgse'-re a kilpshez.
+UninstallAppRunningError=Az eltvolt gy szlelte %1 jelenleg fut.%n%nZrja be az sszes pldnyt, majd kattintson az 'OK'-ra a folytatshoz, vagy a 'Mgse'-re a kilpshez.
+
+; *** Startup questions
+PrivilegesRequiredOverrideTitle=Teleptsi md kivlasztsa
+PrivilegesRequiredOverrideInstruction=Vlasszon teleptsi mdot
+PrivilegesRequiredOverrideText1=%1 telepthet az sszes felhasznlnak (rendszergazdai jogok szksgesek), vagy csak magnak.
+PrivilegesRequiredOverrideText2=%1 csak magnak telepthet, vagy az sszes felhasznlnak (rendszergazdai jogok szksgesek).
+PrivilegesRequiredOverrideAllUsers=Telepts &mindenkinek
+PrivilegesRequiredOverrideAllUsersRecommended=Telepts &mindenkinek (ajnlott)
+PrivilegesRequiredOverrideCurrentUser=Telepts csak &nekem
+PrivilegesRequiredOverrideCurrentUserRecommended=Telepts csak &nekem (ajnlott)
+
+; *** Misc. errors
+ErrorCreatingDir=A Telept nem tudta ltrehozni a(z) "%1" knyvtrat
+ErrorTooManyFilesInDir=Nem hozhat ltre fjl a(z) "%1" knyvtrban, mert az mr tl sok fjlt tartalmaz
+
+; *** Setup common messages
+ExitSetupTitle=Kilps a teleptbl
+ExitSetupMessage=A telepts mg folyamatban van. Ha most kilp, a program nem kerl teleptsre.%n%nMsik alkalommal is futtathat a telepts befejezshez%n%nKilp a teleptbl?
+AboutSetupMenuItem=&Nvjegy...
+AboutSetupTitle=Telept nvjegye
+AboutSetupMessage=%1 %2 verzi%n%3%n%nAz %1 honlapja:%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< &Vissza
+ButtonNext=&Tovbb >
+ButtonInstall=&Telept
+ButtonOK=OK
+ButtonCancel=Mgse
+ButtonYes=&Igen
+ButtonYesToAll=&Mindet
+ButtonNo=&Nem
+ButtonNoToAll=&Egyiket se
+ButtonFinish=&Befejezs
+ButtonBrowse=&Tallzs...
+ButtonWizardBrowse=T&allzs...
+ButtonNewFolder=j &knyvtr
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=Telept nyelvi bellts
+SelectLanguageLabel=Vlassza ki a telepts alatt hasznlt nyelvet.
+
+; *** Common wizard text
+ClickNext=A folytatshoz kattintson a 'Tovbb'-ra, a kilpshez a 'Mgse'-re.
+BeveledLabel=
+BrowseDialogTitle=Vlasszon knyvtrt
+BrowseDialogLabel=Vlasszon egy knyvtrat az albbi listbl, majd kattintson az 'OK'-ra.
+NewFolderName=j knyvtr
+
+; *** "Welcome" wizard page
+WelcomeLabel1=dvzli a(z) [name] Teleptvarzslja.
+WelcomeLabel2=A(z) [name/ver] teleptsre kerl a szmtgpn.%n%nAjnlott minden, egyb fut alkalmazs bezrsa a folytats eltt.
+
+; *** "Password" wizard page
+WizardPassword=Jelsz
+PasswordLabel1=Ez a telepts jelszval vdett.
+PasswordLabel3=Krem adja meg a jelszt, majd kattintson a 'Tovbb'-ra. A jelszavak kis- s nagy bet rzkenyek lehetnek.
+PasswordEditLabel=&Jelsz:
+IncorrectPassword=Az n ltal megadott jelsz helytelen. Prblja jra.
+
+; *** "License Agreement" wizard page
+WizardLicense=Licencszerzds
+LicenseLabel=Olvassa el figyelmesen az informcikat folytats eltt.
+LicenseLabel3=Krem, olvassa el az albbi licencszerzdst. A telepts folytatshoz, el kell fogadnia a szerzdst.
+LicenseAccepted=&Elfogadom a szerzdst
+LicenseNotAccepted=&Nem fogadom el a szerzdst
+
+; *** "Information" wizard pages
+WizardInfoBefore=Informcik
+InfoBeforeLabel=Olvassa el a kvetkez fontos informcikat a folytats eltt.
+InfoBeforeClickLabel=Ha kszen ll, kattintson a 'Tovbb'-ra.
+WizardInfoAfter=Informcik
+InfoAfterLabel=Olvassa el a kvetkez fontos informcikat a folytats eltt.
+InfoAfterClickLabel=Ha kszen ll, kattintson a 'Tovbb'-ra.
+
+; *** "User Information" wizard page
+WizardUserInfo=Felhasznl adatai
+UserInfoDesc=Krem, adja meg az adatait
+UserInfoName=&Felhasznlnv:
+UserInfoOrg=&Szervezet:
+UserInfoSerial=&Sorozatszm:
+UserInfoNameRequired=Meg kell adnia egy nevet.
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=Vlasszon clknyvtrat
+SelectDirDesc=Hova telepljn a(z) [name]?
+SelectDirLabel3=A(z) [name] az albbi knyvtrba lesz teleptve.
+SelectDirBrowseLabel=A folytatshoz, kattintson a 'Tovbb'-ra. Ha msik knyvtrat vlasztana, kattintson a 'Tallzs'-ra.
+DiskSpaceGBLabel=At least [gb] GB szabad terletre van szksg.
+DiskSpaceMBLabel=Legalbb [mb] MB szabad terletre van szksg.
+CannotInstallToNetworkDrive=A Telept nem tud hlzati meghajtra telepteni.
+CannotInstallToUNCPath=A Telept nem tud hlzati UNC elrsi tra telepteni.
+InvalidPath=Teljes tvonalat adjon meg, a meghajt betjelvel; pldul:%n%nC:\Alkalmazs%n%nvagy egy hlzati tvonalat a kvetkez alakban:%n%n\\kiszolgl\megoszts
+InvalidDrive=A kivlasztott meghajt vagy hlzati megoszts nem ltezik vagy nem elrhet. Vlasszon egy msikat.
+DiskSpaceWarningTitle=Nincs elg szabad terlet
+DiskSpaceWarning=A Teleptnek legalbb %1 KB szabad lemezterletre van szksge, viszont a kivlasztott meghajtn csupn %2 KB ll rendelkezsre.%n%nMindenkppen folytatja?
+DirNameTooLong=A knyvtr neve vagy az tvonal tl hossz.
+InvalidDirName=A knyvtr neve rvnytelen.
+BadDirName32=A knyvtrak nevei ezen karakterek egyikt sem tartalmazhatjk:%n%n%1
+DirExistsTitle=A knyvtr mr ltezik
+DirExists=A knyvtr:%n%n%1%n%nmr ltezik. Mindenkpp ide akar telepteni?
+DirDoesntExistTitle=A knyvtr nem ltezik
+DirDoesntExist=A knyvtr:%n%n%1%n%nnem ltezik. Szeretn ltrehozni?
+
+; *** "Select Components" wizard page
+WizardSelectComponents=sszetevk kivlasztsa
+SelectComponentsDesc=Mely sszetevk kerljenek teleptsre?
+SelectComponentsLabel2=Jellje ki a teleptend sszetevket; trlje a telepteni nem kvnt sszetevket. Kattintson a 'Tovbb'-ra, ha kszen ll a folytatsra.
+FullInstallation=Teljes telepts
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=Szoksos telepts
+CustomInstallation=Egyni telepts
+NoUninstallWarningTitle=Ltez sszetev
+NoUninstallWarning=A telept gy tallta, hogy a kvetkez sszetevk mr teleptve vannak a szmtgpre:%n%n%1%n%nEzen sszetevk kijellsnek trlse, nem tvoltja el azokat a szmtgprl.%n%nMindenkppen folytatja?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=A jelenlegi kijells legalbb [gb] GB lemezterletet ignyel.
+ComponentsDiskSpaceMBLabel=A jelenlegi kijells legalbb [mb] MB lemezterletet ignyel.
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=Tovbbi feladatok
+SelectTasksDesc=Mely kiegszt feladatok kerljenek vgrehajtsra?
+SelectTasksLabel2=Jellje ki, mely kiegszt feladatokat hajtsa vgre a Telept a(z) [name] teleptse sorn, majd kattintson a 'Tovbb'-ra.
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=Start Men knyvtra
+SelectStartMenuFolderDesc=Hova helyezze a Telept a program parancsikonjait?
+SelectStartMenuFolderLabel3=A Telept a program parancsikonjait a Start men kvetkez mappjban fogja ltrehozni.
+SelectStartMenuFolderBrowseLabel=A folytatshoz kattintson a 'Tovbb'-ra. Ha msik mappt vlasztana, kattintson a 'Tallzs'-ra.
+MustEnterGroupName=Meg kell adnia egy mappanevet.
+GroupNameTooLong=A knyvtr neve vagy az tvonal tl hossz.
+InvalidGroupName=A knyvtr neve rvnytelen.
+BadGroupName=A knyvtrak nevei ezen karakterek egyikt sem tartalmazhatjk:%n%n%1
+NoProgramGroupCheck2=&Ne hozzon ltre mappt a Start menben
+
+; *** "Ready to Install" wizard page
+WizardReady=Kszen llunk a teleptsre
+ReadyLabel1=A Telept kszen ll, a(z) [name] szmtgpre teleptshez.
+ReadyLabel2a=Kattintson a 'Telepts'-re a folytatshoz, vagy a "Vissza"-ra a belltsok ttekintshez vagy megvltoztatshoz.
+ReadyLabel2b=Kattintson a 'Telepts'-re a folytatshoz.
+ReadyMemoUserInfo=Felhasznl adatai:
+ReadyMemoDir=Telepts clknyvtra:
+ReadyMemoType=Telepts tpusa:
+ReadyMemoComponents=Vlasztott sszetevk:
+ReadyMemoGroup=Start men mappja:
+ReadyMemoTasks=Kiegszt feladatok:
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=Felkszls a teleptsre
+PreparingDesc=A Telept felkszl a(z) [name] szmtgpre trtn teleptshez.
+PreviousInstallNotCompleted=gy korbbi program teleptse/eltvoltsa nem fejezdtt be. jra kell indtania a szmtgpt a msik telepts befejezshez.%n%nA szmtgpe jraindtsa utn ismt futtassa a Teleptt a(z) [name] teleptsnek befejezshez.
+CannotContinue=A telepts nem folytathat. A kilpshez kattintson a 'Mgse'-re
+ApplicationsFound=A kvetkez alkalmazsok olyan fjlokat hasznlnak, amelyeket a Teleptnek frissteni kell. Ajnlott, hogy engedlyezze a Teleptnek ezen alkalmazsok automatikus bezrst.
+ApplicationsFound2=A kvetkez alkalmazsok olyan fjlokat hasznlnak, amelyeket a Teleptnek frissteni kell. Ajnlott, hogy engedlyezze a Teleptnek ezen alkalmazsok automatikus bezrst. A telepts befejezse utn a Telept megksrli az alkalmazsok jraindtst.
+CloseApplications=&Alkalmazsok automatikus bezrsa
+DontCloseApplications=&Ne zrja be az alkalmazsokat
+ErrorCloseApplications=A Telept nem tudott minden alkalmazst automatikusan bezrni. A folytats eltt ajnlott minden, a Telept ltal frisstend fjlokat hasznl alkalmazst bezrni.
+PrepareToInstallNeedsRestart=A teleptnek jra kell indtania a szmtgpet. jaindtst kveten, futassa jbl a teleptt, a [name] teleptsnek befejezshez .%n%njra szeretn indtani most a szmtgpet?
+
+; *** "Installing" wizard page
+WizardInstalling=Telepts
+InstallingLabel=Krem vrjon, amg a(z) [name] teleptse zajlik.
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel=A(z) [name] teleptsnek befejezse
+FinishedLabelNoIcons=A Telept vgzett a(z) [name] teleptsvel.
+FinishedLabel=A Telept vgzett a(z) [name] teleptsvel. Az alkalmazst a ltrehozott ikonok kivlasztsval indthatja.
+ClickFinish=Kattintson a 'Befejezs'-re a kilpshez.
+FinishedRestartLabel=A(z) [name] teleptsnek befejezshez jra kell indtani a szmtgpet. jraindtja most?
+FinishedRestartMessage=A(z) [name] teleptsnek befejezshez, a Teleptnek jra kell indtani a szmtgpet.%n%njraindtja most?
+ShowReadmeCheck=Igen, szeretnm elolvasni a FONTOS fjlt
+YesRadio=&Igen, jraindts most
+NoRadio=&Nem, ksbb indtom jra
+; used for example as 'Run MyProg.exe'
+RunEntryExec=%1 futtatsa
+; used for example as 'View Readme.txt'
+RunEntryShellExec=%1 megtekintse
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=A Teleptnek szksge van a kvetkez lemezre
+SelectDiskLabel2=Helyezze be a(z) %1. lemezt s kattintson az 'OK'-ra.%n%nHa a fjlok a lemez egy a megjelentettl klnbz mappjban tallhatk, rja be a helyes tvonalat vagy kattintson a 'Tallzs'-ra.
+PathLabel=&tvonal:
+FileNotInDir2=A(z) "%1" fjl nem tallhat a kvetkez helyen: "%2". Helyezze be a megfelel lemezt vagy vlasszon egy msik mappt.
+SelectDirectoryLabel=Adja meg a kvetkez lemez helyt.
+
+; *** Installation phase messages
+SetupAborted=A telepts nem fejezdtt be.%n%nHrtsa el a hibt s futtassa jbl a Teleptt.
+AbortRetryIgnoreSelectAction=Vlasszon mveletet
+AbortRetryIgnoreRetry=&jra
+AbortRetryIgnoreIgnore=&Hiba elvetse s folytats
+AbortRetryIgnoreCancel=Telepts megszaktsa
+
+; *** Installation status messages
+StatusClosingApplications=Alkalmazsok bezrsa...
+StatusCreateDirs=Knyvtrak ltrehozsa...
+StatusExtractFiles=Fjlok kibontsa...
+StatusCreateIcons=Parancsikonok ltrehozsa...
+StatusCreateIniEntries=INI bejegyzsek ltrehozsa...
+StatusCreateRegistryEntries=Rendszerler bejegyzsek ltrehozsa...
+StatusRegisterFiles=Fjlok regisztrlsa...
+StatusSavingUninstall=Eltvolt informcik mentse...
+StatusRunProgram=Telepts befejezse...
+StatusRestartingApplications=Alkalmazsok jraindtsa...
+StatusRollback=Vltoztatsok visszavonsa...
+
+; *** Misc. errors
+ErrorInternal2=Bels hiba: %1
+ErrorFunctionFailedNoCode=Sikertelen %1
+ErrorFunctionFailed=Sikertelen %1; kd: %2
+ErrorFunctionFailedWithMessage=Sikertelen %1; kd: %2.%n%3
+ErrorExecutingProgram=Nem hajthat vgre a fjl:%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=Nem nyithat meg a rendszerler kulcs:%n%1\%2
+ErrorRegCreateKey=Nem hozhat ltre a rendszerler kulcs:%n%1\%2
+ErrorRegWriteKey=Nem mdosthat a rendszerler kulcs:%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=Bejegyzs ltrehozsa sikertelen a kvetkez INI fjlban: "%1".
+
+; *** File copying errors
+FileAbortRetryIgnoreSkipNotRecommended=&Fjl kihagysa (nem ajnlott)
+FileAbortRetryIgnoreIgnoreNotRecommended=&Hiba elvetse s folytats (nem ajnlott)
+SourceIsCorrupted=A forrsfjl megsrlt
+SourceDoesntExist=A(z) "%1" forrsfjl nem ltezik
+ExistingFileReadOnly2=A fjl csak olvashatknt van jellve.
+ExistingFileReadOnlyRetry=Csak &olvashat tulajdonsg eltvoltsa s jra prblkozs
+ExistingFileReadOnlyKeepExisting=&Ltez fjl megtartsa
+ErrorReadingExistingDest=Hiba lpett fel a fjl olvassa kzben:
+FileExists=A fjl mr ltezik.%n%nFell kvnja rni?
+ExistingFileNewer=A ltez fjl jabb a teleptsre kerlnl. Ajnlott a ltez fjl megtartsa.%n%nMeg kvnja tartani a ltez fjlt?
+ErrorChangingAttr=Hiba lpett fel a fjl attribtumnak mdostsa kzben:
+ErrorCreatingTemp=Hiba lpett fel a fjl teleptsi knyvtrban trtn ltrehozsa kzben:
+ErrorReadingSource=Hiba lpett fel a forrsfjl olvassa kzben:
+ErrorCopying=Hiba lpett fel a fjl msolsa kzben:
+ErrorReplacingExistingFile=Hiba lpett fel a ltez fjl cserje kzben:
+ErrorRestartReplace=A fjl cserje az jraindts utn sikertelen volt:
+ErrorRenamingTemp=Hiba lpett fel fjl teleptsi knyvtrban trtn tnevezse kzben:
+ErrorRegisterServer=Nem lehet regisztrlni a DLL-t/OCX-et: %1
+ErrorRegSvr32Failed=Sikertelen RegSvr32. A visszaadott kd: %1
+ErrorRegisterTypeLib=Nem lehet regisztrlni a tpustrat: %1
+
+; *** Uninstall display name markings
+; used for example as 'My Program (32-bit)'
+UninstallDisplayNameMark=%1 (%2)
+; used for example as 'My Program (32-bit, All users)'
+UninstallDisplayNameMarks=%1 (%2, %3)
+UninstallDisplayNameMark32Bit=32-bit
+UninstallDisplayNameMark64Bit=64-bit
+UninstallDisplayNameMarkAllUsers=Minden felhasznl
+UninstallDisplayNameMarkCurrentUser=Jelenlegi felhasznl
+
+; *** Post-installation errors
+ErrorOpeningReadme=Hiba lpett fel a FONTOS fjl megnyitsa kzben.
+ErrorRestartingComputer=A Telept nem tudta jraindtani a szmtgpet. Indtsa jra kzileg.
+
+; *** Uninstaller messages
+UninstallNotFound=A(z) "%1" fjl nem ltezik. Nem tvolthat el.
+UninstallOpenError=A(z) "%1" fjl nem nyithat meg. Nem tvolthat el
+UninstallUnsupportedVer=A(z) "%1" eltvoltsi naplfjl formtumt nem tudja felismerni az eltvolt jelen verzija. Az eltvolts nem folytathat
+UninstallUnknownEntry=Egy ismeretlen bejegyzs (%1) tallhat az eltvoltsi naplfjlban
+ConfirmUninstall=Biztosan el kvnja tvoltani a(z) %1 programot s minden sszetevjt?
+UninstallOnlyOnWin64=Ezt a teleptst csak 64-bites Windowson lehet eltvoltani.
+OnlyAdminCanUninstall=Ezt a teleptst csak adminisztrcis jogokkal rendelkez felhasznl tvolthatja el.
+UninstallStatusLabel=Legyen trelemmel, amg a(z) %1 szmtgprl trtn eltvoltsa befejezdik.
+UninstalledAll=A(z) %1 sikeresen el lett tvoltva a szmtgprl.
+UninstalledMost=A(z) %1 eltvoltsa befejezdtt.%n%nNhny elemet nem lehetetett eltvoltani. Trlje kzileg.
+UninstalledAndNeedsRestart=A(z) %1 eltvoltsnak befejezshez jra kell indtania a szmtgpt.%n%njraindtja most?
+UninstallDataCorrupted=A(z) "%1" fjl srlt. Nem tvolthat el.
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=Trli a megosztott fjlt?
+ConfirmDeleteSharedFile2=A rendszer azt jelzi, hogy a kvetkez megosztott fjlra mr nincs szksge egyetlen programnak sem. Eltvoltja a megosztott fjlt?%n%nHa ms programok mg mindig hasznljk a megosztott fjlt, akkor az eltvoltsa utn lehet, hogy nem fognak megfelelen mkdni. Ha bizonytalan, vlassza a Nemet. A fjl megtartsa nem okoz problmt a rendszerben.
+SharedFileNameLabel=Fjlnv:
+SharedFileLocationLabel=Helye:
+WizardUninstalling=Eltvolts llapota
+StatusUninstalling=%1 eltvoltsa...
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=%1 teleptse.
+ShutdownBlockReasonUninstallingApp=%1 eltvoltsa.
+
+; 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, verzi: %2
+AdditionalIcons=Tovbbi parancsikonok:
+CreateDesktopIcon=&Asztali ikon ltrehozsa
+CreateQuickLaunchIcon=&Gyorsindts parancsikon ltrehozsa
+ProgramOnTheWeb=%1 az interneten
+UninstallProgram=Eltvolts - %1
+LaunchProgram=Indts %1
+AssocFileExtension=A(z) %1 &trstsa a(z) %2 fjlkiterjesztssel
+AssocingFileExtension=A(z) %1 trstsa a(z) %2 fjlkiterjesztssel...
+AutoStartProgramGroupDescription=Indtpult:
+AutoStartProgram=%1 automatikus indtsa
+AddonHostProgramNotFound=A(z) %1 nem tallhat a kivlasztott knyvtrban.%n%nMindenkppen folytatja?
diff --git a/Greenshot/releases/innosetup/Languages/Indonesian.isl b/Greenshot/releases/innosetup/Languages/Indonesian.isl
new file mode 100644
index 000000000..b86e81e26
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Indonesian.isl
@@ -0,0 +1,364 @@
+; *** Inno Setup version 6.0.3+ Indonesian messages ***
+;
+; Untuk mengunduh berkas terjemahan hasil konstribusi pengguna, kunjungi:
+; http://www.jrsoftware.org/files/istrans/
+;
+; Alih bahasa oleh: MozaikTM (mozaik.tm@gmail.com)
+;
+; Catatan: Saat menerjemahkan pesan ini, jangan masukkan titik (.) pada
+; akhir pesan tanpa titik, karena Inno Setup menambahkan titik pada pesan tersebut
+; secara otomatis (menambahkan sebuah titik akan memunculkan dua titik).
+
+[LangOptions]
+; Tiga baris berikut sangat penting. Pastikan untuk membaca dan
+; memahami topik 'bagian [LangOption]' dalam berkas bantuan.
+LanguageName=Bahasa Indonesia
+LanguageID=$0421
+LanguageCodePage=0
+; Bila target bahasa Anda memerlukan fon atau ukuran khusus,
+; hapus tanda komentar (;) dari salah satu atau beberapa baris berikut dan ubah seperlunya.
+;DialogFontName=
+;DialogFontSize=8
+;WelcomeFontName=Verdana
+;WelcomeFontSize=12
+;TitleFontName=Arial
+;TitleFontSize=29
+;CopyrightFontName=Arial
+;CopyrightFontSize=8
+
+[Messages]
+
+; *** Judul aplikasi
+SetupAppTitle=Pemasang
+SetupWindowTitle=Pemasangan %1
+UninstallAppTitle=Pelepas
+UninstallAppFullTitle=Pelepasan %1
+
+; *** Misc. common
+InformationTitle=Informasi
+ConfirmTitle=Konfirmasi
+ErrorTitle=Ada Masalah
+
+; *** Pesan untuk SetupLdr
+SetupLdrStartupMessage=Kami akan memasang %1. Lanjutkan?
+LdrCannotCreateTemp=Tidak dapat membuat berkas sementara. Pemasangan dibatalkan
+LdrCannotExecTemp=Tidak dapat mengeksekusi berkas di dalam direktori sementara. Pemasangan dibatalkan
+HelpTextNote=
+
+; *** Pesan kesalahan saat memuat Pemasang
+LastErrorMessage=%1.%n%nKesalahan %2: %3
+SetupFileMissing=Berkas %1 hilang dari lokasi pemasangan. Silakan selesaikan masalah atau dapatkan salinan baru dari pemasang ini.
+SetupFileCorrupt=Berkas Pemasang telah rusak. Silakan dapatkan salinan baru dari pemasang ini.
+SetupFileCorruptOrWrongVer=Berkas-berkas pemasang telah rusak, atau tidak cocok dengan versi pemasang ini. Silakan selesaikan masalah atau dapatkan salinan baru dari berkas ini.
+InvalidParameter=Ada parameter tidak sah pada baris perintah:%n%n%1
+SetupAlreadyRunning=Pemasang sudah berjalan.
+WindowsVersionNotSupported=Program ini tidak mendukung Windows yang terpasang pada komputer ini.
+WindowsServicePackRequired=Program ini memerlukan %1 Service Pack %2 atau yang terbaru.
+NotOnThisPlatform=Program ini tidak akan berjalan pada %1.
+OnlyOnThisPlatform=Program ini harus dijalankan pada %1.
+OnlyOnTheseArchitectures=Program ini hanya dapat dipasang pada versi Windows yang didesain untuk arsitektur prosesor berikut:%n%n%1
+WinVersionTooLowError=Program ini memerlukan %1 versi %2 atau yang terbaru.
+WinVersionTooHighError=Program ini tidak dapat dipasang pada %1 versi %2 atau yang terbaru.
+AdminPrivilegesRequired=Anda wajib masuk sebagai seorang administrator saat memasang program ini.
+PowerUserPrivilegesRequired=Anda wajib masuk sebagai seorang administrator atau pengguna dari grup Power Users saat memasang program ini.
+SetupAppRunningError=Pemasang mendeteksi bahwa %1 sedang berjalan.%n%nSilakan tutup semua program terkait, kemudian klik OK untuk lanjut, atau Batal untuk keluar.
+UninstallAppRunningError=Pelepas mendeteksi bahwa %1 sedang berjalan.%n%nSilakan tutup semua program terkait, kemudian klik OK untuk lanjut, atau Batal untuk keluar.
+
+; *** Pertanyaan saat memuat Pemasang
+PrivilegesRequiredOverrideTitle=Pilih Mode Pemasang
+PrivilegesRequiredOverrideInstruction=Pilih mode pemasangan
+PrivilegesRequiredOverrideText1=%1 bisa dipasang untuk semua pengguna (perlu izin administratif), atau hanya untuk Anda.
+PrivilegesRequiredOverrideText2=%1 bisa dipasang hanya untuk Anda, atau untuk semua pengguna (perlu izin administratif).
+PrivilegesRequiredOverrideAllUsers=Pasang untuk &semua pengguna
+PrivilegesRequiredOverrideAllUsersRecommended=Pasang untuk &semua pengguna (disarankan)
+PrivilegesRequiredOverrideCurrentUser=Pasang hanya untuk saya
+PrivilegesRequiredOverrideCurrentUserRecommended=Pasang hanya untuk saya (disarankan)
+
+; *** Macam-macam galat
+ErrorCreatingDir=Pemasang tidak dapat membuat direktori "%1"
+ErrorTooManyFilesInDir=Tidak dapat membuat berkas dalam direktori "%1" karena berisi terlalu banyak berkas.
+
+; *** Pesan umum pada Pemasamg
+ExitSetupTitle=Tutup Pemasang
+ExitSetupMessage=Pemasangan tidak lengkap. Bila Anda keluar sekarang, program tidak akan terpasang.%n%nAnda dapat menjalankan kembali Pemasang ini lain kali untuk melengkapi pemasangan.%n%nTutup Pemasang?
+AboutSetupMenuItem=&Tentang Pemasang ....
+AboutSetupTitle=Tentang Pemasang
+AboutSetupMessage=%1 versi %2%n%3%n%n%1 laman muka:%n%4
+AboutSetupNote=
+TranslatorNote=Bila Anda menemukan typo (kesalahan pengetikan), terjemahan yang salah atau kurang tepat, atau Anda ingin mendapatkan terjemahan untuk versi lawas, silakan kirimkan surel (email) ke mozaik(dot)tm(at)gmail(dot)com
+
+; *** Tombol-tombol
+ButtonBack=< &Sebelumnya
+ButtonNext=&Berikutnya >
+ButtonInstall=&Pasang
+ButtonOK=OK
+ButtonCancel=Batal
+ButtonYes=&Iya
+ButtonYesToAll=Iya &semuanya
+ButtonNo=&Tidak
+ButtonNoToAll=&Tidak semuanya
+ButtonFinish=&Selesai
+ButtonBrowse=&Jelajahi ....
+ButtonWizardBrowse=J&elajahi ....
+ButtonNewFolder=&Buat Map Baru
+
+; *** Halaman "Pilih Bahasa"
+SelectLanguageTitle=Pilih Bahasa Pemasang
+SelectLanguageLabel=Pilih bahasa untuk digunakan selama pemasangan.
+
+; *** Pesan umum pada Pemasang
+ClickNext=Klik Berikutnya untuk melanjutkan, atau Batal untuk menutup Pemasang.
+BeveledLabel=
+BrowseDialogTitle=Pilih Map
+BrowseDialogLabel=Pilih satu map dalam daftar di bawah, kemudian klik OK.
+NewFolderName=Map Baru
+
+; *** Halaman "Selamat Datang"
+WelcomeLabel1=Selamat datang di Asisten Pemasangan [name]
+WelcomeLabel2=Kami akan memasang [name/ver] pada komputer Anda.%n%nAnda disarankan untuk menutup semua aplikasi sebelum melanjutkan.
+
+; *** Halaman "Kata Sandi"
+WizardPassword=Kata Sandi
+PasswordLabel1=Pemasang ini dilindungi kata sandi.
+PasswordLabel3=Silakan masukkan kata sandi, lalu klik Berikutnya untuk melanjutkan. Kata sandi bersifat sensitif kapitalisasi.
+PasswordEditLabel=&Kata Sandi:
+IncorrectPassword=Kata sandi yang Anda masukkan salah. Silakan coba lagi.
+
+; *** Halaman "Kesepakatan Lisensi"
+WizardLicense=Kesepakatan Lisensi
+LicenseLabel=Silakan baca informasi penting berikut sebelum melanjutkan.
+LicenseLabel3=Silakan baca Kesepakatan Lisensi berikut. Anda wajib menyetujui syarat-syarat kesepakatan ini sebelum melanjutkan pemasangan.
+LicenseAccepted=Saya &setuju dengan kesepakatan ini
+LicenseNotAccepted=Saya &tidak setuju dengan kesepakatan ini
+
+; *** Halaman "Informasi"
+WizardInfoBefore=Informasi
+InfoBeforeLabel=Silakan baca informasi penting berikut sebelum melanjutkan.
+InfoBeforeClickLabel=Bila Anda sudah siap melanjutkan pemasangan, klik Berikutnya.
+WizardInfoAfter=Informasi
+InfoAfterLabel=Silakan baca informasi penting berikut sebelum melanjutkan.
+InfoAfterClickLabel=Bila Anda sudah siap melanjutkan pemasangan, klik Berikutnya.
+
+; *** Halaman "Informasi Pengguna"
+WizardUserInfo=Informasi Pengguna
+UserInfoDesc=Silakan masukkan informasi Anda.
+UserInfoName=&Nama Pengguna:
+UserInfoOrg=&Organisasi:
+UserInfoSerial=Nomor Seri:
+UserInfoNameRequired=Anda wajib memasukkan nama.
+
+; *** Halaman "Pilih Lokasi Pemasangan"
+WizardSelectDir=Pilih Lokasi Pemasangan
+SelectDirDesc=Di manakah [name] sebaiknya dipasang?
+SelectDirLabel3=Kami akan memasang [name] di dalam map berikut.
+SelectDirBrowseLabel=Klik Berikutnya untuk melanjutkan. Bila Anda ingin memilih map lain, klik Jelajahi.
+DiskSpaceGBLabel=Diperlukan sedikitnya [gb] GB ruang kosong.
+DiskSpaceMBLabel=Diperlukan sedikitnya [mb] MB ruang kosong.
+CannotInstallToNetworkDrive=Kami tidak dapat memasang pada kandar jaringan.
+CannotInstallToUNCPath=Kami tidak dapat memasang pada lokasi UNC.
+InvalidPath=Anda wajib memasukkan lokasi map lengkap dengan nama kandar; misalnya:%n%nC:\APP%n%natau sebuah alamat UNC dengan format:%n%n\\server\share
+InvalidDrive=Kandar atau alamat UNC yang Anda pilih tidak ada atau tidak dapat diakses. Silakan pilih yang lain.
+DiskSpaceWarningTitle=Ruang Kosong Tidak Mencukupi
+DiskSpaceWarning=Pemasang memerlukan sedikitnya %1 KB ruang kosong, tetapi kandar terpilih hanya memiliki %2 KB tersedia.%n%nTetap lanjutkan?
+DirNameTooLong=Alamat atau nama map terlalu panjang.
+InvalidDirName=Nama map ini tidak sah.
+BadDirName32=Nama map dilarang berisi karakter berikut:%n%n%1
+DirExistsTitle=Map Sudah Ada
+DirExists=Map:%n%n%1%n%nsudah ada. Tetap pasang di map tersebut?
+DirDoesntExistTitle=Map Belum Ada
+DirDoesntExist=Map:%n%n%1%n%nbelum ada. Buat map tersebut?
+
+; *** Halaman "Pilih Komponen"
+WizardSelectComponents=Pilih Komponen
+SelectComponentsDesc=Komponen mana sajakah yang sebaiknya dipasang?
+SelectComponentsLabel2=Pilih komponen-komponen yang Anda ingin pasang; hapus centang pada komponen yang Anda tidak ingin pasang. Klik Berikutnya bila Anda siap melanjutkan.
+FullInstallation=Pasang secara penuh
+; kalau bisa, jangan terjemahkan "Padat" (Compact) menjadi "Minimal". Maksudnya, "Minimal" dalam bahasa Anda
+CompactInstallation=Pemasangan Padat
+CustomInstallation=Suka-suka saya
+NoUninstallWarningTitle=Komponen Sudah Ada
+NoUninstallWarning=Kami mendeteksi bahwa komponen-komponen berikut sudah terpasang pada komputer Anda:%n%n%1%n%nKomponen-komponen tersebut tidak akan dihapus walau Anda batal memilihnya.%n%nTetap lanjutkan?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceGBLabel=Pilihan Anda saat ini memerlukan sedikitnya [gb] GB ruang kosong.
+ComponentsDiskSpaceMBLabel=Pilihan Anda saat ini memerlukan sedikitnya [mb] MB ruang kosong.
+
+; *** Halaman "Pilih Tugas Tambahan"
+WizardSelectTasks=Pilih Tugas Tambahan
+SelectTasksDesc=Tugas tambahan mana sajakah yang Anda ingin jalankan?
+SelectTasksLabel2=Pilih tugas tambahan yang Anda ingin agar kami jalankan saat memasang [name], lalu klik Berikutnya.
+
+; *** Halaman "Pilih Map Menu Start"
+WizardSelectProgramGroup=Pilih Map Menu Start
+SelectStartMenuFolderDesc=Di manakah sebaiknya kami menempatkan pintasan program?
+SelectStartMenuFolderLabel3=Kami akan membuat pintasan program di dalam map Menu Start berikut.
+SelectStartMenuFolderBrowseLabel=Klik Berikutnya untuk melanjutkan. Bila Anda ingin memilih map lain, klik Jelajahi.
+MustEnterGroupName=Anda wajib memasukkan nama map.
+GroupNameTooLong=Alamat atau nama map terlalu panjang.
+InvalidGroupName=Nama map tidak sah.
+BadGroupName=Nama map dilarang berisi karakter berikut:%n%n%1
+NoProgramGroupCheck2=&Jangan buat map Menu Start
+
+; *** Halaman "Siap Memasang"
+WizardReady=Siap Memasang
+ReadyLabel1=Kami telah siap untuk mulai memasang [name] pada komputer Anda.
+ReadyLabel2a=Klik Pasang untuk melanjutkan dengan pengaturan yang Anda pilih, atau klik Sebelumnya bila Anda ingin melihat ulang atau mengubah pengaturan.
+ReadyLabel2b=Klik Pasang untuk melanjutkan dengan pengaturan yang Anda pilih
+ReadyMemoUserInfo=Informasi pengguna:
+ReadyMemoDir=Lokasi pemasangan:
+ReadyMemoType=Jenis pemasangan:
+ReadyMemoComponents=Komponen terpilih:
+ReadyMemoGroup=Map Menu Start:
+ReadyMemoTasks=Tugas Tambahan:
+
+; *** Halaman "Bersiap Memasang"
+WizardPreparing=Bersiap Memasang
+PreparingDesc=Kami sedang bersiap memasang [name] pada komputer Anda.
+PreviousInstallNotCompleted=Pemasangan/pelepasan dari program sebelumnya tidaklah lengkap. Anda perlu memulai ulang komputer untuk melengkapi pemasangan tersebut.%n%nSeusai memulai ulang komputer, jalankan Pemasang ini lagi untuk melengkapi pemasangan [name].
+CannotContinue=Kami tidak dapat melanjutkan. Silakan klik Batal untuk keluar.
+ApplicationsFound=Aplikasi-aplikasi berikut sedang memakai berkas-berkas yang perlu diperbarui oleh kami. Disarankan agar Anda mengizinkan kami untuk menutup aplikasi-aplikasi tersebut secara otomatis.
+ApplicationsFound2=Aplikasi-aplikasi berikut sedang memakai berkas-berkas yang perlu diperbaru oleh kami. Disarankan agar Anda mengizinkan kami untuk menutup aplikasi-aplikasi tersebut secara otomatis. Seusai memasang, kami akan berusaha menjalankan ulang aplikasi-aplikasi tersebut.
+CloseApplications=&Otomatis tutup aplikasi-aplikasi tersebut
+DontCloseApplications=&Jangan tutup aplikasi-aplikasi tersebut
+ErrorCloseApplications=Kami tidak dapat menutup semua aplikasi tersebut secara otomatis. Disarankan agar Anda menutup semua aplikasi yang memakai berkas-berkas yang perlu kami perbarui sebelum melanjutkan.
+PrepareToInstallNeedsRestart=Kami harus memulai ulang komputer Anda. Seusai memulai ulang, jalankan kembali Pemasang ini untuk melengkapi pemasangan [name].%n%nMulai ulang sekarang?
+
+; *** Halaman "Memasang"
+WizardInstalling=Memasang
+InstallingLabel=Silakan tunggu sementara kami memasang [name] pada komputer Anda.
+
+; *** Halaman "Pemasangan Lengkap"
+FinishedHeadingLabel=Menyelesaikan Asisten Pemasangan [name]
+FinishedLabelNoIcons=Kami telah selesai memasang [name] pada komputer Anda.
+FinishedLabel=Kami telah selesai memasang [name] pada komputer Anda. Program tersebut dapat dijalankan dengan memilih pintasan yang terpasang.
+ClickFinish=Klik Selesai untuk mengakhiri pemasangan.
+FinishedRestartLabel=Agar pemasangan [name] lengkap, kami harus memulai ulang komputer Anda. Mulai ulang sekarang?
+FinishedRestartMessage=Agar pemasangan [name] lengkap, kami harus memulai ulang komputer Anda.%n%nMulai ulang sekarang?
+ShowReadmeCheck=Ya, saya mau membaca berkas README
+YesRadio=&Ya, mulai ulang sekarang
+NoRadio=&Tidak, saya akan memulai ulang nanti
+; contoh: 'Jalankan MyProg.exe'
+RunEntryExec=Jalankan %1
+; contoh: 'Lihat Readme.txt'
+RunEntryShellExec=Lihat %1
+
+; *** Pesan yang berkaitan dengan "Setup Needs the Next Disk"
+ChangeDiskTitle=Kami Memerlukan Kandar Lanjutan
+SelectDiskLabel2=Silakan masukkan Kandar %1 dan klik OK.%n%nBila berkas-berkas pada kandar ini dapat ditemukan selain pada map berikut, masukkan alamat yang tepat atau klik Jelajahi.
+PathLabel=&Alamat:
+FileNotInDir2=Berkas "%1" tidak dapat ditemukan di dalam "%2". Silakan masukkan kandar yang tepat atau pilih map lain.
+SelectDirectoryLabel=Silakan tunjukkan lokasi kandar lanjutan.
+
+; *** Pesan untuk fase pemasangan
+SetupAborted=Pemasangan tidak lengkap.%n%nSilakan selesaikan masalah dan jalankan Pemasang ini kembali.
+AbortRetryIgnoreSelectAction=Pilih tindakan
+AbortRetryIgnoreRetry=&Coba lagi
+AbortRetryIgnoreIgnore=&Abaikan masalah dan lanjutkan
+AbortRetryIgnoreCancel=Batalkan pemasangan
+
+; *** Pesan untuk status pemasangan
+StatusClosingApplications=Menutup aplikasi ....
+StatusCreateDirs=Membuat direktori ....
+StatusExtractFiles=Mengekstrak berkas ....
+StatusCreateIcons=Membuat pintasan ....
+StatusCreateIniEntries=Membuat isi berkas INI ...
+StatusCreateRegistryEntries=Membuat daftar registri ....
+StatusRegisterFiles=Mendaftarkan berkas ....
+StatusSavingUninstall=Menyimpan informasi pelepasan ....
+StatusRunProgram=Mengakhiri pemasangan ....
+StatusRestartingApplications=Memulai ulang aplikasi ....
+StatusRollback=Membatalkan perubahan ....
+
+; *** Masalah secara umum
+ErrorInternal2=Masalah internal: %1
+ErrorFunctionFailedNoCode=%1 gagal
+ErrorFunctionFailed=%1 gagal; kode %2
+ErrorFunctionFailedWithMessage=%1 gagal; kode %2.%n%3
+ErrorExecutingProgram=Tidak dapat mengeksekusi berkas:%n%1
+
+; *** Masalah pada Registry
+ErrorRegOpenKey=Masalah saat membuka kunci registri:%n%1\%2
+ErrorRegCreateKey=Masalah saat membuat kunci registri:%n%1\%2
+ErrorRegWriteKey=Masalah saat menulis pada kunci registri:%n%1\%2
+
+; *** Masalah pada INI
+ErrorIniEntry=Terjadi masalah saat membuat entri INI dalam berkas "%1".
+
+; *** Masalah saat menyalin berkas
+FileAbortRetryIgnoreSkipNotRecommended=&Lewati berkas ini (tidak disarankan)
+FileAbortRetryIgnoreIgnoreNotRecommended=&Abaikan masalah dan lanjutkan (tidak disarankan)
+SourceIsCorrupted=Berkas sumber telah rusak
+SourceDoesntExist=Berkas sumber "%1" tidak ada
+ExistingFileReadOnly2=Berkas yang telah ada tidak bisa diganti karena ditandai hanya-baca.
+ExistingFileReadOnlyRetry=&Hapus atribut hanya-baca dan coba lagi
+ExistingFileReadOnlyKeepExisting=&Pertahankan berkas yang sudah ada
+ErrorReadingExistingDest=Terjadi masalah saat mencoba membaca berkas yang sudah ada:
+FileExists=Berkas sudah ada.%n%nTimpa berkas tersebut?
+ExistingFileNewer=Berkas yang sudah ada lebih baru dibanding dengan yang akan kami pasang. Disarankan agar Anda mempertahankan berkas tersebut.%n%nPertahankan berkas tersebut?
+ErrorChangingAttr=Terjadi masalah saat mencoba mengubah atribut berkas yang sudah ada:
+ErrorCreatingTemp=Terjadi masalah saat mencoba membuat berkas di dalam direktori pemasangan:
+ErrorReadingSource=Terjadi masalah saat mencoba membaca berkas sumber:
+ErrorCopying=Terjadi masalah saat mencoba menyalin berkas:
+ErrorReplacingExistingFile=Terjadi masalah saat mencoba menimpa berkas yang sudah ada:
+ErrorRestartReplace=Fungsi RestartReplace gagal:
+ErrorRenamingTemp=Terjadi masalah saat mencoba mengubah nama berkas dalam direktori pemasangan:
+ErrorRegisterServer=Tidak dapat mendaftarkan berkas DLL/OCX: %1
+ErrorRegSvr32Failed=RegSvr32 gagal dengan kode akhir %1
+ErrorRegisterTypeLib=Tidak dapat mendaftarkan pustaka: %1
+
+; *** Penandaan tampilan nama saat melepas
+; contoh 'Program saya (32-bita)'
+UninstallDisplayNameMark=%1 (%2)
+; contoh 'Program saya (32-bita, Semua pengguna)'
+UninstallDisplayNameMarks=%1 (%2, %3)
+UninstallDisplayNameMark32Bit=32-bita
+UninstallDisplayNameMark64Bit=64-bita
+UninstallDisplayNameMarkAllUsers=Semua pengguna
+UninstallDisplayNameMarkCurrentUser=Pengguna saat ini
+
+; *** Masalah pasca-pemasangan
+ErrorOpeningReadme=Terjadi masalah saat mencoba membuka berkas README.
+ErrorRestartingComputer=Kami tidak dapat memulai ulang komputer. Silakan lakukan secara manual.
+
+; *** Pesan untuk Pelepas
+UninstallNotFound=Berkas "%1" tidak ada. Tidak bisa melepas.
+UninstallOpenError=Berkas "%1" tidak bisa dibuka. Tidak bisa melepas
+UninstallUnsupportedVer=Berkas catatan pelepas "%1" tertulis dalam format yang tak dikenali oleh pelepas versi ini. Tidak bisa melepas.
+UninstallUnknownEntry=Entri tak dikenal (%1) ditemukan dalam catatan pelepas
+ConfirmUninstall=Apakah Anda yakin hendak menghapus %1 beserta semua komponennya?
+UninstallOnlyOnWin64=Instalasi ini hanya dapat dilepas pada Windows 64-bita.
+OnlyAdminCanUninstall=Instalasi ini hanya dapat dilepas oleh pengguna dengan izin administratif.
+UninstallStatusLabel=Silakan tunggu sementara %1 dihapus dari komputer Anda.
+UninstalledAll=%1 berhasil dilepas dari komputer Anda.
+UninstalledMost=Selesai melepas %1.%n%nBeberapa elemen tidak dapat dihapus. Anda dapat menghapusnya secara manual.
+UninstalledAndNeedsRestart=Untuk melengkapi pelepasan %1, komputer Anda harus dimulai ulang.%n%nMulai ulang sekarang?
+UninstallDataCorrupted=Berkas "%1" telah rusak. Tidak bisa melepas
+
+; *** Pesan untuk fase pelepasan
+ConfirmDeleteSharedFileTitle=Hapus Berkas Bersama?
+ConfirmDeleteSharedFile2=Sistem mengindikasi bahwa berkas-berkas bersama berikut tidak lagi dipakai oleh program apa pun. Apakah Anda ingin kami menghapus berkas-berkas tersebut?%n%nJika berkas-berkas tersebut dihapus dan masih ada program yang memakainya, program tersebut mungkin akan berjalan di luar semestinya. Bila Anda tidak yakin, pilih Tidak. Membiarkan berkas tersebut pada komputer Anda tidak akan menimbulkan masalah.
+SharedFileNameLabel=Nama berkas:
+SharedFileLocationLabel=Lokasi:
+WizardUninstalling=Status Pelepasan
+StatusUninstalling=Melepas %1...
+
+; *** Blok alasan Shutdown
+ShutdownBlockReasonInstallingApp=Memasang %1.
+ShutdownBlockReasonUninstallingApp=Melepas %1.
+
+; Pesan khusus berikut tidak digunakan oleh Pemasang itu sendiri,
+; namun bila Anda memakainya di dalam skrip Anda, maka terjemahkan.
+
+[CustomMessages]
+NameAndVersion=%1 versi %2
+AdditionalIcons=Pintasan tambahan:
+CreateDesktopIcon=Buat pintasan di &Desktop
+CreateQuickLaunchIcon=Buat pintasan di &Quick Launch
+ProgramOnTheWeb=%1 di web
+UninstallProgram=Lepas %1
+LaunchProgram=Jalankan %1
+AssocFileExtension=&Asosiasikan %1 dengan ekstensi berkas %2
+AssocingFileExtension=Mengasosiasikan %1 dengan ekstensi berkas %2 ....
+AutoStartProgramGroupDescription=Startup:
+AutoStartProgram=Jalankan %1 secara otomatis
+AddonHostProgramNotFound=%1 tidak dapat ditemukan di dalam map yang Anda pilih.%n%nTetap lanjutkan?
diff --git a/installer/innosetup/Languages/Kazakh.islu b/Greenshot/releases/innosetup/Languages/Kazakh.islu
similarity index 100%
rename from installer/innosetup/Languages/Kazakh.islu
rename to Greenshot/releases/innosetup/Languages/Kazakh.islu
diff --git a/installer/innosetup/Languages/Korean.isl b/Greenshot/releases/innosetup/Languages/Korean.isl
similarity index 100%
rename from installer/innosetup/Languages/Korean.isl
rename to Greenshot/releases/innosetup/Languages/Korean.isl
diff --git a/installer/innosetup/Languages/Kurdish.isl b/Greenshot/releases/innosetup/Languages/Kurdish.isl
similarity index 100%
rename from installer/innosetup/Languages/Kurdish.isl
rename to Greenshot/releases/innosetup/Languages/Kurdish.isl
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/Ligurian.isl b/Greenshot/releases/innosetup/Languages/Ligurian.isl
similarity index 100%
rename from installer/innosetup/Languages/Ligurian.isl
rename to Greenshot/releases/innosetup/Languages/Ligurian.isl
diff --git a/installer/innosetup/Languages/Lithuanian.isl b/Greenshot/releases/innosetup/Languages/Lithuanian.isl
similarity index 88%
rename from installer/innosetup/Languages/Lithuanian.isl
rename to Greenshot/releases/innosetup/Languages/Lithuanian.isl
index 74c99b2cd..b3e220036 100644
--- a/installer/innosetup/Languages/Lithuanian.isl
+++ b/Greenshot/releases/innosetup/Languages/Lithuanian.isl
@@ -1,7 +1,7 @@
-; *** Inno Setup version 6.1.0+ Lithuanian messages ***
+; *** Inno Setup version 6.0.3+ Lithuanian messages ***
;
; To download user-contributed translations of this file, go to:
-; https://jrsoftware.org/files/istrans/
+; 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
@@ -165,9 +165,9 @@ DiskSpaceWarning=Diegimui reikia bent %1 KB laisvos vietos, bet nurodytame diske
DirNameTooLong=Katalogo pavadinimas ar kelias iki jo per ilgas.
InvalidDirName=Nekorektikas katalogo pavadinimas.
BadDirName32=Katalogo pavadinime neturi bti simboli:%n%n%1
-DirExistsTitle=Tokio katalogo nra
-DirExists=Katalogas:%n%n%1%n%n jau yra. Vis tiek norite diegti program tame kataloge?
-DirDoesntExistTitle=Tokio katalogo nra.
+DirExistsTitle=Toks katalogas egzistuoja
+DirExists=Katalogas:%n%n%1%n%n jau egzistuoja. Vis tiek norite diegti program tame kataloge?
+DirDoesntExistTitle=Toks katalogas neegzistuoja.
DirDoesntExist=Katalogas:%n%n%1%n%n neegzistuoja. Norite kad katalogas bt sukurtas?
; *** "Select Components" wizard page
@@ -213,18 +213,6 @@ ReadyMemoComponents=Pasirinkti komponentai:
ReadyMemoGroup=Start Menu katalogas:
ReadyMemoTasks=Papildomi veiksmai:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=Parsisiuniami papildomi failai...
-ButtonStopDownload=&Stabdyti parsisiuntim
-StopDownload=Ar tikrai norite sustabdyti parsisiuntim?
-ErrorDownloadAborted=Parsisiuntimas nutrauktas
-ErrorDownloadFailed=Parsisisti nepavyko: %1 %2
-ErrorDownloadSizeFailed=Nepavyko gauti dydio: %1 %2
-ErrorFileHash1=Failo patikrinimas nepavyko: %1
-ErrorFileHash2=Neteisinga failo hash reikm: numatyta %1, rasta %2
-ErrorProgress=Netinkama eiga: %1 i %2
-ErrorFileSize=Neteisingas failo dydis: numatytas %1, rastas %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=Pasirengimas diegimui
PreparingDesc=Diegimo programa pasirengusi [name] diegimui Js kompiuteryje.
@@ -302,27 +290,18 @@ ErrorIniEntry=Klaida ra
FileAbortRetryIgnoreSkipNotRecommended=Pralei&sti fail (nerekomenduojama)
FileAbortRetryIgnoreIgnoreNotRecommended=&Ignoruoti klaid ir tsti (nerekomenduojama)
SourceIsCorrupted=Pradinis failas sugadintas
-SourceDoesntExist=Pradinio failo %1 nra
-ExistingFileReadOnly2=Esamas failas yra paymtas Tik skaitymui todl negali bti pakeistas.
+SourceDoesntExist=Pradinis failas %1 neegzistuoja
+ExistingFileReadOnly2=Egzistuojantis failas yra paymtas Tik skaitymui todl negali bti pakeistas.
ExistingFileReadOnlyRetry=Paalinkite at&ribut Tik skaitymui ir bandykite vl
-ExistingFileReadOnlyKeepExisting=Pali&kti esam fail
-ErrorReadingExistingDest=Skaitant esam fail vyko klaida:
-FileExistsSelectAction=Pasirinkite veiksm
-FileExists2=Toks failas jau yra.
-FileExistsOverwriteExisting=&Perrayti esam fail
-FileExistsKeepExisting=Pali&kti esam fail
-FileExistsOverwriteOrKeepAll=&Daryti taip ir esant kitiems konfliktams
-ExistingFileNewerSelectAction=Pasirinkite veiksm
-ExistingFileNewer=Esamas failas yra naujesnis u t, kur diegimo programa bando rayti. Rekomenduojama palikti esam fail.%n%nPalikti naujesn fail?
-ExistingFileNewer2=Esamas failas yra naujesnis u t, kur diegimo programa bando rayti.
-ExistingFileNewerOverwriteExisting=&Perrayti esam fail
-ExistingFileNewerKeepExisting=Pali&kti esam fail (rekomenduojama)
-ExistingFileNewerOverwriteOrKeepAll=&Daryti taip ir esant kitiems konfliktams
+ExistingFileReadOnlyKeepExisting=Pali&kti egzistuojant fail
+ErrorReadingExistingDest=Skaitant egzistuojant fail vyko klaida:
+FileExists=Toks failas jau egzistuoja.%n%nNorite, kad diegimo programa perrayt fail?
+ExistingFileNewer=Egzistuojantis failas yra naujesnis u t, kur diegimo programa bando rayti. Rekomenduojama palikti esant naujesn fail.%n%nNorite palikti naujesn fail?
ErrorChangingAttr=Keiiant failo atributus vyko klaida:
ErrorCreatingTemp=Kuriant fail pasirinktame kataloge vyko klaida:
ErrorReadingSource=Skaitant diegiamj fail vyko klaida:
ErrorCopying=Kopijuojant fail vyko klaida:
-ErrorReplacingExistingFile=Perraant esam fail vyko klaida:
+ErrorReplacingExistingFile=Perraant egzistuojant fail vyko klaida:
ErrorRestartReplace=Perkrovimas/Perraymas nepavyko:
ErrorRenamingTemp=Pervadinant fail pasirinktame kataloge vyko klaida:
ErrorRegisterServer=Nepavyko uregistruoti DLL/OCX bibliotekos: %1
@@ -344,7 +323,7 @@ ErrorOpeningReadme=Bandant atidaryti
ErrorRestartingComputer=Diegimo programa negali perkrauti kompiuterio. Perkraukite kompiuter prastu bdu.
; *** Uninstaller messages
-UninstallNotFound=%1 failo nra. Paalinti nemanoma.
+UninstallNotFound=%1 failas neegzistuoja. Paalinti nemanoma.
UninstallOpenError=%1 failas negali bti atidarytas. Paalinti nemanoma.
UninstallUnsupportedVer=Paalinimo urnalo failas %1 yra paalinimo programai nesuprantamo formato. Paalinti nemanoma.
UninstallUnknownEntry=Neinomas raas (%1) rastas paalinimo urnalo faile.
@@ -383,6 +362,6 @@ UninstallProgram=Pa
LaunchProgram=Paleisti %1
AssocFileExtension=&Susieti %1 program su failo pltiniu %2
AssocingFileExtension=%1 programa susiejama su failo pltiniu %2...
-AutoStartProgramGroupDescription=Automatin paleistis:
-AutoStartProgram=Automatikai paleisti %1
+AutoStartProgramGroupDescription=Atomatin paleistis:
+AutoStartProgram=Atomatikai paleisti %1
AddonHostProgramNotFound=%1 nerasta Js nurodytame kataloge.%n%nVis tiek norite tsti?
diff --git a/installer/innosetup/Languages/Luxemburgish.isl b/Greenshot/releases/innosetup/Languages/Luxemburgish.isl
similarity index 100%
rename from installer/innosetup/Languages/Luxemburgish.isl
rename to Greenshot/releases/innosetup/Languages/Luxemburgish.isl
diff --git a/installer/innosetup/Languages/Macedonian.isl b/Greenshot/releases/innosetup/Languages/Macedonian.isl
similarity index 100%
rename from installer/innosetup/Languages/Macedonian.isl
rename to Greenshot/releases/innosetup/Languages/Macedonian.isl
diff --git a/installer/innosetup/Languages/Malaysian.isl b/Greenshot/releases/innosetup/Languages/Malaysian.isl
similarity index 100%
rename from installer/innosetup/Languages/Malaysian.isl
rename to Greenshot/releases/innosetup/Languages/Malaysian.isl
diff --git a/installer/innosetup/Languages/Marathi.islu b/Greenshot/releases/innosetup/Languages/Marathi.islu
similarity index 100%
rename from installer/innosetup/Languages/Marathi.islu
rename to Greenshot/releases/innosetup/Languages/Marathi.islu
diff --git a/installer/innosetup/Languages/Mongolian.isl b/Greenshot/releases/innosetup/Languages/Mongolian.isl
similarity index 100%
rename from installer/innosetup/Languages/Mongolian.isl
rename to Greenshot/releases/innosetup/Languages/Mongolian.isl
diff --git a/installer/innosetup/Languages/Montenegrian.isl b/Greenshot/releases/innosetup/Languages/Montenegrian.isl
similarity index 100%
rename from installer/innosetup/Languages/Montenegrian.isl
rename to Greenshot/releases/innosetup/Languages/Montenegrian.isl
diff --git a/installer/innosetup/Languages/Nepali.islu b/Greenshot/releases/innosetup/Languages/Nepali.islu
similarity index 100%
rename from installer/innosetup/Languages/Nepali.islu
rename to Greenshot/releases/innosetup/Languages/Nepali.islu
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/Occitan.isl b/Greenshot/releases/innosetup/Languages/Occitan.isl
similarity index 100%
rename from installer/innosetup/Languages/Occitan.isl
rename to Greenshot/releases/innosetup/Languages/Occitan.isl
diff --git a/installer/innosetup/Languages/Romanian.isl b/Greenshot/releases/innosetup/Languages/Romanian.isl
similarity index 100%
rename from installer/innosetup/Languages/Romanian.isl
rename to Greenshot/releases/innosetup/Languages/Romanian.isl
diff --git a/installer/innosetup/Languages/ScottishGaelic.isl b/Greenshot/releases/innosetup/Languages/ScottishGaelic.isl
similarity index 100%
rename from installer/innosetup/Languages/ScottishGaelic.isl
rename to Greenshot/releases/innosetup/Languages/ScottishGaelic.isl
diff --git a/installer/innosetup/Languages/SerbianCyrillic.isl b/Greenshot/releases/innosetup/Languages/SerbianCyrillic.isl
similarity index 81%
rename from installer/innosetup/Languages/SerbianCyrillic.isl
rename to Greenshot/releases/innosetup/Languages/SerbianCyrillic.isl
index 743212575..0ea72f5e0 100644
--- a/installer/innosetup/Languages/SerbianCyrillic.isl
+++ b/Greenshot/releases/innosetup/Languages/SerbianCyrillic.isl
@@ -1,9 +1,9 @@
-; *** Inno Setup version 6.1.0+ Serbian (Cyrillic) messages ***
+; *** Inno Setup version 5.5.3+ Serbian (Cyrillic) messages ***
;
; To download user-contributed translations of this file, go to:
; http://www.jrsoftware.org/files/istrans/
;
-; Translated by Rancher (theranchcowboy@gmail.com) and Davor (davornik@yahoo.com).
+; Translated by Rancher (theranchcowboy@gmail.com).
;
; 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
@@ -44,7 +44,6 @@ ErrorTitle=
SetupLdrStartupMessage= %1. ?
LdrCannotCreateTemp= . .
LdrCannotExecTemp= . .
-HelpTextNote=
; *** Startup error messages
LastErrorMessage=%1.%n%n %2: %3
@@ -58,21 +57,13 @@ WindowsServicePackRequired=
NotOnThisPlatform= %1.
OnlyOnThisPlatform= %1.
OnlyOnTheseArchitectures= :%n%n%1
+MissingWOW64APIs= 64- . %1 .
WinVersionTooLowError= %1, %2 .
WinVersionTooHighError= %1 %2 .
AdminPrivilegesRequired= .
PowerUserPrivilegesRequired= .
SetupAppRunningError= %1 .%n%n .
UninstallAppRunningError= %1 .%n%n .
-; *** Startup questions
-PrivilegesRequiredOverrideTitle=
-PrivilegesRequiredOverrideInstruction=
-PrivilegesRequiredOverrideText1=%1 ( ) .
-PrivilegesRequiredOverrideText2=%1 ( ).
-PrivilegesRequiredOverrideAllUsers= &
-PrivilegesRequiredOverrideAllUsersRecommended= & ()
-PrivilegesRequiredOverrideCurrentUser= &
-PrivilegesRequiredOverrideCurrentUserRecommended= & ()
; *** Misc. errors
ErrorCreatingDir= %1.
@@ -85,7 +76,7 @@ AboutSetupMenuItem=&
AboutSetupTitle=
AboutSetupMessage=%1 %2%n%3%n%n%1 :%n%4
AboutSetupNote=
-TranslatorNote=
+TranslatorNote=Serbian translation by Rancher.
; *** Buttons
ButtonBack=< &
@@ -152,7 +143,6 @@ WizardSelectDir=
SelectDirDesc= [name].
SelectDirLabel3= [name] .
SelectDirBrowseLabel= . , 腓.
-DiskSpaceGBLabel= [gb] GB .
DiskSpaceMBLabel= [mb] MB .
CannotInstallToNetworkDrive= .
CannotInstallToUNCPath= UNC .
@@ -180,7 +170,6 @@ NoUninstallWarningTitle=
NoUninstallWarning= :%n%n%1%n%n .%n%n ?
ComponentSize1=%1 kB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel= [gb] GB .
ComponentsDiskSpaceMBLabel= [mb] MB .
; *** "Select Additional Tasks" wizard page
@@ -211,18 +200,6 @@ ReadyMemoComponents=
ReadyMemoGroup= :
ReadyMemoTasks= :
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel= ...
-ButtonStopDownload=&
-StopDownload= ?
-ErrorDownloadAborted=
-ErrorDownloadFailed= : %1 %2
-ErrorDownloadSizeFailed= : %1 %2
-ErrorFileHash1= : %1
-ErrorFileHash2= : %1, %2
-ErrorProgress= : %1 %2
-ErrorFileSize= : %1, %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=
PreparingDesc= [name] .
@@ -233,7 +210,6 @@ ApplicationsFound2=
CloseApplications=&
DontCloseApplications=&
ErrorCloseApplications= . , .
-PrepareToInstallNeedsRestart= . , [name].%n%n ?
; *** "Installing" wizard page
WizardInstalling=
@@ -263,10 +239,7 @@ SelectDirectoryLabel=
; *** Installation phase messages
SetupAborted= .%n%n .
-AbortRetryIgnoreSelectAction=
-AbortRetryIgnoreRetry=&
-AbortRetryIgnoreIgnore=&
-AbortRetryIgnoreCancel=
+EntryAbortRetryIgnore= , .
; *** Installation status messages
StatusClosingApplications=
@@ -297,24 +270,14 @@ ErrorRegWriteKey=
ErrorIniEntry= INI %1.
; *** File copying errors
-FileAbortRetryIgnoreSkipNotRecommended=& ( )
-FileAbortRetryIgnoreIgnoreNotRecommended=& ( )
+FileAbortRetryIgnore= , ( ) .
+FileAbortRetryIgnore2= , ( ) .
SourceIsCorrupted=
SourceDoesntExist= %1
-ExistingFileReadOnly2= .
-ExistingFileReadOnlyRetry=&
-ExistingFileReadOnlyKeepExisting=&
+ExistingFileReadOnly= .%n%n , .
ErrorReadingExistingDest= :
-FileExistsSelectAction=
-FileExists2= .
-FileExistsOverwriteExisting=&
-FileExistsKeepExisting=&
-FileExistsOverwriteOrKeepAll=&
-ExistingFileNewerSelectAction=
-ExistingFileNewer2= .
-ExistingFileNewerOverwriteExisting=&
-ExistingFileNewerKeepExisting=& ()
-ExistingFileNewerOverwriteOrKeepAll=&
+FileExists= .%n%n ?
+ExistingFileNewer= . .%n%n ?
ErrorChangingAttr= :
ErrorCreatingTemp= :
ErrorReadingSource= :
@@ -326,16 +289,6 @@ ErrorRegisterServer=
ErrorRegSvr32Failed=RegSvr32 . %1
ErrorRegisterTypeLib= : %1
-; *** Uninstall display name markings
-; used for example as 'My Program (32-bit)'
-UninstallDisplayNameMark=%1 (%2)
-; used for example as 'My Program (32-bit, All users)'
-UninstallDisplayNameMarks=%1 (%2, %3)
-UninstallDisplayNameMark32Bit=32-bit
-UninstallDisplayNameMark64Bit=64-bit
-UninstallDisplayNameMarkAllUsers=
-UninstallDisplayNameMarkCurrentUser=
-
; *** Post-installation errors
ErrorOpeningReadme= .
ErrorRestartingComputer= . .
diff --git a/installer/innosetup/Languages/SerbianLatin.isl b/Greenshot/releases/innosetup/Languages/SerbianLatin.isl
similarity index 80%
rename from installer/innosetup/Languages/SerbianLatin.isl
rename to Greenshot/releases/innosetup/Languages/SerbianLatin.isl
index 55ebbb8f5..4c28549d7 100644
--- a/installer/innosetup/Languages/SerbianLatin.isl
+++ b/Greenshot/releases/innosetup/Languages/SerbianLatin.isl
@@ -1,9 +1,9 @@
-; *** Inno Setup version 6.1.0+ Serbian (Latin) messages ***
+; *** Inno Setup version 5.5.3+ Serbian (Latin) messages ***
;
; To download user-contributed translations of this file, go to:
; http://www.jrsoftware.org/files/istrans/
;
-; Translated by Rancher (theranchcowboy@gmail.com) and Davor (davornik@yahoo.com).
+; Translated by Rancher (theranchcowboy@gmail.com).
;
; 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
@@ -44,7 +44,6 @@ ErrorTitle=Gre
SetupLdrStartupMessage=Instaliraete %1. elite li da nastavite?
LdrCannotCreateTemp=Ne mogu da napravim privremenu datoteku. Instalacija je prekinuta.
LdrCannotExecTemp=Ne mogu da pokrenem datoteku u privremenoj fascikli. Instalacija je prekinuta.
-HelpTextNote=
; *** Startup error messages
LastErrorMessage=%1.%n%nGreka %2: %3
@@ -53,11 +52,12 @@ SetupFileCorrupt=Instalacione datoteke su o
SetupFileCorruptOrWrongVer=Instalacione datoteke su oteene ili nisu saglasne s ovom verzijom instalacije. Ispravite problem ili nabavite novi primerak programa.
InvalidParameter=Neispravan parametar je prenet na komandnu liniju: %n%n%1
SetupAlreadyRunning=Instalacija je ve pokrenuta.
-WindowsVersionNotSupported=Program ne podrava izdanje Windows-a koje koristite.
+WindowsVersionNotSupported=Program ne podrava izdanje vindousa koje koristite.
WindowsServicePackRequired=Program zahteva %1 servisni paket %2 ili noviji.
NotOnThisPlatform=Program nee raditi na %1.
OnlyOnThisPlatform=Program e raditi na %1.
-OnlyOnTheseArchitectures=Program se moe instalirati samo na izdanjima Windows-a koji rade na sledeim arhitekturama procesora:%n%n%1
+OnlyOnTheseArchitectures=Program se moe instalirati samo na izdanjima vindousa koji rade na sledeim arhitekturama procesora:%n%n%1
+MissingWOW64APIs=Izdanje vindousa koje koristite ne sadri funkcionalnost potrebnu za izvravanje 64-bitnih instalacija. Instalirajte servisni paket %1 da biste reili ovaj problem.
WinVersionTooLowError=Program zahteva %1, izdanje %2 ili novije.
WinVersionTooHighError=Program ne moete instalirati na %1 izdanju %2 ili novijem.
AdminPrivilegesRequired=Morate biti prijavljeni kao administrator da biste instalirali program.
@@ -65,16 +65,6 @@ PowerUserPrivilegesRequired=Morate biti prijavljeni kao administrator ili ovla
SetupAppRunningError=Program %1 je trenutno pokrenut.%n%nZatvorite ga i kliknite na dugme U redu da nastavite ili Otkai da napustite instalaciju.
UninstallAppRunningError=Program %1 je trenutno pokrenut.%n%nZatvorite ga i kliknite na dugme U redu da nastavite ili Otkai da napustite instalaciju.
-; *** Startup questions
-PrivilegesRequiredOverrideTitle=Odaberite nain instalacije
-PrivilegesRequiredOverrideInstruction=Odaberite nain instalacije
-PrivilegesRequiredOverrideText1=%1 moe biti instaliran za sve korisnike (zahteva administrativne privilegije) ili samo za vas.
-PrivilegesRequiredOverrideText2=%1 moe da se instalira samo za vas ili za sve korisnike (zahteva administrativne privilegije).
-PrivilegesRequiredOverrideAllUsers=Instaliraj za &sve korisnike
-PrivilegesRequiredOverrideAllUsersRecommended=Instaliraj za &sve korisnike (preporueno)
-PrivilegesRequiredOverrideCurrentUser=Instaliraj samo za &mene
-PrivilegesRequiredOverrideCurrentUserRecommended=Instaliraj samo za &mene (preporueno)
-
; *** Misc. errors
ErrorCreatingDir=Ne mogu da napravim fasciklu %1.
ErrorTooManyFilesInDir=Ne mogu da napravim datoteku u fascikli %1 jer sadri previe datoteka.
@@ -84,9 +74,9 @@ ExitSetupTitle=Napu
ExitSetupMessage=Instalacija nije zavrena. Ako sada izaete, program nee biti instaliran.%n%nInstalaciju moete pokrenuti i dovriti nekom dugom prilikom.%n%nelite li da je zatvorite?
AboutSetupMenuItem=&O programu
AboutSetupTitle=Podaci o programu
-AboutSetupMessage=%1 verzija %2%n%3%n%n%1 internet stranica:%n%4
+AboutSetupMessage=%1 verzija %2%n%3%n%n%1 matina stranica:%n%4
AboutSetupNote=
-TranslatorNote=
+TranslatorNote=Serbian translation by Rancher.
; *** Buttons
ButtonBack=< &Nazad
@@ -99,13 +89,13 @@ ButtonYesToAll=D&a za sve
ButtonNo=&Ne
ButtonNoToAll=N&e za sve
ButtonFinish=&Zavri
-ButtonBrowse=&Pretrai
-ButtonWizardBrowse=&Pretrai
+ButtonBrowse=&Potrai
+ButtonWizardBrowse=&Potrai
ButtonNewFolder=&Napravi fasciklu
; *** "Select Language" dialog messages
SelectLanguageTitle=Odabir jezika
-SelectLanguageLabel=Izaberite jezik za korienje tokom instalacije:
+SelectLanguageLabel=Izaberite jezik tokom instalacije:
; *** Common wizard text
ClickNext=Kliknite na Dalje da nastavite ili Otkai da napustite instalaciju.
@@ -153,7 +143,6 @@ WizardSelectDir=Odabir odredi
SelectDirDesc=Izaberite mesto na kom elite da instalirate [name].
SelectDirLabel3=Program e instalirati [name] u sledeu fasciklu.
SelectDirBrowseLabel=Kliknite na Dalje da nastavite. Ako elite da izaberete drugu fasciklu, kliknite na Potrai.
-DiskSpaceGBLabel=Potrebno je najmanje [gb] GB slobodnog prostora na disku.
DiskSpaceMBLabel=Potrebno je najmanje [mb] MB slobodnog prostora na disku.
CannotInstallToNetworkDrive=Ne mogu da instaliram na mrenu jedinicu.
CannotInstallToUNCPath=Ne mogu da instaliram na UNC putanju.
@@ -181,7 +170,6 @@ NoUninstallWarningTitle=Komponente ve
NoUninstallWarning=Sledee komponente ve postoje na raunaru:%n%n%1%n%nDetrikliranje ovih komponenti ih nee ukloniti.%n%nelite li da nastavite?
ComponentSize1=%1 kB
ComponentSize2=%1 MB
-ComponentsDiskSpaceGBLabel=Izabrane stavke zahtevaju najmanje [gb] GB slobodnog prostora.
ComponentsDiskSpaceMBLabel=Izabrane stavke zahtevaju najmanje [mb] MB slobodnog prostora.
; *** "Select Additional Tasks" wizard page
@@ -212,18 +200,6 @@ ReadyMemoComponents=Izabrane komponente:
ReadyMemoGroup=Fascikla u meniju Start:
ReadyMemoTasks=Dodatni zadaci:
-; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
-DownloadingLabel=Preuzimanje dodatnih datoteka...
-ButtonStopDownload=&Zaustavi preuzimanje
-StopDownload=Da li ste sigurni da elite da zaustavite preuzimanje?
-ErrorDownloadAborted=Preuzimanje je prekinuto
-ErrorDownloadFailed=Preuzimanje nije uspelo: %1 %2
-ErrorDownloadSizeFailed=Dobijanje veliine nije uspelo: %1 %2
-ErrorFileHash1=He datoteke nije uspeo: %1
-ErrorFileHash2=Neispravan he datoteke: oekivan %1, pronaen %2
-ErrorProgress=Neispravan napredak: %1 od %2
-ErrorFileSize=Neispravna veliina datoteke: oekivan %1, pronaen %2
-
; *** "Preparing to Install" wizard page
WizardPreparing=Priprema za instalaciju
PreparingDesc=Program se priprema da instalira [name] na raunar.
@@ -234,7 +210,6 @@ ApplicationsFound2=Slede
CloseApplications=&Zatvori programe
DontCloseApplications=&Ne zatvaraj programe
ErrorCloseApplications=Ne mogu da zatvorim sve programe. Pre nego to nastavite, preporuujemo vam da zatvorite sve programe koji koriste datoteke koje treba da aurira instalacioni program.
-PrepareToInstallNeedsRestart=Instalacija mora da ponovo pokrene raunar. Nakon ponovnog pokretanja raunara, ponovo pokrenite instalaciju da biste dovrili instalaciju [name].%n%nelite li da ponovo pokrenete raunar sada?
; *** "Installing" wizard page
WizardInstalling=Instaliranje
@@ -264,10 +239,7 @@ SelectDirectoryLabel=Izaberite mesto slede
; *** Installation phase messages
SetupAborted=Instalacija nije zavrena.%n%nIspravite problem i pokrenite je ponovo.
-AbortRetryIgnoreSelectAction=Odaberite radnju
-AbortRetryIgnoreRetry=&Pokuaj opet
-AbortRetryIgnoreIgnore=&Zanemari greku i nastavi
-AbortRetryIgnoreCancel=Prekini instalaciju
+EntryAbortRetryIgnore=Kliknite na Pokuaj opet da ponovite radnju, Zanemari da nastavite u svakom sluaju ili Prekini da obustavite instalaciju.
; *** Installation status messages
StatusClosingApplications=Zatvaram programe
@@ -298,24 +270,14 @@ ErrorRegWriteKey=Gre
ErrorIniEntry=Greka pri stvaranju INI unosa u datoteci %1.
; *** File copying errors
-FileAbortRetryIgnoreSkipNotRecommended=&Preskoite ovu datoteku (ne preporuuje se)
-FileAbortRetryIgnoreIgnoreNotRecommended=&Zanemari greku i nastavi (ne preporuuje se)
+FileAbortRetryIgnore=Kliknite na Pokuaj opet da ponovite radnju, Zanemari da preskoite datoteku (ne preporuuje se) ili Prekini da obustavite instalaciju.
+FileAbortRetryIgnore2=Kliknite na Pokuaj opet da ponovite radnju, Zanemari da nastavite u svakom sluaju (ne preporuuje se) ili Prekini da obustavite instalaciju.
SourceIsCorrupted=Izvorna datoteka je oteena
SourceDoesntExist=Izvorna datoteka %1 ne postoji
-ExistingFileReadOnly2=Postojea datoteka ne moe da se zameni jer je samo za itanje.
-ExistingFileReadOnlyRetry=&Uklonite atribut samo za itanje i pokuajte ponovo
-ExistingFileReadOnlyKeepExisting=&Zadrite postojeu datoteku
+ExistingFileReadOnly=Postojea datoteka je samo za itanje.%n%nKliknite na Pokuaj opet da uklonite osobinu samo za itanje i ponovite radnju, Zanemari da preskoite datoteku ili Prekini da obustavite instalaciju.
ErrorReadingExistingDest=Dolo je do greke pri pokuaju itanja postojee datoteke:
-FileExistsSelectAction=Odaberi akciju
-FileExists2=Datoteka ve postoji.
-FileExistsOverwriteExisting=&Zameni postojeu datoteku
-FileExistsKeepExisting=&Zadri postojeu datoteku
-FileExistsOverwriteOrKeepAll=&Uradi ovo i ubudue
-ExistingFileNewerSelectAction=Odaberi akciju
-ExistingFileNewer2=Postojea datoteka je novija od one koju treba instalirati.
-ExistingFileNewerOverwriteExisting=&Zameni postojeu datoteku
-ExistingFileNewerKeepExisting=&Zadri postojeu datoteku (preporueno)
-ExistingFileNewerOverwriteOrKeepAll=&Uradi ovo i ubudue
+FileExists=Datoteka ve postoji.%n%nelite li da je zamenite?
+ExistingFileNewer=Postojea datoteka je novija od one koju treba postaviti. Preporuujemo vam da zadrite postojeu datoteku.%n%nelite li to da uradite?
ErrorChangingAttr=Dolo je do greke pri izmeni osobine sledee datoteke:
ErrorCreatingTemp=Dolo je do greke pri stvaranju datoteke u odredinoj fascikli:
ErrorReadingSource=Dolo je do greke pri itanju izvorne datoteke:
@@ -327,16 +289,6 @@ ErrorRegisterServer=Ne mogu da upi
ErrorRegSvr32Failed=RegSvr32 nije uspeo. Greka %1
ErrorRegisterTypeLib=Ne mogu da upiem biblioteku tipova: %1
-; *** Uninstall display name markings
-; used for example as 'My Program (32-bit)'
-UninstallDisplayNameMark=%1 (%2)
-; used for example as 'My Program (32-bit, All users)'
-UninstallDisplayNameMarks=%1 (%2, %3)
-UninstallDisplayNameMark32Bit=32-bit
-UninstallDisplayNameMark64Bit=64-bit
-UninstallDisplayNameMarkAllUsers=Svi korisnici
-UninstallDisplayNameMarkCurrentUser=Trenutni korisnik
-
; *** Post-installation errors
ErrorOpeningReadme=Dolo je do greke pri otvaranju tekstualne datoteke.
ErrorRestartingComputer=Ne mogu ponovo da pokrenem raunar. Uradite to sami.
diff --git a/installer/innosetup/Languages/Sinhala.islu b/Greenshot/releases/innosetup/Languages/Sinhala.islu
similarity index 100%
rename from installer/innosetup/Languages/Sinhala.islu
rename to Greenshot/releases/innosetup/Languages/Sinhala.islu
diff --git a/installer/innosetup/Languages/Swedish.isl b/Greenshot/releases/innosetup/Languages/Swedish.isl
similarity index 89%
rename from installer/innosetup/Languages/Swedish.isl
rename to Greenshot/releases/innosetup/Languages/Swedish.isl
index f458ca651..f89324798 100644
--- a/installer/innosetup/Languages/Swedish.isl
+++ b/Greenshot/releases/innosetup/Languages/Swedish.isl
@@ -1,4 +1,4 @@
-; *** Inno Setup version 6.1.0+ Swedish messages ***
+; *** Inno Setup version 6.0.0+ Swedish messages ***
;
; To download user-contributed translations of this file, go to:
; http://www.jrsoftware.org/files/istrans/
@@ -151,9 +151,6 @@ IncorrectPassword=L
; *** "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.
@@ -163,9 +160,6 @@ 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.
@@ -176,9 +170,6 @@ InfoAfterClickLabel=N
; *** "User Information" wizard page
-
-
-
WizardUserInfo=Anvndarinformation
UserInfoDesc=Var god och fyll i fljande uppgifter.
UserInfoName=&Namn:
@@ -189,14 +180,10 @@ UserInfoNameRequired=Du m
; *** "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.
@@ -215,9 +202,6 @@ 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.
@@ -225,24 +209,17 @@ FullInstallation=Fullst
; 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.
@@ -250,9 +227,6 @@ SelectTasksLabel2=Markera ytterligare uppgifter att utf
; *** "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.
@@ -266,9 +240,6 @@ 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.
@@ -279,23 +250,10 @@ 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].
@@ -305,23 +263,16 @@ ApplicationsFound2=F
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.
@@ -334,24 +285,15 @@ NoRadio=&Nej, jag startar sj
; 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:
@@ -361,9 +303,6 @@ SelectDirectoryLabel=Var god ange s
; *** Installation phase messages
-
-
-
SetupAborted=Installationen slutfrdes inte.%n%nVar god rtta till felet och kr installationen igen.
AbortRetryIgnoreSelectAction=Vlj tgrd
AbortRetryIgnoreRetry=&Frsk igen
@@ -373,9 +312,6 @@ AbortRetryIgnoreCancel=Avbryt installationen
; *** Installation status messages
-
-
-
StatusClosingApplications=Stnger program...
StatusCreateDirs=Skapar kataloger...
StatusExtractFiles=Packar upp filer...
@@ -391,9 +327,6 @@ StatusRollback=
; *** Misc. errors
-
-
-
ErrorInternal2=Internt fel: %1
ErrorFunctionFailedNoCode=%1 misslyckades
ErrorFunctionFailed=%1 misslyckades; kod %2
@@ -403,9 +336,6 @@ ErrorExecutingProgram=Kan inte k
; *** 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
@@ -413,9 +343,6 @@ 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)
@@ -425,16 +352,8 @@ ExistingFileReadOnly2=Den befintliga filen kunde inte bytas ut eftersom den
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
+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:
@@ -455,18 +374,12 @@ UninstallDisplayNameMarkCurrentUser=Nuvarande anv
; *** 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
@@ -483,9 +396,6 @@ UninstallDataCorrupted=Filen "%1"
; *** 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:
@@ -496,9 +406,6 @@ StatusUninstalling=Avinstallerar %1...
; *** Shutdown block reasons
-
-
-
ShutdownBlockReasonInstallingApp=Installerar %1.
ShutdownBlockReasonUninstallingApp=Avinstallerar %1.
@@ -508,14 +415,11 @@ ShutdownBlockReasonUninstallingApp=Avinstallerar %1.
-
-
-
[CustomMessages]
NameAndVersion=%1 version %2
AdditionalIcons=terstende ikoner:
-CreateDesktopIcon=Skapa en genvg p skrivbordet
-CreateQuickLaunchIcon=Skapa en genvg i Snabbstartfltet
+CreateDesktopIcon=Skapa en ikon p skrivbordet
+CreateQuickLaunchIcon=Skapa en ikon i Snabbstartfltet
ProgramOnTheWeb=%1 p Webben
UninstallProgram=Avinstallera %1
LaunchProgram=Starta %1
diff --git a/installer/innosetup/Languages/Tatar.isl b/Greenshot/releases/innosetup/Languages/Tatar.isl
similarity index 100%
rename from installer/innosetup/Languages/Tatar.isl
rename to Greenshot/releases/innosetup/Languages/Tatar.isl
diff --git a/installer/innosetup/Languages/Thai.isl b/Greenshot/releases/innosetup/Languages/Thai.isl
similarity index 100%
rename from installer/innosetup/Languages/Thai.isl
rename to Greenshot/releases/innosetup/Languages/Thai.isl
diff --git a/Greenshot/releases/innosetup/Languages/Uyghur.islu b/Greenshot/releases/innosetup/Languages/Uyghur.islu
new file mode 100644
index 000000000..1f702c7a5
--- /dev/null
+++ b/Greenshot/releases/innosetup/Languages/Uyghur.islu
@@ -0,0 +1,338 @@
+; *** Inno Setup version 5.5.3+ Uyghur messages ***
+; Translated by Irshat ghalib [ uqkun09@msn.cn ]
+; 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=ئۇيغۇرچە
+LanguageID=$0480
+LanguageCodePage=0
+
+;If the language you are translating to requires special font faces or
+; sizes, uncomment any of the following entries and change them accordingly.
+DialogFontName=ALKATIP
+;DialogFontSize=12
+WelcomeFontName=ALKATIP
+;WelcomeFontSize=18
+TitleFontName=ALKATIP
+;TitleFontSize=35
+CopyrightFontName=ALKATIP
+;CopyrightFontSize=11
+
+[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=ئۈنۈمسىز بۇيرۇق پارامېتىرى:%n%n%1
+SetupAlreadyRunning=قاچىلاش يېتەكچىسى ئىجرا بولۇۋاتىدۇ.
+WindowsVersionNotSupported=دېتال بۇ كومپيۇتېرنىڭ نەشرىنى قوللىمايدۇ.
+WindowsServicePackRequired=دېتال %1 Service Pack %2 ياكى ئۇنىڭدىن يۇقىرى نەشرىنى تەلەپ قىلىدۇ.
+NotOnThisPlatform=دېتال %1 دە ئىجرا بولمايدۇ.
+OnlyOnThisPlatform=دېتال چوقۇم %1دە ئىجرا بولىدۇ.
+OnlyOnTheseArchitectures=دېتال پەقەت تۆۋەندىكى CPU بولغان Windows نەشرىگە قاچىلىغىلى بولىدۇ:%n%n%1
+MissingWOW64APIs=كومپيۇتېرىڭىزدا Windows نىڭ 64 لىك دېتاللىرى ئىجرا بولمايدۇ.Service Pack %1 ئارقىلىق مەسىلىڭىزنى ھەل قىلىڭ.
+WinVersionTooLowError=دېتال %2 نەشرىدىن يۇقىرى بولغان %1 نى تەلەپ قىلىدۇ.
+WinVersionTooHighError=دېتال %2 نەشرى ياكى %1 دىن يۇقىرى نەشىرىدە ئىجرا بولىدۇ.
+AdminPrivilegesRequired=باشقۇرغۇچىلىق سالاھىيتىدە كىرگەندىن كېيىن ئاندىن بۇ دېتالنى قاچىلالايسىز.
+PowerUserPrivilegesRequired=باشقۇرغۇچىلىق سالاھىيتىدە ياكى ئۇنىڭدىن يۇقىرى سالاھىيەتتە كىرگەندىن كېيىن ئاندىن بۇ دېتالنى قاچىلالايسىز.
+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:\دېتال%n%nياكى تۆۋەندىكى فورماتتىكى UNCيولى:%n%n\\مۇلازىمىتېر نامى\ئورتاقلاشقان مۇندەرىجە نامى
+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)
+ErrorCloseApplications=قاچىلاش يېتەكچىسى بارلىق پىروگراممىلارنى ئاپتوماتىك ئۆچۈرەلمىدى. كېيىنكى باسقۇچقا ئۆتۈشتى ئاۋۋال بۇ پىروگراممىلارنى چوقۇم ئۆچۈرۋېتىشىڭىز كېرەك.
+
+; *** "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%nمەلۇم تۈرلەرنى ئۆچۈرۈش جەريانىدا ئۆچۈرەلمىدى. بۇلارنى قولدا ئۆچۈرۈۋەتسىڭىز بولىدۇ.
+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شۇنداقتىمۇ داۋاملاشتۇرامسىز؟
\ No newline at end of file
diff --git a/installer/innosetup/Languages/Uzbek.isl b/Greenshot/releases/innosetup/Languages/Uzbek.isl
similarity index 100%
rename from installer/innosetup/Languages/Uzbek.isl
rename to Greenshot/releases/innosetup/Languages/Uzbek.isl
diff --git a/installer/innosetup/Languages/Valencian.isl b/Greenshot/releases/innosetup/Languages/Valencian.isl
similarity index 100%
rename from installer/innosetup/Languages/Valencian.isl
rename to Greenshot/releases/innosetup/Languages/Valencian.isl
diff --git a/installer/innosetup/Languages/Vietnamese.isl b/Greenshot/releases/innosetup/Languages/Vietnamese.isl
similarity index 100%
rename from installer/innosetup/Languages/Vietnamese.isl
rename to Greenshot/releases/innosetup/Languages/Vietnamese.isl
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/chinese.ini b/Greenshot/releases/innosetup/scripts/isxdl/chinese.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/chinese.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/chinese.ini
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/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/installer/innosetup/scripts/isxdl/italian.ini b/Greenshot/releases/innosetup/scripts/isxdl/italian.ini
similarity index 100%
rename from installer/innosetup/scripts/isxdl/italian.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/italian.ini
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 100%
rename from installer/innosetup/scripts/isxdl/russian.ini
rename to Greenshot/releases/innosetup/scripts/isxdl/russian.ini
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/lang/chinese.iss b/Greenshot/releases/innosetup/scripts/lang/chinese.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/chinese.iss
rename to Greenshot/releases/innosetup/scripts/lang/chinese.iss
diff --git a/installer/innosetup/scripts/lang/dutch.iss b/Greenshot/releases/innosetup/scripts/lang/dutch.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/dutch.iss
rename to Greenshot/releases/innosetup/scripts/lang/dutch.iss
diff --git a/installer/innosetup/scripts/lang/english.iss b/Greenshot/releases/innosetup/scripts/lang/english.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/english.iss
rename to Greenshot/releases/innosetup/scripts/lang/english.iss
diff --git a/installer/innosetup/scripts/lang/french.iss b/Greenshot/releases/innosetup/scripts/lang/french.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/french.iss
rename to Greenshot/releases/innosetup/scripts/lang/french.iss
diff --git a/installer/innosetup/scripts/lang/german.iss b/Greenshot/releases/innosetup/scripts/lang/german.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/german.iss
rename to Greenshot/releases/innosetup/scripts/lang/german.iss
diff --git a/installer/innosetup/scripts/lang/italian.iss b/Greenshot/releases/innosetup/scripts/lang/italian.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/italian.iss
rename to Greenshot/releases/innosetup/scripts/lang/italian.iss
diff --git a/installer/innosetup/scripts/lang/japanese.iss b/Greenshot/releases/innosetup/scripts/lang/japanese.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/japanese.iss
rename to Greenshot/releases/innosetup/scripts/lang/japanese.iss
diff --git a/installer/innosetup/scripts/lang/polish.iss b/Greenshot/releases/innosetup/scripts/lang/polish.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/polish.iss
rename to Greenshot/releases/innosetup/scripts/lang/polish.iss
diff --git a/installer/innosetup/scripts/lang/russian.iss b/Greenshot/releases/innosetup/scripts/lang/russian.iss
similarity index 100%
rename from installer/innosetup/scripts/lang/russian.iss
rename to Greenshot/releases/innosetup/scripts/lang/russian.iss
diff --git a/installer/innosetup/scripts/products.iss b/Greenshot/releases/innosetup/scripts/products.iss
similarity index 100%
rename from installer/innosetup/scripts/products.iss
rename to Greenshot/releases/innosetup/scripts/products.iss
diff --git a/installer/innosetup/scripts/products.pas b/Greenshot/releases/innosetup/scripts/products.pas
similarity index 100%
rename from installer/innosetup/scripts/products.pas
rename to Greenshot/releases/innosetup/scripts/products.pas
diff --git a/installer/innosetup/scripts/products/directxruntime.iss b/Greenshot/releases/innosetup/scripts/products/directxruntime.iss
similarity index 100%
rename from installer/innosetup/scripts/products/directxruntime.iss
rename to Greenshot/releases/innosetup/scripts/products/directxruntime.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx11.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx11.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx11lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11lp.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx11lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11lp.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx11sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx11sp1.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx11sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx11sp1.iss
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 100%
rename from installer/innosetup/scripts/products/dotnetfx20lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20lp.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx20sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp1lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1lp.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx20sp1lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp1lp.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp2.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx20sp2.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx20sp2lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2lp.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx20sp2lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx20sp2lp.iss
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 100%
rename from installer/innosetup/scripts/products/dotnetfx35lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35lp.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx35sp1.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx35sp1.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx35sp1lp.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1lp.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx35sp1lp.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx35sp1lp.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx40client.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx40client.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx40client.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx40client.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx40full.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx40full.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx40full.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx40full.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx45.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx45.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx45.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx45.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx46.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx46.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx46.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx46.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx47.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx47.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx47.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx47.iss
diff --git a/installer/innosetup/scripts/products/dotnetfx48.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfx48.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfx48.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfx48.iss
diff --git a/installer/innosetup/scripts/products/dotnetfxversion.iss b/Greenshot/releases/innosetup/scripts/products/dotnetfxversion.iss
similarity index 100%
rename from installer/innosetup/scripts/products/dotnetfxversion.iss
rename to Greenshot/releases/innosetup/scripts/products/dotnetfxversion.iss
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 100%
rename from installer/innosetup/scripts/products/ie6.iss
rename to Greenshot/releases/innosetup/scripts/products/ie6.iss
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 100%
rename from installer/innosetup/scripts/products/jet4sp8.iss
rename to Greenshot/releases/innosetup/scripts/products/jet4sp8.iss
diff --git a/installer/innosetup/scripts/products/kb835732.iss b/Greenshot/releases/innosetup/scripts/products/kb835732.iss
similarity index 100%
rename from installer/innosetup/scripts/products/kb835732.iss
rename to Greenshot/releases/innosetup/scripts/products/kb835732.iss
diff --git a/installer/innosetup/scripts/products/mdac28.iss b/Greenshot/releases/innosetup/scripts/products/mdac28.iss
similarity index 100%
rename from installer/innosetup/scripts/products/mdac28.iss
rename to Greenshot/releases/innosetup/scripts/products/mdac28.iss
diff --git a/installer/innosetup/scripts/products/msi20.iss b/Greenshot/releases/innosetup/scripts/products/msi20.iss
similarity index 100%
rename from installer/innosetup/scripts/products/msi20.iss
rename to Greenshot/releases/innosetup/scripts/products/msi20.iss
diff --git a/installer/innosetup/scripts/products/msi31.iss b/Greenshot/releases/innosetup/scripts/products/msi31.iss
similarity index 100%
rename from installer/innosetup/scripts/products/msi31.iss
rename to Greenshot/releases/innosetup/scripts/products/msi31.iss
diff --git a/installer/innosetup/scripts/products/msi45.iss b/Greenshot/releases/innosetup/scripts/products/msi45.iss
similarity index 100%
rename from installer/innosetup/scripts/products/msi45.iss
rename to Greenshot/releases/innosetup/scripts/products/msi45.iss
diff --git a/installer/innosetup/scripts/products/msiproduct.iss b/Greenshot/releases/innosetup/scripts/products/msiproduct.iss
similarity index 100%
rename from installer/innosetup/scripts/products/msiproduct.iss
rename to Greenshot/releases/innosetup/scripts/products/msiproduct.iss
diff --git a/installer/innosetup/scripts/products/sql2005express.iss b/Greenshot/releases/innosetup/scripts/products/sql2005express.iss
similarity index 100%
rename from installer/innosetup/scripts/products/sql2005express.iss
rename to Greenshot/releases/innosetup/scripts/products/sql2005express.iss
diff --git a/installer/innosetup/scripts/products/sql2008express.iss b/Greenshot/releases/innosetup/scripts/products/sql2008express.iss
similarity index 100%
rename from installer/innosetup/scripts/products/sql2008express.iss
rename to Greenshot/releases/innosetup/scripts/products/sql2008express.iss
diff --git a/installer/innosetup/scripts/products/sqlcompact35sp2.iss b/Greenshot/releases/innosetup/scripts/products/sqlcompact35sp2.iss
similarity index 100%
rename from installer/innosetup/scripts/products/sqlcompact35sp2.iss
rename to Greenshot/releases/innosetup/scripts/products/sqlcompact35sp2.iss
diff --git a/installer/innosetup/scripts/products/stringversion.iss b/Greenshot/releases/innosetup/scripts/products/stringversion.iss
similarity index 100%
rename from installer/innosetup/scripts/products/stringversion.iss
rename to Greenshot/releases/innosetup/scripts/products/stringversion.iss
diff --git a/installer/innosetup/scripts/products/vcredist2005.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2005.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2005.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2005.iss
diff --git a/installer/innosetup/scripts/products/vcredist2008.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2008.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2008.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2008.iss
diff --git a/installer/innosetup/scripts/products/vcredist2010.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2010.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2010.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2010.iss
diff --git a/installer/innosetup/scripts/products/vcredist2012.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2012.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2012.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2012.iss
diff --git a/installer/innosetup/scripts/products/vcredist2013.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2013.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2013.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2013.iss
diff --git a/installer/innosetup/scripts/products/vcredist2015.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2015.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2015.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2015.iss
diff --git a/installer/innosetup/scripts/products/vcredist2017.iss b/Greenshot/releases/innosetup/scripts/products/vcredist2017.iss
similarity index 100%
rename from installer/innosetup/scripts/products/vcredist2017.iss
rename to Greenshot/releases/innosetup/scripts/products/vcredist2017.iss
diff --git a/installer/innosetup/scripts/products/wic.iss b/Greenshot/releases/innosetup/scripts/products/wic.iss
similarity index 100%
rename from installer/innosetup/scripts/products/wic.iss
rename to Greenshot/releases/innosetup/scripts/products/wic.iss
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/installer/innosetup/setup.iss b/Greenshot/releases/innosetup/setup.iss
similarity index 67%
rename from installer/innosetup/setup.iss
rename to Greenshot/releases/innosetup/setup.iss
index fa358ee7b..3195d1f55 100644
--- a/installer/innosetup/setup.iss
+++ b/Greenshot/releases/innosetup/setup.iss
@@ -1,16 +1,12 @@
#define ExeName "Greenshot"
#define Version GetEnv('BuildVersionSimple')
#define FileVersion GetEnv('AssemblyInformationalVersion')
-#define BaseDir "..\..\src"
-#define GreenshotProjectDir "..\..\src\Greenshot"
-#define LanguagesDir "..\..\src\Greenshot\Languages"
+#define BaseDir "..\..\.."
+#define ReleaseDir "..\..\bin\Release\net472"
#define BinDir "bin\Release\net472"
-#define ReleaseDir "..\..\src\Greenshot\bin\Release\net472"
-#define PluginDir "..\..\src\Greenshot\bin\Release\net472\Plugins"
-#define CertumThumbprint GetEnv('CertumThumbprint')
; Include the scripts to install .NET Framework
-; See https://www.codeproject.com/KB/install/dotnetfx_innosetup_instal.aspx
+; 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"
@@ -22,17 +18,15 @@
[Files]
Source: {#ReleaseDir}\Greenshot.exe; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#ReleaseDir}\Greenshot.Base.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#ReleaseDir}\Greenshot.Editor.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: {#ReleaseDir}\GreenshotPlugin.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
Source: {#ReleaseDir}\Greenshot.exe.config; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
Source: {#ReleaseDir}\log4net.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#ReleaseDir}\Dapplo.*.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#ReleaseDir}\System.*.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: {#ReleaseDir}\Dapplo.Http*.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
+Source: {#ReleaseDir}\Dapplo.Log.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
Source: {#ReleaseDir}\Svg.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
Source: {#ReleaseDir}\Fizzler.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#ReleaseDir}\HtmlAgilityPack.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
Source: {#ReleaseDir}\Newtonsoft.Json.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion
-Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion
+Source: ..\..\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion
Source: {#ReleaseDir}\checksum.SHA256; 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
@@ -40,78 +34,85 @@ Source: ..\additional_files\license.txt; DestDir: {app}; Components: greenshot;
Source: ..\additional_files\readme.txt; DestDir: {app}; Components: greenshot; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion
; Core language files
-Source: {#LanguagesDir}\*nl-NL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*en-US*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*de-DE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion;
+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: {#LanguagesDir}\*ar-SY*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\arSY; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*ca-CA*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\caCA; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*cs-CZ*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\csCZ; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*da-DK*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\daDK; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*de-x-franconia*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\dexfranconia; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*el-GR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\elGR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*es-ES*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\esES; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*et-EE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\etEE; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*fa-IR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\faIR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*fi-FI*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\fiFI; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*fr-FR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\frFR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*fr-QC*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\frQC; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*he-IL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\heIL; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*hu-HU*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\huHU; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*id-ID*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\idID; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*it-IT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\itIT; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*ja-JP*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\jaJP; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*ko-KR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\koKR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*kab-DZ*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\kabDZ; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*lt-LT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ltLT; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*lv-LV*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\lvLV; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*nn-NO*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\nnNO; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*pl-PL*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\plPL; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*pt-BR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ptBR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*pt-PT*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ptPT; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*ro-RO*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\roRO; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*ru-RU*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ruRU; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*sk-SK*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\skSK; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*sl-SI*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\slSI; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*sr-RS*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\srRS; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*sv-SE*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\svSE; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*tr-TR*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\trTR; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*uk-UA*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\ukUA; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*vi-VN*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\viVN; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*zh-CN*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhCN; Flags: overwritereadonly ignoreversion replacesameversion;
-Source: {#LanguagesDir}\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhTW; Flags: overwritereadonly ignoreversion replacesameversion;
+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: {#PluginDir}\Greenshot.Plugin.Office\Greenshot.Plugin.Office.dll; DestDir: {app}\Plugins\Office; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotOfficePlugin\{#BinDir}\GreenshotOfficePlugin.dll; DestDir: {app}\Plugins\GreenshotOfficePlugin; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+;OCR Plugin
+Source: {#BaseDir}\GreenshotOCRPlugin\{#BinDir}\GreenshotOCRPlugin.dll; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotOCRPlugin\Languages\language_ocr*.xml; DestDir: {app}\Languages\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotOCRCommand\{#BinDir}\GreenshotOCRCommand.exe; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotOCRCommand\{#BinDir}\GreenshotOCRCommand.exe.config; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
;JIRA Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Jira\*Jira*.dll; DestDir: {app}\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Jira\Languages\language_jira*.xml; DestDir: {app}\Languages\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotJiraPlugin\{#BinDir}\GreenshotJiraPlugin.dll; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotJiraPlugin\{#BinDir}\Dapplo.Jira*.dll; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotJiraPlugin\Languages\language_jira*.xml; DestDir: {app}\Languages\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
;Imgur Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Imgur\Greenshot.Plugin.Imgur.dll; DestDir: {app}\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Imgur\Languages\language_imgur*.xml; DestDir: {app}\Languages\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotImgurPlugin\{#BinDir}\GreenshotImgurPlugin.dll; DestDir: {app}\Plugins\GreenshotImgurPlugin; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotImgurPlugin\Languages\language_imgur*.xml; DestDir: {app}\Languages\Plugins\GreenshotImgurPlugin; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion;
;Box Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Box\Greenshot.Plugin.Box.dll; DestDir: {app}\Plugins\Box; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Box\Languages\language_box*.xml; DestDir: {app}\Languages\Plugins\Box; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotBoxPlugin\{#BinDir}\GreenshotBoxPlugin.dll; DestDir: {app}\Plugins\GreenshotBoxPlugin; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotBoxPlugin\Languages\language_box*.xml; DestDir: {app}\Languages\Plugins\GreenshotBoxPlugin; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion;
;DropBox Plugin
-Source: {#PluginDir}\Greenshot.Plugin.DropBox\Greenshot.Plugin.DropBox.dll; DestDir: {app}\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.DropBox\Languages\language_dropbox*.xml; DestDir: {app}\Languages\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotDropBoxPlugin\{#BinDir}\GreenshotDropboxPlugin.dll; DestDir: {app}\Plugins\GreenshotDropBoxPlugin; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotDropBoxPlugin\Languages\language_dropbox*.xml; DestDir: {app}\Languages\Plugins\GreenshotDropBoxPlugin; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion;
;Flickr Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Flickr\Greenshot.Plugin.Flickr.dll; DestDir: {app}\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Flickr\Languages\language_flickr*.xml; DestDir: {app}\Languages\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotFlickrPlugin\{#BinDir}\GreenshotFlickrPlugin.dll; DestDir: {app}\Plugins\GreenshotFlickrPlugin; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotFlickrPlugin\Languages\language_flickr*.xml; DestDir: {app}\Languages\Plugins\GreenshotFlickrPlugin; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion;
;Photobucket Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Photobucket\Greenshot.Plugin.Photobucket.dll; DestDir: {app}\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Photobucket\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotPhotobucketPlugin\{#BinDir}\GreenshotPhotobucketPlugin.dll; DestDir: {app}\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotPhotobucketPlugin\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion;
+;Picasa Plugin
+Source: {#BaseDir}\GreenshotPicasaPlugin\{#BinDir}\GreenshotPicasaPlugin.dll; DestDir: {app}\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotPicasaPlugin\Languages\language_picasa*.xml; DestDir: {app}\Languages\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly ignoreversion replacesameversion;
;Confluence Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Confluence\Greenshot.Plugin.Confluence.dll; DestDir: {app}\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.Confluence\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotConfluencePlugin\{#BinDir}\GreenshotConfluencePlugin.dll; DestDir: {app}\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotConfluencePlugin\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion;
;ExternalCommand Plugin
-Source: {#PluginDir}\Greenshot.Plugin.ExternalCommand\Greenshot.Plugin.ExternalCommand.dll; DestDir: {app}\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#BaseDir}\Greenshot.Plugin.ExternalCommand\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotExternalCommandPlugin\{#BinDir}\GreenshotExternalCommandPlugin.dll; DestDir: {app}\Plugins\GreenshotExternalCommandPlugin; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
+Source: {#BaseDir}\GreenshotExternalCommandPlugin\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\GreenshotExternalCommandPlugin; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion;
;Win 10 Plugin
-Source: {#PluginDir}\Greenshot.Plugin.Win10\Greenshot.Plugin.Win10.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-Source: {#PluginDir}\Greenshot.Plugin.Win10\Microsoft.Toolkit.Uwp.Notifications.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
-
+Source: {#BaseDir}\GreenshotWin10Plugin\{#BinDir}\GreenshotWin10Plugin.dll; 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
@@ -119,35 +120,29 @@ AppId={#ExeName}
AppName={#ExeName}
AppMutex=F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08
AppPublisher={#ExeName}
-AppPublisherURL=https://getgreenshot.org
-AppSupportURL=https://getgreenshot.org
-AppUpdatesURL=https://getgreenshot.org
+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={autopf}\{#ExeName}
+DefaultDirName={code:DefDirRoot}\{#ExeName}
DefaultGroupName={#ExeName}
InfoBeforeFile=..\additional_files\readme.txt
LicenseFile=..\additional_files\license.txt
LanguageDetectionMethod=uilanguage
MinVersion=6.1sp1
+OutputBaseFilename={#ExeName}-INSTALLER-{#Version}-UNSTABLE
OutputDir=..\
-; user may choose between all-users vs. current-user installation in a dialog or by using the /ALLUSERS flag (on the command line)
-; in registry section, HKA will take care of the appropriate root key (HKLM vs. HKCU), see https://jrsoftware.org/ishelp/index.php?topic=admininstallmode
-PrivilegesRequiredOverridesAllowed=dialog
-; admin privileges not required, unless user chooses all-users installation
-; the installer will ask for elevation if needed
PrivilegesRequired=lowest
-SetupIconFile=..\..\src\Greenshot\icons\applicationIcon\icon.ico
-#if CertumThumbprint != ""
- OutputBaseFilename={#ExeName}-INSTALLER-{#Version}-UNSTABLE
- SignTool=SignTool sign /sha1 "{#CertumThumbprint}" /tr http://time.certum.pl /td sha256 /fd sha256 /v $f
- SignedUninstaller=yes
-#else
- OutputBaseFilename={#ExeName}-INSTALLER-{#Version}-UNSTABLE-UNSIGNED
-#endif
+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}
@@ -159,15 +154,12 @@ VersionInfoVersion={#Version}
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()
-Root: HKCU64; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror; Check: IsWin64()
-Root: HKLM64; 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
@@ -178,16 +170,22 @@ Root: HKLM; Subkey: Software\Classes\.greenshot; ValueType: none; ValueName: {#E
Root: HKLM; Subkey: Software\Classes\Greenshot; ValueType: none; ValueName: {#ExeName}; Flags: deletevalue noerror;
; Create the startup entries if requested to do so
-Root: HKA; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: {#ExeName}; ValueData: """{app}\{#ExeName}.exe"""; Flags: uninsdeletevalue noerror; Tasks: startup
+; 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
-Root: HKA; Subkey: Software\Classes\.greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot"; Flags: uninsdeletevalue noerror
-Root: HKA; Subkey: Software\Classes\Greenshot; ValueType: string; ValueName: ""; ValueData: "Greenshot File"; Flags: uninsdeletevalue noerror
-Root: HKA; Subkey: Software\Classes\Greenshot\DefaultIcon; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE,0"""; Flags: uninsdeletevalue noerror
-Root: HKA; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Flags: uninsdeletevalue noerror
-
-; Disable the default PRTSCR Snipping Tool in Windows 11
-Root: HKCU; Subkey: Control Panel\Keyboard; ValueType: dword; ValueName: "PrintScreenKeyForSnippingEnabled"; ValueData: "0"; Flags: uninsdeletevalue; Check: ShouldDisableSnippingTool
+; 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}; AppUserModelID: "{#ExeName}"
@@ -219,7 +217,7 @@ Name: startup; Description: {cm:startup}
dexfranconia=Frängisch (Deutsch)
arSY=العربية
caCA=Català
-csCZ=Čeština
+csCZ=Ceština
daDK=Dansk
elGR=ελληνικά
esES=Español
@@ -259,39 +257,41 @@ en.default=Default installation
en.dropbox=Dropbox plug-in
en.externalcommand=Open with external command plug-in
en.flickr=Flickr plug-in
-en.imgur=Imgur plug-in (See: https://imgur.com)
+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.office=Microsoft Office plug-in
en.optimize=Optimizing performance, this may take a while.
en.photobucket=Photobucket plug-in
+en.picasa=Picasa plug-in
en.startgreenshot=Start {#ExeName}
en.startup=Start {#ExeName} with Windows start
en.win10=Windows 10 plug-in
en.UninstallIconDescription=Uninstall
-en.ShowLicense=Show license
-en.ShowReadme=Show Readme
-en.disablewin11snippingtool=Disable Win11 default PrtScr snipping tool
+en.ShowLicense=Show licenze
+en.ShowReadme=how Readme
de.confluence=Confluence Plug-in
de.default=Standard installation
de.externalcommand=Externes Kommando Plug-in
-de.imgur=Imgur Plug-in (Siehe: https://imgur.com)
+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.office=Microsoft Office Plug-in
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
-de.disablewin11snippingtool=Deaktiviere das Standard Windows 11 Snipping Tool auf "Druck"
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 https://imgur.com)
+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
@@ -300,9 +300,10 @@ es.win10=Extensión para Windows 10
fi.confluence=Confluence-liitännäinen
fi.default=${default}
fi.externalcommand=Avaa Ulkoinen komento-liitännäisellä
-fi.imgur=Imgur-liitännäinen (Katso: https://imgur.com)
+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.office=Microsoft-Office-liitännäinen
fi.optimize=Optimoidaan suorituskykyä, tämä voi kestää hetken.
fi.startgreenshot=Käynnistä {#ExeName}
@@ -312,9 +313,10 @@ fi.win10=Windows 10-liitännäinen
fr.confluence=Greffon Confluence
fr.default=${default}
fr.externalcommand=Ouvrir avec le greffon de commande externe
-fr.imgur=Greffon Imgur (Voir: https://imgur.com)
+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.office=Greffon Microsoft Office
fr.optimize=Optimisation des performances, Ceci peut prendre un certain temps.
fr.startgreenshot=Démarrer {#ExeName}
@@ -327,12 +329,14 @@ it.default=Installazione predefinita
it.dropbox=Plugin Dropbox
it.externalcommand=Apri con comando esterno plugin
it.flickr=Plugin Flickr
-it.imgur=Plugin Imgur (vedi: https://imgur.com)
+it.imgur=Plugin Imgur (vedi: http://imgur.com)
it.jira=Plugin Jira
it.language=Lingue aggiuntive
+it.ocr=Plugin OCR (richiede Microsoft Office Document Imaging (MODI))
it.office=Plugin Microsoft Office
it.optimize=Ottimizzazione prestazioni (può richiedere tempo).
it.photobucket=Plugin Photobucket
+it.picasa=Plugin Picasa
it.startgreenshot=Esegui {#ExeName}
it.startup=Esegui {#ExeName} all''avvio di Windows
it.win10=Plugin Windows 10
@@ -379,9 +383,10 @@ it.zhTW=Cinese (Taiwan)
lt.confluence=Confluence spraudnis
lt.default=${default}
lt.externalcommand=Pielāgotu darbību spraudnis
-lt.imgur=Imgur spraudnis (Vairāk šeit: https://imgur.com)
+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.office=Microsoft Office spraudnis
lt.optimize=Uzlaboju veikstpēju, tas prasīs kādu laiciņu.
lt.startgreenshot=Palaist {#ExeName}
@@ -391,9 +396,10 @@ lt.win10=Windows 10 spraudnis
lt.confluence=Confluence spraudnis
lt.default=${default}
lt.externalcommand=Pielāgotu darbību spraudnis
-lt.imgur=Imgur spraudnis (Vairāk šeit: https://imgur.com)
+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.office=Microsoft Office spraudnis
lt.optimize=Uzlaboju veikstpēju, tas prasīs kādu laiciņu.
lt.startgreenshot=Palaist {#ExeName}
@@ -403,9 +409,10 @@ lt.win10=Windows 10 spraudnis
nl.confluence=Confluence plug-in
nl.default=Standaardinstallatie
nl.externalcommand=Openen met extern commando plug-in
-nl.imgur=Imgur plug-in (zie: https://imgur.com)
+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.office=Microsoft Office plug-in
nl.optimize=Prestaties verbeteren, even geduld.
nl.startgreenshot={#ExeName} starten
@@ -415,9 +422,10 @@ nl.win10=Windows 10 plug-in
nn.confluence=Confluence-tillegg
nn.default=Default installation
nn.externalcommand=Tillegg for å opne med ekstern kommando
-nn.imgur=Imgur-tillegg (sjå https://imgur.com)
+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.office=Microsoft Office Tillegg
nn.optimize=Optimaliserar ytelse, dette kan ta litt tid...
nn.startgreenshot=Start {#ExeName}
@@ -430,6 +438,7 @@ ru.externalcommand=Открыть с плагином с помощью внеш
ru.imgur=Плагин Imgur (смотрите https://imgur.com/)
ru.jira=Плагин Jira
ru.language=Дополнительные языки
+ru.ocr=Плагин OCR (требуется Microsoft Office Document Imaging (MODI))
ru.office=Плагин Microsoft Office
ru.optimize=Идет оптимизация производительности, это может занять некоторое время.
ru.startgreenshot=Запустить {#ExeName}
@@ -439,9 +448,10 @@ ru.win10=Плагин Windows 10
sr.confluence=Прикључак за Конфлуенс
sr.default=${default}
sr.externalcommand=Отвори са прикључком за спољне наредбе
-sr.imgur=Прикључак за Имиџер (https://imgur.com)
+sr.imgur=Прикључак за Имиџер (http://imgur.com)
sr.jira=Прикључак за Џиру
sr.language=Додатни језици
+sr.ocr=OCR прикључак (захтева Microsoft Office Document Imaging (MODI))
sr.optimize=Оптимизујем перформансе…
sr.startgreenshot=Покрени Гриншот
sr.startup=Покрени програм са системом
@@ -449,9 +459,10 @@ sr.win10=Прикључак за Windows 10
sv.confluence=Confluence-insticksprogram
sv.externalcommand=Öppna med externt kommando-insticksprogram
-sv.imgur=Imgur-insticksprogram (Se: https://imgur.com)
+sv.imgur=Imgur-insticksprogram (Se: http://imgur.com)
sv.jira=Jira-insticksprogram
sv.language=Ytterligare språk
+sv.ocr=OCR-insticksprogram (kräver Microsoft Office Document Imaging (MODI))
sv.optimize=Optimerar prestanda, detta kan ta en stund.
sv.startgreenshot=Starta {#ExeName}
sv.startup=Starta {#ExeName} med Windows
@@ -460,9 +471,10 @@ sv.win10=Windows 10-insticksprogram
uk.confluence=Плагін Confluence
uk.default=${default}
uk.externalcommand=Плагін запуску зовнішньої команди
-uk.imgur=Плагін Imgur (див.: https://imgur.com)
+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
@@ -471,9 +483,10 @@ uk.win10=Плагін Windows 10
cn.confluence=Confluence插件
cn.default=${default}
cn.externalcommand=使用外部命令打开插件
-cn.imgur=Imgur插件( (请访问: https://imgur.com))
+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一起启动
@@ -486,7 +499,6 @@ Name: "compact"; Description: "{code:CompactInstall}"
Name: "custom"; Description: "{code:CustomInstall}"; Flags: iscustom
[Components]
-Name: "disablesnippingtool"; Description: {cm:disablewin11snippingtool}; Flags: disablenouninstallwarning; Types: default full custom; Check: IsWindows11OrNewer()
Name: "greenshot"; Description: "Greenshot"; Types: default full compact custom; Flags: fixed
;Name: "plugins\networkimport"; Description: "Network Import Plugin"; Types: full
Name: "plugins\box"; Description: {cm:box}; Types: full custom; Flags: disablenouninstallwarning
@@ -496,8 +508,10 @@ Name: "plugins\externalcommand"; Description: {cm:externalcommand}; Types: defau
Name: "plugins\flickr"; Description: {cm:flickr}; Types: full custom; Flags: disablenouninstallwarning
Name: "plugins\imgur"; Description: {cm:imgur}; Types: default full custom; Flags: disablenouninstallwarning
Name: "plugins\jira"; Description: {cm:jira}; Types: full custom; Flags: disablenouninstallwarning
+Name: "plugins\ocr"; Description: {cm:ocr}; Types: default full custom; Flags: disablenouninstallwarning
Name: "plugins\office"; Description: {cm:office}; Types: default full custom; Flags: disablenouninstallwarning
Name: "plugins\photobucket"; Description: {cm:photobucket}; Types: full custom; Flags: disablenouninstallwarning
+Name: "plugins\picasa"; Description: {cm:picasa}; Types: full custom; Flags: disablenouninstallwarning
Name: "plugins\win10"; Description: {cm:win10}; Types: default full custom; Flags: disablenouninstallwarning; Check: IsWindows10OrNewer()
Name: "languages"; Description: {cm:language}; Types: full custom; Flags: disablenouninstallwarning
Name: "languages\arSY"; Description: {cm:arSY}; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('d')
@@ -536,8 +550,23 @@ Name: "languages\ukUA"; Description: {cm:ukUA}; Types: full custom; Flags: disab
Name: "languages\viVN"; Description: {cm:viVN}; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('e')
Name: "languages\zhCN"; Description: {cm:zhCN}; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('a')
Name: "languages\zhTW"; Description: {cm:zhTW}; 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 (IsAdmin or IsAdminInstallMode);
+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);
@@ -554,7 +583,7 @@ begin
end;
/////////////////////////////////////////////////////////////////////
// The following uninstall code was found at:
-// https://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version
+// 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;
@@ -735,22 +764,9 @@ begin
Result := IsWindowsVersionOrNewer(10, 0);
end;
-function IsWindows11OrNewer: Boolean;
-var
- WindowsVersion: TWindowsVersion;
-begin
- GetWindowsVersionEx(WindowsVersion);
- Result := (WindowsVersion.Major >= 10) and (WindowsVersion.Build >= 22000);
-end;
-
-function ShouldDisableSnippingTool: Boolean;
-begin
- Result := IsComponentSelected('disablesnippingtool');
-end;
-
[Run]
Filename: "{app}\{#ExeName}.exe"; Description: "{cm:startgreenshot}"; Parameters: "{code:GetParamsForGS}"; WorkingDir: "{app}"; Flags: nowait postinstall runasoriginaluser
-Filename: "https://getgreenshot.org/thank-you/?language={language}&version={#Version}"; Flags: shellexec runasoriginaluser
+Filename: "http://getgreenshot.org/thank-you/?language={language}&version={#Version}"; Flags: shellexec runasoriginaluser
[InstallDelete]
Name: {app}; Type: dirifempty;
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/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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ Revolutionary screenshot tool optimized for productivity. Save a screenshot or a part of the screen to a file within a second. Apply text and shapes to the screenshot. Offers capture of window, region or full screenshot. Supports several image formats.
+
();
+ form.BeginInvoke((MethodInvoker)delegate
+ {
+ var historyMenuItem = _historyMenuItem;
+ if (historyMenuItem == null)
+ {
+ return;
+ }
+ 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 100%
rename from src/Greenshot.Plugin.Imgur/ImgurPlugin.resx
rename to GreenshotImgurPlugin/ImgurPlugin.resx
diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs
new file mode 100644
index 000000000..ecbbf775b
--- /dev/null
+++ b/GreenshotImgurPlugin/ImgurUtils.cs
@@ -0,0 +1,349 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Net;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+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://getgreenshot.org/oauth/imgur",
+ CloudServiceName = "Imgur",
+ ClientId = ImgurCredentials.CONSUMER_KEY,
+ ClientSecret = ImgurCredentials.CONSUMER_SECRET,
+ AuthorizeMode = OAuth2AuthorizeMode.OutOfBoundAuto,
+ 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
+ if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out var credits)) {
+ Config.Credits = credits;
+ }
+ }
+ }
+}
diff --git a/GreenshotImgurPlugin/LanguageKeys.cs b/GreenshotImgurPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..25b3e311f
--- /dev/null
+++ b/GreenshotImgurPlugin/LanguageKeys.cs
@@ -0,0 +1,41 @@
+/*
+ * 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 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 96%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-it-IT.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-it-IT.xml
index b0d86a5d0..ebab6e677 100644
--- a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-it-IT.xml
+++ b/GreenshotImgurPlugin/Languages/language_imgurplugin-it-IT.xml
@@ -1,53 +1,53 @@
-
-
-
-
- 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
+
+
+ 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
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Imgur/Languages/language_imgur-ja-JP.xml b/GreenshotImgurPlugin/Languages/language_imgurplugin-ja-JP.xml
similarity index 100%
rename from src/Greenshot.Plugin.Imgur/Languages/language_imgur-ja-JP.xml
rename to GreenshotImgurPlugin/Languages/language_imgurplugin-ja-JP.xml
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/src/Greenshot.Plugin.Imgur/Properties/AssemblyInfo.cs b/GreenshotImgurPlugin/Properties/AssemblyInfo.cs
similarity index 83%
rename from src/Greenshot.Plugin.Imgur/Properties/AssemblyInfo.cs
rename to GreenshotImgurPlugin/Properties/AssemblyInfo.cs
index 4f9d4afb5..6818a420b 100644
--- a/src/Greenshot.Plugin.Imgur/Properties/AssemblyInfo.cs
+++ b/GreenshotImgurPlugin/Properties/AssemblyInfo.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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,17 @@
* GNU General 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 Imgur")]
-[assembly: AssemblyPluginIdentifier("Imgur Plugin")]
// 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)]
diff --git a/GreenshotJiraPlugin/AsyncMemoryCache.cs b/GreenshotJiraPlugin/AsyncMemoryCache.cs
new file mode 100644
index 000000000..de2a61d04
--- /dev/null
+++ b/GreenshotJiraPlugin/AsyncMemoryCache.cs
@@ -0,0 +1,236 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Runtime.Caching;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Log;
+
+
+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);
+
+ ///
+ /// 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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;
+ }
+ }
+
+ // Test if we got an existing object or our own
+ if (_cache.AddOrGetExisting(key, completionSource.Task, cacheItemPolicy) is Task result && !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);
+ if (cacheEntryRemovedArguments.CacheItem.Value is IDisposable disposable)
+ {
+ _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 96%
rename from src/Greenshot.Plugin.Jira/Forms/JiraForm.Designer.cs
rename to GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
index c233ab6f1..bcd10427a 100644
--- a/src/Greenshot.Plugin.Jira/Forms/JiraForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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.
diff --git a/GreenshotJiraPlugin/Forms/JiraForm.cs b/GreenshotJiraPlugin/Forms/JiraForm.cs
new file mode 100644
index 000000000..b9e4c3df8
--- /dev/null
+++ b/GreenshotJiraPlugin/Forms/JiraForm.cs
@@ -0,0 +1,236 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Windows.Forms;
+using Dapplo.Jira.Entities;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using GreenshotPlugin.IniFile;
+
+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)
+ {
+ if (!Language.TryGetString("jira", column, out var translation))
+ {
+ translation = string.Empty;
+ }
+ jiraListView.Columns.Add(translation);
+ }
+ var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, DpiHelper.GetDpi(Handle));
+ var imageList = new ImageList {
+ ImageSize = scaledIconSize
+ };
+ 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.HasValue
+ ? issue.Fields.Created.Value.ToString("d", DateTimeFormatInfo.InvariantInfo)
+ : string.Empty);
+ 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.Plugin.Jira/Forms/JiraFormBase.cs b/GreenshotJiraPlugin/Forms/JiraFormBase.cs
similarity index 75%
rename from src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs
rename to GreenshotJiraPlugin/Forms/JiraFormBase.cs
index 10ea7556c..efc4d0201 100644
--- a/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs
+++ b/GreenshotJiraPlugin/Forms/JiraFormBase.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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.Jira.Forms
-{
- public class JiraFormBase : GreenshotForm
- {
- }
-}
\ No newline at end of file
+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 80%
rename from src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs
rename to GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
index 6903f74fd..0b0195cf4 100644
--- a/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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..043df8f8b
--- /dev/null
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,37 @@
+/*
+ * 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 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..d37465111
--- /dev/null
+++ b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
@@ -0,0 +1,18 @@
+
+
+
+ GreenshotJiraPlugin
+ GreenshotJiraPlugin
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/IssueTypeBitmapCache.cs b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
new file mode 100644
index 000000000..c37cee314
--- /dev/null
+++ b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+ */
+
+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..ba8cad80c
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraConfiguration.cs
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+
+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..6bf5739fe
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraConnector.cs
@@ -0,0 +1,284 @@
+/*
+ * 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 .
+ */
+
+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.Entities;
+using Dapplo.Jira.SvgWinForms.Converters;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// This encapsulates the JiraClient to make it possible to change as less old Greenshot code as needed
+ ///
+ public sealed 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 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))
+ {
+ var jiraConnector = SimpleServiceProvider.Current.GetInstance();
+ jiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height });
+ }
+ };
+
+ }
+
+ ///
+ /// Dispose, logout the users
+ ///
+ public void Dispose() {
+ if (_jiraClient != null)
+ {
+ Logout();
+ }
+ FavIcon?.Dispose();
+ }
+
+ ///
+ /// Constructor
+ ///
+ public JiraConnector()
+ {
+ JiraConfig.Url = JiraConfig.Url.Replace(DefaultPostfix, string.Empty);
+ }
+
+ ///
+ /// 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 successfully
+ private async Task DoLoginAsync(string user, string password, CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
+ {
+ return false;
+ }
+ _jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
+ _jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height });
+ _jiraClient.SetBasicAuthentication(user, password);
+
+ _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
+ try
+ {
+ 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 ex2)
+ {
+ Log.WarnFormat("Couldn't connect to JIRA {0}", JiraConfig.Url);
+ Log.Warn("Exception details: ", ex2);
+ 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) {
+ Logout();
+ 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);
+ }
+ IsLoggedIn = true;
+ 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 void Logout() {
+ if (_jiraClient == null || !IsLoggedIn) return;
+ Monitor.Dispose();
+ IsLoggedIn = 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) {
+ if (!IsLoggedIn) {
+ await LoginAsync(cancellationToken);
+ }
+ }
+
+ ///
+ /// Get the favorite filters
+ ///
+ /// List with filters
+ public async Task> GetFavoriteFiltersAsync(CancellationToken cancellationToken = default)
+ {
+ 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)
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ try
+ {
+ return await _jiraClient.Issue.GetAsync(issueKey, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Attach the content to the jira
+ ///
+ ///
+ /// IBinaryContainer
+ ///
+ ///
+ public async Task AttachAsync(string issueKey, IBinaryContainer content, CancellationToken cancellationToken = default)
+ {
+ 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, Visibility visibility = null, CancellationToken cancellationToken = default)
+ {
+ 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)
+ {
+ await CheckCredentialsAsync(cancellationToken);
+ var searchResult = await _jiraClient.Issue.SearchAsync(filter.Jql, null, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, null, 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)
+ {
+ 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 { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraDestination.cs b/GreenshotJiraPlugin/JiraDestination.cs
new file mode 100644
index 000000000..080ec8619
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraDestination.cs
@@ -0,0 +1,160 @@
+/*
+ * 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 .
+ */
+
+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 GreenshotJiraPlugin.Forms;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+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 Issue _jiraIssue;
+
+ public JiraDestination(Issue jiraIssue = null) {
+ _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 = SimpleServiceProvider.Current.GetInstance();
+ 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 = SimpleServiceProvider.Current.GetInstance();
+ if (jiraConnector == null || !jiraConnector.IsLoggedIn) {
+ yield break;
+ }
+ foreach(var jiraDetails in jiraConnector.Monitor.RecentJiras)
+ {
+ yield return new JiraDestination(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);
+ var jiraConnector = SimpleServiceProvider.Current.GetInstance();
+ 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 jiraConnector.AttachAsync(_jiraIssue.Key, surfaceContainer);
+ surfaceToUpload.UploadUrl = 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(jiraConnector);
+ jiraForm.SetFilename(filename);
+ var dialogResult = jiraForm.ShowDialog();
+ if (dialogResult == DialogResult.OK) {
+ try {
+ surfaceToUpload.UploadUrl = 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..67bbc0f61
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraDetails.cs
@@ -0,0 +1,71 @@
+/*
+ * 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
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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 69%
rename from src/Greenshot.Plugin.Jira/JiraEventArgs.cs
rename to GreenshotJiraPlugin/JiraEventArgs.cs
index d847c9392..eb60e5fcf 100644
--- a/src/Greenshot.Plugin.Jira/JiraEventArgs.cs
+++ b/GreenshotJiraPlugin/JiraEventArgs.cs
@@ -2,7 +2,7 @@
* 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/
+ * 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 73%
rename from src/Greenshot.Plugin.Jira/JiraEventTypes.cs
rename to GreenshotJiraPlugin/JiraEventTypes.cs
index cc433c85e..37e62cab1 100644
--- a/src/Greenshot.Plugin.Jira/JiraEventTypes.cs
+++ b/GreenshotJiraPlugin/JiraEventTypes.cs
@@ -2,7 +2,7 @@
* 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/
+ * 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..65b73924a
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraMonitor.cs
@@ -0,0 +1,218 @@
+/*
+ * 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
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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 GreenshotPlugin.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;
+ }
+
+ ///
+ /// 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.
+ }
+
+ ///
+ /// 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
+ ///
+ /// IJiraClient
+ /// CancellationToken
+ public async Task AddJiraInstanceAsync(IJiraClient jiraInstance, CancellationToken token = default)
+ {
+ _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
+ {
+ if (_projectJiraClientMap.TryGetValue(jiraDetails.ProjectKey, out var 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];
+
+ // Check if we have a JIRA instance with a project for this key
+ if (_projectJiraClientMap.TryGetValue(projectKey, out var jiraClient))
+ {
+ // We have found a project for this _jira key, so it must be a valid & known JIRA
+ if (_recentJiras.TryGetValue(jiraKey, out var 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..d58978328
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraPlugin.cs
@@ -0,0 +1,138 @@
+/*
+ * 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 .
+ */
+
+using System.Windows.Forms;
+using System;
+using System.Threading.Tasks;
+using Dapplo.Log;
+using GreenshotJiraPlugin.Forms;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+using log4net;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// This is the JiraPlugin base code
+ ///
+ [Plugin("Jira", true)]
+ public class JiraPlugin : IGreenshotPlugin {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin));
+ private JiraConfiguration _config;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing) {
+ if (disposing)
+ {
+ var jiraConnector = SimpleServiceProvider.Current.GetInstance();
+ jiraConnector?.Dispose();
+ }
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize() {
+ // Register configuration (don't need the configuration itself)
+ _config = IniConfig.GetIniSection();
+
+ // Provide the JiraConnector
+ SimpleServiceProvider.Current.AddService(new JiraConnector());
+ // Provide the IDestination
+ SimpleServiceProvider.Current.AddService(new JiraDestination());
+
+ // Make sure the log is enabled for the correct 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);
+ }
+
+ return true;
+ }
+
+ public void Shutdown() {
+ Log.Debug("Jira Plugin shutdown.");
+ var jiraConnector = SimpleServiceProvider.Current.GetInstance();
+ jiraConnector?.Logout();
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public void Configure() {
+ string url = _config.Url;
+ if (ShowConfigDialog()) {
+ // check for re-login
+ var jiraConnector = SimpleServiceProvider.Current.GetInstance();
+ if (jiraConnector != null && jiraConnector.IsLoggedIn && !string.IsNullOrEmpty(url)) {
+ if (!url.Equals(_config.Url)) {
+ jiraConnector.Logout();
+ Task.Run(async () =>
+ {
+ 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 100%
rename from src/Greenshot.Plugin.Jira/JiraPlugin.resx
rename to GreenshotJiraPlugin/JiraPlugin.resx
diff --git a/GreenshotJiraPlugin/LanguageKeys.cs b/GreenshotJiraPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..d881be575
--- /dev/null
+++ b/GreenshotJiraPlugin/LanguageKeys.cs
@@ -0,0 +1,46 @@
+/*
+ * 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 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 95%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-it-IT.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-it-IT.xml
index f69d1fb37..be20028fb 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
+
+
+ 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...
+
+
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-ja-JP.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-ja-JP.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-ja-JP.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-ja-JP.xml
diff --git a/src/Greenshot.Plugin.Jira/Languages/language_jira-kab-DZ.xml b/GreenshotJiraPlugin/Languages/language_jiraplugin-kab-DZ.xml
similarity index 100%
rename from src/Greenshot.Plugin.Jira/Languages/language_jira-kab-DZ.xml
rename to GreenshotJiraPlugin/Languages/language_jiraplugin-kab-DZ.xml
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..d7b8d601c
--- /dev/null
+++ b/GreenshotJiraPlugin/Log4NetLogger.cs
@@ -0,0 +1,120 @@
+/*
+ * 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 .
+ */
+
+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/GreenshotOCRCommand/COMWrapper.cs b/GreenshotOCRCommand/COMWrapper.cs
new file mode 100644
index 000000000..fd26cfeb9
--- /dev/null
+++ b/GreenshotOCRCommand/COMWrapper.cs
@@ -0,0 +1,513 @@
+/*
+ * 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 .
+ */
+
+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 GreenshotOCRCommand {
+ ///
+ /// 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;
+
+ ///
+ /// 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;
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 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)) {
+ if (RemotingServices.GetRealProxy(value) is COMWrapper 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;
+ }
+
+ ///
+ /// 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_"))) {
+ if (!(callMessage.InArgs[0] is Delegate 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..936ea34f9
--- /dev/null
+++ b/GreenshotOCRCommand/ComProgIdAttribute.cs
@@ -0,0 +1,78 @@
+/*
+ * 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 .
+ */
+
+using System;
+
+namespace GreenshotOCRCommand {
+ ///
+ /// 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..4267325f2
--- /dev/null
+++ b/GreenshotOCRCommand/GreenshotOCRCommand.csproj
@@ -0,0 +1,14 @@
+
+
+
+ GreenshotOCRCommand
+ GreenshotOCRCommand
+ WinExe
+
+
+
+
+
+
+
+
diff --git a/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs b/GreenshotOCRCommand/Modi/CompressionLevel.cs
similarity index 72%
rename from src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs
rename to GreenshotOCRCommand/Modi/CompressionLevel.cs
index 7fd1b94c5..0cb9a4bc7 100644
--- a/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs
+++ b/GreenshotOCRCommand/Modi/CompressionLevel.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-2021 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,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.Flickr.Forms
+namespace GreenshotOCRCommand.Modi
{
- public class FlickrForm : GreenshotForm
- {
- }
+ public enum CompressionLevel {
+ miCOMP_LEVEL_LOW = 0,
+ miCOMP_LEVEL_MEDIUM = 1,
+ miCOMP_LEVEL_HIGH = 2
+ }
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs b/GreenshotOCRCommand/Modi/FileFormat.cs
similarity index 70%
rename from src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs
rename to GreenshotOCRCommand/Modi/FileFormat.cs
index 4cb0e6141..42c86a104 100644
--- a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs
+++ b/GreenshotOCRCommand/Modi/FileFormat.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-2021 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,14 +16,15 @@
* GNU General 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 GreenshotOCRCommand.Modi
{
- public class DropboxForm : GreenshotForm
- {
- }
+ 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..433fcd121
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ICommon.cs
@@ -0,0 +1,32 @@
+/*
+ * 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 .
+ */
+
+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..623feef72
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IDispatch.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..cd9098f61
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IDocument.cs
@@ -0,0 +1,79 @@
+/*
+ * 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 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..5329c4eaf
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IImage.cs
@@ -0,0 +1,41 @@
+/*
+ * 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 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..3c429c7d0
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IImages.cs
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+
+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..351724150
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ILayout.cs
@@ -0,0 +1,55 @@
+/*
+ * 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 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..3474a5e86
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IMiRect.cs
@@ -0,0 +1,48 @@
+/*
+ * 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 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..e322b577d
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IMiRects.cs
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+ */
+
+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..6ba1a425b
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IWord.cs
@@ -0,0 +1,65 @@
+/*
+ * 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 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..4e7243cdd
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/IWords.cs
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+ */
+
+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..b1af9f30c
--- /dev/null
+++ b/GreenshotOCRCommand/Modi/ModiLanguage.cs
@@ -0,0 +1,48 @@
+/*
+ * 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 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..7f1c81b09
--- /dev/null
+++ b/GreenshotOCRCommand/Program.cs
@@ -0,0 +1,121 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+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..85d71c24d
--- /dev/null
+++ b/GreenshotOCRCommand/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+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: AssemblyDescription("A small executable to OCR a bitmap")]
+
+// 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")]
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/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj
similarity index 54%
rename from src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj
rename to GreenshotOCRPlugin/GreenshotOCRPlugin.csproj
index d0151b7c0..42e03e628 100644
--- a/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj
+++ b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj
@@ -1,15 +1,16 @@
-
- none
- false
+
+
+ GreenshotOCRPlugin
+ GreenshotOCRPlugin
+
PreserveNewest
-
-
+
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..52259f004
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Lingua OCR
+
+
+ Orientamento immagine
+
+
+ Raddrizza immagine
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml
new file mode 100644
index 000000000..c103704d4
--- /dev/null
+++ b/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml
@@ -0,0 +1,8 @@
+
+
+
+ OCRの言語
+ 画像の向きを揃える
+ 画像の傾きを補正する
+
+
\ 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/ModiLanguage.cs b/GreenshotOCRPlugin/ModiLanguage.cs
new file mode 100644
index 000000000..3edd95d0f
--- /dev/null
+++ b/GreenshotOCRPlugin/ModiLanguage.cs
@@ -0,0 +1,50 @@
+/*
+ * 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 GreenshotOCRPlugin
+{
+ ///
+ /// 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
+ }
+}
\ No newline at end of file
diff --git a/GreenshotOCRPlugin/OCRConfiguration.cs b/GreenshotOCRPlugin/OCRConfiguration.cs
new file mode 100644
index 000000000..8eebcc91e
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRConfiguration.cs
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+ */
+
+using GreenshotPlugin.IniFile;
+
+namespace GreenshotOCRPlugin {
+ ///
+ /// 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..5c774bfc1
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRDestination.cs
@@ -0,0 +1,60 @@
+/*
+ * 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 .
+ */
+
+using System.Drawing;
+using System.IO;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+
+namespace GreenshotOCRPlugin {
+ ///
+ /// 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..5ba8fda84
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRForm.cs
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+using GreenshotPlugin.Controls;
+
+namespace GreenshotOCRPlugin {
+ ///
+ /// 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..677e22342
--- /dev/null
+++ b/GreenshotOCRPlugin/OCRPlugin.cs
@@ -0,0 +1,206 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Effects;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+//using Microsoft.Win32;
+
+namespace GreenshotOCRPlugin {
+ ///
+ /// OCR Plugin Greenshot
+ ///
+ [Plugin("Ocr", true)]
+ public class OcrPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OcrPlugin));
+ private string _ocrCommand;
+ private static OCRConfiguration _config;
+ private ToolStripMenuItem _ocrMenuItem = new ToolStripMenuItem();
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+ if (_ocrMenuItem == null) return;
+ _ocrMenuItem.Dispose();
+ _ocrMenuItem = null;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize() {
+ Log.Debug("Initialize called");
+
+ var ocrDirectory = Path.GetDirectoryName(GetType().Assembly.Location);
+ if (ocrDirectory == null)
+ {
+ return false;
+ }
+ _ocrCommand = Path.Combine(ocrDirectory, "greenshotocrcommand.exe");
+
+ if (!HasModi()) {
+ Log.Warn("No MODI found!");
+ return false;
+ }
+ // Provide the IDestination
+ SimpleServiceProvider.Current.AddService(new OCRDestination(this));
+ // Load configuration
+ _config = IniConfig.GetIniSection();
+
+ if (_config.Language != null) {
+ _config.Language = _config.Language.Replace("miLANG_", string.Empty).Replace("_"," ");
+ }
+ return true;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Shutdown
+ ///
+ public void Shutdown() {
+ Log.Debug("Shutdown");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public 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/GreenshotOCRPlugin/SettingsForm.Designer.cs b/GreenshotOCRPlugin/SettingsForm.Designer.cs
new file mode 100644
index 000000000..a9e57749a
--- /dev/null
+++ b/GreenshotOCRPlugin/SettingsForm.Designer.cs
@@ -0,0 +1,146 @@
+/*
+ * 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 GreenshotOCRPlugin
+{
+ 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..94805f941
--- /dev/null
+++ b/GreenshotOCRPlugin/SettingsForm.cs
@@ -0,0 +1,65 @@
+/*
+ * 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 .
+ */
+
+using System;
+
+namespace GreenshotOCRPlugin {
+ ///
+ /// 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/src/Greenshot.Plugin.Office/Com/DisposableCom.cs b/GreenshotOfficePlugin/Com/DisposableCom.cs
similarity index 92%
rename from src/Greenshot.Plugin.Office/Com/DisposableCom.cs
rename to GreenshotOfficePlugin/Com/DisposableCom.cs
index e722f48e3..1fc17a78b 100644
--- a/src/Greenshot.Plugin.Office/Com/DisposableCom.cs
+++ b/GreenshotOfficePlugin/Com/DisposableCom.cs
@@ -1,7 +1,6 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-namespace Greenshot.Plugin.Office.Com
+namespace GreenshotOfficePlugin.Com
{
///
/// A factory for IDisposableCom
diff --git a/src/Greenshot.Plugin.Office/Com/DisposableComImplementation.cs b/GreenshotOfficePlugin/Com/DisposableComImplementation.cs
similarity index 94%
rename from src/Greenshot.Plugin.Office/Com/DisposableComImplementation.cs
rename to GreenshotOfficePlugin/Com/DisposableComImplementation.cs
index 572de52d8..e7a52baac 100644
--- a/src/Greenshot.Plugin.Office/Com/DisposableComImplementation.cs
+++ b/GreenshotOfficePlugin/Com/DisposableComImplementation.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.InteropServices;
-namespace Greenshot.Plugin.Office.Com
+namespace GreenshotOfficePlugin.Com
{
///
/// Implementation of the IDisposableCom, this is internal to prevent other code to use it directly
@@ -38,7 +38,6 @@ namespace Greenshot.Plugin.Office.Com
{
return;
}
-
// Do not catch an exception from this.
// You may want to remove these guards depending on
// what you think the semantics should be.
@@ -46,7 +45,6 @@ namespace Greenshot.Plugin.Office.Com
{
Marshal.ReleaseComObject(ComObject);
}
-
ComObject = default;
}
}
diff --git a/src/Greenshot.Plugin.Office/Com/IDisposableCom.cs b/GreenshotOfficePlugin/Com/IDisposableCom.cs
similarity index 90%
rename from src/Greenshot.Plugin.Office/Com/IDisposableCom.cs
rename to GreenshotOfficePlugin/Com/IDisposableCom.cs
index d99b6f4c6..6bf1327c7 100644
--- a/src/Greenshot.Plugin.Office/Com/IDisposableCom.cs
+++ b/GreenshotOfficePlugin/Com/IDisposableCom.cs
@@ -3,7 +3,7 @@
using System;
-namespace Greenshot.Plugin.Office.Com
+namespace GreenshotOfficePlugin.Com
{
///
/// A simple com wrapper which helps with "using"
diff --git a/src/Greenshot.Plugin.Office/Com/Ole32Api.cs b/GreenshotOfficePlugin/Com/Ole32Api.cs
similarity index 51%
rename from src/Greenshot.Plugin.Office/Com/Ole32Api.cs
rename to GreenshotOfficePlugin/Com/Ole32Api.cs
index 1a57aa6c9..783f48d0d 100644
--- a/src/Greenshot.Plugin.Office/Com/Ole32Api.cs
+++ b/GreenshotOfficePlugin/Com/Ole32Api.cs
@@ -3,10 +3,10 @@
using System;
using System.Runtime.InteropServices;
-using Dapplo.Windows.Common.Enums;
-using Dapplo.Windows.Common.Extensions;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Core.Enums;
-namespace Greenshot.Plugin.Office.Com
+namespace GreenshotOfficePlugin.Com
{
///
/// This provides an API for OLE32
@@ -24,10 +24,24 @@ namespace Greenshot.Plugin.Office.Com
{
return clsId;
}
-
return clsId;
}
+ ///
+ /// This converts a clsid (Class ID) into a ProgID (program ID)
+ ///
+ /// Guid with the clsid (Class ID)
+ /// string with the progid
+ public static string ProgIdFromClassId(Guid clsId)
+ {
+ if (ProgIDFromCLSID(ref clsId, out string progId).Succeeded())
+ {
+ return progId;
+ }
+
+ return null;
+ }
+
///
/// See more here
///
@@ -36,5 +50,14 @@ namespace Greenshot.Plugin.Office.Com
/// HResult
[DllImport("ole32.dll", ExactSpelling = true)]
private static extern HResult CLSIDFromProgID([In] [MarshalAs(UnmanagedType.LPWStr)] string progId, [Out] out Guid clsId);
+
+ ///
+ /// See more here
+ ///
+ /// Guid The CLSID for which the ProgID is to be requested.
+ /// string the ProgID string. The string that represents clsid includes enclosing braces.
+ /// HResult
+ [DllImport("ole32.dll")]
+ private static extern HResult ProgIDFromCLSID([In] ref Guid clsId, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgId);
}
-}
\ No newline at end of file
+}
diff --git a/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs b/GreenshotOfficePlugin/Com/OleAut32Api.cs
similarity index 89%
rename from src/Greenshot.Plugin.Office/Com/OleAut32Api.cs
rename to GreenshotOfficePlugin/Com/OleAut32Api.cs
index ea0f1b0c9..6a3e4284c 100644
--- a/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs
+++ b/GreenshotOfficePlugin/Com/OleAut32Api.cs
@@ -3,10 +3,10 @@
using System;
using System.Runtime.InteropServices;
-using Dapplo.Windows.Common.Enums;
-using Dapplo.Windows.Common.Extensions;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Core.Enums;
-namespace Greenshot.Plugin.Office.Com
+namespace GreenshotOfficePlugin.Com
{
///
/// API for OLEAUT32
@@ -23,7 +23,7 @@ namespace Greenshot.Plugin.Office.Com
{
if (GetActiveObject(ref clsId, IntPtr.Zero, out object comObject).Succeeded())
{
- return DisposableCom.Create((T) comObject);
+ return DisposableCom.Create((T)comObject);
}
return null;
@@ -51,4 +51,4 @@ namespace Greenshot.Plugin.Office.Com
[DllImport("oleaut32.dll")]
private static extern HResult GetActiveObject(ref Guid rclsId, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out object ppunk);
}
-}
\ No newline at end of file
+}
diff --git a/GreenshotOfficePlugin/Destinations/ExcelDestination.cs b/GreenshotOfficePlugin/Destinations/ExcelDestination.cs
new file mode 100644
index 000000000..dfd0ed7e0
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/ExcelDestination.cs
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Text.RegularExpressions;
+using GreenshotOfficePlugin.OfficeExport;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotOfficePlugin.Destinations {
+ ///
+ /// 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..df833c6a1
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs
@@ -0,0 +1,124 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using GreenshotOfficePlugin.OfficeExport;
+using GreenshotOfficePlugin.OfficeExport.Entities;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+
+namespace GreenshotOfficePlugin.Destinations {
+ 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;
+ private readonly OneNoteExporter _oneNoteExporter = new OneNoteExporter();
+
+ 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..65ccf03be
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/OutlookDestination.cs
@@ -0,0 +1,165 @@
+/*
+ * 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 .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using GreenshotOfficePlugin.OfficeExport;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+using Microsoft.Office.Interop.Outlook;
+
+namespace GreenshotOfficePlugin.Destinations {
+ ///
+ /// 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;
+ private readonly OutlookEmailExporter _outlookEmailExporter = new OutlookEmailExporter();
+
+ 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]", string.Empty);
+
+ 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..3e3700e4c
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/PowerpointDestination.cs
@@ -0,0 +1,123 @@
+/*
+ * 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 .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using GreenshotOfficePlugin.OfficeExport;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotOfficePlugin.Destinations {
+ ///
+ /// 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;
+ private readonly PowerpointExporter _powerpointExporter = new PowerpointExporter();
+
+ 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().ToList();
+ 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..a7d630d1d
--- /dev/null
+++ b/GreenshotOfficePlugin/Destinations/WordDestination.cs
@@ -0,0 +1,131 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using GreenshotOfficePlugin.OfficeExport;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotOfficePlugin.Destinations {
+ ///
+ /// 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;
+ private readonly WordExporter _wordExporter = new WordExporter();
+ 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().ToList();
+ 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/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj
similarity index 92%
rename from src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj
rename to GreenshotOfficePlugin/GreenshotOfficePlugin.csproj
index 982b86833..f6f07e98d 100644
--- a/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj
+++ b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj
@@ -1,15 +1,17 @@
-
- none
- false
+
+
+ GreenshotOfficePlugin
+ GreenshotOfficePlugin
+
PreserveNewest
-
+
@@ -82,23 +84,23 @@
-
+ trueruntime
-
+ trueruntime
-
+ trueruntime
-
+ trueruntime
-
+ trueruntime
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/OfficeConfiguration.cs b/GreenshotOfficePlugin/OfficeConfiguration.cs
new file mode 100644
index 000000000..7064715fd
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficeConfiguration.cs
@@ -0,0 +1,54 @@
+/*
+ * 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 .
+ */
+
+using GreenshotOfficePlugin.OfficeInterop;
+using GreenshotPlugin.IniFile;
+using Microsoft.Office.Interop.PowerPoint;
+
+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/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteNotebook.cs b/GreenshotOfficePlugin/OfficeExport/Entities/OneNoteNotebook.cs
similarity index 84%
rename from src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteNotebook.cs
rename to GreenshotOfficePlugin/OfficeExport/Entities/OneNoteNotebook.cs
index e161c6bcd..40bf4255e 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteNotebook.cs
+++ b/GreenshotOfficePlugin/OfficeExport/Entities/OneNoteNotebook.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,9 +15,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.Office.OfficeExport.Entities
+namespace GreenshotOfficePlugin.OfficeExport.Entities
{
///
/// Container for transporting notebook information
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNotePage.cs b/GreenshotOfficePlugin/OfficeExport/Entities/OneNotePage.cs
similarity index 87%
rename from src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNotePage.cs
rename to GreenshotOfficePlugin/OfficeExport/Entities/OneNotePage.cs
index e6fcd4bff..6bc67084b 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNotePage.cs
+++ b/GreenshotOfficePlugin/OfficeExport/Entities/OneNotePage.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,9 +15,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.Office.OfficeExport.Entities
+namespace GreenshotOfficePlugin.OfficeExport.Entities
{
///
/// Container for transporting Page information
@@ -34,7 +34,6 @@ namespace Greenshot.Plugin.Office.OfficeExport.Entities
{
return string.Format("{0} / {1}", Parent.Name, Name);
}
-
return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name);
}
}
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteSection.cs b/GreenshotOfficePlugin/OfficeExport/Entities/OneNoteSection.cs
similarity index 85%
rename from src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteSection.cs
rename to GreenshotOfficePlugin/OfficeExport/Entities/OneNoteSection.cs
index 93fd20e63..00eafb5ae 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/Entities/OneNoteSection.cs
+++ b/GreenshotOfficePlugin/OfficeExport/Entities/OneNoteSection.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,9 +15,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.Office.OfficeExport.Entities
+namespace GreenshotOfficePlugin.OfficeExport.Entities
{
///
/// Container for transporting section information
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs b/GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs
similarity index 91%
rename from src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs
rename to GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs
index cfffff5f6..ad92c6743 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs
+++ b/GreenshotOfficePlugin/OfficeExport/ExcelExporter.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,19 +15,19 @@
// GNU General 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;
using System.Collections.Generic;
using System.Drawing;
-using Dapplo.Windows.User32;
-using Greenshot.Plugin.Office.Com;
-using Greenshot.Plugin.Office.OfficeInterop;
+using GreenshotOfficePlugin.Com;
+using GreenshotOfficePlugin.OfficeInterop;
+using GreenshotPlugin.UnmanagedHelpers;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Excel;
using Version = System.Version;
-namespace Greenshot.Plugin.Office.OfficeExport
+namespace GreenshotOfficePlugin.OfficeExport
{
///
/// Excel exporter
@@ -53,12 +53,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no excel running
return null;
}
-
if (excelApplication?.ComObject != null)
{
InitializeVariables(excelApplication);
}
-
return excelApplication;
}
@@ -73,7 +71,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
excelApplication = DisposableCom.Create(new Application());
}
-
InitializeVariables(excelApplication);
return excelApplication;
}
@@ -111,11 +108,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return;
}
-
if (!Version.TryParse(excelApplication.ComObject.Version, out _excelVersion))
{
LOG.Warn("Assuming Excel version 1997.");
- _excelVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
+ _excelVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0);
}
}
@@ -136,7 +132,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
for (int i = 1; i <= workbooks.ComObject.Count; i++)
{
- using var workbook = DisposableCom.Create((_Workbook) workbooks.ComObject[i]);
+ using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject[i]);
if ((workbook != null) && workbook.ComObject.Name.StartsWith(workbookName))
{
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
@@ -177,7 +173,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
workbook.ComObject.Activate();
using var application = DisposableCom.Create(workbook.ComObject.Application);
- User32Api.SetForegroundWindow((IntPtr) application.ComObject.Hwnd);
+ User32.SetForegroundWindow((IntPtr) application.ComObject.Hwnd);
}
///
@@ -195,8 +191,9 @@ namespace Greenshot.Plugin.Office.OfficeExport
excelApplication.ComObject.Visible = true;
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
- using var workbook = DisposableCom.Create((_Workbook) workbooks.ComObject.Add());
+ using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject.Add());
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
}
}
+
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs
similarity index 90%
rename from src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs
rename to GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs
index 645623780..5b0fcb8c5 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs
+++ b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,34 +15,30 @@
// GNU General 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;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Xml;
-using Greenshot.Base.Core;
-using Greenshot.Base.Core.Enums;
-using Greenshot.Base.Interfaces;
-using Greenshot.Base.Interfaces.Plugin;
-using Greenshot.Plugin.Office.Com;
-using Greenshot.Plugin.Office.OfficeExport.Entities;
+using GreenshotOfficePlugin.Com;
+using GreenshotOfficePlugin.OfficeExport.Entities;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
using Microsoft.Office.Interop.OneNote;
-namespace Greenshot.Plugin.Office.OfficeExport
+namespace GreenshotOfficePlugin.OfficeExport
{
///
/// OneNote exporter
- /// More details about OneNote: https://msdn.microsoft.com/en-us/magazine/ff796230.aspx
+ /// More details about OneNote: http://msdn.microsoft.com/en-us/magazine/ff796230.aspx
///
public class OneNoteExporter
{
private const string XmlImageContent = "{0}";
-
- private const string XmlOutline =
- "{0}";
-
+ private const string XmlOutline = "{0}";
private const string OnenoteNamespace2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote";
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OneNoteExporter));
@@ -97,7 +93,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var pngStream = new MemoryStream();
var pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
- ImageIO.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
+ ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height);
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
@@ -111,7 +107,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Warn("Unable to navigate to the target page", ex);
}
-
return true;
}
@@ -131,7 +126,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no OneNote running
return null;
}
-
return oneNoteApplication;
}
@@ -146,7 +140,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
oneNoteApplication = DisposableCom.Create(new Application());
}
-
return oneNoteApplication;
}
@@ -190,7 +183,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
};
}
}
-
if ("one:Section".Equals(xmlReader.Name))
{
string id = xmlReader.GetAttribute("ID");
@@ -204,7 +196,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
};
}
}
-
if ("one:Page".Equals(xmlReader.Name))
{
// Skip deleted items
@@ -223,7 +214,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
pages.Add(page);
}
@@ -241,26 +231,22 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
catch (COMException cEx)
{
- if (cEx.ErrorCode == unchecked((int) 0x8002801D))
+ if (cEx.ErrorCode == unchecked((int)0x8002801D))
{
- LOG.Warn(
- "Wrong registry keys, to solve this remove the OneNote key as described here: https://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/");
+ 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((page1, page2) =>
{
if (page1.IsCurrentlyViewed || page2.IsCurrentlyViewed)
{
return page2.IsCurrentlyViewed.CompareTo(page1.IsCurrentlyViewed);
}
-
return string.Compare(page1.DisplayName, page2.DisplayName, StringComparison.Ordinal);
});
return pages;
@@ -278,7 +264,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return null;
}
-
// ReSharper disable once RedundantAssignment
string unfiledNotesPath = "";
oneNoteApplication.ComObject.GetSpecialLocation(specialLocation, out unfiledNotesPath);
@@ -300,7 +285,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
string id = xmlReader.GetAttribute("ID");
string path = xmlReader.GetAttribute("path");
if (unfiledNotesPath.Equals(path))
@@ -317,7 +301,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return null;
}
}
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs b/GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs
similarity index 91%
rename from src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs
rename to GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs
index 72724c40b..40306ecf7 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs
+++ b/GreenshotOfficePlugin/OfficeExport/OutlookEmailExporter.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,15 +15,15 @@
// GNU General 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;
using System.Collections.Generic;
using System.IO;
using System.Text;
-using Greenshot.Base.IniFile;
-using Greenshot.Plugin.Office.Com;
-using Greenshot.Plugin.Office.OfficeInterop;
+using GreenshotOfficePlugin.Com;
+using GreenshotOfficePlugin.OfficeInterop;
+using GreenshotPlugin.IniFile;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Interop.Word;
using Microsoft.Win32;
@@ -32,7 +32,7 @@ using Application = Microsoft.Office.Interop.Outlook.Application;
using Exception = System.Exception;
using Version = System.Version;
-namespace Greenshot.Plugin.Office.OfficeExport
+namespace GreenshotOfficePlugin.OfficeExport
{
///
/// Outlook exporter has all the functionality to export to outlook
@@ -47,9 +47,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
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";
-
// Schema definitions for the MAPI properties, see: http://msdn.microsoft.com/en-us/library/aa454438.aspx and: http://msdn.microsoft.com/en-us/library/bb446117.aspx
private const string AttachmentContentId = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
@@ -75,10 +73,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2013)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
{
// Check inline "panel" for Outlook 2013
- using var activeExplorer = DisposableCom.Create((_Explorer) outlookApplication.ComObject.ActiveExplorer());
+ using var activeExplorer = DisposableCom.Create((_Explorer)outlookApplication.ComObject.ActiveExplorer());
// Only if we have one and if the capture is the one we selected
if ((activeExplorer != null) && activeExplorer.ComObject.Caption.StartsWith(inspectorCaption))
{
@@ -92,17 +90,15 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName);
}
-
break;
case AppointmentItem appointmentItem:
- if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
+ if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
{
return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName);
}
}
-
break;
}
}
@@ -114,11 +110,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return false;
}
-
LOG.DebugFormat("Got {0} inspectors to check", inspectors.ComObject.Count);
for (int i = 1; i <= inspectors.ComObject.Count; i++)
{
- using var inspector = DisposableCom.Create((_Inspector) inspectors.ComObject[i]);
+ using var inspector = DisposableCom.Create((_Inspector)inspectors.ComObject[i]);
string currentCaption = inspector.ComObject.Caption;
if (!currentCaption.StartsWith(inspectorCaption))
{
@@ -135,7 +130,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
try
{
return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName);
@@ -144,10 +138,9 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Error($"Export to {currentCaption} failed.", exExport);
}
-
break;
case AppointmentItem appointmentItem:
- if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
+ if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
{
@@ -160,7 +153,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
// skip, can't export to olAppointment
continue;
}
-
try
{
return ExportToInspector(inspector, null, appointmentItem.Class, null, tmpFile, attachmentName);
@@ -169,7 +161,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Error($"Export to {currentCaption} failed.", exExport);
}
-
break;
default:
continue;
@@ -177,7 +168,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return false;
}
@@ -191,8 +181,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
///
///
///
- private bool ExportToInspector(IDisposableCom<_Inspector> inspector, IDisposableCom<_Explorer> explorer, OlObjectClass itemClass, MailItem mailItem, string tmpFile,
- string attachmentName)
+ private bool ExportToInspector(IDisposableCom<_Inspector> inspector, IDisposableCom<_Explorer> explorer, OlObjectClass itemClass, MailItem mailItem, string tmpFile, string attachmentName)
{
bool isMail = OlObjectClass.olMail.Equals(itemClass);
bool isAppointment = OlObjectClass.olAppointment.Equals(itemClass);
@@ -201,7 +190,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Item is no mail or appointment.");
return false;
}
-
try
{
// Make sure the inspector is activated, only this way the word editor is active!
@@ -212,27 +200,25 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
isTextFormat = OlBodyFormat.olFormatPlain.Equals(mailItem.BodyFormat);
}
-
if (isAppointment || !isTextFormat)
{
// Check for wordmail, if so use the wordexporter
- // https://msdn.microsoft.com/en-us/library/dd492012%28v=office.12%29.aspx
+ // 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.
IDisposableCom<_Document> wordDocument = null;
- if ((explorer != null) && (_outlookVersion.Major >= (int) OfficeVersions.Office2013))
+ if ((explorer != null) && (_outlookVersion.Major >= (int)OfficeVersions.Office2013))
{
// TODO: Needs to have the Microsoft Outlook 15.0 Object Library installed
- wordDocument = DisposableCom.Create((_Document) explorer.ComObject.ActiveInlineResponseWordEditor);
+ wordDocument = DisposableCom.Create((_Document)explorer.ComObject.ActiveInlineResponseWordEditor);
}
else if (inspector != null)
{
if (inspector.ComObject.IsWordMail() && (inspector.ComObject.EditorType == OlEditorType.olEditorWord))
{
- var tmpWordDocument = (_Document) inspector.ComObject.WordEditor;
+ var tmpWordDocument = (_Document)inspector.ComObject.WordEditor;
wordDocument = DisposableCom.Create(tmpWordDocument);
}
}
-
if (wordDocument != null)
{
using (wordDocument)
@@ -262,7 +248,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Info("Trying export for outlook < 2007.");
}
}
-
// Only use mailitem as it should be filled!!
if (mailItem != null)
{
@@ -270,7 +255,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
string contentId;
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
{
contentId = Guid.NewGuid().ToString();
}
@@ -298,7 +283,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
var selection = document2.selection;
if (selection != null)
{
- var range = (IHTMLTxtRange) selection.createRange();
+ var range = (IHTMLTxtRange)selection.createRange();
if (range != null)
{
// First paste, than attach (otherwise the range is wrong!)
@@ -330,7 +315,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Create the attachment (if inlined the attachment isn't visible as attachment!)
using var attachments = DisposableCom.Create(mailItem.Attachments);
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName));
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
{
// Add the content id to the attachment, this only works for Outlook >= 2007
try
@@ -356,11 +341,9 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
caption = explorer.ComObject.Caption;
}
-
LOG.Warn($"Problem while trying to add attachment to Item '{caption}'", ex);
return false;
}
-
try
{
if (inspector != null)
@@ -377,7 +360,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Problem activating inspector/explorer: ", ex);
return false;
}
-
LOG.Debug("Finished!");
return true;
}
@@ -394,32 +376,27 @@ namespace Greenshot.Plugin.Office.OfficeExport
///
///
///
- private void ExportToNewEmail(IDisposableCom outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to,
- string cc, string bcc, string url)
+ private void ExportToNewEmail(IDisposableCom outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url)
{
- using var newItem = DisposableCom.Create((MailItem) outlookApplication.ComObject.CreateItem(OlItemType.olMailItem));
+ using var newItem = DisposableCom.Create((MailItem)outlookApplication.ComObject.CreateItem(OlItemType.olMailItem));
if (newItem == null)
{
return;
}
-
var newMail = newItem.ComObject;
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
@@ -431,7 +408,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Error("Problem reading signature!", e);
}
-
switch (format)
{
case EmailFormat.Text:
@@ -445,11 +421,9 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
bodyString = "";
}
-
newMail.Body = bodyString;
}
}
-
break;
default:
string contentId = Path.GetFileName(tmpFile);
@@ -458,7 +432,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName));
// add content ID to the attachment
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
{
try
{
@@ -482,7 +456,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
href = $"";
hrefEnd = "";
}
-
string htmlImgEmbedded = $" {href}{hrefEnd} ";
string fallbackBody = $"{htmlImgEmbedded}";
if (bodyString == null)
@@ -509,15 +482,13 @@ namespace Greenshot.Plugin.Office.OfficeExport
bodyString = fallbackBody;
}
}
-
newMail.HTMLBody = bodyString;
break;
}
-
// So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
newMail.Display(false);
- using var inspector = DisposableCom.Create((_Inspector) newMail.GetInspector);
+ using var inspector = DisposableCom.Create((_Inspector)newMail.GetInspector);
if (inspector != null)
{
try
@@ -557,14 +528,12 @@ namespace Greenshot.Plugin.Office.OfficeExport
exported = true;
}
}
-
return exported;
}
catch (Exception e)
{
LOG.Error("Error while creating an outlook mail item: ", e);
}
-
return exported;
}
@@ -579,7 +548,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
outlookApplication = DisposableCom.Create(new Application());
}
-
InitializeVariables(outlookApplication);
return outlookApplication;
}
@@ -600,12 +568,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no outlook running
return null;
}
-
if ((outlookApplication != null) && (outlookApplication.ComObject != null))
{
InitializeVariables(outlookApplication);
}
-
return outlookApplication;
}
@@ -621,8 +587,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return null;
}
-
- string defaultProfile = (string) profilesKey.GetValue(DefaultProfileValue);
+ string defaultProfile = (string)profilesKey.GetValue(DefaultProfileValue);
LOG.DebugFormat("defaultProfile={0}", defaultProfile);
using var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false);
if (profileKey != null)
@@ -634,21 +599,19 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var numberKey = profileKey.OpenSubKey(number, false);
if (numberKey != null)
{
- byte[] val = (byte[]) numberKey.GetValue(NewSignatureValue);
+ byte[] val = (byte[])numberKey.GetValue(NewSignatureValue);
if (val == null)
{
continue;
}
-
string signatureName = "";
foreach (byte b in val)
{
if (b != 0)
{
- signatureName += (char) b;
+ signatureName += (char)b;
}
}
-
LOG.DebugFormat("Found email signature: {0}", signatureName);
var extension = format switch
{
@@ -665,7 +628,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return null;
}
@@ -680,15 +642,13 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return;
}
-
if (!Version.TryParse(outlookApplication.ComObject.Version, out _outlookVersion))
{
LOG.Warn("Assuming outlook version 1997.");
- _outlookVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
+ _outlookVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0);
}
-
// Preventing retrieval of currentUser if Outlook is older than 2007
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2007)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
{
try
{
@@ -697,7 +657,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser);
_currentUser = currentUser.ComObject.Name;
}
-
LOG.InfoFormat("Current user: {0}", _currentUser);
}
catch (Exception exNs)
@@ -723,7 +682,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
- if (_outlookVersion.Major >= (int) OfficeVersions.Office2013)
+ if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
{
// Check inline "panel" for Outlook 2013
using var activeExplorer = DisposableCom.Create(outlookApplication.ComObject.ActiveExplorer());
@@ -742,17 +701,15 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
inspectorCaptions.Add(caption, mailItem.Class);
}
-
break;
case AppointmentItem appointmentItem:
- if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
+ if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
{
inspectorCaptions.Add(caption, appointmentItem.Class);
}
}
-
break;
}
}
@@ -783,11 +740,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
inspectorCaptions.Add(caption, mailItem.Class);
break;
case AppointmentItem appointmentItem:
- if ((_outlookVersion.Major >= (int) OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
+ if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
{
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
{
@@ -800,7 +756,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
// skip, can't export to olAppointment
continue;
}
-
inspectorCaptions.Add(caption, appointmentItem.Class);
break;
default:
@@ -814,7 +769,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Warn("Problem retrieving word destinations, ignoring: ", ex);
}
-
return inspectorCaptions;
}
}
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs b/GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs
similarity index 94%
rename from src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs
rename to GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs
index 21862f38d..7f87ff111 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs
+++ b/GreenshotOfficePlugin/OfficeExport/PowerpointExporter.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,19 +15,19 @@
// GNU General 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;
using System.Collections.Generic;
using System.Drawing;
-using Greenshot.Base.IniFile;
-using Greenshot.Plugin.Office.Com;
-using Greenshot.Plugin.Office.OfficeInterop;
+using GreenshotOfficePlugin.Com;
+using GreenshotOfficePlugin.OfficeInterop;
+using GreenshotPlugin.IniFile;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using Shape = Microsoft.Office.Interop.PowerPoint.Shape;
-namespace Greenshot.Plugin.Office.OfficeExport
+namespace GreenshotOfficePlugin.OfficeExport
{
///
/// Export logic for powerpoint
@@ -60,7 +60,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
left = pageSetup.ComObject.SlideWidth / 2 - imageSize.Width / 2f;
top = pageSetup.ComObject.SlideHeight / 2 - imageSize.Height / 2f;
}
-
float width = imageSize.Width;
float height = imageSize.Height;
IDisposableCom shapeForCaption = null;
@@ -87,7 +86,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
shapeForLocation.ComObject.Left = left;
}
-
shapeForLocation.ComObject.Width = imageSize.Width;
if (height > shapeForLocation.ComObject.Height)
@@ -100,7 +98,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
top = shapeForLocation.ComObject.Top + shapeForLocation.ComObject.Height / 2 - imageSize.Height / 2f;
}
-
shapeForLocation.ComObject.Height = imageSize.Height;
}
catch (Exception e)
@@ -109,7 +106,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var slides = DisposableCom.Create(presentation.ComObject.Slides);
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank));
}
-
using (var shapes = DisposableCom.Create(slide.ComObject.Shapes))
{
using var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height));
@@ -121,24 +117,20 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
shape.ComObject.LockAspectRatio = MsoTriState.msoFalse;
}
-
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
if (hasScaledWidth)
{
shape.ComObject.Width = width;
}
-
if (hasScaledHeight)
{
shape.ComObject.Height = height;
}
-
shape.ComObject.Left = left;
shape.ComObject.Top = top;
shape.ComObject.AlternativeText = title;
}
-
if (shapeForCaption != null)
{
try
@@ -156,7 +148,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.Warn("Problem setting the title to a text-range", ex);
}
}
-
// Activate/Goto the slide
try
{
@@ -203,12 +194,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
if (!presentation.ComObject.Name.StartsWith(presentationName))
{
continue;
}
-
try
{
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
@@ -220,7 +209,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return false;
}
@@ -235,7 +223,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
powerPointApplication = DisposableCom.Create(new Application());
}
-
InitializeVariables(powerPointApplication);
return powerPointApplication;
}
@@ -256,12 +243,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no PowerPoint running
return null;
}
-
if (powerPointApplication?.ComObject != null)
{
InitializeVariables(powerPointApplication);
}
-
return powerPointApplication;
}
@@ -286,12 +271,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue)
{
continue;
}
-
if (IsAfter2003())
{
if (presentation.ComObject.Final)
@@ -299,7 +282,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
continue;
}
}
-
yield return presentation.ComObject.Name;
}
}
@@ -314,11 +296,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return;
}
-
if (!Version.TryParse(powerpointApplication.ComObject.Version, out _powerpointVersion))
{
LOG.Warn("Assuming Powerpoint version 1997.");
- _powerpointVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
+ _powerpointVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0);
}
}
@@ -351,13 +332,13 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return isPictureAdded;
}
private bool IsAfter2003()
{
- return _powerpointVersion.Major > (int) OfficeVersions.Office2003;
+ return _powerpointVersion.Major > (int)OfficeVersions.Office2003;
}
}
+
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs b/GreenshotOfficePlugin/OfficeExport/WordExporter.cs
similarity index 93%
rename from src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs
rename to GreenshotOfficePlugin/OfficeExport/WordExporter.cs
index 8100bf650..b44f08161 100644
--- a/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs
+++ b/GreenshotOfficePlugin/OfficeExport/WordExporter.cs
@@ -1,7 +1,7 @@
// 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/
+// 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
@@ -15,18 +15,18 @@
// GNU General 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;
using System.Collections.Generic;
-using Greenshot.Base.IniFile;
-using Greenshot.Plugin.Office.Com;
-using Greenshot.Plugin.Office.OfficeInterop;
+using GreenshotOfficePlugin.Com;
+using GreenshotOfficePlugin.OfficeInterop;
+using GreenshotPlugin.IniFile;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Word;
using Version = System.Version;
-namespace Greenshot.Plugin.Office.OfficeExport
+namespace GreenshotOfficePlugin.OfficeExport
{
///
/// This makes it possible to export to word
@@ -53,7 +53,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
}
-
selection.ComObject.InsertAfter("\r\n");
selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing);
return shape;
@@ -70,7 +69,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
wordApplication = DisposableCom.Create(new Application());
}
-
InitializeVariables(wordApplication);
return wordApplication;
}
@@ -91,12 +89,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
// Ignore, probably no word running
return null;
}
-
if ((wordApplication != null) && (wordApplication.ComObject != null))
{
InitializeVariables(wordApplication);
}
-
return wordApplication;
}
@@ -120,7 +116,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
continue;
}
-
if (IsAfter2003())
{
if (document.ComObject.Final)
@@ -144,11 +139,10 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return;
}
-
if (!Version.TryParse(wordApplication.ComObject.Version, out _wordVersion))
{
LOG.Warn("Assuming Word version 1997.");
- _wordVersion = new Version((int) OfficeVersions.Office97, 0, 0, 0);
+ _wordVersion = new Version((int)OfficeVersions.Office97, 0, 0, 0);
}
}
@@ -170,7 +164,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
using var documents = DisposableCom.Create(wordApplication.ComObject.Documents);
for (int i = 1; i <= documents.ComObject.Count; i++)
{
- using var wordDocument = DisposableCom.Create((_Document) documents.ComObject[i]);
+ using var wordDocument = DisposableCom.Create((_Document)documents.ComObject[i]);
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
if (activeWindow.ComObject.Caption.StartsWith(wordCaption))
{
@@ -178,7 +172,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
return false;
}
@@ -191,8 +184,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
/// string
/// string with the tooltip of the image
/// bool
- internal bool InsertIntoExistingDocument(IDisposableCom wordApplication, IDisposableCom<_Document> wordDocument, string tmpFile, string address,
- string tooltip)
+ internal bool InsertIntoExistingDocument(IDisposableCom wordApplication, IDisposableCom<_Document> 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!
@@ -212,7 +204,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.InfoFormat("No selection to insert {0} into found.", tmpFile);
return false;
}
-
// Add Picture
using (var shape = AddPictureToSelection(selection, tmpFile))
{
@@ -223,7 +214,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
screentip = tooltip;
}
-
try
{
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
@@ -235,7 +225,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
try
{
// When called for Outlook, the follow error is created: This object model command is not available in e-mail
@@ -256,7 +245,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
LOG.WarnFormat("Couldn't set zoom to 100, error: {0}", e.Message);
}
}
-
try
{
wordApplication.ComObject.Activate();
@@ -266,7 +254,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Warn("Error activating word application", ex);
}
-
try
{
wordDocument.ComObject.Activate();
@@ -276,7 +263,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Warn("Error activating word document", ex);
}
-
return true;
}
@@ -293,7 +279,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
return;
}
-
wordApplication.ComObject.Visible = true;
wordApplication.ComObject.Activate();
// Create new Document
@@ -314,7 +299,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
screentip = tooltip;
}
-
try
{
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
@@ -329,7 +313,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
}
}
}
-
try
{
wordDocument.ComObject.Activate();
@@ -339,7 +322,6 @@ namespace Greenshot.Plugin.Office.OfficeExport
{
LOG.Warn("Error activating word document", ex);
}
-
try
{
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
@@ -358,7 +340,7 @@ namespace Greenshot.Plugin.Office.OfficeExport
///
private bool IsAfter2003()
{
- return _wordVersion.Major > (int) OfficeVersions.Office2003;
+ return _wordVersion.Major > (int)OfficeVersions.Office2003;
}
}
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Office/OfficeInterop/EmailFormat.cs b/GreenshotOfficePlugin/OfficeInterop/EmailFormat.cs
similarity index 71%
rename from src/Greenshot.Plugin.Office/OfficeInterop/EmailFormat.cs
rename to GreenshotOfficePlugin/OfficeInterop/EmailFormat.cs
index d01a289f4..2de5cbf71 100644
--- a/src/Greenshot.Plugin.Office/OfficeInterop/EmailFormat.cs
+++ b/GreenshotOfficePlugin/OfficeInterop/EmailFormat.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,23 +15,22 @@
// GNU General 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.Office.OfficeInterop
+namespace GreenshotOfficePlugin.OfficeInterop
{
- ///
- /// Specifies which EmailFormat the email needs to use
- ///
- public enum EmailFormat
- {
+ ///
+ /// Specifies which EmailFormat the email needs to use
+ ///
+ public enum EmailFormat
+ {
///
/// Use the plain text format
///
- Text,
-
+ Text,
///
/// Use HTML format
///
- Html
- }
+ Html
+ }
}
\ No newline at end of file
diff --git a/src/Greenshot.Plugin.Office/OfficeInterop/OfficeVersions.cs b/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs
similarity index 67%
rename from src/Greenshot.Plugin.Office/OfficeInterop/OfficeVersions.cs
rename to GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs
index e39d000ff..03943e4db 100644
--- a/src/Greenshot.Plugin.Office/OfficeInterop/OfficeVersions.cs
+++ b/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs
@@ -1,7 +1,7 @@
// 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/
+// For more information see: http://getgreenshot.org/
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
//
// This program is free software: you can redistribute it and/or modify
@@ -15,48 +15,50 @@
// GNU General 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.Office.OfficeInterop
+namespace GreenshotOfficePlugin.OfficeInterop
{
- ///
- /// A mapping between the version and a usable name
- ///
- public enum OfficeVersions
- {
+ ///
+ /// A mapping between the version and a usable name
+ ///
+ public enum OfficeVersions
+ {
///
/// Office 97
///
- Office97 = 8,
-
+ Office97 = 8,
+ ///
+ /// Office 2000
+ ///
+ Office2000 = 9,
+ ///
+ /// Office 2002
+ ///
+ Office2002 = 10,
///
/// Office 2003
///
- Office2003 = 11,
-
+ Office2003 = 11,
///
/// Office 2007
///
- Office2007 = 12,
-
+ Office2007 = 12,
///
/// Office 2010
///
- Office2010 = 14,
-
+ Office2010 = 14,
///
/// Office 2013
///
- Office2013 = 15,
-
+ Office2013 = 15,
///
/// Office 2016
///
Office2016 = 16,
-
///
/// Office 2019
///
Office2019 = 17
- }
+ }
}
\ No newline at end of file
diff --git a/GreenshotOfficePlugin/OfficePlugin.cs b/GreenshotOfficePlugin/OfficePlugin.cs
new file mode 100644
index 000000000..6a17626a8
--- /dev/null
+++ b/GreenshotOfficePlugin/OfficePlugin.cs
@@ -0,0 +1,115 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using GreenshotOfficePlugin.Destinations;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotOfficePlugin {
+ ///
+ /// This is the OfficePlugin base code
+ ///
+ [Plugin("Office", false)]
+ 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
+ }
+
+ private 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;
+ }
+ }
+
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize() {
+ SimpleServiceProvider.Current.AddService(Destinations());
+ return true;
+ }
+
+ public void Shutdown() {
+ LOG.Debug("Office Plugin shutdown.");
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public void Configure() {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs b/GreenshotOfficePlugin/Properties/AssemblyInfo.cs
similarity index 83%
rename from src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs
rename to GreenshotOfficePlugin/Properties/AssemblyInfo.cs
index 6b14a40f5..3e2563a07 100644
--- a/src/Greenshot.Plugin.Office/Properties/AssemblyInfo.cs
+++ b/GreenshotOfficePlugin/Properties/AssemblyInfo.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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,17 @@
* GNU General 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 export images to Office applications")]
-[assembly: AssemblyPluginIdentifier("Office Plugin")]
// 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)]
diff --git a/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs b/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs
new file mode 100644
index 000000000..70971ca61
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/Forms/PhotobucketForm.cs
@@ -0,0 +1,28 @@
+/*
+ * 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 GreenshotPhotobucketPlugin.Forms {
+ ///
+ /// 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 80%
rename from src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs
rename to GreenshotPhotobucketPlugin/Forms/SettingsForm.Designer.cs
index 1fff9f5c3..4a0486dd1 100644
--- a/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs
+++ b/GreenshotPhotobucketPlugin/Forms/SettingsForm.Designer.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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.Forms {
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;
@@ -102,7 +99,7 @@ namespace Greenshot.Plugin.Photobucket.Forms {
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 +124,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..1d221b2a9
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/Forms/SettingsForm.cs
@@ -0,0 +1,37 @@
+/*
+ * 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 GreenshotPhotobucketPlugin.Forms {
+ ///
+ /// 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/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.Credentials.template
similarity index 96%
rename from src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template
rename to GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.Credentials.template
index 8895f5a73..312099888 100644
--- a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.Credentials.template
+++ b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.Credentials.template
@@ -19,7 +19,7 @@
* along with this program. If not, see .
*/
-namespace Greenshot.Plugin.Photobucket {
+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
diff --git a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj
similarity index 52%
rename from src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj
rename to GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj
index d0151b7c0..bab11d46e 100644
--- a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj
+++ b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj
@@ -1,8 +1,10 @@
-
- none
- false
+
+
+ GreenshotPhotobucketPlugin
+ GreenshotPhotobucketPlugin
+
PreserveNewest
@@ -10,6 +12,6 @@
-
+
diff --git a/GreenshotPhotobucketPlugin/LanguageKeys.cs b/GreenshotPhotobucketPlugin/LanguageKeys.cs
new file mode 100644
index 000000000..b94f13722
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/LanguageKeys.cs
@@ -0,0 +1,34 @@
+/*
+ * 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 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 96%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-it-IT.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-it-IT.xml
index 233153065..3ec36383f 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
+
+
+ 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
+
+
+
diff --git a/src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ja-JP.xml b/GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ja-JP.xml
similarity index 100%
rename from src/Greenshot.Plugin.Photobucket/Languages/language_photobucket-ja-JP.xml
rename to GreenshotPhotobucketPlugin/Languages/language_photobucketplugin-ja-JP.xml
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..8136adbff
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs
@@ -0,0 +1,74 @@
+/*
+ * 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 .
+ */
+using System.Windows.Forms;
+using GreenshotPhotobucketPlugin.Forms;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+
+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("Photobucket", 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/GreenshotPhotobucketPlugin/PhotobucketDestination.cs b/GreenshotPhotobucketPlugin/PhotobucketDestination.cs
new file mode 100644
index 000000000..96dc98926
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketDestination.cs
@@ -0,0 +1,101 @@
+/*
+ * 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 .
+ */
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Drawing;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+
+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 = null) {
+ _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);
+ bool uploaded = _plugin.Upload(captureDetails, surface, _albumPath, out var 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..b9759eb3c
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketInfo.cs
@@ -0,0 +1,67 @@
+/*
+ * 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 .
+ */
+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..a9670a6a2
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketPlugin.cs
@@ -0,0 +1,141 @@
+/*
+ * 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 .
+ */
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotPhotobucketPlugin {
+ ///
+ /// This is the GreenshotPhotobucketPlugin base code
+ ///
+ [Plugin("Photobucket", true)]
+ public class PhotobucketPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PhotobucketPlugin));
+ private static PhotobucketConfiguration _config;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+ if (_itemPlugInConfig == null) return;
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ /// true if plugin is initialized, false if not (doesn't show)
+ public bool Initialize() {
+ SimpleServiceProvider.Current.AddService(new PhotobucketDestination(this));
+
+ // Get configuration
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(PhotobucketPlugin));
+
+ _itemPlugInConfig = new ToolStripMenuItem(Language.GetString("photobucket", LangKey.configure))
+ {
+ Image = (Image)_resources.GetObject("Photobucket")
+ };
+ _itemPlugInConfig.Click += delegate {
+ _config.ShowConfigDialog();
+ };
+
+ PluginUtils.AddToContextMenu(_itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("photobucket", LangKey.configure);
+ }
+ }
+
+ public void Shutdown() {
+ Log.Debug("Photobucket Plugin shutdown.");
+ Language.LanguageChanged -= OnLanguageChanged;
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public 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("Photobucket", 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 100%
rename from src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.resx
rename to GreenshotPhotobucketPlugin/PhotobucketPlugin.resx
diff --git a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs
new file mode 100644
index 000000000..4226e57c4
--- /dev/null
+++ b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs
@@ -0,0 +1,224 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Xml;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+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
+ { "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/src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs b/GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs
similarity index 83%
rename from src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs
rename to GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs
index 231ca594d..99952c5c0 100644
--- a/src/Greenshot.Plugin.Photobucket/Properties/AssemblyInfo.cs
+++ b/GreenshotPhotobucketPlugin/Properties/AssemblyInfo.cs
@@ -2,7 +2,7 @@
* 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/
+ * For more information see: http://getgreenshot.org/
* 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,19 @@
* GNU General 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")]
// 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)]
+
diff --git a/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs b/GreenshotPicasaPlugin/Forms/PicasaForm.cs
similarity index 67%
rename from src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs
rename to GreenshotPicasaPlugin/Forms/PicasaForm.cs
index 84471d011..cea5a2f35 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,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.GooglePhotos.Forms
-{
- public class GooglePhotosForm : GreenshotForm
- {
- }
-}
\ No newline at end of file
+namespace GreenshotPicasaPlugin.Forms {
+ 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..38555c179 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs
+++ b/GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs
@@ -1,150 +1,147 @@
-/*
- * 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.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 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.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..a6691a424
--- /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.Forms {
+ ///
+ /// 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/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template
similarity index 83%
rename from src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template
rename to GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template
index c4ff6bfc6..47172f2d4 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.Credentials.template
+++ b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template
@@ -19,13 +19,13 @@
* along with this program. If not, see .
*/
-namespace Greenshot.Plugin.GooglePhotos {
+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 GooglePhotosCredentials {
- public static string ClientId = "${GooglePhotos_ClientId}";
- public static string ClientSecret = "${GooglePhotos_ClientSecret}";
+ public static class PicasaCredentials {
+ public static string ClientId = "${Picasa_ClientId}";
+ public static string ClientSecret = "${Picasa_ClientSecret}";
}
}
diff --git a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj
similarity index 52%
rename from src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj
rename to GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj
index 8bdb8bcb4..ac827cfec 100644
--- a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj
+++ b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj
@@ -1,8 +1,10 @@
-
- none
- false
+
+
+ GreenshotPicasaPlugin
+ GreenshotPicasaPlugin
+
PreserveNewest
@@ -10,10 +12,10 @@
-
+
-
+
\ 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/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-it-IT.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml
similarity index 73%
rename from src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-it-IT.xml
rename to GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml
index 801e57cfd..6f0b76c78 100644
--- a/src/Greenshot.Plugin.GooglePhotos/Languages/language_googlephotos-it-IT.xml
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml
@@ -1,32 +1,32 @@
-
-
-
-
- Collegamento agli Appunti
-
-
- Dopo il caricamento
-
-
- Impostazioni GooglePhotos
-
-
- Carica su GooglePhotos
-
-
- Impostazioni GooglePhotos
-
-
- Caricamento immagine su GooglePhotos completato!
-
-
- Si è verificato un errore durante il caricamento su GooglePhotos:
-
-
- Formato immagine
-
-
- Comunicazione con GooglePhotos...
-
-
-
+
+
+
+
+ Collegamento agli Appunti
+
+
+ Dopo il caricamento
+
+
+ Impostazioni Picasa
+
+
+ Carica su Picasa
+
+
+ Impostazioni Picasa
+
+
+ Caricamento immagine su Picasa completato!
+
+
+ Si è verificato un errore durante il caricamento su Picasa:
+
+
+ Formato immagine
+
+
+ Comunicazione con Picasa...
+
+
+
diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml
new file mode 100644
index 000000000..ac8216e96
--- /dev/null
+++ b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml
@@ -0,0 +1,14 @@
+
+
+
+ リンクをクリップボードへコピー
+ アップロード後
+ Picasa の設定
+ Picasa にアップロード
+ Picasa の設定
+ Picasa へのアップロードに成功しました!
+ Picasa へのアップロード中にエラーが発生しました:
+ 画像フォーマット
+ 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 PicasaTicki yemmed usaliNɣel aseɣwen ɣef afusAmsal 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..202929459
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaConfiguration.cs
@@ -0,0 +1,93 @@
+/*
+ * 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 GreenshotPlugin.Core;
+using System;
+using GreenshotPicasaPlugin.Forms;
+using GreenshotPlugin.IniFile;
+
+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/GreenshotPicasaPlugin/PicasaDestination.cs b/GreenshotPicasaPlugin/PicasaDestination.cs
new file mode 100644
index 000000000..4107ecd48
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaDestination.cs
@@ -0,0 +1,54 @@
+/*
+ * 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 GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces;
+
+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);
+ bool uploaded = _plugin.Upload(captureDetails, surface, out var 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..a8f312484
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaPlugin.cs
@@ -0,0 +1,125 @@
+/*
+ * 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.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using GreenshotPlugin.Controls;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+namespace GreenshotPicasaPlugin {
+ ///
+ /// This is the Picasa base code
+ ///
+ [Plugin("Picasa", true)]
+ public class PicasaPlugin : IGreenshotPlugin {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PicasaPlugin));
+ private static PicasaConfiguration _config;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInRoot;
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void Dispose(bool disposing) {
+ if (disposing) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Dispose();
+ _itemPlugInRoot = null;
+ }
+ }
+ }
+
+ ///
+ /// Implementation of the IGreenshotPlugin.Initialize
+ ///
+ public bool Initialize() {
+ SimpleServiceProvider.Current.AddService(new PicasaDestination(this));
+
+ // Get configuration
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(PicasaPlugin));
+
+ _itemPlugInRoot = new ToolStripMenuItem
+ {
+ Text = Language.GetString("picasa", LangKey.Configure),
+ Image = (Image) _resources.GetObject("Picasa")
+ };
+ _itemPlugInRoot.Click += ConfigMenuClick;
+ PluginUtils.AddToContextMenu(_itemPlugInRoot);
+ Language.LanguageChanged += OnLanguageChanged;
+ return true;
+ }
+
+ public void OnLanguageChanged(object sender, EventArgs e) {
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Text = Language.GetString("picasa", LangKey.Configure);
+ }
+ }
+
+ public void Shutdown() {
+ Log.Debug("Picasa Plugin shutdown.");
+ Language.LanguageChanged -= OnLanguageChanged;
+ //host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened);
+ }
+
+ ///
+ /// Implementation of the IPlugin.Configure
+ ///
+ public 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("Picasa", 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 96%
rename from src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.resx
rename to GreenshotPicasaPlugin/PicasaPlugin.resx
index 240e4a53e..de5045226 100644
--- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.resx
+++ b/GreenshotPicasaPlugin/PicasaPlugin.resx
@@ -118,7 +118,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.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=4.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..eb2b2be2e
--- /dev/null
+++ b/GreenshotPicasaPlugin/PicasaUtils.cs
@@ -0,0 +1,119 @@
+/*
+ * 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 GreenshotPlugin.Core;
+using System;
+using System.Xml;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+
+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/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs b/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..3a917ddcd
--- /dev/null
+++ b/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,32 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2021 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.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: AssemblyDescription("A plugin to upload images to Picasa")]
+
+// 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)]
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..55d6e1865
--- /dev/null
+++ b/GreenshotPlugin/Controls/AnimatingForm.cs
@@ -0,0 +1,128 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Windows.Forms;
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.UnmanagedHelpers.Enums;
+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 93%
rename from src/Greenshot.Base/Controls/BackgroundForm.Designer.cs
rename to GreenshotPlugin/Controls/BackgroundForm.Designer.cs
index 331dedd48..cafbb6e18 100644
--- a/src/Greenshot.Base/Controls/BackgroundForm.Designer.cs
+++ b/GreenshotPlugin/Controls/BackgroundForm.Designer.cs
@@ -1,96 +1,96 @@
-/*
- * 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-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 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.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;
+ }
+}
diff --git a/GreenshotPlugin/Controls/BackgroundForm.cs b/GreenshotPlugin/Controls/BackgroundForm.cs
new file mode 100644
index 000000000..5ce737185
--- /dev/null
+++ b/GreenshotPlugin/Controls/BackgroundForm.cs
@@ -0,0 +1,100 @@
+/*
+ * 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 .
+ */
+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..c18a2071f
--- /dev/null
+++ b/GreenshotPlugin/Controls/ExtendedWebBrowser.cs
@@ -0,0 +1,58 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Windows.Forms;
+using GreenshotPlugin.Interop;
+
+namespace GreenshotPlugin.Controls {
+ public class ExtendedWebBrowser : WebBrowser {
+ protected class ExtendedWebBrowserSite : WebBrowserSite, IOleCommandTarget {
+ private const int OLECMDID_SHOWSCRIPTERROR = 40;
+
+ 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);
+
+ public ExtendedWebBrowserSite(WebBrowser wb) : base(wb) {
+ }
+
+ 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;
+ }
+ }
+
+ 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 76%
rename from src/Greenshot.Base/Controls/FormWithoutActivation.cs
rename to GreenshotPlugin/Controls/FormWithoutActivation.cs
index 0a69bc043..4491bbf2b 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-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 .
+ */
+
+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..16288ce43
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotButton.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..e7e3483ab
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotCheckBox.cs
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+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..efad46cd0
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotColumnSorter.cs
@@ -0,0 +1,118 @@
+/*
+ * 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 .
+ */
+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..c9f0b3d9e
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotComboBox.cs
@@ -0,0 +1,104 @@
+/*
+ * 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 .
+ */
+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..1375c0b7a
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotForm.cs
@@ -0,0 +1,526 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using System.Reflection;
+using GreenshotPlugin.Core;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.IO;
+using GreenshotPlugin.IniFile;
+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) return;
+ _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) return;
+ if (!"LanguageKey".Equals(ce.Member.Name)) return;
+ if (ce.Component is Control control) {
+ LOG.InfoFormat("Changing LanguageKey for {0} to {1}", control.Name, ce.NewValue);
+ ApplyLanguage(control, (string)ce.NewValue);
+ } else {
+ if (ce.Component is ToolStripItem item) {
+ 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) return;
+ if (ce.Component is Control control) {
+ if (!_designTimeControls.ContainsKey(control.Name)) {
+ _designTimeControls.Add(control.Name, control);
+ } else {
+ _designTimeControls[control.Name] = control;
+ }
+ }
+ else
+ {
+ if (ce.Component is ToolStripItem stripItem) {
+ 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) {
+ if (applyTo is IGreenshotLanguageBindable languageBindable) {
+ ApplyLanguage(applyTo, languageBindable.LanguageKey);
+ }
+ }
+
+ protected void ApplyLanguage(Control applyTo) {
+ if (!(applyTo is IGreenshotLanguageBindable languageBindable)) {
+ // check if it's a menu!
+ if (!(applyTo is ToolStrip toolStrip))
+ {
+ return;
+ }
+ foreach (ToolStripItem item in toolStrip.Items) {
+ ApplyLanguage(item);
+ }
+ return;
+ }
+
+ // Apply language text to the control
+ ApplyLanguage(applyTo, languageBindable.LanguageKey);
+
+ // Repopulate the combox boxes
+ if (applyTo is IGreenshotConfigBindable configBindable && applyTo is GreenshotComboBox comboxBox) {
+ 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) {
+ if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out var 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
+ if (!string.IsNullOrEmpty(LanguageKey) && Language.TryGetString(LanguageKey, out var 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;
+ }
+
+ if (!(controlObject is Control applyToControl)) {
+ 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) {
+ if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) {
+ LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'",configBindable.PropertyName,field.Name);
+ continue;
+ }
+
+ if (controlObject is CheckBox checkBox) {
+ checkBox.Checked = (bool)iniValue.Value;
+ checkBox.Enabled = !iniValue.IsFixed;
+ continue;
+ }
+
+ if (controlObject is RadioButton radíoButton) {
+ radíoButton.Checked = (bool)iniValue.Value;
+ radíoButton.Enabled = !iniValue.IsFixed;
+ continue;
+ }
+
+ if (controlObject is TextBox textBox) {
+ if (controlObject is HotkeyControl hotkeyControl) {
+ 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;
+ }
+
+ if (controlObject is GreenshotComboBox comboxBox) {
+ 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) {
+ if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) {
+ continue;
+ }
+
+ if (controlObject is CheckBox checkBox) {
+ iniValue.Value = checkBox.Checked;
+ iniDirty = true;
+ continue;
+ }
+
+ if (controlObject is RadioButton radioButton) {
+ iniValue.Value = radioButton.Checked;
+ iniDirty = true;
+ continue;
+ }
+
+ if (controlObject is TextBox textBox) {
+ if (controlObject is HotkeyControl hotkeyControl) {
+ iniValue.Value = hotkeyControl.ToString();
+ iniDirty = true;
+ continue;
+ }
+ iniValue.UseValueOrDefault(textBox.Text);
+ iniDirty = true;
+ continue;
+ }
+
+ if (controlObject is GreenshotComboBox comboxBox) {
+ 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..954027948
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotGroupBox.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..887bdb2ea
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotLabel.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..ca68fb284
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotRadioButton.cs
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+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..6941a861a
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotTabPage.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..a4f743f25
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotTextBox.cs
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+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..e9a9edb7d
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..06bf59597
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripButton.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..5bee42167
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..8547b65c8
--- /dev/null
+++ b/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 .
+ */
+
+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..6e6557522
--- /dev/null
+++ b/GreenshotPlugin/Controls/HotkeyControl.cs
@@ -0,0 +1,582 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+using log4net;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.Interfaces.Plugin;
+
+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 ContextMenuStrip _dummy = new ContextMenuStrip();
+
+ ///
+ /// Used to make sure that there is no right-click menu available
+ ///
+ public override ContextMenuStrip ContextMenuStrip
+ {
+ get {
+ return _dummy;
+ }
+ set {
+ base.ContextMenuStrip = _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() {
+ ContextMenuStrip = _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 = string.Empty;
+ 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 = string.Empty;
+ 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 = string.Empty;
+ 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 = string.Empty;
+ 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;
+ }
+
+ if (KeyHandlers.TryGetValue((int)m.WParam, out var 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("*", string.Empty).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("*", string.Empty).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..d20ed1cd1
--- /dev/null
+++ b/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs
@@ -0,0 +1,40 @@
+/*
+ * 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 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..06237dcc9
--- /dev/null
+++ b/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs
@@ -0,0 +1,36 @@
+/*
+ * 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 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 92%
rename from src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs
rename to GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs
index cac4d8528..abf92060c 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-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 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(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;
+
+ }
+}
diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.cs b/GreenshotPlugin/Controls/OAuthLoginForm.cs
new file mode 100644
index 000000000..e2b036f97
--- /dev/null
+++ b/GreenshotPlugin/Controls/OAuthLoginForm.cs
@@ -0,0 +1,108 @@
+/*
+ * 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 .
+ */
+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 93%
rename from src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs
rename to GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs
index 26fc19d38..a3ab2832b 100644
--- a/src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs
+++ b/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs
@@ -1,99 +1,99 @@
-/*
- * 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-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 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.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;
+ }
+}
diff --git a/GreenshotPlugin/Controls/PleaseWaitForm.cs b/GreenshotPlugin/Controls/PleaseWaitForm.cs
new file mode 100644
index 000000000..fecd1afc9
--- /dev/null
+++ b/GreenshotPlugin/Controls/PleaseWaitForm.cs
@@ -0,0 +1,124 @@
+/*
+ * 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 .
+ */
+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 |= 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 88%
rename from src/Greenshot.Base/Controls/QualityDialog.Designer.cs
rename to GreenshotPlugin/Controls/QualityDialog.Designer.cs
index 725b17328..5f1c03fce 100644
--- a/src/Greenshot.Base/Controls/QualityDialog.Designer.cs
+++ b/GreenshotPlugin/Controls/QualityDialog.Designer.cs
@@ -1,147 +1,147 @@
-/*
- * 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-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 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.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..0e196f387
--- /dev/null
+++ b/GreenshotPlugin/Controls/QualityDialog.cs
@@ -0,0 +1,67 @@
+/*
+ * 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 .
+ */
+using System;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces.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..0245dc05e
--- /dev/null
+++ b/GreenshotPlugin/Controls/SaveImageFileDialog.cs
@@ -0,0 +1,203 @@
+/*
+ * 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 .
+ */
+using System;
+using System.IO;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+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 = string.Empty;
+ 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..3578b63d3
--- /dev/null
+++ b/GreenshotPlugin/Controls/ThumbnailForm.cs
@@ -0,0 +1,120 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Windows.Forms;
+using GreenshotPlugin.Core;
+using System.Drawing;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.UnmanagedHelpers.Enums;
+using GreenshotPlugin.UnmanagedHelpers.Structs;
+
+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) {
+ DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var 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..7efa0f570
--- /dev/null
+++ b/GreenshotPlugin/Core/AbstractDestination.cs
@@ -0,0 +1,350 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Threading;
+using System.Windows.Forms;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+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) {
+ if (!(obj is IDestination other)) {
+ 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.ScaledIconSize,
+ Tag = null,
+ TopLevel = true
+ };
+
+ menu.Opening += (sender, args) =>
+ {
+ // find the DPI settings for the screen where this is going to land
+ var screenDpi = DpiHelper.GetDpi(menu.Location);
+ var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, screenDpi);
+ menu.SuspendLayout();
+ var fontSize = DpiHelper.ScaleWithDpi(12f, screenDpi);
+ menu.Font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
+ menu.ImageScalingSize = scaledIconSize;
+ menu.ResumeLayout();
+ };
+
+ 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(SimpleServiceProvider.Current.GetInstance().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..f93a405fb
--- /dev/null
+++ b/GreenshotPlugin/Core/AbstractProcessor.cs
@@ -0,0 +1,63 @@
+/*
+ * 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 .
+ */
+using System;
+using GreenshotPlugin.Interfaces;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of AbstractProcessor.
+ ///
+ public abstract class AbstractProcessor : IProcessor {
+
+ public virtual int CompareTo(object obj) {
+ if (!(obj is IProcessor other)) {
+ 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 void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ //if (disposing) {}
+ }
+
+ public virtual bool isActive => 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..871892e64
--- /dev/null
+++ b/GreenshotPlugin/Core/AccessibleHelper.cs
@@ -0,0 +1,276 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using Accessibility;
+
+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 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);
+
+ 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 {
+ object[] res = GetAccessibleChildren(accessible, out var num);
+ if (res == null) {
+ return new Accessible[0];
+ }
+
+ List list = new List(res.Length);
+ foreach (object obj in res) {
+ if (obj is IAccessible acc) {
+ 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) {
+ accessible = acc ?? throw new Exception();
+ }
+
+ 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..9ed92eef6
--- /dev/null
+++ b/GreenshotPlugin/Core/AnimationHelpers.cs
@@ -0,0 +1,547 @@
+/*
+ * 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 .
+ */
+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 =>
+ EasingMode switch
+ {
+ EasingMode.EaseOut => Easing.EaseOut(CurrentFrameNr / (double) Frames, EasingType),
+ EasingMode.EaseInOut => Easing.EaseInOut(CurrentFrameNr / (double) Frames, EasingType),
+ EasingMode.EaseIn => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType),
+ _ => 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) =>
+ type switch
+ {
+ EasingType.Step => (linearStep < 0.5 ? 0 : 1),
+ EasingType.Linear => linearStep,
+ EasingType.Sine => Sine.EaseIn(linearStep),
+ EasingType.Quadratic => Power.EaseIn(linearStep, 2),
+ EasingType.Cubic => Power.EaseIn(linearStep, 3),
+ EasingType.Quartic => Power.EaseIn(linearStep, 4),
+ EasingType.Quintic => Power.EaseIn(linearStep, 5),
+ _ => throw new NotImplementedException()
+ };
+
+ public static double EaseOut(double linearStep, EasingType type) =>
+ type switch
+ {
+ EasingType.Step => (linearStep < 0.5 ? 0 : 1),
+ EasingType.Linear => linearStep,
+ EasingType.Sine => Sine.EaseOut(linearStep),
+ EasingType.Quadratic => Power.EaseOut(linearStep, 2),
+ EasingType.Cubic => Power.EaseOut(linearStep, 3),
+ EasingType.Quartic => Power.EaseOut(linearStep, 4),
+ EasingType.Quintic => 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) =>
+ type switch
+ {
+ EasingType.Step => (linearStep < 0.5 ? 0 : 1),
+ EasingType.Linear => linearStep,
+ EasingType.Sine => Sine.EaseInOut(linearStep),
+ EasingType.Quadratic => Power.EaseInOut(linearStep, 2),
+ EasingType.Cubic => Power.EaseInOut(linearStep, 3),
+ EasingType.Quartic => Power.EaseInOut(linearStep, 4),
+ EasingType.Quintic => 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..1d8af4700
--- /dev/null
+++ b/GreenshotPlugin/Core/BinaryStructHelper.cs
@@ -0,0 +1,93 @@
+/*
+ * 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 .
+ */
+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..857f5327a
--- /dev/null
+++ b/GreenshotPlugin/Core/Cache.cs
@@ -0,0 +1,214 @@
+/*
+ * 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 .
+ */
+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;
+ 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/src/Greenshot.Base/Core/Capture.cs b/GreenshotPlugin/Core/Capture.cs
similarity index 69%
rename from src/Greenshot.Base/Core/Capture.cs
rename to GreenshotPlugin/Core/Capture.cs
index 0be688727..95a7fb872 100644
--- a/src/Greenshot.Base/Core/Capture.cs
+++ b/GreenshotPlugin/Core/Capture.cs
@@ -1,119 +1,75 @@
-/*
- * 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.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
-using Dapplo.Windows.Common.Extensions;
-using Dapplo.Windows.Common.Structs;
-using Dapplo.Windows.User32;
-using Greenshot.Base.Interfaces;
-using Greenshot.Base.Interfaces.Ocr;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Ocr;
using log4net;
-namespace Greenshot.Base.Core
+namespace GreenshotPlugin.Core
{
///
/// This class is used to pass an instance of the "Capture" around
/// Having the Bitmap, eventually the Windows Title and cursor all together.
///
- public class Capture : ICapture
- {
+ public class Capture : ICapture {
private static readonly ILog Log = LogManager.GetLogger(typeof(Capture));
+ private List _elements = new List();
- private NativeRect _screenBounds;
-
+ private Rectangle _screenBounds;
///
/// Get/Set the screen bounds
///
- public NativeRect ScreenBounds
- {
- get
- {
- if (_screenBounds.IsEmpty)
- {
- _screenBounds = DisplayInfo.ScreenBounds;
+ public Rectangle ScreenBounds {
+ get {
+ if (_screenBounds == Rectangle.Empty) {
+ _screenBounds = WindowCapture.GetScreenBounds();
}
-
return _screenBounds;
}
set => _screenBounds = value;
}
private Image _image;
-
///
/// Get/Set the Image
///
- public Image Image
- {
+ public Image Image {
get => _image;
- set
- {
+ set {
_image?.Dispose();
_image = value;
- if (value != null)
- {
- if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) ||
- value.PixelFormat.Equals(PixelFormat.Format4bppIndexed))
- {
+ if (value != null) {
+ if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format4bppIndexed)) {
Log.Debug("Converting Bitmap to PixelFormat.Format32bppArgb as we don't support: " + value.PixelFormat);
- try
- {
+ try {
// Default Bitmap PixelFormat is Format32bppArgb
_image = new Bitmap(value);
- }
- finally
- {
- // Always dispose, even when a exception occurred
+ } finally {
+ // Always dispose, even when a exception occured
value.Dispose();
}
}
-
Log.DebugFormat("Image is set with the following specifications: {0} - {1}", _image.Size, _image.PixelFormat);
- }
- else
- {
+ } else {
Log.Debug("Image is removed.");
}
}
}
- public void NullImage()
- {
+ public void NullImage() {
_image = null;
}
private Icon _cursor;
-
///
/// Get/Set the image for the Cursor
///
- public Icon Cursor
- {
+ public Icon Cursor {
get => _cursor;
- set
- {
+ set {
_cursor?.Dispose();
- _cursor = (Icon) value.Clone();
+ _cursor = (Icon)value.Clone();
}
}
@@ -127,45 +83,38 @@ namespace Greenshot.Base.Core
///
public bool CursorVisible { get; set; }
- private NativePoint _cursorLocation = NativePoint.Empty;
-
+ private Point _cursorLocation = Point.Empty;
///
/// Get/Set the CursorLocation
///
- public NativePoint CursorLocation
- {
+ public Point CursorLocation {
get => _cursorLocation;
set => _cursorLocation = value;
}
- private NativePoint _location = NativePoint.Empty;
-
+ private Point _location = Point.Empty;
///
/// Get/set the Location
///
- public NativePoint Location
- {
+ public Point Location {
get => _location;
set => _location = value;
}
private CaptureDetails _captureDetails;
-
///
/// Get/set the CaptureDetails
///
- public ICaptureDetails CaptureDetails
- {
+ public ICaptureDetails CaptureDetails {
get => _captureDetails;
- set => _captureDetails = (CaptureDetails) value;
+ set => _captureDetails = (CaptureDetails)value;
}
///
/// Default Constructor
///
- public Capture()
- {
- _screenBounds = DisplayInfo.ScreenBounds;
+ public Capture() {
+ _screenBounds = WindowCapture.GetScreenBounds();
_captureDetails = new CaptureDetails();
}
@@ -174,16 +123,14 @@ namespace Greenshot.Base.Core
/// Note: the supplied bitmap can be disposed immediately or when constructor is called.
///
/// Image
- public Capture(Image newImage) : this()
- {
+ public Capture(Image newImage) : this() {
Image = newImage;
}
///
/// Destructor
///
- ~Capture()
- {
+ ~Capture() {
Dispose(false);
}
@@ -191,8 +138,7 @@ namespace Greenshot.Base.Core
/// The public accessible Dispose
/// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
///
- public void Dispose()
- {
+ public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
@@ -202,14 +148,11 @@ namespace Greenshot.Base.Core
/// When disposing==true all non-managed resources should be freed too!
///
///
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
_image?.Dispose();
_cursor?.Dispose();
}
-
_image = null;
_cursor = null;
}
@@ -217,15 +160,13 @@ namespace Greenshot.Base.Core
///
/// Crops the capture to the specified rectangle (with Bitmap coordinates!)
///
- /// NativeRect with bitmap coordinates
- public bool Crop(NativeRect cropRectangle)
- {
+ /// Rectangle with bitmap coordinates
+ public bool Crop(Rectangle cropRectangle) {
Log.Debug("Cropping to: " + cropRectangle);
if (!ImageHelper.Crop(ref _image, ref cropRectangle))
{
return false;
}
-
_location = cropRectangle.Location;
// Change mouse location according to the cropRectangle (including screenbounds) offset
MoveMouseLocation(-cropRectangle.Location.X, -cropRectangle.Location.Y);
@@ -237,6 +178,15 @@ namespace Greenshot.Base.Core
// TODO: Remove invisible lines/words?
CaptureDetails.OcrInformation?.Offset(-cropRectangle.Location.X, -cropRectangle.Location.Y);
+ // Remove invisible elements
+ var visibleElements = new List();
+ foreach(var captureElement in _elements) {
+ if (captureElement.Bounds.IntersectsWith(cropRectangle)) {
+ visibleElements.Add(captureElement);
+ }
+ }
+ _elements = visibleElements;
+
return true;
}
@@ -246,9 +196,8 @@ namespace Greenshot.Base.Core
///
/// x coordinates to move the mouse
/// y coordinates to move the mouse
- public void MoveMouseLocation(int x, int y)
- {
- _cursorLocation = _cursorLocation.Offset(x, y);
+ public void MoveMouseLocation(int x, int y) {
+ _cursorLocation.Offset(x, y);
}
// TODO: Enable when the elements are usable again.
@@ -264,7 +213,7 @@ namespace Greenshot.Base.Core
//private void MoveElements(List listOfElements, int x, int y) {
// foreach(ICaptureElement childElement in listOfElements) {
- // NativeRect bounds = childElement.Bounds;
+ // Rectangle bounds = childElement.Bounds;
// bounds.Offset(x, y);
// childElement.Bounds = bounds;
// MoveElements(childElement.Children, x, y);
@@ -298,5 +247,6 @@ namespace Greenshot.Base.Core
// elements = value;
// }
//}
+
}
}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/CaptureDetails.cs b/GreenshotPlugin/Core/CaptureDetails.cs
new file mode 100644
index 000000000..f6e0474ea
--- /dev/null
+++ b/GreenshotPlugin/Core/CaptureDetails.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Ocr;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// This Class is used to pass details about the capture around.
+ /// The time the Capture was taken and the Title of the window (or a region of) that is captured
+ ///
+ public class CaptureDetails : ICaptureDetails {
+
+ ///
+ public string Title {
+ get;
+ set;
+ }
+
+ ///
+ public string Filename {
+ get;
+ set;
+ }
+
+ ///
+ public DateTime DateTime {
+ get;
+ set;
+ }
+
+ ///
+ public float DpiX {
+ get;
+ set;
+ }
+
+ ///
+ public float DpiY {
+ get;
+ set;
+ }
+
+ ///
+ public OcrInformation OcrInformation { get; set; }
+
+ ///
+ public Dictionary MetaData { get; } = new Dictionary();
+
+ ///
+ public void AddMetaData(string key, string value) {
+ if (MetaData.ContainsKey(key)) {
+ MetaData[key] = value;
+ } else {
+ MetaData.Add(key, value);
+ }
+ }
+
+ ///
+ public CaptureMode CaptureMode {
+ get;
+ set;
+ }
+
+ ///
+ public List CaptureDestinations { get; set; } = new List();
+
+ ///
+ public void ClearDestinations() {
+ CaptureDestinations.Clear();
+ }
+
+ ///
+ public void RemoveDestination(IDestination destination) {
+ if (CaptureDestinations.Contains(destination)) {
+ CaptureDestinations.Remove(destination);
+ }
+ }
+
+ ///
+ public void AddDestination(IDestination captureDestination) {
+ if (!CaptureDestinations.Contains(captureDestination)) {
+ CaptureDestinations.Add(captureDestination);
+ }
+ }
+
+ ///
+ public bool HasDestination(string designation) {
+ foreach(IDestination destination in CaptureDestinations) {
+ if (designation.Equals(destination.Designation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public CaptureDetails() {
+ DateTime = DateTime.Now;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/CaptureElement.cs b/GreenshotPlugin/Core/CaptureElement.cs
new file mode 100644
index 000000000..6b0f3ab73
--- /dev/null
+++ b/GreenshotPlugin/Core/CaptureElement.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using System.Drawing;
+using GreenshotPlugin.Interfaces;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// A class representing an element in the capture
+ ///
+ public class CaptureElement : ICaptureElement {
+ public CaptureElement(Rectangle bounds) {
+ Bounds = bounds;
+ }
+ public CaptureElement(string name) {
+ Name = name;
+ }
+ public CaptureElement(string name, Rectangle bounds) {
+ Name = name;
+ Bounds = bounds;
+ }
+
+ public List Children { get; set; } = new List();
+
+ public string Name {
+ get;
+ set;
+ }
+ public Rectangle Bounds {
+ get;
+ set;
+ }
+
+ // CaptureElements are regarded equal if their bounds are equal. this should be sufficient.
+ public override bool Equals(object obj) {
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+
+ return obj is CaptureElement other && Bounds.Equals(other.Bounds);
+ }
+
+ public override int GetHashCode() {
+ // TODO: Fix this, this is not right...
+ return Bounds.GetHashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/CaptureHandler.cs b/GreenshotPlugin/Core/CaptureHandler.cs
new file mode 100644
index 000000000..7716b56c1
--- /dev/null
+++ b/GreenshotPlugin/Core/CaptureHandler.cs
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+ */
+
+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..046838716
--- /dev/null
+++ b/GreenshotPlugin/Core/ClipboardHelper.cs
@@ -0,0 +1,850 @@
+/*
+ * 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 .
+ */
+
+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 GreenshotPlugin.UnmanagedHelpers;
+using System.Runtime.InteropServices;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+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_JPEG = "JPEG";
+ 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
+ {
+ User32.GetWindowThreadProcessId(hWnd, out var 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_JFIF)
+ || dataObject.GetDataPresent(FORMAT_JPEG)
+ || 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_JPEG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
+ } else {
+ retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, 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 disappear 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..15f408480
--- /dev/null
+++ b/GreenshotPlugin/Core/CoreConfiguration.cs
@@ -0,0 +1,545 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Reflection;
+using System.Windows.Forms;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+
+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("BaseIconSize", Description = "Defines the base size of the icons (e.g. for the buttons in the editor), default value 16,16 and it's scaled to the current DPI", 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"));
+ }
+ }
+ }
+
+ public Size ScaledIconSize => DpiHelper.ScaleWithCurrentDpi(_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", string.Empty }, {"IE", string.Empty }, {"Chrome", string.Empty } };
+ }
+ 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..95426e934
--- /dev/null
+++ b/GreenshotPlugin/Core/CredentialsHelper.cs
@@ -0,0 +1,532 @@
+/*
+ * 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 .
+ */
+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 |= CredUi.CredFlags.INCORRECT_PASSWORD;
+ }
+
+ if (AlwaysDisplay) {
+ credFlags |= CredUi.CredFlags.ALWAYS_SHOW_UI;
+ }
+
+ if (ExcludeCertificates) {
+ credFlags |= CredUi.CredFlags.EXCLUDE_CERTIFICATES;
+ }
+
+ if (Persist) {
+ credFlags |= CredUi.CredFlags.EXPECT_CONFIRMATION;
+ if (SaveDisplayed) {
+ credFlags |= CredUi.CredFlags.SHOW_SAVE_CHECK_BOX;
+ } else {
+ credFlags |= CredUi.CredFlags.PERSIST;
+ }
+ } else {
+ credFlags |= CredUi.CredFlags.DO_NOT_PERSIST;
+ }
+
+ if (KeepName) {
+ credFlags |= CredUi.CredFlags.KEEP_USERNAME;
+ }
+
+ return credFlags;
+ }
+
+ /// Returns a DialogResult from the specified code.
+ /// The credential return code.
+ private DialogResult GetDialogResult(CredUi.ReturnCodes code) =>
+ code switch
+ {
+ CredUi.ReturnCodes.NO_ERROR => DialogResult.OK,
+ CredUi.ReturnCodes.ERROR_CANCELLED => DialogResult.Cancel,
+ CredUi.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION => throw new ApplicationException(
+ "No such logon session."),
+ CredUi.ReturnCodes.ERROR_NOT_FOUND => throw new ApplicationException("Not found."),
+ CredUi.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME =>
+ throw new ApplicationException("Invalid account name."),
+ CredUi.ReturnCodes.ERROR_INSUFFICIENT_BUFFER => throw new ApplicationException("Insufficient buffer."),
+ CredUi.ReturnCodes.ERROR_INVALID_PARAMETER => throw new ApplicationException("Invalid parameter."),
+ CredUi.ReturnCodes.ERROR_INVALID_FLAGS => throw new ApplicationException("Invalid flags."),
+ _ => throw new ApplicationException("Unknown credential result encountered.")
+ };
+ }
+
+ 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..8f1b81b68
--- /dev/null
+++ b/GreenshotPlugin/Core/DisplayKeyAttribute.cs
@@ -0,0 +1,35 @@
+/*
+ * 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 .
+ */
+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/DpiHelper.cs b/GreenshotPlugin/Core/DpiHelper.cs
new file mode 100644
index 000000000..991f2897e
--- /dev/null
+++ b/GreenshotPlugin/Core/DpiHelper.cs
@@ -0,0 +1,731 @@
+using GreenshotPlugin.Core.Enums;
+using GreenshotPlugin.UnmanagedHelpers;
+using log4net;
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using GreenshotPlugin.UnmanagedHelpers.Enums;
+using GreenshotPlugin.UnmanagedHelpers.Structs;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// This handles DPI changes see
+ /// Writing DPI-Aware Desktop and Win32 Applications
+ ///
+ public static class DpiHelper
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(DpiHelper));
+
+ ///
+ /// This is the default DPI for the screen
+ ///
+ public const uint DefaultScreenDpi = 96;
+
+ ///
+ /// Retrieve the current DPI for the UI element which is related to this DpiHandler
+ ///
+ public static uint Dpi { get; private set; } = WindowsVersion.IsWindows10OrLater ? GetDpiForSystem() : DefaultScreenDpi;
+
+ ///
+ /// Calculate a DPI scale factor
+ ///
+ /// uint
+ /// double
+ public static float DpiScaleFactor(uint dpi)
+ {
+ if (dpi == 0)
+ {
+ dpi = Dpi;
+ }
+ return (float)dpi / DefaultScreenDpi;
+ }
+
+ ///
+ /// Scale the supplied number according to the supplied dpi
+ ///
+ /// double with e.g. the width 16 for 16x16 images
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// double with the scaled number
+ public static float ScaleWithDpi(float someNumber, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return dpiScaleFactor * someNumber;
+ }
+
+ ///
+ /// Scale the supplied number according to the supplied dpi
+ ///
+ /// int with e.g. 16 for 16x16 images
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// Scaled width
+ public static int ScaleWithDpi(int number, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return (int)(dpiScaleFactor * number);
+ }
+
+ ///
+ /// Scale the supplied Size according to the supplied dpi
+ ///
+ /// Size to resize
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// NativeSize scaled
+ public static Size ScaleWithDpi(Size size, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return new Size((int)(dpiScaleFactor * size.Width), (int)(dpiScaleFactor * size.Height));
+ }
+
+ ///
+ /// Scale the supplied NativePoint according to the supplied dpi
+ ///
+ /// NativePoint to resize
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// NativePoint scaled
+ public static Point ScaleWithDpi(Point size, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return new Point((int)(dpiScaleFactor * size.X), (int)(dpiScaleFactor * size.Y));
+ }
+
+ ///
+ /// Scale the supplied NativeSizeFloat according to the supplied dpi
+ ///
+ /// PointF
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// PointF
+ public static PointF ScaleWithDpi(PointF point, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return new PointF(dpiScaleFactor * point.X, dpiScaleFactor * point.Y);
+ }
+
+ ///
+ /// Scale the supplied NativeSizeFloat according to the supplied dpi
+ ///
+ /// NativeSizeFloat to resize
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// NativeSize scaled
+ public static SizeF ScaleWithDpi(SizeF size, uint dpi, Func scaleModifier = null)
+ {
+ var dpiScaleFactor = DpiScaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiScaleFactor = scaleModifier(dpiScaleFactor);
+ }
+ return new SizeF(dpiScaleFactor * size.Width, dpiScaleFactor * size.Height);
+ }
+
+ ///
+ /// Scale the supplied number to the current dpi
+ ///
+ /// double with e.g. a width like 16 for 16x16 images
+ /// A function which can modify the scale factor
+ /// double with scaled number
+ public static float ScaleWithCurrentDpi(float someNumber, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(someNumber, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Scale the supplied number to the current dpi
+ ///
+ /// int with e.g. a width like 16 for 16x16 images
+ /// A function which can modify the scale factor
+ /// int with scaled number
+ public static int ScaleWithCurrentDpi(int someNumber, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(someNumber, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Scale the supplied NativeSize to the current dpi
+ ///
+ /// NativeSize to scale
+ /// A function which can modify the scale factor
+ /// NativeSize scaled
+ public static Size ScaleWithCurrentDpi(Size size, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(size, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Scale the supplied NativeSizeFloat to the current dpi
+ ///
+ /// NativeSizeFloat to scale
+ /// A function which can modify the scale factor
+ /// NativeSizeFloat scaled
+ public static SizeF ScaleWithCurrentDpi(SizeF size, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(size, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Scale the supplied NativePoint to the current dpi
+ ///
+ /// NativePoint to scale
+ /// A function which can modify the scale factor
+ /// NativePoint scaled
+ public static Point ScaleWithCurrentDpi(Point point, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(point, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Scale the supplied PointF to the current dpi
+ ///
+ /// PointF to scale
+ /// A function which can modify the scale factor
+ /// PointF scaled
+ public static PointF ScaleWithCurrentDpi(PointF point, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(point, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Calculate a DPI unscale factor
+ ///
+ /// uint
+ /// float
+ public static float DpiUnscaleFactor(uint dpi)
+ {
+ return (float)DefaultScreenDpi / dpi;
+ }
+
+ ///
+ /// Unscale the supplied number according to the supplied dpi
+ ///
+ /// double with e.g. the scaled width
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// double with the unscaled number
+ public static float UnscaleWithDpi(float someNumber, uint dpi, Func scaleModifier = null)
+ {
+ var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
+ }
+ return dpiUnscaleFactor * someNumber;
+ }
+
+ ///
+ /// Unscale the supplied number according to the supplied dpi
+ ///
+ /// int with a scaled width
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// Unscaled width
+ public static int UnscaleWithDpi(int number, uint dpi, Func scaleModifier = null)
+ {
+ var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
+ }
+ return (int)(dpiUnscaleFactor * number);
+ }
+
+ ///
+ /// Unscale the supplied NativeSize according to the supplied dpi
+ ///
+ /// NativeSize to unscale
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// Size unscaled
+ public static Size UnscaleWithDpi(Size size, uint dpi, Func scaleModifier = null)
+ {
+ var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
+ }
+ return new Size((int)(dpiUnscaleFactor * size.Width), (int)(dpiUnscaleFactor * size.Height));
+ }
+
+ ///
+ /// Unscale the supplied Point according to the supplied dpi
+ ///
+ /// Point to unscale
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// Point unscaled
+ public static Point UnscaleWithDpi(Point point, uint dpi, Func scaleModifier = null)
+ {
+ var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
+ }
+ return new Point((int)(dpiUnscaleFactor * point.X), (int)(dpiUnscaleFactor * point.Y));
+ }
+
+ ///
+ /// unscale the supplied NativeSizeFloat according to the supplied dpi
+ ///
+ /// NativeSizeFloat to resize
+ /// current dpi, normal is 96.
+ /// A function which can modify the scale factor
+ /// SizeF unscaled
+ public static SizeF UnscaleWithDpi(SizeF size, uint dpi, Func scaleModifier = null)
+ {
+ float dpiUnscaleFactor = DpiUnscaleFactor(dpi);
+ if (scaleModifier != null)
+ {
+ dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
+ }
+ return new SizeF(dpiUnscaleFactor * size.Width, dpiUnscaleFactor * size.Height);
+ }
+
+ ///
+ /// Unscale the supplied number to the current dpi
+ ///
+ /// double with e.g. a width like 16 for 16x16 images
+ /// A function which can modify the scale factor
+ /// double with unscaled number
+ public static float UnscaleWithCurrentDpi(float someNumber, Func scaleModifier = null)
+ {
+ return UnscaleWithDpi(someNumber, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Unscale the supplied number to the current dpi
+ ///
+ /// int with e.g. a width like 16 for 16x16 images
+ /// A function which can modify the scale factor
+ /// int with unscaled number
+ public static int UnscaleWithCurrentDpi(int someNumber, Func scaleModifier = null)
+ {
+ return UnscaleWithDpi(someNumber, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Unscale the supplied NativeSize to the current dpi
+ ///
+ /// Size to unscale
+ /// A function which can modify the scale factor
+ /// Size unscaled
+ public static Size UnscaleWithCurrentDpi(Size size, Func scaleModifier = null)
+ {
+ return UnscaleWithDpi(size, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Unscale the supplied NativeSizeFloat to the current dpi
+ ///
+ /// NativeSizeFloat to unscale
+ /// A function which can modify the scale factor
+ /// NativeSizeFloat unscaled
+ public static SizeF UnscaleWithCurrentDpi(SizeF size, Func scaleModifier = null)
+ {
+ return UnscaleWithDpi(size, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Unscale the supplied NativePoint to the current dpi
+ ///
+ /// NativePoint to unscale
+ /// A function which can modify the scale factor
+ /// NativePoint unscaled
+ public static Point UnscaleWithCurrentDpi(Point point, Func scaleModifier = null)
+ {
+ return UnscaleWithDpi(point, Dpi, scaleModifier);
+ }
+
+ ///
+ /// Unscale the supplied NativePointFloat to the current dpi
+ ///
+ /// NativePointFloat to unscale
+ /// A function which can modify the scale factor
+ /// NativePointFloat unscaled
+ public static PointF UnscaleWithCurrentDpi(PointF point, Func scaleModifier = null)
+ {
+ return ScaleWithDpi(point, Dpi, scaleModifier);
+ }
+
+ ///
+ /// public wrapper for EnableNonClientDpiScaling, this also checks if the function is available.
+ ///
+ /// IntPtr
+ /// true if it worked
+ public static bool TryEnableNonClientDpiScaling(IntPtr hWnd)
+ {
+ // EnableNonClientDpiScaling is only available on Windows 10 and later
+ if (!WindowsVersion.IsWindows10OrLater)
+ {
+ return false;
+ }
+
+ var result = EnableNonClientDpiScaling(hWnd);
+ if (result.Succeeded())
+ {
+ return true;
+ }
+
+ var error = Win32.GetLastErrorCode();
+ if (Log.IsDebugEnabled)
+ {
+ Log.DebugFormat("Error enabling non client dpi scaling : {0}", Win32.GetMessage(error));
+ }
+
+ return false;
+ }
+
+ ///
+ /// Make the current process DPI Aware, this should be done via the manifest but sometimes this is not possible.
+ ///
+ /// bool true if it was possible to change the DPI awareness
+ public static bool EnableDpiAware()
+ {
+ // We can only test this for Windows 8.1 or later
+ if (!WindowsVersion.IsWindows81OrLater)
+ {
+ Log.Debug("An application can only be DPI aware starting with Window 8.1 and later.");
+ return false;
+ }
+
+ if (WindowsVersion.IsWindows10BuildOrLater(15063))
+ {
+ if (IsValidDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2))
+ {
+ SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2);
+ }
+ else
+ {
+ SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2);
+ }
+
+ return true;
+ }
+ return SetProcessDpiAwareness(DpiAwareness.PerMonitorAware).Succeeded();
+ }
+
+ ///
+ /// Check if the process is DPI Aware, an DpiHandler doesn't make sense if not.
+ ///
+ public static bool IsDpiAware
+ {
+ get
+ {
+ // We can only test this for Windows 8.1 or later
+ if (!WindowsVersion.IsWindows81OrLater)
+ {
+ Log.Debug("An application can only be DPI aware starting with Window 8.1 and later.");
+ return false;
+ }
+
+ using var process = Process.GetCurrentProcess();
+ GetProcessDpiAwareness(process.Handle, out var dpiAwareness);
+ if (Log.IsDebugEnabled)
+ {
+ Log.DebugFormat("Process {0} has a Dpi awareness {1}", process.ProcessName, dpiAwareness);
+ }
+
+ return dpiAwareness != DpiAwareness.Unaware && dpiAwareness != DpiAwareness.Invalid;
+ }
+ }
+
+ ///
+ /// Return the DPI for the screen which the location is located on
+ ///
+ /// POINT
+ /// uint
+ public static uint GetDpi(POINT location)
+ {
+ RECT rect = new RECT(location.X, location.Y, 1,1);
+ IntPtr hMonitor = User32.MonitorFromRect(ref rect, User32.MONITOR_DEFAULTTONEAREST);
+ var result = GetDpiForMonitor(hMonitor, MonitorDpiType.EffectiveDpi, out var dpiX, out var dpiY);
+ if (result.Succeeded())
+ {
+ return dpiX;
+ }
+ return DefaultScreenDpi;
+ }
+
+
+ ///
+ /// Retrieve the DPI value for the supplied window handle
+ ///
+ /// IntPtr
+ /// dpi value
+ public static uint GetDpi(IntPtr hWnd)
+ {
+ if (!User32.IsWindow(hWnd))
+ {
+ return DefaultScreenDpi;
+ }
+
+ // Use the easiest method, but this only works for Windows 10
+ if (WindowsVersion.IsWindows10OrLater)
+ {
+ return GetDpiForWindow(hWnd);
+ }
+
+ // Use the second easiest method, but this only works for Windows 8.1 or later
+ if (WindowsVersion.IsWindows81OrLater)
+ {
+ var hMonitor = User32.MonitorFromWindow(hWnd, MonitorFrom.DefaultToNearest);
+ // ReSharper disable once UnusedVariable
+ var result = GetDpiForMonitor(hMonitor, MonitorDpiType.EffectiveDpi, out var dpiX, out var dpiY);
+ if (result.Succeeded())
+ {
+ return dpiX;
+ }
+ }
+
+ // Fallback to the global DPI settings
+ using var hdc = SafeWindowDcHandle.FromWindow(hWnd);
+ if (hdc == null)
+ {
+ return DefaultScreenDpi;
+ }
+ return (uint)GDI32.GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX);
+ }
+
+ ///
+ /// See details GetProcessDpiAwareness function
+ /// Retrieves the dots per inch (dpi) awareness of the specified process.
+ ///
+ /// IntPtr with handle of the process that is being queried. If this parameter is NULL, the current process is queried.
+ /// out DpiAwareness - The DPI awareness of the specified process. Possible values are from the PROCESS_DPI_AWARENESS enumeration.
+ /// HResult
+ [DllImport("shcore")]
+ private static extern HResult GetProcessDpiAwareness(IntPtr processHandle, out DpiAwareness value);
+
+ ///
+ /// Sets the current process to a specified dots per inch (dpi) awareness level. The DPI awareness levels are from the PROCESS_DPI_AWARENESS enumeration.
+ /// See SetProcessDpiAwareness function
+ ///
+ /// DpiAwareness
+ /// HResult
+ [DllImport("shcore")]
+ private static extern HResult SetProcessDpiAwareness(DpiAwareness dpiAwareness);
+
+ ///
+ /// It is recommended that you set the process-default DPI awareness via application manifest. See Setting the default DPI awareness for a process for more information. Setting the process-default DPI awareness via API call can lead to unexpected application behavior.
+ ///
+ /// Sets the current process to a specified dots per inch (dpi) awareness context. The DPI awareness contexts are from the DPI_AWARENESS_CONTEXT value.
+ /// Remarks:
+ /// This API is a more advanced version of the previously existing SetProcessDpiAwareness API, allowing for the process default to be set to the finer-grained DPI_AWARENESS_CONTEXT values. Most importantly, this allows you to programmatically set Per Monitor v2 as the process default value, which is not possible with the previous API.
+ ///
+ /// This method sets the default DPI_AWARENESS_CONTEXT for all threads within an application. Individual threads can have their DPI awareness changed from the default with the SetThreadDpiAwarenessContext method.
+ /// See SetProcessDpiAwarenessContext function
+ ///
+ /// DpiAwarenessContext
+ /// bool
+ [DllImport("User32.dll", SetLastError = true)]
+ private static extern bool SetProcessDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
+
+ ///
+ /// See more at GetDpiForWindow function
+ /// Returns the dots per inch (dpi) value for the associated window.
+ ///
+ /// IntPtr
+ /// uint with dpi
+ [DllImport("User32.dll")]
+ private static extern uint GetDpiForWindow(IntPtr hWnd);
+
+ ///
+ /// See
+ /// GetDpiForMonitor function
+ /// Queries the dots per inch (dpi) of a display.
+ ///
+ /// IntPtr
+ /// MonitorDpiType
+ /// out int for the horizontal dpi
+ /// out int for the vertical dpi
+ /// true if all okay
+ [DllImport("shcore.dll", SetLastError = true)]
+ private static extern HResult GetDpiForMonitor(IntPtr hMonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);
+
+ ///
+ /// See EnableNonClientDpiScaling function
+ ///
+ /// IntPtr
+ /// bool
+ [DllImport("User32.dll", SetLastError = true)]
+ private static extern HResult EnableNonClientDpiScaling(IntPtr hWnd);
+
+ ///
+ /// See GetDpiForSystem function
+ /// Returns the system DPI.
+ ///
+ /// uint with the system DPI
+ [DllImport("User32.dll")]
+ private static extern uint GetDpiForSystem();
+
+ ///
+ /// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS.
+ /// See more at LogicalToPhysicalPointForPerMonitorDPI function
+ ///
+ /// IntPtr A handle to the window whose transform is used for the conversion.
+ /// A pointer to a POINT structure that specifies the logical coordinates to be converted. The new physical coordinates are copied into this structure if the function succeeds.
+ /// bool
+ [DllImport("User32.dll")]
+ private static extern bool LogicalToPhysicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point);
+
+ ///
+ /// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS.
+ /// See more at PhysicalToLogicalPointForPerMonitorDPI function
+ ///
+ /// IntPtr A handle to the window whose transform is used for the conversion.
+ /// NativePoint A pointer to a POINT structure that specifies the physical/screen coordinates to be converted. The new logical coordinates are copied into this structure if the function succeeds.
+ /// bool
+ [DllImport("User32.dll")]
+ private static extern bool PhysicalToLogicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point);
+
+ ///
+ /// See SystemParametersInfo function
+ /// Retrieves the value of one of the system-wide parameters, taking into account the provided DPI value.
+ ///
+ ///
+ /// SystemParametersInfoActions The system-wide parameter to be retrieved.
+ /// This function is only intended for use with SPI_GETICONTITLELOGFONT, SPI_GETICONMETRICS, or SPI_GETNONCLIENTMETRICS. See SystemParametersInfo for more information on these values.
+ ///
+ ///
+ /// A parameter whose usage and format depends on the system parameter being queried or set. For more
+ /// information about system-wide parameters, see the uiAction parameter. If not otherwise indicated, you must specify
+ /// zero for this parameter.
+ ///
+ /// IntPtr
+ /// SystemParametersInfoBehaviors
+ /// uint with dpi value
+ /// bool
+ [DllImport("User32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool SystemParametersInfoForDpi(SystemParametersInfoActions uiAction, uint uiParam, IntPtr pvParam, SystemParametersInfoBehaviors fWinIni, uint dpi);
+
+ ///
+ /// See GetThreadDpiAwarenessContext function
+ /// Gets the DPI_AWARENESS_CONTEXT for the current thread.
+ ///
+ /// This method will return the latest DPI_AWARENESS_CONTEXT sent to SetThreadDpiAwarenessContext. If SetThreadDpiAwarenessContext was never called for this thread, then the return value will equal the default DPI_AWARENESS_CONTEXT for the process.
+ ///
+ /// DpiAwarenessContext
+ [DllImport("User32.dll")]
+ private static extern DpiAwarenessContext GetThreadDpiAwarenessContext();
+
+ ///
+ /// Set the DPI awareness for the current thread to the provided value.
+ ///
+ /// DpiAwarenessContext the new value for the current thread
+ /// DpiAwarenessContext previous value
+ [DllImport("User32.dll")]
+ private static extern DpiAwarenessContext SetThreadDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
+
+ ///
+ /// Retrieves the DpiAwareness value from a DpiAwarenessContext.
+ ///
+ /// DpiAwarenessContext
+ /// DpiAwareness
+ [DllImport("User32.dll")]
+ private static extern DpiAwareness GetAwarenessFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
+
+ ///
+ /// Retrieves the DPI from a given DPI_AWARENESS_CONTEXT handle. This enables you to determine the DPI of a thread without needed to examine a window created within that thread.
+ ///
+ /// DpiAwarenessContext
+ /// uint with dpi value
+ [DllImport("User32.dll")]
+ private static extern uint GetDpiFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
+
+ ///
+ /// Determines if a specified DPI_AWARENESS_CONTEXT is valid and supported by the current system.
+ ///
+ /// DpiAwarenessContext The context that you want to determine if it is supported.
+ /// bool true if supported otherwise false
+ [DllImport("User32.dll")]
+ private static extern bool IsValidDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
+
+ ///
+ /// Returns the DPI_HOSTING_BEHAVIOR of the specified window.
+ ///
+ /// This API allows you to examine the hosting behavior of a window after it has been created. A window's hosting behavior is the hosting behavior of the thread in which the window was created, as set by a call to SetThreadDpiHostingBehavior. This is a permanent value and cannot be changed after the window is created, even if the thread's hosting behavior is changed.
+ ///
+ /// DpiHostingBehavior
+ [DllImport("User32.dll")]
+ private static extern DpiHostingBehavior GetWindowDpiHostingBehavior();
+
+ ///
+ /// See more at SetThreadDpiHostingBehavior function
+ /// Sets the thread's DPI_HOSTING_BEHAVIOR. This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT.
+ ///
+ /// DPI_HOSTING_BEHAVIOR enables a mixed content hosting behavior, which allows parent windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT value. This property only effects new windows created within this thread while the mixed hosting behavior is active. A parent window with this hosting behavior is able to host child windows with different DPI_AWARENESS_CONTEXT values, regardless of whether the child windows have mixed hosting behavior enabled.
+ ///
+ /// This hosting behavior does not allow for windows with per-monitor DPI_AWARENESS_CONTEXT values to be hosted until windows with DPI_AWARENESS_CONTEXT values of system or unaware.
+ ///
+ /// To avoid unexpected outcomes, a thread's DPI_HOSTING_BEHAVIOR should be changed to support mixed hosting behaviors only when creating a new window which needs to support those behaviors. Once that window is created, the hosting behavior should be switched back to its default value.
+ ///
+ /// This API is used to change the thread's DPI_HOSTING_BEHAVIOR from its default value. This is only necessary if your app needs to host child windows from plugins and third-party components that do not support per-monitor-aware context. This is most likely to occur if you are updating complex applications to support per-monitor DPI_AWARENESS_CONTEXT behaviors.
+ ///
+ /// Enabling mixed hosting behavior will not automatically adjust the thread's DPI_AWARENESS_CONTEXT to be compatible with legacy content. The thread's awareness context must still be manually changed before new windows are created to host such content.
+ ///
+ /// DpiHostingBehavior
+ /// previous DpiHostingBehavior
+ [DllImport("User32.dll")]
+ private static extern DpiHostingBehavior SetThreadDpiHostingBehavior(DpiHostingBehavior dpiHostingBehavior);
+
+ ///
+ ///Retrieves the DPI_HOSTING_BEHAVIOR from the current thread.
+ ///
+ /// DpiHostingBehavior
+ [DllImport("User32.dll")]
+ private static extern DpiHostingBehavior GetThreadDpiHostingBehavior();
+
+ ///
+ /// Overrides the default per-monitor DPI scaling behavior of a child window in a dialog.
+ /// This function returns TRUE if the operation was successful, and FALSE otherwise. To get extended error information, call GetLastError.
+ ///
+ /// Possible errors are ERROR_INVALID_HANDLE if passed an invalid HWND, and ERROR_ACCESS_DENIED if the windows belongs to another process.
+ ///
+ /// The behaviors are specified as values from the DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS enum. This function follows the typical two-parameter approach to setting flags, where a mask specifies the subset of the flags to be changed.
+ ///
+ /// It is valid to set these behaviors on any window. It does not matter if the window is currently a child of a dialog at the point in time that SetDialogControlDpiChangeBehavior is called. The behaviors are retained and will take effect only when the window is an immediate child of a dialog that has per-monitor DPI scaling enabled.
+ ///
+ /// This API influences individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior is controlled by SetDialogDpiChangeBehavior.
+ ///
+ /// IntPtr A handle for the window whose behavior will be modified.
+ /// DialogScalingBehaviors A mask specifying the subset of flags to be changed.
+ /// DialogScalingBehaviors The desired value to be set for the specified subset of flags.
+ /// bool
+ [DllImport("User32.dll")]
+ private static extern bool SetDialogControlDpiChangeBehavior(IntPtr hWnd, DialogScalingBehaviors mask, DialogScalingBehaviors values);
+
+ ///
+ /// Retrieves and per-monitor DPI scaling behavior overrides of a child window in a dialog.
+ /// The flags set on the given window. If passed an invalid handle, this function will return zero, and set its last error to ERROR_INVALID_HANDLE.
+ ///
+ /// IntPtr A handle for the window whose behavior will be modified.
+ /// DialogScalingBehaviors
+ [DllImport("User32.dll")]
+ private static extern DialogScalingBehaviors GetDialogControlDpiChangeBehavior(IntPtr hWnd);
+ }
+}
diff --git a/GreenshotPlugin/Core/EffectConverter.cs b/GreenshotPlugin/Core/EffectConverter.cs
new file mode 100644
index 000000000..f72e271dc
--- /dev/null
+++ b/GreenshotPlugin/Core/EffectConverter.cs
@@ -0,0 +1,170 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Globalization;
+using System.Text;
+using GreenshotPlugin.Effects;
+
+namespace GreenshotPlugin.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) {
+ if (value is string settings) {
+ 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" :
+ // Fix to prevent BUG-1753
+ if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, _numberFormatInfo, out var darkness)) {
+ if (darkness <= 1.0) {
+ effect.Darkness = darkness;
+ }
+ }
+ break;
+ case "ShadowSize":
+ if (int.TryParse(pair[1], out var shadowSize)) {
+ effect.ShadowSize = shadowSize;
+ }
+ break;
+ case "ShadowOffset":
+ Point shadowOffset = new Point();
+ string[] coordinates = pair[1].Split(',');
+ if (int.TryParse(coordinates[0], out var shadowOffsetX)) {
+ shadowOffset.X = shadowOffsetX;
+ }
+ if (int.TryParse(coordinates[1], out var 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":
+ if (bool.TryParse(pair[1], out var generateShadow)) {
+ effect.GenerateShadow = generateShadow;
+ }
+ break;
+ case "ToothHeight":
+ if (int.TryParse(pair[1], out var toothHeight)) {
+ effect.ToothHeight = toothHeight;
+ }
+ break;
+ case "HorizontalToothRange":
+ if (int.TryParse(pair[1], out var horizontalToothRange)) {
+ effect.HorizontalToothRange = horizontalToothRange;
+ }
+ break;
+ case "VerticalToothRange":
+ if (int.TryParse(pair[1], out var verticalToothRange)) {
+ effect.VerticalToothRange = verticalToothRange;
+ }
+ break;
+ case "Edges":
+ string[] edges = pair[1].Split(',');
+ if (bool.TryParse(edges[0], out var 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..354f02c33
--- /dev/null
+++ b/GreenshotPlugin/Core/EmailConfigHelper.cs
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+ */
+
+using System.IO;
+using Microsoft.Win32;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Description of EmailConfigHelper.
+ ///
+ public static class EmailConfigHelper {
+
+ public static string GetMapiClient() => Registry.LocalMachine.ReadKey64Or32(@"Clients\Mail");
+
+ public static bool HasMapi()
+ {
+ var value = Registry.LocalMachine.ReadKey64Or32(@"Microsoft\Windows Messaging Subsystem", "MAPI", "0");
+ return "1".Equals(value);
+
+ }
+
+ public static string GetOutlookExePath() => Registry.LocalMachine.ReadKey64Or32(@"Microsoft\Windows\CurrentVersion\App Paths\OUTLOOK.EXE");
+
+ ///
+ /// Check if Outlook is installed
+ ///
+ /// Returns true if outlook is installed
+ public static bool HasOutlook() {
+ string outlookPath = GetOutlookExePath();
+ if (outlookPath == null)
+ {
+ return false;
+ }
+ return File.Exists(outlookPath);
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/EnumExtensions.cs b/GreenshotPlugin/Core/EnumExtensions.cs
new file mode 100644
index 000000000..1bda1071f
--- /dev/null
+++ b/GreenshotPlugin/Core/EnumExtensions.cs
@@ -0,0 +1,102 @@
+/*
+ * 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 .
+ */
+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/Enums/DialogDpiChangeBehaviors.cs b/GreenshotPlugin/Core/Enums/DialogDpiChangeBehaviors.cs
new file mode 100644
index 000000000..fa5b61635
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/DialogDpiChangeBehaviors.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// In Per Monitor v2 contexts, dialogs will automatically respond to DPI changes by resizing themselves and re-computing the positions of their child windows (here referred to as re-layouting). This enum works in conjunction with SetDialogDpiChangeBehavior in order to override the default DPI scaling behavior for dialogs.
+ /// This does not affect DPI scaling behavior for the child windows of dialogs(beyond re-layouting), which is controlled by DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS.
+ ///
+ [Flags]
+ public enum DialogDpiChangeBehaviors
+ {
+ ///
+ /// The default behavior of the dialog manager. In response to a DPI change, the dialog manager will re-layout each control, update the font on each control, resize the dialog, and update the dialog's own font.
+ ///
+ Default = 0,
+
+ ///
+ /// Prevents the dialog manager from responding to WM_GETDPISCALEDSIZE and WM_DPICHANGED, disabling all default DPI scaling behavior.
+ ///
+ DisableAll = 1,
+
+ ///
+ /// Prevents the dialog manager from resizing the dialog in response to a DPI change.
+ ///
+ DisableResize = 2,
+
+ ///
+ /// Prevents the dialog manager from re-layouting all of the dialogue's immediate children HWNDs in response to a DPI change.
+ ///
+ DisableControlRelayout = 3
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs b/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs
new file mode 100644
index 000000000..4de8e4c35
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// Describes per-monitor DPI scaling behavior overrides for child windows within dialogs. The values in this enumeration are bitfields and can be combined.
+ ///
+ /// This enum is used with SetDialogControlDpiChangeBehavior in order to override the default per-monitor DPI scaling behavior for a child window within a dialog.
+ ///
+ /// These settings only apply to individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior of a dialog is controlled by DIALOG_DPI_CHANGE_BEHAVIORS.
+ ///
+ [Flags]
+ public enum DialogScalingBehaviors
+ {
+ ///
+ /// The default behavior of the dialog manager. The dialog managed will update the font, size, and position of the child window on DPI changes.
+ ///
+ Default = 0,
+
+ ///
+ /// Prevents the dialog manager from sending an updated font to the child window via WM_SETFONT in response to a DPI change.
+ ///
+ DisableFontUpdate = 1,
+
+ ///
+ /// Prevents the dialog manager from resizing and repositioning the child window in response to a DPI change.
+ ///
+ DisableRelayout = 2
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/DpiAwareness.cs b/GreenshotPlugin/Core/Enums/DpiAwareness.cs
new file mode 100644
index 000000000..7dd22431e
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/DpiAwareness.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// Identifies the dots per inch (dpi) setting for a thread, process, or window.
+ /// Can be used everywhere ProcessDpiAwareness is passed.
+ ///
+ public enum DpiAwareness
+ {
+ ///
+ /// Invalid DPI awareness. This is an invalid DPI awareness value.
+ ///
+ Invalid = -1,
+
+ ///
+ /// DPI unaware.
+ /// This process does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI).
+ /// It will be automatically scaled by the system on any other DPI setting.
+ ///
+ Unaware = 0,
+
+ ///
+ /// System DPI aware.
+ /// This process does not scale for DPI changes.
+ /// It will query for the DPI once and use that value for the lifetime of the process.
+ /// If the DPI changes, the process will not adjust to the new DPI value.
+ /// It will be automatically scaled up or down by the system when the DPI changes from the system value.
+ ///
+ SystemAware = 1,
+
+ ///
+ /// Per monitor DPI aware.
+ /// This process checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes.
+ /// These processes are not automatically scaled by the system.
+ ///
+ PerMonitorAware = 2
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs b/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs
new file mode 100644
index 000000000..276d73550
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ ///
+ public enum DpiAwarenessContext
+ {
+ ///
+ /// DPI unaware.
+ /// This window does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI).
+ /// It will be automatically scaled by the system on any other DPI setting.
+ ///
+ Unaware = -1,
+
+ ///
+ /// System DPI aware.
+ /// This window does not scale for DPI changes.
+ /// It will query for the DPI once and use that value for the lifetime of the process.
+ /// If the DPI changes, the process will not adjust to the new DPI value.
+ /// It will be automatically scaled up or down by the system when the DPI changes from the system value.
+ ///
+ SystemAware = -2,
+
+ ///
+ /// Per monitor DPI aware.
+ /// This window checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes.
+ /// These processes are not automatically scaled by the system.
+ ///
+ PerMonitorAware = -3,
+
+ ///
+ /// Also known as Per Monitor v2. An advancement over the original per-monitor DPI awareness mode, which enables applications to access new DPI-related scaling behaviors on a per top-level window basis.
+ /// Per Monitor v2 was made available in the Creators Update of Windows 10, and is not available on earlier versions of the operating system.
+ /// The additional behaviors introduced are as follows:
+ /// * Child window DPI change notifications - In Per Monitor v2 contexts, the entire window tree is notified of any DPI changes that occur.
+ /// * Scaling of non-client area - All windows will automatically have their non-client area drawn in a DPI sensitive fashion. Calls to EnableNonClientDpiScaling are unnecessary.
+ /// * Scaling of Win32 menus - All NTUSER menus created in Per Monitor v2 contexts will be scaling in a per-monitor fashion.
+ /// * Dialog Scaling - Win32 dialogs created in Per Monitor v2 contexts will automatically respond to DPI changes.
+ /// * Improved scaling of comctl32 controls - Various comctl32 controls have improved DPI scaling behavior in Per Monitor v2 contexts.
+ /// * Improved theming behavior - UxTheme handles opened in the context of a Per Monitor v2 window will operate in terms of the DPI associated with that window.
+ ///
+ PerMonitorAwareV2 = -4
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs b/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs
new file mode 100644
index 000000000..0b0abf686
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// Identifies the DPI hosting behavior for a window.
+ /// This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT
+ ///
+ public enum DpiHostingBehavior
+ {
+ ///
+ /// Invalid DPI hosting behavior. This usually occurs if the previous SetThreadDpiHostingBehavior call used an invalid parameter.
+ ///
+ Invalid = -1,
+
+ ///
+ /// Default DPI hosting behavior. The associated window behaves as normal, and cannot create or re-parent child windows with a different DPI_AWARENESS_CONTEXT.
+ ///
+ Default = 0,
+
+ ///
+ /// Mixed DPI hosting behavior. This enables the creation and re-parenting of child windows with different DPI_AWARENESS_CONTEXT. These child windows will be independently scaled by the OS.
+ ///
+ Mixed = 1
+
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/HResult.cs b/GreenshotPlugin/Core/Enums/HResult.cs
new file mode 100644
index 000000000..40bb62a7b
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/HResult.cs
@@ -0,0 +1,56 @@
+// 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 .
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// The HRESULT represents Windows error codes
+ /// See wikipedia
+ ///
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ public enum HResult
+ {
+#pragma warning disable 1591
+ S_OK = 0,
+ S_FALSE = 1,
+ E_FAIL = unchecked((int)0x80004005),
+ E_INVALIDARG = unchecked((int)0x80070057),
+ E_NOTIMPL = unchecked((int)0x80004001),
+ E_POINTER = unchecked((int)0x80004003),
+ E_PENDING = unchecked((int)0x8000000A),
+ E_NOINTERFACE = unchecked((int)0x80004002),
+ E_ABORT = unchecked((int)0x80004004),
+ E_ACCESSDENIED = unchecked((int)0x80070006),
+ E_HANDLE = unchecked((int)0x80070006),
+ E_UNEXPECTED = unchecked((int)0x8000FFFF),
+ E_FILENOTFOUND = unchecked((int)0x80070002),
+ E_PATHNOTFOUND = unchecked((int)0x80070003),
+ E_INVALID_DATA = unchecked((int)0x8007000D),
+ E_OUTOFMEMORY = unchecked((int)0x8007000E),
+ E_INSUFFICIENT_BUFFER = unchecked((int)0x8007007A),
+ WSAECONNABORTED = unchecked((int)0x80072745),
+ WSAECONNRESET = unchecked((int)0x80072746),
+ ERROR_TOO_MANY_CMDS = unchecked((int)0x80070038),
+ ERROR_NOT_SUPPORTED = unchecked((int)0x80070032),
+ TYPE_E_ELEMENTNOTFOUND = unchecked((int)0x8002802B)
+#pragma warning restore 1591
+ }
+}
diff --git a/GreenshotPlugin/Core/Enums/MonitorDpiType.cs b/GreenshotPlugin/Core/Enums/MonitorDpiType.cs
new file mode 100644
index 000000000..ebe0033b4
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/MonitorDpiType.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// See
+ ///
+ /// MONITOR_DPI_TYPE
+ /// enumeration
+ ///
+ ///
+ [Flags]
+ public enum MonitorDpiType
+ {
+ ///
+ /// The effective DPI.
+ /// This value should be used when determining the correct scale factor for scaling UI elements.
+ /// This incorporates the scale factor set by the user for this specific display.
+ ///
+ EffectiveDpi = 0,
+
+ ///
+ /// The angular DPI.
+ /// This DPI ensures rendering at a compliant angular resolution on the screen.
+ /// This does not include the scale factor set by the user for this specific display
+ ///
+ AngularDpi = 1,
+
+ ///
+ /// The raw DPI.
+ /// This value is the linear DPI of the screen as measured on the screen itself.
+ /// Use this value when you want to read the pixel density and not the recommended scaling setting.
+ /// This does not include the scale factor set by the user for this specific display and is not guaranteed to be a
+ /// supported DPI value.
+ ///
+ RawDpi = 2
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/MonitorFrom.cs b/GreenshotPlugin/Core/Enums/MonitorFrom.cs
new file mode 100644
index 000000000..57e57a390
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/MonitorFrom.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// Flags for the MonitorFromRect / MonitorFromWindow "flags" field
+ /// see MonitorFromRect function
+ /// or see MonitorFromWindow function
+ ///
+ [Flags]
+ public enum MonitorFrom : uint
+ {
+ ///
+ /// Returns a handle to the display monitor that is nearest to the rectangle.
+ ///
+ DefaultToNearest = 0,
+
+ ///
+ /// Returns NULL. (why??)
+ ///
+ DefaultToNull = 1,
+
+ ///
+ /// Returns a handle to the primary display monitor.
+ ///
+ DefaultToPrimary = 2
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs b/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs
new file mode 100644
index 000000000..62a4eb5f4
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs
@@ -0,0 +1,1390 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Diagnostics.CodeAnalysis;
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// SPI_ System-wide parameter - Used in SystemParametersInfo function
+ ///
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ public enum SystemParametersInfoActions : uint
+ {
+ ///
+ /// No value
+ ///
+ SPI_NONE = 0,
+
+ ///
+ /// Determines whether the warning beeper is on.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE if the beeper is on, or FALSE if it is off.
+ ///
+ SPI_GETBEEP = 0x0001,
+
+ ///
+ /// Turns the warning beeper on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
+ ///
+ SPI_SETBEEP = 0x0002,
+
+ ///
+ /// Retrieves the two mouse threshold values and the mouse speed.
+ ///
+ SPI_GETMOUSE = 0x0003,
+
+ ///
+ /// Sets the two mouse threshold values and the mouse speed.
+ ///
+ SPI_SETMOUSE = 0x0004,
+
+ ///
+ /// Retrieves the border multiplier factor that determines the width of a window's sizing border.
+ /// The pvParam parameter must point to an integer variable that receives this value.
+ ///
+ SPI_GETBORDER = 0x0005,
+
+ ///
+ /// Sets the border multiplier factor that determines the width of a window's sizing border.
+ /// The uiParam parameter specifies the new value.
+ ///
+ SPI_SETBORDER = 0x0006,
+
+ ///
+ /// Retrieves the keyboard repeat-speed setting, which is a value in the range from 0 (approximately 2.5 repetitions
+ /// per second)
+ /// through 31 (approximately 30 repetitions per second). The actual repeat rates are hardware-dependent and may vary
+ /// from
+ /// a linear scale by as much as 20%. The pvParam parameter must point to a DWORD variable that receives the setting
+ ///
+ SPI_GETKEYBOARDSPEED = 0x000A,
+
+ ///
+ /// Sets the keyboard repeat-speed setting. The uiParam parameter must specify a value in the range from 0
+ /// (approximately 2.5 repetitions per second) through 31 (approximately 30 repetitions per second).
+ /// The actual repeat rates are hardware-dependent and may vary from a linear scale by as much as 20%.
+ /// If uiParam is greater than 31, the parameter is set to 31.
+ ///
+ SPI_SETKEYBOARDSPEED = 0x000B,
+
+ ///
+ /// Not implemented.
+ ///
+ SPI_LANGDRIVER = 0x000C,
+
+ ///
+ /// Sets or retrieves the width, in pixels, of an icon cell. The system uses this rectangle to arrange icons in large
+ /// icon view.
+ /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than
+ /// SM_CXICON.
+ /// To retrieve this value, pvParam must point to an integer that receives the current value.
+ ///
+ SPI_ICONHORIZONTALSPACING = 0x000D,
+
+ ///
+ /// Retrieves the screen saver time-out value, in seconds. The pvParam parameter must point to an integer variable that
+ /// receives the value.
+ ///
+ SPI_GETSCREENSAVETIMEOUT = 0x000E,
+
+ ///
+ /// Sets the screen saver time-out value to the value of the uiParam parameter. This value is the amount of time, in
+ /// seconds,
+ /// that the system must be idle before the screen saver activates.
+ ///
+ SPI_SETSCREENSAVETIMEOUT = 0x000F,
+
+ ///
+ /// Determines whether screen saving is enabled. The pvParam parameter must point to a bool variable that receives TRUE
+ /// if screen saving is enabled, or FALSE otherwise.
+ /// Does not work for Windows 7: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx
+ ///
+ SPI_GETSCREENSAVEACTIVE = 0x0010,
+
+ ///
+ /// Sets the state of the screen saver. The uiParam parameter specifies TRUE to activate screen saving, or FALSE to
+ /// deactivate it.
+ ///
+ SPI_SETSCREENSAVEACTIVE = 0x0011,
+
+ ///
+ /// Retrieves the current granularity value of the desktop sizing grid. The pvParam parameter must point to an integer
+ /// variable
+ /// that receives the granularity.
+ ///
+ SPI_GETGRIDGRANULARITY = 0x0012,
+
+ ///
+ /// Sets the granularity of the desktop sizing grid to the value of the uiParam parameter.
+ ///
+ SPI_SETGRIDGRANULARITY = 0x0013,
+
+ ///
+ /// Sets the desktop wallpaper. The value of the pvParam parameter determines the new wallpaper. To specify a wallpaper
+ /// bitmap,
+ /// set pvParam to point to a null-terminated string containing the name of a bitmap file. Setting pvParam to ""
+ /// removes the wallpaper.
+ /// Setting pvParam to SETWALLPAPER_DEFAULT or null reverts to the default wallpaper.
+ ///
+ SPI_SETDESKWALLPAPER = 0x0014,
+
+ ///
+ /// Sets the current desktop pattern by causing Windows to read the Pattern= setting from the WIN.INI file.
+ ///
+ SPI_SETDESKPATTERN = 0x0015,
+
+ ///
+ /// Retrieves the keyboard repeat-delay setting, which is a value in the range from 0 (approximately 250 ms delay)
+ /// through 3
+ /// (approximately 1 second delay). The actual delay associated with each value may vary depending on the hardware. The
+ /// pvParam parameter must point to an integer variable that receives the setting.
+ ///
+ SPI_GETKEYBOARDDELAY = 0x0016,
+
+ ///
+ /// Sets the keyboard repeat-delay setting. The uiParam parameter must specify 0, 1, 2, or 3, where zero sets the
+ /// shortest delay
+ /// (approximately 250 ms) and 3 sets the longest delay (approximately 1 second). The actual delay associated with each
+ /// value may
+ /// vary depending on the hardware.
+ ///
+ SPI_SETKEYBOARDDELAY = 0x0017,
+
+ ///
+ /// Sets or retrieves the height, in pixels, of an icon cell.
+ /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than
+ /// SM_CYICON.
+ /// To retrieve this value, pvParam must point to an integer that receives the current value.
+ ///
+ SPI_ICONVERTICALSPACING = 0x0018,
+
+ ///
+ /// Determines whether icon-title wrapping is enabled. The pvParam parameter must point to a bool variable that
+ /// receives TRUE
+ /// if enabled, or FALSE otherwise.
+ ///
+ SPI_GETICONTITLEWRAP = 0x0019,
+
+ ///
+ /// Turns icon-title wrapping on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
+ ///
+ SPI_SETICONTITLEWRAP = 0x001A,
+
+ ///
+ /// Determines whether pop-up menus are left-aligned or right-aligned, relative to the corresponding menu-bar item.
+ /// The pvParam parameter must point to a bool variable that receives TRUE if left-aligned, or FALSE otherwise.
+ ///
+ SPI_GETMENUDROPALIGNMENT = 0x001B,
+
+ ///
+ /// Sets the alignment value of pop-up menus. The uiParam parameter specifies TRUE for right alignment, or FALSE for
+ /// left alignment.
+ ///
+ SPI_SETMENUDROPALIGNMENT = 0x001C,
+
+ ///
+ /// Sets the width of the double-click rectangle to the value of the uiParam parameter.
+ /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be
+ /// registered
+ /// as a double-click.
+ /// To retrieve the width of the double-click rectangle, call GetSystemMetrics with the SM_CXDOUBLECLK flag.
+ ///
+ SPI_SETDOUBLECLKWIDTH = 0x001D,
+
+ ///
+ /// Sets the height of the double-click rectangle to the value of the uiParam parameter.
+ /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be
+ /// registered
+ /// as a double-click.
+ /// To retrieve the height of the double-click rectangle, call GetSystemMetrics with the SM_CYDOUBLECLK flag.
+ ///
+ SPI_SETDOUBLECLKHEIGHT = 0x001E,
+
+ ///
+ /// Retrieves the logical font information for the current icon-title font. The uiParam parameter specifies the size of
+ /// a LOGFONT structure,
+ /// and the pvParam parameter must point to the LOGFONT structure to fill in.
+ ///
+ SPI_GETICONTITLELOGFONT = 0x001F,
+
+ ///
+ /// Sets the double-click time for the mouse to the value of the uiParam parameter. The double-click time is the
+ /// maximum number
+ /// of milliseconds that can occur between the first and second clicks of a double-click. You can also call the
+ /// SetDoubleClickTime
+ /// function to set the double-click time. To get the current double-click time, call the GetDoubleClickTime function.
+ ///
+ SPI_SETDOUBLECLICKTIME = 0x0020,
+
+ ///
+ /// Swaps or restores the meaning of the left and right mouse buttons. The uiParam parameter specifies TRUE to swap the
+ /// meanings
+ /// of the buttons, or FALSE to restore their original meanings.
+ ///
+ SPI_SETMOUSEBUTTONSWAP = 0x0021,
+
+ ///
+ /// Sets the font that is used for icon titles. The uiParam parameter specifies the size of a LOGFONT structure,
+ /// and the pvParam parameter must point to a LOGFONT structure.
+ ///
+ SPI_SETICONTITLELOGFONT = 0x0022,
+
+ ///
+ /// This flag is obsolete. Previous versions of the system use this flag to determine whether ALT+TAB fast task
+ /// switching is enabled.
+ /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled.
+ ///
+ SPI_GETFASTTASKSWITCH = 0x0023,
+
+ ///
+ /// This flag is obsolete. Previous versions of the system use this flag to enable or disable ALT+TAB fast task
+ /// switching.
+ /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled.
+ ///
+ SPI_SETFASTTASKSWITCH = 0x0024,
+
+ ///
+ /// Sets dragging of full windows either on or off. The uiParam parameter specifies TRUE for on, or FALSE for off.
+ /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
+ ///
+ SPI_SETDRAGFULLWINDOWS = 0x0025,
+
+ ///
+ /// Determines whether dragging of full windows is enabled. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if enabled, or FALSE otherwise.
+ /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
+ ///
+ SPI_GETDRAGFULLWINDOWS = 0x0026,
+
+ ///
+ /// Retrieves the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point
+ /// to a NONCLIENTMETRICS structure that receives the information. Set the cbSize member of this structure and the
+ /// uiParam parameter
+ /// to sizeof(NONCLIENTMETRICS).
+ ///
+ SPI_GETNONCLIENTMETRICS = 0x0029,
+
+ ///
+ /// Sets the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point
+ /// to a NONCLIENTMETRICS structure that contains the new parameters. Set the cbSize member of this structure
+ /// and the uiParam parameter to sizeof(NONCLIENTMETRICS). Also, the lfHeight member of the LOGFONT structure must be a
+ /// negative value.
+ ///
+ SPI_SETNONCLIENTMETRICS = 0x002A,
+
+ ///
+ /// Retrieves the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(MINIMIZEDMETRICS).
+ ///
+ SPI_GETMINIMIZEDMETRICS = 0x002B,
+
+ ///
+ /// Sets the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(MINIMIZEDMETRICS).
+ ///
+ SPI_SETMINIMIZEDMETRICS = 0x002C,
+
+ ///
+ /// Retrieves the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that
+ /// receives
+ /// the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS).
+ ///
+ SPI_GETICONMETRICS = 0x002D,
+
+ ///
+ /// Sets the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that contains
+ /// the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS).
+ ///
+ SPI_SETICONMETRICS = 0x002E,
+
+ ///
+ /// Sets the size of the work area. The work area is the portion of the screen not obscured by the system taskbar
+ /// or by application desktop toolbars. The pvParam parameter is a pointer to a RECT structure that specifies the new
+ /// work area rectangle,
+ /// expressed in virtual screen coordinates. In a system with multiple display monitors, the function sets the work
+ /// area
+ /// of the monitor that contains the specified rectangle.
+ ///
+ SPI_SETWORKAREA = 0x002F,
+
+ ///
+ /// Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen not
+ /// obscured
+ /// by the system taskbar or by application desktop toolbars. The pvParam parameter must point to a RECT structure that
+ /// receives
+ /// the coordinates of the work area, expressed in virtual screen coordinates.
+ /// To get the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function.
+ ///
+ SPI_GETWORKAREA = 0x0030,
+
+ ///
+ /// Windows Me/98/95: Pen windows is being loaded or unloaded. The uiParam parameter is TRUE when loading and FALSE
+ /// when unloading pen windows. The pvParam parameter is null.
+ ///
+ SPI_SETPENWINDOWS = 0x0031,
+
+ ///
+ /// Retrieves information about the HighContrast accessibility feature. The pvParam parameter must point to a
+ /// HIGHCONTRAST structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(HIGHCONTRAST).
+ /// For a general discussion, see remarks.
+ /// Windows NT: This value is not supported.
+ ///
+ ///
+ /// There is a difference between the High Contrast color scheme and the High Contrast Mode. The High Contrast color
+ /// scheme changes
+ /// the system colors to colors that have obvious contrast; you switch to this color scheme by using the Display
+ /// Options in the control panel.
+ /// The High Contrast Mode, which uses SPI_GETHIGHCONTRAST and SPI_SETHIGHCONTRAST, advises applications to modify
+ /// their appearance
+ /// for visually-impaired users. It involves such things as audible warning to users and customized color scheme
+ /// (using the Accessibility Options in the control panel). For more information, see HIGHCONTRAST on MSDN.
+ /// For more information on general accessibility features, see Accessibility on MSDN.
+ ///
+ SPI_GETHIGHCONTRAST = 0x0042,
+
+ ///
+ /// Sets the parameters of the HighContrast accessibility feature. The pvParam parameter must point to a HIGHCONTRAST
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(HIGHCONTRAST).
+ /// Windows NT: This value is not supported.
+ ///
+ SPI_SETHIGHCONTRAST = 0x0043,
+
+ ///
+ /// Determines whether the user relies on the keyboard instead of the mouse, and wants applications to display keyboard
+ /// interfaces
+ /// that would otherwise be hidden. The pvParam parameter must point to a BOOL variable that receives TRUE
+ /// if the user relies on the keyboard; or FALSE otherwise.
+ /// Windows NT: This value is not supported.
+ ///
+ SPI_GETKEYBOARDPREF = 0x0044,
+
+ ///
+ /// Sets the keyboard preference. The uiParam parameter specifies TRUE if the user relies on the keyboard instead of
+ /// the mouse,
+ /// and wants applications to display keyboard interfaces that would otherwise be hidden; uiParam is FALSE otherwise.
+ /// Windows NT: This value is not supported.
+ ///
+ SPI_SETKEYBOARDPREF = 0x0045,
+
+ ///
+ /// Determines whether a screen reviewer utility is running. A screen reviewer utility directs textual information to
+ /// an output device,
+ /// such as a speech synthesizer or Braille display. When this flag is set, an application should provide textual
+ /// information
+ /// in situations where it would otherwise present the information graphically.
+ /// The pvParam parameter is a pointer to a BOOL variable that receives TRUE if a screen reviewer utility is running,
+ /// or FALSE otherwise.
+ /// Windows NT: This value is not supported.
+ ///
+ SPI_GETSCREENREADER = 0x0046,
+
+ ///
+ /// Determines whether a screen review utility is running. The uiParam parameter specifies TRUE for on, or FALSE for
+ /// off.
+ /// Windows NT: This value is not supported.
+ ///
+ SPI_SETSCREENREADER = 0x0047,
+
+ ///
+ /// Retrieves the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(ANIMATIONINFO).
+ ///
+ SPI_GETANIMATION = 0x0048,
+
+ ///
+ /// Sets the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(ANIMATIONINFO).
+ ///
+ SPI_SETANIMATION = 0x0049,
+
+ ///
+ /// Determines whether the font smoothing feature is enabled. This feature uses font antialiasing to make font curves
+ /// appear smoother
+ /// by painting pixels at different gray levels.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is enabled, or FALSE if it is
+ /// not.
+ /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
+ ///
+ SPI_GETFONTSMOOTHING = 0x004A,
+
+ ///
+ /// Enables or disables the font smoothing feature, which uses font antialiasing to make font curves appear smoother
+ /// by painting pixels at different gray levels.
+ /// To enable the feature, set the uiParam parameter to TRUE. To disable the feature, set uiParam to FALSE.
+ /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION.
+ ///
+ SPI_SETFONTSMOOTHING = 0x004B,
+
+ ///
+ /// Sets the width, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new
+ /// value.
+ /// To retrieve the drag width, call GetSystemMetrics with the SM_CXDRAG flag.
+ ///
+ SPI_SETDRAGWIDTH = 0x004C,
+
+ ///
+ /// Sets the height, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new
+ /// value.
+ /// To retrieve the drag height, call GetSystemMetrics with the SM_CYDRAG flag.
+ ///
+ SPI_SETDRAGHEIGHT = 0x004D,
+
+ ///
+ /// Used internally; applications should not use this value.
+ ///
+ SPI_SETHANDHELD = 0x004E,
+
+ ///
+ /// Retrieves the time-out value for the low-power phase of screen saving. The pvParam parameter must point to an
+ /// integer variable
+ /// that receives the value. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_GETLOWPOWERTIMEOUT = 0x004F,
+
+ ///
+ /// Retrieves the time-out value for the power-off phase of screen saving. The pvParam parameter must point to an
+ /// integer variable
+ /// that receives the value. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_GETPOWEROFFTIMEOUT = 0x0050,
+
+ ///
+ /// Sets the time-out value, in seconds, for the low-power phase of screen saving. The uiParam parameter specifies the
+ /// new value.
+ /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_SETLOWPOWERTIMEOUT = 0x0051,
+
+ ///
+ /// Sets the time-out value, in seconds, for the power-off phase of screen saving. The uiParam parameter specifies the
+ /// new value.
+ /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_SETPOWEROFFTIMEOUT = 0x0052,
+
+ ///
+ /// Determines whether the low-power phase of screen saving is enabled. The pvParam parameter must point to a BOOL
+ /// variable
+ /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_GETLOWPOWERACTIVE = 0x0053,
+
+ ///
+ /// Determines whether the power-off phase of screen saving is enabled. The pvParam parameter must point to a BOOL
+ /// variable
+ /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_GETPOWEROFFACTIVE = 0x0054,
+
+ ///
+ /// Activates or deactivates the low-power phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate.
+ /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_SETLOWPOWERACTIVE = 0x0055,
+
+ ///
+ /// Activates or deactivates the power-off phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate.
+ /// The pvParam parameter must be null. This flag is supported for 32-bit applications only.
+ /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications.
+ /// Windows 95: This flag is supported for 16-bit applications only.
+ ///
+ SPI_SETPOWEROFFACTIVE = 0x0056,
+
+ ///
+ /// Reloads the system cursors. Set the uiParam parameter to zero and the pvParam parameter to null.
+ ///
+ SPI_SETCURSORS = 0x0057,
+
+ ///
+ /// Reloads the system icons. Set the uiParam parameter to zero and the pvParam parameter to null.
+ ///
+ SPI_SETICONS = 0x0058,
+
+ ///
+ /// Retrieves the input locale identifier for the system default input language. The pvParam parameter must point
+ /// to an HKL variable that receives this value. For more information, see Languages, Locales, and Keyboard Layouts on
+ /// MSDN.
+ ///
+ SPI_GETDEFAULTINPUTLANG = 0x0059,
+
+ ///
+ /// Sets the default input language for the system shell and applications. The specified language must be displayable
+ /// using the current system character set. The pvParam parameter must point to an HKL variable that contains
+ /// the input locale identifier for the default language. For more information, see Languages, Locales, and Keyboard
+ /// Layouts on MSDN.
+ ///
+ SPI_SETDEFAULTINPUTLANG = 0x005A,
+
+ ///
+ /// Sets the hot key set for switching between input languages. The uiParam and pvParam parameters are not used.
+ /// The value sets the shortcut keys in the keyboard property sheets by reading the registry again. The registry must
+ /// be set before this flag is used. the path in the registry is \HKEY_CURRENT_USER\keyboard layout\toggle. Valid
+ /// values are "1" = ALT+SHIFT, "2" = CTRL+SHIFT, and "3" = none.
+ ///
+ SPI_SETLANGTOGGLE = 0x005B,
+
+ ///
+ /// Windows 95: Determines whether the Windows extension, Windows Plus!, is installed. Set the uiParam parameter to 1.
+ /// The pvParam parameter is not used. The function returns TRUE if the extension is installed, or FALSE if it is not.
+ ///
+ SPI_GETWINDOWSEXTENSION = 0x005C,
+
+ ///
+ /// Enables or disables the Mouse Trails feature, which improves the visibility of mouse cursor movements by briefly
+ /// showing
+ /// a trail of cursors and quickly erasing them.
+ /// To disable the feature, set the uiParam parameter to zero or 1. To enable the feature, set uiParam to a value
+ /// greater than 1
+ /// to indicate the number of cursors drawn in the trail.
+ /// Windows 2000/NT: This value is not supported.
+ ///
+ SPI_SETMOUSETRAILS = 0x005D,
+
+ ///
+ /// Determines whether the Mouse Trails feature is enabled. This feature improves the visibility of mouse cursor
+ /// movements
+ /// by briefly showing a trail of cursors and quickly erasing them.
+ /// The pvParam parameter must point to an integer variable that receives a value. If the value is zero or 1, the
+ /// feature is disabled.
+ /// If the value is greater than 1, the feature is enabled and the value indicates the number of cursors drawn in the
+ /// trail.
+ /// The uiParam parameter is not used.
+ /// Windows 2000/NT: This value is not supported.
+ ///
+ SPI_GETMOUSETRAILS = 0x005E,
+
+ ///
+ /// Windows Me/98: Used internally; applications should not use this flag.
+ ///
+ SPI_SETSCREENSAVERRUNNING = 0x0061,
+
+ ///
+ /// Same as SPI_SETSCREENSAVERRUNNING.
+ ///
+ SPI_SCREENSAVERRUNNING = SPI_SETSCREENSAVERRUNNING,
+ //#endif /* WINVER >= 0x0400 */
+
+ ///
+ /// Retrieves information about the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(FILTERKEYS).
+ ///
+ SPI_GETFILTERKEYS = 0x0032,
+
+ ///
+ /// Sets the parameters of the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(FILTERKEYS).
+ ///
+ SPI_SETFILTERKEYS = 0x0033,
+
+ ///
+ /// Retrieves information about the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(TOGGLEKEYS).
+ ///
+ SPI_GETTOGGLEKEYS = 0x0034,
+
+ ///
+ /// Sets the parameters of the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(TOGGLEKEYS).
+ ///
+ SPI_SETTOGGLEKEYS = 0x0035,
+
+ ///
+ /// Retrieves information about the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(MOUSEKEYS).
+ ///
+ SPI_GETMOUSEKEYS = 0x0036,
+
+ ///
+ /// Sets the parameters of the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(MOUSEKEYS).
+ ///
+ SPI_SETMOUSEKEYS = 0x0037,
+
+ ///
+ /// Determines whether the Show Sounds accessibility flag is on or off. If it is on, the user requires an application
+ /// to present information visually in situations where it would otherwise present the information only in audible
+ /// form.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is on, or FALSE if it is off.
+ /// Using this value is equivalent to calling GetSystemMetrics (SM_SHOWSOUNDS). That is the recommended call.
+ ///
+ SPI_GETSHOWSOUNDS = 0x0038,
+
+ ///
+ /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(SOUNDSENTRY).
+ ///
+ SPI_SETSHOWSOUNDS = 0x0039,
+
+ ///
+ /// Retrieves information about the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS
+ /// structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(STICKYKEYS).
+ ///
+ SPI_GETSTICKYKEYS = 0x003A,
+
+ ///
+ /// Sets the parameters of the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(STICKYKEYS).
+ ///
+ SPI_SETSTICKYKEYS = 0x003B,
+
+ ///
+ /// Retrieves information about the time-out period associated with the accessibility features. The pvParam parameter
+ /// must point
+ /// to an ACCESSTIMEOUT structure that receives the information. Set the cbSize member of this structure and the
+ /// uiParam parameter
+ /// to sizeof(ACCESSTIMEOUT).
+ ///
+ SPI_GETACCESSTIMEOUT = 0x003C,
+
+ ///
+ /// Sets the time-out period associated with the accessibility features. The pvParam parameter must point to an
+ /// ACCESSTIMEOUT
+ /// structure that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(ACCESSTIMEOUT).
+ ///
+ SPI_SETACCESSTIMEOUT = 0x003D,
+
+ ///
+ /// Windows Me/98/95: Retrieves information about the SerialKeys accessibility feature. The pvParam parameter must
+ /// point
+ /// to a SERIALKEYS structure that receives the information. Set the cbSize member of this structure and the uiParam
+ /// parameter
+ /// to sizeof(SERIALKEYS).
+ /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel.
+ ///
+ SPI_GETSERIALKEYS = 0x003E,
+
+ ///
+ /// Windows Me/98/95: Sets the parameters of the SerialKeys accessibility feature. The pvParam parameter must point
+ /// to a SERIALKEYS structure that contains the new parameters. Set the cbSize member of this structure and the uiParam
+ /// parameter
+ /// to sizeof(SERIALKEYS).
+ /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel.
+ ///
+ SPI_SETSERIALKEYS = 0x003F,
+ //#endif /* WINVER >= 0x0400 */
+
+ ///
+ /// Retrieves information about the SoundSentry accessibility feature. The pvParam parameter must point to a
+ /// SOUNDSENTRY structure
+ /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(SOUNDSENTRY).
+ ///
+ SPI_GETSOUNDSENTRY = 0x0040,
+
+ ///
+ /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY
+ /// structure
+ /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to
+ /// sizeof(SOUNDSENTRY).
+ ///
+ SPI_SETSOUNDSENTRY = 0x0041,
+
+ ///
+ /// Determines whether the snap-to-default-button feature is enabled. If enabled, the mouse cursor automatically moves
+ /// to the default button, such as OK or Apply, of a dialog box. The pvParam parameter must point to a BOOL variable
+ /// that receives TRUE if the feature is on, or FALSE if it is off.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETSNAPTODEFBUTTON = 0x005F,
+
+ ///
+ /// Enables or disables the snap-to-default-button feature. If enabled, the mouse cursor automatically moves to the
+ /// default button,
+ /// such as OK or Apply, of a dialog box. Set the uiParam parameter to TRUE to enable the feature, or FALSE to disable
+ /// it.
+ /// Applications should use the ShowWindow function when displaying a dialog box so the dialog manager can position the
+ /// mouse cursor.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETSNAPTODEFBUTTON = 0x0060,
+
+ ///
+ /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETMOUSEHOVERWIDTH = 0x0062,
+
+ ///
+ /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETMOUSEHOVERWIDTH = 0x0063,
+
+ ///
+ /// Retrieves the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the height.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETMOUSEHOVERHEIGHT = 0x0064,
+
+ ///
+ /// Sets the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. Set the uiParam parameter to the new height.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETMOUSEHOVERHEIGHT = 0x0065,
+
+ ///
+ /// Retrieves the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the time.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETMOUSEHOVERTIME = 0x0066,
+
+ ///
+ /// Sets the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent
+ /// to generate a WM_MOUSEHOVER message. This is used only if you pass HOVER_DEFAULT in the dwHoverTime parameter in
+ /// the call to TrackMouseEvent. Set the uiParam parameter to the new time.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETMOUSEHOVERTIME = 0x0067,
+
+ ///
+ /// Retrieves the number of lines to scroll when the mouse wheel is rotated. The pvParam parameter must point
+ /// to a UINT variable that receives the number of lines. The default value is 3.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETWHEELSCROLLLINES = 0x0068,
+
+ ///
+ /// Sets the number of lines to scroll when the mouse wheel is rotated. The number of lines is set from the uiParam
+ /// parameter.
+ /// The number of lines is the suggested number of lines to scroll when the mouse wheel is rolled without using
+ /// modifier keys.
+ /// If the number is 0, then no scrolling should occur. If the number of lines to scroll is greater than the number of
+ /// lines viewable,
+ /// and in particular if it is WHEEL_PAGESCROLL (#defined as UINT_MAX), the scroll operation should be interpreted
+ /// as clicking once in the page down or page up regions of the scroll bar.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETWHEELSCROLLLINES = 0x0069,
+
+ ///
+ /// Retrieves the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse cursor
+ /// is
+ /// over a submenu item. The pvParam parameter must point to a DWORD variable that receives the time of the delay.
+ /// Windows 95: Not supported.
+ ///
+ SPI_GETMENUSHOWDELAY = 0x006A,
+
+ ///
+ /// Sets uiParam to the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse
+ /// cursor is
+ /// over a submenu item.
+ /// Windows 95: Not supported.
+ ///
+ SPI_SETMENUSHOWDELAY = 0x006B,
+
+ ///
+ /// Determines whether the IME status window is visible (on a per-user basis). The pvParam parameter must point to a
+ /// BOOL variable
+ /// that receives TRUE if the status window is visible, or FALSE if it is not.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETSHOWIMEUI = 0x006E,
+
+ ///
+ /// Sets whether the IME status window is visible or not on a per-user basis. The uiParam parameter specifies TRUE for
+ /// on or FALSE for off.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETSHOWIMEUI = 0x006F,
+
+ ///
+ /// Retrieves the current mouse speed. The mouse speed determines how far the pointer will move based on the distance
+ /// the mouse moves.
+ /// The pvParam parameter must point to an integer that receives a value which ranges between 1 (slowest) and 20
+ /// (fastest).
+ /// A value of 10 is the default. The value can be set by an end user using the mouse control panel application or
+ /// by an application using SPI_SETMOUSESPEED.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETMOUSESPEED = 0x0070,
+
+ ///
+ /// Sets the current mouse speed. The pvParam parameter is an integer between 1 (slowest) and 20 (fastest). A value of
+ /// 10 is the default.
+ /// This value is typically set using the mouse control panel application.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETMOUSESPEED = 0x0071,
+
+ ///
+ /// Determines whether a screen saver is currently running on the window station of the calling process.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE if a screen saver is currently running, or
+ /// FALSE otherwise.
+ /// Note that only the interactive window station, "WinSta0", can have a screen saver running.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETSCREENSAVERRUNNING = 0x0072,
+
+ ///
+ /// Retrieves the full path of the bitmap file for the desktop wallpaper. The pvParam parameter must point to a buffer
+ /// that receives a null-terminated path string. Set the uiParam parameter to the size, in characters, of the pvParam
+ /// buffer. The returned string will not exceed MAX_PATH characters. If there is no desktop wallpaper, the returned
+ /// string is empty.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETDESKWALLPAPER = 0x0073,
+
+ ///
+ /// Determines whether active window tracking (activating the window the mouse is on) is on or off. The pvParam
+ /// parameter must point
+ /// to a BOOL variable that receives TRUE for on, or FALSE for off.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETACTIVEWINDOWTRACKING = 0x1000,
+
+ ///
+ /// Sets active window tracking (activating the window the mouse is on) either on or off. Set pvParam to TRUE for on or
+ /// FALSE for off.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETACTIVEWINDOWTRACKING = 0x1001,
+
+ ///
+ /// Determines whether the menu animation feature is enabled. This master switch must be on to enable menu animation
+ /// effects.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE if animation is enabled and FALSE if it is
+ /// disabled.
+ /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETMENUANIMATION = 0x1002,
+
+ ///
+ /// Enables or disables menu animation. This master switch must be on for any menu animation to occur.
+ /// The pvParam parameter is a BOOL variable; set pvParam to TRUE to enable animation and FALSE to disable animation.
+ /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETMENUANIMATION = 0x1003,
+
+ ///
+ /// Determines whether the slide-open effect for combo boxes is enabled. The pvParam parameter must point to a BOOL
+ /// variable
+ /// that receives TRUE for enabled, or FALSE for disabled.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETCOMBOBOXANIMATION = 0x1004,
+
+ ///
+ /// Enables or disables the slide-open effect for combo boxes. Set the pvParam parameter to TRUE to enable the gradient
+ /// effect,
+ /// or FALSE to disable it.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETCOMBOBOXANIMATION = 0x1005,
+
+ ///
+ /// Determines whether the smooth-scrolling effect for list boxes is enabled. The pvParam parameter must point to a
+ /// BOOL variable
+ /// that receives TRUE for enabled, or FALSE for disabled.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETLISTBOXSMOOTHSCROLLING = 0x1006,
+
+ ///
+ /// Enables or disables the smooth-scrolling effect for list boxes. Set the pvParam parameter to TRUE to enable the
+ /// smooth-scrolling effect,
+ /// or FALSE to disable it.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETLISTBOXSMOOTHSCROLLING = 0x1007,
+
+ ///
+ /// Determines whether the gradient effect for window title bars is enabled. The pvParam parameter must point to a BOOL
+ /// variable
+ /// that receives TRUE for enabled, or FALSE for disabled. For more information about the gradient effect, see the
+ /// GetSysColor function.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETGRADIENTCAPTIONS = 0x1008,
+
+ ///
+ /// Enables or disables the gradient effect for window title bars. Set the pvParam parameter to TRUE to enable it, or
+ /// FALSE to disable it.
+ /// The gradient effect is possible only if the system has a color depth of more than 256 colors. For more information
+ /// about
+ /// the gradient effect, see the GetSysColor function.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETGRADIENTCAPTIONS = 0x1009,
+
+ ///
+ /// Determines whether menu access keys are always underlined. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if menu access keys are always underlined, and FALSE if they are underlined only when the menu is activated by the
+ /// keyboard.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETKEYBOARDCUES = 0x100A,
+
+ ///
+ /// Sets the underlining of menu access key letters. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to
+ /// always underline menu
+ /// access keys, or FALSE to underline menu access keys only when the menu is activated from the keyboard.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETKEYBOARDCUES = 0x100B,
+
+ ///
+ /// Same as SPI_GETKEYBOARDCUES.
+ ///
+ SPI_GETMENUUNDERLINES = SPI_GETKEYBOARDCUES,
+
+ ///
+ /// Same as SPI_SETKEYBOARDCUES.
+ ///
+ SPI_SETMENUUNDERLINES = SPI_SETKEYBOARDCUES,
+
+ ///
+ /// Determines whether windows activated through active window tracking will be brought to the top. The pvParam
+ /// parameter must point
+ /// to a BOOL variable that receives TRUE for on, or FALSE for off.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETACTIVEWNDTRKZORDER = 0x100C,
+
+ ///
+ /// Determines whether or not windows activated through active window tracking should be brought to the top. Set
+ /// pvParam to TRUE
+ /// for on or FALSE for off.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETACTIVEWNDTRKZORDER = 0x100D,
+
+ ///
+ /// Determines whether hot tracking of user-interface elements, such as menu names on menu bars, is enabled. The
+ /// pvParam parameter
+ /// must point to a BOOL variable that receives TRUE for enabled, or FALSE for disabled.
+ /// Hot tracking means that when the cursor moves over an item, it is highlighted but not selected. You can query this
+ /// value to decide
+ /// whether to use hot tracking in the user interface of your application.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETHOTTRACKING = 0x100E,
+
+ ///
+ /// Enables or disables hot tracking of user-interface elements such as menu names on menu bars. Set the pvParam
+ /// parameter to TRUE
+ /// to enable it, or FALSE to disable it.
+ /// Hot-tracking means that when the cursor moves over an item, it is highlighted but not selected.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETHOTTRACKING = 0x100F,
+
+ ///
+ /// Determines whether menu fade animation is enabled. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// when fade animation is enabled and FALSE when it is disabled. If fade animation is disabled, menus use slide
+ /// animation.
+ /// This flag is ignored unless menu animation is enabled, which you can do using the SPI_SETMENUANIMATION flag.
+ /// For more information, see AnimateWindow.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETMENUFADE = 0x1012,
+
+ ///
+ /// Enables or disables menu fade animation. Set pvParam to TRUE to enable the menu fade effect or FALSE to disable it.
+ /// If fade animation is disabled, menus use slide animation. he The menu fade effect is possible only if the system
+ /// has a color depth of more than 256 colors. This flag is ignored unless SPI_MENUANIMATION is also set. For more
+ /// information,
+ /// see AnimateWindow.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETMENUFADE = 0x1013,
+
+ ///
+ /// Determines whether the selection fade effect is enabled. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if enabled or FALSE if disabled.
+ /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading
+ /// out
+ /// after the menu is dismissed.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETSELECTIONFADE = 0x1014,
+
+ ///
+ /// Set pvParam to TRUE to enable the selection fade effect or FALSE to disable it.
+ /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading
+ /// out
+ /// after the menu is dismissed. The selection fade effect is possible only if the system has a color depth of more
+ /// than 256 colors.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETSELECTIONFADE = 0x1015,
+
+ ///
+ /// Determines whether ToolTip animation is enabled. The pvParam parameter must point to a BOOL variable that receives
+ /// TRUE
+ /// if enabled or FALSE if disabled. If ToolTip animation is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTips use
+ /// fade or slide animation.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETTOOLTIPANIMATION = 0x1016,
+
+ ///
+ /// Set pvParam to TRUE to enable ToolTip animation or FALSE to disable it. If enabled, you can use SPI_SETTOOLTIPFADE
+ /// to specify fade or slide animation.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETTOOLTIPANIMATION = 0x1017,
+
+ ///
+ /// If SPI_SETTOOLTIPANIMATION is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTip animation uses a fade effect or
+ /// a slide effect.
+ /// The pvParam parameter must point to a BOOL variable that receives TRUE for fade animation or FALSE for slide
+ /// animation.
+ /// For more information on slide and fade effects, see AnimateWindow.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETTOOLTIPFADE = 0x1018,
+
+ ///
+ /// If the SPI_SETTOOLTIPANIMATION flag is enabled, use SPI_SETTOOLTIPFADE to indicate whether ToolTip animation uses a
+ /// fade effect
+ /// or a slide effect. Set pvParam to TRUE for fade animation or FALSE for slide animation. The tooltip fade effect is
+ /// possible only
+ /// if the system has a color depth of more than 256 colors. For more information on the slide and fade effects,
+ /// see the AnimateWindow function.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETTOOLTIPFADE = 0x1019,
+
+ ///
+ /// Determines whether the cursor has a shadow around it. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if the shadow is enabled, FALSE if it is disabled. This effect appears only if the system has a color depth of more
+ /// than 256 colors.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETCURSORSHADOW = 0x101A,
+
+ ///
+ /// Enables or disables a shadow around the cursor. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to
+ /// enable the shadow
+ /// or FALSE to disable the shadow. This effect appears only if the system has a color depth of more than 256 colors.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETCURSORSHADOW = 0x101B,
+
+ ///
+ /// Retrieves the state of the Mouse Sonar feature. The pvParam parameter must point to a BOOL variable that receives
+ /// TRUE
+ /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_GETMOUSESONAR = 0x101C,
+
+ ///
+ /// Turns the Sonar accessibility feature on or off. This feature briefly shows several concentric circles around the
+ /// mouse pointer when the user presses and releases the CTRL key. The pvParam parameter specifies TRUE for on and FALSE for off.
+ /// The default is off.
+ /// For more information, see About Mouse Input.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_SETMOUSESONAR = 0x101D,
+
+ ///
+ /// Retrieves the state of the Mouse ClickLock feature. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if enabled, or FALSE otherwise. For more information, see About Mouse Input.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_GETMOUSECLICKLOCK = 0x101E,
+
+ ///
+ /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse
+ /// button
+ /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam
+ /// parameter specifies
+ /// TRUE for on,
+ /// or FALSE for off. The default is off. For more information, see Remarks and About Mouse Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_SETMOUSECLICKLOCK = 0x101F,
+
+ ///
+ /// Retrieves the state of the Mouse Vanish feature. The pvParam parameter must point to a BOOL variable that receives
+ /// TRUE
+ /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_GETMOUSEVANISH = 0x1020,
+
+ ///
+ /// Turns the Vanish feature on or off. This feature hides the mouse pointer when the user types; the pointer reappears
+ /// when the user moves the mouse. The pvParam parameter specifies TRUE for on and FALSE for off. The default is off.
+ /// For more information, see About Mouse Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_SETMOUSEVANISH = 0x1021,
+
+ ///
+ /// Determines whether native User menus have flat menu appearance. The pvParam parameter must point to a BOOL variable
+ /// that returns TRUE if the flat menu appearance is set, or FALSE otherwise.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETFLATMENU = 0x1022,
+
+ ///
+ /// Enables or disables flat menu appearance for native User menus. Set pvParam to TRUE to enable flat menu appearance
+ /// or FALSE to disable it.
+ /// When enabled, the menu bar uses COLOR_MENUBAR for the menubar background, COLOR_MENU for the menu-popup background,
+ /// COLOR_MENUHILIGHT
+ /// for the fill of the current menu selection, and COLOR_HILIGHT for the outline of the current menu selection.
+ /// If disabled, menus are drawn using the same metrics and colors as in Windows 2000 and earlier.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETFLATMENU = 0x1023,
+
+ ///
+ /// Determines whether the drop shadow effect is enabled. The pvParam parameter must point to a BOOL variable that
+ /// returns TRUE
+ /// if enabled or FALSE if disabled.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETDROPSHADOW = 0x1024,
+
+ ///
+ /// Enables or disables the drop shadow effect. Set pvParam to TRUE to enable the drop shadow effect or FALSE to
+ /// disable it.
+ /// You must also have CS_DROPSHADOW in the window class style.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETDROPSHADOW = 0x1025,
+
+ ///
+ /// Retrieves a BOOL indicating whether an application can reset the screensaver's timer by calling the SendInput
+ /// function
+ /// to simulate keyboard or mouse input. The pvParam parameter must point to a BOOL variable that receives TRUE
+ /// if the simulated input will be blocked, or FALSE otherwise.
+ ///
+ SPI_GETBLOCKSENDINPUTRESETS = 0x1026,
+
+ ///
+ /// Determines whether an application can reset the screensaver's timer by calling the SendInput function to simulate
+ /// keyboard
+ /// or mouse input. The uiParam parameter specifies TRUE if the screensaver will not be deactivated by simulated input,
+ /// or FALSE if the screensaver will be deactivated by simulated input.
+ ///
+ SPI_SETBLOCKSENDINPUTRESETS = 0x1027,
+ //#endif /* _WIN32_WINNT >= 0x0501 */
+
+ ///
+ /// Determines whether UI effects are enabled or disabled. The pvParam parameter must point to a BOOL variable that
+ /// receives TRUE
+ /// if all UI effects are enabled, or FALSE if they are disabled.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETUIEFFECTS = 0x103E,
+
+ ///
+ /// Enables or disables UI effects. Set the pvParam parameter to TRUE to enable all UI effects or FALSE to disable all
+ /// UI effects.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETUIEFFECTS = 0x103F,
+
+ ///
+ /// Retrieves the amount of time following user input, in milliseconds, during which the system will not allow
+ /// applications
+ /// to force themselves into the foreground. The pvParam parameter must point to a DWORD variable that receives the
+ /// time.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000,
+
+ ///
+ /// Sets the amount of time following user input, in milliseconds, during which the system does not allow applications
+ /// to force themselves into the foreground. Set pvParam to the new timeout value.
+ /// The calling thread must be able to change the foreground window, otherwise the call fails.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001,
+
+ ///
+ /// Retrieves the active window tracking delay, in milliseconds. The pvParam parameter must point to a DWORD variable
+ /// that receives the time.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETACTIVEWNDTRKTIMEOUT = 0x2002,
+
+ ///
+ /// Sets the active window tracking delay. Set pvParam to the number of milliseconds to delay before activating the
+ /// window
+ /// under the mouse pointer.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETACTIVEWNDTRKTIMEOUT = 0x2003,
+
+ ///
+ /// Retrieves the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch
+ /// request.
+ /// The pvParam parameter must point to a DWORD variable that receives the value.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_GETFOREGROUNDFLASHCOUNT = 0x2004,
+
+ ///
+ /// Sets the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch
+ /// request.
+ /// Set pvParam to the number of times to flash.
+ /// Windows NT, Windows 95: This value is not supported.
+ ///
+ SPI_SETFOREGROUNDFLASHCOUNT = 0x2005,
+
+ ///
+ /// Retrieves the caret width in edit controls, in pixels. The pvParam parameter must point to a DWORD that receives
+ /// this value.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETCARETWIDTH = 0x2006,
+
+ ///
+ /// Sets the caret width in edit controls. Set pvParam to the desired width, in pixels. The default and minimum value
+ /// is 1.
+ /// Windows NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETCARETWIDTH = 0x2007,
+
+ ///
+ /// Retrieves the time delay before the primary mouse button is locked. The pvParam parameter must point to DWORD that
+ /// receives
+ /// the time delay. This is only enabled if SPI_SETMOUSECLICKLOCK is set to TRUE. For more information, see About Mouse
+ /// Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_GETMOUSECLICKLOCKTIME = 0x2008,
+
+ ///
+ /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse
+ /// button
+ /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam
+ /// parameter
+ /// specifies TRUE for on, or FALSE for off. The default is off. For more information, see Remarks and About Mouse
+ /// Input on MSDN.
+ /// Windows 2000/NT, Windows 98/95: This value is not supported.
+ ///
+ SPI_SETMOUSECLICKLOCKTIME = 0x2009,
+
+ ///
+ /// Retrieves the type of font smoothing. The pvParam parameter must point to a UINT that receives the information.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETFONTSMOOTHINGTYPE = 0x200A,
+
+ ///
+ /// Sets the font smoothing type. The pvParam parameter points to a UINT that contains either FE_FONTSMOOTHINGSTANDARD,
+ /// if standard anti-aliasing is used, or FE_FONTSMOOTHINGCLEARTYPE, if ClearType is used. The default is
+ /// FE_FONTSMOOTHINGSTANDARD.
+ /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise,
+ /// SystemParametersInfo fails.
+ ///
+ SPI_SETFONTSMOOTHINGTYPE = 0x200B,
+
+ ///
+ /// Retrieves a contrast value that is used in ClearType™ smoothing. The pvParam parameter must point to a UINT
+ /// that receives the information.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETFONTSMOOTHINGCONTRAST = 0x200C,
+
+ ///
+ /// Sets the contrast value used in ClearType smoothing. The pvParam parameter points to a UINT that holds the contrast
+ /// value.
+ /// Valid contrast values are from 1000 to 2200. The default value is 1400.
+ /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise,
+ /// SystemParametersInfo fails.
+ /// SPI_SETFONTSMOOTHINGTYPE must also be set to FE_FONTSMOOTHINGCLEARTYPE.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETFONTSMOOTHINGCONTRAST = 0x200D,
+
+ ///
+ /// Retrieves the width, in pixels, of the left and right edges of the focus rectangle drawn with DrawFocusRect.
+ /// The pvParam parameter must point to a UINT.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETFOCUSBORDERWIDTH = 0x200E,
+
+ ///
+ /// Sets the height of the left and right edges of the focus rectangle drawn with DrawFocusRect to the value of the
+ /// pvParam parameter.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETFOCUSBORDERWIDTH = 0x200F,
+
+ ///
+ /// Retrieves the height, in pixels, of the top and bottom edges of the focus rectangle drawn with DrawFocusRect.
+ /// The pvParam parameter must point to a UINT.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_GETFOCUSBORDERHEIGHT = 0x2010,
+
+ ///
+ /// Sets the height of the top and bottom edges of the focus rectangle drawn with DrawFocusRect to the value of the
+ /// pvParam parameter.
+ /// Windows 2000/NT, Windows Me/98/95: This value is not supported.
+ ///
+ SPI_SETFOCUSBORDERHEIGHT = 0x2011,
+
+ ///
+ /// Not implemented.
+ ///
+ SPI_GETFONTSMOOTHINGORIENTATION = 0x2012,
+
+ ///
+ /// Not implemented.
+ ///
+ SPI_SETFONTSMOOTHINGORIENTATION = 0x2013
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs b/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs
new file mode 100644
index 000000000..4b5872ae5
--- /dev/null
+++ b/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Dapplo and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace GreenshotPlugin.Core.Enums
+{
+ ///
+ /// If a system parameter is being set, specifies whether the user profile is to be updated, and if so, whether the
+ /// WM_SETTINGCHANGE message is to be broadcast to all top-level windows to notify them of the change.
+ /// This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message,
+ /// or it can be one or more of the following values.
+ ///
+ public enum SystemParametersInfoBehaviors : uint
+ {
+ ///
+ /// Do nothing
+ ///
+ None = 0x00,
+
+ /// Writes the new system-wide parameter setting to the user profile.
+ UpdateIniFile = 0x01,
+
+ /// Broadcasts the WM_SETTINGCHANGE message after updating the user profile.
+ SendChange = 0x02,
+
+ /// Same as SPIF_SENDCHANGE.
+ SendWinIniChange = SendChange
+ }
+}
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/EventDelay.cs b/GreenshotPlugin/Core/EventDelay.cs
new file mode 100644
index 000000000..c00306309
--- /dev/null
+++ b/GreenshotPlugin/Core/EventDelay.cs
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+
+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..8f67018b1
--- /dev/null
+++ b/GreenshotPlugin/Core/ExplorerHelper.cs
@@ -0,0 +1,52 @@
+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/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs
new file mode 100644
index 000000000..0e52e04fb
--- /dev/null
+++ b/GreenshotPlugin/Core/FastBitmap.cs
@@ -0,0 +1,1019 @@
+/*
+ * 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 .
+ */
+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);
+
+ 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ if (!_colorCache.TryGetValue(color, out var 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..5edf92afb
--- /dev/null
+++ b/GreenshotPlugin/Core/FilenameHelper.cs
@@ -0,0 +1,559 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using log4net;
+using System.Collections.Generic;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+
+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 = "_";
+ private static readonly Random RandomNumberGen = new Random();
+ private static readonly Regex RandRegexp = new Regex("^R+$", RegexOptions.Compiled);
+
+ ///
+ /// 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.Empty;
+ string variable = match.Groups["variable"].Value;
+ string parameters = match.Groups["parameters"].Value;
+ string randomChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ 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 if (RandRegexp.IsMatch(variable)) {
+ for (int i = 0; i < variable.Length; i++) {
+ replaceValue += randomChars[RandomNumberGen.Next(randomChars.Length)];
+ }
+ } 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/src/Greenshot.Base/Core/Fraction.cs b/GreenshotPlugin/Core/Fraction.cs
similarity index 97%
rename from src/Greenshot.Base/Core/Fraction.cs
rename to GreenshotPlugin/Core/Fraction.cs
index e7d999445..312b91bb8 100644
--- a/src/Greenshot.Base/Core/Fraction.cs
+++ b/GreenshotPlugin/Core/Fraction.cs
@@ -1,7 +1,7 @@
using System;
using System.Text.RegularExpressions;
-namespace Greenshot.Base.Core
+namespace GreenshotPlugin.Core
{
///
/// Basic Fraction (Rational) numbers with features only needed to represent scale factors.
@@ -19,12 +19,10 @@ namespace Greenshot.Base.Core
{
throw new ArgumentException("Can't divide by zero.", nameof(denominator));
}
-
if (numerator == 0)
{
throw new ArgumentException("Zero is not supported by this implementation.", nameof(numerator));
}
-
var gcd = GreatestCommonDivisor(numerator, denominator);
Numerator = numerator / gcd;
Denominator = denominator / gcd;
@@ -36,7 +34,6 @@ namespace Greenshot.Base.Core
#region Parse
private static readonly Regex PARSE_REGEX = new Regex(@"^([1-9][0-9]*)\/([1-9][0-9]*)$", RegexOptions.Compiled);
-
public static bool TryParse(string str, out Fraction result)
{
var match = PARSE_REGEX.Match(str);
@@ -45,7 +42,6 @@ namespace Greenshot.Base.Core
result = Identity;
return false;
}
-
var numerator = uint.Parse(match.Groups[1].Value);
var denominator = uint.Parse(match.Groups[2].Value);
result = new Fraction(numerator, denominator);
@@ -82,7 +78,7 @@ namespace Greenshot.Base.Core
}
public int CompareTo(Fraction other)
- => (int) (Numerator * other.Denominator) - (int) (other.Numerator * Denominator);
+ => (int)(Numerator * other.Denominator) - (int)(other.Numerator * Denominator);
#endregion
@@ -153,4 +149,4 @@ namespace Greenshot.Base.Core
private static uint GreatestCommonDivisor(uint a, uint b)
=> (b != 0) ? GreatestCommonDivisor(b, a % b) : a;
}
-}
\ No newline at end of file
+}
diff --git a/GreenshotPlugin/Core/GreenshotResources.cs b/GreenshotPlugin/Core/GreenshotResources.cs
new file mode 100644
index 000000000..6b80acf3f
--- /dev/null
+++ b/GreenshotPlugin/Core/GreenshotResources.cs
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+ */
+using System.ComponentModel;
+using System.Drawing;
+
+namespace GreenshotPlugin.Core {
+ ///
+ /// Centralized storage of the icons & bitmaps
+ ///
+ public static class GreenshotResources {
+ private static readonly ComponentResourceManager GreenshotResourceManager = new ComponentResourceManager(typeof(GreenshotResources));
+
+ public static Image GetImage(string imageName) {
+ return (Image)GreenshotResourceManager.GetObject(imageName);
+ }
+ public static Icon GetIcon(string imageName) {
+ return (Icon)GreenshotResourceManager.GetObject(imageName);
+ }
+
+ public static Icon GetGreenshotIcon() {
+ return GetIcon("Greenshot.Icon");
+ }
+
+ }
+}
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..521a6125f 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=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
+
+
\ No newline at end of file
diff --git a/GreenshotPlugin/Core/HResultExtensions.cs b/GreenshotPlugin/Core/HResultExtensions.cs
new file mode 100644
index 000000000..a85bd7600
--- /dev/null
+++ b/GreenshotPlugin/Core/HResultExtensions.cs
@@ -0,0 +1,65 @@
+// 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 .
+
+using GreenshotPlugin.Core.Enums;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+
+namespace GreenshotPlugin.Core
+{
+ ///
+ /// Extensions to handle the HResult
+ ///
+ public static class HResultExtensions
+ {
+ ///
+ /// Test if the HResult respresents a fail
+ ///
+ /// HResult
+ /// bool
+ [Pure]
+ public static bool Failed(this HResult hResult)
+ {
+ return hResult < 0;
+ }
+
+ ///
+ /// Test if the HResult respresents a success
+ ///
+ /// HResult
+ /// bool
+ [Pure]
+ public static bool Succeeded(this HResult hResult)
+ {
+ return hResult >= HResult.S_OK;
+ }
+
+ ///
+ /// Throw an exception on Failure
+ ///
+ /// HResult
+ public static void ThrowOnFailure(this HResult hResult)
+ {
+ if (hResult.Failed())
+ {
+ throw Marshal.GetExceptionForHR((int)hResult);
+ }
+ }
+ }
+}
diff --git a/GreenshotPlugin/Core/IEHelper.cs b/GreenshotPlugin/Core/IEHelper.cs
new file mode 100644
index 000000000..2a85958fc
--- /dev/null
+++ b/GreenshotPlugin/Core/IEHelper.cs
@@ -0,0 +1,189 @@
+/*
+ * 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 .
+ */
+
+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);
+ }
+
+ if (int.TryParse(strVal, out var 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..710a0d04d
--- /dev/null
+++ b/GreenshotPlugin/Core/IImage.cs
@@ -0,0 +1,68 @@
+/*
+ * 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 .
+ */
+
+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..b80879141
--- /dev/null
+++ b/GreenshotPlugin/Core/ImageHelper.cs
@@ -0,0 +1,1733 @@
+/*
+ * 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 .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using GreenshotPlugin.UnmanagedHelpers;
+using GreenshotPlugin.Effects;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+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;
+
+ static ImageHelper()
+ {
+ StreamConverters["greenshot"] = (stream, s) =>
+ {
+ var surface = SimpleServiceProvider.Current.GetInstance>().Invoke();
+ return surface.GetImageForExport();
+ };
+
+ // Add a SVG converter
+ 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;
+ };
+
+ static Image DefaultConverter(Stream stream, string 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[string.Empty] = 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)
+ {
+ Shell32.ExtractIconEx(location, index, out var large, out var 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)
+ {
+ return Shell32.ExtractIconEx(location, -1, out _, out _, 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)
+ {
+ LineJoin = LineJoin.Round,
+ StartCap = LineCap.Round,
+ 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);
+ }
+
+ // In WINE someone getting the PropertyItems doesn't work
+ try
+ {
+ // Clone property items (EXIF information etc)
+ foreach (var propertyItem in sourceImage.PropertyItems)
+ {
+ try
+ {
+ newImage.SetPropertyItem(propertyItem);
+ }
+ catch (Exception innerEx)
+ {
+ Log.Warn("Problem cloning a propertyItem.", innerEx);
+ }
+ }
+ }
+ 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 &= 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 &= 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(".", string.Empty);
+ }
+
+ // Make sure we can try multiple times
+ if (!stream.CanSeek)
+ {
+ var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
+ stream = memoryStream;
+ }
+
+ Image returnImage = null;
+ if (StreamConverters.TryGetValue(extension ?? string.Empty, out var 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..4388f2b59
--- /dev/null
+++ b/GreenshotPlugin/Core/ImageOutput.cs
@@ -0,0 +1,657 @@
+/*
+ * 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 .
+ */
+
+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 GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotPlugin.Interfaces.Plugin;
+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;
+ }
+
+ ///
+ /// 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) {
+ bool disposeImage = CreateImageFromSurface(surface, outputSettings, out var 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 {
+ var imageFormat = outputSettings.Format switch
+ {
+ OutputFormat.bmp => ImageFormat.Bmp,
+ OutputFormat.gif => ImageFormat.Gif,
+ OutputFormat.jpg => ImageFormat.Jpeg,
+ OutputFormat.tiff => ImageFormat.Tiff,
+ OutputFormat.ico => ImageFormat.Icon,
+ _ => ImageFormat.Png
+ };
+ 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
+ {
+ 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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\.]", string.Empty);
+ 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) {
+ if (filename is string path && File.Exists(path)) {
+ Log.DebugFormat("Removing expired file {0}", path);
+ File.Delete(path);
+ }
+ }
+
+ ///
+ /// 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();
+ }
+ }
+ }
+}
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..89c8079f0
--- /dev/null
+++ b/GreenshotPlugin/Core/InterfaceUtils.cs
@@ -0,0 +1,74 @@
+/*
+ * 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 .
+ */
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
+using GreenshotPlugin.Interfaces;
+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..d02845b72
--- /dev/null
+++ b/GreenshotPlugin/Core/JSONHelper.cs
@@ -0,0 +1,359 @@
+/*
+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